@kokoa/clotho-editor 0.2.0 → 0.4.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.
- package/dist/{chunk-FAI2G3XK.js → chunk-WOP52KFW.js} +196 -4
- package/dist/chunk-WOP52KFW.js.map +1 -0
- package/dist/clotho-editor.css +301 -0
- package/dist/index.d.ts +62 -3
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/{main-SKM3P4X7.js → main-HDE5SDKM.js} +736 -12
- package/dist/main-HDE5SDKM.js.map +1 -0
- package/package.json +3 -3
- package/dist/chunk-FAI2G3XK.js.map +0 -1
- package/dist/main-SKM3P4X7.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/Studio.tsx","../src/template-editor-plugin.ts","../src/story-editor-plugin.ts","../src/StudioMount.tsx","../src/repository.ts","../src/visual-regression-plugin.ts","../src/responsive-inspector-plugin.ts","../src/performance-profiler-plugin.ts","../src/linter-plugin.ts"],"names":["setDef","addElement","deleteElement","document","useEffect","jsx","escapeHtml","renderDocumentToSvg"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { AnimationDocument } from \"@kokoa/clotho\";\nimport { AnimationStage, usePlayer } from \"@kokoa/clotho/react\";\nimport { downloadAnimationJson } from \"./export-json\";\n\ntype EditableElement = Record<string, unknown> & { id: string; type: string };\ntype ElementList = AnimationDocument[\"elements\"];\n\nexport interface StudioProps {\n initial: AnimationDocument;\n onSave: (def: AnimationDocument) => void | Promise<void>;\n}\n\nfunction elementsOf(def: AnimationDocument): EditableElement[] {\n return def.elements as unknown as EditableElement[];\n}\n\nexport function Studio({ initial, onSave }: StudioProps): React.JSX.Element {\n const [def, setDef] = useState<AnimationDocument>(initial);\n const [selectedId, setSelectedId] = useState<string | null>(\n elementsOf(initial)[0]?.id ?? null,\n );\n const [playing, setPlaying] = useState(false);\n const [time, setTime] = useState(0);\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n\n // The clock for preview playback. It lives outside React (core/player), so the\n // editor subscribes rather than owning a rAF loop of its own.\n const { player, state: playerState } = usePlayer(def, { autoplay: false });\n\n useEffect(() => {\n if (playing) player.play();\n else {\n player.pause();\n player.seek(time);\n }\n }, [playing, player, time]);\n\n const elements = elementsOf(def);\n const selected = elements.find((e) => e.id === selectedId) ?? null;\n const scalarProps = selected\n ? Object.entries(selected).filter(\n ([key, value]) =>\n (typeof value === \"string\" || typeof value === \"number\") &&\n key !== \"id\" &&\n key !== \"type\",\n )\n : [];\n\n function setElements(next: EditableElement[]): void {\n setDef((current) => ({\n ...current,\n elements: next as unknown as ElementList,\n }));\n setSaved(false);\n }\n\n function updateElement(\n id: string,\n key: string,\n raw: string,\n numeric: boolean,\n ): void {\n setElements(\n elements.map((e) =>\n e.id === id ? { ...e, [key]: numeric ? Number(raw) : raw } : e,\n ),\n );\n }\n\n function addElement(): void {\n const id = `el-${Date.now().toString(36)}`;\n const el: EditableElement = {\n type: \"text\",\n id,\n x: 100,\n y: 100,\n rotation: 0,\n content: \"New\",\n translations: {},\n references: {},\n fontSize: 24,\n color: \"#4f46e5\",\n textAnchor: \"start\",\n appearances: [{ start: 0, end: def.duration }],\n tracks: [],\n };\n setElements([...elements, el]);\n setSelectedId(id);\n }\n\n function deleteElement(id: string): void {\n setElements(elements.filter((e) => e.id !== id));\n if (selectedId === id) setSelectedId(null);\n }\n\n async function handleSave(): Promise<void> {\n setSaving(true);\n try {\n await onSave(def);\n setSaved(true);\n } finally {\n setSaving(false);\n }\n }\n\n return (\n <div className=\"studio\">\n <aside className=\"studio-panel studio-left\">\n <div className=\"studio-panel-head\">\n <span>요소 ({elements.length})</span>\n <button type=\"button\" className=\"studio-btn\" onClick={addElement}>\n + 추가\n </button>\n </div>\n <ul className=\"studio-el-list\">\n {elements.map((e) => (\n <li key={e.id}>\n <button\n type=\"button\"\n className={\n e.id === selectedId ? \"studio-el active\" : \"studio-el\"\n }\n onClick={() => setSelectedId(e.id)}\n >\n <span className=\"studio-el-type\">{e.type}</span>\n <span className=\"studio-el-id\">{e.id}</span>\n </button>\n </li>\n ))}\n </ul>\n </aside>\n\n <div className=\"studio-preview\">\n <div className=\"studio-preview-bar\">\n <button\n type=\"button\"\n className=\"studio-btn\"\n onClick={() => downloadAnimationJson(def)}\n >\n JSON 내보내기\n </button>\n <button\n type=\"button\"\n className=\"studio-btn\"\n onClick={() => setPlaying((p) => !p)}\n >\n {playing ? \"⏸ 정지\" : \"▶ 재생\"}\n </button>\n <input\n type=\"range\"\n min={0}\n max={def.duration}\n step={50}\n value={time}\n disabled={playing}\n onChange={(e) => {\n setTime(Number(e.target.value));\n setPlaying(false);\n }}\n />\n <span className=\"studio-time\">\n {time} / {def.duration}ms\n </span>\n <button\n type=\"button\"\n className=\"studio-btn studio-save\"\n onClick={() => void handleSave()}\n disabled={saving}\n >\n {saving ? \"저장 중…\" : saved ? \"✓ 저장됨\" : \"저장\"}\n </button>\n </div>\n <div className=\"studio-canvas\">\n {/* One frame at a time: the editor's scrubber is the source of truth, and the\n player only supplies the clock while previewing. Same buildScene path as\n the published animation, so preview and production cannot diverge. */}\n <AnimationStage doc={def} time={playing ? playerState.time : time} />\n </div>\n </div>\n\n <aside className=\"studio-panel studio-right\">\n <div className=\"studio-panel-head\">메타</div>\n <label className=\"studio-field\">\n <span>제목</span>\n <input\n value={def.title}\n onChange={(e) => {\n setDef((d) => ({ ...d, title: e.target.value }));\n setSaved(false);\n }}\n />\n </label>\n <label className=\"studio-field\">\n <span>duration (ms)</span>\n <input\n type=\"number\"\n value={def.duration}\n onChange={(e) => {\n setDef((d) => ({ ...d, duration: Number(e.target.value) }));\n setSaved(false);\n }}\n />\n </label>\n <div className=\"studio-panel-head\">\n 속성 {selected ? `(${selected.type})` : \"\"}\n </div>\n {selected ? (\n <>\n {scalarProps.map(([key, value]) => (\n <label key={key} className=\"studio-field\">\n <span>{key}</span>\n <input\n value={String(value)}\n onChange={(e) =>\n updateElement(\n selected.id,\n key,\n e.target.value,\n typeof value === \"number\",\n )\n }\n />\n </label>\n ))}\n <button\n type=\"button\"\n className=\"studio-btn studio-del\"\n onClick={() => deleteElement(selected.id)}\n >\n 요소 삭제\n </button>\n </>\n ) : (\n <p className=\"studio-empty\">요소를 선택하세요.</p>\n )}\n </aside>\n </div>\n );\n}\n","import type {\n AnimationTemplate,\n ParameterSchema,\n TemplateParameterError,\n TemplateReference,\n} from \"@kokoa/clotho\";\nimport { downloadAnimationJson } from \"./export-json\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport function initialParameterValue(schema: ParameterSchema): unknown {\n if (schema.default !== undefined) return structuredClone(schema.default);\n if (schema.type === \"string\") return \"\";\n if (schema.type === \"number\") return schema.min ?? 0;\n if (schema.type === \"boolean\") return false;\n if (schema.type === \"enum\") return schema.values[0];\n if (schema.type === \"array\") return [];\n return Object.fromEntries(\n Object.entries(schema.properties).map(([key, child]) => [\n key,\n initialParameterValue(child),\n ]),\n );\n}\n\nexport function parameterInputValue(\n schema: ParameterSchema,\n raw: string | boolean,\n): unknown {\n if (schema.type === \"boolean\") return Boolean(raw);\n if (schema.type === \"number\") return Number(raw);\n if (schema.type === \"array\" || schema.type === \"object\")\n return JSON.parse(String(raw));\n return String(raw);\n}\n\nfunction downloadReference(reference: TemplateReference): void {\n const blob = new Blob([JSON.stringify(reference, null, 2)], {\n type: \"application/json\",\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `${reference.templateId.replace(/[^a-z0-9._-]/gi, \"-\")}.template.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n}\n\nfunction field(\n key: string,\n schema: ParameterSchema,\n value: unknown,\n onChange: (value: unknown) => void,\n): HTMLElement {\n const label = document.createElement(\"label\");\n label.className = \"studio-field studio-template-field\";\n const title = document.createElement(\"span\");\n title.textContent = key;\n if (schema.description) title.title = schema.description;\n label.append(title);\n\n let control: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n if (schema.type === \"enum\") {\n control = document.createElement(\"select\");\n for (const option of schema.values) {\n const element = document.createElement(\"option\");\n element.value = option;\n element.textContent = option;\n control.append(element);\n }\n control.value = String(value);\n } else if (schema.type === \"array\" || schema.type === \"object\") {\n control = document.createElement(\"textarea\");\n control.rows = 3;\n control.value = JSON.stringify(value, null, 2);\n } else {\n control = document.createElement(\"input\");\n control.type = schema.type === \"boolean\" ? \"checkbox\" : schema.type;\n if (schema.type === \"boolean\") control.checked = Boolean(value);\n else control.value = String(value);\n if (schema.type === \"number\") {\n if (schema.min !== undefined) control.min = String(schema.min);\n if (schema.max !== undefined) control.max = String(schema.max);\n control.step = schema.integer ? \"1\" : \"any\";\n }\n if (schema.type === \"string\") {\n if (schema.minLength !== undefined) control.minLength = schema.minLength;\n if (schema.maxLength !== undefined) control.maxLength = schema.maxLength;\n if (schema.pattern !== undefined) control.pattern = schema.pattern;\n }\n }\n control.dataset.templateParameter = key;\n const update = (): void => {\n try {\n const raw =\n control instanceof HTMLInputElement && control.type === \"checkbox\"\n ? control.checked\n : control.value;\n onChange(parameterInputValue(schema, raw));\n control.setCustomValidity(\"\");\n } catch {\n control.setCustomValidity(\"올바른 JSON을 입력하세요.\");\n }\n };\n control.addEventListener(\n schema.type === \"enum\" || schema.type === \"boolean\" ? \"change\" : \"input\",\n update,\n );\n label.append(control);\n return label;\n}\n\n/** Built-in authoring panel for trusted templates registered by the host. */\nexport function createTemplateEditorPlugin(\n templates: readonly AnimationTemplate[],\n): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.templates\",\n name: \"Template parameters\",\n capabilities: [\"editor\"],\n editor: { panels: [\"parameters\"] },\n },\n panels: {\n parameters: {\n id: \"parameters\",\n label: \"Template parameters\",\n mount(container, context) {\n if (templates.length === 0) return;\n container.classList.add(\n \"studio-tools-section\",\n \"studio-template-panel\",\n );\n const heading = document.createElement(\"div\");\n heading.className = \"studio-tools-title\";\n heading.textContent = \"Template\";\n const select = document.createElement(\"select\");\n select.className = \"studio-template-select\";\n for (const template of templates) {\n const option = document.createElement(\"option\");\n option.value = template.id;\n option.textContent = template.id;\n select.append(option);\n }\n const form = document.createElement(\"div\");\n const status = document.createElement(\"p\");\n status.className = \"studio-props-empty studio-template-status\";\n const actions = document.createElement(\"div\");\n actions.className = \"studio-align-row\";\n const standalone = document.createElement(\"button\");\n standalone.className = \"studio-btn\";\n standalone.textContent = \"Standalone JSON\";\n const reference = document.createElement(\"button\");\n reference.className = \"studio-btn\";\n reference.textContent = \"Template 참조\";\n actions.append(standalone, reference);\n container.append(heading, select, form, status, actions);\n\n let active = templates[0]!;\n let values: Record<string, unknown> = {};\n let previewDocument = context.getDocument();\n const rebuild = (): void => {\n try {\n previewDocument = active.instantiate(values);\n context.replaceDocument(previewDocument);\n status.textContent = \"parameter가 미리보기에 반영되었습니다.\";\n status.removeAttribute(\"data-error\");\n } catch (error) {\n const issues = (error as TemplateParameterError).issues;\n status.textContent = issues\n ? issues\n .map(({ path, message }) => `${path}: ${message}`)\n .join(\" · \")\n : String(error);\n status.dataset.error = \"true\";\n }\n };\n const render = (): void => {\n values = Object.fromEntries(\n Object.entries(active.parameters).map(([key, schema]) => [\n key,\n initialParameterValue(schema),\n ]),\n );\n form.replaceChildren(\n ...Object.entries(active.parameters).map(([key, schema]) =>\n field(key, schema, values[key], (value) => {\n values[key] = value;\n rebuild();\n }),\n ),\n );\n rebuild();\n };\n select.addEventListener(\"change\", () => {\n active =\n templates.find(({ id }) => id === select.value) ?? templates[0]!;\n render();\n });\n standalone.addEventListener(\"click\", () =>\n downloadAnimationJson(previewDocument),\n );\n reference.addEventListener(\"click\", () =>\n downloadReference(active.reference(values)),\n );\n render();\n },\n },\n },\n };\n}\n","import {\n defineStory,\n type AnimationDocument,\n type StoryEdge,\n type StoryManifest,\n} from \"@kokoa/clotho\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport interface StoryEditorOptions {\n manifest: StoryManifest;\n onChange?(manifest: StoryManifest): void;\n}\n\nexport function replaceStoryNodeDocument(\n manifest: StoryManifest,\n nodeId: string,\n document: AnimationDocument,\n): StoryManifest {\n return defineStory({\n ...manifest,\n nodes: manifest.nodes.map((node) =>\n node.id === nodeId ? { ...node, document } : node,\n ),\n });\n}\n\nexport function appendStoryEdge(\n manifest: StoryManifest,\n edge: StoryEdge,\n): StoryManifest {\n return defineStory({ ...manifest, edges: [...manifest.edges, edge] });\n}\n\nexport function createStoryEditorPlugin(\n options: StoryEditorOptions,\n): EditorPluginDefinition {\n let manifest = structuredClone(options.manifest);\n let activeNode = manifest.initialNode;\n return {\n manifest: {\n id: \"dev.clotho.story\",\n name: \"Story Graph\",\n capabilities: [\"editor\"],\n editor: { panels: [\"story-graph\"] },\n },\n panels: {\n \"story-graph\": {\n id: \"story-graph\",\n label: \"Story Graph\",\n mount(container, context) {\n const render = () => {\n container.innerHTML = `<div class=\"studio-tools-section\"><div class=\"studio-tools-title\">Story Graph</div><div class=\"studio-story-nodes\">${manifest.nodes.map((node) => `<button type=\"button\" class=\"studio-btn${node.id === activeNode ? \" is-active\" : \"\"}\" data-story-node=\"${escapeAttribute(node.id)}\">${escapeHtml(node.title || node.id)}</button>`).join(\"\")}</div><div class=\"studio-tools-hint\">${manifest.edges.map((edge) => `${escapeHtml(edge.from)} → ${escapeHtml(edge.to)}${edge.label ? ` · ${escapeHtml(edge.label)}` : \"\"}`).join(\"<br>\") || \"연결이 없습니다.\"}</div></div>`;\n };\n const click = (event: Event) => {\n const button = (event.target as HTMLElement).closest<HTMLElement>(\n \"[data-story-node]\",\n );\n const nextId = button?.dataset.storyNode;\n if (!nextId || nextId === activeNode) return;\n manifest = replaceStoryNodeDocument(\n manifest,\n activeNode,\n context.getDocument(),\n );\n const node = manifest.nodes.find(({ id }) => id === nextId);\n if (!node) return;\n activeNode = nextId;\n context.replaceDocument(node.document);\n options.onChange?.(structuredClone(manifest));\n render();\n };\n container.addEventListener(\"click\", click);\n render();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n}\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replaceAll('\"', \""\");\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useRef } from \"react\";\nimport type { AnimationTemplate } from \"@kokoa/clotho\";\nimport type { AnimationRepository } from \"./repository\";\nimport { configureAnimationRepository } from \"./legacy/api\";\nimport type { ImageUploadResolver } from \"./legacy/studio-image-upload\";\nimport type {\n DocumentImporter,\n EditorPluginDefinition,\n EditorPluginPermissionResolver,\n} from \"./plugin-host\";\nimport { createTemplateEditorPlugin } from \"./template-editor-plugin\";\nimport {\n createStoryEditorPlugin,\n type StoryEditorOptions,\n} from \"./story-editor-plugin\";\n// The stylesheet ships as a separate entry rather than an import, so a consumer that\n// only wants the headless pieces does not pull CSS into its bundle:\n// import \"@kokoa/clotho-editor/styles.css\";\n\nexport interface StudioMountProps {\n initialId?: string;\n repository?: AnimationRepository;\n editorTitle?: string;\n resolveImage?: ImageUploadResolver;\n importDocument?: DocumentImporter;\n plugins?: readonly EditorPluginDefinition[];\n resolvePluginPermissions?: EditorPluginPermissionResolver;\n /** Trusted build-time templates shown as a parameter panel. */\n templates?: readonly AnimationTemplate[];\n /** Optional multi-document Story Graph edited alongside the active node timeline. */\n story?: StoryEditorOptions;\n}\n\nconst EMPTY_EDITOR_PLUGINS: readonly EditorPluginDefinition[] = [];\nconst EMPTY_TEMPLATES: readonly AnimationTemplate[] = [];\nconst DENY_PLUGIN_PERMISSIONS: EditorPluginPermissionResolver = () => ({});\n\nconst CANVAS_PRESETS: {\n id: string;\n label: string;\n sub: string;\n w: number;\n h: number;\n}[] = [\n { id: \"800x500\", label: \"8:5\", sub: \"800×500\", w: 32, h: 20 },\n { id: \"1280x720\", label: \"16:9\", sub: \"HD\", w: 32, h: 18 },\n { id: \"1024x768\", label: \"4:3\", sub: \"1024×768\", w: 28, h: 21 },\n { id: \"600x600\", label: \"1:1\", sub: \"정사각\", w: 22, h: 22 },\n { id: \"1200x400\", label: \"3:1\", sub: \"와이드\", w: 36, h: 12 },\n { id: \"375x812\", label: \"9:19\", sub: \"모바일\", w: 14, h: 30 },\n];\n\nconst PRESET_HTML = CANVAS_PRESETS.map(\n (p) => `\n <button type=\"button\" class=\"studio-preset-btn\" aria-label=\"캔버스 크기 ${p.id} (${p.sub})\" title=\"${p.id} · ${p.sub}\" data-canvas-preset=\"${p.id}\">\n <svg class=\"studio-preset-thumb\" viewBox=\"0 0 ${p.w + 2} ${p.h + 2}\" width=\"${p.w + 2}\" height=\"${p.h + 2}\" aria-hidden=\"true\">\n <rect x=\"1\" y=\"1\" width=\"${p.w}\" height=\"${p.h}\" rx=\"2\" />\n </svg>\n <span class=\"studio-preset-label\">${p.label}</span>\n <span class=\"studio-preset-sub\">${p.sub}</span>\n </button>`,\n).join(\"\");\n\nconst SKELETON = `\n<div id=\"studio-app\" class=\"studio-app\">\n <header class=\"studio-header\">\n <h1 id=\"studio-editor-title\" class=\"studio-header-title\">Clotho Editor</h1>\n <div class=\"studio-header-actions\">\n <span class=\"studio-plugin-toolbar\" data-editor-plugin-slot=\"toolbar\"></span>\n <button type=\"button\" id=\"studio-open\" class=\"studio-btn\" aria-label=\"저장된 애니메이션 열기\">📁 열기</button>\n <button type=\"button\" id=\"studio-new\" class=\"studio-btn\" aria-label=\"새 애니메이션 만들기\">+ 새 애니메이션</button>\n <button type=\"button\" id=\"studio-undo\" class=\"studio-btn studio-btn-icon\" aria-label=\"실행 취소\" title=\"실행 취소 (⌘Z)\" disabled>↶</button>\n <button type=\"button\" id=\"studio-redo\" class=\"studio-btn studio-btn-icon\" aria-label=\"다시 실행\" title=\"다시 실행 (⌘⇧Z / ⌘Y)\" disabled>↷</button>\n <button type=\"button\" id=\"studio-grid-toggle\" class=\"studio-btn studio-btn-grid\" aria-label=\"격자 + 스냅\" title=\"격자 + 스냅 (G)\" aria-pressed=\"false\"><span class=\"studio-btn-grid-icon\">⊞</span><span class=\"studio-btn-grid-label\" id=\"studio-grid-label\">격자 끔</span></button>\n <input type=\"text\" id=\"studio-title\" class=\"studio-title-input\" placeholder=\"제목\" aria-label=\"애니메이션 제목\" disabled />\n <span id=\"studio-id-display\" class=\"studio-id-display\"></span>\n <span id=\"studio-status\" class=\"studio-status\" aria-live=\"polite\">대기 중</span>\n <button type=\"button\" id=\"studio-save\" class=\"studio-btn studio-btn-primary\" aria-label=\"저장\" disabled>💾 저장 (⌘S)</button>\n <button type=\"button\" id=\"studio-export-json\" class=\"studio-btn\" aria-label=\"현재 애니메이션을 JSON 파일로 내보내기\" disabled>⬇ JSON 내보내기</button>\n <button type=\"button\" id=\"studio-player-preview\" class=\"studio-btn\" aria-label=\"실제 애니메이션 컴포넌트 미리보기\" aria-pressed=\"false\">↗ 실제 미리보기</button>\n <button type=\"button\" id=\"studio-import-json\" class=\"studio-btn\" aria-label=\"JSON 파일에서 애니메이션 가져오기\">⬆ JSON 가져오기</button>\n <input type=\"file\" id=\"studio-import-file\" accept=\"application/json,.json\" hidden />\n <button type=\"button\" id=\"studio-delete\" class=\"studio-btn studio-btn-danger\" aria-label=\"삭제\" disabled>🗑 삭제</button>\n </div>\n </header>\n\n <div class=\"studio-body\">\n <aside class=\"studio-tools\" aria-label=\"요소 추가\">\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">도구</div>\n <button type=\"button\" class=\"studio-tool-btn is-active\" data-studio-tool=\"select\" aria-pressed=\"true\" title=\"선택 · 이동 · 크기 (V)\"><span>↖ 선택 · 이동 · 크기</span><kbd>V</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"rect\" title=\"사각형 (R)\" aria-label=\"사각형 도구\"><span>□ Rect</span><kbd>R</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"circle\" title=\"원 (O)\" aria-label=\"원 도구\"><span>○ Circle</span><kbd>O</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"line\" title=\"선 (L)\" aria-label=\"선 도구\"><span>/ Line</span><kbd>L</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"arrow\" title=\"화살표 (A)\" aria-label=\"화살표 도구\"><span>↗ Arrow</span><kbd>A</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"text\" title=\"텍스트 (T)\" aria-label=\"텍스트 도구\"><span>T Text</span><kbd>T</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"image\" title=\"이미지 (I)\" aria-label=\"이미지 도구\"><span>🖼 Image</span><kbd>I</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"path\" title=\"Path (B)\" aria-label=\"Path 도구\"><span>✎ Path</span><kbd>B</kbd></button>\n <div class=\"studio-tool-with-option\"><button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"polygon\" title=\"다각형 (Y)\" aria-label=\"다각형 도구\"><span>⬢ Polygon</span><kbd>Y</kbd></button><label>변 <input type=\"number\" id=\"studio-polygon-sides\" min=\"3\" max=\"24\" value=\"6\" aria-label=\"다각형의 변 개수\" /></label></div>\n <button type=\"button\" class=\"studio-tool-btn\" id=\"studio-open-icons\" title=\"아이콘 라이브러리\" aria-label=\"아이콘 라이브러리 추가\">🎨 Icons</button>\n </div>\n <div class=\"studio-plugin-panels\" data-editor-plugin-slot=\"panel\"></div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">캔버스 크기</div>\n <div class=\"studio-canvas-size-row\">\n <input type=\"number\" id=\"studio-canvas-width\" class=\"studio-canvas-size-input\" min=\"100\" max=\"8000\" step=\"10\" placeholder=\"width\" />\n <span class=\"studio-canvas-size-x\">×</span>\n <input type=\"number\" id=\"studio-canvas-height\" class=\"studio-canvas-size-input\" min=\"100\" max=\"8000\" step=\"10\" placeholder=\"height\" />\n </div>\n <div class=\"studio-canvas-presets\">${PRESET_HTML}</div>\n </div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">이미지</div>\n <button type=\"button\" class=\"studio-tool-btn\" id=\"studio-image-upload\">📤 이미지 업로드</button>\n <input type=\"file\" id=\"studio-image-file\" accept=\"image/*\" hidden />\n <div class=\"studio-tools-hint\">이미지를 캔버스에 직접 드래그하거나 ⌘V 로 붙여넣어도 됩니다.</div>\n </div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">단축키</div>\n <button type=\"button\" class=\"studio-tool-btn\" id=\"studio-help\">⌨ 단축키 보기 (?)</button>\n </div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">요소 목록</div>\n <input type=\"text\" id=\"studio-element-search\" class=\"studio-element-search\" placeholder=\"🔍 검색 (name / label / id / type)\" autocomplete=\"off\" />\n <ul id=\"studio-element-list\" class=\"studio-element-list\"></ul>\n </div>\n </aside>\n\n <main class=\"studio-canvas-wrap\">\n <div class=\"studio-canvas-frame\">\n <svg id=\"studio-canvas\" class=\"studio-canvas\" xmlns=\"http://www.w3.org/2000/svg\"></svg>\n </div>\n <button type=\"button\" id=\"studio-floating-help\" class=\"studio-floating-help\" aria-label=\"단축키 보기\" title=\"단축키 보기 (? / Shift+/)\">?</button>\n <div id=\"studio-help-hint\" class=\"studio-help-hint\" hidden>\n <span>💡 단축키는 <kbd>?</kbd> 또는 우측 하단 버튼으로 확인하세요</span>\n <button type=\"button\" id=\"studio-help-hint-close\" aria-label=\"닫기\">✕</button>\n </div>\n </main>\n\n <aside class=\"studio-props\" aria-label=\"속성 패널\">\n <div id=\"studio-props-content\" class=\"studio-props-content\">\n <p class=\"studio-props-empty\">요소 또는 step 을 선택하세요.</p>\n </div>\n <div class=\"studio-plugin-inspectors\" data-editor-plugin-slot=\"inspector\"></div>\n </aside>\n </div>\n\n <div id=\"studio-timeline-resizer\" class=\"studio-timeline-resizer\" role=\"separator\" aria-orientation=\"horizontal\" aria-label=\"타임라인 영역 크기 조정\" tabindex=\"0\"><span class=\"studio-timeline-resizer-grip\" aria-hidden=\"true\"><i></i><i></i><i></i></span></div>\n <footer class=\"studio-timeline-wrap\">\n <div class=\"studio-timeline-header\">\n <button type=\"button\" id=\"studio-play\" class=\"studio-btn\">▶ Play</button>\n <button type=\"button\" id=\"studio-restart\" class=\"studio-btn\">⟲ Reset</button>\n <label class=\"studio-speed\">속도\n <input type=\"range\" id=\"studio-speed\" min=\"0.25\" max=\"3\" step=\"0.25\" value=\"1\" />\n <span id=\"studio-speed-value\">1.00x</span>\n </label>\n <label class=\"studio-timeline-option\"><input type=\"checkbox\" id=\"studio-preview-loop\" /> 무한 재생</label>\n <button type=\"button\" id=\"studio-detach-timeline\" class=\"studio-btn\" aria-pressed=\"false\">▣ 타임라인 분리</button>\n <span class=\"studio-timeline-spacer\"></span>\n <button type=\"button\" id=\"studio-add-step\" class=\"studio-btn\">+ Chapter 추가</button>\n </div>\n <div class=\"studio-timeline-tracks-wrap\">\n <div id=\"studio-timeline-tracks\" class=\"studio-timeline-tracks\"></div>\n </div>\n <div class=\"studio-element-tracks-wrap\">\n <div id=\"studio-element-tracks\" class=\"studio-element-tracks\"></div>\n </div>\n </footer>\n\n <dialog id=\"studio-library-dialog\" class=\"studio-dialog\">\n <div class=\"studio-dialog-header\">\n <h2>저장된 애니메이션</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close>✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <ul id=\"studio-library-list\" class=\"studio-library-list\"></ul>\n </div>\n </dialog>\n\n <dialog id=\"studio-icon-dialog\" class=\"studio-dialog\">\n <div class=\"studio-dialog-header\">\n <h2>🎨 아이콘 라이브러리</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-icon-dialog-close>✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <input type=\"search\" id=\"studio-icon-search\" placeholder=\"아이콘 검색…\" class=\"studio-icon-search-input\" />\n <div id=\"studio-icon-list\"></div>\n </div>\n </dialog>\n\n <dialog id=\"studio-help-dialog\" class=\"studio-dialog studio-dialog-small\">\n <div class=\"studio-dialog-header\">\n <h2>⌨ 단축키</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close>✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <table class=\"studio-help-table\">\n <tbody>\n <tr><th>⌘ S</th><td>저장</td></tr>\n <tr><th>⌘ Z / ⌘ ⇧ Z</th><td>Undo / Redo</td></tr>\n <tr><th>⌘ C / V / X</th><td>요소 복사 / 붙여넣기 / 잘라내기</td></tr>\n <tr><th>V / R / O</th><td>선택 / 사각형 / 원 도구</td></tr>\n <tr><th>L / A</th><td>선 / 화살표 도구</td></tr>\n <tr><th>T / I / B / Y</th><td>텍스트 / 이미지 / Path / 다각형 도구</td></tr>\n <tr><th>⌘·Ctrl·Shift + 클릭</th><td>여러 요소 선택 또는 선택 해제</td></tr>\n <tr><th>Delete / Backspace</th><td>선택된 요소 또는 step 삭제</td></tr>\n <tr><th>?</th><td>이 화면 열기</td></tr>\n <tr><th>Esc</th><td>선택 해제 / 다이얼로그 닫기</td></tr>\n <tr><th>드래그 (캔버스)</th><td>요소 이동</td></tr>\n <tr><th>드래그 (요소 위 dot)</th><td>화살표 연결</td></tr>\n <tr><th>드래그 (선/화살표 끝점)</th><td>끝점 재배치 + 다른 요소에 sticky</td></tr>\n <tr><th>드래그 (회전 핸들)</th><td>요소 회전</td></tr>\n <tr><th>드래그 (타임라인 바 우측)</th><td>step duration 조정</td></tr>\n <tr><th>이미지 드래그 in</th><td>이미지 업로드 + 배치</td></tr>\n </tbody>\n </table>\n </div>\n </dialog>\n\n <dialog id=\"studio-new-dialog\" class=\"studio-dialog studio-dialog-small\">\n <div class=\"studio-dialog-header\">\n <h2 id=\"studio-new-dialog-title\">새 애니메이션 만들기</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close aria-label=\"닫기\">✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <label class=\"studio-field\"><span>ID (영문 소문자 / 숫자 / - / _)</span>\n <input type=\"text\" id=\"studio-new-id\" placeholder=\"예: user-login-flow\" />\n </label>\n <label class=\"studio-field\"><span>제목</span>\n <input type=\"text\" id=\"studio-new-title\" placeholder=\"사용자 로그인 흐름\" />\n </label>\n <div id=\"studio-new-error\" class=\"studio-new-error\"></div>\n </div>\n <footer class=\"studio-dialog-footer\">\n <button type=\"button\" class=\"studio-btn\" data-studio-dialog-close>취소</button>\n <button type=\"button\" id=\"studio-new-create\" class=\"studio-btn studio-btn-primary\">만들기</button>\n </footer>\n </dialog>\n\n <dialog id=\"studio-palette-dialog\" class=\"studio-palette-dialog\">\n <input type=\"text\" id=\"studio-palette-input\" class=\"studio-palette-input\" placeholder=\"🔍 명령 또는 요소 검색…\" autocomplete=\"off\" spellcheck=\"false\" />\n <ul id=\"studio-palette-list\" class=\"studio-palette-list\"></ul>\n <div class=\"studio-palette-footer\">↑↓ 이동 · Enter 실행 · Esc 닫기</div>\n </dialog>\n\n <dialog id=\"studio-history-dialog\" class=\"studio-history-dialog\">\n <div class=\"studio-history-header\">\n <h2>📜 작업 이력</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close aria-label=\"닫기\">✕</button>\n </div>\n <ul id=\"studio-history-list\" class=\"studio-history-list\"></ul>\n <div class=\"studio-history-footer\">항목을 클릭하면 해당 시점으로 이동합니다 · ⌘Z / ⌘⇧Z</div>\n </dialog>\n</div>\n`;\n\nexport function StudioMount({\n initialId,\n repository,\n editorTitle = \"Clotho Editor\",\n resolveImage,\n importDocument,\n plugins = EMPTY_EDITOR_PLUGINS,\n resolvePluginPermissions = DENY_PLUGIN_PERMISSIONS,\n templates = EMPTY_TEMPLATES,\n story,\n}: StudioMountProps): React.JSX.Element {\n const inited = useRef(false);\n const mountedPlugins = useMemo(\n () => [\n ...(templates.length > 0 ? [createTemplateEditorPlugin(templates)] : []),\n ...(story ? [createStoryEditorPlugin(story)] : []),\n ...plugins,\n ],\n [plugins, templates, story],\n );\n const permissionResolver = useMemo<EditorPluginPermissionResolver>(\n () => (plugin) =>\n plugin.id === \"dev.clotho.templates\" || plugin.id === \"dev.clotho.story\"\n ? { ui: true, documentRead: true, documentWrite: true }\n : resolvePluginPermissions(plugin),\n [resolvePluginPermissions],\n );\n\n useEffect(() => {\n if (inited.current) return;\n inited.current = true;\n if (repository) configureAnimationRepository(repository);\n let disposed = false;\n let cleanup: (() => void) | undefined;\n void import(\"./legacy/main\").then(({ initStudio }) => {\n if (disposed) return;\n cleanup = initStudio({\n initialId,\n editorTitle,\n resolveImage,\n importDocument,\n plugins: mountedPlugins,\n resolvePluginPermissions: permissionResolver,\n });\n });\n return () => {\n disposed = true;\n cleanup?.();\n document.body.classList.remove(\"editor-active\");\n document.documentElement.classList.remove(\"editor-active\");\n };\n }, [\n editorTitle,\n importDocument,\n initialId,\n mountedPlugins,\n repository,\n resolveImage,\n permissionResolver,\n ]);\n\n return (\n <section className=\"studio-shell w-full\" data-pagefind-ignore=\"all\">\n <div dangerouslySetInnerHTML={{ __html: SKELETON }} />\n </section>\n );\n}\n","import { animationDocumentSchema, type AnimationDocument } from \"@kokoa/clotho\";\n\nexport interface AnimationSummary {\n id: string;\n title: string;\n description: string;\n updatedAt?: string;\n source?: \"saved\" | \"example\";\n}\n\nexport interface AnimationRepository {\n list(): Promise<AnimationSummary[]>;\n load(id: string): Promise<AnimationDocument>;\n create(id: string, title: string): Promise<AnimationDocument>;\n save(def: AnimationDocument): Promise<AnimationDocument>;\n delete(id: string): Promise<void>;\n}\n\nexport interface LocalStorageRepositoryOptions {\n storageKey?: string;\n examples?: readonly AnimationDocument[];\n storage?: Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n}\n\nfunction browserStorage(): Storage {\n if (typeof localStorage === \"undefined\")\n throw new Error(\"이 저장소는 브라우저에서만 사용할 수 있습니다.\");\n return localStorage;\n}\n\nexport function createLocalStorageRepository(\n options: LocalStorageRepositoryOptions = {},\n): AnimationRepository {\n const prefix = options.storageKey ?? \"clotho-editor.animations\";\n const examples = new Map(\n (options.examples ?? []).map((value) => {\n const def = animationDocumentSchema.parse(value);\n return [def.id, def] as const;\n }),\n );\n const storage = (): Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\"> =>\n options.storage ?? browserStorage();\n const indexKey = `${prefix}:index`;\n const documentKey = (id: string): string => `${prefix}:document:${id}`;\n const readIds = (): string[] => {\n const value = storage().getItem(indexKey);\n if (!value) return [];\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed)\n ? parsed.filter((id): id is string => typeof id === \"string\")\n : [];\n } catch {\n return [];\n }\n };\n const write = (def: AnimationDocument): AnimationDocument => {\n const parsed = animationDocumentSchema.parse(def);\n const ids = readIds();\n if (!ids.includes(parsed.id))\n storage().setItem(indexKey, JSON.stringify([...ids, parsed.id]));\n storage().setItem(documentKey(parsed.id), JSON.stringify(parsed));\n return parsed;\n };\n const read = (id: string): AnimationDocument | null => {\n const value = storage().getItem(documentKey(id));\n return value ? animationDocumentSchema.parse(JSON.parse(value)) : null;\n };\n\n return {\n async list() {\n const saved = readIds()\n .map((id) => read(id))\n .filter((def): def is AnimationDocument => def !== null);\n const savedIds = new Set(saved.map((def) => def.id));\n return [\n ...saved.map((def) => ({\n id: def.id,\n title: def.title || def.id,\n description: def.description,\n source: \"saved\" as const,\n })),\n ...[...examples.values()]\n .filter((def) => !savedIds.has(def.id))\n .map((def) => ({\n id: def.id,\n title: def.title || def.id,\n description: def.description,\n source: \"example\" as const,\n })),\n ];\n },\n async load(id) {\n const def = read(id) ?? examples.get(id);\n if (!def) throw new Error(`'${id}' 애니메이션을 찾을 수 없습니다.`);\n return structuredClone(def);\n },\n async create(id, title) {\n if (read(id)) throw new Error(`'${id}' 애니메이션이 이미 있습니다.`);\n return write(\n animationDocumentSchema.parse({\n clothoVersion: 1,\n id,\n title,\n description: \"\",\n }),\n );\n },\n async save(def) {\n return write(def);\n },\n async delete(id) {\n storage().removeItem(documentKey(id));\n storage().setItem(\n indexKey,\n JSON.stringify(readIds().filter((value) => value !== id)),\n );\n },\n };\n}\n","import {\n AnimationAssertionError,\n animationFailureReport,\n animationSampleTimes,\n expectAnimation,\n snapshotAnimationMatrix,\n} from \"@kokoa/clotho/testing\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nfunction downloadReport(html: string): void {\n const url = URL.createObjectURL(new Blob([html], { type: \"text/html\" }));\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = \"clotho-animation-qa.html\";\n link.click();\n URL.revokeObjectURL(url);\n}\n\nexport function createVisualRegressionPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.visual-regression\",\n name: \"Animation QA\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"animation-qa\"] },\n },\n inspectors: {\n \"animation-qa\": {\n id: \"animation-qa\",\n label: \"Animation QA\",\n mount(container, context) {\n container.classList.add(\"studio-qa-panel\");\n const title = document.createElement(\"strong\");\n title.textContent = \"Animation QA\";\n const run = document.createElement(\"button\");\n run.type = \"button\";\n run.className = \"studio-btn\";\n run.textContent = \"전체 frame 검사\";\n const status = document.createElement(\"p\");\n status.className = \"studio-props-empty\";\n container.append(title, run, status);\n run.addEventListener(\"click\", () => {\n const animation = context.getDocument();\n const errors: AnimationAssertionError[] = [];\n for (const time of animationSampleTimes(animation)) {\n for (const element of animation.elements) {\n if (![\"rect\", \"circle\", \"image\", \"code\"].includes(element.type))\n continue;\n try {\n expectAnimation(animation).at(time).insideCanvas(element.id);\n } catch (error) {\n if (error instanceof AnimationAssertionError)\n errors.push(error);\n }\n }\n }\n const snapshots = snapshotAnimationMatrix(animation);\n if (errors.length === 0) {\n status.textContent = `${snapshots.length}개 locale·theme frame을 검사했습니다. 문제가 없습니다.`;\n status.removeAttribute(\"data-error\");\n } else {\n status.textContent = `${errors.length}개 문제를 발견했습니다. HTML report를 내려받습니다.`;\n status.dataset.error = \"true\";\n downloadReport(animationFailureReport(errors));\n }\n });\n },\n },\n },\n };\n}\n","import { compileResponsiveStage, type AnimationDocument } from \"@kokoa/clotho\";\nimport { renderDocumentToSvg } from \"@kokoa/clotho/svg\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport const RESPONSIVE_VIEWPORTS = [\n { id: \"compact\", label: \"모바일\", width: 375 },\n { id: \"regular\", label: \"본문\", width: 768 },\n { id: \"wide\", label: \"넓은 화면\", width: 1280 },\n] as const;\n\nexport function addDefaultResponsiveVariants(\n document: AnimationDocument,\n): AnimationDocument {\n if (document.responsive?.length) return document;\n return {\n ...document,\n responsive: [\n {\n id: \"compact\",\n minWidth: 0,\n maxWidth: 479,\n chapterListPosition: \"bottom\",\n elementOverrides: {},\n },\n { id: \"regular\", minWidth: 480, maxWidth: 959, elementOverrides: {} },\n { id: \"wide\", minWidth: 960, elementOverrides: {} },\n ],\n };\n}\n\nexport function createResponsiveInspectorPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.responsive\",\n name: \"Responsive Stage\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"responsive\"] },\n },\n inspectors: {\n responsive: {\n id: \"responsive\",\n label: \"Responsive Stage\",\n mount(container, context) {\n const render = () => {\n const document = context.getDocument();\n container.innerHTML = `<div class=\"studio-props-header\"><span class=\"studio-props-header-title\">Responsive Stage</span></div><button type=\"button\" class=\"studio-btn\" data-responsive-defaults>기본 breakpoint 만들기</button><div class=\"studio-responsive-grid\">${RESPONSIVE_VIEWPORTS.map((viewport) => `<figure><figcaption>${viewport.label} · ${viewport.width}px</figcaption>${renderDocumentToSvg(compileResponsiveStage(document, viewport.width), 0)}</figure>`).join(\"\")}</div>`;\n };\n const click = (event: Event) => {\n if (\n !(event.target as HTMLElement).closest(\n \"[data-responsive-defaults]\",\n )\n )\n return;\n context.replaceDocument(\n addDefaultResponsiveVariants(context.getDocument()),\n );\n render();\n };\n container.addEventListener(\"click\", click);\n render();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n","import {\n buildScene,\n compileSceneDependencyPlan,\n type AnimationDocument,\n} from \"@kokoa/clotho\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport interface SceneProfile {\n elementCount: number;\n trackCount: number;\n keyframeCount: number;\n sampleCount: number;\n totalMs: number;\n averageMs: number;\n maxMs: number;\n overBudget: boolean;\n}\n\nexport function profileAnimation(\n document: AnimationDocument,\n sampleCount = 30,\n frameBudgetMs = 16.7,\n): SceneProfile {\n const plan = compileSceneDependencyPlan(document);\n const samples: number[] = [];\n for (let index = 0; index < sampleCount; index += 1) {\n const time =\n sampleCount === 1 ? 0 : (document.duration * index) / (sampleCount - 1);\n const started = performance.now();\n buildScene(document, time);\n samples.push(performance.now() - started);\n }\n const totalMs = samples.reduce((sum, value) => sum + value, 0);\n const maxMs = Math.max(0, ...samples);\n return {\n elementCount: plan.elementCount,\n trackCount: plan.trackCount,\n keyframeCount: plan.keyframeCount,\n sampleCount,\n totalMs,\n averageMs: totalMs / Math.max(1, sampleCount),\n maxMs,\n overBudget: maxMs > frameBudgetMs,\n };\n}\n\nexport function createPerformanceProfilerPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.performance\",\n name: \"Scene Profiler\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"performance\"] },\n },\n inspectors: {\n performance: {\n id: \"performance\",\n label: \"Scene Profiler\",\n mount(container, context) {\n const run = () => {\n const profile = profileAnimation(context.getDocument());\n container.innerHTML = `<div class=\"studio-props-header\"><span class=\"studio-props-header-title\">Scene Profiler</span></div><dl class=\"studio-profile\"><div><dt>Elements</dt><dd>${profile.elementCount}</dd></div><div><dt>Tracks / keyframes</dt><dd>${profile.trackCount} / ${profile.keyframeCount}</dd></div><div><dt>평균 / 최대</dt><dd>${profile.averageMs.toFixed(2)} / ${profile.maxMs.toFixed(2)} ms</dd></div></dl><p class=\"studio-template-status\" data-error=\"${profile.overBudget}\">${profile.overBudget ? \"16.7ms frame budget을 넘었습니다.\" : \"60fps frame budget 안에 있습니다.\"}</p><button type=\"button\" class=\"studio-btn\" data-run-profiler>다시 측정</button>`;\n };\n const click = (event: Event) => {\n if ((event.target as HTMLElement).closest(\"[data-run-profiler]\"))\n run();\n };\n container.addEventListener(\"click\", click);\n run();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n","import { autofixDocument, lintDocument } from \"@kokoa/clotho\";\nimport { renderDocumentToSvg } from \"@kokoa/clotho/svg\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport function createLinterPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.linter\",\n name: \"Clotho Linter\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"linter\"] },\n },\n inspectors: {\n linter: {\n id: \"linter\",\n label: \"Clotho Linter\",\n mount(container, context) {\n let selectedIndex = 0;\n const render = () => {\n const document = context.getDocument();\n const issues = lintDocument(document);\n const selected = issues[selectedIndex] ?? issues[0];\n const fixed = autofixDocument(document).document;\n container.innerHTML = `<div class=\"studio-props-header\"><span class=\"studio-props-header-title\">Clotho Linter (${issues.length})</span><button type=\"button\" class=\"studio-btn\" data-lint-fix ${issues.some(({ fixable }) => fixable) ? \"\" : \"disabled\"}>안전한 수정 적용</button></div><ol class=\"studio-lint-list\">${issues.map((issue, index) => `<li><button type=\"button\" data-lint-index=\"${index}\" data-element-id=\"${issue.elementId ?? \"\"}\"><strong>${escapeHtml(issue.ruleId)}</strong><span>${escapeHtml(issue.message)}</span>${issue.fixable ? \"<em>자동 수정</em>\" : \"\"}</button></li>`).join(\"\") || \"<li>문제가 없습니다.</li>\"}</ol>${selected ? `<div class=\"studio-lint-compare\"><figure><figcaption>현재</figcaption>${renderDocumentToSvg(document, selected.time ?? 0)}</figure><figure><figcaption>수정 후</figcaption>${renderDocumentToSvg(fixed, selected.time ?? 0)}</figure></div>` : \"\"}`;\n };\n const click = (event: Event) => {\n const target = event.target as HTMLElement;\n if (target.closest(\"[data-lint-fix]\")) {\n context.replaceDocument(\n autofixDocument(context.getDocument()).document,\n );\n selectedIndex = 0;\n render();\n return;\n }\n const issue = target.closest<HTMLElement>(\"[data-lint-index]\");\n if (!issue) return;\n selectedIndex = Number(issue.dataset.lintIndex);\n if (issue.dataset.elementId)\n context.setSelection({\n kind: \"element\",\n elementId: issue.dataset.elementId,\n });\n render();\n };\n container.addEventListener(\"click\", click);\n render();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/Studio.tsx","../src/template-editor-plugin.ts","../src/story-editor-plugin.ts","../src/StudioMount.tsx","../src/repository.ts","../src/visual-regression-plugin.ts","../src/responsive-inspector-plugin.ts","../src/performance-profiler-plugin.ts","../src/linter-plugin.ts"],"names":["setDef","addElement","deleteElement","document","useEffect","jsx","escapeHtml","renderDocumentToSvg"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { AnimationDocument } from \"@kokoa/clotho\";\nimport { AnimationStage, usePlayer } from \"@kokoa/clotho/react\";\nimport { downloadAnimationJson } from \"./export-json\";\n\ntype EditableElement = Record<string, unknown> & { id: string; type: string };\ntype ElementList = AnimationDocument[\"elements\"];\n\nexport interface StudioProps {\n initial: AnimationDocument;\n onSave: (def: AnimationDocument) => void | Promise<void>;\n}\n\nfunction elementsOf(def: AnimationDocument): EditableElement[] {\n return def.elements as unknown as EditableElement[];\n}\n\nexport function Studio({ initial, onSave }: StudioProps): React.JSX.Element {\n const [def, setDef] = useState<AnimationDocument>(initial);\n const [selectedId, setSelectedId] = useState<string | null>(\n elementsOf(initial)[0]?.id ?? null,\n );\n const [playing, setPlaying] = useState(false);\n const [time, setTime] = useState(0);\n const [saving, setSaving] = useState(false);\n const [saved, setSaved] = useState(false);\n\n // The clock for preview playback. It lives outside React (core/player), so the\n // editor subscribes rather than owning a rAF loop of its own.\n const { player, state: playerState } = usePlayer(def, { autoplay: false });\n\n useEffect(() => {\n if (playing) player.play();\n else {\n player.pause();\n player.seek(time);\n }\n }, [playing, player, time]);\n\n const elements = elementsOf(def);\n const selected = elements.find((e) => e.id === selectedId) ?? null;\n const scalarProps = selected\n ? Object.entries(selected).filter(\n ([key, value]) =>\n (typeof value === \"string\" || typeof value === \"number\") &&\n key !== \"id\" &&\n key !== \"type\",\n )\n : [];\n\n function setElements(next: EditableElement[]): void {\n setDef((current) => ({\n ...current,\n elements: next as unknown as ElementList,\n }));\n setSaved(false);\n }\n\n function updateElement(\n id: string,\n key: string,\n raw: string,\n numeric: boolean,\n ): void {\n setElements(\n elements.map((e) =>\n e.id === id ? { ...e, [key]: numeric ? Number(raw) : raw } : e,\n ),\n );\n }\n\n function addElement(): void {\n const id = `el-${Date.now().toString(36)}`;\n const el: EditableElement = {\n type: \"text\",\n id,\n x: 100,\n y: 100,\n rotation: 0,\n content: \"New\",\n translations: {},\n references: {},\n fontSize: 24,\n color: \"#4f46e5\",\n textAnchor: \"start\",\n appearances: [{ start: 0, end: def.duration }],\n tracks: [],\n };\n setElements([...elements, el]);\n setSelectedId(id);\n }\n\n function deleteElement(id: string): void {\n setElements(elements.filter((e) => e.id !== id));\n if (selectedId === id) setSelectedId(null);\n }\n\n async function handleSave(): Promise<void> {\n setSaving(true);\n try {\n await onSave(def);\n setSaved(true);\n } finally {\n setSaving(false);\n }\n }\n\n return (\n <div className=\"studio\">\n <aside className=\"studio-panel studio-left\">\n <div className=\"studio-panel-head\">\n <span>요소 ({elements.length})</span>\n <button type=\"button\" className=\"studio-btn\" onClick={addElement}>\n + 추가\n </button>\n </div>\n <ul className=\"studio-el-list\">\n {elements.map((e) => (\n <li key={e.id}>\n <button\n type=\"button\"\n className={\n e.id === selectedId ? \"studio-el active\" : \"studio-el\"\n }\n onClick={() => setSelectedId(e.id)}\n >\n <span className=\"studio-el-type\">{e.type}</span>\n <span className=\"studio-el-id\">{e.id}</span>\n </button>\n </li>\n ))}\n </ul>\n </aside>\n\n <div className=\"studio-preview\">\n <div className=\"studio-preview-bar\">\n <button\n type=\"button\"\n className=\"studio-btn\"\n onClick={() => downloadAnimationJson(def)}\n >\n JSON 내보내기\n </button>\n <button\n type=\"button\"\n className=\"studio-btn\"\n onClick={() => setPlaying((p) => !p)}\n >\n {playing ? \"⏸ 정지\" : \"▶ 재생\"}\n </button>\n <input\n type=\"range\"\n min={0}\n max={def.duration}\n step={50}\n value={time}\n disabled={playing}\n onChange={(e) => {\n setTime(Number(e.target.value));\n setPlaying(false);\n }}\n />\n <span className=\"studio-time\">\n {time} / {def.duration}ms\n </span>\n <button\n type=\"button\"\n className=\"studio-btn studio-save\"\n onClick={() => void handleSave()}\n disabled={saving}\n >\n {saving ? \"저장 중…\" : saved ? \"✓ 저장됨\" : \"저장\"}\n </button>\n </div>\n <div className=\"studio-canvas\">\n {/* One frame at a time: the editor's scrubber is the source of truth, and the\n player only supplies the clock while previewing. Same buildScene path as\n the published animation, so preview and production cannot diverge. */}\n <AnimationStage doc={def} time={playing ? playerState.time : time} />\n </div>\n </div>\n\n <aside className=\"studio-panel studio-right\">\n <div className=\"studio-panel-head\">메타</div>\n <label className=\"studio-field\">\n <span>제목</span>\n <input\n value={def.title}\n onChange={(e) => {\n setDef((d) => ({ ...d, title: e.target.value }));\n setSaved(false);\n }}\n />\n </label>\n <label className=\"studio-field\">\n <span>duration (ms)</span>\n <input\n type=\"number\"\n value={def.duration}\n onChange={(e) => {\n setDef((d) => ({ ...d, duration: Number(e.target.value) }));\n setSaved(false);\n }}\n />\n </label>\n <div className=\"studio-panel-head\">\n 속성 {selected ? `(${selected.type})` : \"\"}\n </div>\n {selected ? (\n <>\n {scalarProps.map(([key, value]) => (\n <label key={key} className=\"studio-field\">\n <span>{key}</span>\n <input\n value={String(value)}\n onChange={(e) =>\n updateElement(\n selected.id,\n key,\n e.target.value,\n typeof value === \"number\",\n )\n }\n />\n </label>\n ))}\n <button\n type=\"button\"\n className=\"studio-btn studio-del\"\n onClick={() => deleteElement(selected.id)}\n >\n 요소 삭제\n </button>\n </>\n ) : (\n <p className=\"studio-empty\">요소를 선택하세요.</p>\n )}\n </aside>\n </div>\n );\n}\n","import type {\n AnimationTemplate,\n ParameterSchema,\n TemplateParameterError,\n TemplateReference,\n} from \"@kokoa/clotho\";\nimport { downloadAnimationJson } from \"./export-json\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport function initialParameterValue(schema: ParameterSchema): unknown {\n if (schema.default !== undefined) return structuredClone(schema.default);\n if (schema.type === \"string\") return \"\";\n if (schema.type === \"number\") return schema.min ?? 0;\n if (schema.type === \"boolean\") return false;\n if (schema.type === \"enum\") return schema.values[0];\n if (schema.type === \"array\") return [];\n return Object.fromEntries(\n Object.entries(schema.properties).map(([key, child]) => [\n key,\n initialParameterValue(child),\n ]),\n );\n}\n\nexport function parameterInputValue(\n schema: ParameterSchema,\n raw: string | boolean,\n): unknown {\n if (schema.type === \"boolean\") return Boolean(raw);\n if (schema.type === \"number\") return Number(raw);\n if (schema.type === \"array\" || schema.type === \"object\")\n return JSON.parse(String(raw));\n return String(raw);\n}\n\nfunction downloadReference(reference: TemplateReference): void {\n const blob = new Blob([JSON.stringify(reference, null, 2)], {\n type: \"application/json\",\n });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `${reference.templateId.replace(/[^a-z0-9._-]/gi, \"-\")}.template.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n}\n\nfunction field(\n key: string,\n schema: ParameterSchema,\n value: unknown,\n onChange: (value: unknown) => void,\n): HTMLElement {\n const label = document.createElement(\"label\");\n label.className = \"studio-field studio-template-field\";\n const title = document.createElement(\"span\");\n title.textContent = key;\n if (schema.description) title.title = schema.description;\n label.append(title);\n\n let control: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n if (schema.type === \"enum\") {\n control = document.createElement(\"select\");\n for (const option of schema.values) {\n const element = document.createElement(\"option\");\n element.value = option;\n element.textContent = option;\n control.append(element);\n }\n control.value = String(value);\n } else if (schema.type === \"array\" || schema.type === \"object\") {\n control = document.createElement(\"textarea\");\n control.rows = 3;\n control.value = JSON.stringify(value, null, 2);\n } else {\n control = document.createElement(\"input\");\n control.type = schema.type === \"boolean\" ? \"checkbox\" : schema.type;\n if (schema.type === \"boolean\") control.checked = Boolean(value);\n else control.value = String(value);\n if (schema.type === \"number\") {\n if (schema.min !== undefined) control.min = String(schema.min);\n if (schema.max !== undefined) control.max = String(schema.max);\n control.step = schema.integer ? \"1\" : \"any\";\n }\n if (schema.type === \"string\") {\n if (schema.minLength !== undefined) control.minLength = schema.minLength;\n if (schema.maxLength !== undefined) control.maxLength = schema.maxLength;\n if (schema.pattern !== undefined) control.pattern = schema.pattern;\n }\n }\n control.dataset.templateParameter = key;\n const update = (): void => {\n try {\n const raw =\n control instanceof HTMLInputElement && control.type === \"checkbox\"\n ? control.checked\n : control.value;\n onChange(parameterInputValue(schema, raw));\n control.setCustomValidity(\"\");\n } catch {\n control.setCustomValidity(\"올바른 JSON을 입력하세요.\");\n }\n };\n control.addEventListener(\n schema.type === \"enum\" || schema.type === \"boolean\" ? \"change\" : \"input\",\n update,\n );\n label.append(control);\n return label;\n}\n\n/** Built-in authoring panel for trusted templates registered by the host. */\nexport function createTemplateEditorPlugin(\n templates: readonly AnimationTemplate[],\n): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.templates\",\n name: \"Template parameters\",\n capabilities: [\"editor\"],\n editor: { panels: [\"parameters\"] },\n },\n panels: {\n parameters: {\n id: \"parameters\",\n label: \"Template parameters\",\n mount(container, context) {\n if (templates.length === 0) return;\n container.classList.add(\n \"studio-tools-section\",\n \"studio-template-panel\",\n );\n const heading = document.createElement(\"div\");\n heading.className = \"studio-tools-title\";\n heading.textContent = \"Template\";\n const select = document.createElement(\"select\");\n select.className = \"studio-template-select\";\n for (const template of templates) {\n const option = document.createElement(\"option\");\n option.value = template.id;\n option.textContent = template.id;\n select.append(option);\n }\n const form = document.createElement(\"div\");\n const status = document.createElement(\"p\");\n status.className = \"studio-props-empty studio-template-status\";\n const actions = document.createElement(\"div\");\n actions.className = \"studio-align-row\";\n const standalone = document.createElement(\"button\");\n standalone.className = \"studio-btn\";\n standalone.textContent = \"Standalone JSON\";\n const reference = document.createElement(\"button\");\n reference.className = \"studio-btn\";\n reference.textContent = \"Template 참조\";\n actions.append(standalone, reference);\n container.append(heading, select, form, status, actions);\n\n let active = templates[0]!;\n let values: Record<string, unknown> = {};\n let previewDocument = context.getDocument();\n const rebuild = (): void => {\n try {\n previewDocument = active.instantiate(values);\n context.replaceDocument(previewDocument);\n status.textContent = \"parameter가 미리보기에 반영되었습니다.\";\n status.removeAttribute(\"data-error\");\n } catch (error) {\n const issues = (error as TemplateParameterError).issues;\n status.textContent = issues\n ? issues\n .map(({ path, message }) => `${path}: ${message}`)\n .join(\" · \")\n : String(error);\n status.dataset.error = \"true\";\n }\n };\n const render = (): void => {\n values = Object.fromEntries(\n Object.entries(active.parameters).map(([key, schema]) => [\n key,\n initialParameterValue(schema),\n ]),\n );\n form.replaceChildren(\n ...Object.entries(active.parameters).map(([key, schema]) =>\n field(key, schema, values[key], (value) => {\n values[key] = value;\n rebuild();\n }),\n ),\n );\n rebuild();\n };\n select.addEventListener(\"change\", () => {\n active =\n templates.find(({ id }) => id === select.value) ?? templates[0]!;\n render();\n });\n standalone.addEventListener(\"click\", () =>\n downloadAnimationJson(previewDocument),\n );\n reference.addEventListener(\"click\", () =>\n downloadReference(active.reference(values)),\n );\n render();\n },\n },\n },\n };\n}\n","import {\n defineStory,\n type AnimationDocument,\n type StoryEdge,\n type StoryManifest,\n} from \"@kokoa/clotho\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport interface StoryEditorOptions {\n manifest: StoryManifest;\n onChange?(manifest: StoryManifest): void;\n}\n\nexport function replaceStoryNodeDocument(\n manifest: StoryManifest,\n nodeId: string,\n document: AnimationDocument,\n): StoryManifest {\n return defineStory({\n ...manifest,\n nodes: manifest.nodes.map((node) =>\n node.id === nodeId ? { ...node, document } : node,\n ),\n });\n}\n\nexport function appendStoryEdge(\n manifest: StoryManifest,\n edge: StoryEdge,\n): StoryManifest {\n return defineStory({ ...manifest, edges: [...manifest.edges, edge] });\n}\n\nexport function createStoryEditorPlugin(\n options: StoryEditorOptions,\n): EditorPluginDefinition {\n let manifest = structuredClone(options.manifest);\n let activeNode = manifest.initialNode;\n return {\n manifest: {\n id: \"dev.clotho.story\",\n name: \"Story Graph\",\n capabilities: [\"editor\"],\n editor: { panels: [\"story-graph\"] },\n },\n panels: {\n \"story-graph\": {\n id: \"story-graph\",\n label: \"Story Graph\",\n mount(container, context) {\n const render = () => {\n container.innerHTML = `<div class=\"studio-tools-section\"><div class=\"studio-tools-title\">Story Graph</div><div class=\"studio-story-nodes\">${manifest.nodes.map((node) => `<button type=\"button\" class=\"studio-btn${node.id === activeNode ? \" is-active\" : \"\"}\" data-story-node=\"${escapeAttribute(node.id)}\">${escapeHtml(node.title || node.id)}</button>`).join(\"\")}</div><div class=\"studio-tools-hint\">${manifest.edges.map((edge) => `${escapeHtml(edge.from)} → ${escapeHtml(edge.to)}${edge.label ? ` · ${escapeHtml(edge.label)}` : \"\"}`).join(\"<br>\") || \"연결이 없습니다.\"}</div></div>`;\n };\n const click = (event: Event) => {\n const button = (event.target as HTMLElement).closest<HTMLElement>(\n \"[data-story-node]\",\n );\n const nextId = button?.dataset.storyNode;\n if (!nextId || nextId === activeNode) return;\n manifest = replaceStoryNodeDocument(\n manifest,\n activeNode,\n context.getDocument(),\n );\n const node = manifest.nodes.find(({ id }) => id === nextId);\n if (!node) return;\n activeNode = nextId;\n context.replaceDocument(node.document);\n options.onChange?.(structuredClone(manifest));\n render();\n };\n container.addEventListener(\"click\", click);\n render();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n}\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replaceAll('\"', \""\");\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useRef } from \"react\";\nimport type { AnimationTemplate } from \"@kokoa/clotho\";\nimport type { AnimationRepository } from \"./repository\";\nimport { configureAnimationRepository } from \"./legacy/api\";\nimport type { ImageUploadResolver } from \"./legacy/studio-image-upload\";\nimport type {\n DocumentImporter,\n EditorPluginDefinition,\n EditorPluginPermissionResolver,\n} from \"./plugin-host\";\nimport { createTemplateEditorPlugin } from \"./template-editor-plugin\";\nimport {\n createStoryEditorPlugin,\n type StoryEditorOptions,\n} from \"./story-editor-plugin\";\n// The stylesheet ships as a separate entry rather than an import, so a consumer that\n// only wants the headless pieces does not pull CSS into its bundle:\n// import \"@kokoa/clotho-editor/styles.css\";\n\nexport interface StudioMountProps {\n initialId?: string;\n repository?: AnimationRepository;\n editorTitle?: string;\n resolveImage?: ImageUploadResolver;\n importDocument?: DocumentImporter;\n plugins?: readonly EditorPluginDefinition[];\n resolvePluginPermissions?: EditorPluginPermissionResolver;\n /** Trusted build-time templates shown as a parameter panel. */\n templates?: readonly AnimationTemplate[];\n /** Optional multi-document Story Graph edited alongside the active node timeline. */\n story?: StoryEditorOptions;\n}\n\nconst EMPTY_EDITOR_PLUGINS: readonly EditorPluginDefinition[] = [];\nconst EMPTY_TEMPLATES: readonly AnimationTemplate[] = [];\nconst DENY_PLUGIN_PERMISSIONS: EditorPluginPermissionResolver = () => ({});\n\nconst CANVAS_PRESETS: {\n id: string;\n label: string;\n sub: string;\n w: number;\n h: number;\n}[] = [\n { id: \"800x500\", label: \"8:5\", sub: \"800×500\", w: 32, h: 20 },\n { id: \"1280x720\", label: \"16:9\", sub: \"HD\", w: 32, h: 18 },\n { id: \"1024x768\", label: \"4:3\", sub: \"1024×768\", w: 28, h: 21 },\n { id: \"600x600\", label: \"1:1\", sub: \"정사각\", w: 22, h: 22 },\n { id: \"1200x400\", label: \"3:1\", sub: \"와이드\", w: 36, h: 12 },\n { id: \"375x812\", label: \"9:19\", sub: \"모바일\", w: 14, h: 30 },\n];\n\nconst PRESET_HTML = CANVAS_PRESETS.map(\n (p) => `\n <button type=\"button\" class=\"studio-preset-btn\" aria-label=\"캔버스 크기 ${p.id} (${p.sub})\" title=\"${p.id} · ${p.sub}\" data-canvas-preset=\"${p.id}\">\n <svg class=\"studio-preset-thumb\" viewBox=\"0 0 ${p.w + 2} ${p.h + 2}\" width=\"${p.w + 2}\" height=\"${p.h + 2}\" aria-hidden=\"true\">\n <rect x=\"1\" y=\"1\" width=\"${p.w}\" height=\"${p.h}\" rx=\"2\" />\n </svg>\n <span class=\"studio-preset-label\">${p.label}</span>\n <span class=\"studio-preset-sub\">${p.sub}</span>\n </button>`,\n).join(\"\");\n\nconst SKELETON = `\n<div id=\"studio-app\" class=\"studio-app\">\n <header class=\"studio-header\">\n <h1 id=\"studio-editor-title\" class=\"studio-header-title\">Clotho Editor</h1>\n <div class=\"studio-header-actions\">\n <span class=\"studio-plugin-toolbar\" data-editor-plugin-slot=\"toolbar\"></span>\n <button type=\"button\" id=\"studio-open\" class=\"studio-btn\" aria-label=\"저장된 애니메이션 열기\">📁 열기</button>\n <button type=\"button\" id=\"studio-new\" class=\"studio-btn\" aria-label=\"새 애니메이션 만들기\">+ 새 애니메이션</button>\n <button type=\"button\" id=\"studio-undo\" class=\"studio-btn studio-btn-icon\" aria-label=\"실행 취소\" title=\"실행 취소 (⌘Z)\" disabled>↶</button>\n <button type=\"button\" id=\"studio-redo\" class=\"studio-btn studio-btn-icon\" aria-label=\"다시 실행\" title=\"다시 실행 (⌘⇧Z / ⌘Y)\" disabled>↷</button>\n <button type=\"button\" id=\"studio-grid-toggle\" class=\"studio-btn studio-btn-grid\" aria-label=\"격자 + 스냅\" title=\"격자 + 스냅 (G)\" aria-pressed=\"false\"><span class=\"studio-btn-grid-icon\">⊞</span><span class=\"studio-btn-grid-label\" id=\"studio-grid-label\">격자 끔</span></button>\n <button type=\"button\" id=\"studio-camera-frame-toggle\" class=\"studio-btn studio-btn-grid\" aria-label=\"카메라 영역 표시\" title=\"캔버스에 카메라가 보여주는 영역을 표시합니다\" aria-pressed=\"true\"><span class=\"studio-btn-grid-icon\">🎥</span><span class=\"studio-btn-grid-label\" id=\"studio-camera-frame-label\">카메라 영역</span></button>\n <input type=\"text\" id=\"studio-title\" class=\"studio-title-input\" placeholder=\"제목\" aria-label=\"애니메이션 제목\" disabled />\n <span id=\"studio-id-display\" class=\"studio-id-display\"></span>\n <span id=\"studio-status\" class=\"studio-status\" aria-live=\"polite\">대기 중</span>\n <button type=\"button\" id=\"studio-save\" class=\"studio-btn studio-btn-primary\" aria-label=\"저장\" disabled>💾 저장 (⌘S)</button>\n <button type=\"button\" id=\"studio-export-json\" class=\"studio-btn\" aria-label=\"현재 애니메이션을 JSON 파일로 내보내기\" disabled>⬇ JSON 내보내기</button>\n <button type=\"button\" id=\"studio-player-preview\" class=\"studio-btn\" aria-label=\"실제 애니메이션 컴포넌트 미리보기\" aria-pressed=\"false\">↗ 실제 미리보기</button>\n <button type=\"button\" id=\"studio-import-json\" class=\"studio-btn\" aria-label=\"JSON 파일에서 애니메이션 가져오기\">⬆ JSON 가져오기</button>\n <input type=\"file\" id=\"studio-import-file\" accept=\"application/json,.json\" hidden />\n <button type=\"button\" id=\"studio-delete\" class=\"studio-btn studio-btn-danger\" aria-label=\"삭제\" disabled>🗑 삭제</button>\n </div>\n </header>\n\n <div class=\"studio-body\">\n <aside class=\"studio-tools\" aria-label=\"요소 추가\">\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">도구</div>\n <button type=\"button\" class=\"studio-tool-btn is-active\" data-studio-tool=\"select\" aria-pressed=\"true\" title=\"선택 · 이동 · 크기 (V)\"><span>↖ 선택 · 이동 · 크기</span><kbd>V</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"rect\" title=\"사각형 (R)\" aria-label=\"사각형 도구\"><span>□ Rect</span><kbd>R</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"circle\" title=\"원 (O)\" aria-label=\"원 도구\"><span>○ Circle</span><kbd>O</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"line\" title=\"선 (L)\" aria-label=\"선 도구\"><span>/ Line</span><kbd>L</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"arrow\" title=\"화살표 (A)\" aria-label=\"화살표 도구\"><span>↗ Arrow</span><kbd>A</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"text\" title=\"텍스트 (T)\" aria-label=\"텍스트 도구\"><span>T Text</span><kbd>T</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"image\" title=\"이미지 (I)\" aria-label=\"이미지 도구\"><span>🖼 Image</span><kbd>I</kbd></button>\n <button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"path\" title=\"Path (B)\" aria-label=\"Path 도구\"><span>✎ Path</span><kbd>B</kbd></button>\n <div class=\"studio-tool-with-option\"><button type=\"button\" class=\"studio-tool-btn\" data-add-element=\"polygon\" title=\"다각형 (Y)\" aria-label=\"다각형 도구\"><span>⬢ Polygon</span><kbd>Y</kbd></button><label>변 <input type=\"number\" id=\"studio-polygon-sides\" min=\"3\" max=\"24\" value=\"6\" aria-label=\"다각형의 변 개수\" /></label></div>\n <button type=\"button\" class=\"studio-tool-btn\" id=\"studio-open-icons\" title=\"아이콘 라이브러리\" aria-label=\"아이콘 라이브러리 추가\">🎨 Icons</button>\n </div>\n <div class=\"studio-plugin-panels\" data-editor-plugin-slot=\"panel\"></div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">캔버스 크기</div>\n <div class=\"studio-canvas-size-row\">\n <input type=\"number\" id=\"studio-canvas-width\" class=\"studio-canvas-size-input\" min=\"100\" max=\"8000\" step=\"10\" placeholder=\"width\" />\n <span class=\"studio-canvas-size-x\">×</span>\n <input type=\"number\" id=\"studio-canvas-height\" class=\"studio-canvas-size-input\" min=\"100\" max=\"8000\" step=\"10\" placeholder=\"height\" />\n </div>\n <div class=\"studio-canvas-presets\">${PRESET_HTML}</div>\n </div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">이미지</div>\n <button type=\"button\" class=\"studio-tool-btn\" id=\"studio-image-upload\">📤 이미지 업로드</button>\n <input type=\"file\" id=\"studio-image-file\" accept=\"image/*\" hidden />\n <div class=\"studio-tools-hint\">이미지를 캔버스에 직접 드래그하거나 ⌘V 로 붙여넣어도 됩니다.</div>\n </div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">단축키</div>\n <button type=\"button\" class=\"studio-tool-btn\" id=\"studio-help\">⌨ 단축키 보기 (?)</button>\n </div>\n <div class=\"studio-tools-section\">\n <div class=\"studio-tools-title\">요소 목록</div>\n <input type=\"text\" id=\"studio-element-search\" class=\"studio-element-search\" placeholder=\"🔍 검색 (name / label / id / type)\" autocomplete=\"off\" />\n <ul id=\"studio-element-list\" class=\"studio-element-list\"></ul>\n </div>\n </aside>\n\n <main class=\"studio-canvas-wrap\">\n <div class=\"studio-canvas-frame\">\n <svg id=\"studio-canvas\" class=\"studio-canvas\" xmlns=\"http://www.w3.org/2000/svg\"></svg>\n </div>\n <button type=\"button\" id=\"studio-floating-help\" class=\"studio-floating-help\" aria-label=\"단축키 보기\" title=\"단축키 보기 (? / Shift+/)\">?</button>\n <div id=\"studio-help-hint\" class=\"studio-help-hint\" hidden>\n <span>💡 단축키는 <kbd>?</kbd> 또는 우측 하단 버튼으로 확인하세요</span>\n <button type=\"button\" id=\"studio-help-hint-close\" aria-label=\"닫기\">✕</button>\n </div>\n </main>\n\n <aside class=\"studio-props\" aria-label=\"속성 패널\">\n <div id=\"studio-props-content\" class=\"studio-props-content\">\n <p class=\"studio-props-empty\">요소 또는 step 을 선택하세요.</p>\n </div>\n <div class=\"studio-plugin-inspectors\" data-editor-plugin-slot=\"inspector\"></div>\n </aside>\n </div>\n\n <div id=\"studio-timeline-resizer\" class=\"studio-timeline-resizer\" role=\"separator\" aria-orientation=\"horizontal\" aria-label=\"타임라인 영역 크기 조정\" tabindex=\"0\"><span class=\"studio-timeline-resizer-grip\" aria-hidden=\"true\"><i></i><i></i><i></i></span></div>\n <footer class=\"studio-timeline-wrap\">\n <div class=\"studio-timeline-header\">\n <button type=\"button\" id=\"studio-play\" class=\"studio-btn\">▶ Play</button>\n <button type=\"button\" id=\"studio-restart\" class=\"studio-btn\">⟲ Reset</button>\n <label class=\"studio-speed\">속도\n <input type=\"range\" id=\"studio-speed\" min=\"0.25\" max=\"3\" step=\"0.25\" value=\"1\" />\n <span id=\"studio-speed-value\">1.00x</span>\n </label>\n <label class=\"studio-timeline-option\"><input type=\"checkbox\" id=\"studio-preview-loop\" /> 무한 재생</label>\n <button type=\"button\" id=\"studio-detach-timeline\" class=\"studio-btn\" aria-pressed=\"false\">▣ 타임라인 분리</button>\n <span class=\"studio-timeline-spacer\"></span>\n <button type=\"button\" id=\"studio-add-step\" class=\"studio-btn\">+ Chapter 추가</button>\n </div>\n <div class=\"studio-timeline-tracks-wrap\">\n <div id=\"studio-timeline-tracks\" class=\"studio-timeline-tracks\"></div>\n </div>\n <div class=\"studio-element-tracks-wrap\">\n <div id=\"studio-element-tracks\" class=\"studio-element-tracks\"></div>\n </div>\n </footer>\n\n <dialog id=\"studio-library-dialog\" class=\"studio-dialog\">\n <div class=\"studio-dialog-header\">\n <h2>저장된 애니메이션</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close>✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <ul id=\"studio-library-list\" class=\"studio-library-list\"></ul>\n </div>\n </dialog>\n\n <dialog id=\"studio-icon-dialog\" class=\"studio-dialog\">\n <div class=\"studio-dialog-header\">\n <h2>🎨 아이콘 라이브러리</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-icon-dialog-close>✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <input type=\"search\" id=\"studio-icon-search\" placeholder=\"아이콘 검색…\" class=\"studio-icon-search-input\" />\n <div id=\"studio-icon-list\"></div>\n </div>\n </dialog>\n\n <dialog id=\"studio-help-dialog\" class=\"studio-dialog studio-dialog-small\">\n <div class=\"studio-dialog-header\">\n <h2>⌨ 단축키</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close>✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <table class=\"studio-help-table\">\n <tbody>\n <tr><th>⌘ S</th><td>저장</td></tr>\n <tr><th>⌘ Z / ⌘ ⇧ Z</th><td>Undo / Redo</td></tr>\n <tr><th>⌘ C / V / X</th><td>요소 복사 / 붙여넣기 / 잘라내기</td></tr>\n <tr><th>V / R / O</th><td>선택 / 사각형 / 원 도구</td></tr>\n <tr><th>L / A</th><td>선 / 화살표 도구</td></tr>\n <tr><th>T / I / B / Y</th><td>텍스트 / 이미지 / Path / 다각형 도구</td></tr>\n <tr><th>⌘·Ctrl·Shift + 클릭</th><td>여러 요소 선택 또는 선택 해제</td></tr>\n <tr><th>Delete / Backspace</th><td>선택된 요소 또는 step 삭제</td></tr>\n <tr><th>?</th><td>이 화면 열기</td></tr>\n <tr><th>Esc</th><td>선택 해제 / 다이얼로그 닫기</td></tr>\n <tr><th>드래그 (캔버스)</th><td>요소 이동</td></tr>\n <tr><th>드래그 (요소 위 dot)</th><td>화살표 연결</td></tr>\n <tr><th>드래그 (선/화살표 끝점)</th><td>끝점 재배치 + 다른 요소에 sticky</td></tr>\n <tr><th>드래그 (회전 핸들)</th><td>요소 회전</td></tr>\n <tr><th>드래그 (타임라인 바 우측)</th><td>step duration 조정</td></tr>\n <tr><th>이미지 드래그 in</th><td>이미지 업로드 + 배치</td></tr>\n </tbody>\n </table>\n </div>\n </dialog>\n\n <dialog id=\"studio-new-dialog\" class=\"studio-dialog studio-dialog-small\">\n <div class=\"studio-dialog-header\">\n <h2 id=\"studio-new-dialog-title\">새 애니메이션 만들기</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close aria-label=\"닫기\">✕</button>\n </div>\n <div class=\"studio-dialog-body\">\n <label class=\"studio-field\"><span>ID (영문 소문자 / 숫자 / - / _)</span>\n <input type=\"text\" id=\"studio-new-id\" placeholder=\"예: user-login-flow\" />\n </label>\n <label class=\"studio-field\"><span>제목</span>\n <input type=\"text\" id=\"studio-new-title\" placeholder=\"사용자 로그인 흐름\" />\n </label>\n <div id=\"studio-new-error\" class=\"studio-new-error\"></div>\n </div>\n <footer class=\"studio-dialog-footer\">\n <button type=\"button\" class=\"studio-btn\" data-studio-dialog-close>취소</button>\n <button type=\"button\" id=\"studio-new-create\" class=\"studio-btn studio-btn-primary\">만들기</button>\n </footer>\n </dialog>\n\n <dialog id=\"studio-palette-dialog\" class=\"studio-palette-dialog\">\n <input type=\"text\" id=\"studio-palette-input\" class=\"studio-palette-input\" placeholder=\"🔍 명령 또는 요소 검색…\" autocomplete=\"off\" spellcheck=\"false\" />\n <ul id=\"studio-palette-list\" class=\"studio-palette-list\"></ul>\n <div class=\"studio-palette-footer\">↑↓ 이동 · Enter 실행 · Esc 닫기</div>\n </dialog>\n\n <dialog id=\"studio-history-dialog\" class=\"studio-history-dialog\">\n <div class=\"studio-history-header\">\n <h2>📜 작업 이력</h2>\n <button type=\"button\" class=\"studio-dialog-close\" data-studio-dialog-close aria-label=\"닫기\">✕</button>\n </div>\n <ul id=\"studio-history-list\" class=\"studio-history-list\"></ul>\n <div class=\"studio-history-footer\">항목을 클릭하면 해당 시점으로 이동합니다 · ⌘Z / ⌘⇧Z</div>\n </dialog>\n</div>\n`;\n\nexport function StudioMount({\n initialId,\n repository,\n editorTitle = \"Clotho Editor\",\n resolveImage,\n importDocument,\n plugins = EMPTY_EDITOR_PLUGINS,\n resolvePluginPermissions = DENY_PLUGIN_PERMISSIONS,\n templates = EMPTY_TEMPLATES,\n story,\n}: StudioMountProps): React.JSX.Element {\n const inited = useRef(false);\n const mountedPlugins = useMemo(\n () => [\n ...(templates.length > 0 ? [createTemplateEditorPlugin(templates)] : []),\n ...(story ? [createStoryEditorPlugin(story)] : []),\n ...plugins,\n ],\n [plugins, templates, story],\n );\n const permissionResolver = useMemo<EditorPluginPermissionResolver>(\n () => (plugin) =>\n plugin.id === \"dev.clotho.templates\" || plugin.id === \"dev.clotho.story\"\n ? { ui: true, documentRead: true, documentWrite: true }\n : resolvePluginPermissions(plugin),\n [resolvePluginPermissions],\n );\n\n useEffect(() => {\n if (inited.current) return;\n inited.current = true;\n if (repository) configureAnimationRepository(repository);\n let disposed = false;\n let cleanup: (() => void) | undefined;\n void import(\"./legacy/main\").then(({ initStudio }) => {\n if (disposed) return;\n cleanup = initStudio({\n initialId,\n editorTitle,\n resolveImage,\n importDocument,\n plugins: mountedPlugins,\n resolvePluginPermissions: permissionResolver,\n });\n });\n return () => {\n disposed = true;\n cleanup?.();\n document.body.classList.remove(\"editor-active\");\n document.documentElement.classList.remove(\"editor-active\");\n };\n }, [\n editorTitle,\n importDocument,\n initialId,\n mountedPlugins,\n repository,\n resolveImage,\n permissionResolver,\n ]);\n\n return (\n <section className=\"studio-shell w-full\" data-pagefind-ignore=\"all\">\n <div dangerouslySetInnerHTML={{ __html: SKELETON }} />\n </section>\n );\n}\n","import { animationDocumentSchema, type AnimationDocument } from \"@kokoa/clotho\";\n\nexport interface AnimationSummary {\n id: string;\n title: string;\n description: string;\n updatedAt?: string;\n source?: \"saved\" | \"example\";\n}\n\nexport interface AnimationRepository {\n list(): Promise<AnimationSummary[]>;\n load(id: string): Promise<AnimationDocument>;\n create(id: string, title: string): Promise<AnimationDocument>;\n save(def: AnimationDocument): Promise<AnimationDocument>;\n delete(id: string): Promise<void>;\n}\n\nexport interface LocalStorageRepositoryOptions {\n storageKey?: string;\n examples?: readonly AnimationDocument[];\n storage?: Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\">;\n}\n\nfunction browserStorage(): Storage {\n if (typeof localStorage === \"undefined\")\n throw new Error(\"이 저장소는 브라우저에서만 사용할 수 있습니다.\");\n return localStorage;\n}\n\nexport function createLocalStorageRepository(\n options: LocalStorageRepositoryOptions = {},\n): AnimationRepository {\n const prefix = options.storageKey ?? \"clotho-editor.animations\";\n const examples = new Map(\n (options.examples ?? []).map((value) => {\n const def = animationDocumentSchema.parse(value);\n return [def.id, def] as const;\n }),\n );\n const storage = (): Pick<Storage, \"getItem\" | \"setItem\" | \"removeItem\"> =>\n options.storage ?? browserStorage();\n const indexKey = `${prefix}:index`;\n const documentKey = (id: string): string => `${prefix}:document:${id}`;\n const readIds = (): string[] => {\n const value = storage().getItem(indexKey);\n if (!value) return [];\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed)\n ? parsed.filter((id): id is string => typeof id === \"string\")\n : [];\n } catch {\n return [];\n }\n };\n const write = (def: AnimationDocument): AnimationDocument => {\n const parsed = animationDocumentSchema.parse(def);\n const ids = readIds();\n if (!ids.includes(parsed.id))\n storage().setItem(indexKey, JSON.stringify([...ids, parsed.id]));\n storage().setItem(documentKey(parsed.id), JSON.stringify(parsed));\n return parsed;\n };\n const read = (id: string): AnimationDocument | null => {\n const value = storage().getItem(documentKey(id));\n return value ? animationDocumentSchema.parse(JSON.parse(value)) : null;\n };\n\n return {\n async list() {\n const saved = readIds()\n .map((id) => read(id))\n .filter((def): def is AnimationDocument => def !== null);\n const savedIds = new Set(saved.map((def) => def.id));\n return [\n ...saved.map((def) => ({\n id: def.id,\n title: def.title || def.id,\n description: def.description,\n source: \"saved\" as const,\n })),\n ...[...examples.values()]\n .filter((def) => !savedIds.has(def.id))\n .map((def) => ({\n id: def.id,\n title: def.title || def.id,\n description: def.description,\n source: \"example\" as const,\n })),\n ];\n },\n async load(id) {\n const def = read(id) ?? examples.get(id);\n if (!def) throw new Error(`'${id}' 애니메이션을 찾을 수 없습니다.`);\n return structuredClone(def);\n },\n async create(id, title) {\n if (read(id)) throw new Error(`'${id}' 애니메이션이 이미 있습니다.`);\n return write(\n animationDocumentSchema.parse({\n clothoVersion: 1,\n id,\n title,\n description: \"\",\n }),\n );\n },\n async save(def) {\n return write(def);\n },\n async delete(id) {\n storage().removeItem(documentKey(id));\n storage().setItem(\n indexKey,\n JSON.stringify(readIds().filter((value) => value !== id)),\n );\n },\n };\n}\n","import {\n AnimationAssertionError,\n animationFailureReport,\n animationSampleTimes,\n expectAnimation,\n snapshotAnimationMatrix,\n} from \"@kokoa/clotho/testing\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nfunction downloadReport(html: string): void {\n const url = URL.createObjectURL(new Blob([html], { type: \"text/html\" }));\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = \"clotho-animation-qa.html\";\n link.click();\n URL.revokeObjectURL(url);\n}\n\nexport function createVisualRegressionPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.visual-regression\",\n name: \"Animation QA\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"animation-qa\"] },\n },\n inspectors: {\n \"animation-qa\": {\n id: \"animation-qa\",\n label: \"Animation QA\",\n mount(container, context) {\n container.classList.add(\"studio-qa-panel\");\n const title = document.createElement(\"strong\");\n title.textContent = \"Animation QA\";\n const run = document.createElement(\"button\");\n run.type = \"button\";\n run.className = \"studio-btn\";\n run.textContent = \"전체 frame 검사\";\n const status = document.createElement(\"p\");\n status.className = \"studio-props-empty\";\n container.append(title, run, status);\n run.addEventListener(\"click\", () => {\n const animation = context.getDocument();\n const errors: AnimationAssertionError[] = [];\n for (const time of animationSampleTimes(animation)) {\n for (const element of animation.elements) {\n if (![\"rect\", \"circle\", \"image\", \"code\"].includes(element.type))\n continue;\n try {\n expectAnimation(animation).at(time).insideCanvas(element.id);\n } catch (error) {\n if (error instanceof AnimationAssertionError)\n errors.push(error);\n }\n }\n }\n const snapshots = snapshotAnimationMatrix(animation);\n if (errors.length === 0) {\n status.textContent = `${snapshots.length}개 locale·theme frame을 검사했습니다. 문제가 없습니다.`;\n status.removeAttribute(\"data-error\");\n } else {\n status.textContent = `${errors.length}개 문제를 발견했습니다. HTML report를 내려받습니다.`;\n status.dataset.error = \"true\";\n downloadReport(animationFailureReport(errors));\n }\n });\n },\n },\n },\n };\n}\n","import { compileResponsiveStage, type AnimationDocument } from \"@kokoa/clotho\";\nimport { renderDocumentToSvg } from \"@kokoa/clotho/svg\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport const RESPONSIVE_VIEWPORTS = [\n { id: \"compact\", label: \"모바일\", width: 375 },\n { id: \"regular\", label: \"본문\", width: 768 },\n { id: \"wide\", label: \"넓은 화면\", width: 1280 },\n] as const;\n\nexport function addDefaultResponsiveVariants(\n document: AnimationDocument,\n): AnimationDocument {\n if (document.responsive?.length) return document;\n return {\n ...document,\n responsive: [\n {\n id: \"compact\",\n minWidth: 0,\n maxWidth: 479,\n chapterListPosition: \"bottom\",\n elementOverrides: {},\n },\n { id: \"regular\", minWidth: 480, maxWidth: 959, elementOverrides: {} },\n { id: \"wide\", minWidth: 960, elementOverrides: {} },\n ],\n };\n}\n\nexport function createResponsiveInspectorPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.responsive\",\n name: \"Responsive Stage\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"responsive\"] },\n },\n inspectors: {\n responsive: {\n id: \"responsive\",\n label: \"Responsive Stage\",\n mount(container, context) {\n const render = () => {\n const document = context.getDocument();\n container.innerHTML = `<div class=\"studio-props-header\"><span class=\"studio-props-header-title\">Responsive Stage</span></div><button type=\"button\" class=\"studio-btn\" data-responsive-defaults>기본 breakpoint 만들기</button><div class=\"studio-responsive-grid\">${RESPONSIVE_VIEWPORTS.map((viewport) => `<figure><figcaption>${viewport.label} · ${viewport.width}px</figcaption>${renderDocumentToSvg(compileResponsiveStage(document, viewport.width), 0)}</figure>`).join(\"\")}</div>`;\n };\n const click = (event: Event) => {\n if (\n !(event.target as HTMLElement).closest(\n \"[data-responsive-defaults]\",\n )\n )\n return;\n context.replaceDocument(\n addDefaultResponsiveVariants(context.getDocument()),\n );\n render();\n };\n container.addEventListener(\"click\", click);\n render();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n","import {\n buildScene,\n compileSceneDependencyPlan,\n type AnimationDocument,\n} from \"@kokoa/clotho\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport interface SceneProfile {\n elementCount: number;\n trackCount: number;\n keyframeCount: number;\n sampleCount: number;\n totalMs: number;\n averageMs: number;\n maxMs: number;\n overBudget: boolean;\n}\n\nexport function profileAnimation(\n document: AnimationDocument,\n sampleCount = 30,\n frameBudgetMs = 16.7,\n): SceneProfile {\n const plan = compileSceneDependencyPlan(document);\n const samples: number[] = [];\n for (let index = 0; index < sampleCount; index += 1) {\n const time =\n sampleCount === 1 ? 0 : (document.duration * index) / (sampleCount - 1);\n const started = performance.now();\n buildScene(document, time);\n samples.push(performance.now() - started);\n }\n const totalMs = samples.reduce((sum, value) => sum + value, 0);\n const maxMs = Math.max(0, ...samples);\n return {\n elementCount: plan.elementCount,\n trackCount: plan.trackCount,\n keyframeCount: plan.keyframeCount,\n sampleCount,\n totalMs,\n averageMs: totalMs / Math.max(1, sampleCount),\n maxMs,\n overBudget: maxMs > frameBudgetMs,\n };\n}\n\nexport function createPerformanceProfilerPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.performance\",\n name: \"Scene Profiler\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"performance\"] },\n },\n inspectors: {\n performance: {\n id: \"performance\",\n label: \"Scene Profiler\",\n mount(container, context) {\n const run = () => {\n const profile = profileAnimation(context.getDocument());\n container.innerHTML = `<div class=\"studio-props-header\"><span class=\"studio-props-header-title\">Scene Profiler</span></div><dl class=\"studio-profile\"><div><dt>Elements</dt><dd>${profile.elementCount}</dd></div><div><dt>Tracks / keyframes</dt><dd>${profile.trackCount} / ${profile.keyframeCount}</dd></div><div><dt>평균 / 최대</dt><dd>${profile.averageMs.toFixed(2)} / ${profile.maxMs.toFixed(2)} ms</dd></div></dl><p class=\"studio-template-status\" data-error=\"${profile.overBudget}\">${profile.overBudget ? \"16.7ms frame budget을 넘었습니다.\" : \"60fps frame budget 안에 있습니다.\"}</p><button type=\"button\" class=\"studio-btn\" data-run-profiler>다시 측정</button>`;\n };\n const click = (event: Event) => {\n if ((event.target as HTMLElement).closest(\"[data-run-profiler]\"))\n run();\n };\n container.addEventListener(\"click\", click);\n run();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n","import { autofixDocument, lintDocument } from \"@kokoa/clotho\";\nimport { renderDocumentToSvg } from \"@kokoa/clotho/svg\";\nimport type { EditorPluginDefinition } from \"./plugin-host\";\n\nexport function createLinterPlugin(): EditorPluginDefinition {\n return {\n manifest: {\n id: \"dev.clotho.linter\",\n name: \"Clotho Linter\",\n capabilities: [\"editor\"],\n editor: { inspectors: [\"linter\"] },\n },\n inspectors: {\n linter: {\n id: \"linter\",\n label: \"Clotho Linter\",\n mount(container, context) {\n let selectedIndex = 0;\n const render = () => {\n const document = context.getDocument();\n const issues = lintDocument(document);\n const selected = issues[selectedIndex] ?? issues[0];\n const fixed = autofixDocument(document).document;\n container.innerHTML = `<div class=\"studio-props-header\"><span class=\"studio-props-header-title\">Clotho Linter (${issues.length})</span><button type=\"button\" class=\"studio-btn\" data-lint-fix ${issues.some(({ fixable }) => fixable) ? \"\" : \"disabled\"}>안전한 수정 적용</button></div><ol class=\"studio-lint-list\">${issues.map((issue, index) => `<li><button type=\"button\" data-lint-index=\"${index}\" data-element-id=\"${issue.elementId ?? \"\"}\"><strong>${escapeHtml(issue.ruleId)}</strong><span>${escapeHtml(issue.message)}</span>${issue.fixable ? \"<em>자동 수정</em>\" : \"\"}</button></li>`).join(\"\") || \"<li>문제가 없습니다.</li>\"}</ol>${selected ? `<div class=\"studio-lint-compare\"><figure><figcaption>현재</figcaption>${renderDocumentToSvg(document, selected.time ?? 0)}</figure><figure><figcaption>수정 후</figcaption>${renderDocumentToSvg(fixed, selected.time ?? 0)}</figure></div>` : \"\"}`;\n };\n const click = (event: Event) => {\n const target = event.target as HTMLElement;\n if (target.closest(\"[data-lint-fix]\")) {\n context.replaceDocument(\n autofixDocument(context.getDocument()).document,\n );\n selectedIndex = 0;\n render();\n return;\n }\n const issue = target.closest<HTMLElement>(\"[data-lint-index]\");\n if (!issue) return;\n selectedIndex = Number(issue.dataset.lintIndex);\n if (issue.dataset.elementId)\n context.setSelection({\n kind: \"element\",\n elementId: issue.dataset.elementId,\n });\n render();\n };\n container.addEventListener(\"click\", click);\n render();\n return () => container.removeEventListener(\"click\", click);\n },\n },\n },\n };\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n}\n"]}
|