@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
package/dist/clotho-editor.css
CHANGED
|
@@ -2051,3 +2051,132 @@ body.studio-player-popout #clotho-player-preview {
|
|
|
2051
2051
|
margin-top: 0.4rem;
|
|
2052
2052
|
}
|
|
2053
2053
|
}
|
|
2054
|
+
|
|
2055
|
+
.studio-plugin-toolbar {
|
|
2056
|
+
display: contents;
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
.studio-plugin-panels,
|
|
2060
|
+
.studio-plugin-inspectors {
|
|
2061
|
+
display: grid;
|
|
2062
|
+
gap: 0.55rem;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
.studio-plugin-panels > section,
|
|
2066
|
+
.studio-plugin-inspectors > section {
|
|
2067
|
+
padding: 0.65rem;
|
|
2068
|
+
border: 1px solid var(--color-border);
|
|
2069
|
+
border-radius: 0.55rem;
|
|
2070
|
+
background: var(--color-surface);
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
.studio-template-panel {
|
|
2074
|
+
display: grid;
|
|
2075
|
+
gap: 0.55rem;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
.studio-template-select {
|
|
2079
|
+
width: 100%;
|
|
2080
|
+
padding: 0.35rem 0.45rem;
|
|
2081
|
+
border: 1px solid var(--color-border);
|
|
2082
|
+
border-radius: 0.3rem;
|
|
2083
|
+
background: var(--color-surface);
|
|
2084
|
+
color: var(--color-fg);
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
.studio-template-status[data-error="true"] {
|
|
2088
|
+
color: var(--color-danger);
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
.studio-checkpoint-card {
|
|
2092
|
+
margin-bottom: 0.7rem;
|
|
2093
|
+
padding: 0.65rem;
|
|
2094
|
+
border: 1px solid var(--color-border);
|
|
2095
|
+
border-radius: 0.5rem;
|
|
2096
|
+
background: var(--color-surface-raised, var(--color-surface));
|
|
2097
|
+
}
|
|
2098
|
+
|
|
2099
|
+
.studio-responsive-grid {
|
|
2100
|
+
display: grid;
|
|
2101
|
+
gap: 0.6rem;
|
|
2102
|
+
margin-top: 0.65rem;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
.studio-responsive-grid figure {
|
|
2106
|
+
margin: 0;
|
|
2107
|
+
padding: 0.4rem;
|
|
2108
|
+
border: 1px solid var(--color-border);
|
|
2109
|
+
border-radius: 0.45rem;
|
|
2110
|
+
overflow: hidden;
|
|
2111
|
+
background: var(--color-canvas);
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
.studio-responsive-grid figcaption {
|
|
2115
|
+
margin-bottom: 0.35rem;
|
|
2116
|
+
color: var(--color-fg-muted);
|
|
2117
|
+
font-size: 0.7rem;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
.studio-responsive-grid svg {
|
|
2121
|
+
display: block;
|
|
2122
|
+
width: 100%;
|
|
2123
|
+
height: auto;
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
.studio-profile {
|
|
2127
|
+
display: grid;
|
|
2128
|
+
gap: 0.35rem;
|
|
2129
|
+
margin: 0.55rem 0;
|
|
2130
|
+
}
|
|
2131
|
+
.studio-profile > div {
|
|
2132
|
+
display: flex;
|
|
2133
|
+
justify-content: space-between;
|
|
2134
|
+
gap: 0.75rem;
|
|
2135
|
+
}
|
|
2136
|
+
.studio-profile dt {
|
|
2137
|
+
color: var(--color-fg-muted);
|
|
2138
|
+
}
|
|
2139
|
+
.studio-profile dd {
|
|
2140
|
+
margin: 0;
|
|
2141
|
+
font-family: var(--font-mono);
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
.studio-lint-list {
|
|
2145
|
+
display: grid;
|
|
2146
|
+
gap: 0.35rem;
|
|
2147
|
+
padding: 0;
|
|
2148
|
+
list-style: none;
|
|
2149
|
+
}
|
|
2150
|
+
.studio-lint-list button {
|
|
2151
|
+
width: 100%;
|
|
2152
|
+
display: grid;
|
|
2153
|
+
gap: 0.2rem;
|
|
2154
|
+
padding: 0.45rem;
|
|
2155
|
+
border: 1px solid var(--color-border);
|
|
2156
|
+
border-radius: 0.4rem;
|
|
2157
|
+
background: var(--color-surface);
|
|
2158
|
+
color: var(--color-fg);
|
|
2159
|
+
text-align: left;
|
|
2160
|
+
}
|
|
2161
|
+
.studio-lint-list span {
|
|
2162
|
+
color: var(--color-fg-muted);
|
|
2163
|
+
font-size: 0.72rem;
|
|
2164
|
+
}
|
|
2165
|
+
.studio-lint-list em {
|
|
2166
|
+
color: var(--color-accent);
|
|
2167
|
+
font-size: 0.68rem;
|
|
2168
|
+
font-style: normal;
|
|
2169
|
+
}
|
|
2170
|
+
.studio-lint-compare {
|
|
2171
|
+
display: grid;
|
|
2172
|
+
grid-template-columns: 1fr 1fr;
|
|
2173
|
+
gap: 0.4rem;
|
|
2174
|
+
}
|
|
2175
|
+
.studio-lint-compare figure {
|
|
2176
|
+
min-width: 0;
|
|
2177
|
+
margin: 0;
|
|
2178
|
+
}
|
|
2179
|
+
.studio-lint-compare svg {
|
|
2180
|
+
width: 100%;
|
|
2181
|
+
height: auto;
|
|
2182
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnimationDocument, SnapshotMap, Appearance, AnimationElement, TrackKeyframe, Chapter, AnimationEffect, GroupElement } from '@kokoa/clotho';
|
|
1
|
+
import { AnimationDocument, SnapshotMap, Appearance, AnimationElement, TrackKeyframe, Chapter, AnimationEffect, DataValue, LayoutMode, Checkpoint, StoryManifest, StoryEdge, AnimationTemplate, GroupElement, ParameterSchema } from '@kokoa/clotho';
|
|
2
2
|
|
|
3
3
|
interface StudioProps {
|
|
4
4
|
initial: AnimationDocument;
|
|
@@ -29,22 +29,12 @@ declare function createLocalStorageRepository(options?: LocalStorageRepositoryOp
|
|
|
29
29
|
|
|
30
30
|
type ImageUploadResolver = (file: File) => Promise<string> | string;
|
|
31
31
|
|
|
32
|
-
interface
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
interface PaletteCommand {
|
|
33
|
+
id: string;
|
|
34
|
+
label: string;
|
|
35
|
+
hint?: string;
|
|
36
|
+
run: () => void;
|
|
37
37
|
}
|
|
38
|
-
declare function StudioMount({ initialId, repository, editorTitle, resolveImage, }: StudioMountProps): React.JSX.Element;
|
|
39
|
-
|
|
40
|
-
/** 검증된 애니메이션 문서를 읽기 쉬운 JSON으로 변환한다. */
|
|
41
|
-
declare function animationDocumentToJson(def: AnimationDocument): string;
|
|
42
|
-
/** 어떤 image 요소에서도 참조하지 않는 asset을 제거한 새 문서를 반환한다. */
|
|
43
|
-
declare function garbageCollectAnimationAssets(def: AnimationDocument): AnimationDocument;
|
|
44
|
-
/** 문서 ID를 운영체제에서 안전하게 사용할 수 있는 파일 이름으로 바꾼다. */
|
|
45
|
-
declare function animationDocumentFileName(def: AnimationDocument): string;
|
|
46
|
-
/** 현재 문서를 브라우저에서 JSON 파일로 내려받는다. */
|
|
47
|
-
declare function downloadAnimationJson(def: AnimationDocument): void;
|
|
48
38
|
|
|
49
39
|
type Selection = {
|
|
50
40
|
kind: "none";
|
|
@@ -61,7 +51,7 @@ type Selection = {
|
|
|
61
51
|
kind: "effect";
|
|
62
52
|
effectId: string;
|
|
63
53
|
};
|
|
64
|
-
type HistoryKind = "meta" | "canvas" | "settings" | "add" | "delete" | "move" | "style" | "rotate" | "resize" | "reorder" | "track" | "appearance" | "chapter" | "effect" | "group" | "asset" | "other";
|
|
54
|
+
type HistoryKind = "meta" | "canvas" | "settings" | "add" | "delete" | "move" | "style" | "rotate" | "resize" | "reorder" | "track" | "appearance" | "chapter" | "effect" | "group" | "layout" | "checkpoint" | "asset" | "other";
|
|
65
55
|
interface HistoryEntry {
|
|
66
56
|
snap: string;
|
|
67
57
|
label: string;
|
|
@@ -127,6 +117,8 @@ declare function updateDuration(ms: number): void;
|
|
|
127
117
|
declare function updateMeta(patch: Partial<Pick<AnimationDocument, "title" | "description">>): void;
|
|
128
118
|
/** Update the locales offered to localized text elements in this document. */
|
|
129
119
|
declare function updateLocales(locales: string[]): void;
|
|
120
|
+
declare function updateData(data: Record<string, DataValue>): void;
|
|
121
|
+
declare function updateResponsive(responsive: NonNullable<AnimationDocument["responsive"]>): void;
|
|
130
122
|
declare function updateCanvas(patch: Partial<AnimationDocument["canvas"]>): void;
|
|
131
123
|
declare function updateSettings(patch: Partial<AnimationDocument["settings"]>): void;
|
|
132
124
|
declare function uniqueElementId(type: string): string;
|
|
@@ -152,6 +144,107 @@ declare function registerInlineAsset(bytes: Uint8Array, mime: string): string;
|
|
|
152
144
|
*/
|
|
153
145
|
declare function registerDataUriAsset(dataUri: string): string;
|
|
154
146
|
|
|
147
|
+
interface LayoutCollision {
|
|
148
|
+
readonly firstId: string;
|
|
149
|
+
readonly secondId: string;
|
|
150
|
+
}
|
|
151
|
+
declare function createLayout(elementIds: readonly string[], mode: LayoutMode): void;
|
|
152
|
+
declare function detachFromLayout(elementIds: readonly string[]): void;
|
|
153
|
+
declare function layoutIdsFor(elementIds: readonly string[]): string[];
|
|
154
|
+
declare function findLayoutCollisions(def: AnimationDocument): LayoutCollision[];
|
|
155
|
+
|
|
156
|
+
declare function addCheckpoint(checkpoint: Checkpoint): void;
|
|
157
|
+
declare function updateCheckpoint(id: string, patch: Partial<Checkpoint>): void;
|
|
158
|
+
declare function deleteCheckpoint(id: string): void;
|
|
159
|
+
declare function uniqueCheckpointId(): string;
|
|
160
|
+
|
|
161
|
+
type EditorPluginSlot = "toolbar" | "panel" | "inspector";
|
|
162
|
+
interface EditorPluginManifestLike {
|
|
163
|
+
id: string;
|
|
164
|
+
name: string;
|
|
165
|
+
capabilities: readonly string[];
|
|
166
|
+
editor?: {
|
|
167
|
+
toolbarItems?: readonly string[];
|
|
168
|
+
panels?: readonly string[];
|
|
169
|
+
inspectors?: readonly string[];
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
interface EditorPluginPermissions {
|
|
173
|
+
ui?: boolean;
|
|
174
|
+
documentRead?: boolean;
|
|
175
|
+
documentWrite?: boolean;
|
|
176
|
+
}
|
|
177
|
+
interface EditorPluginContext {
|
|
178
|
+
readonly pluginId: string;
|
|
179
|
+
getDocument(): AnimationDocument;
|
|
180
|
+
replaceDocument(document: AnimationDocument): void;
|
|
181
|
+
getSelection(): Selection;
|
|
182
|
+
setSelection(selection: Selection): void;
|
|
183
|
+
}
|
|
184
|
+
interface EditorPluginView {
|
|
185
|
+
id: string;
|
|
186
|
+
label: string;
|
|
187
|
+
mount(container: HTMLElement, context: EditorPluginContext): void | (() => void);
|
|
188
|
+
}
|
|
189
|
+
interface EditorPluginDefinition {
|
|
190
|
+
manifest: EditorPluginManifestLike;
|
|
191
|
+
toolbarItems?: Record<string, EditorPluginView>;
|
|
192
|
+
panels?: Record<string, EditorPluginView>;
|
|
193
|
+
inspectors?: Record<string, EditorPluginView>;
|
|
194
|
+
commands?: readonly PaletteCommand[];
|
|
195
|
+
}
|
|
196
|
+
type EditorPluginPermissionResolver = (plugin: EditorPluginManifestLike) => EditorPluginPermissions;
|
|
197
|
+
type DocumentImporter = (input: unknown) => AnimationDocument | Promise<AnimationDocument>;
|
|
198
|
+
interface EditorPluginHostState {
|
|
199
|
+
getDocument(): AnimationDocument | null;
|
|
200
|
+
replaceDocument(document: AnimationDocument): void;
|
|
201
|
+
getSelection(): Selection;
|
|
202
|
+
setSelection(selection: Selection): void;
|
|
203
|
+
}
|
|
204
|
+
interface EditorPluginMountResult {
|
|
205
|
+
commands: PaletteCommand[];
|
|
206
|
+
dispose(): void;
|
|
207
|
+
}
|
|
208
|
+
interface EditorPluginIssue {
|
|
209
|
+
pluginId: string;
|
|
210
|
+
message: string;
|
|
211
|
+
}
|
|
212
|
+
declare function validateEditorPlugin(plugin: EditorPluginDefinition): EditorPluginIssue[];
|
|
213
|
+
declare function createEditorPluginContext(pluginId: string, permissions: EditorPluginPermissions, state: EditorPluginHostState): EditorPluginContext;
|
|
214
|
+
declare function mountEditorPlugins(root: HTMLElement, plugins: readonly EditorPluginDefinition[], resolvePermissions: EditorPluginPermissionResolver, state: EditorPluginHostState): EditorPluginMountResult;
|
|
215
|
+
|
|
216
|
+
interface StoryEditorOptions {
|
|
217
|
+
manifest: StoryManifest;
|
|
218
|
+
onChange?(manifest: StoryManifest): void;
|
|
219
|
+
}
|
|
220
|
+
declare function replaceStoryNodeDocument(manifest: StoryManifest, nodeId: string, document: AnimationDocument): StoryManifest;
|
|
221
|
+
declare function appendStoryEdge(manifest: StoryManifest, edge: StoryEdge): StoryManifest;
|
|
222
|
+
declare function createStoryEditorPlugin(options: StoryEditorOptions): EditorPluginDefinition;
|
|
223
|
+
|
|
224
|
+
interface StudioMountProps {
|
|
225
|
+
initialId?: string;
|
|
226
|
+
repository?: AnimationRepository;
|
|
227
|
+
editorTitle?: string;
|
|
228
|
+
resolveImage?: ImageUploadResolver;
|
|
229
|
+
importDocument?: DocumentImporter;
|
|
230
|
+
plugins?: readonly EditorPluginDefinition[];
|
|
231
|
+
resolvePluginPermissions?: EditorPluginPermissionResolver;
|
|
232
|
+
/** Trusted build-time templates shown as a parameter panel. */
|
|
233
|
+
templates?: readonly AnimationTemplate[];
|
|
234
|
+
/** Optional multi-document Story Graph edited alongside the active node timeline. */
|
|
235
|
+
story?: StoryEditorOptions;
|
|
236
|
+
}
|
|
237
|
+
declare function StudioMount({ initialId, repository, editorTitle, resolveImage, importDocument, plugins, resolvePluginPermissions, templates, story, }: StudioMountProps): React.JSX.Element;
|
|
238
|
+
|
|
239
|
+
/** 검증된 애니메이션 문서를 읽기 쉬운 JSON으로 변환한다. */
|
|
240
|
+
declare function animationDocumentToJson(def: AnimationDocument): string;
|
|
241
|
+
/** 어떤 image 요소에서도 참조하지 않는 asset을 제거한 새 문서를 반환한다. */
|
|
242
|
+
declare function garbageCollectAnimationAssets(def: AnimationDocument): AnimationDocument;
|
|
243
|
+
/** 문서 ID를 운영체제에서 안전하게 사용할 수 있는 파일 이름으로 바꾼다. */
|
|
244
|
+
declare function animationDocumentFileName(def: AnimationDocument): string;
|
|
245
|
+
/** 현재 문서를 브라우저에서 JSON 파일로 내려받는다. */
|
|
246
|
+
declare function downloadAnimationJson(def: AnimationDocument): void;
|
|
247
|
+
|
|
155
248
|
declare function isGroup(el: AnimationElement): el is GroupElement;
|
|
156
249
|
/** Direct children of a group, in document order (which is also paint order). */
|
|
157
250
|
declare function childIdsOf(groupId: string): string[];
|
|
@@ -173,4 +266,42 @@ interface HostOptions {
|
|
|
173
266
|
declare function configureHost(options: HostOptions): void;
|
|
174
267
|
declare function placeholderImageUrl(): string;
|
|
175
268
|
|
|
176
|
-
|
|
269
|
+
declare function initialParameterValue(schema: ParameterSchema): unknown;
|
|
270
|
+
declare function parameterInputValue(schema: ParameterSchema, raw: string | boolean): unknown;
|
|
271
|
+
/** Built-in authoring panel for trusted templates registered by the host. */
|
|
272
|
+
declare function createTemplateEditorPlugin(templates: readonly AnimationTemplate[]): EditorPluginDefinition;
|
|
273
|
+
|
|
274
|
+
declare function createVisualRegressionPlugin(): EditorPluginDefinition;
|
|
275
|
+
|
|
276
|
+
declare const RESPONSIVE_VIEWPORTS: readonly [{
|
|
277
|
+
readonly id: "compact";
|
|
278
|
+
readonly label: "모바일";
|
|
279
|
+
readonly width: 375;
|
|
280
|
+
}, {
|
|
281
|
+
readonly id: "regular";
|
|
282
|
+
readonly label: "본문";
|
|
283
|
+
readonly width: 768;
|
|
284
|
+
}, {
|
|
285
|
+
readonly id: "wide";
|
|
286
|
+
readonly label: "넓은 화면";
|
|
287
|
+
readonly width: 1280;
|
|
288
|
+
}];
|
|
289
|
+
declare function addDefaultResponsiveVariants(document: AnimationDocument): AnimationDocument;
|
|
290
|
+
declare function createResponsiveInspectorPlugin(): EditorPluginDefinition;
|
|
291
|
+
|
|
292
|
+
interface SceneProfile {
|
|
293
|
+
elementCount: number;
|
|
294
|
+
trackCount: number;
|
|
295
|
+
keyframeCount: number;
|
|
296
|
+
sampleCount: number;
|
|
297
|
+
totalMs: number;
|
|
298
|
+
averageMs: number;
|
|
299
|
+
maxMs: number;
|
|
300
|
+
overBudget: boolean;
|
|
301
|
+
}
|
|
302
|
+
declare function profileAnimation(document: AnimationDocument, sampleCount?: number, frameBudgetMs?: number): SceneProfile;
|
|
303
|
+
declare function createPerformanceProfilerPlugin(): EditorPluginDefinition;
|
|
304
|
+
|
|
305
|
+
declare function createLinterPlugin(): EditorPluginDefinition;
|
|
306
|
+
|
|
307
|
+
export { type AnimationRepository, type AnimationSummary, type DocumentImporter, type EditorPluginContext, type EditorPluginDefinition, type EditorPluginHostState, type EditorPluginManifestLike, type EditorPluginMountResult, type EditorPluginPermissionResolver, type EditorPluginPermissions, type EditorPluginSlot, type EditorPluginView, type HistoryEntry, type HistoryKind, type HostOptions, type ImageUploadResolver, type LocalStorageRepositoryOptions, RESPONSIVE_VIEWPORTS, type SceneProfile, type Selection, type StoryEditorOptions, Studio, StudioMount, type StudioMountProps, type StudioProps, addAppearance, addChapter, addCheckpoint, addDefaultResponsiveVariants, addEffect, addElement, animationDocumentFileName, animationDocumentToJson, apiBaseUrl, appendStoryEdge, beginTransient, canRedo, canUndo, childIdsOf, configureAnimationRepository, configureApi, configureHost, createEditorPluginContext, createLayout, createLinterPlugin, createLocalStorageRepository, createPerformanceProfilerPlugin, createResponsiveInspectorPlugin, createStoryEditorPlugin, createTemplateEditorPlugin, createVisualRegressionPlugin, deleteChapter, deleteCheckpoint, deleteEffect, deleteElement, detachFromLayout, downloadAnimationJson, endTransient, findLayoutCollisions, garbageCollectAnimationAssets, getCurrentSnapshot, getCurrentTime, getDef, getHistory, getSelectedElementIds, getSelection, groupElements, initialParameterValue, isDirty, isDraft, isElementSelected, isGroup, jumpBack, jumpForward, layoutIdsFor, markClean, mountEditorPlugins, moveElementToEnd, moveElementToFront, parameterInputValue, placeholderImageUrl, profileAnimation, promoteDraftToSaved, redo, registerDataUriAsset, registerExternalAsset, registerInlineAsset, removeAppearance, removeTrack, removeTrackKeyframe, reorderElement, replaceStoryNodeDocument, resetHistory, setCurrentTime, setDef, setDraft, setElementValueAtTime, setSelection, setTrackKeyframe, subscribe, toggleSelectionFor, undo, ungroupElement, uniqueChapterId, uniqueCheckpointId, uniqueEffectId, uniqueElementId, updateAppearance, updateCanvas, updateChapter, updateCheckpoint, updateData, updateDuration, updateEffect, updateElementBase, updateLocales, updateMeta, updateResponsive, updateSettings, validateEditorPlugin };
|