@pixerate/editor-react 0.46.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -686,6 +686,13 @@ function SceneSettings({ controller, className = "" }) {
686
686
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "loop", children: "Loop" }),
687
687
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "ping-pong", children: "Ping-pong" })
688
688
  ] }),
689
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "text-muted-foreground", children: "Motion blur" }),
690
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("select", { className: input2, "aria-label": "Motion blur", disabled: readOnly, value: scene.motionBlur ? String(scene.motionBlur.shutter ?? 180) : "", onChange: (e) => settings({ motionBlur: e.target.value ? { ...scene.motionBlur ?? {}, shutter: Number(e.target.value) } : null }, "Change motion blur"), children: [
691
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: "Off" }),
692
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "90", children: "Light (90\xB0)" }),
693
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "180", children: "Normal (180\xB0)" }),
694
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "360", children: "Heavy (360\xB0)" })
695
+ ] }),
689
696
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("label", { className: "text-muted-foreground", children: "Plays on" }),
690
697
  /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("select", { className: input2, "aria-label": "Scene trigger", title: "How a viewer plays it when exported to Flair", disabled: readOnly, value: scene.trigger ?? "", onChange: (e) => settings({ trigger: e.target.value || null }, "Change trigger"), children: [
691
698
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("option", { value: "", children: "Its own (autoplay)" }),
@@ -824,6 +831,26 @@ function SceneSettings({ controller, className = "" }) {
824
831
  (0, import_animation_editor7.formatMotionNarration)(scene.narration)
825
832
  )
826
833
  ] }),
834
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("label", { className: "flex flex-col gap-0.5", children: [
835
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-muted-foreground", children: "Drivers (one a line: target.property <- source.property * factor)" }),
836
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
837
+ "textarea",
838
+ {
839
+ className: `${input2} h-14 font-mono`,
840
+ "aria-label": "Drivers",
841
+ placeholder: "back.x <- front.x * 0.5\nwheel.rotation <- wheel.x * 2.86",
842
+ disabled: readOnly,
843
+ defaultValue: (0, import_animation_editor7.formatMotionDrivers)(scene.drivers),
844
+ onBlur: (e) => {
845
+ if (e.currentTarget.value === (0, import_animation_editor7.formatMotionDrivers)(scene.drivers)) return;
846
+ const parsed = (0, import_animation_editor7.parseMotionDrivers)(e.currentTarget.value);
847
+ if ("error" in parsed) return setLocal(parsed.error);
848
+ apply({ op: "set_drivers", drivers: parsed.drivers }, parsed.drivers.length ? "Set drivers" : "Clear drivers");
849
+ }
850
+ },
851
+ (0, import_animation_editor7.formatMotionDrivers)(scene.drivers)
852
+ )
853
+ ] }),
827
854
  message && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-red-500", role: "alert", "data-edit-error": "", children: message })
828
855
  ] });
829
856
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/animation-editor/index.ts","../../src/animation-editor/useAnimationEditor.ts","../../src/animation-editor/AnimationStage.tsx","../../src/animation-editor/ShotTimeline.tsx","../../src/animation-editor/AnimationEditor.tsx","../../src/animation-editor/CommandInspector.tsx","../../src/animation-editor/EasePicker.tsx","../../src/animation-editor/CommitInput.tsx","../../src/animation-editor/CommandList.tsx","../../src/animation-editor/PlayheadScrubber.tsx","../../src/animation-editor/SceneSettings.tsx","../../src/animation-editor/ShotInspector.tsx"],"sourcesContent":["export * from './useAnimationEditor';\nexport * from './AnimationStage';\nexport * from './ShotTimeline';\nexport * from './AnimationEditor';\nexport * from './PlayheadScrubber';\nexport * from './CommandList';\nexport * from './CommandInspector';\nexport * from './EasePicker';\nexport * from './ShotInspector';\nexport * from './SceneSettings';\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n AnimationEditorController,\n createAnimationEditorToolProvider,\n type AnimationEditorOptions,\n type AnimationEditorState,\n type AnimationEditorToolProviderOptions,\n} from '@pixerate/editor/animation-editor';\nimport type { ToolRegistry } from '@pixerate/editor/tools';\n\n/** An `AnimationEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useAnimationEditorController(options: AnimationEditorOptions = {}): AnimationEditorController {\n const ref = useRef<AnimationEditorController | null>(null);\n if (!ref.current) ref.current = new AnimationEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change, including each played frame). */\nexport function useAnimationEditorState(controller: AnimationEditorController): AnimationEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseAnimationEditorResult {\n controller: AnimationEditorController;\n state: AnimationEditorState;\n play: () => void;\n pause: () => void;\n toggle: () => void;\n seek: (time: number) => void;\n undo: () => void;\n redo: () => void;\n /** The frame at the playhead as SVG. */\n toSvg: () => string;\n}\n\n/**\n * Subscribes to an animation editor controller and exposes its state with bound actions.\n * Pass options instead of a controller to create one for the component's lifetime.\n */\nexport function useAnimationEditor(controllerOrOptions: AnimationEditorController | AnimationEditorOptions = {}): UseAnimationEditorResult {\n const own = useRef<AnimationEditorController | null>(null);\n let controller: AnimationEditorController;\n if (controllerOrOptions instanceof AnimationEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new AnimationEditorController(controllerOrOptions);\n controller = own.current;\n }\n useEffect(() => () => own.current?.destroy(), []);\n const state = useAnimationEditorState(controller);\n const actions = useMemo(\n () => ({\n play: () => controller.play(),\n pause: () => controller.pause(),\n toggle: () => controller.toggle(),\n seek: (time: number) => controller.seek(time),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/**\n * Registers the animation editor's agent tools (`get_animation`, `add_commands`,\n * `export_flair_effect`, …) in `registry` while mounted.\n */\nexport function useAnimationEditorTools(\n registry: ToolRegistry | null | undefined,\n controller: AnimationEditorController,\n options: AnimationEditorToolProviderOptions = {},\n): void {\n const { id, namespace, readOnly, rasterize } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createAnimationEditorToolProvider(controller, { id, namespace, readOnly, rasterize }));\n }, [registry, controller, id, namespace, readOnly, rasterize]);\n}\n","import React, { useMemo } from 'react';\nimport { highlightMotionSvg, motionNodeAtElement, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationStageProps {\n controller: AnimationEditorController;\n /** Control values to preview (`{ accent: \"#0ea5e9\" }`). */\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel: true for every node whose place changes, or a list of ids. */\n motionPaths?: boolean | readonly string[];\n /**\n * Called when the stage is clicked, with the id of the artwork node under the pointer (the\n * innermost one; null for the background, ghosts and paths). Makes the stage pickable.\n */\n onPick?: (id: string | null, event: React.MouseEvent<HTMLDivElement>) => void;\n /** Node ids to outline (e.g. the picked element and the selected command's targets). */\n highlight?: readonly string[];\n className?: string;\n}\n\n/**\n * The animation's frame at the playhead, drawn as inline SVG scaled to the stage's width. The\n * SVG keeps the artwork's node ids, so `onPick` can say which element was clicked.\n */\nexport function AnimationStage({ controller, values, onionSkin, motionPaths, onPick, highlight, className = '' }: AnimationStageProps) {\n const state = useAnimationEditorState(controller);\n const { scene, time } = state;\n const key = highlight?.join('\\u0000') ?? '';\n const svg = useMemo(\n () =>\n highlightMotionSvg(\n controller.toSvg(time, { pretty: false, idPrefix: 'ae-', values, onionSkin, motionPaths }).replace(/<svg ([^>]*?)width=\"[^\"]*\" height=\"[^\"]*\"/, '<svg $1width=\"100%\" height=\"100%\"'),\n highlight ?? [],\n ),\n [controller, scene, time, values, onionSkin, motionPaths, key],\n );\n return (\n <div\n className={`relative overflow-hidden ${onPick ? 'cursor-crosshair' : ''} ${className}`}\n style={{ aspectRatio: `${scene.artwork.width} / ${scene.artwork.height}` }}\n data-animation-stage=\"\"\n role=\"img\"\n aria-label={`${scene.name} at ${(time / 1000).toFixed(2)} s`}\n onClick={onPick ? (e) => onPick(motionNodeAtElement(scene, e.target as Element, e.currentTarget), e) : undefined}\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n );\n}\n","import React from 'react';\nimport type { AnimationEditorController, MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotTimelineProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(1)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play / pause, the playhead and one block per shot (as wide as it is long): click a shot to\n * select it and jump to its start, click the ruler to seek. Shots with errors or warnings are marked.\n */\nexport function ShotTimeline({ controller, className = '' }: ShotTimelineProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues } = state;\n const span = Math.max(1, duration);\n const onRuler = (event: React.PointerEvent<HTMLDivElement>) => {\n const box = event.currentTarget.getBoundingClientRect();\n controller.seek(((event.clientX - box.left) / Math.max(1, box.width)) * span);\n };\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <span className=\"tabular-nums text-muted-foreground\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div className=\"relative h-3 cursor-pointer rounded bg-muted\" onPointerDown={onRuler} role=\"slider\" aria-label=\"Playhead\" aria-valuemin={0} aria-valuemax={duration} aria-valuenow={Math.round(time)} tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') controller.seek(time + 100);\n if (e.key === 'ArrowLeft') controller.seek(time - 100);\n }}>\n <div className=\"absolute inset-y-0 w-0.5 bg-rose-500\" style={{ left: `${(time / span) * 100}%` }} />\n </div>\n <div className=\"flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot) => {\n const mark = worst(issues.filter((i) => i.shot === shot.id));\n const selected = selection?.shot === shot.id;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.end - shot.start)}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { indexMotionNodes, motionIssueLine, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { AnimationStage } from './AnimationStage';\nimport { CommandInspector } from './CommandInspector';\nimport { CommandList } from './CommandList';\nimport { PlayheadScrubber } from './PlayheadScrubber';\nimport { SceneSettings } from './SceneSettings';\nimport { ShotInspector } from './ShotInspector';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationEditorProps {\n controller: AnimationEditorController;\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead (see `<AnimationStage onionSkin>`). Default: an Onion skin toggle. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel (see `<AnimationStage motionPaths>`). Default: a Motion paths toggle. */\n motionPaths?: boolean | readonly string[];\n /** List the scene's issues under the timeline (default true). */\n showIssues?: boolean;\n /**\n * Show the hand-editing panels: the command list and inspector, the shot inspector, scene\n * settings, undo / redo and picking on the stage (default true). False shows the stage,\n * scrubber and issues only.\n */\n editable?: boolean;\n className?: string;\n}\n\nconst ONION: MotionOnionSkin = { before: 3, after: 1 };\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * A whole animation editor for an `AnimationEditorController`: the stage (click an element to\n * pick it, shift-click to add it to or remove it from the selected command's targets), the\n * playhead scrubber, and panels to edit commands, shots and scene settings by hand. Every edit\n * is one undo step.\n */\nexport function AnimationEditor({ controller, values, onionSkin, motionPaths, showIssues = true, editable = true, className = '' }: AnimationEditorProps) {\n const state = useAnimationEditorState(controller);\n const { issues, scene, selection, readOnly } = state;\n const [picked, setPicked] = useState<string | null>(null);\n const [onion, setOnion] = useState(false);\n const [paths, setPaths] = useState(false);\n const command = selection?.command !== undefined ? scene.shots.find((s) => s.id === selection.shot)?.run[selection.command] : undefined;\n const targets = command && 'targets' in command ? command.targets : [];\n const nodes = useMemo(() => indexMotionNodes(scene.artwork.nodes), [scene.artwork]);\n const pickedValid = picked && nodes.has(picked) ? picked : null;\n const onPick = (id: string | null, event: { shiftKey: boolean }) => {\n if (event.shiftKey && id && command && 'targets' in command && selection?.command !== undefined && !readOnly) {\n const next = targets.includes(id) ? targets.filter((t) => t !== id) : [...targets, id];\n if (next.length) controller.apply({ op: 'update_command', shot: selection.shot, command: selection.command, set: { targets: next } }, next.length > targets.length ? 'Add target' : 'Remove target');\n return;\n }\n setPicked(id);\n };\n const stage = (\n <AnimationStage\n controller={controller}\n values={values}\n onionSkin={onionSkin ?? (onion ? ONION : undefined)}\n motionPaths={motionPaths ?? paths}\n onPick={editable ? onPick : undefined}\n highlight={editable ? [...(pickedValid ? [pickedValid] : []), ...targets] : undefined}\n className=\"rounded-md border border-border bg-muted/40\"\n />\n );\n const issueList = showIssues && issues.length > 0 && (\n <ul className=\"space-y-0.5 text-xs\" aria-label=\"Animation issues\">\n {issues.map((issue, i) => (\n <li key={i} className={issue.severity === 'error' ? 'text-red-500' : issue.severity === 'warning' ? 'text-amber-500' : 'text-muted-foreground'}>\n {motionIssueLine(issue)}\n </li>\n ))}\n </ul>\n );\n if (!editable)\n return (\n <div className={`flex flex-col gap-2 ${className}`} data-animation-editor=\"\">\n {stage}\n <PlayheadScrubber controller={controller} />\n {issueList}\n </div>\n );\n\n return (\n <div\n className={`grid gap-3 lg:grid-cols-[minmax(0,1fr)_20rem] ${className}`}\n data-animation-editor=\"\"\n onKeyDown={(e) => {\n const el = e.target as HTMLElement;\n if (!(e.metaKey || e.ctrlKey) || e.key.toLowerCase() !== 'z' || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName)) return;\n e.preventDefault();\n if (e.shiftKey) controller.redo();\n else controller.undo();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-2\">\n {stage}\n <PlayheadScrubber controller={controller} />\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n <button type=\"button\" className={btn} onClick={() => controller.undo()} disabled={!state.canUndo} title={state.canUndo ? `Undo ${state.undoLabel}` : 'Nothing to undo'} data-undo=\"\">\n Undo\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.redo()} disabled={!state.canRedo} title={state.canRedo ? `Redo ${state.redoLabel}` : 'Nothing to redo'} data-redo=\"\">\n Redo\n </button>\n {onionSkin === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={onion} onChange={(e) => setOnion(e.target.checked)} /> Onion skin\n </label>\n )}\n {motionPaths === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={paths} onChange={(e) => setPaths(e.target.checked)} /> Motion paths\n </label>\n )}\n <span className=\"ml-auto\" data-picked-element={pickedValid ?? undefined}>\n {pickedValid ? (\n <>\n Picked <code className=\"text-rose-500\">{pickedValid}</code>{' '}\n <button type=\"button\" className=\"underline\" onClick={() => setPicked(null)}>\n clear\n </button>\n </>\n ) : (\n 'Click the stage to pick an element; shift-click to toggle it as a target.'\n )}\n </span>\n </div>\n {issueList}\n </div>\n <div className=\"flex min-w-0 flex-col gap-3\">\n <CommandList controller={controller} targets={pickedValid ? [pickedValid] : undefined} />\n <CommandInspector controller={controller} picked={pickedValid} className=\"border-t border-border pt-2\" />\n <details open className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Shot</summary>\n <ShotInspector controller={controller} className=\"mt-1\" />\n </details>\n <details className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Scene settings</summary>\n <SceneSettings controller={controller} className=\"mt-1\" />\n </details>\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport {\n describeMotionElements,\n motionCommandFields,\n motionFieldEdit,\n motionFlairPrimitive,\n type AnimationEditorController,\n type MotionFieldSpec,\n} from '@pixerate/editor/animation-editor';\nimport { EasePicker } from './EasePicker';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandInspectorProps {\n controller: AnimationEditorController;\n /** An element picked on the stage, offered as a target to add. */\n picked?: string | null;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\n\n\n/**\n * A form for the selected command, generated from `MOTION_COMMAND_SCHEMA` (the schema the\n * agent tools take): enums as selects, numbers with their units and limits, node pickers for\n * targets and for `into` / `path`, and an ease picker. Shows the Flair primitive it plays.\n */\nexport function CommandInspector({ controller, picked, className = '' }: CommandInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const shot = selection ? scene.shots.find((s) => s.id === selection.shot) : undefined;\n const index = selection?.command;\n const command = shot && index !== undefined ? shot.run[index] : undefined;\n if (!shot || index === undefined || !command) {\n return (\n <div className={`text-xs text-muted-foreground ${className}`} data-command-inspector=\"\">\n Select a command to edit it.\n </div>\n );\n }\n const values = command as unknown as Record<string, unknown>;\n const fields = motionCommandFields(command.type);\n const primitive = motionFlairPrimitive(command);\n const commit = (field: MotionFieldSpec, raw: Parameters<typeof motionFieldEdit>[3]) => {\n const edit = motionFieldEdit(shot.id, index, field, raw);\n if ('error' in edit) return setLocal(edit.error);\n setLocal(null);\n controller.apply(edit, `Set ${field.label.toLowerCase()}`);\n };\n const name = (id: string) => elements.find((e) => e.id === id)?.name ?? id;\n const targets = (values.targets as string[] | undefined) ?? [];\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n const control = (field: MotionFieldSpec) => {\n const v = values[field.name];\n const common = { disabled: readOnly, 'aria-label': field.label, title: field.description };\n switch (field.kind) {\n case 'targets':\n return (\n <div className=\"flex flex-wrap items-center gap-1\" data-targets=\"\">\n {targets.map((id) => (\n <span key={id} className=\"flex items-center gap-0.5 rounded bg-muted px-1 text-[11px]\" data-target={id}>\n {name(id)}\n {!readOnly && targets.length > 1 && (\n <button type=\"button\" aria-label={`Remove ${id}`} onClick={() => commit(field, targets.filter((t) => t !== id))}>\n ×\n </button>\n )}\n </span>\n ))}\n {!readOnly && picked && !targets.includes(picked) && (\n <button type=\"button\" className=\"rounded border border-rose-500 px-1 text-[11px] text-rose-500\" onClick={() => commit(field, [...targets, picked])} data-add-picked=\"\">\n + {name(picked)}\n </button>\n )}\n {!readOnly && (\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\" aria-label=\"Add target\" value=\"\" onChange={(e) => e.target.value && commit(field, [...targets, e.target.value])}>\n <option value=\"\">+ target…</option>\n {elements.filter((e) => !targets.includes(e.id)).map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n </option>\n ))}\n </select>\n )}\n </div>\n );\n case 'node':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">—</option>}\n {elements.filter((e) => field.name !== 'path' || e.type === 'path').map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n {e.hidden ? ' · hidden' : ''}\n </option>\n ))}\n </select>\n );\n case 'enum':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">default</option>}\n {field.options!.map((o) => (\n <option key={o} value={o}>\n {o}\n </option>\n ))}\n </select>\n );\n case 'boolean':\n return <input type=\"checkbox\" {...common} checked={v === true} onChange={(e) => commit(field, e.target.checked)} />;\n case 'ease':\n return <EasePicker value={v as never} disabled={readOnly} onChange={(ease) => commit(field, ease === undefined ? '' : (ease as string))} />;\n case 'color':\n return (\n <div className=\"flex items-center gap-1\">\n <input type=\"color\" disabled={readOnly} aria-label={`${field.label} swatch`} value={typeof v === 'string' && /^#[0-9a-f]{6}$/i.test(v) ? v : '#000000'} onChange={(e) => commit(field, e.target.value)} />\n <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} placeholder=\"unchanged\" onCommit={(raw) => commit(field, raw)} />\n </div>\n );\n case 'point': {\n const p = (v as { x: number; y: number } | undefined) ?? undefined;\n return (\n <div className=\"flex items-center gap-1\">\n {(['x', 'y'] as const).map((axis) => (\n <CommitInput\n key={axis}\n className={input}\n type=\"number\"\n disabled={readOnly}\n aria-label={`${field.label} ${axis}`}\n placeholder={axis}\n value={p ? String(p[axis]) : ''}\n onCommit={(raw) => commit(field, axis === 'x' ? { x: raw, y: p ? String(p.y) : raw ? '0' : '' } : { x: p ? String(p.x) : raw ? '0' : '', y: raw })}\n />\n ))}\n </div>\n );\n }\n case 'scale':\n case 'number':\n case 'integer':\n return (\n <div className=\"flex items-center gap-1\">\n <CommitInput\n className={input}\n type=\"number\"\n {...common}\n min={field.min}\n max={field.max}\n step={field.kind === 'integer' ? 1 : field.unit === 'ms' ? 50 : field.unit === '0–1' ? 0.05 : 'any'}\n placeholder=\"default\"\n value={typeof v === 'number' ? String(v) : ''}\n onCommit={(raw) => commit(field, raw)}\n />\n {field.unit && <span className=\"shrink-0 text-[10px] text-muted-foreground\">{field.unit}</span>}\n </div>\n );\n default:\n return <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} onCommit={(raw) => commit(field, raw)} />;\n }\n };\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-command-inspector=\"\" data-command-type={command.type}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">\n {index + 1}. {command.type}\n </span>\n {primitive ? (\n <code className=\"rounded bg-muted px-1 text-[10px]\" data-flair-primitive={primitive} title=\"The Flair motion primitive this command plays\">\n {primitive}\n </code>\n ) : (\n <span className=\"text-[10px] text-muted-foreground\">editor-only (no Flair primitive)</span>\n )}\n </div>\n {(['main', 'timing'] as const).map((group) => (\n <fieldset key={group} className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <legend className=\"mb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">{group === 'main' ? 'Command' : 'Timing'}</legend>\n {fields\n .filter((f) => f.group === group)\n .map((field) => (\n <React.Fragment key={field.name}>\n <label className=\"truncate text-muted-foreground\" title={field.description}>\n {field.label}\n {field.required ? ' *' : ''}\n </label>\n <div data-field={field.name}>{control(field)}</div>\n </React.Fragment>\n ))}\n </fieldset>\n ))}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo } from 'react';\nimport { MOTION_EASE_CHOICES, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, type MotionCommandBase } from '@pixerate/editor/animation-editor';\n\n/** An easing (a preset name or a curve), as commands take it. */\ntype AnimationEasing = NonNullable<MotionCommandBase['ease']>;\n\nexport interface EasePickerProps {\n /** The easing (undefined: the command type's default). */\n value: AnimationEasing | undefined;\n /** Called with the picked preset, or undefined for the default. */\n onChange: (ease: AnimationEasing | undefined) => void;\n disabled?: boolean;\n className?: string;\n}\n\nconst W = 72;\nconst H = 44;\n\n/**\n * Picks an easing preset (springs included) and previews its curve, drawn by sampling\n * `evaluateEasing`; a spring is drawn over the time it takes to settle, overshoot included.\n */\nexport function EasePicker({ value, onChange, disabled, className = '' }: EasePickerProps) {\n const key = motionEaseKey(value);\n const curve = useMemo(() => motionEasingCurve(value ?? 'ease-out'), [value]);\n const guides = motionEasingGuides(curve, H);\n const spring = typeof value === 'string' ? value.startsWith('spring') : value?.type === 'spring';\n return (\n <div className={`flex items-center gap-2 ${className}`} data-ease-picker=\"\">\n <select\n className=\"min-w-0 flex-1 rounded border border-border bg-transparent px-1 py-0.5 text-xs\"\n aria-label=\"Ease\"\n value={key}\n disabled={disabled}\n onChange={(e) => {\n if (e.target.value === 'custom') return;\n onChange(e.target.value ? (e.target.value as AnimationEasing) : undefined);\n }}\n >\n {MOTION_EASE_CHOICES.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n {key === 'custom' && <option value=\"custom\">Custom</option>}\n </select>\n <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} className=\"shrink-0 rounded border border-border\" data-ease-curve={key || 'default'} aria-hidden=\"true\">\n <line x1={0} x2={W} y1={guides.zero} y2={guides.zero} stroke=\"currentColor\" strokeOpacity={0.2} />\n <line x1={0} x2={W} y1={guides.one} y2={guides.one} stroke=\"currentColor\" strokeOpacity={0.2} strokeDasharray=\"2 2\" />\n <path d={motionEasingPath(curve, W, H)} fill=\"none\" stroke=\"#f43f5e\" strokeWidth={1.5} />\n </svg>\n {spring && <span className=\"text-[10px] tabular-nums text-muted-foreground\">{Math.round(curve.durationMs)} ms</span>}\n </div>\n );\n}\n","import React from 'react';\n\n/** An input that commits on blur or Enter, and resets when its value changes from outside. */\nexport function CommitInput({ value, onCommit, ...rest }: { value: string; onCommit: (raw: string) => void } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue'>) {\n return (\n <input\n key={value}\n {...rest}\n defaultValue={value}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n if (e.currentTarget.value !== value) onCommit(e.currentTarget.value);\n }}\n />\n );\n}\n","import React, { useState } from 'react';\nimport {\n MOTION_COMMAND_TYPES,\n defaultMotionCommand,\n duplicateMotionCommandEdit,\n motionCommandRows,\n type AnimationEditorController,\n type MotionCommandType,\n} from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandListProps {\n controller: AnimationEditorController;\n /** The shot to list (default: the selected shot, else the first). */\n shot?: string;\n /** Targets for a new command (e.g. the element picked on the stage); default: the selected command's. */\n targets?: readonly string[];\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n/**\n * A shot's commands in order: select one to inspect it, change `with` and `delay` inline, move,\n * duplicate or delete it, and add new ones. Each change is one `controller.apply` edit (one undo\n * step); a refused edit shows its reason.\n */\nexport function CommandList({ controller, shot, targets, className = '' }: CommandListProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const shotId = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const current = scene.shots.find((s) => s.id === shotId);\n const [type, setType] = useState<MotionCommandType>('enter');\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n if (!current) return <div className={`text-xs text-muted-foreground ${className}`} data-command-list=\"\">Add a shot to start.</div>;\n const rows = motionCommandRows(scene, current.id);\n const selected = selection?.shot === current.id ? selection.command : undefined;\n const run = (edit: Parameters<AnimationEditorController['apply']>[0], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const add = () => {\n const from = targets?.length ? targets : selected !== undefined ? ((current.run[selected] as { targets?: string[] }).targets ?? []) : [];\n const command = defaultMotionCommand(type, from, scene);\n if ('error' in command) return setLocal(command.error);\n const at = selected !== undefined ? selected + 1 : current.run.length;\n const result = run({ op: 'add_commands', shot: current.id, commands: [command], at }, `Add ${type}`);\n if (result.ok) controller.select({ shot: current.id, command: at });\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1 text-xs ${className}`} data-command-list=\"\" data-for-shot={current.id}>\n <div className=\"font-medium\">\n Commands in <span className=\"text-rose-500\">{current.label ?? current.id}</span>\n </div>\n <ol className=\"flex flex-col gap-1\" aria-label=\"Commands\">\n {rows.map((row) => {\n const c = row.command as { with?: string; delay?: number };\n const isSelected = row.index === selected;\n return (\n <li\n key={`${row.index}:${row.summary}`}\n className={`flex flex-wrap items-center gap-1 rounded border px-1.5 py-1 ${isSelected ? 'border-rose-500 bg-rose-500/10' : 'border-border'}`}\n data-command={row.index}\n data-selected={isSelected || undefined}\n onClick={() => controller.select({ shot: current.id, command: row.index })}\n >\n <span className=\"min-w-0 flex-1 truncate\" title={row.summary}>\n {row.index + 1}. {row.summary}\n </span>\n {row.flairPrimitive && (\n <code className=\"rounded bg-muted px-1 text-[10px] text-muted-foreground\" data-flair-primitive={row.flairPrimitive}>\n {row.flairPrimitive}\n </code>\n )}\n <span className=\"tabular-nums text-[10px] text-muted-foreground\">{((row.end - row.start) / 1000).toFixed(2)} s</span>\n <div className=\"flex w-full items-center gap-1\" onClick={(e) => e.stopPropagation()}>\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\"\n aria-label=\"Starts\"\n value={c.with ?? 'after'}\n disabled={readOnly || row.index === 0}\n onChange={(e) =>\n run(\n e.target.value === 'after' ? { op: 'update_command', shot: current.id, command: row.index, remove: ['with'] } : { op: 'update_command', shot: current.id, command: row.index, set: { with: e.target.value } },\n 'Change start',\n )\n }\n >\n <option value=\"after\">after previous</option>\n <option value=\"previous\">with previous</option>\n </select>\n <label className=\"flex items-center gap-0.5 text-muted-foreground\">\n +\n <input\n key={String(c.delay ?? '')}\n className=\"w-14 rounded border border-border bg-transparent px-1 py-0.5 text-[11px] tabular-nums\"\n type=\"number\"\n min={0}\n step={50}\n aria-label=\"Delay\"\n placeholder=\"0\"\n defaultValue={c.delay ?? ''}\n disabled={readOnly}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n const raw = e.currentTarget.value.trim();\n if (raw === String(c.delay ?? '')) return;\n const n = Number(raw);\n if (raw && !(Number.isFinite(n) && n >= 0)) return setLocal('Delay must be a number of ms, 0 or more.');\n run(raw && n > 0 ? { op: 'update_command', shot: current.id, command: row.index, set: { delay: n } } : { op: 'update_command', shot: current.id, command: row.index, remove: ['delay'] }, 'Change delay');\n }}\n />\n ms\n </label>\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} aria-label=\"Move up\" disabled={readOnly || row.index === 0} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index - 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index - 1 })}>\n ↑\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move down\" disabled={readOnly || row.index === rows.length - 1} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index + 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ↓\n </button>\n <button type=\"button\" className={btn} aria-label=\"Duplicate\" disabled={readOnly} onClick={() => run(duplicateMotionCommandEdit(scene, current.id, row.index), 'Duplicate command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ⧉\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete\" disabled={readOnly} onClick={() => run({ op: 'delete_commands', shot: current.id, commands: [row.index] }, 'Delete command')}>\n ✕\n </button>\n </span>\n </div>\n </li>\n );\n })}\n </ol>\n {!readOnly && (\n <div className=\"flex items-center gap-1\">\n <select className=\"flex-1 rounded border border-border bg-transparent px-1 py-0.5\" aria-label=\"New command type\" value={type} onChange={(e) => setType(e.target.value as MotionCommandType)}>\n {MOTION_COMMAND_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <button type=\"button\" className={btn} onClick={add} data-add-command=\"\">\n Add command\n </button>\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { motionBeatTime, motionCueTime, motionRulerTicks, type AnimationEditorController, type MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface PlayheadScrubberProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(2)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play, pause and loop, a time ruler (with the beat grid and narration words when the scene has\n * them) to scrub by dragging, and one band per shot (as wide as it is long): click a band to\n * select the shot and jump to its start. Loop is a scene setting, so changing it is one undo step.\n */\nexport function PlayheadScrubber({ controller, className = '' }: PlayheadScrubberProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues, scene, readOnly } = state;\n const span = Math.max(1, duration);\n const track = useRef<HTMLDivElement>(null);\n const [width, setWidth] = useState(600);\n useEffect(() => {\n const el = track.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => setWidth(el.clientWidth || 600));\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n const ticks = motionRulerTicks(duration, width);\n const pct = (ms: number) => `${(Math.min(span, Math.max(0, ms)) / span) * 100}%`;\n const seekAt = (clientX: number) => {\n const box = track.current!.getBoundingClientRect();\n controller.seek(Math.min(1, Math.max(0, (clientX - box.left) / Math.max(1, box.width))) * span);\n };\n const beats: number[] = [];\n if (scene.beat && scene.beat.bpm > 0) for (let b = 0, t = motionBeatTime(scene.beat, 0); t <= span && beats.length < 400; t = motionBeatTime(scene.beat, ++b)) if (t >= 0) beats.push(t);\n\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-playhead-scrubber=\"\" data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => { controller.pause(); controller.seek(0); }} aria-label=\"Back to start\">\n ⏮\n </button>\n <label className=\"flex items-center gap-1 text-muted-foreground\">\n Loop\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5\"\n value={scene.loop ?? 'none'}\n disabled={readOnly}\n aria-label=\"Loop\"\n onChange={(e) => controller.apply({ op: 'set_settings', loop: e.target.value as 'none' | 'loop' | 'ping-pong' }, 'Change loop')}\n >\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n </label>\n <span className=\"ml-auto tabular-nums text-muted-foreground\" data-time=\"\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div\n ref={track}\n className=\"relative cursor-ew-resize select-none touch-none\"\n role=\"slider\"\n aria-label=\"Playhead\"\n aria-valuemin={0}\n aria-valuemax={duration}\n aria-valuenow={Math.round(time)}\n tabIndex={0}\n data-scrub-track=\"\"\n onPointerDown={(e) => {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n seekAt(e.clientX);\n }}\n onPointerMove={(e) => {\n if (e.buttons & 1) seekAt(e.clientX);\n }}\n onKeyDown={(e) => {\n const step = e.shiftKey ? 1000 : 100;\n if (e.key === 'ArrowRight') controller.seek(time + step);\n else if (e.key === 'ArrowLeft') controller.seek(time - step);\n else if (e.key === 'Home') controller.seek(0);\n else if (e.key === 'End') controller.seek(duration);\n else if (e.key === ' ') controller.toggle();\n else return;\n e.preventDefault();\n }}\n >\n <div className=\"relative h-5 border-b border-border text-[10px] text-muted-foreground\" data-ruler=\"\">\n {beats.map((t, i) => (\n <div key={`b${i}`} className=\"absolute bottom-0 h-1.5 w-px bg-sky-500/60\" style={{ left: pct(t) }} data-beat={i} />\n ))}\n {scene.narration?.words.map((w, i) => (\n <div key={`w${i}`} className=\"absolute top-0 h-1.5 w-px bg-emerald-500/70\" style={{ left: pct(w.start) }} title={`“${w.text}” at ${seconds(w.start)}`} data-word={i} />\n ))}\n {ticks.map((t) => (\n <div key={t.time} className={`absolute bottom-0 w-px ${t.major ? 'h-2.5 bg-muted-foreground/70' : 'h-1 bg-muted-foreground/40'}`} style={{ left: pct(t.time) }}>\n {t.label && <span className=\"absolute -top-0.5 left-1 whitespace-nowrap tabular-nums\">{t.label}</span>}\n </div>\n ))}\n </div>\n <div className=\"mt-1 flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot, i) => {\n const mark = worst(issues.filter((x) => x.shot === shot.id));\n const selected = selection?.shot === shot.id;\n const cue = scene.shots[i]?.at;\n const cueTime = cue ? motionCueTime(scene, cue) : undefined;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`relative min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border bg-muted/40'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.start)}–${seconds(shot.end)}${cueTime !== undefined ? ` · cued at ${seconds(cueTime)}` : ''}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onPointerDown={(e) => e.stopPropagation()}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n <div className=\"pointer-events-none absolute inset-y-0 w-0.5 -translate-x-1/2 bg-rose-500\" style={{ left: pct(time) }} data-playhead=\"\" />\n </div>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport { fitMotionSceneEdits, formatMotionNarration, parseMotionNarration, type AnimationEditorController, type MotionEdit, type MotionTrigger } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface SceneSettingsProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\nconst unit = (u: string) => <span className=\"shrink-0 text-[10px] text-muted-foreground\">{u}</span>;\n\n/**\n * Scene settings: loop, frame rate, stepped time, the wanted length with a Fit button (sets the\n * shots' speeds with `fitMotionScene`, as `fit_animation` does), a beat grid and narration words\n * to cue shots to. Every change is one undo step; refusals show their reason.\n */\nexport function SceneSettings({ controller, className = '' }: SceneSettingsProps) {\n const state = useAnimationEditorState(controller);\n const { scene, readOnly, error, duration } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const [fitTo, setFitTo] = useState<string>('');\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const settings = (set: Omit<Extract<MotionEdit, { op: 'set_settings' }>, 'op'>, label: string) => apply({ op: 'set_settings', ...set }, label);\n const num = (raw: string, what: string, ok: (n: number) => boolean, then: (n: number | null) => void) => {\n if (raw.trim() === '') return then(null);\n const n = Number(raw);\n if (!Number.isFinite(n) || !ok(n)) return setLocal(what);\n then(n);\n };\n const target = scene.target;\n const fitSeconds = fitTo || String(target ? (target[0] + target[1]) / 2 : Math.round(duration / 100) / 10);\n const fit = () => {\n const s = Number(fitSeconds);\n if (!(Number.isFinite(s) && s > 0)) return setLocal('Give the length to fit in seconds, above 0.');\n try {\n const edits = fitMotionSceneEdits(scene, s * 1000);\n if (edits.length) apply(edits, `Fit to ${s} s`);\n else setLocal(null);\n } catch (e) {\n setLocal((e as Error).message);\n }\n };\n const beat = scene.beat;\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-scene-settings=\"\">\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Loop</label>\n <select className={input} aria-label=\"Scene loop\" disabled={readOnly} value={scene.loop ?? 'none'} onChange={(e) => settings({ loop: e.target.value as 'none' }, 'Change loop')}>\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n <label className=\"text-muted-foreground\">Plays on</label>\n <select className={input} aria-label=\"Scene trigger\" title=\"How a viewer plays it when exported to Flair\" disabled={readOnly} value={scene.trigger ?? ''} onChange={(e) => settings({ trigger: (e.target.value || null) as MotionTrigger | null }, 'Change trigger')}>\n <option value=\"\">Its own (autoplay)</option>\n <option value=\"click\">Click (a shot per click)</option>\n <option value=\"hover\">Hover</option>\n <option value=\"press\">Press</option>\n <option value=\"scroll\">Scroll</option>\n </select>\n <label className=\"text-muted-foreground\">Frame rate</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Frame rate\" placeholder=\"30\" disabled={readOnly} value={scene.fps !== undefined ? String(scene.fps) : ''}\n onCommit={(raw) => num(raw, 'Frame rate must be 1 to 120 fps.', (n) => n >= 1 && n <= 120, (n) => n !== null && settings({ fps: n }, 'Change frame rate'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\" title=\"Hold changes on a grid of this many frames a second (12 = on twos); empty is smooth\">\n Steps\n </label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Steps\" placeholder=\"smooth\" disabled={readOnly} value={scene.steps !== undefined ? String(scene.steps) : ''}\n onCommit={(raw) => num(raw, 'Steps must be above 0 and at most 120 fps, or empty for smooth.', (n) => n > 0 && n <= 120, (n) => settings({ steps: n }, 'Change steps'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\">Target length</label>\n <div className=\"flex items-center gap-1\">\n {[0, 1].map((i) => (\n <CommitInput key={i} className={input} type=\"number\" min={0} step={0.5} aria-label={i ? 'Target max' : 'Target min'} placeholder={i ? 'max' : 'min'} disabled={readOnly} value={target ? String(target[i]) : ''}\n onCommit={(raw) =>\n num(raw, 'Target lengths are seconds, 0 or more.', (n) => n >= 0, (n) => {\n if (n === null) return settings({ target: null }, 'Clear target length');\n const next: [number, number] = target ? [...target] : [n, n];\n next[i] = n;\n if (next[0] > next[1]) return setLocal('The shortest target length must not be longer than the longest.');\n settings({ target: next }, 'Change target length');\n })\n } />\n ))}\n {unit('s')}\n </div>\n <label className=\"text-muted-foreground\">Fit to</label>\n <div className=\"flex items-center gap-1\">\n <input className={input} type=\"number\" min={0.1} step={0.5} aria-label=\"Fit to\" value={fitSeconds} onChange={(e) => setFitTo(e.target.value)} />\n {unit('s')}\n <button type=\"button\" className={btn} disabled={readOnly || !scene.shots.length} onClick={fit} data-fit=\"\" title=\"Change the shots' speeds so the scene lasts this long\">\n Fit\n </button>\n </div>\n <label className=\"text-muted-foreground\">Beat grid</label>\n <div className=\"flex items-center gap-1\" data-beat-grid=\"\">\n <CommitInput className={input} type=\"number\" min={1} aria-label=\"BPM\" placeholder=\"bpm\" disabled={readOnly} value={beat ? String(beat.bpm) : ''}\n onCommit={(raw) => num(raw, 'BPM must be above 0.', (n) => n > 0, (n) => settings({ beat: n === null ? null : { ...(beat ?? {}), bpm: n } }, n === null ? 'Clear beat grid' : 'Change tempo'))} />\n <CommitInput className={input} type=\"number\" aria-label=\"Beat offset\" placeholder=\"offset ms\" disabled={readOnly || !beat} value={beat?.offset !== undefined ? String(beat.offset) : ''}\n onCommit={(raw) => beat && num(raw, 'The offset is a number of ms.', () => true, (n) => settings({ beat: { ...beat, offset: n ?? 0 } }, 'Change beat offset'))} />\n <CommitInput className={input} type=\"number\" min={1} step={1} aria-label=\"Meter\" placeholder=\"4/bar\" disabled={readOnly || !beat} value={beat?.meter !== undefined ? String(beat.meter) : ''}\n onCommit={(raw) => beat && num(raw, 'The meter is a whole number of beats a bar.', (n) => Number.isInteger(n) && n >= 1, (n) => settings({ beat: { ...beat, meter: n ?? 4 } }, 'Change meter'))} />\n </div>\n </div>\n <label className=\"flex flex-col gap-0.5\">\n <span className=\"text-muted-foreground\">Narration (a word a line: start ms, then the word)</span>\n <textarea\n key={formatMotionNarration(scene.narration)}\n className={`${input} h-20 font-mono`}\n aria-label=\"Narration\"\n placeholder={'0 Meet\\n320 the\\n480 badge'}\n disabled={readOnly}\n defaultValue={formatMotionNarration(scene.narration)}\n onBlur={(e) => {\n if (e.currentTarget.value === formatMotionNarration(scene.narration)) return;\n const parsed = parseMotionNarration(e.currentTarget.value);\n if ('error' in parsed) return setLocal(parsed.error);\n settings({ narration: parsed.narration }, parsed.narration ? 'Change narration' : 'Clear narration');\n }}\n />\n </label>\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { describeMotionElements, freshShotId, motionCueChoices, motionCueFromKey, motionCueKey, type AnimationEditorController, type MotionEdit } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotInspectorProps {\n controller: AnimationEditorController;\n /** The shot to edit (default: the selected shot, else the first). */\n shot?: string;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n\n/**\n * The selected shot: its label, hold, speed, the node the camera frames, and the cue it starts\n * on (a beat of the scene's grid or a narration word). Also adds, moves and deletes shots.\n * Every change is one undo step.\n */\nexport function ShotInspector({ controller, shot, className = '' }: ShotInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const cues = useMemo(() => motionCueChoices(scene), [scene]);\n const id = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const index = scene.shots.findIndex((s) => s.id === id);\n const current = scene.shots[index];\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const addShot = () => {\n const newId = freshShotId(scene, 'shot');\n const at = index >= 0 ? index + 1 : scene.shots.length;\n if (apply({ op: 'insert_shots', shots: [{ id: newId, label: 'New shot', run: [] }], at }, 'Add shot').ok) {\n controller.select({ shot: newId });\n controller.seekShot(newId);\n }\n };\n const number = (key: 'hold' | 'speed', raw: string, label: string) => {\n const n = Number(raw);\n if (raw.trim() === '') return apply({ op: 'update_shot', shot: current.id, remove: [key] }, label);\n if (!Number.isFinite(n) || n < 0 || (key === 'speed' && n <= 0)) return setLocal(key === 'speed' ? 'Speed must be a number above 0 (1 = as written).' : 'Hold must be a number of ms, 0 or more.');\n apply({ op: 'update_shot', shot: current.id, set: { [key]: n } }, label);\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n const cueKey = current ? motionCueKey(current.at) : '';\n const frame = current?.camera && 'frame' in current.camera ? current.camera.frame : '';\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-shot-inspector=\"\">\n <div className=\"flex items-center gap-1\">\n <span className=\"font-medium\">Shot</span>\n {current && <code className=\"text-[10px] text-muted-foreground\">{current.id}</code>}\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} disabled={readOnly} onClick={addShot} data-add-shot=\"\">\n + Shot\n </button>\n {current && (\n <>\n <button type=\"button\" className={btn} aria-label=\"Move shot earlier\" disabled={readOnly || index === 0} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index - 1 }, 'Move shot')}>\n ←\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move shot later\" disabled={readOnly || index === scene.shots.length - 1} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index + 1 }, 'Move shot')}>\n →\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete shot\" disabled={readOnly} onClick={() => apply({ op: 'delete_shots', shots: [current.id] }, 'Delete shot')}>\n ✕\n </button>\n </>\n )}\n </span>\n </div>\n {current && (\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Label</label>\n <CommitInput className={input} aria-label=\"Shot label\" disabled={readOnly} value={current.label ?? ''} onCommit={(raw) => apply(raw.trim() ? { op: 'update_shot', shot: current.id, set: { label: raw.trim() } } : { op: 'update_shot', shot: current.id, remove: ['label'] }, 'Rename shot')} />\n <label className=\"text-muted-foreground\">Hold</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0} step={50} aria-label=\"Hold\" placeholder=\"600\" disabled={readOnly} value={current.hold !== undefined ? String(current.hold) : ''} onCommit={(raw) => number('hold', raw, 'Change hold')} />\n <span className=\"text-[10px] text-muted-foreground\">ms</span>\n </div>\n <label className=\"text-muted-foreground\">Speed</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0.05} step={0.05} aria-label=\"Speed\" placeholder=\"1\" disabled={readOnly} value={current.speed !== undefined ? String(current.speed) : ''} onCommit={(raw) => number('speed', raw, 'Change speed')} />\n <span className=\"text-[10px] text-muted-foreground\">×</span>\n </div>\n <label className=\"text-muted-foreground\">Camera</label>\n <select\n className={input}\n aria-label=\"Camera frames\"\n disabled={readOnly}\n value={current.camera ? (frame ? `frame:${frame}` : 'rect') : ''}\n onChange={(e) => {\n const v = e.target.value;\n if (!v) apply({ op: 'update_shot', shot: current.id, remove: ['camera'] }, 'Clear camera');\n else if (v.startsWith('frame:')) apply({ op: 'update_shot', shot: current.id, set: { camera: { frame: v.slice(6), padding: 24 } } }, 'Frame camera');\n }}\n >\n <option value=\"\">keep framing</option>\n {current.camera && !frame && <option value=\"rect\">a rectangle</option>}\n {elements.map((e) => (\n <option key={e.id} value={`frame:${e.id}`}>\n frame {e.name ?? e.id}\n </option>\n ))}\n </select>\n <label className=\"text-muted-foreground\">Starts on</label>\n <select\n className={input}\n aria-label=\"Cue\"\n disabled={readOnly || index === 0}\n value={cueKey}\n onChange={(e) => {\n const cue = motionCueFromKey(e.target.value);\n apply(cue ? { op: 'update_shot', shot: current.id, set: { at: cue } } : { op: 'update_shot', shot: current.id, remove: ['at'] }, 'Cue shot');\n }}\n >\n <option value=\"\">after the shot before</option>\n {cueKey && !cues.some((c) => c.value === cueKey) && <option value={cueKey}>{cueKey}</option>}\n {cues.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </select>\n {!cues.length && index > 0 && <p className=\"col-span-2 text-[10px] text-muted-foreground\">Add a beat grid or narration in the scene settings to cue shots to them.</p>}\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","import_animation_editor","import_jsx_runtime","import_react","import_animation_editor","import_react","import_animation_editor","import_react","import_animation_editor","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React","import_react","import_animation_editor","import_jsx_runtime","import_react","import_animation_editor","import_jsx_runtime","seconds","worst","import_react","import_animation_editor","import_jsx_runtime","input","btn","import_react","import_animation_editor","import_jsx_runtime","input","btn","import_jsx_runtime","btn"]}
1
+ {"version":3,"sources":["../../src/animation-editor/index.ts","../../src/animation-editor/useAnimationEditor.ts","../../src/animation-editor/AnimationStage.tsx","../../src/animation-editor/ShotTimeline.tsx","../../src/animation-editor/AnimationEditor.tsx","../../src/animation-editor/CommandInspector.tsx","../../src/animation-editor/EasePicker.tsx","../../src/animation-editor/CommitInput.tsx","../../src/animation-editor/CommandList.tsx","../../src/animation-editor/PlayheadScrubber.tsx","../../src/animation-editor/SceneSettings.tsx","../../src/animation-editor/ShotInspector.tsx"],"sourcesContent":["export * from './useAnimationEditor';\nexport * from './AnimationStage';\nexport * from './ShotTimeline';\nexport * from './AnimationEditor';\nexport * from './PlayheadScrubber';\nexport * from './CommandList';\nexport * from './CommandInspector';\nexport * from './EasePicker';\nexport * from './ShotInspector';\nexport * from './SceneSettings';\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n AnimationEditorController,\n createAnimationEditorToolProvider,\n type AnimationEditorOptions,\n type AnimationEditorState,\n type AnimationEditorToolProviderOptions,\n} from '@pixerate/editor/animation-editor';\nimport type { ToolRegistry } from '@pixerate/editor/tools';\n\n/** An `AnimationEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useAnimationEditorController(options: AnimationEditorOptions = {}): AnimationEditorController {\n const ref = useRef<AnimationEditorController | null>(null);\n if (!ref.current) ref.current = new AnimationEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change, including each played frame). */\nexport function useAnimationEditorState(controller: AnimationEditorController): AnimationEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseAnimationEditorResult {\n controller: AnimationEditorController;\n state: AnimationEditorState;\n play: () => void;\n pause: () => void;\n toggle: () => void;\n seek: (time: number) => void;\n undo: () => void;\n redo: () => void;\n /** The frame at the playhead as SVG. */\n toSvg: () => string;\n}\n\n/**\n * Subscribes to an animation editor controller and exposes its state with bound actions.\n * Pass options instead of a controller to create one for the component's lifetime.\n */\nexport function useAnimationEditor(controllerOrOptions: AnimationEditorController | AnimationEditorOptions = {}): UseAnimationEditorResult {\n const own = useRef<AnimationEditorController | null>(null);\n let controller: AnimationEditorController;\n if (controllerOrOptions instanceof AnimationEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new AnimationEditorController(controllerOrOptions);\n controller = own.current;\n }\n useEffect(() => () => own.current?.destroy(), []);\n const state = useAnimationEditorState(controller);\n const actions = useMemo(\n () => ({\n play: () => controller.play(),\n pause: () => controller.pause(),\n toggle: () => controller.toggle(),\n seek: (time: number) => controller.seek(time),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/**\n * Registers the animation editor's agent tools (`get_animation`, `add_commands`,\n * `export_flair_effect`, …) in `registry` while mounted.\n */\nexport function useAnimationEditorTools(\n registry: ToolRegistry | null | undefined,\n controller: AnimationEditorController,\n options: AnimationEditorToolProviderOptions = {},\n): void {\n const { id, namespace, readOnly, rasterize } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createAnimationEditorToolProvider(controller, { id, namespace, readOnly, rasterize }));\n }, [registry, controller, id, namespace, readOnly, rasterize]);\n}\n","import React, { useMemo } from 'react';\nimport { highlightMotionSvg, motionNodeAtElement, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationStageProps {\n controller: AnimationEditorController;\n /** Control values to preview (`{ accent: \"#0ea5e9\" }`). */\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel: true for every node whose place changes, or a list of ids. */\n motionPaths?: boolean | readonly string[];\n /**\n * Called when the stage is clicked, with the id of the artwork node under the pointer (the\n * innermost one; null for the background, ghosts and paths). Makes the stage pickable.\n */\n onPick?: (id: string | null, event: React.MouseEvent<HTMLDivElement>) => void;\n /** Node ids to outline (e.g. the picked element and the selected command's targets). */\n highlight?: readonly string[];\n className?: string;\n}\n\n/**\n * The animation's frame at the playhead, drawn as inline SVG scaled to the stage's width. The\n * SVG keeps the artwork's node ids, so `onPick` can say which element was clicked.\n */\nexport function AnimationStage({ controller, values, onionSkin, motionPaths, onPick, highlight, className = '' }: AnimationStageProps) {\n const state = useAnimationEditorState(controller);\n const { scene, time } = state;\n const key = highlight?.join('\\u0000') ?? '';\n const svg = useMemo(\n () =>\n highlightMotionSvg(\n controller.toSvg(time, { pretty: false, idPrefix: 'ae-', values, onionSkin, motionPaths }).replace(/<svg ([^>]*?)width=\"[^\"]*\" height=\"[^\"]*\"/, '<svg $1width=\"100%\" height=\"100%\"'),\n highlight ?? [],\n ),\n [controller, scene, time, values, onionSkin, motionPaths, key],\n );\n return (\n <div\n className={`relative overflow-hidden ${onPick ? 'cursor-crosshair' : ''} ${className}`}\n style={{ aspectRatio: `${scene.artwork.width} / ${scene.artwork.height}` }}\n data-animation-stage=\"\"\n role=\"img\"\n aria-label={`${scene.name} at ${(time / 1000).toFixed(2)} s`}\n onClick={onPick ? (e) => onPick(motionNodeAtElement(scene, e.target as Element, e.currentTarget), e) : undefined}\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n );\n}\n","import React from 'react';\nimport type { AnimationEditorController, MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotTimelineProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(1)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play / pause, the playhead and one block per shot (as wide as it is long): click a shot to\n * select it and jump to its start, click the ruler to seek. Shots with errors or warnings are marked.\n */\nexport function ShotTimeline({ controller, className = '' }: ShotTimelineProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues } = state;\n const span = Math.max(1, duration);\n const onRuler = (event: React.PointerEvent<HTMLDivElement>) => {\n const box = event.currentTarget.getBoundingClientRect();\n controller.seek(((event.clientX - box.left) / Math.max(1, box.width)) * span);\n };\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <span className=\"tabular-nums text-muted-foreground\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div className=\"relative h-3 cursor-pointer rounded bg-muted\" onPointerDown={onRuler} role=\"slider\" aria-label=\"Playhead\" aria-valuemin={0} aria-valuemax={duration} aria-valuenow={Math.round(time)} tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') controller.seek(time + 100);\n if (e.key === 'ArrowLeft') controller.seek(time - 100);\n }}>\n <div className=\"absolute inset-y-0 w-0.5 bg-rose-500\" style={{ left: `${(time / span) * 100}%` }} />\n </div>\n <div className=\"flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot) => {\n const mark = worst(issues.filter((i) => i.shot === shot.id));\n const selected = selection?.shot === shot.id;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.end - shot.start)}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { indexMotionNodes, motionIssueLine, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { AnimationStage } from './AnimationStage';\nimport { CommandInspector } from './CommandInspector';\nimport { CommandList } from './CommandList';\nimport { PlayheadScrubber } from './PlayheadScrubber';\nimport { SceneSettings } from './SceneSettings';\nimport { ShotInspector } from './ShotInspector';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationEditorProps {\n controller: AnimationEditorController;\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead (see `<AnimationStage onionSkin>`). Default: an Onion skin toggle. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel (see `<AnimationStage motionPaths>`). Default: a Motion paths toggle. */\n motionPaths?: boolean | readonly string[];\n /** List the scene's issues under the timeline (default true). */\n showIssues?: boolean;\n /**\n * Show the hand-editing panels: the command list and inspector, the shot inspector, scene\n * settings, undo / redo and picking on the stage (default true). False shows the stage,\n * scrubber and issues only.\n */\n editable?: boolean;\n className?: string;\n}\n\nconst ONION: MotionOnionSkin = { before: 3, after: 1 };\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * A whole animation editor for an `AnimationEditorController`: the stage (click an element to\n * pick it, shift-click to add it to or remove it from the selected command's targets), the\n * playhead scrubber, and panels to edit commands, shots and scene settings by hand. Every edit\n * is one undo step.\n */\nexport function AnimationEditor({ controller, values, onionSkin, motionPaths, showIssues = true, editable = true, className = '' }: AnimationEditorProps) {\n const state = useAnimationEditorState(controller);\n const { issues, scene, selection, readOnly } = state;\n const [picked, setPicked] = useState<string | null>(null);\n const [onion, setOnion] = useState(false);\n const [paths, setPaths] = useState(false);\n const command = selection?.command !== undefined ? scene.shots.find((s) => s.id === selection.shot)?.run[selection.command] : undefined;\n const targets = command && 'targets' in command ? command.targets : [];\n const nodes = useMemo(() => indexMotionNodes(scene.artwork.nodes), [scene.artwork]);\n const pickedValid = picked && nodes.has(picked) ? picked : null;\n const onPick = (id: string | null, event: { shiftKey: boolean }) => {\n if (event.shiftKey && id && command && 'targets' in command && selection?.command !== undefined && !readOnly) {\n const next = targets.includes(id) ? targets.filter((t) => t !== id) : [...targets, id];\n if (next.length) controller.apply({ op: 'update_command', shot: selection.shot, command: selection.command, set: { targets: next } }, next.length > targets.length ? 'Add target' : 'Remove target');\n return;\n }\n setPicked(id);\n };\n const stage = (\n <AnimationStage\n controller={controller}\n values={values}\n onionSkin={onionSkin ?? (onion ? ONION : undefined)}\n motionPaths={motionPaths ?? paths}\n onPick={editable ? onPick : undefined}\n highlight={editable ? [...(pickedValid ? [pickedValid] : []), ...targets] : undefined}\n className=\"rounded-md border border-border bg-muted/40\"\n />\n );\n const issueList = showIssues && issues.length > 0 && (\n <ul className=\"space-y-0.5 text-xs\" aria-label=\"Animation issues\">\n {issues.map((issue, i) => (\n <li key={i} className={issue.severity === 'error' ? 'text-red-500' : issue.severity === 'warning' ? 'text-amber-500' : 'text-muted-foreground'}>\n {motionIssueLine(issue)}\n </li>\n ))}\n </ul>\n );\n if (!editable)\n return (\n <div className={`flex flex-col gap-2 ${className}`} data-animation-editor=\"\">\n {stage}\n <PlayheadScrubber controller={controller} />\n {issueList}\n </div>\n );\n\n return (\n <div\n className={`grid gap-3 lg:grid-cols-[minmax(0,1fr)_20rem] ${className}`}\n data-animation-editor=\"\"\n onKeyDown={(e) => {\n const el = e.target as HTMLElement;\n if (!(e.metaKey || e.ctrlKey) || e.key.toLowerCase() !== 'z' || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName)) return;\n e.preventDefault();\n if (e.shiftKey) controller.redo();\n else controller.undo();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-2\">\n {stage}\n <PlayheadScrubber controller={controller} />\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n <button type=\"button\" className={btn} onClick={() => controller.undo()} disabled={!state.canUndo} title={state.canUndo ? `Undo ${state.undoLabel}` : 'Nothing to undo'} data-undo=\"\">\n Undo\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.redo()} disabled={!state.canRedo} title={state.canRedo ? `Redo ${state.redoLabel}` : 'Nothing to redo'} data-redo=\"\">\n Redo\n </button>\n {onionSkin === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={onion} onChange={(e) => setOnion(e.target.checked)} /> Onion skin\n </label>\n )}\n {motionPaths === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={paths} onChange={(e) => setPaths(e.target.checked)} /> Motion paths\n </label>\n )}\n <span className=\"ml-auto\" data-picked-element={pickedValid ?? undefined}>\n {pickedValid ? (\n <>\n Picked <code className=\"text-rose-500\">{pickedValid}</code>{' '}\n <button type=\"button\" className=\"underline\" onClick={() => setPicked(null)}>\n clear\n </button>\n </>\n ) : (\n 'Click the stage to pick an element; shift-click to toggle it as a target.'\n )}\n </span>\n </div>\n {issueList}\n </div>\n <div className=\"flex min-w-0 flex-col gap-3\">\n <CommandList controller={controller} targets={pickedValid ? [pickedValid] : undefined} />\n <CommandInspector controller={controller} picked={pickedValid} className=\"border-t border-border pt-2\" />\n <details open className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Shot</summary>\n <ShotInspector controller={controller} className=\"mt-1\" />\n </details>\n <details className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Scene settings</summary>\n <SceneSettings controller={controller} className=\"mt-1\" />\n </details>\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport {\n describeMotionElements,\n motionCommandFields,\n motionFieldEdit,\n motionFlairPrimitive,\n type AnimationEditorController,\n type MotionFieldSpec,\n} from '@pixerate/editor/animation-editor';\nimport { EasePicker } from './EasePicker';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandInspectorProps {\n controller: AnimationEditorController;\n /** An element picked on the stage, offered as a target to add. */\n picked?: string | null;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\n\n\n/**\n * A form for the selected command, generated from `MOTION_COMMAND_SCHEMA` (the schema the\n * agent tools take): enums as selects, numbers with their units and limits, node pickers for\n * targets and for `into` / `path`, and an ease picker. Shows the Flair primitive it plays.\n */\nexport function CommandInspector({ controller, picked, className = '' }: CommandInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const shot = selection ? scene.shots.find((s) => s.id === selection.shot) : undefined;\n const index = selection?.command;\n const command = shot && index !== undefined ? shot.run[index] : undefined;\n if (!shot || index === undefined || !command) {\n return (\n <div className={`text-xs text-muted-foreground ${className}`} data-command-inspector=\"\">\n Select a command to edit it.\n </div>\n );\n }\n const values = command as unknown as Record<string, unknown>;\n const fields = motionCommandFields(command.type);\n const primitive = motionFlairPrimitive(command);\n const commit = (field: MotionFieldSpec, raw: Parameters<typeof motionFieldEdit>[3]) => {\n const edit = motionFieldEdit(shot.id, index, field, raw);\n if ('error' in edit) return setLocal(edit.error);\n setLocal(null);\n controller.apply(edit, `Set ${field.label.toLowerCase()}`);\n };\n const name = (id: string) => elements.find((e) => e.id === id)?.name ?? id;\n const targets = (values.targets as string[] | undefined) ?? [];\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n const control = (field: MotionFieldSpec) => {\n const v = values[field.name];\n const common = { disabled: readOnly, 'aria-label': field.label, title: field.description };\n switch (field.kind) {\n case 'targets':\n return (\n <div className=\"flex flex-wrap items-center gap-1\" data-targets=\"\">\n {targets.map((id) => (\n <span key={id} className=\"flex items-center gap-0.5 rounded bg-muted px-1 text-[11px]\" data-target={id}>\n {name(id)}\n {!readOnly && targets.length > 1 && (\n <button type=\"button\" aria-label={`Remove ${id}`} onClick={() => commit(field, targets.filter((t) => t !== id))}>\n ×\n </button>\n )}\n </span>\n ))}\n {!readOnly && picked && !targets.includes(picked) && (\n <button type=\"button\" className=\"rounded border border-rose-500 px-1 text-[11px] text-rose-500\" onClick={() => commit(field, [...targets, picked])} data-add-picked=\"\">\n + {name(picked)}\n </button>\n )}\n {!readOnly && (\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\" aria-label=\"Add target\" value=\"\" onChange={(e) => e.target.value && commit(field, [...targets, e.target.value])}>\n <option value=\"\">+ target…</option>\n {elements.filter((e) => !targets.includes(e.id)).map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n </option>\n ))}\n </select>\n )}\n </div>\n );\n case 'node':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">—</option>}\n {elements.filter((e) => field.name !== 'path' || e.type === 'path').map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n {e.hidden ? ' · hidden' : ''}\n </option>\n ))}\n </select>\n );\n case 'enum':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">default</option>}\n {field.options!.map((o) => (\n <option key={o} value={o}>\n {o}\n </option>\n ))}\n </select>\n );\n case 'boolean':\n return <input type=\"checkbox\" {...common} checked={v === true} onChange={(e) => commit(field, e.target.checked)} />;\n case 'ease':\n return <EasePicker value={v as never} disabled={readOnly} onChange={(ease) => commit(field, ease === undefined ? '' : (ease as string))} />;\n case 'color':\n return (\n <div className=\"flex items-center gap-1\">\n <input type=\"color\" disabled={readOnly} aria-label={`${field.label} swatch`} value={typeof v === 'string' && /^#[0-9a-f]{6}$/i.test(v) ? v : '#000000'} onChange={(e) => commit(field, e.target.value)} />\n <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} placeholder=\"unchanged\" onCommit={(raw) => commit(field, raw)} />\n </div>\n );\n case 'point': {\n const p = (v as { x: number; y: number } | undefined) ?? undefined;\n return (\n <div className=\"flex items-center gap-1\">\n {(['x', 'y'] as const).map((axis) => (\n <CommitInput\n key={axis}\n className={input}\n type=\"number\"\n disabled={readOnly}\n aria-label={`${field.label} ${axis}`}\n placeholder={axis}\n value={p ? String(p[axis]) : ''}\n onCommit={(raw) => commit(field, axis === 'x' ? { x: raw, y: p ? String(p.y) : raw ? '0' : '' } : { x: p ? String(p.x) : raw ? '0' : '', y: raw })}\n />\n ))}\n </div>\n );\n }\n case 'scale':\n case 'number':\n case 'integer':\n return (\n <div className=\"flex items-center gap-1\">\n <CommitInput\n className={input}\n type=\"number\"\n {...common}\n min={field.min}\n max={field.max}\n step={field.kind === 'integer' ? 1 : field.unit === 'ms' ? 50 : field.unit === '0–1' ? 0.05 : 'any'}\n placeholder=\"default\"\n value={typeof v === 'number' ? String(v) : ''}\n onCommit={(raw) => commit(field, raw)}\n />\n {field.unit && <span className=\"shrink-0 text-[10px] text-muted-foreground\">{field.unit}</span>}\n </div>\n );\n default:\n return <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} onCommit={(raw) => commit(field, raw)} />;\n }\n };\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-command-inspector=\"\" data-command-type={command.type}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">\n {index + 1}. {command.type}\n </span>\n {primitive ? (\n <code className=\"rounded bg-muted px-1 text-[10px]\" data-flair-primitive={primitive} title=\"The Flair motion primitive this command plays\">\n {primitive}\n </code>\n ) : (\n <span className=\"text-[10px] text-muted-foreground\">editor-only (no Flair primitive)</span>\n )}\n </div>\n {(['main', 'timing'] as const).map((group) => (\n <fieldset key={group} className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <legend className=\"mb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">{group === 'main' ? 'Command' : 'Timing'}</legend>\n {fields\n .filter((f) => f.group === group)\n .map((field) => (\n <React.Fragment key={field.name}>\n <label className=\"truncate text-muted-foreground\" title={field.description}>\n {field.label}\n {field.required ? ' *' : ''}\n </label>\n <div data-field={field.name}>{control(field)}</div>\n </React.Fragment>\n ))}\n </fieldset>\n ))}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo } from 'react';\nimport { MOTION_EASE_CHOICES, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, type MotionCommandBase } from '@pixerate/editor/animation-editor';\n\n/** An easing (a preset name or a curve), as commands take it. */\ntype AnimationEasing = NonNullable<MotionCommandBase['ease']>;\n\nexport interface EasePickerProps {\n /** The easing (undefined: the command type's default). */\n value: AnimationEasing | undefined;\n /** Called with the picked preset, or undefined for the default. */\n onChange: (ease: AnimationEasing | undefined) => void;\n disabled?: boolean;\n className?: string;\n}\n\nconst W = 72;\nconst H = 44;\n\n/**\n * Picks an easing preset (springs included) and previews its curve, drawn by sampling\n * `evaluateEasing`; a spring is drawn over the time it takes to settle, overshoot included.\n */\nexport function EasePicker({ value, onChange, disabled, className = '' }: EasePickerProps) {\n const key = motionEaseKey(value);\n const curve = useMemo(() => motionEasingCurve(value ?? 'ease-out'), [value]);\n const guides = motionEasingGuides(curve, H);\n const spring = typeof value === 'string' ? value.startsWith('spring') : value?.type === 'spring';\n return (\n <div className={`flex items-center gap-2 ${className}`} data-ease-picker=\"\">\n <select\n className=\"min-w-0 flex-1 rounded border border-border bg-transparent px-1 py-0.5 text-xs\"\n aria-label=\"Ease\"\n value={key}\n disabled={disabled}\n onChange={(e) => {\n if (e.target.value === 'custom') return;\n onChange(e.target.value ? (e.target.value as AnimationEasing) : undefined);\n }}\n >\n {MOTION_EASE_CHOICES.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n {key === 'custom' && <option value=\"custom\">Custom</option>}\n </select>\n <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} className=\"shrink-0 rounded border border-border\" data-ease-curve={key || 'default'} aria-hidden=\"true\">\n <line x1={0} x2={W} y1={guides.zero} y2={guides.zero} stroke=\"currentColor\" strokeOpacity={0.2} />\n <line x1={0} x2={W} y1={guides.one} y2={guides.one} stroke=\"currentColor\" strokeOpacity={0.2} strokeDasharray=\"2 2\" />\n <path d={motionEasingPath(curve, W, H)} fill=\"none\" stroke=\"#f43f5e\" strokeWidth={1.5} />\n </svg>\n {spring && <span className=\"text-[10px] tabular-nums text-muted-foreground\">{Math.round(curve.durationMs)} ms</span>}\n </div>\n );\n}\n","import React from 'react';\n\n/** An input that commits on blur or Enter, and resets when its value changes from outside. */\nexport function CommitInput({ value, onCommit, ...rest }: { value: string; onCommit: (raw: string) => void } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue'>) {\n return (\n <input\n key={value}\n {...rest}\n defaultValue={value}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n if (e.currentTarget.value !== value) onCommit(e.currentTarget.value);\n }}\n />\n );\n}\n","import React, { useState } from 'react';\nimport {\n MOTION_COMMAND_TYPES,\n defaultMotionCommand,\n duplicateMotionCommandEdit,\n motionCommandRows,\n type AnimationEditorController,\n type MotionCommandType,\n} from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandListProps {\n controller: AnimationEditorController;\n /** The shot to list (default: the selected shot, else the first). */\n shot?: string;\n /** Targets for a new command (e.g. the element picked on the stage); default: the selected command's. */\n targets?: readonly string[];\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n/**\n * A shot's commands in order: select one to inspect it, change `with` and `delay` inline, move,\n * duplicate or delete it, and add new ones. Each change is one `controller.apply` edit (one undo\n * step); a refused edit shows its reason.\n */\nexport function CommandList({ controller, shot, targets, className = '' }: CommandListProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const shotId = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const current = scene.shots.find((s) => s.id === shotId);\n const [type, setType] = useState<MotionCommandType>('enter');\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n if (!current) return <div className={`text-xs text-muted-foreground ${className}`} data-command-list=\"\">Add a shot to start.</div>;\n const rows = motionCommandRows(scene, current.id);\n const selected = selection?.shot === current.id ? selection.command : undefined;\n const run = (edit: Parameters<AnimationEditorController['apply']>[0], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const add = () => {\n const from = targets?.length ? targets : selected !== undefined ? ((current.run[selected] as { targets?: string[] }).targets ?? []) : [];\n const command = defaultMotionCommand(type, from, scene);\n if ('error' in command) return setLocal(command.error);\n const at = selected !== undefined ? selected + 1 : current.run.length;\n const result = run({ op: 'add_commands', shot: current.id, commands: [command], at }, `Add ${type}`);\n if (result.ok) controller.select({ shot: current.id, command: at });\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1 text-xs ${className}`} data-command-list=\"\" data-for-shot={current.id}>\n <div className=\"font-medium\">\n Commands in <span className=\"text-rose-500\">{current.label ?? current.id}</span>\n </div>\n <ol className=\"flex flex-col gap-1\" aria-label=\"Commands\">\n {rows.map((row) => {\n const c = row.command as { with?: string; delay?: number };\n const isSelected = row.index === selected;\n return (\n <li\n key={`${row.index}:${row.summary}`}\n className={`flex flex-wrap items-center gap-1 rounded border px-1.5 py-1 ${isSelected ? 'border-rose-500 bg-rose-500/10' : 'border-border'}`}\n data-command={row.index}\n data-selected={isSelected || undefined}\n onClick={() => controller.select({ shot: current.id, command: row.index })}\n >\n <span className=\"min-w-0 flex-1 truncate\" title={row.summary}>\n {row.index + 1}. {row.summary}\n </span>\n {row.flairPrimitive && (\n <code className=\"rounded bg-muted px-1 text-[10px] text-muted-foreground\" data-flair-primitive={row.flairPrimitive}>\n {row.flairPrimitive}\n </code>\n )}\n <span className=\"tabular-nums text-[10px] text-muted-foreground\">{((row.end - row.start) / 1000).toFixed(2)} s</span>\n <div className=\"flex w-full items-center gap-1\" onClick={(e) => e.stopPropagation()}>\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\"\n aria-label=\"Starts\"\n value={c.with ?? 'after'}\n disabled={readOnly || row.index === 0}\n onChange={(e) =>\n run(\n e.target.value === 'after' ? { op: 'update_command', shot: current.id, command: row.index, remove: ['with'] } : { op: 'update_command', shot: current.id, command: row.index, set: { with: e.target.value } },\n 'Change start',\n )\n }\n >\n <option value=\"after\">after previous</option>\n <option value=\"previous\">with previous</option>\n </select>\n <label className=\"flex items-center gap-0.5 text-muted-foreground\">\n +\n <input\n key={String(c.delay ?? '')}\n className=\"w-14 rounded border border-border bg-transparent px-1 py-0.5 text-[11px] tabular-nums\"\n type=\"number\"\n min={0}\n step={50}\n aria-label=\"Delay\"\n placeholder=\"0\"\n defaultValue={c.delay ?? ''}\n disabled={readOnly}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n const raw = e.currentTarget.value.trim();\n if (raw === String(c.delay ?? '')) return;\n const n = Number(raw);\n if (raw && !(Number.isFinite(n) && n >= 0)) return setLocal('Delay must be a number of ms, 0 or more.');\n run(raw && n > 0 ? { op: 'update_command', shot: current.id, command: row.index, set: { delay: n } } : { op: 'update_command', shot: current.id, command: row.index, remove: ['delay'] }, 'Change delay');\n }}\n />\n ms\n </label>\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} aria-label=\"Move up\" disabled={readOnly || row.index === 0} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index - 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index - 1 })}>\n ↑\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move down\" disabled={readOnly || row.index === rows.length - 1} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index + 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ↓\n </button>\n <button type=\"button\" className={btn} aria-label=\"Duplicate\" disabled={readOnly} onClick={() => run(duplicateMotionCommandEdit(scene, current.id, row.index), 'Duplicate command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ⧉\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete\" disabled={readOnly} onClick={() => run({ op: 'delete_commands', shot: current.id, commands: [row.index] }, 'Delete command')}>\n ✕\n </button>\n </span>\n </div>\n </li>\n );\n })}\n </ol>\n {!readOnly && (\n <div className=\"flex items-center gap-1\">\n <select className=\"flex-1 rounded border border-border bg-transparent px-1 py-0.5\" aria-label=\"New command type\" value={type} onChange={(e) => setType(e.target.value as MotionCommandType)}>\n {MOTION_COMMAND_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <button type=\"button\" className={btn} onClick={add} data-add-command=\"\">\n Add command\n </button>\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { motionBeatTime, motionCueTime, motionRulerTicks, type AnimationEditorController, type MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface PlayheadScrubberProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(2)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play, pause and loop, a time ruler (with the beat grid and narration words when the scene has\n * them) to scrub by dragging, and one band per shot (as wide as it is long): click a band to\n * select the shot and jump to its start. Loop is a scene setting, so changing it is one undo step.\n */\nexport function PlayheadScrubber({ controller, className = '' }: PlayheadScrubberProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues, scene, readOnly } = state;\n const span = Math.max(1, duration);\n const track = useRef<HTMLDivElement>(null);\n const [width, setWidth] = useState(600);\n useEffect(() => {\n const el = track.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => setWidth(el.clientWidth || 600));\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n const ticks = motionRulerTicks(duration, width);\n const pct = (ms: number) => `${(Math.min(span, Math.max(0, ms)) / span) * 100}%`;\n const seekAt = (clientX: number) => {\n const box = track.current!.getBoundingClientRect();\n controller.seek(Math.min(1, Math.max(0, (clientX - box.left) / Math.max(1, box.width))) * span);\n };\n const beats: number[] = [];\n if (scene.beat && scene.beat.bpm > 0) for (let b = 0, t = motionBeatTime(scene.beat, 0); t <= span && beats.length < 400; t = motionBeatTime(scene.beat, ++b)) if (t >= 0) beats.push(t);\n\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-playhead-scrubber=\"\" data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => { controller.pause(); controller.seek(0); }} aria-label=\"Back to start\">\n ⏮\n </button>\n <label className=\"flex items-center gap-1 text-muted-foreground\">\n Loop\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5\"\n value={scene.loop ?? 'none'}\n disabled={readOnly}\n aria-label=\"Loop\"\n onChange={(e) => controller.apply({ op: 'set_settings', loop: e.target.value as 'none' | 'loop' | 'ping-pong' }, 'Change loop')}\n >\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n </label>\n <span className=\"ml-auto tabular-nums text-muted-foreground\" data-time=\"\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div\n ref={track}\n className=\"relative cursor-ew-resize select-none touch-none\"\n role=\"slider\"\n aria-label=\"Playhead\"\n aria-valuemin={0}\n aria-valuemax={duration}\n aria-valuenow={Math.round(time)}\n tabIndex={0}\n data-scrub-track=\"\"\n onPointerDown={(e) => {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n seekAt(e.clientX);\n }}\n onPointerMove={(e) => {\n if (e.buttons & 1) seekAt(e.clientX);\n }}\n onKeyDown={(e) => {\n const step = e.shiftKey ? 1000 : 100;\n if (e.key === 'ArrowRight') controller.seek(time + step);\n else if (e.key === 'ArrowLeft') controller.seek(time - step);\n else if (e.key === 'Home') controller.seek(0);\n else if (e.key === 'End') controller.seek(duration);\n else if (e.key === ' ') controller.toggle();\n else return;\n e.preventDefault();\n }}\n >\n <div className=\"relative h-5 border-b border-border text-[10px] text-muted-foreground\" data-ruler=\"\">\n {beats.map((t, i) => (\n <div key={`b${i}`} className=\"absolute bottom-0 h-1.5 w-px bg-sky-500/60\" style={{ left: pct(t) }} data-beat={i} />\n ))}\n {scene.narration?.words.map((w, i) => (\n <div key={`w${i}`} className=\"absolute top-0 h-1.5 w-px bg-emerald-500/70\" style={{ left: pct(w.start) }} title={`“${w.text}” at ${seconds(w.start)}`} data-word={i} />\n ))}\n {ticks.map((t) => (\n <div key={t.time} className={`absolute bottom-0 w-px ${t.major ? 'h-2.5 bg-muted-foreground/70' : 'h-1 bg-muted-foreground/40'}`} style={{ left: pct(t.time) }}>\n {t.label && <span className=\"absolute -top-0.5 left-1 whitespace-nowrap tabular-nums\">{t.label}</span>}\n </div>\n ))}\n </div>\n <div className=\"mt-1 flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot, i) => {\n const mark = worst(issues.filter((x) => x.shot === shot.id));\n const selected = selection?.shot === shot.id;\n const cue = scene.shots[i]?.at;\n const cueTime = cue ? motionCueTime(scene, cue) : undefined;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`relative min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border bg-muted/40'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.start)}–${seconds(shot.end)}${cueTime !== undefined ? ` · cued at ${seconds(cueTime)}` : ''}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onPointerDown={(e) => e.stopPropagation()}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n <div className=\"pointer-events-none absolute inset-y-0 w-0.5 -translate-x-1/2 bg-rose-500\" style={{ left: pct(time) }} data-playhead=\"\" />\n </div>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport { fitMotionSceneEdits, formatMotionDrivers, formatMotionNarration, parseMotionDrivers, parseMotionNarration, type AnimationEditorController, type MotionEdit, type MotionTrigger } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface SceneSettingsProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\nconst unit = (u: string) => <span className=\"shrink-0 text-[10px] text-muted-foreground\">{u}</span>;\n\n/**\n * Scene settings: loop, frame rate, stepped time, the wanted length with a Fit button (sets the\n * shots' speeds with `fitMotionScene`, as `fit_animation` does), a beat grid and narration words\n * to cue shots to. Every change is one undo step; refusals show their reason.\n */\nexport function SceneSettings({ controller, className = '' }: SceneSettingsProps) {\n const state = useAnimationEditorState(controller);\n const { scene, readOnly, error, duration } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const [fitTo, setFitTo] = useState<string>('');\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const settings = (set: Omit<Extract<MotionEdit, { op: 'set_settings' }>, 'op'>, label: string) => apply({ op: 'set_settings', ...set }, label);\n const num = (raw: string, what: string, ok: (n: number) => boolean, then: (n: number | null) => void) => {\n if (raw.trim() === '') return then(null);\n const n = Number(raw);\n if (!Number.isFinite(n) || !ok(n)) return setLocal(what);\n then(n);\n };\n const target = scene.target;\n const fitSeconds = fitTo || String(target ? (target[0] + target[1]) / 2 : Math.round(duration / 100) / 10);\n const fit = () => {\n const s = Number(fitSeconds);\n if (!(Number.isFinite(s) && s > 0)) return setLocal('Give the length to fit in seconds, above 0.');\n try {\n const edits = fitMotionSceneEdits(scene, s * 1000);\n if (edits.length) apply(edits, `Fit to ${s} s`);\n else setLocal(null);\n } catch (e) {\n setLocal((e as Error).message);\n }\n };\n const beat = scene.beat;\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-scene-settings=\"\">\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Loop</label>\n <select className={input} aria-label=\"Scene loop\" disabled={readOnly} value={scene.loop ?? 'none'} onChange={(e) => settings({ loop: e.target.value as 'none' }, 'Change loop')}>\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n <label className=\"text-muted-foreground\">Motion blur</label>\n <select className={input} aria-label=\"Motion blur\" disabled={readOnly} value={scene.motionBlur ? String(scene.motionBlur.shutter ?? 180) : ''} onChange={(e) => settings({ motionBlur: e.target.value ? { ...(scene.motionBlur ?? {}), shutter: Number(e.target.value) } : null }, 'Change motion blur')}>\n <option value=\"\">Off</option>\n <option value=\"90\">Light (90°)</option>\n <option value=\"180\">Normal (180°)</option>\n <option value=\"360\">Heavy (360°)</option>\n </select>\n <label className=\"text-muted-foreground\">Plays on</label>\n <select className={input} aria-label=\"Scene trigger\" title=\"How a viewer plays it when exported to Flair\" disabled={readOnly} value={scene.trigger ?? ''} onChange={(e) => settings({ trigger: (e.target.value || null) as MotionTrigger | null }, 'Change trigger')}>\n <option value=\"\">Its own (autoplay)</option>\n <option value=\"click\">Click (a shot per click)</option>\n <option value=\"hover\">Hover</option>\n <option value=\"press\">Press</option>\n <option value=\"scroll\">Scroll</option>\n </select>\n <label className=\"text-muted-foreground\">Frame rate</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Frame rate\" placeholder=\"30\" disabled={readOnly} value={scene.fps !== undefined ? String(scene.fps) : ''}\n onCommit={(raw) => num(raw, 'Frame rate must be 1 to 120 fps.', (n) => n >= 1 && n <= 120, (n) => n !== null && settings({ fps: n }, 'Change frame rate'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\" title=\"Hold changes on a grid of this many frames a second (12 = on twos); empty is smooth\">\n Steps\n </label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Steps\" placeholder=\"smooth\" disabled={readOnly} value={scene.steps !== undefined ? String(scene.steps) : ''}\n onCommit={(raw) => num(raw, 'Steps must be above 0 and at most 120 fps, or empty for smooth.', (n) => n > 0 && n <= 120, (n) => settings({ steps: n }, 'Change steps'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\">Target length</label>\n <div className=\"flex items-center gap-1\">\n {[0, 1].map((i) => (\n <CommitInput key={i} className={input} type=\"number\" min={0} step={0.5} aria-label={i ? 'Target max' : 'Target min'} placeholder={i ? 'max' : 'min'} disabled={readOnly} value={target ? String(target[i]) : ''}\n onCommit={(raw) =>\n num(raw, 'Target lengths are seconds, 0 or more.', (n) => n >= 0, (n) => {\n if (n === null) return settings({ target: null }, 'Clear target length');\n const next: [number, number] = target ? [...target] : [n, n];\n next[i] = n;\n if (next[0] > next[1]) return setLocal('The shortest target length must not be longer than the longest.');\n settings({ target: next }, 'Change target length');\n })\n } />\n ))}\n {unit('s')}\n </div>\n <label className=\"text-muted-foreground\">Fit to</label>\n <div className=\"flex items-center gap-1\">\n <input className={input} type=\"number\" min={0.1} step={0.5} aria-label=\"Fit to\" value={fitSeconds} onChange={(e) => setFitTo(e.target.value)} />\n {unit('s')}\n <button type=\"button\" className={btn} disabled={readOnly || !scene.shots.length} onClick={fit} data-fit=\"\" title=\"Change the shots' speeds so the scene lasts this long\">\n Fit\n </button>\n </div>\n <label className=\"text-muted-foreground\">Beat grid</label>\n <div className=\"flex items-center gap-1\" data-beat-grid=\"\">\n <CommitInput className={input} type=\"number\" min={1} aria-label=\"BPM\" placeholder=\"bpm\" disabled={readOnly} value={beat ? String(beat.bpm) : ''}\n onCommit={(raw) => num(raw, 'BPM must be above 0.', (n) => n > 0, (n) => settings({ beat: n === null ? null : { ...(beat ?? {}), bpm: n } }, n === null ? 'Clear beat grid' : 'Change tempo'))} />\n <CommitInput className={input} type=\"number\" aria-label=\"Beat offset\" placeholder=\"offset ms\" disabled={readOnly || !beat} value={beat?.offset !== undefined ? String(beat.offset) : ''}\n onCommit={(raw) => beat && num(raw, 'The offset is a number of ms.', () => true, (n) => settings({ beat: { ...beat, offset: n ?? 0 } }, 'Change beat offset'))} />\n <CommitInput className={input} type=\"number\" min={1} step={1} aria-label=\"Meter\" placeholder=\"4/bar\" disabled={readOnly || !beat} value={beat?.meter !== undefined ? String(beat.meter) : ''}\n onCommit={(raw) => beat && num(raw, 'The meter is a whole number of beats a bar.', (n) => Number.isInteger(n) && n >= 1, (n) => settings({ beat: { ...beat, meter: n ?? 4 } }, 'Change meter'))} />\n </div>\n </div>\n <label className=\"flex flex-col gap-0.5\">\n <span className=\"text-muted-foreground\">Narration (a word a line: start ms, then the word)</span>\n <textarea\n key={formatMotionNarration(scene.narration)}\n className={`${input} h-20 font-mono`}\n aria-label=\"Narration\"\n placeholder={'0 Meet\\n320 the\\n480 badge'}\n disabled={readOnly}\n defaultValue={formatMotionNarration(scene.narration)}\n onBlur={(e) => {\n if (e.currentTarget.value === formatMotionNarration(scene.narration)) return;\n const parsed = parseMotionNarration(e.currentTarget.value);\n if ('error' in parsed) return setLocal(parsed.error);\n settings({ narration: parsed.narration }, parsed.narration ? 'Change narration' : 'Clear narration');\n }}\n />\n </label>\n <label className=\"flex flex-col gap-0.5\">\n <span className=\"text-muted-foreground\">Drivers (one a line: target.property &lt;- source.property * factor)</span>\n <textarea\n key={formatMotionDrivers(scene.drivers)}\n className={`${input} h-14 font-mono`}\n aria-label=\"Drivers\"\n placeholder={'back.x <- front.x * 0.5\\nwheel.rotation <- wheel.x * 2.86'}\n disabled={readOnly}\n defaultValue={formatMotionDrivers(scene.drivers)}\n onBlur={(e) => {\n if (e.currentTarget.value === formatMotionDrivers(scene.drivers)) return;\n const parsed = parseMotionDrivers(e.currentTarget.value);\n if ('error' in parsed) return setLocal(parsed.error);\n apply({ op: 'set_drivers', drivers: parsed.drivers }, parsed.drivers.length ? 'Set drivers' : 'Clear drivers');\n }}\n />\n </label>\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { describeMotionElements, freshShotId, motionCueChoices, motionCueFromKey, motionCueKey, type AnimationEditorController, type MotionEdit } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotInspectorProps {\n controller: AnimationEditorController;\n /** The shot to edit (default: the selected shot, else the first). */\n shot?: string;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n\n/**\n * The selected shot: its label, hold, speed, the node the camera frames, and the cue it starts\n * on (a beat of the scene's grid or a narration word). Also adds, moves and deletes shots.\n * Every change is one undo step.\n */\nexport function ShotInspector({ controller, shot, className = '' }: ShotInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const cues = useMemo(() => motionCueChoices(scene), [scene]);\n const id = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const index = scene.shots.findIndex((s) => s.id === id);\n const current = scene.shots[index];\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const addShot = () => {\n const newId = freshShotId(scene, 'shot');\n const at = index >= 0 ? index + 1 : scene.shots.length;\n if (apply({ op: 'insert_shots', shots: [{ id: newId, label: 'New shot', run: [] }], at }, 'Add shot').ok) {\n controller.select({ shot: newId });\n controller.seekShot(newId);\n }\n };\n const number = (key: 'hold' | 'speed', raw: string, label: string) => {\n const n = Number(raw);\n if (raw.trim() === '') return apply({ op: 'update_shot', shot: current.id, remove: [key] }, label);\n if (!Number.isFinite(n) || n < 0 || (key === 'speed' && n <= 0)) return setLocal(key === 'speed' ? 'Speed must be a number above 0 (1 = as written).' : 'Hold must be a number of ms, 0 or more.');\n apply({ op: 'update_shot', shot: current.id, set: { [key]: n } }, label);\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n const cueKey = current ? motionCueKey(current.at) : '';\n const frame = current?.camera && 'frame' in current.camera ? current.camera.frame : '';\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-shot-inspector=\"\">\n <div className=\"flex items-center gap-1\">\n <span className=\"font-medium\">Shot</span>\n {current && <code className=\"text-[10px] text-muted-foreground\">{current.id}</code>}\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} disabled={readOnly} onClick={addShot} data-add-shot=\"\">\n + Shot\n </button>\n {current && (\n <>\n <button type=\"button\" className={btn} aria-label=\"Move shot earlier\" disabled={readOnly || index === 0} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index - 1 }, 'Move shot')}>\n ←\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move shot later\" disabled={readOnly || index === scene.shots.length - 1} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index + 1 }, 'Move shot')}>\n →\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete shot\" disabled={readOnly} onClick={() => apply({ op: 'delete_shots', shots: [current.id] }, 'Delete shot')}>\n ✕\n </button>\n </>\n )}\n </span>\n </div>\n {current && (\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Label</label>\n <CommitInput className={input} aria-label=\"Shot label\" disabled={readOnly} value={current.label ?? ''} onCommit={(raw) => apply(raw.trim() ? { op: 'update_shot', shot: current.id, set: { label: raw.trim() } } : { op: 'update_shot', shot: current.id, remove: ['label'] }, 'Rename shot')} />\n <label className=\"text-muted-foreground\">Hold</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0} step={50} aria-label=\"Hold\" placeholder=\"600\" disabled={readOnly} value={current.hold !== undefined ? String(current.hold) : ''} onCommit={(raw) => number('hold', raw, 'Change hold')} />\n <span className=\"text-[10px] text-muted-foreground\">ms</span>\n </div>\n <label className=\"text-muted-foreground\">Speed</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0.05} step={0.05} aria-label=\"Speed\" placeholder=\"1\" disabled={readOnly} value={current.speed !== undefined ? String(current.speed) : ''} onCommit={(raw) => number('speed', raw, 'Change speed')} />\n <span className=\"text-[10px] text-muted-foreground\">×</span>\n </div>\n <label className=\"text-muted-foreground\">Camera</label>\n <select\n className={input}\n aria-label=\"Camera frames\"\n disabled={readOnly}\n value={current.camera ? (frame ? `frame:${frame}` : 'rect') : ''}\n onChange={(e) => {\n const v = e.target.value;\n if (!v) apply({ op: 'update_shot', shot: current.id, remove: ['camera'] }, 'Clear camera');\n else if (v.startsWith('frame:')) apply({ op: 'update_shot', shot: current.id, set: { camera: { frame: v.slice(6), padding: 24 } } }, 'Frame camera');\n }}\n >\n <option value=\"\">keep framing</option>\n {current.camera && !frame && <option value=\"rect\">a rectangle</option>}\n {elements.map((e) => (\n <option key={e.id} value={`frame:${e.id}`}>\n frame {e.name ?? e.id}\n </option>\n ))}\n </select>\n <label className=\"text-muted-foreground\">Starts on</label>\n <select\n className={input}\n aria-label=\"Cue\"\n disabled={readOnly || index === 0}\n value={cueKey}\n onChange={(e) => {\n const cue = motionCueFromKey(e.target.value);\n apply(cue ? { op: 'update_shot', shot: current.id, set: { at: cue } } : { op: 'update_shot', shot: current.id, remove: ['at'] }, 'Cue shot');\n }}\n >\n <option value=\"\">after the shot before</option>\n {cueKey && !cues.some((c) => c.value === cueKey) && <option value={cueKey}>{cueKey}</option>}\n {cues.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </select>\n {!cues.length && index > 0 && <p className=\"col-span-2 text-[10px] text-muted-foreground\">Add a beat grid or narration in the scene settings to cue shots to them.</p>}\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","import_animation_editor","import_jsx_runtime","import_react","import_animation_editor","import_react","import_animation_editor","import_react","import_animation_editor","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","React","import_react","import_animation_editor","import_jsx_runtime","import_react","import_animation_editor","import_jsx_runtime","seconds","worst","import_react","import_animation_editor","import_jsx_runtime","input","btn","import_react","import_animation_editor","import_jsx_runtime","input","btn","import_jsx_runtime","btn"]}
@@ -606,7 +606,7 @@ function PlayheadScrubber({ controller, className = "" }) {
606
606
 
607
607
  // src/animation-editor/SceneSettings.tsx
608
608
  import { useState as useState4 } from "react";
609
- import { fitMotionSceneEdits, formatMotionNarration, parseMotionNarration } from "@pixerate/editor/animation-editor";
609
+ import { fitMotionSceneEdits, formatMotionDrivers, formatMotionNarration, parseMotionDrivers, parseMotionNarration } from "@pixerate/editor/animation-editor";
610
610
  import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
611
611
  var input2 = "w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs";
612
612
  var btn2 = "rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40";
@@ -651,6 +651,13 @@ function SceneSettings({ controller, className = "" }) {
651
651
  /* @__PURE__ */ jsx8("option", { value: "loop", children: "Loop" }),
652
652
  /* @__PURE__ */ jsx8("option", { value: "ping-pong", children: "Ping-pong" })
653
653
  ] }),
654
+ /* @__PURE__ */ jsx8("label", { className: "text-muted-foreground", children: "Motion blur" }),
655
+ /* @__PURE__ */ jsxs6("select", { className: input2, "aria-label": "Motion blur", disabled: readOnly, value: scene.motionBlur ? String(scene.motionBlur.shutter ?? 180) : "", onChange: (e) => settings({ motionBlur: e.target.value ? { ...scene.motionBlur ?? {}, shutter: Number(e.target.value) } : null }, "Change motion blur"), children: [
656
+ /* @__PURE__ */ jsx8("option", { value: "", children: "Off" }),
657
+ /* @__PURE__ */ jsx8("option", { value: "90", children: "Light (90\xB0)" }),
658
+ /* @__PURE__ */ jsx8("option", { value: "180", children: "Normal (180\xB0)" }),
659
+ /* @__PURE__ */ jsx8("option", { value: "360", children: "Heavy (360\xB0)" })
660
+ ] }),
654
661
  /* @__PURE__ */ jsx8("label", { className: "text-muted-foreground", children: "Plays on" }),
655
662
  /* @__PURE__ */ jsxs6("select", { className: input2, "aria-label": "Scene trigger", title: "How a viewer plays it when exported to Flair", disabled: readOnly, value: scene.trigger ?? "", onChange: (e) => settings({ trigger: e.target.value || null }, "Change trigger"), children: [
656
663
  /* @__PURE__ */ jsx8("option", { value: "", children: "Its own (autoplay)" }),
@@ -789,6 +796,26 @@ function SceneSettings({ controller, className = "" }) {
789
796
  formatMotionNarration(scene.narration)
790
797
  )
791
798
  ] }),
799
+ /* @__PURE__ */ jsxs6("label", { className: "flex flex-col gap-0.5", children: [
800
+ /* @__PURE__ */ jsx8("span", { className: "text-muted-foreground", children: "Drivers (one a line: target.property <- source.property * factor)" }),
801
+ /* @__PURE__ */ jsx8(
802
+ "textarea",
803
+ {
804
+ className: `${input2} h-14 font-mono`,
805
+ "aria-label": "Drivers",
806
+ placeholder: "back.x <- front.x * 0.5\nwheel.rotation <- wheel.x * 2.86",
807
+ disabled: readOnly,
808
+ defaultValue: formatMotionDrivers(scene.drivers),
809
+ onBlur: (e) => {
810
+ if (e.currentTarget.value === formatMotionDrivers(scene.drivers)) return;
811
+ const parsed = parseMotionDrivers(e.currentTarget.value);
812
+ if ("error" in parsed) return setLocal(parsed.error);
813
+ apply({ op: "set_drivers", drivers: parsed.drivers }, parsed.drivers.length ? "Set drivers" : "Clear drivers");
814
+ }
815
+ },
816
+ formatMotionDrivers(scene.drivers)
817
+ )
818
+ ] }),
792
819
  message && /* @__PURE__ */ jsx8("p", { className: "text-red-500", role: "alert", "data-edit-error": "", children: message })
793
820
  ] });
794
821
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/animation-editor/useAnimationEditor.ts","../../src/animation-editor/AnimationStage.tsx","../../src/animation-editor/ShotTimeline.tsx","../../src/animation-editor/AnimationEditor.tsx","../../src/animation-editor/CommandInspector.tsx","../../src/animation-editor/EasePicker.tsx","../../src/animation-editor/CommitInput.tsx","../../src/animation-editor/CommandList.tsx","../../src/animation-editor/PlayheadScrubber.tsx","../../src/animation-editor/SceneSettings.tsx","../../src/animation-editor/ShotInspector.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n AnimationEditorController,\n createAnimationEditorToolProvider,\n type AnimationEditorOptions,\n type AnimationEditorState,\n type AnimationEditorToolProviderOptions,\n} from '@pixerate/editor/animation-editor';\nimport type { ToolRegistry } from '@pixerate/editor/tools';\n\n/** An `AnimationEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useAnimationEditorController(options: AnimationEditorOptions = {}): AnimationEditorController {\n const ref = useRef<AnimationEditorController | null>(null);\n if (!ref.current) ref.current = new AnimationEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change, including each played frame). */\nexport function useAnimationEditorState(controller: AnimationEditorController): AnimationEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseAnimationEditorResult {\n controller: AnimationEditorController;\n state: AnimationEditorState;\n play: () => void;\n pause: () => void;\n toggle: () => void;\n seek: (time: number) => void;\n undo: () => void;\n redo: () => void;\n /** The frame at the playhead as SVG. */\n toSvg: () => string;\n}\n\n/**\n * Subscribes to an animation editor controller and exposes its state with bound actions.\n * Pass options instead of a controller to create one for the component's lifetime.\n */\nexport function useAnimationEditor(controllerOrOptions: AnimationEditorController | AnimationEditorOptions = {}): UseAnimationEditorResult {\n const own = useRef<AnimationEditorController | null>(null);\n let controller: AnimationEditorController;\n if (controllerOrOptions instanceof AnimationEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new AnimationEditorController(controllerOrOptions);\n controller = own.current;\n }\n useEffect(() => () => own.current?.destroy(), []);\n const state = useAnimationEditorState(controller);\n const actions = useMemo(\n () => ({\n play: () => controller.play(),\n pause: () => controller.pause(),\n toggle: () => controller.toggle(),\n seek: (time: number) => controller.seek(time),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/**\n * Registers the animation editor's agent tools (`get_animation`, `add_commands`,\n * `export_flair_effect`, …) in `registry` while mounted.\n */\nexport function useAnimationEditorTools(\n registry: ToolRegistry | null | undefined,\n controller: AnimationEditorController,\n options: AnimationEditorToolProviderOptions = {},\n): void {\n const { id, namespace, readOnly, rasterize } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createAnimationEditorToolProvider(controller, { id, namespace, readOnly, rasterize }));\n }, [registry, controller, id, namespace, readOnly, rasterize]);\n}\n","import React, { useMemo } from 'react';\nimport { highlightMotionSvg, motionNodeAtElement, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationStageProps {\n controller: AnimationEditorController;\n /** Control values to preview (`{ accent: \"#0ea5e9\" }`). */\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel: true for every node whose place changes, or a list of ids. */\n motionPaths?: boolean | readonly string[];\n /**\n * Called when the stage is clicked, with the id of the artwork node under the pointer (the\n * innermost one; null for the background, ghosts and paths). Makes the stage pickable.\n */\n onPick?: (id: string | null, event: React.MouseEvent<HTMLDivElement>) => void;\n /** Node ids to outline (e.g. the picked element and the selected command's targets). */\n highlight?: readonly string[];\n className?: string;\n}\n\n/**\n * The animation's frame at the playhead, drawn as inline SVG scaled to the stage's width. The\n * SVG keeps the artwork's node ids, so `onPick` can say which element was clicked.\n */\nexport function AnimationStage({ controller, values, onionSkin, motionPaths, onPick, highlight, className = '' }: AnimationStageProps) {\n const state = useAnimationEditorState(controller);\n const { scene, time } = state;\n const key = highlight?.join('\\u0000') ?? '';\n const svg = useMemo(\n () =>\n highlightMotionSvg(\n controller.toSvg(time, { pretty: false, idPrefix: 'ae-', values, onionSkin, motionPaths }).replace(/<svg ([^>]*?)width=\"[^\"]*\" height=\"[^\"]*\"/, '<svg $1width=\"100%\" height=\"100%\"'),\n highlight ?? [],\n ),\n [controller, scene, time, values, onionSkin, motionPaths, key],\n );\n return (\n <div\n className={`relative overflow-hidden ${onPick ? 'cursor-crosshair' : ''} ${className}`}\n style={{ aspectRatio: `${scene.artwork.width} / ${scene.artwork.height}` }}\n data-animation-stage=\"\"\n role=\"img\"\n aria-label={`${scene.name} at ${(time / 1000).toFixed(2)} s`}\n onClick={onPick ? (e) => onPick(motionNodeAtElement(scene, e.target as Element, e.currentTarget), e) : undefined}\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n );\n}\n","import React from 'react';\nimport type { AnimationEditorController, MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotTimelineProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(1)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play / pause, the playhead and one block per shot (as wide as it is long): click a shot to\n * select it and jump to its start, click the ruler to seek. Shots with errors or warnings are marked.\n */\nexport function ShotTimeline({ controller, className = '' }: ShotTimelineProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues } = state;\n const span = Math.max(1, duration);\n const onRuler = (event: React.PointerEvent<HTMLDivElement>) => {\n const box = event.currentTarget.getBoundingClientRect();\n controller.seek(((event.clientX - box.left) / Math.max(1, box.width)) * span);\n };\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <span className=\"tabular-nums text-muted-foreground\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div className=\"relative h-3 cursor-pointer rounded bg-muted\" onPointerDown={onRuler} role=\"slider\" aria-label=\"Playhead\" aria-valuemin={0} aria-valuemax={duration} aria-valuenow={Math.round(time)} tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') controller.seek(time + 100);\n if (e.key === 'ArrowLeft') controller.seek(time - 100);\n }}>\n <div className=\"absolute inset-y-0 w-0.5 bg-rose-500\" style={{ left: `${(time / span) * 100}%` }} />\n </div>\n <div className=\"flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot) => {\n const mark = worst(issues.filter((i) => i.shot === shot.id));\n const selected = selection?.shot === shot.id;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.end - shot.start)}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { indexMotionNodes, motionIssueLine, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { AnimationStage } from './AnimationStage';\nimport { CommandInspector } from './CommandInspector';\nimport { CommandList } from './CommandList';\nimport { PlayheadScrubber } from './PlayheadScrubber';\nimport { SceneSettings } from './SceneSettings';\nimport { ShotInspector } from './ShotInspector';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationEditorProps {\n controller: AnimationEditorController;\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead (see `<AnimationStage onionSkin>`). Default: an Onion skin toggle. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel (see `<AnimationStage motionPaths>`). Default: a Motion paths toggle. */\n motionPaths?: boolean | readonly string[];\n /** List the scene's issues under the timeline (default true). */\n showIssues?: boolean;\n /**\n * Show the hand-editing panels: the command list and inspector, the shot inspector, scene\n * settings, undo / redo and picking on the stage (default true). False shows the stage,\n * scrubber and issues only.\n */\n editable?: boolean;\n className?: string;\n}\n\nconst ONION: MotionOnionSkin = { before: 3, after: 1 };\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * A whole animation editor for an `AnimationEditorController`: the stage (click an element to\n * pick it, shift-click to add it to or remove it from the selected command's targets), the\n * playhead scrubber, and panels to edit commands, shots and scene settings by hand. Every edit\n * is one undo step.\n */\nexport function AnimationEditor({ controller, values, onionSkin, motionPaths, showIssues = true, editable = true, className = '' }: AnimationEditorProps) {\n const state = useAnimationEditorState(controller);\n const { issues, scene, selection, readOnly } = state;\n const [picked, setPicked] = useState<string | null>(null);\n const [onion, setOnion] = useState(false);\n const [paths, setPaths] = useState(false);\n const command = selection?.command !== undefined ? scene.shots.find((s) => s.id === selection.shot)?.run[selection.command] : undefined;\n const targets = command && 'targets' in command ? command.targets : [];\n const nodes = useMemo(() => indexMotionNodes(scene.artwork.nodes), [scene.artwork]);\n const pickedValid = picked && nodes.has(picked) ? picked : null;\n const onPick = (id: string | null, event: { shiftKey: boolean }) => {\n if (event.shiftKey && id && command && 'targets' in command && selection?.command !== undefined && !readOnly) {\n const next = targets.includes(id) ? targets.filter((t) => t !== id) : [...targets, id];\n if (next.length) controller.apply({ op: 'update_command', shot: selection.shot, command: selection.command, set: { targets: next } }, next.length > targets.length ? 'Add target' : 'Remove target');\n return;\n }\n setPicked(id);\n };\n const stage = (\n <AnimationStage\n controller={controller}\n values={values}\n onionSkin={onionSkin ?? (onion ? ONION : undefined)}\n motionPaths={motionPaths ?? paths}\n onPick={editable ? onPick : undefined}\n highlight={editable ? [...(pickedValid ? [pickedValid] : []), ...targets] : undefined}\n className=\"rounded-md border border-border bg-muted/40\"\n />\n );\n const issueList = showIssues && issues.length > 0 && (\n <ul className=\"space-y-0.5 text-xs\" aria-label=\"Animation issues\">\n {issues.map((issue, i) => (\n <li key={i} className={issue.severity === 'error' ? 'text-red-500' : issue.severity === 'warning' ? 'text-amber-500' : 'text-muted-foreground'}>\n {motionIssueLine(issue)}\n </li>\n ))}\n </ul>\n );\n if (!editable)\n return (\n <div className={`flex flex-col gap-2 ${className}`} data-animation-editor=\"\">\n {stage}\n <PlayheadScrubber controller={controller} />\n {issueList}\n </div>\n );\n\n return (\n <div\n className={`grid gap-3 lg:grid-cols-[minmax(0,1fr)_20rem] ${className}`}\n data-animation-editor=\"\"\n onKeyDown={(e) => {\n const el = e.target as HTMLElement;\n if (!(e.metaKey || e.ctrlKey) || e.key.toLowerCase() !== 'z' || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName)) return;\n e.preventDefault();\n if (e.shiftKey) controller.redo();\n else controller.undo();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-2\">\n {stage}\n <PlayheadScrubber controller={controller} />\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n <button type=\"button\" className={btn} onClick={() => controller.undo()} disabled={!state.canUndo} title={state.canUndo ? `Undo ${state.undoLabel}` : 'Nothing to undo'} data-undo=\"\">\n Undo\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.redo()} disabled={!state.canRedo} title={state.canRedo ? `Redo ${state.redoLabel}` : 'Nothing to redo'} data-redo=\"\">\n Redo\n </button>\n {onionSkin === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={onion} onChange={(e) => setOnion(e.target.checked)} /> Onion skin\n </label>\n )}\n {motionPaths === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={paths} onChange={(e) => setPaths(e.target.checked)} /> Motion paths\n </label>\n )}\n <span className=\"ml-auto\" data-picked-element={pickedValid ?? undefined}>\n {pickedValid ? (\n <>\n Picked <code className=\"text-rose-500\">{pickedValid}</code>{' '}\n <button type=\"button\" className=\"underline\" onClick={() => setPicked(null)}>\n clear\n </button>\n </>\n ) : (\n 'Click the stage to pick an element; shift-click to toggle it as a target.'\n )}\n </span>\n </div>\n {issueList}\n </div>\n <div className=\"flex min-w-0 flex-col gap-3\">\n <CommandList controller={controller} targets={pickedValid ? [pickedValid] : undefined} />\n <CommandInspector controller={controller} picked={pickedValid} className=\"border-t border-border pt-2\" />\n <details open className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Shot</summary>\n <ShotInspector controller={controller} className=\"mt-1\" />\n </details>\n <details className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Scene settings</summary>\n <SceneSettings controller={controller} className=\"mt-1\" />\n </details>\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport {\n describeMotionElements,\n motionCommandFields,\n motionFieldEdit,\n motionFlairPrimitive,\n type AnimationEditorController,\n type MotionFieldSpec,\n} from '@pixerate/editor/animation-editor';\nimport { EasePicker } from './EasePicker';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandInspectorProps {\n controller: AnimationEditorController;\n /** An element picked on the stage, offered as a target to add. */\n picked?: string | null;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\n\n\n/**\n * A form for the selected command, generated from `MOTION_COMMAND_SCHEMA` (the schema the\n * agent tools take): enums as selects, numbers with their units and limits, node pickers for\n * targets and for `into` / `path`, and an ease picker. Shows the Flair primitive it plays.\n */\nexport function CommandInspector({ controller, picked, className = '' }: CommandInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const shot = selection ? scene.shots.find((s) => s.id === selection.shot) : undefined;\n const index = selection?.command;\n const command = shot && index !== undefined ? shot.run[index] : undefined;\n if (!shot || index === undefined || !command) {\n return (\n <div className={`text-xs text-muted-foreground ${className}`} data-command-inspector=\"\">\n Select a command to edit it.\n </div>\n );\n }\n const values = command as unknown as Record<string, unknown>;\n const fields = motionCommandFields(command.type);\n const primitive = motionFlairPrimitive(command);\n const commit = (field: MotionFieldSpec, raw: Parameters<typeof motionFieldEdit>[3]) => {\n const edit = motionFieldEdit(shot.id, index, field, raw);\n if ('error' in edit) return setLocal(edit.error);\n setLocal(null);\n controller.apply(edit, `Set ${field.label.toLowerCase()}`);\n };\n const name = (id: string) => elements.find((e) => e.id === id)?.name ?? id;\n const targets = (values.targets as string[] | undefined) ?? [];\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n const control = (field: MotionFieldSpec) => {\n const v = values[field.name];\n const common = { disabled: readOnly, 'aria-label': field.label, title: field.description };\n switch (field.kind) {\n case 'targets':\n return (\n <div className=\"flex flex-wrap items-center gap-1\" data-targets=\"\">\n {targets.map((id) => (\n <span key={id} className=\"flex items-center gap-0.5 rounded bg-muted px-1 text-[11px]\" data-target={id}>\n {name(id)}\n {!readOnly && targets.length > 1 && (\n <button type=\"button\" aria-label={`Remove ${id}`} onClick={() => commit(field, targets.filter((t) => t !== id))}>\n ×\n </button>\n )}\n </span>\n ))}\n {!readOnly && picked && !targets.includes(picked) && (\n <button type=\"button\" className=\"rounded border border-rose-500 px-1 text-[11px] text-rose-500\" onClick={() => commit(field, [...targets, picked])} data-add-picked=\"\">\n + {name(picked)}\n </button>\n )}\n {!readOnly && (\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\" aria-label=\"Add target\" value=\"\" onChange={(e) => e.target.value && commit(field, [...targets, e.target.value])}>\n <option value=\"\">+ target…</option>\n {elements.filter((e) => !targets.includes(e.id)).map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n </option>\n ))}\n </select>\n )}\n </div>\n );\n case 'node':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">—</option>}\n {elements.filter((e) => field.name !== 'path' || e.type === 'path').map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n {e.hidden ? ' · hidden' : ''}\n </option>\n ))}\n </select>\n );\n case 'enum':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">default</option>}\n {field.options!.map((o) => (\n <option key={o} value={o}>\n {o}\n </option>\n ))}\n </select>\n );\n case 'boolean':\n return <input type=\"checkbox\" {...common} checked={v === true} onChange={(e) => commit(field, e.target.checked)} />;\n case 'ease':\n return <EasePicker value={v as never} disabled={readOnly} onChange={(ease) => commit(field, ease === undefined ? '' : (ease as string))} />;\n case 'color':\n return (\n <div className=\"flex items-center gap-1\">\n <input type=\"color\" disabled={readOnly} aria-label={`${field.label} swatch`} value={typeof v === 'string' && /^#[0-9a-f]{6}$/i.test(v) ? v : '#000000'} onChange={(e) => commit(field, e.target.value)} />\n <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} placeholder=\"unchanged\" onCommit={(raw) => commit(field, raw)} />\n </div>\n );\n case 'point': {\n const p = (v as { x: number; y: number } | undefined) ?? undefined;\n return (\n <div className=\"flex items-center gap-1\">\n {(['x', 'y'] as const).map((axis) => (\n <CommitInput\n key={axis}\n className={input}\n type=\"number\"\n disabled={readOnly}\n aria-label={`${field.label} ${axis}`}\n placeholder={axis}\n value={p ? String(p[axis]) : ''}\n onCommit={(raw) => commit(field, axis === 'x' ? { x: raw, y: p ? String(p.y) : raw ? '0' : '' } : { x: p ? String(p.x) : raw ? '0' : '', y: raw })}\n />\n ))}\n </div>\n );\n }\n case 'scale':\n case 'number':\n case 'integer':\n return (\n <div className=\"flex items-center gap-1\">\n <CommitInput\n className={input}\n type=\"number\"\n {...common}\n min={field.min}\n max={field.max}\n step={field.kind === 'integer' ? 1 : field.unit === 'ms' ? 50 : field.unit === '0–1' ? 0.05 : 'any'}\n placeholder=\"default\"\n value={typeof v === 'number' ? String(v) : ''}\n onCommit={(raw) => commit(field, raw)}\n />\n {field.unit && <span className=\"shrink-0 text-[10px] text-muted-foreground\">{field.unit}</span>}\n </div>\n );\n default:\n return <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} onCommit={(raw) => commit(field, raw)} />;\n }\n };\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-command-inspector=\"\" data-command-type={command.type}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">\n {index + 1}. {command.type}\n </span>\n {primitive ? (\n <code className=\"rounded bg-muted px-1 text-[10px]\" data-flair-primitive={primitive} title=\"The Flair motion primitive this command plays\">\n {primitive}\n </code>\n ) : (\n <span className=\"text-[10px] text-muted-foreground\">editor-only (no Flair primitive)</span>\n )}\n </div>\n {(['main', 'timing'] as const).map((group) => (\n <fieldset key={group} className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <legend className=\"mb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">{group === 'main' ? 'Command' : 'Timing'}</legend>\n {fields\n .filter((f) => f.group === group)\n .map((field) => (\n <React.Fragment key={field.name}>\n <label className=\"truncate text-muted-foreground\" title={field.description}>\n {field.label}\n {field.required ? ' *' : ''}\n </label>\n <div data-field={field.name}>{control(field)}</div>\n </React.Fragment>\n ))}\n </fieldset>\n ))}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo } from 'react';\nimport { MOTION_EASE_CHOICES, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, type MotionCommandBase } from '@pixerate/editor/animation-editor';\n\n/** An easing (a preset name or a curve), as commands take it. */\ntype AnimationEasing = NonNullable<MotionCommandBase['ease']>;\n\nexport interface EasePickerProps {\n /** The easing (undefined: the command type's default). */\n value: AnimationEasing | undefined;\n /** Called with the picked preset, or undefined for the default. */\n onChange: (ease: AnimationEasing | undefined) => void;\n disabled?: boolean;\n className?: string;\n}\n\nconst W = 72;\nconst H = 44;\n\n/**\n * Picks an easing preset (springs included) and previews its curve, drawn by sampling\n * `evaluateEasing`; a spring is drawn over the time it takes to settle, overshoot included.\n */\nexport function EasePicker({ value, onChange, disabled, className = '' }: EasePickerProps) {\n const key = motionEaseKey(value);\n const curve = useMemo(() => motionEasingCurve(value ?? 'ease-out'), [value]);\n const guides = motionEasingGuides(curve, H);\n const spring = typeof value === 'string' ? value.startsWith('spring') : value?.type === 'spring';\n return (\n <div className={`flex items-center gap-2 ${className}`} data-ease-picker=\"\">\n <select\n className=\"min-w-0 flex-1 rounded border border-border bg-transparent px-1 py-0.5 text-xs\"\n aria-label=\"Ease\"\n value={key}\n disabled={disabled}\n onChange={(e) => {\n if (e.target.value === 'custom') return;\n onChange(e.target.value ? (e.target.value as AnimationEasing) : undefined);\n }}\n >\n {MOTION_EASE_CHOICES.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n {key === 'custom' && <option value=\"custom\">Custom</option>}\n </select>\n <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} className=\"shrink-0 rounded border border-border\" data-ease-curve={key || 'default'} aria-hidden=\"true\">\n <line x1={0} x2={W} y1={guides.zero} y2={guides.zero} stroke=\"currentColor\" strokeOpacity={0.2} />\n <line x1={0} x2={W} y1={guides.one} y2={guides.one} stroke=\"currentColor\" strokeOpacity={0.2} strokeDasharray=\"2 2\" />\n <path d={motionEasingPath(curve, W, H)} fill=\"none\" stroke=\"#f43f5e\" strokeWidth={1.5} />\n </svg>\n {spring && <span className=\"text-[10px] tabular-nums text-muted-foreground\">{Math.round(curve.durationMs)} ms</span>}\n </div>\n );\n}\n","import React from 'react';\n\n/** An input that commits on blur or Enter, and resets when its value changes from outside. */\nexport function CommitInput({ value, onCommit, ...rest }: { value: string; onCommit: (raw: string) => void } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue'>) {\n return (\n <input\n key={value}\n {...rest}\n defaultValue={value}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n if (e.currentTarget.value !== value) onCommit(e.currentTarget.value);\n }}\n />\n );\n}\n","import React, { useState } from 'react';\nimport {\n MOTION_COMMAND_TYPES,\n defaultMotionCommand,\n duplicateMotionCommandEdit,\n motionCommandRows,\n type AnimationEditorController,\n type MotionCommandType,\n} from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandListProps {\n controller: AnimationEditorController;\n /** The shot to list (default: the selected shot, else the first). */\n shot?: string;\n /** Targets for a new command (e.g. the element picked on the stage); default: the selected command's. */\n targets?: readonly string[];\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n/**\n * A shot's commands in order: select one to inspect it, change `with` and `delay` inline, move,\n * duplicate or delete it, and add new ones. Each change is one `controller.apply` edit (one undo\n * step); a refused edit shows its reason.\n */\nexport function CommandList({ controller, shot, targets, className = '' }: CommandListProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const shotId = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const current = scene.shots.find((s) => s.id === shotId);\n const [type, setType] = useState<MotionCommandType>('enter');\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n if (!current) return <div className={`text-xs text-muted-foreground ${className}`} data-command-list=\"\">Add a shot to start.</div>;\n const rows = motionCommandRows(scene, current.id);\n const selected = selection?.shot === current.id ? selection.command : undefined;\n const run = (edit: Parameters<AnimationEditorController['apply']>[0], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const add = () => {\n const from = targets?.length ? targets : selected !== undefined ? ((current.run[selected] as { targets?: string[] }).targets ?? []) : [];\n const command = defaultMotionCommand(type, from, scene);\n if ('error' in command) return setLocal(command.error);\n const at = selected !== undefined ? selected + 1 : current.run.length;\n const result = run({ op: 'add_commands', shot: current.id, commands: [command], at }, `Add ${type}`);\n if (result.ok) controller.select({ shot: current.id, command: at });\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1 text-xs ${className}`} data-command-list=\"\" data-for-shot={current.id}>\n <div className=\"font-medium\">\n Commands in <span className=\"text-rose-500\">{current.label ?? current.id}</span>\n </div>\n <ol className=\"flex flex-col gap-1\" aria-label=\"Commands\">\n {rows.map((row) => {\n const c = row.command as { with?: string; delay?: number };\n const isSelected = row.index === selected;\n return (\n <li\n key={`${row.index}:${row.summary}`}\n className={`flex flex-wrap items-center gap-1 rounded border px-1.5 py-1 ${isSelected ? 'border-rose-500 bg-rose-500/10' : 'border-border'}`}\n data-command={row.index}\n data-selected={isSelected || undefined}\n onClick={() => controller.select({ shot: current.id, command: row.index })}\n >\n <span className=\"min-w-0 flex-1 truncate\" title={row.summary}>\n {row.index + 1}. {row.summary}\n </span>\n {row.flairPrimitive && (\n <code className=\"rounded bg-muted px-1 text-[10px] text-muted-foreground\" data-flair-primitive={row.flairPrimitive}>\n {row.flairPrimitive}\n </code>\n )}\n <span className=\"tabular-nums text-[10px] text-muted-foreground\">{((row.end - row.start) / 1000).toFixed(2)} s</span>\n <div className=\"flex w-full items-center gap-1\" onClick={(e) => e.stopPropagation()}>\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\"\n aria-label=\"Starts\"\n value={c.with ?? 'after'}\n disabled={readOnly || row.index === 0}\n onChange={(e) =>\n run(\n e.target.value === 'after' ? { op: 'update_command', shot: current.id, command: row.index, remove: ['with'] } : { op: 'update_command', shot: current.id, command: row.index, set: { with: e.target.value } },\n 'Change start',\n )\n }\n >\n <option value=\"after\">after previous</option>\n <option value=\"previous\">with previous</option>\n </select>\n <label className=\"flex items-center gap-0.5 text-muted-foreground\">\n +\n <input\n key={String(c.delay ?? '')}\n className=\"w-14 rounded border border-border bg-transparent px-1 py-0.5 text-[11px] tabular-nums\"\n type=\"number\"\n min={0}\n step={50}\n aria-label=\"Delay\"\n placeholder=\"0\"\n defaultValue={c.delay ?? ''}\n disabled={readOnly}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n const raw = e.currentTarget.value.trim();\n if (raw === String(c.delay ?? '')) return;\n const n = Number(raw);\n if (raw && !(Number.isFinite(n) && n >= 0)) return setLocal('Delay must be a number of ms, 0 or more.');\n run(raw && n > 0 ? { op: 'update_command', shot: current.id, command: row.index, set: { delay: n } } : { op: 'update_command', shot: current.id, command: row.index, remove: ['delay'] }, 'Change delay');\n }}\n />\n ms\n </label>\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} aria-label=\"Move up\" disabled={readOnly || row.index === 0} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index - 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index - 1 })}>\n ↑\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move down\" disabled={readOnly || row.index === rows.length - 1} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index + 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ↓\n </button>\n <button type=\"button\" className={btn} aria-label=\"Duplicate\" disabled={readOnly} onClick={() => run(duplicateMotionCommandEdit(scene, current.id, row.index), 'Duplicate command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ⧉\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete\" disabled={readOnly} onClick={() => run({ op: 'delete_commands', shot: current.id, commands: [row.index] }, 'Delete command')}>\n ✕\n </button>\n </span>\n </div>\n </li>\n );\n })}\n </ol>\n {!readOnly && (\n <div className=\"flex items-center gap-1\">\n <select className=\"flex-1 rounded border border-border bg-transparent px-1 py-0.5\" aria-label=\"New command type\" value={type} onChange={(e) => setType(e.target.value as MotionCommandType)}>\n {MOTION_COMMAND_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <button type=\"button\" className={btn} onClick={add} data-add-command=\"\">\n Add command\n </button>\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { motionBeatTime, motionCueTime, motionRulerTicks, type AnimationEditorController, type MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface PlayheadScrubberProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(2)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play, pause and loop, a time ruler (with the beat grid and narration words when the scene has\n * them) to scrub by dragging, and one band per shot (as wide as it is long): click a band to\n * select the shot and jump to its start. Loop is a scene setting, so changing it is one undo step.\n */\nexport function PlayheadScrubber({ controller, className = '' }: PlayheadScrubberProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues, scene, readOnly } = state;\n const span = Math.max(1, duration);\n const track = useRef<HTMLDivElement>(null);\n const [width, setWidth] = useState(600);\n useEffect(() => {\n const el = track.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => setWidth(el.clientWidth || 600));\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n const ticks = motionRulerTicks(duration, width);\n const pct = (ms: number) => `${(Math.min(span, Math.max(0, ms)) / span) * 100}%`;\n const seekAt = (clientX: number) => {\n const box = track.current!.getBoundingClientRect();\n controller.seek(Math.min(1, Math.max(0, (clientX - box.left) / Math.max(1, box.width))) * span);\n };\n const beats: number[] = [];\n if (scene.beat && scene.beat.bpm > 0) for (let b = 0, t = motionBeatTime(scene.beat, 0); t <= span && beats.length < 400; t = motionBeatTime(scene.beat, ++b)) if (t >= 0) beats.push(t);\n\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-playhead-scrubber=\"\" data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => { controller.pause(); controller.seek(0); }} aria-label=\"Back to start\">\n ⏮\n </button>\n <label className=\"flex items-center gap-1 text-muted-foreground\">\n Loop\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5\"\n value={scene.loop ?? 'none'}\n disabled={readOnly}\n aria-label=\"Loop\"\n onChange={(e) => controller.apply({ op: 'set_settings', loop: e.target.value as 'none' | 'loop' | 'ping-pong' }, 'Change loop')}\n >\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n </label>\n <span className=\"ml-auto tabular-nums text-muted-foreground\" data-time=\"\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div\n ref={track}\n className=\"relative cursor-ew-resize select-none touch-none\"\n role=\"slider\"\n aria-label=\"Playhead\"\n aria-valuemin={0}\n aria-valuemax={duration}\n aria-valuenow={Math.round(time)}\n tabIndex={0}\n data-scrub-track=\"\"\n onPointerDown={(e) => {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n seekAt(e.clientX);\n }}\n onPointerMove={(e) => {\n if (e.buttons & 1) seekAt(e.clientX);\n }}\n onKeyDown={(e) => {\n const step = e.shiftKey ? 1000 : 100;\n if (e.key === 'ArrowRight') controller.seek(time + step);\n else if (e.key === 'ArrowLeft') controller.seek(time - step);\n else if (e.key === 'Home') controller.seek(0);\n else if (e.key === 'End') controller.seek(duration);\n else if (e.key === ' ') controller.toggle();\n else return;\n e.preventDefault();\n }}\n >\n <div className=\"relative h-5 border-b border-border text-[10px] text-muted-foreground\" data-ruler=\"\">\n {beats.map((t, i) => (\n <div key={`b${i}`} className=\"absolute bottom-0 h-1.5 w-px bg-sky-500/60\" style={{ left: pct(t) }} data-beat={i} />\n ))}\n {scene.narration?.words.map((w, i) => (\n <div key={`w${i}`} className=\"absolute top-0 h-1.5 w-px bg-emerald-500/70\" style={{ left: pct(w.start) }} title={`“${w.text}” at ${seconds(w.start)}`} data-word={i} />\n ))}\n {ticks.map((t) => (\n <div key={t.time} className={`absolute bottom-0 w-px ${t.major ? 'h-2.5 bg-muted-foreground/70' : 'h-1 bg-muted-foreground/40'}`} style={{ left: pct(t.time) }}>\n {t.label && <span className=\"absolute -top-0.5 left-1 whitespace-nowrap tabular-nums\">{t.label}</span>}\n </div>\n ))}\n </div>\n <div className=\"mt-1 flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot, i) => {\n const mark = worst(issues.filter((x) => x.shot === shot.id));\n const selected = selection?.shot === shot.id;\n const cue = scene.shots[i]?.at;\n const cueTime = cue ? motionCueTime(scene, cue) : undefined;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`relative min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border bg-muted/40'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.start)}–${seconds(shot.end)}${cueTime !== undefined ? ` · cued at ${seconds(cueTime)}` : ''}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onPointerDown={(e) => e.stopPropagation()}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n <div className=\"pointer-events-none absolute inset-y-0 w-0.5 -translate-x-1/2 bg-rose-500\" style={{ left: pct(time) }} data-playhead=\"\" />\n </div>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport { fitMotionSceneEdits, formatMotionNarration, parseMotionNarration, type AnimationEditorController, type MotionEdit, type MotionTrigger } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface SceneSettingsProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\nconst unit = (u: string) => <span className=\"shrink-0 text-[10px] text-muted-foreground\">{u}</span>;\n\n/**\n * Scene settings: loop, frame rate, stepped time, the wanted length with a Fit button (sets the\n * shots' speeds with `fitMotionScene`, as `fit_animation` does), a beat grid and narration words\n * to cue shots to. Every change is one undo step; refusals show their reason.\n */\nexport function SceneSettings({ controller, className = '' }: SceneSettingsProps) {\n const state = useAnimationEditorState(controller);\n const { scene, readOnly, error, duration } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const [fitTo, setFitTo] = useState<string>('');\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const settings = (set: Omit<Extract<MotionEdit, { op: 'set_settings' }>, 'op'>, label: string) => apply({ op: 'set_settings', ...set }, label);\n const num = (raw: string, what: string, ok: (n: number) => boolean, then: (n: number | null) => void) => {\n if (raw.trim() === '') return then(null);\n const n = Number(raw);\n if (!Number.isFinite(n) || !ok(n)) return setLocal(what);\n then(n);\n };\n const target = scene.target;\n const fitSeconds = fitTo || String(target ? (target[0] + target[1]) / 2 : Math.round(duration / 100) / 10);\n const fit = () => {\n const s = Number(fitSeconds);\n if (!(Number.isFinite(s) && s > 0)) return setLocal('Give the length to fit in seconds, above 0.');\n try {\n const edits = fitMotionSceneEdits(scene, s * 1000);\n if (edits.length) apply(edits, `Fit to ${s} s`);\n else setLocal(null);\n } catch (e) {\n setLocal((e as Error).message);\n }\n };\n const beat = scene.beat;\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-scene-settings=\"\">\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Loop</label>\n <select className={input} aria-label=\"Scene loop\" disabled={readOnly} value={scene.loop ?? 'none'} onChange={(e) => settings({ loop: e.target.value as 'none' }, 'Change loop')}>\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n <label className=\"text-muted-foreground\">Plays on</label>\n <select className={input} aria-label=\"Scene trigger\" title=\"How a viewer plays it when exported to Flair\" disabled={readOnly} value={scene.trigger ?? ''} onChange={(e) => settings({ trigger: (e.target.value || null) as MotionTrigger | null }, 'Change trigger')}>\n <option value=\"\">Its own (autoplay)</option>\n <option value=\"click\">Click (a shot per click)</option>\n <option value=\"hover\">Hover</option>\n <option value=\"press\">Press</option>\n <option value=\"scroll\">Scroll</option>\n </select>\n <label className=\"text-muted-foreground\">Frame rate</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Frame rate\" placeholder=\"30\" disabled={readOnly} value={scene.fps !== undefined ? String(scene.fps) : ''}\n onCommit={(raw) => num(raw, 'Frame rate must be 1 to 120 fps.', (n) => n >= 1 && n <= 120, (n) => n !== null && settings({ fps: n }, 'Change frame rate'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\" title=\"Hold changes on a grid of this many frames a second (12 = on twos); empty is smooth\">\n Steps\n </label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Steps\" placeholder=\"smooth\" disabled={readOnly} value={scene.steps !== undefined ? String(scene.steps) : ''}\n onCommit={(raw) => num(raw, 'Steps must be above 0 and at most 120 fps, or empty for smooth.', (n) => n > 0 && n <= 120, (n) => settings({ steps: n }, 'Change steps'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\">Target length</label>\n <div className=\"flex items-center gap-1\">\n {[0, 1].map((i) => (\n <CommitInput key={i} className={input} type=\"number\" min={0} step={0.5} aria-label={i ? 'Target max' : 'Target min'} placeholder={i ? 'max' : 'min'} disabled={readOnly} value={target ? String(target[i]) : ''}\n onCommit={(raw) =>\n num(raw, 'Target lengths are seconds, 0 or more.', (n) => n >= 0, (n) => {\n if (n === null) return settings({ target: null }, 'Clear target length');\n const next: [number, number] = target ? [...target] : [n, n];\n next[i] = n;\n if (next[0] > next[1]) return setLocal('The shortest target length must not be longer than the longest.');\n settings({ target: next }, 'Change target length');\n })\n } />\n ))}\n {unit('s')}\n </div>\n <label className=\"text-muted-foreground\">Fit to</label>\n <div className=\"flex items-center gap-1\">\n <input className={input} type=\"number\" min={0.1} step={0.5} aria-label=\"Fit to\" value={fitSeconds} onChange={(e) => setFitTo(e.target.value)} />\n {unit('s')}\n <button type=\"button\" className={btn} disabled={readOnly || !scene.shots.length} onClick={fit} data-fit=\"\" title=\"Change the shots' speeds so the scene lasts this long\">\n Fit\n </button>\n </div>\n <label className=\"text-muted-foreground\">Beat grid</label>\n <div className=\"flex items-center gap-1\" data-beat-grid=\"\">\n <CommitInput className={input} type=\"number\" min={1} aria-label=\"BPM\" placeholder=\"bpm\" disabled={readOnly} value={beat ? String(beat.bpm) : ''}\n onCommit={(raw) => num(raw, 'BPM must be above 0.', (n) => n > 0, (n) => settings({ beat: n === null ? null : { ...(beat ?? {}), bpm: n } }, n === null ? 'Clear beat grid' : 'Change tempo'))} />\n <CommitInput className={input} type=\"number\" aria-label=\"Beat offset\" placeholder=\"offset ms\" disabled={readOnly || !beat} value={beat?.offset !== undefined ? String(beat.offset) : ''}\n onCommit={(raw) => beat && num(raw, 'The offset is a number of ms.', () => true, (n) => settings({ beat: { ...beat, offset: n ?? 0 } }, 'Change beat offset'))} />\n <CommitInput className={input} type=\"number\" min={1} step={1} aria-label=\"Meter\" placeholder=\"4/bar\" disabled={readOnly || !beat} value={beat?.meter !== undefined ? String(beat.meter) : ''}\n onCommit={(raw) => beat && num(raw, 'The meter is a whole number of beats a bar.', (n) => Number.isInteger(n) && n >= 1, (n) => settings({ beat: { ...beat, meter: n ?? 4 } }, 'Change meter'))} />\n </div>\n </div>\n <label className=\"flex flex-col gap-0.5\">\n <span className=\"text-muted-foreground\">Narration (a word a line: start ms, then the word)</span>\n <textarea\n key={formatMotionNarration(scene.narration)}\n className={`${input} h-20 font-mono`}\n aria-label=\"Narration\"\n placeholder={'0 Meet\\n320 the\\n480 badge'}\n disabled={readOnly}\n defaultValue={formatMotionNarration(scene.narration)}\n onBlur={(e) => {\n if (e.currentTarget.value === formatMotionNarration(scene.narration)) return;\n const parsed = parseMotionNarration(e.currentTarget.value);\n if ('error' in parsed) return setLocal(parsed.error);\n settings({ narration: parsed.narration }, parsed.narration ? 'Change narration' : 'Clear narration');\n }}\n />\n </label>\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { describeMotionElements, freshShotId, motionCueChoices, motionCueFromKey, motionCueKey, type AnimationEditorController, type MotionEdit } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotInspectorProps {\n controller: AnimationEditorController;\n /** The shot to edit (default: the selected shot, else the first). */\n shot?: string;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n\n/**\n * The selected shot: its label, hold, speed, the node the camera frames, and the cue it starts\n * on (a beat of the scene's grid or a narration word). Also adds, moves and deletes shots.\n * Every change is one undo step.\n */\nexport function ShotInspector({ controller, shot, className = '' }: ShotInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const cues = useMemo(() => motionCueChoices(scene), [scene]);\n const id = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const index = scene.shots.findIndex((s) => s.id === id);\n const current = scene.shots[index];\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const addShot = () => {\n const newId = freshShotId(scene, 'shot');\n const at = index >= 0 ? index + 1 : scene.shots.length;\n if (apply({ op: 'insert_shots', shots: [{ id: newId, label: 'New shot', run: [] }], at }, 'Add shot').ok) {\n controller.select({ shot: newId });\n controller.seekShot(newId);\n }\n };\n const number = (key: 'hold' | 'speed', raw: string, label: string) => {\n const n = Number(raw);\n if (raw.trim() === '') return apply({ op: 'update_shot', shot: current.id, remove: [key] }, label);\n if (!Number.isFinite(n) || n < 0 || (key === 'speed' && n <= 0)) return setLocal(key === 'speed' ? 'Speed must be a number above 0 (1 = as written).' : 'Hold must be a number of ms, 0 or more.');\n apply({ op: 'update_shot', shot: current.id, set: { [key]: n } }, label);\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n const cueKey = current ? motionCueKey(current.at) : '';\n const frame = current?.camera && 'frame' in current.camera ? current.camera.frame : '';\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-shot-inspector=\"\">\n <div className=\"flex items-center gap-1\">\n <span className=\"font-medium\">Shot</span>\n {current && <code className=\"text-[10px] text-muted-foreground\">{current.id}</code>}\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} disabled={readOnly} onClick={addShot} data-add-shot=\"\">\n + Shot\n </button>\n {current && (\n <>\n <button type=\"button\" className={btn} aria-label=\"Move shot earlier\" disabled={readOnly || index === 0} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index - 1 }, 'Move shot')}>\n ←\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move shot later\" disabled={readOnly || index === scene.shots.length - 1} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index + 1 }, 'Move shot')}>\n →\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete shot\" disabled={readOnly} onClick={() => apply({ op: 'delete_shots', shots: [current.id] }, 'Delete shot')}>\n ✕\n </button>\n </>\n )}\n </span>\n </div>\n {current && (\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Label</label>\n <CommitInput className={input} aria-label=\"Shot label\" disabled={readOnly} value={current.label ?? ''} onCommit={(raw) => apply(raw.trim() ? { op: 'update_shot', shot: current.id, set: { label: raw.trim() } } : { op: 'update_shot', shot: current.id, remove: ['label'] }, 'Rename shot')} />\n <label className=\"text-muted-foreground\">Hold</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0} step={50} aria-label=\"Hold\" placeholder=\"600\" disabled={readOnly} value={current.hold !== undefined ? String(current.hold) : ''} onCommit={(raw) => number('hold', raw, 'Change hold')} />\n <span className=\"text-[10px] text-muted-foreground\">ms</span>\n </div>\n <label className=\"text-muted-foreground\">Speed</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0.05} step={0.05} aria-label=\"Speed\" placeholder=\"1\" disabled={readOnly} value={current.speed !== undefined ? String(current.speed) : ''} onCommit={(raw) => number('speed', raw, 'Change speed')} />\n <span className=\"text-[10px] text-muted-foreground\">×</span>\n </div>\n <label className=\"text-muted-foreground\">Camera</label>\n <select\n className={input}\n aria-label=\"Camera frames\"\n disabled={readOnly}\n value={current.camera ? (frame ? `frame:${frame}` : 'rect') : ''}\n onChange={(e) => {\n const v = e.target.value;\n if (!v) apply({ op: 'update_shot', shot: current.id, remove: ['camera'] }, 'Clear camera');\n else if (v.startsWith('frame:')) apply({ op: 'update_shot', shot: current.id, set: { camera: { frame: v.slice(6), padding: 24 } } }, 'Frame camera');\n }}\n >\n <option value=\"\">keep framing</option>\n {current.camera && !frame && <option value=\"rect\">a rectangle</option>}\n {elements.map((e) => (\n <option key={e.id} value={`frame:${e.id}`}>\n frame {e.name ?? e.id}\n </option>\n ))}\n </select>\n <label className=\"text-muted-foreground\">Starts on</label>\n <select\n className={input}\n aria-label=\"Cue\"\n disabled={readOnly || index === 0}\n value={cueKey}\n onChange={(e) => {\n const cue = motionCueFromKey(e.target.value);\n apply(cue ? { op: 'update_shot', shot: current.id, set: { at: cue } } : { op: 'update_shot', shot: current.id, remove: ['at'] }, 'Cue shot');\n }}\n >\n <option value=\"\">after the shot before</option>\n {cueKey && !cues.some((c) => c.value === cueKey) && <option value={cueKey}>{cueKey}</option>}\n {cues.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </select>\n {!cues.length && index > 0 && <p className=\"col-span-2 text-[10px] text-muted-foreground\">Add a beat grid or narration in the scene settings to cue shots to them.</p>}\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["useMemo","useMemo","jsx","useMemo","useState","React","useMemo","useMemo","jsx","jsxs","jsx","jsx","jsxs","useMemo","React","useState","jsx","jsxs","useState","useEffect","useRef","useState","jsx","jsxs","seconds","worst","useRef","useState","useEffect","useState","jsx","jsxs","input","btn","useState","useMemo","useState","describeMotionElements","jsx","jsxs","input","btn","useState","useMemo","describeMotionElements","Fragment","jsx","jsxs","btn","useState","useMemo"]}
1
+ {"version":3,"sources":["../../src/animation-editor/useAnimationEditor.ts","../../src/animation-editor/AnimationStage.tsx","../../src/animation-editor/ShotTimeline.tsx","../../src/animation-editor/AnimationEditor.tsx","../../src/animation-editor/CommandInspector.tsx","../../src/animation-editor/EasePicker.tsx","../../src/animation-editor/CommitInput.tsx","../../src/animation-editor/CommandList.tsx","../../src/animation-editor/PlayheadScrubber.tsx","../../src/animation-editor/SceneSettings.tsx","../../src/animation-editor/ShotInspector.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n AnimationEditorController,\n createAnimationEditorToolProvider,\n type AnimationEditorOptions,\n type AnimationEditorState,\n type AnimationEditorToolProviderOptions,\n} from '@pixerate/editor/animation-editor';\nimport type { ToolRegistry } from '@pixerate/editor/tools';\n\n/** An `AnimationEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useAnimationEditorController(options: AnimationEditorOptions = {}): AnimationEditorController {\n const ref = useRef<AnimationEditorController | null>(null);\n if (!ref.current) ref.current = new AnimationEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change, including each played frame). */\nexport function useAnimationEditorState(controller: AnimationEditorController): AnimationEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseAnimationEditorResult {\n controller: AnimationEditorController;\n state: AnimationEditorState;\n play: () => void;\n pause: () => void;\n toggle: () => void;\n seek: (time: number) => void;\n undo: () => void;\n redo: () => void;\n /** The frame at the playhead as SVG. */\n toSvg: () => string;\n}\n\n/**\n * Subscribes to an animation editor controller and exposes its state with bound actions.\n * Pass options instead of a controller to create one for the component's lifetime.\n */\nexport function useAnimationEditor(controllerOrOptions: AnimationEditorController | AnimationEditorOptions = {}): UseAnimationEditorResult {\n const own = useRef<AnimationEditorController | null>(null);\n let controller: AnimationEditorController;\n if (controllerOrOptions instanceof AnimationEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new AnimationEditorController(controllerOrOptions);\n controller = own.current;\n }\n useEffect(() => () => own.current?.destroy(), []);\n const state = useAnimationEditorState(controller);\n const actions = useMemo(\n () => ({\n play: () => controller.play(),\n pause: () => controller.pause(),\n toggle: () => controller.toggle(),\n seek: (time: number) => controller.seek(time),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/**\n * Registers the animation editor's agent tools (`get_animation`, `add_commands`,\n * `export_flair_effect`, …) in `registry` while mounted.\n */\nexport function useAnimationEditorTools(\n registry: ToolRegistry | null | undefined,\n controller: AnimationEditorController,\n options: AnimationEditorToolProviderOptions = {},\n): void {\n const { id, namespace, readOnly, rasterize } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createAnimationEditorToolProvider(controller, { id, namespace, readOnly, rasterize }));\n }, [registry, controller, id, namespace, readOnly, rasterize]);\n}\n","import React, { useMemo } from 'react';\nimport { highlightMotionSvg, motionNodeAtElement, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationStageProps {\n controller: AnimationEditorController;\n /** Control values to preview (`{ accent: \"#0ea5e9\" }`). */\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel: true for every node whose place changes, or a list of ids. */\n motionPaths?: boolean | readonly string[];\n /**\n * Called when the stage is clicked, with the id of the artwork node under the pointer (the\n * innermost one; null for the background, ghosts and paths). Makes the stage pickable.\n */\n onPick?: (id: string | null, event: React.MouseEvent<HTMLDivElement>) => void;\n /** Node ids to outline (e.g. the picked element and the selected command's targets). */\n highlight?: readonly string[];\n className?: string;\n}\n\n/**\n * The animation's frame at the playhead, drawn as inline SVG scaled to the stage's width. The\n * SVG keeps the artwork's node ids, so `onPick` can say which element was clicked.\n */\nexport function AnimationStage({ controller, values, onionSkin, motionPaths, onPick, highlight, className = '' }: AnimationStageProps) {\n const state = useAnimationEditorState(controller);\n const { scene, time } = state;\n const key = highlight?.join('\\u0000') ?? '';\n const svg = useMemo(\n () =>\n highlightMotionSvg(\n controller.toSvg(time, { pretty: false, idPrefix: 'ae-', values, onionSkin, motionPaths }).replace(/<svg ([^>]*?)width=\"[^\"]*\" height=\"[^\"]*\"/, '<svg $1width=\"100%\" height=\"100%\"'),\n highlight ?? [],\n ),\n [controller, scene, time, values, onionSkin, motionPaths, key],\n );\n return (\n <div\n className={`relative overflow-hidden ${onPick ? 'cursor-crosshair' : ''} ${className}`}\n style={{ aspectRatio: `${scene.artwork.width} / ${scene.artwork.height}` }}\n data-animation-stage=\"\"\n role=\"img\"\n aria-label={`${scene.name} at ${(time / 1000).toFixed(2)} s`}\n onClick={onPick ? (e) => onPick(motionNodeAtElement(scene, e.target as Element, e.currentTarget), e) : undefined}\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n );\n}\n","import React from 'react';\nimport type { AnimationEditorController, MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotTimelineProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(1)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play / pause, the playhead and one block per shot (as wide as it is long): click a shot to\n * select it and jump to its start, click the ruler to seek. Shots with errors or warnings are marked.\n */\nexport function ShotTimeline({ controller, className = '' }: ShotTimelineProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues } = state;\n const span = Math.max(1, duration);\n const onRuler = (event: React.PointerEvent<HTMLDivElement>) => {\n const box = event.currentTarget.getBoundingClientRect();\n controller.seek(((event.clientX - box.left) / Math.max(1, box.width)) * span);\n };\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <span className=\"tabular-nums text-muted-foreground\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div className=\"relative h-3 cursor-pointer rounded bg-muted\" onPointerDown={onRuler} role=\"slider\" aria-label=\"Playhead\" aria-valuemin={0} aria-valuemax={duration} aria-valuenow={Math.round(time)} tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') controller.seek(time + 100);\n if (e.key === 'ArrowLeft') controller.seek(time - 100);\n }}>\n <div className=\"absolute inset-y-0 w-0.5 bg-rose-500\" style={{ left: `${(time / span) * 100}%` }} />\n </div>\n <div className=\"flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot) => {\n const mark = worst(issues.filter((i) => i.shot === shot.id));\n const selected = selection?.shot === shot.id;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.end - shot.start)}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { indexMotionNodes, motionIssueLine, type AnimationEditorController, type MotionFrameOptions, type MotionOnionSkin } from '@pixerate/editor/animation-editor';\nimport { AnimationStage } from './AnimationStage';\nimport { CommandInspector } from './CommandInspector';\nimport { CommandList } from './CommandList';\nimport { PlayheadScrubber } from './PlayheadScrubber';\nimport { SceneSettings } from './SceneSettings';\nimport { ShotInspector } from './ShotInspector';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface AnimationEditorProps {\n controller: AnimationEditorController;\n values?: MotionFrameOptions['values'];\n /** Faded frames either side of the playhead (see `<AnimationStage onionSkin>`). Default: an Onion skin toggle. */\n onionSkin?: MotionOnionSkin;\n /** Draw where nodes travel (see `<AnimationStage motionPaths>`). Default: a Motion paths toggle. */\n motionPaths?: boolean | readonly string[];\n /** List the scene's issues under the timeline (default true). */\n showIssues?: boolean;\n /**\n * Show the hand-editing panels: the command list and inspector, the shot inspector, scene\n * settings, undo / redo and picking on the stage (default true). False shows the stage,\n * scrubber and issues only.\n */\n editable?: boolean;\n className?: string;\n}\n\nconst ONION: MotionOnionSkin = { before: 3, after: 1 };\nconst btn = 'rounded border border-border px-2 py-0.5 text-xs disabled:opacity-40';\n\n/**\n * A whole animation editor for an `AnimationEditorController`: the stage (click an element to\n * pick it, shift-click to add it to or remove it from the selected command's targets), the\n * playhead scrubber, and panels to edit commands, shots and scene settings by hand. Every edit\n * is one undo step.\n */\nexport function AnimationEditor({ controller, values, onionSkin, motionPaths, showIssues = true, editable = true, className = '' }: AnimationEditorProps) {\n const state = useAnimationEditorState(controller);\n const { issues, scene, selection, readOnly } = state;\n const [picked, setPicked] = useState<string | null>(null);\n const [onion, setOnion] = useState(false);\n const [paths, setPaths] = useState(false);\n const command = selection?.command !== undefined ? scene.shots.find((s) => s.id === selection.shot)?.run[selection.command] : undefined;\n const targets = command && 'targets' in command ? command.targets : [];\n const nodes = useMemo(() => indexMotionNodes(scene.artwork.nodes), [scene.artwork]);\n const pickedValid = picked && nodes.has(picked) ? picked : null;\n const onPick = (id: string | null, event: { shiftKey: boolean }) => {\n if (event.shiftKey && id && command && 'targets' in command && selection?.command !== undefined && !readOnly) {\n const next = targets.includes(id) ? targets.filter((t) => t !== id) : [...targets, id];\n if (next.length) controller.apply({ op: 'update_command', shot: selection.shot, command: selection.command, set: { targets: next } }, next.length > targets.length ? 'Add target' : 'Remove target');\n return;\n }\n setPicked(id);\n };\n const stage = (\n <AnimationStage\n controller={controller}\n values={values}\n onionSkin={onionSkin ?? (onion ? ONION : undefined)}\n motionPaths={motionPaths ?? paths}\n onPick={editable ? onPick : undefined}\n highlight={editable ? [...(pickedValid ? [pickedValid] : []), ...targets] : undefined}\n className=\"rounded-md border border-border bg-muted/40\"\n />\n );\n const issueList = showIssues && issues.length > 0 && (\n <ul className=\"space-y-0.5 text-xs\" aria-label=\"Animation issues\">\n {issues.map((issue, i) => (\n <li key={i} className={issue.severity === 'error' ? 'text-red-500' : issue.severity === 'warning' ? 'text-amber-500' : 'text-muted-foreground'}>\n {motionIssueLine(issue)}\n </li>\n ))}\n </ul>\n );\n if (!editable)\n return (\n <div className={`flex flex-col gap-2 ${className}`} data-animation-editor=\"\">\n {stage}\n <PlayheadScrubber controller={controller} />\n {issueList}\n </div>\n );\n\n return (\n <div\n className={`grid gap-3 lg:grid-cols-[minmax(0,1fr)_20rem] ${className}`}\n data-animation-editor=\"\"\n onKeyDown={(e) => {\n const el = e.target as HTMLElement;\n if (!(e.metaKey || e.ctrlKey) || e.key.toLowerCase() !== 'z' || /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName)) return;\n e.preventDefault();\n if (e.shiftKey) controller.redo();\n else controller.undo();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-2\">\n {stage}\n <PlayheadScrubber controller={controller} />\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-muted-foreground\">\n <button type=\"button\" className={btn} onClick={() => controller.undo()} disabled={!state.canUndo} title={state.canUndo ? `Undo ${state.undoLabel}` : 'Nothing to undo'} data-undo=\"\">\n Undo\n </button>\n <button type=\"button\" className={btn} onClick={() => controller.redo()} disabled={!state.canRedo} title={state.canRedo ? `Redo ${state.redoLabel}` : 'Nothing to redo'} data-redo=\"\">\n Redo\n </button>\n {onionSkin === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={onion} onChange={(e) => setOnion(e.target.checked)} /> Onion skin\n </label>\n )}\n {motionPaths === undefined && (\n <label className=\"flex items-center gap-1\">\n <input type=\"checkbox\" checked={paths} onChange={(e) => setPaths(e.target.checked)} /> Motion paths\n </label>\n )}\n <span className=\"ml-auto\" data-picked-element={pickedValid ?? undefined}>\n {pickedValid ? (\n <>\n Picked <code className=\"text-rose-500\">{pickedValid}</code>{' '}\n <button type=\"button\" className=\"underline\" onClick={() => setPicked(null)}>\n clear\n </button>\n </>\n ) : (\n 'Click the stage to pick an element; shift-click to toggle it as a target.'\n )}\n </span>\n </div>\n {issueList}\n </div>\n <div className=\"flex min-w-0 flex-col gap-3\">\n <CommandList controller={controller} targets={pickedValid ? [pickedValid] : undefined} />\n <CommandInspector controller={controller} picked={pickedValid} className=\"border-t border-border pt-2\" />\n <details open className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Shot</summary>\n <ShotInspector controller={controller} className=\"mt-1\" />\n </details>\n <details className=\"border-t border-border pt-2\">\n <summary className=\"cursor-pointer text-xs font-medium\">Scene settings</summary>\n <SceneSettings controller={controller} className=\"mt-1\" />\n </details>\n </div>\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport {\n describeMotionElements,\n motionCommandFields,\n motionFieldEdit,\n motionFlairPrimitive,\n type AnimationEditorController,\n type MotionFieldSpec,\n} from '@pixerate/editor/animation-editor';\nimport { EasePicker } from './EasePicker';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandInspectorProps {\n controller: AnimationEditorController;\n /** An element picked on the stage, offered as a target to add. */\n picked?: string | null;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\n\n\n/**\n * A form for the selected command, generated from `MOTION_COMMAND_SCHEMA` (the schema the\n * agent tools take): enums as selects, numbers with their units and limits, node pickers for\n * targets and for `into` / `path`, and an ease picker. Shows the Flair primitive it plays.\n */\nexport function CommandInspector({ controller, picked, className = '' }: CommandInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const shot = selection ? scene.shots.find((s) => s.id === selection.shot) : undefined;\n const index = selection?.command;\n const command = shot && index !== undefined ? shot.run[index] : undefined;\n if (!shot || index === undefined || !command) {\n return (\n <div className={`text-xs text-muted-foreground ${className}`} data-command-inspector=\"\">\n Select a command to edit it.\n </div>\n );\n }\n const values = command as unknown as Record<string, unknown>;\n const fields = motionCommandFields(command.type);\n const primitive = motionFlairPrimitive(command);\n const commit = (field: MotionFieldSpec, raw: Parameters<typeof motionFieldEdit>[3]) => {\n const edit = motionFieldEdit(shot.id, index, field, raw);\n if ('error' in edit) return setLocal(edit.error);\n setLocal(null);\n controller.apply(edit, `Set ${field.label.toLowerCase()}`);\n };\n const name = (id: string) => elements.find((e) => e.id === id)?.name ?? id;\n const targets = (values.targets as string[] | undefined) ?? [];\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n const control = (field: MotionFieldSpec) => {\n const v = values[field.name];\n const common = { disabled: readOnly, 'aria-label': field.label, title: field.description };\n switch (field.kind) {\n case 'targets':\n return (\n <div className=\"flex flex-wrap items-center gap-1\" data-targets=\"\">\n {targets.map((id) => (\n <span key={id} className=\"flex items-center gap-0.5 rounded bg-muted px-1 text-[11px]\" data-target={id}>\n {name(id)}\n {!readOnly && targets.length > 1 && (\n <button type=\"button\" aria-label={`Remove ${id}`} onClick={() => commit(field, targets.filter((t) => t !== id))}>\n ×\n </button>\n )}\n </span>\n ))}\n {!readOnly && picked && !targets.includes(picked) && (\n <button type=\"button\" className=\"rounded border border-rose-500 px-1 text-[11px] text-rose-500\" onClick={() => commit(field, [...targets, picked])} data-add-picked=\"\">\n + {name(picked)}\n </button>\n )}\n {!readOnly && (\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\" aria-label=\"Add target\" value=\"\" onChange={(e) => e.target.value && commit(field, [...targets, e.target.value])}>\n <option value=\"\">+ target…</option>\n {elements.filter((e) => !targets.includes(e.id)).map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n </option>\n ))}\n </select>\n )}\n </div>\n );\n case 'node':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">—</option>}\n {elements.filter((e) => field.name !== 'path' || e.type === 'path').map((e) => (\n <option key={e.id} value={e.id}>\n {e.name ? `${e.name} (${e.id})` : e.id}\n {e.hidden ? ' · hidden' : ''}\n </option>\n ))}\n </select>\n );\n case 'enum':\n return (\n <select className={input} {...common} value={typeof v === 'string' ? v : ''} onChange={(e) => commit(field, e.target.value)}>\n {!field.required && <option value=\"\">default</option>}\n {field.options!.map((o) => (\n <option key={o} value={o}>\n {o}\n </option>\n ))}\n </select>\n );\n case 'boolean':\n return <input type=\"checkbox\" {...common} checked={v === true} onChange={(e) => commit(field, e.target.checked)} />;\n case 'ease':\n return <EasePicker value={v as never} disabled={readOnly} onChange={(ease) => commit(field, ease === undefined ? '' : (ease as string))} />;\n case 'color':\n return (\n <div className=\"flex items-center gap-1\">\n <input type=\"color\" disabled={readOnly} aria-label={`${field.label} swatch`} value={typeof v === 'string' && /^#[0-9a-f]{6}$/i.test(v) ? v : '#000000'} onChange={(e) => commit(field, e.target.value)} />\n <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} placeholder=\"unchanged\" onCommit={(raw) => commit(field, raw)} />\n </div>\n );\n case 'point': {\n const p = (v as { x: number; y: number } | undefined) ?? undefined;\n return (\n <div className=\"flex items-center gap-1\">\n {(['x', 'y'] as const).map((axis) => (\n <CommitInput\n key={axis}\n className={input}\n type=\"number\"\n disabled={readOnly}\n aria-label={`${field.label} ${axis}`}\n placeholder={axis}\n value={p ? String(p[axis]) : ''}\n onCommit={(raw) => commit(field, axis === 'x' ? { x: raw, y: p ? String(p.y) : raw ? '0' : '' } : { x: p ? String(p.x) : raw ? '0' : '', y: raw })}\n />\n ))}\n </div>\n );\n }\n case 'scale':\n case 'number':\n case 'integer':\n return (\n <div className=\"flex items-center gap-1\">\n <CommitInput\n className={input}\n type=\"number\"\n {...common}\n min={field.min}\n max={field.max}\n step={field.kind === 'integer' ? 1 : field.unit === 'ms' ? 50 : field.unit === '0–1' ? 0.05 : 'any'}\n placeholder=\"default\"\n value={typeof v === 'number' ? String(v) : ''}\n onCommit={(raw) => commit(field, raw)}\n />\n {field.unit && <span className=\"shrink-0 text-[10px] text-muted-foreground\">{field.unit}</span>}\n </div>\n );\n default:\n return <CommitInput className={input} {...common} value={typeof v === 'string' ? v : ''} onCommit={(raw) => commit(field, raw)} />;\n }\n };\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-command-inspector=\"\" data-command-type={command.type}>\n <div className=\"flex items-center gap-2\">\n <span className=\"font-medium\">\n {index + 1}. {command.type}\n </span>\n {primitive ? (\n <code className=\"rounded bg-muted px-1 text-[10px]\" data-flair-primitive={primitive} title=\"The Flair motion primitive this command plays\">\n {primitive}\n </code>\n ) : (\n <span className=\"text-[10px] text-muted-foreground\">editor-only (no Flair primitive)</span>\n )}\n </div>\n {(['main', 'timing'] as const).map((group) => (\n <fieldset key={group} className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <legend className=\"mb-1 text-[10px] uppercase tracking-wide text-muted-foreground\">{group === 'main' ? 'Command' : 'Timing'}</legend>\n {fields\n .filter((f) => f.group === group)\n .map((field) => (\n <React.Fragment key={field.name}>\n <label className=\"truncate text-muted-foreground\" title={field.description}>\n {field.label}\n {field.required ? ' *' : ''}\n </label>\n <div data-field={field.name}>{control(field)}</div>\n </React.Fragment>\n ))}\n </fieldset>\n ))}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo } from 'react';\nimport { MOTION_EASE_CHOICES, motionEaseKey, motionEasingCurve, motionEasingGuides, motionEasingPath, type MotionCommandBase } from '@pixerate/editor/animation-editor';\n\n/** An easing (a preset name or a curve), as commands take it. */\ntype AnimationEasing = NonNullable<MotionCommandBase['ease']>;\n\nexport interface EasePickerProps {\n /** The easing (undefined: the command type's default). */\n value: AnimationEasing | undefined;\n /** Called with the picked preset, or undefined for the default. */\n onChange: (ease: AnimationEasing | undefined) => void;\n disabled?: boolean;\n className?: string;\n}\n\nconst W = 72;\nconst H = 44;\n\n/**\n * Picks an easing preset (springs included) and previews its curve, drawn by sampling\n * `evaluateEasing`; a spring is drawn over the time it takes to settle, overshoot included.\n */\nexport function EasePicker({ value, onChange, disabled, className = '' }: EasePickerProps) {\n const key = motionEaseKey(value);\n const curve = useMemo(() => motionEasingCurve(value ?? 'ease-out'), [value]);\n const guides = motionEasingGuides(curve, H);\n const spring = typeof value === 'string' ? value.startsWith('spring') : value?.type === 'spring';\n return (\n <div className={`flex items-center gap-2 ${className}`} data-ease-picker=\"\">\n <select\n className=\"min-w-0 flex-1 rounded border border-border bg-transparent px-1 py-0.5 text-xs\"\n aria-label=\"Ease\"\n value={key}\n disabled={disabled}\n onChange={(e) => {\n if (e.target.value === 'custom') return;\n onChange(e.target.value ? (e.target.value as AnimationEasing) : undefined);\n }}\n >\n {MOTION_EASE_CHOICES.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n {key === 'custom' && <option value=\"custom\">Custom</option>}\n </select>\n <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`} className=\"shrink-0 rounded border border-border\" data-ease-curve={key || 'default'} aria-hidden=\"true\">\n <line x1={0} x2={W} y1={guides.zero} y2={guides.zero} stroke=\"currentColor\" strokeOpacity={0.2} />\n <line x1={0} x2={W} y1={guides.one} y2={guides.one} stroke=\"currentColor\" strokeOpacity={0.2} strokeDasharray=\"2 2\" />\n <path d={motionEasingPath(curve, W, H)} fill=\"none\" stroke=\"#f43f5e\" strokeWidth={1.5} />\n </svg>\n {spring && <span className=\"text-[10px] tabular-nums text-muted-foreground\">{Math.round(curve.durationMs)} ms</span>}\n </div>\n );\n}\n","import React from 'react';\n\n/** An input that commits on blur or Enter, and resets when its value changes from outside. */\nexport function CommitInput({ value, onCommit, ...rest }: { value: string; onCommit: (raw: string) => void } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue'>) {\n return (\n <input\n key={value}\n {...rest}\n defaultValue={value}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n if (e.currentTarget.value !== value) onCommit(e.currentTarget.value);\n }}\n />\n );\n}\n","import React, { useState } from 'react';\nimport {\n MOTION_COMMAND_TYPES,\n defaultMotionCommand,\n duplicateMotionCommandEdit,\n motionCommandRows,\n type AnimationEditorController,\n type MotionCommandType,\n} from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface CommandListProps {\n controller: AnimationEditorController;\n /** The shot to list (default: the selected shot, else the first). */\n shot?: string;\n /** Targets for a new command (e.g. the element picked on the stage); default: the selected command's. */\n targets?: readonly string[];\n className?: string;\n}\n\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n/**\n * A shot's commands in order: select one to inspect it, change `with` and `delay` inline, move,\n * duplicate or delete it, and add new ones. Each change is one `controller.apply` edit (one undo\n * step); a refused edit shows its reason.\n */\nexport function CommandList({ controller, shot, targets, className = '' }: CommandListProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const shotId = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const current = scene.shots.find((s) => s.id === shotId);\n const [type, setType] = useState<MotionCommandType>('enter');\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n if (!current) return <div className={`text-xs text-muted-foreground ${className}`} data-command-list=\"\">Add a shot to start.</div>;\n const rows = motionCommandRows(scene, current.id);\n const selected = selection?.shot === current.id ? selection.command : undefined;\n const run = (edit: Parameters<AnimationEditorController['apply']>[0], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const add = () => {\n const from = targets?.length ? targets : selected !== undefined ? ((current.run[selected] as { targets?: string[] }).targets ?? []) : [];\n const command = defaultMotionCommand(type, from, scene);\n if ('error' in command) return setLocal(command.error);\n const at = selected !== undefined ? selected + 1 : current.run.length;\n const result = run({ op: 'add_commands', shot: current.id, commands: [command], at }, `Add ${type}`);\n if (result.ok) controller.select({ shot: current.id, command: at });\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1 text-xs ${className}`} data-command-list=\"\" data-for-shot={current.id}>\n <div className=\"font-medium\">\n Commands in <span className=\"text-rose-500\">{current.label ?? current.id}</span>\n </div>\n <ol className=\"flex flex-col gap-1\" aria-label=\"Commands\">\n {rows.map((row) => {\n const c = row.command as { with?: string; delay?: number };\n const isSelected = row.index === selected;\n return (\n <li\n key={`${row.index}:${row.summary}`}\n className={`flex flex-wrap items-center gap-1 rounded border px-1.5 py-1 ${isSelected ? 'border-rose-500 bg-rose-500/10' : 'border-border'}`}\n data-command={row.index}\n data-selected={isSelected || undefined}\n onClick={() => controller.select({ shot: current.id, command: row.index })}\n >\n <span className=\"min-w-0 flex-1 truncate\" title={row.summary}>\n {row.index + 1}. {row.summary}\n </span>\n {row.flairPrimitive && (\n <code className=\"rounded bg-muted px-1 text-[10px] text-muted-foreground\" data-flair-primitive={row.flairPrimitive}>\n {row.flairPrimitive}\n </code>\n )}\n <span className=\"tabular-nums text-[10px] text-muted-foreground\">{((row.end - row.start) / 1000).toFixed(2)} s</span>\n <div className=\"flex w-full items-center gap-1\" onClick={(e) => e.stopPropagation()}>\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5 text-[11px]\"\n aria-label=\"Starts\"\n value={c.with ?? 'after'}\n disabled={readOnly || row.index === 0}\n onChange={(e) =>\n run(\n e.target.value === 'after' ? { op: 'update_command', shot: current.id, command: row.index, remove: ['with'] } : { op: 'update_command', shot: current.id, command: row.index, set: { with: e.target.value } },\n 'Change start',\n )\n }\n >\n <option value=\"after\">after previous</option>\n <option value=\"previous\">with previous</option>\n </select>\n <label className=\"flex items-center gap-0.5 text-muted-foreground\">\n +\n <input\n key={String(c.delay ?? '')}\n className=\"w-14 rounded border border-border bg-transparent px-1 py-0.5 text-[11px] tabular-nums\"\n type=\"number\"\n min={0}\n step={50}\n aria-label=\"Delay\"\n placeholder=\"0\"\n defaultValue={c.delay ?? ''}\n disabled={readOnly}\n onKeyDown={(e) => e.key === 'Enter' && e.currentTarget.blur()}\n onBlur={(e) => {\n const raw = e.currentTarget.value.trim();\n if (raw === String(c.delay ?? '')) return;\n const n = Number(raw);\n if (raw && !(Number.isFinite(n) && n >= 0)) return setLocal('Delay must be a number of ms, 0 or more.');\n run(raw && n > 0 ? { op: 'update_command', shot: current.id, command: row.index, set: { delay: n } } : { op: 'update_command', shot: current.id, command: row.index, remove: ['delay'] }, 'Change delay');\n }}\n />\n ms\n </label>\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} aria-label=\"Move up\" disabled={readOnly || row.index === 0} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index - 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index - 1 })}>\n ↑\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move down\" disabled={readOnly || row.index === rows.length - 1} onClick={() => run({ op: 'move_command', shot: current.id, command: row.index, to: row.index + 1 }, 'Move command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ↓\n </button>\n <button type=\"button\" className={btn} aria-label=\"Duplicate\" disabled={readOnly} onClick={() => run(duplicateMotionCommandEdit(scene, current.id, row.index), 'Duplicate command').ok && controller.select({ shot: current.id, command: row.index + 1 })}>\n ⧉\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete\" disabled={readOnly} onClick={() => run({ op: 'delete_commands', shot: current.id, commands: [row.index] }, 'Delete command')}>\n ✕\n </button>\n </span>\n </div>\n </li>\n );\n })}\n </ol>\n {!readOnly && (\n <div className=\"flex items-center gap-1\">\n <select className=\"flex-1 rounded border border-border bg-transparent px-1 py-0.5\" aria-label=\"New command type\" value={type} onChange={(e) => setType(e.target.value as MotionCommandType)}>\n {MOTION_COMMAND_TYPES.map((t) => (\n <option key={t} value={t}>\n {t}\n </option>\n ))}\n </select>\n <button type=\"button\" className={btn} onClick={add} data-add-command=\"\">\n Add command\n </button>\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { motionBeatTime, motionCueTime, motionRulerTicks, type AnimationEditorController, type MotionIssue } from '@pixerate/editor/animation-editor';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface PlayheadScrubberProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst seconds = (ms: number) => `${(ms / 1000).toFixed(2)} s`;\n\nfunction worst(issues: readonly MotionIssue[]): 'error' | 'warning' | null {\n if (issues.some((i) => i.severity === 'error')) return 'error';\n if (issues.some((i) => i.severity === 'warning')) return 'warning';\n return null;\n}\n\n/**\n * Play, pause and loop, a time ruler (with the beat grid and narration words when the scene has\n * them) to scrub by dragging, and one band per shot (as wide as it is long): click a band to\n * select the shot and jump to its start. Loop is a scene setting, so changing it is one undo step.\n */\nexport function PlayheadScrubber({ controller, className = '' }: PlayheadScrubberProps) {\n const state = useAnimationEditorState(controller);\n const { duration, shots, time, playing, selection, issues, scene, readOnly } = state;\n const span = Math.max(1, duration);\n const track = useRef<HTMLDivElement>(null);\n const [width, setWidth] = useState(600);\n useEffect(() => {\n const el = track.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => setWidth(el.clientWidth || 600));\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n const ticks = motionRulerTicks(duration, width);\n const pct = (ms: number) => `${(Math.min(span, Math.max(0, ms)) / span) * 100}%`;\n const seekAt = (clientX: number) => {\n const box = track.current!.getBoundingClientRect();\n controller.seek(Math.min(1, Math.max(0, (clientX - box.left) / Math.max(1, box.width))) * span);\n };\n const beats: number[] = [];\n if (scene.beat && scene.beat.bpm > 0) for (let b = 0, t = motionBeatTime(scene.beat, 0); t <= span && beats.length < 400; t = motionBeatTime(scene.beat, ++b)) if (t >= 0) beats.push(t);\n\n return (\n <div className={`flex flex-col gap-1 ${className}`} data-playhead-scrubber=\"\" data-shot-timeline=\"\">\n <div className=\"flex items-center gap-2 text-xs\">\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => controller.toggle()} aria-label={playing ? 'Pause' : 'Play'} disabled={!shots.length}>\n {playing ? 'Pause' : 'Play'}\n </button>\n <button type=\"button\" className=\"rounded border border-border px-2 py-0.5\" onClick={() => { controller.pause(); controller.seek(0); }} aria-label=\"Back to start\">\n ⏮\n </button>\n <label className=\"flex items-center gap-1 text-muted-foreground\">\n Loop\n <select\n className=\"rounded border border-border bg-transparent px-1 py-0.5\"\n value={scene.loop ?? 'none'}\n disabled={readOnly}\n aria-label=\"Loop\"\n onChange={(e) => controller.apply({ op: 'set_settings', loop: e.target.value as 'none' | 'loop' | 'ping-pong' }, 'Change loop')}\n >\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n </label>\n <span className=\"ml-auto tabular-nums text-muted-foreground\" data-time=\"\">\n {seconds(time)} / {seconds(duration)}\n </span>\n </div>\n <div\n ref={track}\n className=\"relative cursor-ew-resize select-none touch-none\"\n role=\"slider\"\n aria-label=\"Playhead\"\n aria-valuemin={0}\n aria-valuemax={duration}\n aria-valuenow={Math.round(time)}\n tabIndex={0}\n data-scrub-track=\"\"\n onPointerDown={(e) => {\n e.currentTarget.setPointerCapture?.(e.pointerId);\n seekAt(e.clientX);\n }}\n onPointerMove={(e) => {\n if (e.buttons & 1) seekAt(e.clientX);\n }}\n onKeyDown={(e) => {\n const step = e.shiftKey ? 1000 : 100;\n if (e.key === 'ArrowRight') controller.seek(time + step);\n else if (e.key === 'ArrowLeft') controller.seek(time - step);\n else if (e.key === 'Home') controller.seek(0);\n else if (e.key === 'End') controller.seek(duration);\n else if (e.key === ' ') controller.toggle();\n else return;\n e.preventDefault();\n }}\n >\n <div className=\"relative h-5 border-b border-border text-[10px] text-muted-foreground\" data-ruler=\"\">\n {beats.map((t, i) => (\n <div key={`b${i}`} className=\"absolute bottom-0 h-1.5 w-px bg-sky-500/60\" style={{ left: pct(t) }} data-beat={i} />\n ))}\n {scene.narration?.words.map((w, i) => (\n <div key={`w${i}`} className=\"absolute top-0 h-1.5 w-px bg-emerald-500/70\" style={{ left: pct(w.start) }} title={`“${w.text}” at ${seconds(w.start)}`} data-word={i} />\n ))}\n {ticks.map((t) => (\n <div key={t.time} className={`absolute bottom-0 w-px ${t.major ? 'h-2.5 bg-muted-foreground/70' : 'h-1 bg-muted-foreground/40'}`} style={{ left: pct(t.time) }}>\n {t.label && <span className=\"absolute -top-0.5 left-1 whitespace-nowrap tabular-nums\">{t.label}</span>}\n </div>\n ))}\n </div>\n <div className=\"mt-1 flex w-full gap-px\" role=\"group\" aria-label=\"Shots\">\n {shots.map((shot, i) => {\n const mark = worst(issues.filter((x) => x.shot === shot.id));\n const selected = selection?.shot === shot.id;\n const cue = scene.shots[i]?.at;\n const cueTime = cue ? motionCueTime(scene, cue) : undefined;\n return (\n <button\n key={shot.id}\n type=\"button\"\n className={`relative min-w-0 truncate rounded border px-1 py-1 text-left text-[11px] ${selected ? 'border-rose-500 bg-rose-500/10' : 'border-border bg-muted/40'} ${state.currentShot === shot.id ? 'font-semibold' : ''}`}\n style={{ flexGrow: Math.max(1, shot.end - shot.start), flexBasis: 0 }}\n title={`${shot.label ?? shot.id} · ${seconds(shot.start)}–${seconds(shot.end)}${cueTime !== undefined ? ` · cued at ${seconds(cueTime)}` : ''}`}\n data-shot={shot.id}\n data-issue={mark ?? undefined}\n onPointerDown={(e) => e.stopPropagation()}\n onClick={() => {\n controller.select({ shot: shot.id });\n controller.seekShot(shot.id);\n }}\n >\n {mark && <span className={mark === 'error' ? 'text-red-500' : 'text-amber-500'}>● </span>}\n {shot.label ?? shot.id}\n </button>\n );\n })}\n </div>\n <div className=\"pointer-events-none absolute inset-y-0 w-0.5 -translate-x-1/2 bg-rose-500\" style={{ left: pct(time) }} data-playhead=\"\" />\n </div>\n </div>\n );\n}\n","import React, { useState } from 'react';\nimport { fitMotionSceneEdits, formatMotionDrivers, formatMotionNarration, parseMotionDrivers, parseMotionNarration, type AnimationEditorController, type MotionEdit, type MotionTrigger } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface SceneSettingsProps {\n controller: AnimationEditorController;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\nconst unit = (u: string) => <span className=\"shrink-0 text-[10px] text-muted-foreground\">{u}</span>;\n\n/**\n * Scene settings: loop, frame rate, stepped time, the wanted length with a Fit button (sets the\n * shots' speeds with `fitMotionScene`, as `fit_animation` does), a beat grid and narration words\n * to cue shots to. Every change is one undo step; refusals show their reason.\n */\nexport function SceneSettings({ controller, className = '' }: SceneSettingsProps) {\n const state = useAnimationEditorState(controller);\n const { scene, readOnly, error, duration } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const [fitTo, setFitTo] = useState<string>('');\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const settings = (set: Omit<Extract<MotionEdit, { op: 'set_settings' }>, 'op'>, label: string) => apply({ op: 'set_settings', ...set }, label);\n const num = (raw: string, what: string, ok: (n: number) => boolean, then: (n: number | null) => void) => {\n if (raw.trim() === '') return then(null);\n const n = Number(raw);\n if (!Number.isFinite(n) || !ok(n)) return setLocal(what);\n then(n);\n };\n const target = scene.target;\n const fitSeconds = fitTo || String(target ? (target[0] + target[1]) / 2 : Math.round(duration / 100) / 10);\n const fit = () => {\n const s = Number(fitSeconds);\n if (!(Number.isFinite(s) && s > 0)) return setLocal('Give the length to fit in seconds, above 0.');\n try {\n const edits = fitMotionSceneEdits(scene, s * 1000);\n if (edits.length) apply(edits, `Fit to ${s} s`);\n else setLocal(null);\n } catch (e) {\n setLocal((e as Error).message);\n }\n };\n const beat = scene.beat;\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-scene-settings=\"\">\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Loop</label>\n <select className={input} aria-label=\"Scene loop\" disabled={readOnly} value={scene.loop ?? 'none'} onChange={(e) => settings({ loop: e.target.value as 'none' }, 'Change loop')}>\n <option value=\"none\">Off</option>\n <option value=\"loop\">Loop</option>\n <option value=\"ping-pong\">Ping-pong</option>\n </select>\n <label className=\"text-muted-foreground\">Motion blur</label>\n <select className={input} aria-label=\"Motion blur\" disabled={readOnly} value={scene.motionBlur ? String(scene.motionBlur.shutter ?? 180) : ''} onChange={(e) => settings({ motionBlur: e.target.value ? { ...(scene.motionBlur ?? {}), shutter: Number(e.target.value) } : null }, 'Change motion blur')}>\n <option value=\"\">Off</option>\n <option value=\"90\">Light (90°)</option>\n <option value=\"180\">Normal (180°)</option>\n <option value=\"360\">Heavy (360°)</option>\n </select>\n <label className=\"text-muted-foreground\">Plays on</label>\n <select className={input} aria-label=\"Scene trigger\" title=\"How a viewer plays it when exported to Flair\" disabled={readOnly} value={scene.trigger ?? ''} onChange={(e) => settings({ trigger: (e.target.value || null) as MotionTrigger | null }, 'Change trigger')}>\n <option value=\"\">Its own (autoplay)</option>\n <option value=\"click\">Click (a shot per click)</option>\n <option value=\"hover\">Hover</option>\n <option value=\"press\">Press</option>\n <option value=\"scroll\">Scroll</option>\n </select>\n <label className=\"text-muted-foreground\">Frame rate</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Frame rate\" placeholder=\"30\" disabled={readOnly} value={scene.fps !== undefined ? String(scene.fps) : ''}\n onCommit={(raw) => num(raw, 'Frame rate must be 1 to 120 fps.', (n) => n >= 1 && n <= 120, (n) => n !== null && settings({ fps: n }, 'Change frame rate'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\" title=\"Hold changes on a grid of this many frames a second (12 = on twos); empty is smooth\">\n Steps\n </label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={1} max={120} aria-label=\"Steps\" placeholder=\"smooth\" disabled={readOnly} value={scene.steps !== undefined ? String(scene.steps) : ''}\n onCommit={(raw) => num(raw, 'Steps must be above 0 and at most 120 fps, or empty for smooth.', (n) => n > 0 && n <= 120, (n) => settings({ steps: n }, 'Change steps'))} />\n {unit('fps')}\n </div>\n <label className=\"text-muted-foreground\">Target length</label>\n <div className=\"flex items-center gap-1\">\n {[0, 1].map((i) => (\n <CommitInput key={i} className={input} type=\"number\" min={0} step={0.5} aria-label={i ? 'Target max' : 'Target min'} placeholder={i ? 'max' : 'min'} disabled={readOnly} value={target ? String(target[i]) : ''}\n onCommit={(raw) =>\n num(raw, 'Target lengths are seconds, 0 or more.', (n) => n >= 0, (n) => {\n if (n === null) return settings({ target: null }, 'Clear target length');\n const next: [number, number] = target ? [...target] : [n, n];\n next[i] = n;\n if (next[0] > next[1]) return setLocal('The shortest target length must not be longer than the longest.');\n settings({ target: next }, 'Change target length');\n })\n } />\n ))}\n {unit('s')}\n </div>\n <label className=\"text-muted-foreground\">Fit to</label>\n <div className=\"flex items-center gap-1\">\n <input className={input} type=\"number\" min={0.1} step={0.5} aria-label=\"Fit to\" value={fitSeconds} onChange={(e) => setFitTo(e.target.value)} />\n {unit('s')}\n <button type=\"button\" className={btn} disabled={readOnly || !scene.shots.length} onClick={fit} data-fit=\"\" title=\"Change the shots' speeds so the scene lasts this long\">\n Fit\n </button>\n </div>\n <label className=\"text-muted-foreground\">Beat grid</label>\n <div className=\"flex items-center gap-1\" data-beat-grid=\"\">\n <CommitInput className={input} type=\"number\" min={1} aria-label=\"BPM\" placeholder=\"bpm\" disabled={readOnly} value={beat ? String(beat.bpm) : ''}\n onCommit={(raw) => num(raw, 'BPM must be above 0.', (n) => n > 0, (n) => settings({ beat: n === null ? null : { ...(beat ?? {}), bpm: n } }, n === null ? 'Clear beat grid' : 'Change tempo'))} />\n <CommitInput className={input} type=\"number\" aria-label=\"Beat offset\" placeholder=\"offset ms\" disabled={readOnly || !beat} value={beat?.offset !== undefined ? String(beat.offset) : ''}\n onCommit={(raw) => beat && num(raw, 'The offset is a number of ms.', () => true, (n) => settings({ beat: { ...beat, offset: n ?? 0 } }, 'Change beat offset'))} />\n <CommitInput className={input} type=\"number\" min={1} step={1} aria-label=\"Meter\" placeholder=\"4/bar\" disabled={readOnly || !beat} value={beat?.meter !== undefined ? String(beat.meter) : ''}\n onCommit={(raw) => beat && num(raw, 'The meter is a whole number of beats a bar.', (n) => Number.isInteger(n) && n >= 1, (n) => settings({ beat: { ...beat, meter: n ?? 4 } }, 'Change meter'))} />\n </div>\n </div>\n <label className=\"flex flex-col gap-0.5\">\n <span className=\"text-muted-foreground\">Narration (a word a line: start ms, then the word)</span>\n <textarea\n key={formatMotionNarration(scene.narration)}\n className={`${input} h-20 font-mono`}\n aria-label=\"Narration\"\n placeholder={'0 Meet\\n320 the\\n480 badge'}\n disabled={readOnly}\n defaultValue={formatMotionNarration(scene.narration)}\n onBlur={(e) => {\n if (e.currentTarget.value === formatMotionNarration(scene.narration)) return;\n const parsed = parseMotionNarration(e.currentTarget.value);\n if ('error' in parsed) return setLocal(parsed.error);\n settings({ narration: parsed.narration }, parsed.narration ? 'Change narration' : 'Clear narration');\n }}\n />\n </label>\n <label className=\"flex flex-col gap-0.5\">\n <span className=\"text-muted-foreground\">Drivers (one a line: target.property &lt;- source.property * factor)</span>\n <textarea\n key={formatMotionDrivers(scene.drivers)}\n className={`${input} h-14 font-mono`}\n aria-label=\"Drivers\"\n placeholder={'back.x <- front.x * 0.5\\nwheel.rotation <- wheel.x * 2.86'}\n disabled={readOnly}\n defaultValue={formatMotionDrivers(scene.drivers)}\n onBlur={(e) => {\n if (e.currentTarget.value === formatMotionDrivers(scene.drivers)) return;\n const parsed = parseMotionDrivers(e.currentTarget.value);\n if ('error' in parsed) return setLocal(parsed.error);\n apply({ op: 'set_drivers', drivers: parsed.drivers }, parsed.drivers.length ? 'Set drivers' : 'Clear drivers');\n }}\n />\n </label>\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n","import React, { useMemo, useState } from 'react';\nimport { describeMotionElements, freshShotId, motionCueChoices, motionCueFromKey, motionCueKey, type AnimationEditorController, type MotionEdit } from '@pixerate/editor/animation-editor';\nimport { CommitInput } from './CommitInput';\nimport { useAnimationEditorState } from './useAnimationEditor';\n\nexport interface ShotInspectorProps {\n controller: AnimationEditorController;\n /** The shot to edit (default: the selected shot, else the first). */\n shot?: string;\n className?: string;\n}\n\nconst input = 'w-full min-w-0 rounded border border-border bg-transparent px-1 py-0.5 text-xs';\nconst btn = 'rounded border border-border px-1.5 py-0.5 text-[11px] disabled:opacity-40';\n\n\n/**\n * The selected shot: its label, hold, speed, the node the camera frames, and the cue it starts\n * on (a beat of the scene's grid or a narration word). Also adds, moves and deletes shots.\n * Every change is one undo step.\n */\nexport function ShotInspector({ controller, shot, className = '' }: ShotInspectorProps) {\n const state = useAnimationEditorState(controller);\n const { scene, selection, readOnly, error } = state;\n const [local, setLocalState] = useState<{ text: string; revision: number } | null>(null);\n const setLocal = (text: string | null) => setLocalState(text ? { text, revision: state.revision } : null);\n const elements = useMemo(() => describeMotionElements(scene), [scene.artwork]);\n const cues = useMemo(() => motionCueChoices(scene), [scene]);\n const id = shot ?? selection?.shot ?? scene.shots[0]?.id;\n const index = scene.shots.findIndex((s) => s.id === id);\n const current = scene.shots[index];\n const apply = (edit: MotionEdit | MotionEdit[], label: string) => {\n setLocal(null);\n return controller.apply(edit, label);\n };\n const addShot = () => {\n const newId = freshShotId(scene, 'shot');\n const at = index >= 0 ? index + 1 : scene.shots.length;\n if (apply({ op: 'insert_shots', shots: [{ id: newId, label: 'New shot', run: [] }], at }, 'Add shot').ok) {\n controller.select({ shot: newId });\n controller.seekShot(newId);\n }\n };\n const number = (key: 'hold' | 'speed', raw: string, label: string) => {\n const n = Number(raw);\n if (raw.trim() === '') return apply({ op: 'update_shot', shot: current.id, remove: [key] }, label);\n if (!Number.isFinite(n) || n < 0 || (key === 'speed' && n <= 0)) return setLocal(key === 'speed' ? 'Speed must be a number above 0 (1 = as written).' : 'Hold must be a number of ms, 0 or more.');\n apply({ op: 'update_shot', shot: current.id, set: { [key]: n } }, label);\n };\n // A local error shows until the editor changes; then the editor's own error (if any) shows.\n const message = (local && local.revision === state.revision ? local.text : null) ?? error;\n const cueKey = current ? motionCueKey(current.at) : '';\n const frame = current?.camera && 'frame' in current.camera ? current.camera.frame : '';\n\n return (\n <div className={`flex flex-col gap-1.5 text-xs ${className}`} data-shot-inspector=\"\">\n <div className=\"flex items-center gap-1\">\n <span className=\"font-medium\">Shot</span>\n {current && <code className=\"text-[10px] text-muted-foreground\">{current.id}</code>}\n <span className=\"ml-auto flex gap-0.5\">\n <button type=\"button\" className={btn} disabled={readOnly} onClick={addShot} data-add-shot=\"\">\n + Shot\n </button>\n {current && (\n <>\n <button type=\"button\" className={btn} aria-label=\"Move shot earlier\" disabled={readOnly || index === 0} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index - 1 }, 'Move shot')}>\n ←\n </button>\n <button type=\"button\" className={btn} aria-label=\"Move shot later\" disabled={readOnly || index === scene.shots.length - 1} onClick={() => apply({ op: 'move_shot', shot: current.id, to: index + 1 }, 'Move shot')}>\n →\n </button>\n <button type=\"button\" className={btn} aria-label=\"Delete shot\" disabled={readOnly} onClick={() => apply({ op: 'delete_shots', shots: [current.id] }, 'Delete shot')}>\n ✕\n </button>\n </>\n )}\n </span>\n </div>\n {current && (\n <div className=\"grid grid-cols-[6.5rem_1fr] items-center gap-x-2 gap-y-1\">\n <label className=\"text-muted-foreground\">Label</label>\n <CommitInput className={input} aria-label=\"Shot label\" disabled={readOnly} value={current.label ?? ''} onCommit={(raw) => apply(raw.trim() ? { op: 'update_shot', shot: current.id, set: { label: raw.trim() } } : { op: 'update_shot', shot: current.id, remove: ['label'] }, 'Rename shot')} />\n <label className=\"text-muted-foreground\">Hold</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0} step={50} aria-label=\"Hold\" placeholder=\"600\" disabled={readOnly} value={current.hold !== undefined ? String(current.hold) : ''} onCommit={(raw) => number('hold', raw, 'Change hold')} />\n <span className=\"text-[10px] text-muted-foreground\">ms</span>\n </div>\n <label className=\"text-muted-foreground\">Speed</label>\n <div className=\"flex items-center gap-1\">\n <CommitInput className={input} type=\"number\" min={0.05} step={0.05} aria-label=\"Speed\" placeholder=\"1\" disabled={readOnly} value={current.speed !== undefined ? String(current.speed) : ''} onCommit={(raw) => number('speed', raw, 'Change speed')} />\n <span className=\"text-[10px] text-muted-foreground\">×</span>\n </div>\n <label className=\"text-muted-foreground\">Camera</label>\n <select\n className={input}\n aria-label=\"Camera frames\"\n disabled={readOnly}\n value={current.camera ? (frame ? `frame:${frame}` : 'rect') : ''}\n onChange={(e) => {\n const v = e.target.value;\n if (!v) apply({ op: 'update_shot', shot: current.id, remove: ['camera'] }, 'Clear camera');\n else if (v.startsWith('frame:')) apply({ op: 'update_shot', shot: current.id, set: { camera: { frame: v.slice(6), padding: 24 } } }, 'Frame camera');\n }}\n >\n <option value=\"\">keep framing</option>\n {current.camera && !frame && <option value=\"rect\">a rectangle</option>}\n {elements.map((e) => (\n <option key={e.id} value={`frame:${e.id}`}>\n frame {e.name ?? e.id}\n </option>\n ))}\n </select>\n <label className=\"text-muted-foreground\">Starts on</label>\n <select\n className={input}\n aria-label=\"Cue\"\n disabled={readOnly || index === 0}\n value={cueKey}\n onChange={(e) => {\n const cue = motionCueFromKey(e.target.value);\n apply(cue ? { op: 'update_shot', shot: current.id, set: { at: cue } } : { op: 'update_shot', shot: current.id, remove: ['at'] }, 'Cue shot');\n }}\n >\n <option value=\"\">after the shot before</option>\n {cueKey && !cues.some((c) => c.value === cueKey) && <option value={cueKey}>{cueKey}</option>}\n {cues.map((c) => (\n <option key={c.value} value={c.value}>\n {c.label}\n </option>\n ))}\n </select>\n {!cues.length && index > 0 && <p className=\"col-span-2 text-[10px] text-muted-foreground\">Add a beat grid or narration in the scene settings to cue shots to them.</p>}\n </div>\n )}\n {message && (\n <p className=\"text-red-500\" role=\"alert\" data-edit-error=\"\">\n {message}\n </p>\n )}\n </div>\n );\n}\n"],"mappings":";AAAA,SAAS,WAAW,SAAS,QAAQ,4BAA4B;AACjE;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAIA,SAAS,6BAA6B,UAAkC,CAAC,GAA8B;AAC5G,QAAM,MAAM,OAAyC,IAAI;AACzD,MAAI,CAAC,IAAI,QAAS,KAAI,UAAU,IAAI,0BAA0B,OAAO;AACrE,QAAM,aAAa,IAAI;AACvB,YAAU,MAAM,MAAM,WAAW,QAAQ,GAAG,CAAC,UAAU,CAAC;AACxD,SAAO;AACT;AAGO,SAAS,wBAAwB,YAA6D;AACnG,SAAO,qBAAqB,WAAW,WAAW,WAAW,UAAU,WAAW,QAAQ;AAC5F;AAmBO,SAAS,mBAAmB,sBAA0E,CAAC,GAA6B;AACzI,QAAM,MAAM,OAAyC,IAAI;AACzD,MAAI;AACJ,MAAI,+BAA+B,0BAA2B,cAAa;AAAA,OACtE;AACH,QAAI,CAAC,IAAI,QAAS,KAAI,UAAU,IAAI,0BAA0B,mBAAmB;AACjF,iBAAa,IAAI;AAAA,EACnB;AACA,YAAU,MAAM,MAAM,IAAI,SAAS,QAAQ,GAAG,CAAC,CAAC;AAChD,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,UAAU;AAAA,IACd,OAAO;AAAA,MACL,MAAM,MAAM,WAAW,KAAK;AAAA,MAC5B,OAAO,MAAM,WAAW,MAAM;AAAA,MAC9B,QAAQ,MAAM,WAAW,OAAO;AAAA,MAChC,MAAM,CAAC,SAAiB,WAAW,KAAK,IAAI;AAAA,MAC5C,MAAM,MAAM,KAAK,WAAW,KAAK;AAAA,MACjC,MAAM,MAAM,KAAK,WAAW,KAAK;AAAA,MACjC,OAAO,MAAM,WAAW,MAAM;AAAA,IAChC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AACA,SAAO,EAAE,YAAY,OAAO,GAAG,QAAQ;AACzC;AAMO,SAAS,wBACd,UACA,YACA,UAA8C,CAAC,GACzC;AACN,QAAM,EAAE,IAAI,WAAW,UAAU,UAAU,IAAI;AAC/C,YAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,WAAO,SAAS,SAAS,kCAAkC,YAAY,EAAE,IAAI,WAAW,UAAU,UAAU,CAAC,CAAC;AAAA,EAChH,GAAG,CAAC,UAAU,YAAY,IAAI,WAAW,UAAU,SAAS,CAAC;AAC/D;;;AChFA,SAAgB,WAAAA,gBAAe;AAC/B,SAAS,oBAAoB,2BAA0G;AAsCnI;AAbG,SAAS,eAAe,EAAE,YAAY,QAAQ,WAAW,aAAa,QAAQ,WAAW,YAAY,GAAG,GAAwB;AACrI,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,OAAO,KAAK,IAAI;AACxB,QAAM,MAAM,WAAW,KAAK,IAAQ,KAAK;AACzC,QAAM,MAAMC;AAAA,IACV,MACE;AAAA,MACE,WAAW,MAAM,MAAM,EAAE,QAAQ,OAAO,UAAU,OAAO,QAAQ,WAAW,YAAY,CAAC,EAAE,QAAQ,6CAA6C,mCAAmC;AAAA,MACnL,aAAa,CAAC;AAAA,IAChB;AAAA,IACF,CAAC,YAAY,OAAO,MAAM,QAAQ,WAAW,aAAa,GAAG;AAAA,EAC/D;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,4BAA4B,SAAS,qBAAqB,EAAE,IAAI,SAAS;AAAA,MACpF,OAAO,EAAE,aAAa,GAAG,MAAM,QAAQ,KAAK,MAAM,MAAM,QAAQ,MAAM,GAAG;AAAA,MACzE,wBAAqB;AAAA,MACrB,MAAK;AAAA,MACL,cAAY,GAAG,MAAM,IAAI,QAAQ,OAAO,KAAM,QAAQ,CAAC,CAAC;AAAA,MACxD,SAAS,SAAS,CAAC,MAAM,OAAO,oBAAoB,OAAO,EAAE,QAAmB,EAAE,aAAa,GAAG,CAAC,IAAI;AAAA,MACvG,yBAAyB,EAAE,QAAQ,IAAI;AAAA;AAAA,EACzC;AAEJ;;;ACjBQ,gBAAAC,MAGA,YAHA;AAvBR,IAAM,UAAU,CAAC,OAAe,IAAI,KAAK,KAAM,QAAQ,CAAC,CAAC;AAEzD,SAAS,MAAM,QAA4D;AACzE,MAAI,OAAO,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO,EAAG,QAAO;AACvD,MAAI,OAAO,KAAK,CAAC,MAAM,EAAE,aAAa,SAAS,EAAG,QAAO;AACzD,SAAO;AACT;AAMO,SAAS,aAAa,EAAE,YAAY,YAAY,GAAG,GAAsB;AAC9E,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,UAAU,OAAO,MAAM,SAAS,WAAW,OAAO,IAAI;AAC9D,QAAM,OAAO,KAAK,IAAI,GAAG,QAAQ;AACjC,QAAM,UAAU,CAAC,UAA8C;AAC7D,UAAM,MAAM,MAAM,cAAc,sBAAsB;AACtD,eAAW,MAAO,MAAM,UAAU,IAAI,QAAQ,KAAK,IAAI,GAAG,IAAI,KAAK,IAAK,IAAI;AAAA,EAC9E;AACA,SACE,qBAAC,SAAI,WAAW,uBAAuB,SAAS,IAAI,sBAAmB,IACrE;AAAA,yBAAC,SAAI,WAAU,mCACb;AAAA,sBAAAA,KAAC,YAAO,MAAK,UAAS,WAAU,4CAA2C,SAAS,MAAM,WAAW,OAAO,GAAG,cAAY,UAAU,UAAU,QAAQ,UAAU,CAAC,MAAM,QACrK,oBAAU,UAAU,QACvB;AAAA,MACA,qBAAC,UAAK,WAAU,sCACb;AAAA,gBAAQ,IAAI;AAAA,QAAE;AAAA,QAAI,QAAQ,QAAQ;AAAA,SACrC;AAAA,OACF;AAAA,IACA,gBAAAA;AAAA,MAAC;AAAA;AAAA,QAAI,WAAU;AAAA,QAA+C,eAAe;AAAA,QAAS,MAAK;AAAA,QAAS,cAAW;AAAA,QAAW,iBAAe;AAAA,QAAG,iBAAe;AAAA,QAAU,iBAAe,KAAK,MAAM,IAAI;AAAA,QAAG,UAAU;AAAA,QAC9M,WAAW,CAAC,MAAM;AAChB,cAAI,EAAE,QAAQ,aAAc,YAAW,KAAK,OAAO,GAAG;AACtD,cAAI,EAAE,QAAQ,YAAa,YAAW,KAAK,OAAO,GAAG;AAAA,QACvD;AAAA,QACA,0BAAAA,KAAC,SAAI,WAAU,wCAAuC,OAAO,EAAE,MAAM,GAAI,OAAO,OAAQ,GAAG,IAAI,GAAG;AAAA;AAAA,IACpG;AAAA,IACA,gBAAAA,KAAC,SAAI,WAAU,sBAAqB,MAAK,SAAQ,cAAW,SACzD,gBAAM,IAAI,CAAC,SAAS;AACnB,YAAM,OAAO,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;AAC3D,YAAM,WAAW,WAAW,SAAS,KAAK;AAC1C,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,WAAW,mEAAmE,WAAW,mCAAmC,eAAe,IAAI,MAAM,gBAAgB,KAAK,KAAK,kBAAkB,EAAE;AAAA,UACnM,OAAO,EAAE,UAAU,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,GAAG,WAAW,EAAE;AAAA,UACpE,OAAO,GAAG,KAAK,SAAS,KAAK,EAAE,SAAM,QAAQ,KAAK,MAAM,KAAK,KAAK,CAAC;AAAA,UACnE,aAAW,KAAK;AAAA,UAChB,cAAY,QAAQ;AAAA,UACpB,SAAS,MAAM;AACb,uBAAW,OAAO,EAAE,MAAM,KAAK,GAAG,CAAC;AACnC,uBAAW,SAAS,KAAK,EAAE;AAAA,UAC7B;AAAA,UAEC;AAAA,oBAAQ,gBAAAA,KAAC,UAAK,WAAW,SAAS,UAAU,iBAAiB,kBAAkB,qBAAE;AAAA,YACjF,KAAK,SAAS,KAAK;AAAA;AAAA;AAAA,QAbf,KAAK;AAAA,MAcZ;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;;;ACxEA,SAAgB,WAAAC,UAAS,YAAAC,iBAAgB;AACzC,SAAS,kBAAkB,uBAAsG;;;ACDjI,OAAOC,UAAS,WAAAC,UAAS,gBAAgB;AACzC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;;;ACRP,SAAgB,WAAAC,gBAAe;AAC/B,SAAS,qBAAqB,eAAe,mBAAmB,oBAAoB,wBAAgD;AA4B9H,SAWI,OAAAC,MAXJ,QAAAC,aAAA;AAdN,IAAM,IAAI;AACV,IAAM,IAAI;AAMH,SAAS,WAAW,EAAE,OAAO,UAAU,UAAU,YAAY,GAAG,GAAoB;AACzF,QAAM,MAAM,cAAc,KAAK;AAC/B,QAAM,QAAQF,SAAQ,MAAM,kBAAkB,SAAS,UAAU,GAAG,CAAC,KAAK,CAAC;AAC3E,QAAM,SAAS,mBAAmB,OAAO,CAAC;AAC1C,QAAM,SAAS,OAAO,UAAU,WAAW,MAAM,WAAW,QAAQ,IAAI,OAAO,SAAS;AACxF,SACE,gBAAAE,MAAC,SAAI,WAAW,2BAA2B,SAAS,IAAI,oBAAiB,IACvE;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,cAAW;AAAA,QACX,OAAO;AAAA,QACP;AAAA,QACA,UAAU,CAAC,MAAM;AACf,cAAI,EAAE,OAAO,UAAU,SAAU;AACjC,mBAAS,EAAE,OAAO,QAAS,EAAE,OAAO,QAA4B,MAAS;AAAA,QAC3E;AAAA,QAEC;AAAA,8BAAoB,IAAI,CAAC,MACxB,gBAAAD,KAAC,YAAqB,OAAO,EAAE,OAC5B,YAAE,SADQ,EAAE,KAEf,CACD;AAAA,UACA,QAAQ,YAAY,gBAAAA,KAAC,YAAO,OAAM,UAAS,oBAAM;AAAA;AAAA;AAAA,IACpD;AAAA,IACA,gBAAAC,MAAC,SAAI,OAAO,GAAG,QAAQ,GAAG,SAAS,OAAO,CAAC,IAAI,CAAC,IAAI,WAAU,yCAAwC,mBAAiB,OAAO,WAAW,eAAY,QACnJ;AAAA,sBAAAD,KAAC,UAAK,IAAI,GAAG,IAAI,GAAG,IAAI,OAAO,MAAM,IAAI,OAAO,MAAM,QAAO,gBAAe,eAAe,KAAK;AAAA,MAChG,gBAAAA,KAAC,UAAK,IAAI,GAAG,IAAI,GAAG,IAAI,OAAO,KAAK,IAAI,OAAO,KAAK,QAAO,gBAAe,eAAe,KAAK,iBAAgB,OAAM;AAAA,MACpH,gBAAAA,KAAC,UAAK,GAAG,iBAAiB,OAAO,GAAG,CAAC,GAAG,MAAK,QAAO,QAAO,WAAU,aAAa,KAAK;AAAA,OACzF;AAAA,IACC,UAAU,gBAAAC,MAAC,UAAK,WAAU,kDAAkD;AAAA,WAAK,MAAM,MAAM,UAAU;AAAA,MAAE;AAAA,OAAG;AAAA,KAC/G;AAEJ;;;ACjDI,gBAAAC,YAAA;AAFG,SAAS,YAAY,EAAE,OAAO,UAAU,GAAG,KAAK,GAAqI;AAC1L,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAEE,GAAG;AAAA,MACJ,cAAc;AAAA,MACd,WAAW,CAAC,MAAM,EAAE,QAAQ,WAAW,EAAE,cAAc,KAAK;AAAA,MAC5D,QAAQ,CAAC,MAAM;AACb,YAAI,EAAE,cAAc,UAAU,MAAO,UAAS,EAAE,cAAc,KAAK;AAAA,MACrE;AAAA;AAAA,IANK;AAAA,EAOP;AAEJ;;;AFwBM,gBAAAC,MA2BQ,QAAAC,aA3BR;AAnBN,IAAM,QAAQ;AAQP,SAAS,iBAAiB,EAAE,YAAY,QAAQ,YAAY,GAAG,GAA0B;AAC9F,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,OAAO,WAAW,UAAU,MAAM,IAAI;AAC9C,QAAM,CAAC,OAAO,aAAa,IAAI,SAAoD,IAAI;AACvF,QAAM,WAAW,CAAC,SAAwB,cAAc,OAAO,EAAE,MAAM,UAAU,MAAM,SAAS,IAAI,IAAI;AACxG,QAAM,WAAWC,SAAQ,MAAM,uBAAuB,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC;AAC7E,QAAM,OAAO,YAAY,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,UAAU,IAAI,IAAI;AAC5E,QAAM,QAAQ,WAAW;AACzB,QAAM,UAAU,QAAQ,UAAU,SAAY,KAAK,IAAI,KAAK,IAAI;AAChE,MAAI,CAAC,QAAQ,UAAU,UAAa,CAAC,SAAS;AAC5C,WACE,gBAAAF,KAAC,SAAI,WAAW,iCAAiC,SAAS,IAAI,0BAAuB,IAAG,0CAExF;AAAA,EAEJ;AACA,QAAM,SAAS;AACf,QAAM,SAAS,oBAAoB,QAAQ,IAAI;AAC/C,QAAM,YAAY,qBAAqB,OAAO;AAC9C,QAAM,SAAS,CAAC,OAAwB,QAA+C;AACrF,UAAM,OAAO,gBAAgB,KAAK,IAAI,OAAO,OAAO,GAAG;AACvD,QAAI,WAAW,KAAM,QAAO,SAAS,KAAK,KAAK;AAC/C,aAAS,IAAI;AACb,eAAW,MAAM,MAAM,OAAO,MAAM,MAAM,YAAY,CAAC,EAAE;AAAA,EAC3D;AACA,QAAM,OAAO,CAAC,OAAe,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,QAAQ;AACxE,QAAM,UAAW,OAAO,WAAoC,CAAC;AAE7D,QAAM,WAAW,SAAS,MAAM,aAAa,MAAM,WAAW,MAAM,OAAO,SAAS;AAEpF,QAAM,UAAU,CAAC,UAA2B;AAC1C,UAAM,IAAI,OAAO,MAAM,IAAI;AAC3B,UAAM,SAAS,EAAE,UAAU,UAAU,cAAc,MAAM,OAAO,OAAO,MAAM,YAAY;AACzF,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,eACE,gBAAAC,MAAC,SAAI,WAAU,qCAAoC,gBAAa,IAC7D;AAAA,kBAAQ,IAAI,CAAC,OACZ,gBAAAA,MAAC,UAAc,WAAU,+DAA8D,eAAa,IACjG;AAAA,iBAAK,EAAE;AAAA,YACP,CAAC,YAAY,QAAQ,SAAS,KAC7B,gBAAAD,KAAC,YAAO,MAAK,UAAS,cAAY,UAAU,EAAE,IAAI,SAAS,MAAM,OAAO,OAAO,QAAQ,OAAO,CAAC,MAAM,MAAM,EAAE,CAAC,GAAG,kBAEjH;AAAA,eALO,EAOX,CACD;AAAA,UACA,CAAC,YAAY,UAAU,CAAC,QAAQ,SAAS,MAAM,KAC9C,gBAAAC,MAAC,YAAO,MAAK,UAAS,WAAU,iEAAgE,SAAS,MAAM,OAAO,OAAO,CAAC,GAAG,SAAS,MAAM,CAAC,GAAG,mBAAgB,IAAG;AAAA;AAAA,YAClK,KAAK,MAAM;AAAA,aAChB;AAAA,UAED,CAAC,YACA,gBAAAA,MAAC,YAAO,WAAU,uEAAsE,cAAW,cAAa,OAAM,IAAG,UAAU,CAAC,MAAM,EAAE,OAAO,SAAS,OAAO,OAAO,CAAC,GAAG,SAAS,EAAE,OAAO,KAAK,CAAC,GACpM;AAAA,4BAAAD,KAAC,YAAO,OAAM,IAAG,4BAAS;AAAA,YACzB,SAAS,OAAO,CAAC,MAAM,CAAC,QAAQ,SAAS,EAAE,EAAE,CAAC,EAAE,IAAI,CAAC,MACpD,gBAAAA,KAAC,YAAkB,OAAO,EAAE,IACzB,YAAE,OAAO,GAAG,EAAE,IAAI,KAAK,EAAE,EAAE,MAAM,EAAE,MADzB,EAAE,EAEf,CACD;AAAA,aACH;AAAA,WAEJ;AAAA,MAEJ,KAAK;AACH,eACE,gBAAAC,MAAC,YAAO,WAAW,OAAQ,GAAG,QAAQ,OAAO,OAAO,MAAM,WAAW,IAAI,IAAI,UAAU,CAAC,MAAM,OAAO,OAAO,EAAE,OAAO,KAAK,GACvH;AAAA,WAAC,MAAM,YAAY,gBAAAD,KAAC,YAAO,OAAM,IAAG,oBAAC;AAAA,UACrC,SAAS,OAAO,CAAC,MAAM,MAAM,SAAS,UAAU,EAAE,SAAS,MAAM,EAAE,IAAI,CAAC,MACvE,gBAAAC,MAAC,YAAkB,OAAO,EAAE,IACzB;AAAA,cAAE,OAAO,GAAG,EAAE,IAAI,KAAK,EAAE,EAAE,MAAM,EAAE;AAAA,YACnC,EAAE,SAAS,iBAAc;AAAA,eAFf,EAAE,EAGf,CACD;AAAA,WACH;AAAA,MAEJ,KAAK;AACH,eACE,gBAAAA,MAAC,YAAO,WAAW,OAAQ,GAAG,QAAQ,OAAO,OAAO,MAAM,WAAW,IAAI,IAAI,UAAU,CAAC,MAAM,OAAO,OAAO,EAAE,OAAO,KAAK,GACvH;AAAA,WAAC,MAAM,YAAY,gBAAAD,KAAC,YAAO,OAAM,IAAG,qBAAO;AAAA,UAC3C,MAAM,QAAS,IAAI,CAAC,MACnB,gBAAAA,KAAC,YAAe,OAAO,GACpB,eADU,CAEb,CACD;AAAA,WACH;AAAA,MAEJ,KAAK;AACH,eAAO,gBAAAA,KAAC,WAAM,MAAK,YAAY,GAAG,QAAQ,SAAS,MAAM,MAAM,UAAU,CAAC,MAAM,OAAO,OAAO,EAAE,OAAO,OAAO,GAAG;AAAA,MACnH,KAAK;AACH,eAAO,gBAAAA,KAAC,cAAW,OAAO,GAAY,UAAU,UAAU,UAAU,CAAC,SAAS,OAAO,OAAO,SAAS,SAAY,KAAM,IAAe,GAAG;AAAA,MAC3I,KAAK;AACH,eACE,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,0BAAAD,KAAC,WAAM,MAAK,SAAQ,UAAU,UAAU,cAAY,GAAG,MAAM,KAAK,WAAW,OAAO,OAAO,MAAM,YAAY,kBAAkB,KAAK,CAAC,IAAI,IAAI,WAAW,UAAU,CAAC,MAAM,OAAO,OAAO,EAAE,OAAO,KAAK,GAAG;AAAA,UACxM,gBAAAA,KAAC,eAAY,WAAW,OAAQ,GAAG,QAAQ,OAAO,OAAO,MAAM,WAAW,IAAI,IAAI,aAAY,aAAY,UAAU,CAAC,QAAQ,OAAO,OAAO,GAAG,GAAG;AAAA,WACnJ;AAAA,MAEJ,KAAK,SAAS;AACZ,cAAM,IAAK,KAA8C;AACzD,eACE,gBAAAA,KAAC,SAAI,WAAU,2BACX,WAAC,KAAK,GAAG,EAAY,IAAI,CAAC,SAC1B,gBAAAA;AAAA,UAAC;AAAA;AAAA,YAEC,WAAW;AAAA,YACX,MAAK;AAAA,YACL,UAAU;AAAA,YACV,cAAY,GAAG,MAAM,KAAK,IAAI,IAAI;AAAA,YAClC,aAAa;AAAA,YACb,OAAO,IAAI,OAAO,EAAE,IAAI,CAAC,IAAI;AAAA,YAC7B,UAAU,CAAC,QAAQ,OAAO,OAAO,SAAS,MAAM,EAAE,GAAG,KAAK,GAAG,IAAI,OAAO,EAAE,CAAC,IAAI,MAAM,MAAM,GAAG,IAAI,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC,IAAI,MAAM,MAAM,IAAI,GAAG,IAAI,CAAC;AAAA;AAAA,UAP5I;AAAA,QAQP,CACD,GACH;AAAA,MAEJ;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eACE,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA,cACX,MAAK;AAAA,cACJ,GAAG;AAAA,cACJ,KAAK,MAAM;AAAA,cACX,KAAK,MAAM;AAAA,cACX,MAAM,MAAM,SAAS,YAAY,IAAI,MAAM,SAAS,OAAO,KAAK,MAAM,SAAS,aAAQ,OAAO;AAAA,cAC9F,aAAY;AAAA,cACZ,OAAO,OAAO,MAAM,WAAW,OAAO,CAAC,IAAI;AAAA,cAC3C,UAAU,CAAC,QAAQ,OAAO,OAAO,GAAG;AAAA;AAAA,UACtC;AAAA,UACC,MAAM,QAAQ,gBAAAA,KAAC,UAAK,WAAU,8CAA8C,gBAAM,MAAK;AAAA,WAC1F;AAAA,MAEJ;AACE,eAAO,gBAAAA,KAAC,eAAY,WAAW,OAAQ,GAAG,QAAQ,OAAO,OAAO,MAAM,WAAW,IAAI,IAAI,UAAU,CAAC,QAAQ,OAAO,OAAO,GAAG,GAAG;AAAA,IACpI;AAAA,EACF;AAEA,SACE,gBAAAC,MAAC,SAAI,WAAW,iCAAiC,SAAS,IAAI,0BAAuB,IAAG,qBAAmB,QAAQ,MACjH;AAAA,oBAAAA,MAAC,SAAI,WAAU,2BACb;AAAA,sBAAAA,MAAC,UAAK,WAAU,eACb;AAAA,gBAAQ;AAAA,QAAE;AAAA,QAAG,QAAQ;AAAA,SACxB;AAAA,MACC,YACC,gBAAAD,KAAC,UAAK,WAAU,qCAAoC,wBAAsB,WAAW,OAAM,iDACxF,qBACH,IAEA,gBAAAA,KAAC,UAAK,WAAU,qCAAoC,8CAAgC;AAAA,OAExF;AAAA,IACE,CAAC,QAAQ,QAAQ,EAAY,IAAI,CAAC,UAClC,gBAAAC,MAAC,cAAqB,WAAU,4DAC9B;AAAA,sBAAAD,KAAC,YAAO,WAAU,kEAAkE,oBAAU,SAAS,YAAY,UAAS;AAAA,MAC3H,OACE,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK,EAC/B,IAAI,CAAC,UACJ,gBAAAC,MAACE,OAAM,UAAN,EACC;AAAA,wBAAAF,MAAC,WAAM,WAAU,kCAAiC,OAAO,MAAM,aAC5D;AAAA,gBAAM;AAAA,UACN,MAAM,WAAW,OAAO;AAAA,WAC3B;AAAA,QACA,gBAAAD,KAAC,SAAI,cAAY,MAAM,MAAO,kBAAQ,KAAK,GAAE;AAAA,WAL1B,MAAM,IAM3B,CACD;AAAA,SAZU,KAaf,CACD;AAAA,IACA,WACC,gBAAAA,KAAC,OAAE,WAAU,gBAAe,MAAK,SAAQ,mBAAgB,IACtD,mBACH;AAAA,KAEJ;AAEJ;;;AG9MA,SAAgB,YAAAI,iBAAgB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AA2BgB,gBAAAC,MAoBjB,QAAAC,aApBiB;AAfvB,IAAM,MAAM;AAOL,SAAS,YAAY,EAAE,YAAY,MAAM,SAAS,YAAY,GAAG,GAAqB;AAC3F,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,OAAO,WAAW,UAAU,MAAM,IAAI;AAC9C,QAAM,SAAS,QAAQ,WAAW,QAAQ,MAAM,MAAM,CAAC,GAAG;AAC1D,QAAM,UAAU,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM;AACvD,QAAM,CAAC,MAAM,OAAO,IAAIC,UAA4B,OAAO;AAC3D,QAAM,CAAC,OAAO,aAAa,IAAIA,UAAoD,IAAI;AACvF,QAAM,WAAW,CAAC,SAAwB,cAAc,OAAO,EAAE,MAAM,UAAU,MAAM,SAAS,IAAI,IAAI;AACxG,MAAI,CAAC,QAAS,QAAO,gBAAAF,KAAC,SAAI,WAAW,iCAAiC,SAAS,IAAI,qBAAkB,IAAG,kCAAoB;AAC5H,QAAM,OAAO,kBAAkB,OAAO,QAAQ,EAAE;AAChD,QAAM,WAAW,WAAW,SAAS,QAAQ,KAAK,UAAU,UAAU;AACtE,QAAM,MAAM,CAAC,MAAyD,UAAkB;AACtF,aAAS,IAAI;AACb,WAAO,WAAW,MAAM,MAAM,KAAK;AAAA,EACrC;AACA,QAAM,MAAM,MAAM;AAChB,UAAM,OAAO,SAAS,SAAS,UAAU,aAAa,SAAc,QAAQ,IAAI,QAAQ,EAA6B,WAAW,CAAC,IAAK,CAAC;AACvI,UAAM,UAAU,qBAAqB,MAAM,MAAM,KAAK;AACtD,QAAI,WAAW,QAAS,QAAO,SAAS,QAAQ,KAAK;AACrD,UAAM,KAAK,aAAa,SAAY,WAAW,IAAI,QAAQ,IAAI;AAC/D,UAAM,SAAS,IAAI,EAAE,IAAI,gBAAgB,MAAM,QAAQ,IAAI,UAAU,CAAC,OAAO,GAAG,GAAG,GAAG,OAAO,IAAI,EAAE;AACnG,QAAI,OAAO,GAAI,YAAW,OAAO,EAAE,MAAM,QAAQ,IAAI,SAAS,GAAG,CAAC;AAAA,EACpE;AAEA,QAAM,WAAW,SAAS,MAAM,aAAa,MAAM,WAAW,MAAM,OAAO,SAAS;AAEpF,SACE,gBAAAC,MAAC,SAAI,WAAW,+BAA+B,SAAS,IAAI,qBAAkB,IAAG,iBAAe,QAAQ,IACtG;AAAA,oBAAAA,MAAC,SAAI,WAAU,eAAc;AAAA;AAAA,MACf,gBAAAD,KAAC,UAAK,WAAU,iBAAiB,kBAAQ,SAAS,QAAQ,IAAG;AAAA,OAC3E;AAAA,IACA,gBAAAA,KAAC,QAAG,WAAU,uBAAsB,cAAW,YAC5C,eAAK,IAAI,CAAC,QAAQ;AACjB,YAAM,IAAI,IAAI;AACd,YAAM,aAAa,IAAI,UAAU;AACjC,aACE,gBAAAC;AAAA,QAAC;AAAA;AAAA,UAEC,WAAW,gEAAgE,aAAa,mCAAmC,eAAe;AAAA,UAC1I,gBAAc,IAAI;AAAA,UAClB,iBAAe,cAAc;AAAA,UAC7B,SAAS,MAAM,WAAW,OAAO,EAAE,MAAM,QAAQ,IAAI,SAAS,IAAI,MAAM,CAAC;AAAA,UAEzE;AAAA,4BAAAA,MAAC,UAAK,WAAU,2BAA0B,OAAO,IAAI,SAClD;AAAA,kBAAI,QAAQ;AAAA,cAAE;AAAA,cAAG,IAAI;AAAA,eACxB;AAAA,YACC,IAAI,kBACH,gBAAAD,KAAC,UAAK,WAAU,2DAA0D,wBAAsB,IAAI,gBACjG,cAAI,gBACP;AAAA,YAEF,gBAAAC,MAAC,UAAK,WAAU,kDAAoD;AAAA,oBAAI,MAAM,IAAI,SAAS,KAAM,QAAQ,CAAC;AAAA,cAAE;AAAA,eAAE;AAAA,YAC9G,gBAAAA,MAAC,SAAI,WAAU,kCAAiC,SAAS,CAAC,MAAM,EAAE,gBAAgB,GAChF;AAAA,8BAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,cAAW;AAAA,kBACX,OAAO,EAAE,QAAQ;AAAA,kBACjB,UAAU,YAAY,IAAI,UAAU;AAAA,kBACpC,UAAU,CAAC,MACT;AAAA,oBACE,EAAE,OAAO,UAAU,UAAU,EAAE,IAAI,kBAAkB,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,kBAAkB,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,MAAM,EAAE;AAAA,oBAC5M;AAAA,kBACF;AAAA,kBAGF;AAAA,oCAAAD,KAAC,YAAO,OAAM,SAAQ,4BAAc;AAAA,oBACpC,gBAAAA,KAAC,YAAO,OAAM,YAAW,2BAAa;AAAA;AAAA;AAAA,cACxC;AAAA,cACA,gBAAAC,MAAC,WAAM,WAAU,mDAAkD;AAAA;AAAA,gBAEjE,gBAAAD;AAAA,kBAAC;AAAA;AAAA,oBAEC,WAAU;AAAA,oBACV,MAAK;AAAA,oBACL,KAAK;AAAA,oBACL,MAAM;AAAA,oBACN,cAAW;AAAA,oBACX,aAAY;AAAA,oBACZ,cAAc,EAAE,SAAS;AAAA,oBACzB,UAAU;AAAA,oBACV,WAAW,CAAC,MAAM,EAAE,QAAQ,WAAW,EAAE,cAAc,KAAK;AAAA,oBAC5D,QAAQ,CAAC,MAAM;AACb,4BAAM,MAAM,EAAE,cAAc,MAAM,KAAK;AACvC,0BAAI,QAAQ,OAAO,EAAE,SAAS,EAAE,EAAG;AACnC,4BAAM,IAAI,OAAO,GAAG;AACpB,0BAAI,OAAO,EAAE,OAAO,SAAS,CAAC,KAAK,KAAK,GAAI,QAAO,SAAS,0CAA0C;AACtG,0BAAI,OAAO,IAAI,IAAI,EAAE,IAAI,kBAAkB,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,KAAK,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,kBAAkB,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,QAAQ,CAAC,OAAO,EAAE,GAAG,cAAc;AAAA,oBAC1M;AAAA;AAAA,kBAhBK,OAAO,EAAE,SAAS,EAAE;AAAA,gBAiB3B;AAAA,gBAAE;AAAA,iBAEJ;AAAA,cACA,gBAAAC,MAAC,UAAK,WAAU,wBACd;AAAA,gCAAAD,KAAC,YAAO,MAAK,UAAS,WAAW,KAAK,cAAW,WAAU,UAAU,YAAY,IAAI,UAAU,GAAG,SAAS,MAAM,IAAI,EAAE,IAAI,gBAAgB,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,IAAI,IAAI,QAAQ,EAAE,GAAG,cAAc,EAAE,MAAM,WAAW,OAAO,EAAE,MAAM,QAAQ,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC,GAAG,oBAE7R;AAAA,gBACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,KAAK,cAAW,aAAY,UAAU,YAAY,IAAI,UAAU,KAAK,SAAS,GAAG,SAAS,MAAM,IAAI,EAAE,IAAI,gBAAgB,MAAM,QAAQ,IAAI,SAAS,IAAI,OAAO,IAAI,IAAI,QAAQ,EAAE,GAAG,cAAc,EAAE,MAAM,WAAW,OAAO,EAAE,MAAM,QAAQ,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC,GAAG,oBAE7S;AAAA,gBACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,KAAK,cAAW,aAAY,UAAU,UAAU,SAAS,MAAM,IAAI,2BAA2B,OAAO,QAAQ,IAAI,IAAI,KAAK,GAAG,mBAAmB,EAAE,MAAM,WAAW,OAAO,EAAE,MAAM,QAAQ,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC,GAAG,oBAE1P;AAAA,gBACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,KAAK,cAAW,UAAS,UAAU,UAAU,SAAS,MAAM,IAAI,EAAE,IAAI,mBAAmB,MAAM,QAAQ,IAAI,UAAU,CAAC,IAAI,KAAK,EAAE,GAAG,gBAAgB,GAAG,oBAExL;AAAA,iBACF;AAAA,eACF;AAAA;AAAA;AAAA,QApEK,GAAG,IAAI,KAAK,IAAI,IAAI,OAAO;AAAA,MAqElC;AAAA,IAEJ,CAAC,GACH;AAAA,IACC,CAAC,YACA,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,sBAAAD,KAAC,YAAO,WAAU,kEAAiE,cAAW,oBAAmB,OAAO,MAAM,UAAU,CAAC,MAAM,QAAQ,EAAE,OAAO,KAA0B,GACvL,+BAAqB,IAAI,CAAC,MACzB,gBAAAA,KAAC,YAAe,OAAO,GACpB,eADU,CAEb,CACD,GACH;AAAA,MACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,KAAK,SAAS,KAAK,oBAAiB,IAAG,yBAExE;AAAA,OACF;AAAA,IAED,WACC,gBAAAA,KAAC,OAAE,WAAU,gBAAe,MAAK,SAAQ,mBAAgB,IACtD,mBACH;AAAA,KAEJ;AAEJ;;;AC9JA,SAAgB,aAAAG,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AACnD,SAAS,gBAAgB,eAAe,wBAA0E;AA8C1G,gBAAAC,MAQE,QAAAC,aARF;AAtCR,IAAMC,WAAU,CAAC,OAAe,IAAI,KAAK,KAAM,QAAQ,CAAC,CAAC;AAEzD,SAASC,OAAM,QAA4D;AACzE,MAAI,OAAO,KAAK,CAAC,MAAM,EAAE,aAAa,OAAO,EAAG,QAAO;AACvD,MAAI,OAAO,KAAK,CAAC,MAAM,EAAE,aAAa,SAAS,EAAG,QAAO;AACzD,SAAO;AACT;AAOO,SAAS,iBAAiB,EAAE,YAAY,YAAY,GAAG,GAA0B;AACtF,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,UAAU,OAAO,MAAM,SAAS,WAAW,QAAQ,OAAO,SAAS,IAAI;AAC/E,QAAM,OAAO,KAAK,IAAI,GAAG,QAAQ;AACjC,QAAM,QAAQC,QAAuB,IAAI;AACzC,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAS,GAAG;AACtC,EAAAC,WAAU,MAAM;AACd,UAAM,KAAK,MAAM;AACjB,QAAI,CAAC,MAAM,OAAO,mBAAmB,YAAa;AAClD,UAAM,WAAW,IAAI,eAAe,MAAM,SAAS,GAAG,eAAe,GAAG,CAAC;AACzE,aAAS,QAAQ,EAAE;AACnB,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,CAAC;AACL,QAAM,QAAQ,iBAAiB,UAAU,KAAK;AAC9C,QAAM,MAAM,CAAC,OAAe,GAAI,KAAK,IAAI,MAAM,KAAK,IAAI,GAAG,EAAE,CAAC,IAAI,OAAQ,GAAG;AAC7E,QAAM,SAAS,CAAC,YAAoB;AAClC,UAAM,MAAM,MAAM,QAAS,sBAAsB;AACjD,eAAW,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,UAAU,IAAI,QAAQ,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI;AAAA,EAChG;AACA,QAAM,QAAkB,CAAC;AACzB,MAAI,MAAM,QAAQ,MAAM,KAAK,MAAM;AAAG,aAAS,IAAI,GAAG,IAAI,eAAe,MAAM,MAAM,CAAC,GAAG,KAAK,QAAQ,MAAM,SAAS,KAAK,IAAI,eAAe,MAAM,MAAM,EAAE,CAAC,EAAG,KAAI,KAAK,EAAG,OAAM,KAAK,CAAC;AAAA;AAEvL,SACE,gBAAAL,MAAC,SAAI,WAAW,uBAAuB,SAAS,IAAI,0BAAuB,IAAG,sBAAmB,IAC/F;AAAA,oBAAAA,MAAC,SAAI,WAAU,mCACb;AAAA,sBAAAD,KAAC,YAAO,MAAK,UAAS,WAAU,4CAA2C,SAAS,MAAM,WAAW,OAAO,GAAG,cAAY,UAAU,UAAU,QAAQ,UAAU,CAAC,MAAM,QACrK,oBAAU,UAAU,QACvB;AAAA,MACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAU,4CAA2C,SAAS,MAAM;AAAE,mBAAW,MAAM;AAAG,mBAAW,KAAK,CAAC;AAAA,MAAG,GAAG,cAAW,iBAAgB,oBAElK;AAAA,MACA,gBAAAC,MAAC,WAAM,WAAU,iDAAgD;AAAA;AAAA,QAE/D,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,MAAM,QAAQ;AAAA,YACrB,UAAU;AAAA,YACV,cAAW;AAAA,YACX,UAAU,CAAC,MAAM,WAAW,MAAM,EAAE,IAAI,gBAAgB,MAAM,EAAE,OAAO,MAAuC,GAAG,aAAa;AAAA,YAE9H;AAAA,8BAAAD,KAAC,YAAO,OAAM,QAAO,iBAAG;AAAA,cACxB,gBAAAA,KAAC,YAAO,OAAM,QAAO,kBAAI;AAAA,cACzB,gBAAAA,KAAC,YAAO,OAAM,aAAY,uBAAS;AAAA;AAAA;AAAA,QACrC;AAAA,SACF;AAAA,MACA,gBAAAC,MAAC,UAAK,WAAU,8CAA6C,aAAU,IACpE;AAAA,QAAAC,SAAQ,IAAI;AAAA,QAAE;AAAA,QAAIA,SAAQ,QAAQ;AAAA,SACrC;AAAA,OACF;AAAA,IACA,gBAAAD;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAU;AAAA,QACV,MAAK;AAAA,QACL,cAAW;AAAA,QACX,iBAAe;AAAA,QACf,iBAAe;AAAA,QACf,iBAAe,KAAK,MAAM,IAAI;AAAA,QAC9B,UAAU;AAAA,QACV,oBAAiB;AAAA,QACjB,eAAe,CAAC,MAAM;AACpB,YAAE,cAAc,oBAAoB,EAAE,SAAS;AAC/C,iBAAO,EAAE,OAAO;AAAA,QAClB;AAAA,QACA,eAAe,CAAC,MAAM;AACpB,cAAI,EAAE,UAAU,EAAG,QAAO,EAAE,OAAO;AAAA,QACrC;AAAA,QACA,WAAW,CAAC,MAAM;AAChB,gBAAM,OAAO,EAAE,WAAW,MAAO;AACjC,cAAI,EAAE,QAAQ,aAAc,YAAW,KAAK,OAAO,IAAI;AAAA,mBAC9C,EAAE,QAAQ,YAAa,YAAW,KAAK,OAAO,IAAI;AAAA,mBAClD,EAAE,QAAQ,OAAQ,YAAW,KAAK,CAAC;AAAA,mBACnC,EAAE,QAAQ,MAAO,YAAW,KAAK,QAAQ;AAAA,mBACzC,EAAE,QAAQ,IAAK,YAAW,OAAO;AAAA,cACrC;AACL,YAAE,eAAe;AAAA,QACnB;AAAA,QAEA;AAAA,0BAAAA,MAAC,SAAI,WAAU,yEAAwE,cAAW,IAC/F;AAAA,kBAAM,IAAI,CAAC,GAAG,MACb,gBAAAD,KAAC,SAAkB,WAAU,8CAA6C,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,GAAG,aAAW,KAApG,IAAI,CAAC,EAAkG,CAClH;AAAA,YACA,MAAM,WAAW,MAAM,IAAI,CAAC,GAAG,MAC9B,gBAAAA,KAAC,SAAkB,WAAU,+CAA8C,OAAO,EAAE,MAAM,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,SAAI,EAAE,IAAI,aAAQE,SAAQ,EAAE,KAAK,CAAC,IAAI,aAAW,KAAxJ,IAAI,CAAC,EAAsJ,CACtK;AAAA,YACA,MAAM,IAAI,CAAC,MACV,gBAAAF,KAAC,SAAiB,WAAW,0BAA0B,EAAE,QAAQ,iCAAiC,4BAA4B,IAAI,OAAO,EAAE,MAAM,IAAI,EAAE,IAAI,EAAE,GAC1J,YAAE,SAAS,gBAAAA,KAAC,UAAK,WAAU,2DAA2D,YAAE,OAAM,KADvF,EAAE,IAEZ,CACD;AAAA,aACH;AAAA,UACA,gBAAAA,KAAC,SAAI,WAAU,2BAA0B,MAAK,SAAQ,cAAW,SAC9D,gBAAM,IAAI,CAAC,MAAM,MAAM;AACtB,kBAAM,OAAOG,OAAM,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;AAC3D,kBAAM,WAAW,WAAW,SAAS,KAAK;AAC1C,kBAAM,MAAM,MAAM,MAAM,CAAC,GAAG;AAC5B,kBAAM,UAAU,MAAM,cAAc,OAAO,GAAG,IAAI;AAClD,mBACE,gBAAAF;AAAA,cAAC;AAAA;AAAA,gBAEC,MAAK;AAAA,gBACL,WAAW,4EAA4E,WAAW,mCAAmC,2BAA2B,IAAI,MAAM,gBAAgB,KAAK,KAAK,kBAAkB,EAAE;AAAA,gBACxN,OAAO,EAAE,UAAU,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,GAAG,WAAW,EAAE;AAAA,gBACpE,OAAO,GAAG,KAAK,SAAS,KAAK,EAAE,SAAMC,SAAQ,KAAK,KAAK,CAAC,SAAIA,SAAQ,KAAK,GAAG,CAAC,GAAG,YAAY,SAAY,iBAAcA,SAAQ,OAAO,CAAC,KAAK,EAAE;AAAA,gBAC7I,aAAW,KAAK;AAAA,gBAChB,cAAY,QAAQ;AAAA,gBACpB,eAAe,CAAC,MAAM,EAAE,gBAAgB;AAAA,gBACxC,SAAS,MAAM;AACb,6BAAW,OAAO,EAAE,MAAM,KAAK,GAAG,CAAC;AACnC,6BAAW,SAAS,KAAK,EAAE;AAAA,gBAC7B;AAAA,gBAEC;AAAA,0BAAQ,gBAAAF,KAAC,UAAK,WAAW,SAAS,UAAU,iBAAiB,kBAAkB,qBAAE;AAAA,kBACjF,KAAK,SAAS,KAAK;AAAA;AAAA;AAAA,cAdf,KAAK;AAAA,YAeZ;AAAA,UAEJ,CAAC,GACH;AAAA,UACA,gBAAAA,KAAC,SAAI,WAAU,6EAA4E,OAAO,EAAE,MAAM,IAAI,IAAI,EAAE,GAAG,iBAAc,IAAG;AAAA;AAAA;AAAA,IAC1I;AAAA,KACF;AAEJ;;;AC/IA,SAAgB,YAAAO,iBAAgB;AAChC,SAAS,qBAAqB,qBAAqB,uBAAuB,oBAAoB,4BAAiG;AAWnK,gBAAAC,MA6CpB,QAAAC,aA7CoB;AAF5B,IAAMC,SAAQ;AACd,IAAMC,OAAM;AACZ,IAAM,OAAO,CAAC,MAAc,gBAAAH,KAAC,UAAK,WAAU,8CAA8C,aAAE;AAOrF,SAAS,cAAc,EAAE,YAAY,YAAY,GAAG,GAAuB;AAChF,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,OAAO,UAAU,OAAO,SAAS,IAAI;AAC7C,QAAM,CAAC,OAAO,aAAa,IAAII,UAAoD,IAAI;AACvF,QAAM,WAAW,CAAC,SAAwB,cAAc,OAAO,EAAE,MAAM,UAAU,MAAM,SAAS,IAAI,IAAI;AACxG,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAiB,EAAE;AAC7C,QAAM,QAAQ,CAAC,MAAiC,UAAkB;AAChE,aAAS,IAAI;AACb,WAAO,WAAW,MAAM,MAAM,KAAK;AAAA,EACrC;AACA,QAAM,WAAW,CAAC,KAA8D,UAAkB,MAAM,EAAE,IAAI,gBAAgB,GAAG,IAAI,GAAG,KAAK;AAC7I,QAAM,MAAM,CAAC,KAAa,MAAc,IAA4B,SAAqC;AACvG,QAAI,IAAI,KAAK,MAAM,GAAI,QAAO,KAAK,IAAI;AACvC,UAAM,IAAI,OAAO,GAAG;AACpB,QAAI,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,EAAG,QAAO,SAAS,IAAI;AACvD,SAAK,CAAC;AAAA,EACR;AACA,QAAM,SAAS,MAAM;AACrB,QAAM,aAAa,SAAS,OAAO,UAAU,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,IAAI,KAAK,MAAM,WAAW,GAAG,IAAI,EAAE;AACzG,QAAM,MAAM,MAAM;AAChB,UAAM,IAAI,OAAO,UAAU;AAC3B,QAAI,EAAE,OAAO,SAAS,CAAC,KAAK,IAAI,GAAI,QAAO,SAAS,6CAA6C;AACjG,QAAI;AACF,YAAM,QAAQ,oBAAoB,OAAO,IAAI,GAAI;AACjD,UAAI,MAAM,OAAQ,OAAM,OAAO,UAAU,CAAC,IAAI;AAAA,UACzC,UAAS,IAAI;AAAA,IACpB,SAAS,GAAG;AACV,eAAU,EAAY,OAAO;AAAA,IAC/B;AAAA,EACF;AACA,QAAM,OAAO,MAAM;AAEnB,QAAM,WAAW,SAAS,MAAM,aAAa,MAAM,WAAW,MAAM,OAAO,SAAS;AAEpF,SACE,gBAAAH,MAAC,SAAI,WAAW,iCAAiC,SAAS,IAAI,uBAAoB,IAChF;AAAA,oBAAAA,MAAC,SAAI,WAAU,4DACb;AAAA,sBAAAD,KAAC,WAAM,WAAU,yBAAwB,kBAAI;AAAA,MAC7C,gBAAAC,MAAC,YAAO,WAAWC,QAAO,cAAW,cAAa,UAAU,UAAU,OAAO,MAAM,QAAQ,QAAQ,UAAU,CAAC,MAAM,SAAS,EAAE,MAAM,EAAE,OAAO,MAAgB,GAAG,aAAa,GAC5K;AAAA,wBAAAF,KAAC,YAAO,OAAM,QAAO,iBAAG;AAAA,QACxB,gBAAAA,KAAC,YAAO,OAAM,QAAO,kBAAI;AAAA,QACzB,gBAAAA,KAAC,YAAO,OAAM,aAAY,uBAAS;AAAA,SACrC;AAAA,MACA,gBAAAA,KAAC,WAAM,WAAU,yBAAwB,yBAAW;AAAA,MACpD,gBAAAC,MAAC,YAAO,WAAWC,QAAO,cAAW,eAAc,UAAU,UAAU,OAAO,MAAM,aAAa,OAAO,MAAM,WAAW,WAAW,GAAG,IAAI,IAAI,UAAU,CAAC,MAAM,SAAS,EAAE,YAAY,EAAE,OAAO,QAAQ,EAAE,GAAI,MAAM,cAAc,CAAC,GAAI,SAAS,OAAO,EAAE,OAAO,KAAK,EAAE,IAAI,KAAK,GAAG,oBAAoB,GACrS;AAAA,wBAAAF,KAAC,YAAO,OAAM,IAAG,iBAAG;AAAA,QACpB,gBAAAA,KAAC,YAAO,OAAM,MAAK,4BAAW;AAAA,QAC9B,gBAAAA,KAAC,YAAO,OAAM,OAAM,8BAAa;AAAA,QACjC,gBAAAA,KAAC,YAAO,OAAM,OAAM,6BAAY;AAAA,SAClC;AAAA,MACA,gBAAAA,KAAC,WAAM,WAAU,yBAAwB,sBAAQ;AAAA,MACjD,gBAAAC,MAAC,YAAO,WAAWC,QAAO,cAAW,iBAAgB,OAAM,gDAA+C,UAAU,UAAU,OAAO,MAAM,WAAW,IAAI,UAAU,CAAC,MAAM,SAAS,EAAE,SAAU,EAAE,OAAO,SAAS,KAA8B,GAAG,gBAAgB,GACjQ;AAAA,wBAAAF,KAAC,YAAO,OAAM,IAAG,gCAAkB;AAAA,QACnC,gBAAAA,KAAC,YAAO,OAAM,SAAQ,sCAAwB;AAAA,QAC9C,gBAAAA,KAAC,YAAO,OAAM,SAAQ,mBAAK;AAAA,QAC3B,gBAAAA,KAAC,YAAO,OAAM,SAAQ,mBAAK;AAAA,QAC3B,gBAAAA,KAAC,YAAO,OAAM,UAAS,oBAAM;AAAA,SAC/B;AAAA,MACA,gBAAAA,KAAC,WAAM,WAAU,yBAAwB,wBAAU;AAAA,MACnD,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YAAY,WAAWE;AAAA,YAAO,MAAK;AAAA,YAAS,KAAK;AAAA,YAAG,KAAK;AAAA,YAAK,cAAW;AAAA,YAAa,aAAY;AAAA,YAAK,UAAU;AAAA,YAAU,OAAO,MAAM,QAAQ,SAAY,OAAO,MAAM,GAAG,IAAI;AAAA,YAC/K,UAAU,CAAC,QAAQ,IAAI,KAAK,oCAAoC,CAAC,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC,MAAM,MAAM,QAAQ,SAAS,EAAE,KAAK,EAAE,GAAG,mBAAmB,CAAC;AAAA;AAAA,QAAG;AAAA,QAC7J,KAAK,KAAK;AAAA,SACb;AAAA,MACA,gBAAAF,KAAC,WAAM,WAAU,yBAAwB,OAAM,uFAAsF,mBAErI;AAAA,MACA,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YAAY,WAAWE;AAAA,YAAO,MAAK;AAAA,YAAS,KAAK;AAAA,YAAG,KAAK;AAAA,YAAK,cAAW;AAAA,YAAQ,aAAY;AAAA,YAAS,UAAU;AAAA,YAAU,OAAO,MAAM,UAAU,SAAY,OAAO,MAAM,KAAK,IAAI;AAAA,YAClL,UAAU,CAAC,QAAQ,IAAI,KAAK,mEAAmE,CAAC,MAAM,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM,SAAS,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC;AAAA;AAAA,QAAG;AAAA,QAC1K,KAAK,KAAK;AAAA,SACb;AAAA,MACA,gBAAAF,KAAC,WAAM,WAAU,yBAAwB,2BAAa;AAAA,MACtD,gBAAAC,MAAC,SAAI,WAAU,2BACZ;AAAA,SAAC,GAAG,CAAC,EAAE,IAAI,CAAC,MACX,gBAAAD;AAAA,UAAC;AAAA;AAAA,YAAoB,WAAWE;AAAA,YAAO,MAAK;AAAA,YAAS,KAAK;AAAA,YAAG,MAAM;AAAA,YAAK,cAAY,IAAI,eAAe;AAAA,YAAc,aAAa,IAAI,QAAQ;AAAA,YAAO,UAAU;AAAA,YAAU,OAAO,SAAS,OAAO,OAAO,CAAC,CAAC,IAAI;AAAA,YAC3M,UAAU,CAAC,QACT,IAAI,KAAK,0CAA0C,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM;AACvE,kBAAI,MAAM,KAAM,QAAO,SAAS,EAAE,QAAQ,KAAK,GAAG,qBAAqB;AACvE,oBAAM,OAAyB,SAAS,CAAC,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC;AAC3D,mBAAK,CAAC,IAAI;AACV,kBAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAG,QAAO,SAAS,iEAAiE;AACxG,uBAAS,EAAE,QAAQ,KAAK,GAAG,sBAAsB;AAAA,YACnD,CAAC;AAAA;AAAA,UARa;AAAA,QASd,CACL;AAAA,QACA,KAAK,GAAG;AAAA,SACX;AAAA,MACA,gBAAAF,KAAC,WAAM,WAAU,yBAAwB,oBAAM;AAAA,MAC/C,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD,KAAC,WAAM,WAAWE,QAAO,MAAK,UAAS,KAAK,KAAK,MAAM,KAAK,cAAW,UAAS,OAAO,YAAY,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,KAAK,GAAG;AAAA,QAC7I,KAAK,GAAG;AAAA,QACT,gBAAAF,KAAC,YAAO,MAAK,UAAS,WAAWG,MAAK,UAAU,YAAY,CAAC,MAAM,MAAM,QAAQ,SAAS,KAAK,YAAS,IAAG,OAAM,yDAAwD,iBAEzK;AAAA,SACF;AAAA,MACA,gBAAAH,KAAC,WAAM,WAAU,yBAAwB,uBAAS;AAAA,MAClD,gBAAAC,MAAC,SAAI,WAAU,2BAA0B,kBAAe,IACtD;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YAAY,WAAWE;AAAA,YAAO,MAAK;AAAA,YAAS,KAAK;AAAA,YAAG,cAAW;AAAA,YAAM,aAAY;AAAA,YAAM,UAAU;AAAA,YAAU,OAAO,OAAO,OAAO,KAAK,GAAG,IAAI;AAAA,YAC3I,UAAU,CAAC,QAAQ,IAAI,KAAK,wBAAwB,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,SAAS,EAAE,MAAM,MAAM,OAAO,OAAO,EAAE,GAAI,QAAQ,CAAC,GAAI,KAAK,EAAE,EAAE,GAAG,MAAM,OAAO,oBAAoB,cAAc,CAAC;AAAA;AAAA,QAAG;AAAA,QAClM,gBAAAF;AAAA,UAAC;AAAA;AAAA,YAAY,WAAWE;AAAA,YAAO,MAAK;AAAA,YAAS,cAAW;AAAA,YAAc,aAAY;AAAA,YAAY,UAAU,YAAY,CAAC;AAAA,YAAM,OAAO,MAAM,WAAW,SAAY,OAAO,KAAK,MAAM,IAAI;AAAA,YACnL,UAAU,CAAC,QAAQ,QAAQ,IAAI,KAAK,iCAAiC,MAAM,MAAM,CAAC,MAAM,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,QAAQ,KAAK,EAAE,EAAE,GAAG,oBAAoB,CAAC;AAAA;AAAA,QAAG;AAAA,QAClK,gBAAAF;AAAA,UAAC;AAAA;AAAA,YAAY,WAAWE;AAAA,YAAO,MAAK;AAAA,YAAS,KAAK;AAAA,YAAG,MAAM;AAAA,YAAG,cAAW;AAAA,YAAQ,aAAY;AAAA,YAAQ,UAAU,YAAY,CAAC;AAAA,YAAM,OAAO,MAAM,UAAU,SAAY,OAAO,KAAK,KAAK,IAAI;AAAA,YACxL,UAAU,CAAC,QAAQ,QAAQ,IAAI,KAAK,+CAA+C,CAAC,MAAM,OAAO,UAAU,CAAC,KAAK,KAAK,GAAG,CAAC,MAAM,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,KAAK,EAAE,EAAE,GAAG,cAAc,CAAC;AAAA;AAAA,QAAG;AAAA,SACrM;AAAA,OACF;AAAA,IACA,gBAAAD,MAAC,WAAM,WAAU,yBACf;AAAA,sBAAAD,KAAC,UAAK,WAAU,yBAAwB,gEAAkD;AAAA,MAC1F,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,WAAW,GAAGE,MAAK;AAAA,UACnB,cAAW;AAAA,UACX,aAAa;AAAA,UACb,UAAU;AAAA,UACV,cAAc,sBAAsB,MAAM,SAAS;AAAA,UACnD,QAAQ,CAAC,MAAM;AACb,gBAAI,EAAE,cAAc,UAAU,sBAAsB,MAAM,SAAS,EAAG;AACtE,kBAAM,SAAS,qBAAqB,EAAE,cAAc,KAAK;AACzD,gBAAI,WAAW,OAAQ,QAAO,SAAS,OAAO,KAAK;AACnD,qBAAS,EAAE,WAAW,OAAO,UAAU,GAAG,OAAO,YAAY,qBAAqB,iBAAiB;AAAA,UACrG;AAAA;AAAA,QAXK,sBAAsB,MAAM,SAAS;AAAA,MAY5C;AAAA,OACF;AAAA,IACA,gBAAAD,MAAC,WAAM,WAAU,yBACf;AAAA,sBAAAD,KAAC,UAAK,WAAU,yBAAwB,+EAAoE;AAAA,MAC5G,gBAAAA;AAAA,QAAC;AAAA;AAAA,UAEC,WAAW,GAAGE,MAAK;AAAA,UACnB,cAAW;AAAA,UACX,aAAa;AAAA,UACb,UAAU;AAAA,UACV,cAAc,oBAAoB,MAAM,OAAO;AAAA,UAC/C,QAAQ,CAAC,MAAM;AACb,gBAAI,EAAE,cAAc,UAAU,oBAAoB,MAAM,OAAO,EAAG;AAClE,kBAAM,SAAS,mBAAmB,EAAE,cAAc,KAAK;AACvD,gBAAI,WAAW,OAAQ,QAAO,SAAS,OAAO,KAAK;AACnD,kBAAM,EAAE,IAAI,eAAe,SAAS,OAAO,QAAQ,GAAG,OAAO,QAAQ,SAAS,gBAAgB,eAAe;AAAA,UAC/G;AAAA;AAAA,QAXK,oBAAoB,MAAM,OAAO;AAAA,MAYxC;AAAA,OACF;AAAA,IACC,WACC,gBAAAF,KAAC,OAAE,WAAU,gBAAe,MAAK,SAAQ,mBAAgB,IACtD,mBACH;AAAA,KAEJ;AAEJ;;;ACtKA,SAAgB,WAAAK,UAAS,YAAAC,iBAAgB;AACzC,SAAS,0BAAAC,yBAAwB,aAAa,kBAAkB,kBAAkB,oBAAqE;AAwD/I,SAOI,UAPJ,OAAAC,MAOI,QAAAC,aAPJ;AA7CR,IAAMC,SAAQ;AACd,IAAMC,OAAM;AAQL,SAAS,cAAc,EAAE,YAAY,MAAM,YAAY,GAAG,GAAuB;AACtF,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,OAAO,WAAW,UAAU,MAAM,IAAI;AAC9C,QAAM,CAAC,OAAO,aAAa,IAAIC,UAAoD,IAAI;AACvF,QAAM,WAAW,CAAC,SAAwB,cAAc,OAAO,EAAE,MAAM,UAAU,MAAM,SAAS,IAAI,IAAI;AACxG,QAAM,WAAWC,SAAQ,MAAMC,wBAAuB,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC;AAC7E,QAAM,OAAOD,SAAQ,MAAM,iBAAiB,KAAK,GAAG,CAAC,KAAK,CAAC;AAC3D,QAAM,KAAK,QAAQ,WAAW,QAAQ,MAAM,MAAM,CAAC,GAAG;AACtD,QAAM,QAAQ,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE;AACtD,QAAM,UAAU,MAAM,MAAM,KAAK;AACjC,QAAM,QAAQ,CAAC,MAAiC,UAAkB;AAChE,aAAS,IAAI;AACb,WAAO,WAAW,MAAM,MAAM,KAAK;AAAA,EACrC;AACA,QAAM,UAAU,MAAM;AACpB,UAAM,QAAQ,YAAY,OAAO,MAAM;AACvC,UAAM,KAAK,SAAS,IAAI,QAAQ,IAAI,MAAM,MAAM;AAChD,QAAI,MAAM,EAAE,IAAI,gBAAgB,OAAO,CAAC,EAAE,IAAI,OAAO,OAAO,YAAY,KAAK,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,UAAU,EAAE,IAAI;AACxG,iBAAW,OAAO,EAAE,MAAM,MAAM,CAAC;AACjC,iBAAW,SAAS,KAAK;AAAA,IAC3B;AAAA,EACF;AACA,QAAM,SAAS,CAAC,KAAuB,KAAa,UAAkB;AACpE,UAAM,IAAI,OAAO,GAAG;AACpB,QAAI,IAAI,KAAK,MAAM,GAAI,QAAO,MAAM,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,QAAQ,CAAC,GAAG,EAAE,GAAG,KAAK;AACjG,QAAI,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,KAAM,QAAQ,WAAW,KAAK,EAAI,QAAO,SAAS,QAAQ,UAAU,qDAAqD,yCAAyC;AACjM,UAAM,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,EAAE,GAAG,KAAK;AAAA,EACzE;AAEA,QAAM,WAAW,SAAS,MAAM,aAAa,MAAM,WAAW,MAAM,OAAO,SAAS;AACpF,QAAM,SAAS,UAAU,aAAa,QAAQ,EAAE,IAAI;AACpD,QAAM,QAAQ,SAAS,UAAU,WAAW,QAAQ,SAAS,QAAQ,OAAO,QAAQ;AAEpF,SACE,gBAAAJ,MAAC,SAAI,WAAW,iCAAiC,SAAS,IAAI,uBAAoB,IAChF;AAAA,oBAAAA,MAAC,SAAI,WAAU,2BACb;AAAA,sBAAAD,KAAC,UAAK,WAAU,eAAc,kBAAI;AAAA,MACjC,WAAW,gBAAAA,KAAC,UAAK,WAAU,qCAAqC,kBAAQ,IAAG;AAAA,MAC5E,gBAAAC,MAAC,UAAK,WAAU,wBACd;AAAA,wBAAAD,KAAC,YAAO,MAAK,UAAS,WAAWG,MAAK,UAAU,UAAU,SAAS,SAAS,iBAAc,IAAG,oBAE7F;AAAA,QACC,WACC,gBAAAF,MAAA,YACE;AAAA,0BAAAD,KAAC,YAAO,MAAK,UAAS,WAAWG,MAAK,cAAW,qBAAoB,UAAU,YAAY,UAAU,GAAG,SAAS,MAAM,MAAM,EAAE,IAAI,aAAa,MAAM,QAAQ,IAAI,IAAI,QAAQ,EAAE,GAAG,WAAW,GAAG,oBAEjM;AAAA,UACA,gBAAAH,KAAC,YAAO,MAAK,UAAS,WAAWG,MAAK,cAAW,mBAAkB,UAAU,YAAY,UAAU,MAAM,MAAM,SAAS,GAAG,SAAS,MAAM,MAAM,EAAE,IAAI,aAAa,MAAM,QAAQ,IAAI,IAAI,QAAQ,EAAE,GAAG,WAAW,GAAG,oBAEpN;AAAA,UACA,gBAAAH,KAAC,YAAO,MAAK,UAAS,WAAWG,MAAK,cAAW,eAAc,UAAU,UAAU,SAAS,MAAM,MAAM,EAAE,IAAI,gBAAgB,OAAO,CAAC,QAAQ,EAAE,EAAE,GAAG,aAAa,GAAG,oBAErK;AAAA,WACF;AAAA,SAEJ;AAAA,OACF;AAAA,IACC,WACC,gBAAAF,MAAC,SAAI,WAAU,4DACb;AAAA,sBAAAD,KAAC,WAAM,WAAU,yBAAwB,mBAAK;AAAA,MAC9C,gBAAAA,KAAC,eAAY,WAAWE,QAAO,cAAW,cAAa,UAAU,UAAU,OAAO,QAAQ,SAAS,IAAI,UAAU,CAAC,QAAQ,MAAM,IAAI,KAAK,IAAI,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,KAAK,EAAE,OAAO,IAAI,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,QAAQ,CAAC,OAAO,EAAE,GAAG,aAAa,GAAG;AAAA,MAC/R,gBAAAF,KAAC,WAAM,WAAU,yBAAwB,kBAAI;AAAA,MAC7C,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD,KAAC,eAAY,WAAWE,QAAO,MAAK,UAAS,KAAK,GAAG,MAAM,IAAI,cAAW,QAAO,aAAY,OAAM,UAAU,UAAU,OAAO,QAAQ,SAAS,SAAY,OAAO,QAAQ,IAAI,IAAI,IAAI,UAAU,CAAC,QAAQ,OAAO,QAAQ,KAAK,aAAa,GAAG;AAAA,QAC7O,gBAAAF,KAAC,UAAK,WAAU,qCAAoC,gBAAE;AAAA,SACxD;AAAA,MACA,gBAAAA,KAAC,WAAM,WAAU,yBAAwB,mBAAK;AAAA,MAC9C,gBAAAC,MAAC,SAAI,WAAU,2BACb;AAAA,wBAAAD,KAAC,eAAY,WAAWE,QAAO,MAAK,UAAS,KAAK,MAAM,MAAM,MAAM,cAAW,SAAQ,aAAY,KAAI,UAAU,UAAU,OAAO,QAAQ,UAAU,SAAY,OAAO,QAAQ,KAAK,IAAI,IAAI,UAAU,CAAC,QAAQ,OAAO,SAAS,KAAK,cAAc,GAAG;AAAA,QACrP,gBAAAF,KAAC,UAAK,WAAU,qCAAoC,kBAAC;AAAA,SACvD;AAAA,MACA,gBAAAA,KAAC,WAAM,WAAU,yBAAwB,oBAAM;AAAA,MAC/C,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWC;AAAA,UACX,cAAW;AAAA,UACX,UAAU;AAAA,UACV,OAAO,QAAQ,SAAU,QAAQ,SAAS,KAAK,KAAK,SAAU;AAAA,UAC9D,UAAU,CAAC,MAAM;AACf,kBAAM,IAAI,EAAE,OAAO;AACnB,gBAAI,CAAC,EAAG,OAAM,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,QAAQ,CAAC,QAAQ,EAAE,GAAG,cAAc;AAAA,qBAChF,EAAE,WAAW,QAAQ,EAAG,OAAM,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,EAAE,EAAE,GAAG,cAAc;AAAA,UACrJ;AAAA,UAEA;AAAA,4BAAAF,KAAC,YAAO,OAAM,IAAG,0BAAY;AAAA,YAC5B,QAAQ,UAAU,CAAC,SAAS,gBAAAA,KAAC,YAAO,OAAM,QAAO,yBAAW;AAAA,YAC5D,SAAS,IAAI,CAAC,MACb,gBAAAC,MAAC,YAAkB,OAAO,SAAS,EAAE,EAAE,IAAI;AAAA;AAAA,cAClC,EAAE,QAAQ,EAAE;AAAA,iBADR,EAAE,EAEf,CACD;AAAA;AAAA;AAAA,MACH;AAAA,MACA,gBAAAD,KAAC,WAAM,WAAU,yBAAwB,uBAAS;AAAA,MAClD,gBAAAC;AAAA,QAAC;AAAA;AAAA,UACC,WAAWC;AAAA,UACX,cAAW;AAAA,UACX,UAAU,YAAY,UAAU;AAAA,UAChC,OAAO;AAAA,UACP,UAAU,CAAC,MAAM;AACf,kBAAM,MAAM,iBAAiB,EAAE,OAAO,KAAK;AAC3C,kBAAM,MAAM,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,KAAK,EAAE,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,eAAe,MAAM,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,GAAG,UAAU;AAAA,UAC7I;AAAA,UAEA;AAAA,4BAAAF,KAAC,YAAO,OAAM,IAAG,mCAAqB;AAAA,YACrC,UAAU,CAAC,KAAK,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM,KAAK,gBAAAA,KAAC,YAAO,OAAO,QAAS,kBAAO;AAAA,YAClF,KAAK,IAAI,CAAC,MACT,gBAAAA,KAAC,YAAqB,OAAO,EAAE,OAC5B,YAAE,SADQ,EAAE,KAEf,CACD;AAAA;AAAA;AAAA,MACH;AAAA,MACC,CAAC,KAAK,UAAU,QAAQ,KAAK,gBAAAA,KAAC,OAAE,WAAU,gDAA+C,sFAAwE;AAAA,OACpK;AAAA,IAED,WACC,gBAAAA,KAAC,OAAE,WAAU,gBAAe,MAAK,SAAQ,mBAAgB,IACtD,mBACH;AAAA,KAEJ;AAEJ;;;APrFI,SA8DU,YAAAO,WA9DV,OAAAC,OAqBE,QAAAC,aArBF;AA5BJ,IAAM,QAAyB,EAAE,QAAQ,GAAG,OAAO,EAAE;AACrD,IAAMC,OAAM;AAQL,SAAS,gBAAgB,EAAE,YAAY,QAAQ,WAAW,aAAa,aAAa,MAAM,WAAW,MAAM,YAAY,GAAG,GAAyB;AACxJ,QAAM,QAAQ,wBAAwB,UAAU;AAChD,QAAM,EAAE,QAAQ,OAAO,WAAW,SAAS,IAAI;AAC/C,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAwB,IAAI;AACxD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,KAAK;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,KAAK;AACxC,QAAM,UAAU,WAAW,YAAY,SAAY,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,UAAU,IAAI,GAAG,IAAI,UAAU,OAAO,IAAI;AAC9H,QAAM,UAAU,WAAW,aAAa,UAAU,QAAQ,UAAU,CAAC;AACrE,QAAM,QAAQC,SAAQ,MAAM,iBAAiB,MAAM,QAAQ,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC;AAClF,QAAM,cAAc,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS;AAC3D,QAAM,SAAS,CAAC,IAAmB,UAAiC;AAClE,QAAI,MAAM,YAAY,MAAM,WAAW,aAAa,WAAW,WAAW,YAAY,UAAa,CAAC,UAAU;AAC5G,YAAM,OAAO,QAAQ,SAAS,EAAE,IAAI,QAAQ,OAAO,CAAC,MAAM,MAAM,EAAE,IAAI,CAAC,GAAG,SAAS,EAAE;AACrF,UAAI,KAAK,OAAQ,YAAW,MAAM,EAAE,IAAI,kBAAkB,MAAM,UAAU,MAAM,SAAS,UAAU,SAAS,KAAK,EAAE,SAAS,KAAK,EAAE,GAAG,KAAK,SAAS,QAAQ,SAAS,eAAe,eAAe;AACnM;AAAA,IACF;AACA,cAAU,EAAE;AAAA,EACd;AACA,QAAM,QACJ,gBAAAJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,WAAW,cAAc,QAAQ,QAAQ;AAAA,MACzC,aAAa,eAAe;AAAA,MAC5B,QAAQ,WAAW,SAAS;AAAA,MAC5B,WAAW,WAAW,CAAC,GAAI,cAAc,CAAC,WAAW,IAAI,CAAC,GAAI,GAAG,OAAO,IAAI;AAAA,MAC5E,WAAU;AAAA;AAAA,EACZ;AAEF,QAAM,YAAY,cAAc,OAAO,SAAS,KAC9C,gBAAAA,MAAC,QAAG,WAAU,uBAAsB,cAAW,oBAC5C,iBAAO,IAAI,CAAC,OAAO,MAClB,gBAAAA,MAAC,QAAW,WAAW,MAAM,aAAa,UAAU,iBAAiB,MAAM,aAAa,YAAY,mBAAmB,yBACpH,0BAAgB,KAAK,KADf,CAET,CACD,GACH;AAEF,MAAI,CAAC;AACH,WACE,gBAAAC,MAAC,SAAI,WAAW,uBAAuB,SAAS,IAAI,yBAAsB,IACvE;AAAA;AAAA,MACD,gBAAAD,MAAC,oBAAiB,YAAwB;AAAA,MACzC;AAAA,OACH;AAGJ,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,iDAAiD,SAAS;AAAA,MACrE,yBAAsB;AAAA,MACtB,WAAW,CAAC,MAAM;AAChB,cAAM,KAAK,EAAE;AACb,YAAI,EAAE,EAAE,WAAW,EAAE,YAAY,EAAE,IAAI,YAAY,MAAM,OAAO,4BAA4B,KAAK,GAAG,OAAO,EAAG;AAC9G,UAAE,eAAe;AACjB,YAAI,EAAE,SAAU,YAAW,KAAK;AAAA,YAC3B,YAAW,KAAK;AAAA,MACvB;AAAA,MAEA;AAAA,wBAAAA,MAAC,SAAI,WAAU,+BACZ;AAAA;AAAA,UACD,gBAAAD,MAAC,oBAAiB,YAAwB;AAAA,UAC1C,gBAAAC,MAAC,SAAI,WAAU,mEACb;AAAA,4BAAAD,MAAC,YAAO,MAAK,UAAS,WAAWE,MAAK,SAAS,MAAM,WAAW,KAAK,GAAG,UAAU,CAAC,MAAM,SAAS,OAAO,MAAM,UAAU,QAAQ,MAAM,SAAS,KAAK,mBAAmB,aAAU,IAAG,kBAErL;AAAA,YACA,gBAAAF,MAAC,YAAO,MAAK,UAAS,WAAWE,MAAK,SAAS,MAAM,WAAW,KAAK,GAAG,UAAU,CAAC,MAAM,SAAS,OAAO,MAAM,UAAU,QAAQ,MAAM,SAAS,KAAK,mBAAmB,aAAU,IAAG,kBAErL;AAAA,YACC,cAAc,UACb,gBAAAD,MAAC,WAAM,WAAU,2BACf;AAAA,8BAAAD,MAAC,WAAM,MAAK,YAAW,SAAS,OAAO,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,OAAO,GAAG;AAAA,cAAE;AAAA,eACxF;AAAA,YAED,gBAAgB,UACf,gBAAAC,MAAC,WAAM,WAAU,2BACf;AAAA,8BAAAD,MAAC,WAAM,MAAK,YAAW,SAAS,OAAO,UAAU,CAAC,MAAM,SAAS,EAAE,OAAO,OAAO,GAAG;AAAA,cAAE;AAAA,eACxF;AAAA,YAEF,gBAAAA,MAAC,UAAK,WAAU,WAAU,uBAAqB,eAAe,QAC3D,wBACC,gBAAAC,MAAAF,WAAA,EAAE;AAAA;AAAA,cACO,gBAAAC,MAAC,UAAK,WAAU,iBAAiB,uBAAY;AAAA,cAAQ;AAAA,cAC5D,gBAAAA,MAAC,YAAO,MAAK,UAAS,WAAU,aAAY,SAAS,MAAM,UAAU,IAAI,GAAG,mBAE5E;AAAA,eACF,IAEA,6EAEJ;AAAA,aACF;AAAA,UACC;AAAA,WACH;AAAA,QACA,gBAAAC,MAAC,SAAI,WAAU,+BACb;AAAA,0BAAAD,MAAC,eAAY,YAAwB,SAAS,cAAc,CAAC,WAAW,IAAI,QAAW;AAAA,UACvF,gBAAAA,MAAC,oBAAiB,YAAwB,QAAQ,aAAa,WAAU,+BAA8B;AAAA,UACvG,gBAAAC,MAAC,aAAQ,MAAI,MAAC,WAAU,+BACtB;AAAA,4BAAAD,MAAC,aAAQ,WAAU,sCAAqC,kBAAI;AAAA,YAC5D,gBAAAA,MAAC,iBAAc,YAAwB,WAAU,QAAO;AAAA,aAC1D;AAAA,UACA,gBAAAC,MAAC,aAAQ,WAAU,+BACjB;AAAA,4BAAAD,MAAC,aAAQ,WAAU,sCAAqC,4BAAc;AAAA,YACtE,gBAAAA,MAAC,iBAAc,YAAwB,WAAU,QAAO;AAAA,aAC1D;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":["useMemo","useMemo","jsx","useMemo","useState","React","useMemo","useMemo","jsx","jsxs","jsx","jsx","jsxs","useMemo","React","useState","jsx","jsxs","useState","useEffect","useRef","useState","jsx","jsxs","seconds","worst","useRef","useState","useEffect","useState","jsx","jsxs","input","btn","useState","useMemo","useState","describeMotionElements","jsx","jsxs","input","btn","useState","useMemo","describeMotionElements","Fragment","jsx","jsxs","btn","useState","useMemo"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-react",
3
- "version": "0.46.0",
3
+ "version": "0.48.0",
4
4
  "description": "React bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -123,7 +123,7 @@
123
123
  },
124
124
  "peerDependencies": {
125
125
  "@dagrejs/dagre": "^1.1.8",
126
- "@pixerate/editor": ">=0.67.0 <1.0.0-0",
126
+ "@pixerate/editor": ">=0.73.0 <1.0.0-0",
127
127
  "@tiptap/core": "^2.11.5",
128
128
  "@tiptap/pm": "^2.11.5",
129
129
  "@tiptap/react": "^2.11.5",
@@ -150,7 +150,7 @@
150
150
  "tsup": "^8.4.0",
151
151
  "typescript": "^5.7.3",
152
152
  "vitest": "^4.1.11",
153
- "@pixerate/editor": "0.67.0"
153
+ "@pixerate/editor": "0.73.0"
154
154
  },
155
155
  "scripts": {
156
156
  "build": "tsup",