@kokoa/clotho-editor 0.1.4 → 0.2.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/README.md +53 -1
- package/dist/{chunk-GMGB7NIL.js → chunk-FAI2G3XK.js} +262 -20
- package/dist/chunk-FAI2G3XK.js.map +1 -0
- package/dist/clotho-editor.css +129 -0
- package/dist/index.d.ts +149 -18
- package/dist/index.js +514 -9
- package/dist/index.js.map +1 -1
- package/dist/{main-NCPWDB2U.js → main-SKM3P4X7.js} +367 -19
- package/dist/main-SKM3P4X7.js.map +1 -0
- package/package.json +7 -3
- package/dist/chunk-GMGB7NIL.js.map +0 -1
- package/dist/main-NCPWDB2U.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { updateCanvas, getDef, subscribe, updateMeta,
|
|
2
|
-
import { activeAppearance, animationDocumentSchema, resolveAsset } from '@kokoa/clotho';
|
|
1
|
+
import { updateCanvas, getDef, subscribe, updateMeta, mountEditorPlugins, setSelection, getSelection, setDef, undo, redo, downloadAnimationJson, importAnimation, markClean, updateSettings, isDirty, isDraft, canUndo, canRedo, uniqueChapterId, getCurrentTime, addChapter, uniqueElementId, registerExternalAsset, addElement, registerDataUriAsset, listAnimations, setDraft, saveAnimation, deleteAnimation, duplicateAnimation, createAnimation, getSelectedElementIds, deleteElement, deleteChapter, deleteEffect, updateChapter, isGroup, ungroupElement, groupElements, moveElementToEnd, moveElementToFront, reorderElement, loadAnimation, getCurrentSnapshot, setElementValueAtTime, findContainingGroup, isElementSelected, updateElementBase, createLayout, detachFromLayout, addCheckpoint, uniqueCheckpointId, deleteCheckpoint, uniqueEffectId, addEffect, removeAppearance, removeTrack, removeTrackKeyframe, setTrackKeyframe, setCurrentTime, addAppearance, jumpBack, jumpForward, getHistory, promoteDraftToSaved, toggleSelectionFor, moveGroupBy, placeholderImageUrl, groupBbox, layoutIdsFor, findLayoutCollisions, updateLocales, updateData, updateResponsive, updateDuration, updateCheckpoint, updateAppearance, updateEffect, childIdsOf } from './chunk-FAI2G3XK.js';
|
|
2
|
+
import { activeAppearance, animationDocumentSchema, bindablePropertiesFor, resolveAsset, compileDataBindings } from '@kokoa/clotho';
|
|
3
3
|
|
|
4
4
|
// src/legacy/grid.ts
|
|
5
5
|
var STORAGE_KEY = "studio.grid";
|
|
@@ -646,6 +646,7 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
646
646
|
rotation: 0,
|
|
647
647
|
appearances: [],
|
|
648
648
|
tracks: [],
|
|
649
|
+
bindings: [],
|
|
649
650
|
x: cx - 60,
|
|
650
651
|
y: cy - 30,
|
|
651
652
|
width: 120,
|
|
@@ -665,6 +666,7 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
665
666
|
rotation: 0,
|
|
666
667
|
appearances: [],
|
|
667
668
|
tracks: [],
|
|
669
|
+
bindings: [],
|
|
668
670
|
cx,
|
|
669
671
|
cy,
|
|
670
672
|
r: 36,
|
|
@@ -682,6 +684,7 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
682
684
|
rotation: 0,
|
|
683
685
|
appearances: [],
|
|
684
686
|
tracks: [],
|
|
687
|
+
bindings: [],
|
|
685
688
|
x1: cx - 80,
|
|
686
689
|
y1: cy,
|
|
687
690
|
x2: cx + 80,
|
|
@@ -698,6 +701,7 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
698
701
|
rotation: 0,
|
|
699
702
|
appearances: [],
|
|
700
703
|
tracks: [],
|
|
704
|
+
bindings: [],
|
|
701
705
|
x1: cx - 100,
|
|
702
706
|
y1: cy,
|
|
703
707
|
x2: cx + 100,
|
|
@@ -718,10 +722,12 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
718
722
|
rotation: 0,
|
|
719
723
|
appearances: [],
|
|
720
724
|
tracks: [],
|
|
725
|
+
bindings: [],
|
|
721
726
|
x: cx,
|
|
722
727
|
y: cy,
|
|
723
728
|
content: id,
|
|
724
729
|
translations: {},
|
|
730
|
+
references: {},
|
|
725
731
|
fontSize: 18,
|
|
726
732
|
fontWeight: 400,
|
|
727
733
|
color: "#18181b",
|
|
@@ -734,6 +740,7 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
734
740
|
rotation: 0,
|
|
735
741
|
appearances: [],
|
|
736
742
|
tracks: [],
|
|
743
|
+
bindings: [],
|
|
737
744
|
x: cx - 50,
|
|
738
745
|
y: cy - 50,
|
|
739
746
|
width: 100,
|
|
@@ -749,6 +756,7 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
749
756
|
rotation: 0,
|
|
750
757
|
appearances: [],
|
|
751
758
|
tracks: [],
|
|
759
|
+
bindings: [],
|
|
752
760
|
x: cx - 40,
|
|
753
761
|
y: cy - 40,
|
|
754
762
|
d: "M 0 0 L 80 0 L 40 80 Z",
|
|
@@ -770,6 +778,7 @@ function makeDefaultElement(type, id, cx, cy, polygonSides = 6) {
|
|
|
770
778
|
rotation: 0,
|
|
771
779
|
appearances: [],
|
|
772
780
|
tracks: [],
|
|
781
|
+
bindings: [],
|
|
773
782
|
points: pts,
|
|
774
783
|
fill: "#a5b4fc",
|
|
775
784
|
stroke: "#6366f1",
|
|
@@ -1045,8 +1054,6 @@ function renderSelectionOutline(canvasEl2, elId, snap2, byId) {
|
|
|
1045
1054
|
rect.classList.add("element-selected-outline");
|
|
1046
1055
|
return rect;
|
|
1047
1056
|
}
|
|
1048
|
-
|
|
1049
|
-
// src/legacy/canvas-preview.ts
|
|
1050
1057
|
var previewRoot = null;
|
|
1051
1058
|
var previewHandle = null;
|
|
1052
1059
|
var unsubscribePreview = null;
|
|
@@ -1075,7 +1082,7 @@ function showPreview(canvasEl2, def, options) {
|
|
|
1075
1082
|
previewRoot.style.cssText = `position:absolute;left:0;top:0;width:${def.canvas.width}px;height:${def.canvas.height}px;background:${bg};z-index:2;overflow:hidden;`;
|
|
1076
1083
|
parent.style.position = "relative";
|
|
1077
1084
|
parent.appendChild(previewRoot);
|
|
1078
|
-
void mountPreview(previewRoot, def, options);
|
|
1085
|
+
void mountPreview(previewRoot, compileDataBindings(def).document, options);
|
|
1079
1086
|
}
|
|
1080
1087
|
function hidePreview(canvasEl2) {
|
|
1081
1088
|
if (canvasEl2) canvasEl2.style.visibility = "";
|
|
@@ -1824,6 +1831,7 @@ function onMouseUp(e) {
|
|
|
1824
1831
|
rotation: 0,
|
|
1825
1832
|
appearances: [],
|
|
1826
1833
|
tracks: [],
|
|
1834
|
+
bindings: [],
|
|
1827
1835
|
fromId: connectState.fromId,
|
|
1828
1836
|
toId: elemId,
|
|
1829
1837
|
fromAnchor: connectState.fromAnchor,
|
|
@@ -2708,6 +2716,41 @@ function parseLocales(value) {
|
|
|
2708
2716
|
return true;
|
|
2709
2717
|
});
|
|
2710
2718
|
}
|
|
2719
|
+
function annotationTokens(...values) {
|
|
2720
|
+
const tokens = values.flatMap(
|
|
2721
|
+
(value) => [...value.matchAll(/\{([a-z][a-z0-9_-]*)\}/g)].map((match) => match[1])
|
|
2722
|
+
);
|
|
2723
|
+
return [...new Set(tokens)];
|
|
2724
|
+
}
|
|
2725
|
+
function annotationReferenceFields(keyPrefix, values, references = {}) {
|
|
2726
|
+
const tokens = annotationTokens(...values);
|
|
2727
|
+
if (tokens.length === 0) {
|
|
2728
|
+
return [
|
|
2729
|
+
'<p class="studio-props-empty studio-annotation-hint">\uBB38\uAD6C\uC5D0 {token}\uC744 \uC785\uB825\uD558\uBA74 \uC7A5\uBA74 \uC694\uC18C\uC640 \uC5F0\uACB0\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.</p>'
|
|
2730
|
+
];
|
|
2731
|
+
}
|
|
2732
|
+
return [
|
|
2733
|
+
'<p class="studio-props-empty studio-annotation-hint">\uB300\uC0C1 element id\uB97C \uC27C\uD45C\uB85C \uAD6C\uBD84\uD558\uC138\uC694. \uC5EC\uB7EC \uC694\uC18C\uB97C \uD568\uAED8 \uAC15\uC870\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.</p>',
|
|
2734
|
+
...tokens.map((token) => {
|
|
2735
|
+
const target = references[token];
|
|
2736
|
+
const value = typeof target === "string" ? target : target?.join(", ") ?? "";
|
|
2737
|
+
return textField(
|
|
2738
|
+
`{${token}} \uB300\uC0C1`,
|
|
2739
|
+
`${keyPrefix}.reference.${token}`,
|
|
2740
|
+
value
|
|
2741
|
+
);
|
|
2742
|
+
})
|
|
2743
|
+
];
|
|
2744
|
+
}
|
|
2745
|
+
function parseReferenceTargets(value) {
|
|
2746
|
+
const targets = [
|
|
2747
|
+
...new Set(
|
|
2748
|
+
value.split(",").map((id) => id.trim()).filter(Boolean)
|
|
2749
|
+
)
|
|
2750
|
+
];
|
|
2751
|
+
if (targets.length === 0) return void 0;
|
|
2752
|
+
return targets.length === 1 ? targets[0] : targets;
|
|
2753
|
+
}
|
|
2711
2754
|
function initProperties(root) {
|
|
2712
2755
|
panelEl = root;
|
|
2713
2756
|
subscribe(render3);
|
|
@@ -2779,6 +2822,9 @@ function textField(label, key, value) {
|
|
|
2779
2822
|
<input type="text" data-prop-key="${escapeHtml2(key)}" value="${escapeHtml2(value ?? "")}" />
|
|
2780
2823
|
</label>`;
|
|
2781
2824
|
}
|
|
2825
|
+
function textareaField(label, key, value) {
|
|
2826
|
+
return `<label class="studio-field"><span>${escapeHtml2(label)}</span><textarea rows="7" spellcheck="false" data-prop-key="${escapeHtml2(key)}">${escapeHtml2(value)}</textarea></label>`;
|
|
2827
|
+
}
|
|
2782
2828
|
function numberField(label, key, value, step = 1) {
|
|
2783
2829
|
return `<label class="studio-field">
|
|
2784
2830
|
<span>${escapeHtml2(label)}</span>
|
|
@@ -2833,7 +2879,18 @@ function renderInner() {
|
|
|
2833
2879
|
"canvas.background",
|
|
2834
2880
|
"canvas.background",
|
|
2835
2881
|
def.canvas.background
|
|
2836
|
-
)
|
|
2882
|
+
),
|
|
2883
|
+
textareaField(
|
|
2884
|
+
"\uC0D8\uD50C \uB370\uC774\uD130 (JSON)",
|
|
2885
|
+
"meta.data",
|
|
2886
|
+
JSON.stringify(def.data, null, 2)
|
|
2887
|
+
),
|
|
2888
|
+
textareaField(
|
|
2889
|
+
"Responsive variants (JSON)",
|
|
2890
|
+
"meta.responsive",
|
|
2891
|
+
JSON.stringify(def.responsive ?? [], null, 2)
|
|
2892
|
+
),
|
|
2893
|
+
`<p class="studio-props-empty">JSON Pointer\uB85C \uC694\uC18C \uC18D\uC131\uC5D0 \uC5F0\uACB0\uD569\uB2C8\uB2E4. \uC774 \uB370\uC774\uD130\uB294 \uBBF8\uB9AC\uBCF4\uAE30\uC640 \uB0B4\uBCF4\uB0B4\uAE30\uC5D0 \uD568\uAED8 \uC800\uC7A5\uB429\uB2C8\uB2E4.</p>`
|
|
2837
2894
|
].join("");
|
|
2838
2895
|
const settingsHeader = `<span class="studio-props-header-title">\uC124\uC815</span>`;
|
|
2839
2896
|
const settingsBody = [
|
|
@@ -2861,10 +2918,61 @@ function renderInner() {
|
|
|
2861
2918
|
]
|
|
2862
2919
|
)
|
|
2863
2920
|
].join("");
|
|
2921
|
+
const checkpoints = def.checkpoints.map((checkpoint, index) => {
|
|
2922
|
+
const specific = checkpoint.interaction === "choice" ? textField(
|
|
2923
|
+
"\uC120\uD0DD\uC9C0 (value:label, \uC27C\uD45C \uAD6C\uBD84)",
|
|
2924
|
+
`checkpoint.${index}.options`,
|
|
2925
|
+
checkpoint.options.map(({ value, label }) => `${value}:${label}`).join(", ")
|
|
2926
|
+
) : checkpoint.interaction === "select-element" ? textField(
|
|
2927
|
+
"\uC120\uD0DD \uAC00\uB2A5\uD55C element id",
|
|
2928
|
+
`checkpoint.${index}.elementIds`,
|
|
2929
|
+
checkpoint.elementIds.join(", ")
|
|
2930
|
+
) : checkpoint.interaction === "number-input" ? [
|
|
2931
|
+
numberField(
|
|
2932
|
+
"\uCD5C\uC19F\uAC12",
|
|
2933
|
+
`checkpoint.${index}.min`,
|
|
2934
|
+
checkpoint.min
|
|
2935
|
+
),
|
|
2936
|
+
numberField(
|
|
2937
|
+
"\uCD5C\uB313\uAC12",
|
|
2938
|
+
`checkpoint.${index}.max`,
|
|
2939
|
+
checkpoint.max
|
|
2940
|
+
),
|
|
2941
|
+
numberField(
|
|
2942
|
+
"\uAC04\uACA9",
|
|
2943
|
+
`checkpoint.${index}.step`,
|
|
2944
|
+
checkpoint.step
|
|
2945
|
+
)
|
|
2946
|
+
].join("") : "";
|
|
2947
|
+
const predicate = "predicate" in checkpoint && checkpoint.predicate?.type === "equals" ? textField(
|
|
2948
|
+
"\uC815\uB2F5 (equals)",
|
|
2949
|
+
`checkpoint.${index}.answer`,
|
|
2950
|
+
String(checkpoint.predicate.value)
|
|
2951
|
+
) : "";
|
|
2952
|
+
return `<div class="studio-checkpoint-card" data-checkpoint-id="${escapeHtml2(checkpoint.id)}">
|
|
2953
|
+
<div class="studio-props-header"><span class="studio-props-header-title">${escapeHtml2(checkpoint.id)}</span><button type="button" class="studio-btn studio-btn-danger" data-delete-checkpoint="${escapeHtml2(checkpoint.id)}">\uC0AD\uC81C</button></div>
|
|
2954
|
+
${numberField("time (ms)", `checkpoint.${index}.time`, checkpoint.time, 50)}
|
|
2955
|
+
${textField("\uC9C8\uBB38", `checkpoint.${index}.prompt`, checkpoint.prompt)}
|
|
2956
|
+
${selectField(
|
|
2957
|
+
"\uC0C1\uD638\uC791\uC6A9",
|
|
2958
|
+
`checkpoint.${index}.interaction`,
|
|
2959
|
+
checkpoint.interaction,
|
|
2960
|
+
[
|
|
2961
|
+
{ value: "continue", label: "\uACC4\uC18D" },
|
|
2962
|
+
{ value: "choice", label: "\uC120\uD0DD\uC9C0" },
|
|
2963
|
+
{ value: "select-element", label: "\uC694\uC18C \uC120\uD0DD" },
|
|
2964
|
+
{ value: "number-input", label: "\uC22B\uC790 \uC785\uB825" }
|
|
2965
|
+
]
|
|
2966
|
+
)}
|
|
2967
|
+
${checkboxField("\uC751\uB2F5 \uD544\uC218", `checkpoint.${index}.required`, checkpoint.required)}
|
|
2968
|
+
${specific}${predicate}
|
|
2969
|
+
</div>`;
|
|
2970
|
+
}).join("");
|
|
2864
2971
|
panelEl.innerHTML = `
|
|
2865
2972
|
${timeHint}
|
|
2866
2973
|
${section("meta", metaHeader, metaBody)}
|
|
2867
2974
|
${section("settings", settingsHeader, settingsBody)}
|
|
2975
|
+
${section("checkpoints", `<span class="studio-props-header-title">Checkpoint (${def.checkpoints.length})</span>`, `${checkpoints}<button type="button" class="studio-btn" data-add-checkpoint>\uFF0B \uD604\uC7AC \uC2DC\uAC04\uC5D0 checkpoint \uCD94\uAC00</button>`)}
|
|
2868
2976
|
<div class="studio-props-header" style="margin-top:0.6rem"><span class="studio-props-header-title">\uBAA9\uCC28 (${def.chapters.length})</span></div>
|
|
2869
2977
|
<button type="button" class="studio-btn" data-add-chapter>\uFF0B \uD604\uC7AC \uC2DC\uAC04\uC5D0 chapter \uCD94\uAC00</button>
|
|
2870
2978
|
<div class="studio-props-header" style="margin-top:0.6rem"><span class="studio-props-header-title">\uD6A8\uACFC (${def.effects.length})</span></div>
|
|
@@ -2882,6 +2990,10 @@ function renderInner() {
|
|
|
2882
2990
|
if (sel.kind === "elements") {
|
|
2883
2991
|
const alignBtn = (kind, label, title) => `<button type="button" class="studio-btn studio-align-btn" data-align="${kind}" title="${escapeHtml2(title)}" aria-label="${escapeHtml2(title)}">${label}</button>`;
|
|
2884
2992
|
const distributeDisabled = sel.elementIds.length < 3 ? "disabled" : "";
|
|
2993
|
+
const layoutIds = layoutIdsFor(sel.elementIds);
|
|
2994
|
+
const collisions = findLayoutCollisions(def).filter(
|
|
2995
|
+
({ firstId, secondId }) => sel.elementIds.includes(firstId) || sel.elementIds.includes(secondId)
|
|
2996
|
+
);
|
|
2885
2997
|
panelEl.innerHTML = `
|
|
2886
2998
|
${timeHint}
|
|
2887
2999
|
<div class="studio-props-header"><span class="studio-props-header-title">\uB2E4\uC911 \uC120\uD0DD</span><span class="studio-props-header-type">${sel.elementIds.length} elements</span></div>
|
|
@@ -2905,6 +3017,16 @@ function renderInner() {
|
|
|
2905
3017
|
<button type="button" class="studio-btn studio-align-btn" data-distribute="vertical" title="\uC138\uB85C \uADE0\uB4F1 \uBD84\uD3EC" ${distributeDisabled}>\u2195</button>
|
|
2906
3018
|
</div>
|
|
2907
3019
|
</div>
|
|
3020
|
+
<div class="studio-align-section studio-layout-section">
|
|
3021
|
+
<div class="studio-align-title">Constraint Layout</div>
|
|
3022
|
+
<div class="studio-align-row">
|
|
3023
|
+
<button type="button" class="studio-btn" data-create-layout="row">\uAC00\uB85C</button>
|
|
3024
|
+
<button type="button" class="studio-btn" data-create-layout="column">\uC138\uB85C</button>
|
|
3025
|
+
<button type="button" class="studio-btn" data-create-layout="grid">\uACA9\uC790</button>
|
|
3026
|
+
</div>
|
|
3027
|
+
${layoutIds.length > 0 ? `<p class="studio-layout-status">\uC801\uC6A9 \uC911: ${layoutIds.map(escapeHtml2).join(", ")}</p><button type="button" class="studio-btn" data-detach-layout>\uD604\uC7AC \uC88C\uD45C\uB85C \uACE0\uC815</button>` : '<p class="studio-layout-status">\uC120\uD0DD\uD55C \uC694\uC18C\uC5D0 \uC801\uC6A9\uB41C layout\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.</p>'}
|
|
3028
|
+
${collisions.length > 0 ? `<p class="studio-layout-collision" role="alert">\uACB9\uCE68: ${collisions.map(({ firstId, secondId }) => `${escapeHtml2(firstId)} \u2194 ${escapeHtml2(secondId)}`).join(", ")}</p>` : ""}
|
|
3029
|
+
</div>
|
|
2908
3030
|
<ul style="font-family:var(--font-mono);font-size:0.72rem;color:var(--color-fg-muted);padding-left:1rem;margin:0.6rem 0 0">
|
|
2909
3031
|
${sel.elementIds.map((id) => `<li>${escapeHtml2(id)}</li>`).join("")}
|
|
2910
3032
|
</ul>
|
|
@@ -2926,12 +3048,14 @@ function renderInner() {
|
|
|
2926
3048
|
setSelection({ kind: "none" });
|
|
2927
3049
|
return;
|
|
2928
3050
|
}
|
|
3051
|
+
const chapterReferences = ch.references;
|
|
2929
3052
|
panelEl.innerHTML = `
|
|
2930
3053
|
${timeHint}
|
|
2931
3054
|
<div class="studio-props-header"><span class="studio-props-header-title">${escapeHtml2(ch.id)}</span><span class="studio-props-header-type">chapter</span></div>
|
|
2932
3055
|
${numberField("time (ms)", "chapter.time", ch.time, 50)}
|
|
2933
3056
|
${textField("label", "chapter.label", ch.label)}
|
|
2934
3057
|
${textField("subtitle", "chapter.subtitle", ch.subtitle)}
|
|
3058
|
+
${annotationReferenceFields("chapter", [ch.label, ch.subtitle], chapterReferences).join("")}
|
|
2935
3059
|
<button type="button" class="studio-btn studio-btn-danger" data-delete-chapter style="margin-top:0.6rem">\u{1F5D1} chapter \uC0AD\uC81C</button>
|
|
2936
3060
|
`;
|
|
2937
3061
|
return;
|
|
@@ -2988,6 +3112,7 @@ function renderElementForm(def, el) {
|
|
|
2988
3112
|
const baseFields = renderBaseFields(def, el);
|
|
2989
3113
|
const appearances = renderAppearances(def, el);
|
|
2990
3114
|
const tracks = renderTracks(el);
|
|
3115
|
+
const bindings = renderBindings(el);
|
|
2991
3116
|
const baseHeader = `<span class="studio-props-header-title">${escapeHtml2(el.id)}</span><span class="studio-props-header-type">${escapeHtml2(el.type)}</span>`;
|
|
2992
3117
|
const apHeader = `<span class="studio-props-header-title">\uCD9C\uD604 (Appearances)</span><button type="button" class="studio-btn studio-btn-small" data-add-appearance>\uFF0B</button>`;
|
|
2993
3118
|
const tracksHeader = `<span class="studio-props-header-title">\uD0A4\uD504\uB808\uC784 \uD2B8\uB799 (${el.tracks.length})</span>`;
|
|
@@ -2996,12 +3121,45 @@ function renderElementForm(def, el) {
|
|
|
2996
3121
|
${section("el-base", baseHeader, baseFields)}
|
|
2997
3122
|
${section("el-appearances", apHeader, appearances)}
|
|
2998
3123
|
${section("el-tracks", tracksHeader, tracks)}
|
|
3124
|
+
${section("el-bindings", `<span class="studio-props-header-title">\uB370\uC774\uD130 \uC5F0\uACB0 (${el.bindings.length})</span>`, bindings)}
|
|
2999
3125
|
<div class="studio-props-empty" style="font-size:0.72rem;margin-top:0.5rem">
|
|
3000
3126
|
base \uC18D\uC131\uC744 \uBCC0\uACBD\uD558\uBA74 \u2192 t=${getCurrentTime()} ms \uC5D0 keyframe \uCD94\uAC00<br/>
|
|
3001
3127
|
\uD2B8\uB799\uC774 \uC5C6\uB294 \uC18D\uC131\uC740 base \uAC12\uC774 \uD56D\uC0C1 \uC0AC\uC6A9\uB428
|
|
3002
3128
|
</div>
|
|
3003
3129
|
`;
|
|
3004
3130
|
}
|
|
3131
|
+
function renderBindings(el) {
|
|
3132
|
+
const properties = bindablePropertiesFor(el);
|
|
3133
|
+
const rows = el.bindings.map(
|
|
3134
|
+
(binding, index) => `<div class="studio-appearance-row">
|
|
3135
|
+
<div class="studio-appearance-row-head"><span class="studio-appearance-row-title">#${index + 1}</span><button type="button" class="studio-btn studio-btn-small studio-btn-danger" data-delete-binding="${index}">\u2715</button></div>
|
|
3136
|
+
${selectField(
|
|
3137
|
+
"\uC18D\uC131",
|
|
3138
|
+
`binding.${index}.property`,
|
|
3139
|
+
binding.property,
|
|
3140
|
+
properties.map((value) => ({ value }))
|
|
3141
|
+
)}
|
|
3142
|
+
${textField("JSON Pointer", `binding.${index}.pointer`, binding.pointer)}
|
|
3143
|
+
${selectField(
|
|
3144
|
+
"\uD45C\uD604 \uBC29\uC2DD",
|
|
3145
|
+
`binding.${index}.formatter`,
|
|
3146
|
+
binding.formatter,
|
|
3147
|
+
[
|
|
3148
|
+
"identity",
|
|
3149
|
+
"string",
|
|
3150
|
+
"number",
|
|
3151
|
+
"fixed",
|
|
3152
|
+
"percent",
|
|
3153
|
+
"uppercase",
|
|
3154
|
+
"lowercase",
|
|
3155
|
+
"color"
|
|
3156
|
+
].map((value) => ({ value }))
|
|
3157
|
+
)}
|
|
3158
|
+
${textField("\uB300\uCCB4 \uAC12", `binding.${index}.fallback`, binding.fallback === void 0 ? "" : String(binding.fallback))}
|
|
3159
|
+
</div>`
|
|
3160
|
+
).join("");
|
|
3161
|
+
return `${rows || '<p class="studio-props-empty">\uC5F0\uACB0\uB41C \uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.</p>'}<button type="button" class="studio-btn" data-add-binding ${properties.length === 0 ? "disabled" : ""}>\uFF0B \uB370\uC774\uD130 \uC5F0\uACB0</button>`;
|
|
3162
|
+
}
|
|
3005
3163
|
function renderBaseFields(def, el) {
|
|
3006
3164
|
const numberFields = [];
|
|
3007
3165
|
const colorFields = [];
|
|
@@ -3133,6 +3291,11 @@ function renderBaseFields(def, el) {
|
|
|
3133
3291
|
`el.translation.${locale}`,
|
|
3134
3292
|
localized.translations?.[locale] ?? ""
|
|
3135
3293
|
)
|
|
3294
|
+
),
|
|
3295
|
+
...annotationReferenceFields(
|
|
3296
|
+
"el",
|
|
3297
|
+
[el.content, ...Object.values(localized.translations ?? {})],
|
|
3298
|
+
localized.references
|
|
3136
3299
|
)
|
|
3137
3300
|
];
|
|
3138
3301
|
})();
|
|
@@ -3208,7 +3371,7 @@ function onInput(e) {
|
|
|
3208
3371
|
if (!key) return;
|
|
3209
3372
|
if (target.type === "text" && e.isComposing) return;
|
|
3210
3373
|
if (target.type === "text" && isComposingFallback) return;
|
|
3211
|
-
if (target.type === "color") {
|
|
3374
|
+
if (target instanceof HTMLInputElement && target.type === "color") {
|
|
3212
3375
|
const textInput = target.parentElement?.querySelector(
|
|
3213
3376
|
`input[type="text"][data-prop-key="${CSS.escape(key)}"]`
|
|
3214
3377
|
);
|
|
@@ -3216,8 +3379,10 @@ function onInput(e) {
|
|
|
3216
3379
|
return;
|
|
3217
3380
|
}
|
|
3218
3381
|
let value = target.value;
|
|
3219
|
-
if (target.type === "number")
|
|
3220
|
-
|
|
3382
|
+
if (target instanceof HTMLInputElement && target.type === "number")
|
|
3383
|
+
value = Number(target.value);
|
|
3384
|
+
else if (target instanceof HTMLInputElement && target.type === "checkbox")
|
|
3385
|
+
value = target.checked;
|
|
3221
3386
|
apply(key, value);
|
|
3222
3387
|
}
|
|
3223
3388
|
function onChange(e) {
|
|
@@ -3239,6 +3404,22 @@ function apply(key, value) {
|
|
|
3239
3404
|
else if (key === "meta.locales") {
|
|
3240
3405
|
const locales = parseLocales(String(value));
|
|
3241
3406
|
if (locales.length > 0) updateLocales(locales);
|
|
3407
|
+
} else if (key === "meta.data") {
|
|
3408
|
+
try {
|
|
3409
|
+
const parsed = JSON.parse(String(value));
|
|
3410
|
+
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed))
|
|
3411
|
+
updateData(parsed);
|
|
3412
|
+
} catch {
|
|
3413
|
+
}
|
|
3414
|
+
} else if (key === "meta.responsive") {
|
|
3415
|
+
try {
|
|
3416
|
+
const parsed = JSON.parse(String(value));
|
|
3417
|
+
if (Array.isArray(parsed))
|
|
3418
|
+
updateResponsive(
|
|
3419
|
+
parsed
|
|
3420
|
+
);
|
|
3421
|
+
} catch {
|
|
3422
|
+
}
|
|
3242
3423
|
} else if (key === "meta.duration") updateDuration(Number(value));
|
|
3243
3424
|
else if (key === "canvas.width") updateCanvas({ width: Number(value) });
|
|
3244
3425
|
else if (key === "canvas.height") updateCanvas({ height: Number(value) });
|
|
@@ -3255,7 +3436,56 @@ function apply(key, value) {
|
|
|
3255
3436
|
updateSettings({
|
|
3256
3437
|
chapterListPosition: String(value)
|
|
3257
3438
|
});
|
|
3258
|
-
else if (key.startsWith("
|
|
3439
|
+
else if (key.startsWith("checkpoint.")) {
|
|
3440
|
+
const [, indexText, property] = key.split(".");
|
|
3441
|
+
const checkpoint = def.checkpoints[Number(indexText)];
|
|
3442
|
+
if (!checkpoint || !property) return;
|
|
3443
|
+
if (property === "interaction") {
|
|
3444
|
+
const base = {
|
|
3445
|
+
id: checkpoint.id,
|
|
3446
|
+
time: checkpoint.time,
|
|
3447
|
+
prompt: checkpoint.prompt,
|
|
3448
|
+
required: checkpoint.required
|
|
3449
|
+
};
|
|
3450
|
+
const interaction = String(value);
|
|
3451
|
+
const replacement = interaction === "choice" ? {
|
|
3452
|
+
...base,
|
|
3453
|
+
interaction,
|
|
3454
|
+
options: [{ value: "option", label: "\uC120\uD0DD\uC9C0" }]
|
|
3455
|
+
} : interaction === "select-element" ? {
|
|
3456
|
+
...base,
|
|
3457
|
+
interaction,
|
|
3458
|
+
elementIds: [def.elements[0]?.id ?? "element"]
|
|
3459
|
+
} : interaction === "number-input" ? { ...base, interaction } : { ...base, interaction: "continue" };
|
|
3460
|
+
updateCheckpoint(checkpoint.id, replacement);
|
|
3461
|
+
} else if (property === "time")
|
|
3462
|
+
updateCheckpoint(checkpoint.id, { time: Number(value) });
|
|
3463
|
+
else if (property === "prompt")
|
|
3464
|
+
updateCheckpoint(checkpoint.id, { prompt: String(value) });
|
|
3465
|
+
else if (property === "required")
|
|
3466
|
+
updateCheckpoint(checkpoint.id, { required: Boolean(value) });
|
|
3467
|
+
else if (property === "options" && checkpoint.interaction === "choice") {
|
|
3468
|
+
const options = String(value).split(",").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
|
|
3469
|
+
const [optionValue, ...label] = entry.split(":");
|
|
3470
|
+
return {
|
|
3471
|
+
value: optionValue || "option",
|
|
3472
|
+
label: label.join(":") || optionValue || "\uC120\uD0DD\uC9C0"
|
|
3473
|
+
};
|
|
3474
|
+
});
|
|
3475
|
+
if (options.length > 0) updateCheckpoint(checkpoint.id, { options });
|
|
3476
|
+
} else if (property === "elementIds" && checkpoint.interaction === "select-element") {
|
|
3477
|
+
const elementIds = String(value).split(",").map((id) => id.trim()).filter(Boolean);
|
|
3478
|
+
if (elementIds.length > 0)
|
|
3479
|
+
updateCheckpoint(checkpoint.id, { elementIds });
|
|
3480
|
+
} else if (["min", "max", "step"].includes(property) && checkpoint.interaction === "number-input") {
|
|
3481
|
+
updateCheckpoint(checkpoint.id, { [property]: Number(value) });
|
|
3482
|
+
} else if (property === "answer" && checkpoint.interaction !== "continue") {
|
|
3483
|
+
const answer = checkpoint.interaction === "number-input" ? Number(value) : String(value);
|
|
3484
|
+
updateCheckpoint(checkpoint.id, {
|
|
3485
|
+
predicate: { type: "equals", value: answer }
|
|
3486
|
+
});
|
|
3487
|
+
}
|
|
3488
|
+
} else if (key.startsWith("el.") && sel.kind === "element") {
|
|
3259
3489
|
const prop = key.slice(3);
|
|
3260
3490
|
const time = getCurrentTime();
|
|
3261
3491
|
const el = def.elements.find((e) => e.id === sel.elementId);
|
|
@@ -3276,6 +3506,16 @@ function apply(key, value) {
|
|
|
3276
3506
|
updateElementBase(sel.elementId, { translations });
|
|
3277
3507
|
return;
|
|
3278
3508
|
}
|
|
3509
|
+
if (prop.startsWith("reference.") && el.type === "text") {
|
|
3510
|
+
const token = prop.slice("reference.".length);
|
|
3511
|
+
const annotated = el;
|
|
3512
|
+
const references = { ...annotated.references ?? {} };
|
|
3513
|
+
const targets = parseReferenceTargets(String(value));
|
|
3514
|
+
if (targets) references[token] = targets;
|
|
3515
|
+
else delete references[token];
|
|
3516
|
+
updateElementBase(sel.elementId, { references });
|
|
3517
|
+
return;
|
|
3518
|
+
}
|
|
3279
3519
|
if (prop === "polygonSides" && el.type === "polygon") {
|
|
3280
3520
|
const points = el.points.trim().split(/\s+/).map((point) => point.split(",").map(Number)).filter(([x, y]) => Number.isFinite(x) && Number.isFinite(y));
|
|
3281
3521
|
if (points.length < 3) return;
|
|
@@ -3300,6 +3540,18 @@ function apply(key, value) {
|
|
|
3300
3540
|
} else {
|
|
3301
3541
|
updateElementBase(sel.elementId, { [prop]: value });
|
|
3302
3542
|
}
|
|
3543
|
+
} else if (key.startsWith("binding.") && sel.kind === "element") {
|
|
3544
|
+
const [, indexText, property] = key.split(".");
|
|
3545
|
+
const el = def.elements.find((item) => item.id === sel.elementId);
|
|
3546
|
+
const binding = el?.bindings[Number(indexText)];
|
|
3547
|
+
if (!el || !binding || !property) return;
|
|
3548
|
+
const bindings = el.bindings.map(
|
|
3549
|
+
(item, index) => index === Number(indexText) ? {
|
|
3550
|
+
...item,
|
|
3551
|
+
[property]: property === "fallback" ? parseBindingFallback(String(value)) : String(value)
|
|
3552
|
+
} : item
|
|
3553
|
+
);
|
|
3554
|
+
updateElementBase(el.id, { bindings });
|
|
3303
3555
|
} else if (key.startsWith("ap.") && sel.kind === "element") {
|
|
3304
3556
|
const [, idxStr, prop] = key.split(".");
|
|
3305
3557
|
const idx = Number(idxStr);
|
|
@@ -3317,6 +3569,16 @@ function apply(key, value) {
|
|
|
3317
3569
|
updateChapter(sel.chapterId, { label: String(value) });
|
|
3318
3570
|
} else if (key === "chapter.subtitle" && sel.kind === "chapter") {
|
|
3319
3571
|
updateChapter(sel.chapterId, { subtitle: String(value) });
|
|
3572
|
+
} else if (key.startsWith("chapter.reference.") && sel.kind === "chapter") {
|
|
3573
|
+
const chapter = def.chapters.find(({ id }) => id === sel.chapterId);
|
|
3574
|
+
if (!chapter) return;
|
|
3575
|
+
const token = key.slice("chapter.reference.".length);
|
|
3576
|
+
const annotated = chapter;
|
|
3577
|
+
const references = { ...annotated.references ?? {} };
|
|
3578
|
+
const targets = parseReferenceTargets(String(value));
|
|
3579
|
+
if (targets) references[token] = targets;
|
|
3580
|
+
else delete references[token];
|
|
3581
|
+
updateChapter(sel.chapterId, { references });
|
|
3320
3582
|
} else if (key.startsWith("effect.") && sel.kind === "effect") {
|
|
3321
3583
|
const prop = key.slice(7);
|
|
3322
3584
|
const patch = {};
|
|
@@ -3328,11 +3590,44 @@ function apply(key, value) {
|
|
|
3328
3590
|
updateEffect(sel.effectId, patch);
|
|
3329
3591
|
}
|
|
3330
3592
|
}
|
|
3593
|
+
function parseBindingFallback(value) {
|
|
3594
|
+
if (value === "") return void 0;
|
|
3595
|
+
if (value === "true") return true;
|
|
3596
|
+
if (value === "false") return false;
|
|
3597
|
+
const number = Number(value);
|
|
3598
|
+
return Number.isFinite(number) && value.trim() !== "" ? number : value;
|
|
3599
|
+
}
|
|
3331
3600
|
function onClick2(e) {
|
|
3332
3601
|
const target = e.target;
|
|
3333
3602
|
const def = getDef();
|
|
3334
3603
|
if (!def) return;
|
|
3335
3604
|
const sel = getSelection();
|
|
3605
|
+
if (target.closest("[data-add-binding]") && sel.kind === "element") {
|
|
3606
|
+
const el = def.elements.find((item) => item.id === sel.elementId);
|
|
3607
|
+
if (!el) return;
|
|
3608
|
+
const property = bindablePropertiesFor(el).find(
|
|
3609
|
+
(candidate) => !el.bindings.some((binding) => binding.property === candidate)
|
|
3610
|
+
);
|
|
3611
|
+
if (property)
|
|
3612
|
+
updateElementBase(el.id, {
|
|
3613
|
+
bindings: [
|
|
3614
|
+
...el.bindings,
|
|
3615
|
+
{ property, pointer: "", formatter: "identity" }
|
|
3616
|
+
]
|
|
3617
|
+
});
|
|
3618
|
+
return;
|
|
3619
|
+
}
|
|
3620
|
+
const deleteBinding = target.closest("[data-delete-binding]");
|
|
3621
|
+
if (deleteBinding && sel.kind === "element") {
|
|
3622
|
+
const el = def.elements.find((item) => item.id === sel.elementId);
|
|
3623
|
+
if (el)
|
|
3624
|
+
updateElementBase(el.id, {
|
|
3625
|
+
bindings: el.bindings.filter(
|
|
3626
|
+
(_, index) => index !== Number(deleteBinding.dataset.deleteBinding)
|
|
3627
|
+
)
|
|
3628
|
+
});
|
|
3629
|
+
return;
|
|
3630
|
+
}
|
|
3336
3631
|
const alignBtn = target.closest("[data-align]");
|
|
3337
3632
|
if (alignBtn) {
|
|
3338
3633
|
alignSelected(alignBtn.dataset.align);
|
|
@@ -3343,6 +3638,37 @@ function onClick2(e) {
|
|
|
3343
3638
|
distributeSelected(distBtn.dataset.distribute);
|
|
3344
3639
|
return;
|
|
3345
3640
|
}
|
|
3641
|
+
const createLayoutButton = target.closest(
|
|
3642
|
+
"[data-create-layout]"
|
|
3643
|
+
);
|
|
3644
|
+
if (createLayoutButton && sel.kind === "elements") {
|
|
3645
|
+
createLayout(
|
|
3646
|
+
sel.elementIds,
|
|
3647
|
+
createLayoutButton.dataset.createLayout
|
|
3648
|
+
);
|
|
3649
|
+
return;
|
|
3650
|
+
}
|
|
3651
|
+
if (target.closest("[data-detach-layout]") && sel.kind === "elements") {
|
|
3652
|
+
detachFromLayout(sel.elementIds);
|
|
3653
|
+
return;
|
|
3654
|
+
}
|
|
3655
|
+
if (target.closest("[data-add-checkpoint]")) {
|
|
3656
|
+
addCheckpoint({
|
|
3657
|
+
id: uniqueCheckpointId(),
|
|
3658
|
+
time: getCurrentTime(),
|
|
3659
|
+
prompt: "\uACC4\uC18D \uC9C4\uD589\uD560\uAE4C\uC694?",
|
|
3660
|
+
required: true,
|
|
3661
|
+
interaction: "continue"
|
|
3662
|
+
});
|
|
3663
|
+
return;
|
|
3664
|
+
}
|
|
3665
|
+
const deleteCheckpointButton = target.closest(
|
|
3666
|
+
"[data-delete-checkpoint]"
|
|
3667
|
+
);
|
|
3668
|
+
if (deleteCheckpointButton?.dataset.deleteCheckpoint) {
|
|
3669
|
+
deleteCheckpoint(deleteCheckpointButton.dataset.deleteCheckpoint);
|
|
3670
|
+
return;
|
|
3671
|
+
}
|
|
3346
3672
|
if (target.closest("[data-ungroup]") && sel.kind === "element") {
|
|
3347
3673
|
ungroupElement(sel.elementId);
|
|
3348
3674
|
return;
|
|
@@ -3362,7 +3688,8 @@ function onClick2(e) {
|
|
|
3362
3688
|
id,
|
|
3363
3689
|
time: getCurrentTime(),
|
|
3364
3690
|
label: `Chapter ${id.split("-")[1]}`,
|
|
3365
|
-
subtitle: ""
|
|
3691
|
+
subtitle: "",
|
|
3692
|
+
references: {}
|
|
3366
3693
|
});
|
|
3367
3694
|
return;
|
|
3368
3695
|
}
|
|
@@ -3497,7 +3824,8 @@ function initTimeline(tracksRoot, addChapterBtn, elementTracks) {
|
|
|
3497
3824
|
id,
|
|
3498
3825
|
time: newTime,
|
|
3499
3826
|
label: `Chapter ${id.split("-")[1]}`,
|
|
3500
|
-
subtitle: ""
|
|
3827
|
+
subtitle: "",
|
|
3828
|
+
references: {}
|
|
3501
3829
|
});
|
|
3502
3830
|
setSelection({ kind: "chapter", chapterId: id });
|
|
3503
3831
|
});
|
|
@@ -15348,6 +15676,7 @@ var IconLibraryDialog = class _IconLibraryDialog {
|
|
|
15348
15676
|
rotation: 0,
|
|
15349
15677
|
appearances: [],
|
|
15350
15678
|
tracks: [],
|
|
15679
|
+
bindings: [],
|
|
15351
15680
|
x: cx - 32,
|
|
15352
15681
|
y: cy - 32,
|
|
15353
15682
|
width: 64,
|
|
@@ -15408,6 +15737,7 @@ async function uploadAndInsertImage(file, host) {
|
|
|
15408
15737
|
rotation: 0,
|
|
15409
15738
|
appearances: [],
|
|
15410
15739
|
tracks: [],
|
|
15740
|
+
bindings: [],
|
|
15411
15741
|
x: Math.round(cx - w / 2),
|
|
15412
15742
|
y: Math.round(cy - h / 2),
|
|
15413
15743
|
width: w,
|
|
@@ -15831,6 +16161,8 @@ var KIND_ICON = {
|
|
|
15831
16161
|
effect: "\u2728",
|
|
15832
16162
|
asset: "\u{1F5BC}",
|
|
15833
16163
|
group: "\u2B1A",
|
|
16164
|
+
layout: "\u25A6",
|
|
16165
|
+
checkpoint: "\u25C6",
|
|
15834
16166
|
other: "\xB7"
|
|
15835
16167
|
};
|
|
15836
16168
|
var dialogEl2 = null;
|
|
@@ -16766,7 +17098,8 @@ function initStudio(opts = {}) {
|
|
|
16766
17098
|
const ui = queryUi();
|
|
16767
17099
|
if (!ui) {
|
|
16768
17100
|
console.error("[studio] missing required elements");
|
|
16769
|
-
return
|
|
17101
|
+
return () => {
|
|
17102
|
+
};
|
|
16770
17103
|
}
|
|
16771
17104
|
document.body.classList.add("editor-active");
|
|
16772
17105
|
document.documentElement.classList.add("editor-active");
|
|
@@ -16856,6 +17189,18 @@ function initStudio(opts = {}) {
|
|
|
16856
17189
|
ui.newBtn.addEventListener("click", () => openNewDialog(ui));
|
|
16857
17190
|
initPalette();
|
|
16858
17191
|
initHistoryPanel();
|
|
17192
|
+
if (!getDef()) startDraft();
|
|
17193
|
+
const pluginMount = mountEditorPlugins(
|
|
17194
|
+
ui.app,
|
|
17195
|
+
opts.plugins ?? [],
|
|
17196
|
+
opts.resolvePluginPermissions ?? (() => ({})),
|
|
17197
|
+
{
|
|
17198
|
+
getDocument: getDef,
|
|
17199
|
+
replaceDocument: setDef,
|
|
17200
|
+
getSelection,
|
|
17201
|
+
setSelection
|
|
17202
|
+
}
|
|
17203
|
+
);
|
|
16859
17204
|
registerCommands([
|
|
16860
17205
|
{
|
|
16861
17206
|
id: "open",
|
|
@@ -16901,7 +17246,8 @@ function initStudio(opts = {}) {
|
|
|
16901
17246
|
hint: "G",
|
|
16902
17247
|
run: () => setGridEnabled(!isGridEnabled())
|
|
16903
17248
|
},
|
|
16904
|
-
{ id: "help", label: "\u2328 \uB2E8\uCD95\uD0A4 \uBCF4\uAE30", hint: "? / Shift+/", run: openHelp }
|
|
17249
|
+
{ id: "help", label: "\u2328 \uB2E8\uCD95\uD0A4 \uBCF4\uAE30", hint: "? / Shift+/", run: openHelp },
|
|
17250
|
+
...pluginMount.commands
|
|
16905
17251
|
]);
|
|
16906
17252
|
ui.saveBtn.addEventListener("click", () => void saveCurrent(ui));
|
|
16907
17253
|
ui.exportBtn.addEventListener("click", () => {
|
|
@@ -16915,7 +17261,9 @@ function initStudio(opts = {}) {
|
|
|
16915
17261
|
const file = ui.importFileInput.files?.[0];
|
|
16916
17262
|
ui.importFileInput.value = "";
|
|
16917
17263
|
if (!file) return;
|
|
16918
|
-
void file.text().then((text) =>
|
|
17264
|
+
void file.text().then((text) => JSON.parse(text)).then(
|
|
17265
|
+
(input) => opts.importDocument ? opts.importDocument(input) : animationDocumentSchema.parse(input)
|
|
17266
|
+
).then((def) => importAnimation(def)).then((def) => {
|
|
16919
17267
|
setDef(def);
|
|
16920
17268
|
markClean();
|
|
16921
17269
|
setStatus(ui, `${def.id}.json \uD30C\uC77C\uC744 \uAC00\uC838\uC654\uC2B5\uB2C8\uB2E4.`, "ok");
|
|
@@ -16978,12 +17326,12 @@ function initStudio(opts = {}) {
|
|
|
16978
17326
|
});
|
|
16979
17327
|
if (opts.initialId) {
|
|
16980
17328
|
void loadAnimation2(ui, opts.initialId);
|
|
16981
|
-
} else if (
|
|
16982
|
-
startDraft();
|
|
17329
|
+
} else if (isDraft()) {
|
|
16983
17330
|
setStatus(ui, "\uC784\uC2DC \uC791\uC5C5 (Draft), \uC800\uC7A5 \uC2DC ID/\uC81C\uBAA9 \uC785\uB825", "ok");
|
|
16984
17331
|
} else {
|
|
16985
17332
|
setStatus(ui, "\uC900\uBE44\uB428", "ok");
|
|
16986
17333
|
}
|
|
17334
|
+
return () => pluginMount.dispose();
|
|
16987
17335
|
}
|
|
16988
17336
|
function reflectState(ui) {
|
|
16989
17337
|
ui.undoBtn.disabled = !canUndo();
|
|
@@ -17024,5 +17372,5 @@ function reflectState(ui) {
|
|
|
17024
17372
|
}
|
|
17025
17373
|
|
|
17026
17374
|
export { getVisibleElementIds, initStudio };
|
|
17027
|
-
//# sourceMappingURL=main-
|
|
17028
|
-
//# sourceMappingURL=main-
|
|
17375
|
+
//# sourceMappingURL=main-SKM3P4X7.js.map
|
|
17376
|
+
//# sourceMappingURL=main-SKM3P4X7.js.map
|