macro-clips slice 4c: button creation in sidebar + drag to clip tracks
- store.seedDefaultButtonClip(name) adds a button clip with a single shared rect asset and four pre-populated state stacks in blue shades (normal/hover/pressed/disabled). Layer name 'Face' is consistent so transitions can later pair layers by name. - AssetSidebar gets a Buttons section below Clips: create via prompt, rename, delete, drag-to-track. Drag uses a new dataTransfer type 'application/x-animatr-button-clip' to keep it distinct from animation-clip drops. - Timeline clip-lane drop accepts both types and dispatches addClipInstance / addButtonInstance accordingly; the new-track drop zone handles both too, so dragging a button to an empty area creates a fresh clip track + instance in one step. - i18n for the sidebar strings and three dialogs. - test covers seedDefaultButtonClip: four populated states, shared asset, consistent layer name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fb58cd18f7
commit
024883943b
5 files changed
+193
-6
No files matched your search
@@ -1145,6 +1145,50 @@ export const useSceneStore = defineStore('scene', {
|
||||
;(this.scene.buttonClips ||= []).push(clip)
|
||||
return clip
|
||||
},
|
||||
/**
|
||||
* Create a ButtonClip pre-populated with a visible rectangle for each
|
||||
* of the four states (different shades per state). The single shared
|
||||
* asset is added to the scene. Intended for the "+ Button" sidebar
|
||||
* flow — advanced users can still edit or replace the layers later.
|
||||
*/
|
||||
seedDefaultButtonClip(name?: string): ButtonClip {
|
||||
const title = name?.trim() || 'Button'
|
||||
const clip = this.addButtonClip(title)
|
||||
const asset = this.addAsset({
|
||||
kind: 'rect',
|
||||
name: `${title} face`,
|
||||
width: 120,
|
||||
height: 40,
|
||||
fill: '#3b82f6',
|
||||
}) as Extract<Asset, { kind: 'rect' }>
|
||||
const makeFace = (fill: string, layerName: string): Layer => ({
|
||||
id: uid(),
|
||||
name: layerName,
|
||||
assetId: asset.id,
|
||||
visible: true,
|
||||
base: { ...DEFAULT_BASE_PROPS, fill },
|
||||
keyframes: [
|
||||
{
|
||||
id: uid(),
|
||||
time: 0,
|
||||
props: { ...DEFAULT_BASE_PROPS, fill },
|
||||
easing: 'linear',
|
||||
},
|
||||
],
|
||||
offsetX: asset.width / 2,
|
||||
offsetY: asset.height / 2,
|
||||
})
|
||||
const target = this.scene.buttonClips?.find((c) => c.id === clip.id)
|
||||
if (target) {
|
||||
target.states = {
|
||||
normal: [makeFace('#3b82f6', 'Face')],
|
||||
hover: [makeFace('#60a5fa', 'Face')],
|
||||
pressed: [makeFace('#2563eb', 'Face')],
|
||||
disabled: [makeFace('#9ca3af', 'Face')],
|
||||
}
|
||||
}
|
||||
return target ?? clip
|
||||
},
|
||||
removeButtonClip(id: string) {
|
||||
if (this.scene.buttonClips) {
|
||||
this.scene.buttonClips = this.scene.buttonClips.filter((c) => c.id !== id)
|
||||
|
||||
Reference in new issue
Block a user