@kokoa/clotho-editor 0.1.4 → 0.3.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-N47HF4VB.js} +436 -20
- package/dist/chunk-N47HF4VB.js.map +1 -0
- package/dist/clotho-editor.css +425 -0
- package/dist/index.d.ts +199 -18
- package/dist/index.js +515 -9
- package/dist/index.js.map +1 -1
- package/dist/{main-NCPWDB2U.js → main-DC6D6RNQ.js} +937 -22
- package/dist/main-DC6D6RNQ.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
|
@@ -1096,6 +1096,227 @@ body.studio-player-popout #clotho-player-preview {
|
|
|
1096
1096
|
color: var(--color-accent);
|
|
1097
1097
|
background: linear-gradient(90deg, transparent, rgba(99, 102, 241, 0.15));
|
|
1098
1098
|
}
|
|
1099
|
+
/* Canvas overlay for the camera. Drawn into the editing SVG, which keeps the
|
|
1100
|
+
full-canvas viewBox, so the frame is the part a reader will actually see. */
|
|
1101
|
+
.studio-camera-frame-scrim {
|
|
1102
|
+
/* Fixed rather than themed: this dims the *document's* canvas, which keeps its
|
|
1103
|
+
own background whatever the editor chrome is doing. A themed value goes
|
|
1104
|
+
invisible exactly when the editor is dark and the canvas is white. */
|
|
1105
|
+
fill: rgba(15, 23, 42, 0.32);
|
|
1106
|
+
}
|
|
1107
|
+
.studio-camera-frame-rect {
|
|
1108
|
+
fill: none;
|
|
1109
|
+
stroke: #7c3aed;
|
|
1110
|
+
stroke-width: 2;
|
|
1111
|
+
stroke-dasharray: 6 4;
|
|
1112
|
+
}
|
|
1113
|
+
.studio-camera-frame.is-selected .studio-camera-frame-rect {
|
|
1114
|
+
stroke-dasharray: none;
|
|
1115
|
+
stroke-width: 2.5;
|
|
1116
|
+
}
|
|
1117
|
+
.studio-camera-frame-rect[data-camera-frame] {
|
|
1118
|
+
cursor: pointer;
|
|
1119
|
+
}
|
|
1120
|
+
/* Transparent, but it takes the pan drag — so it needs a fill to be hit. */
|
|
1121
|
+
.studio-camera-frame-body {
|
|
1122
|
+
fill: transparent;
|
|
1123
|
+
cursor: grab;
|
|
1124
|
+
}
|
|
1125
|
+
.studio-camera-frame-body:active {
|
|
1126
|
+
cursor: grabbing;
|
|
1127
|
+
}
|
|
1128
|
+
.studio-camera-frame-handle {
|
|
1129
|
+
fill: var(--color-surface-elevated, #fff);
|
|
1130
|
+
stroke: #7c3aed;
|
|
1131
|
+
stroke-width: 1.5;
|
|
1132
|
+
cursor: nwse-resize;
|
|
1133
|
+
}
|
|
1134
|
+
.studio-camera-frame-handle:hover {
|
|
1135
|
+
fill: #7c3aed;
|
|
1136
|
+
}
|
|
1137
|
+
.studio-camera-frame-label {
|
|
1138
|
+
fill: #7c3aed;
|
|
1139
|
+
font-family: var(--font-mono);
|
|
1140
|
+
font-size: 12px;
|
|
1141
|
+
}
|
|
1142
|
+
.studio-camera-frame-warning {
|
|
1143
|
+
fill: #ef4444;
|
|
1144
|
+
font-family: var(--font-mono);
|
|
1145
|
+
font-size: 11px;
|
|
1146
|
+
}
|
|
1147
|
+
.studio-camera-readout {
|
|
1148
|
+
padding: 0.4rem 0.55rem;
|
|
1149
|
+
margin-bottom: 0.4rem;
|
|
1150
|
+
border-radius: 6px;
|
|
1151
|
+
background-color: var(--color-surface);
|
|
1152
|
+
font-family: var(--font-mono);
|
|
1153
|
+
font-size: 0.7rem;
|
|
1154
|
+
color: var(--color-fg-muted);
|
|
1155
|
+
}
|
|
1156
|
+
.studio-camera-issue {
|
|
1157
|
+
color: #ef4444;
|
|
1158
|
+
}
|
|
1159
|
+
.studio-camera-focus > summary {
|
|
1160
|
+
cursor: pointer;
|
|
1161
|
+
padding: 0.3rem 0;
|
|
1162
|
+
font-family: var(--font-mono);
|
|
1163
|
+
font-size: 0.7rem;
|
|
1164
|
+
}
|
|
1165
|
+
.studio-camera-track {
|
|
1166
|
+
padding: 0.3rem 0;
|
|
1167
|
+
border-top: 1px solid var(--color-border);
|
|
1168
|
+
}
|
|
1169
|
+
.studio-camera-track-head {
|
|
1170
|
+
display: flex;
|
|
1171
|
+
align-items: center;
|
|
1172
|
+
gap: 0.4rem;
|
|
1173
|
+
font-family: var(--font-mono);
|
|
1174
|
+
font-size: 0.72rem;
|
|
1175
|
+
}
|
|
1176
|
+
.studio-camera-track-now {
|
|
1177
|
+
margin-left: auto;
|
|
1178
|
+
color: var(--color-fg-muted);
|
|
1179
|
+
font-size: 0.68rem;
|
|
1180
|
+
}
|
|
1181
|
+
.studio-camera-track .studio-props-empty {
|
|
1182
|
+
margin: 0.2rem 0 0;
|
|
1183
|
+
padding: 0;
|
|
1184
|
+
text-align: left;
|
|
1185
|
+
font-size: 0.68rem;
|
|
1186
|
+
}
|
|
1187
|
+
.studio-camera-control {
|
|
1188
|
+
color: #7c3aed;
|
|
1189
|
+
}
|
|
1190
|
+
.studio-camera-field-label {
|
|
1191
|
+
margin: 0.5rem 0 0.25rem;
|
|
1192
|
+
font-size: 0.72rem;
|
|
1193
|
+
color: var(--color-fg-muted);
|
|
1194
|
+
}
|
|
1195
|
+
.studio-camera-range {
|
|
1196
|
+
margin: 0.45rem 0;
|
|
1197
|
+
}
|
|
1198
|
+
.studio-camera-range-head {
|
|
1199
|
+
display: flex;
|
|
1200
|
+
justify-content: space-between;
|
|
1201
|
+
align-items: baseline;
|
|
1202
|
+
font-size: 0.72rem;
|
|
1203
|
+
color: var(--color-fg-muted);
|
|
1204
|
+
}
|
|
1205
|
+
.studio-camera-range-value {
|
|
1206
|
+
font-family: var(--font-mono);
|
|
1207
|
+
color: var(--color-fg);
|
|
1208
|
+
}
|
|
1209
|
+
.studio-camera-range-row {
|
|
1210
|
+
display: flex;
|
|
1211
|
+
align-items: center;
|
|
1212
|
+
gap: 0.4rem;
|
|
1213
|
+
}
|
|
1214
|
+
.studio-camera-range-row input[type="range"] {
|
|
1215
|
+
flex: 1;
|
|
1216
|
+
min-width: 0;
|
|
1217
|
+
}
|
|
1218
|
+
.studio-camera-range-row input[type="number"] {
|
|
1219
|
+
width: 5.2rem;
|
|
1220
|
+
flex: 0 0 auto;
|
|
1221
|
+
}
|
|
1222
|
+
.studio-camera-hint {
|
|
1223
|
+
margin: 0.2rem 0 0;
|
|
1224
|
+
font-size: 0.66rem;
|
|
1225
|
+
color: var(--color-fg-muted);
|
|
1226
|
+
}
|
|
1227
|
+
.studio-camera-chips {
|
|
1228
|
+
display: flex;
|
|
1229
|
+
flex-wrap: wrap;
|
|
1230
|
+
gap: 0.25rem;
|
|
1231
|
+
margin: 0.25rem 0;
|
|
1232
|
+
}
|
|
1233
|
+
.studio-chip {
|
|
1234
|
+
padding: 0.1rem 0.45rem;
|
|
1235
|
+
border: 1px solid var(--color-border);
|
|
1236
|
+
border-radius: 999px;
|
|
1237
|
+
background: none;
|
|
1238
|
+
color: var(--color-fg-muted);
|
|
1239
|
+
font: inherit;
|
|
1240
|
+
font-size: 0.68rem;
|
|
1241
|
+
cursor: pointer;
|
|
1242
|
+
}
|
|
1243
|
+
.studio-chip.is-on {
|
|
1244
|
+
border-color: #7c3aed;
|
|
1245
|
+
background-color: color-mix(in srgb, #7c3aed 18%, transparent);
|
|
1246
|
+
color: var(--color-fg);
|
|
1247
|
+
}
|
|
1248
|
+
.studio-camera-focus-actions {
|
|
1249
|
+
display: flex;
|
|
1250
|
+
flex-wrap: wrap;
|
|
1251
|
+
gap: 0.3rem;
|
|
1252
|
+
margin: 0.3rem 0;
|
|
1253
|
+
}
|
|
1254
|
+
/* The target list scrolls: a document with forty elements must not push the
|
|
1255
|
+
padding and maxZoom controls off the panel. */
|
|
1256
|
+
.studio-camera-targets {
|
|
1257
|
+
max-height: 11rem;
|
|
1258
|
+
overflow-y: auto;
|
|
1259
|
+
border: 1px solid var(--color-border);
|
|
1260
|
+
border-radius: 6px;
|
|
1261
|
+
padding: 0.2rem;
|
|
1262
|
+
}
|
|
1263
|
+
.studio-camera-target {
|
|
1264
|
+
display: flex;
|
|
1265
|
+
align-items: center;
|
|
1266
|
+
gap: 0.35rem;
|
|
1267
|
+
padding: 0.15rem 0.3rem;
|
|
1268
|
+
border-radius: 4px;
|
|
1269
|
+
font-size: 0.72rem;
|
|
1270
|
+
cursor: pointer;
|
|
1271
|
+
}
|
|
1272
|
+
.studio-camera-target:hover {
|
|
1273
|
+
background-color: color-mix(in srgb, var(--color-accent) 10%, transparent);
|
|
1274
|
+
}
|
|
1275
|
+
.studio-camera-target.is-on {
|
|
1276
|
+
background-color: color-mix(in srgb, #7c3aed 16%, transparent);
|
|
1277
|
+
}
|
|
1278
|
+
.studio-camera-target-name {
|
|
1279
|
+
flex: 1;
|
|
1280
|
+
overflow: hidden;
|
|
1281
|
+
text-overflow: ellipsis;
|
|
1282
|
+
white-space: nowrap;
|
|
1283
|
+
}
|
|
1284
|
+
.studio-camera-target-id,
|
|
1285
|
+
.studio-camera-target-type {
|
|
1286
|
+
font-family: var(--font-mono);
|
|
1287
|
+
font-size: 0.64rem;
|
|
1288
|
+
color: var(--color-fg-muted);
|
|
1289
|
+
}
|
|
1290
|
+
.studio-camera-kf-list {
|
|
1291
|
+
list-style: none;
|
|
1292
|
+
margin: 0.3rem 0 0;
|
|
1293
|
+
padding: 0;
|
|
1294
|
+
display: flex;
|
|
1295
|
+
flex-wrap: wrap;
|
|
1296
|
+
gap: 0.3rem;
|
|
1297
|
+
}
|
|
1298
|
+
.studio-camera-kf-list li {
|
|
1299
|
+
display: flex;
|
|
1300
|
+
align-items: center;
|
|
1301
|
+
gap: 0.25rem;
|
|
1302
|
+
padding: 0.1rem 0.3rem;
|
|
1303
|
+
border: 1px solid var(--color-border);
|
|
1304
|
+
border-radius: 999px;
|
|
1305
|
+
font-family: var(--font-mono);
|
|
1306
|
+
font-size: 0.68rem;
|
|
1307
|
+
}
|
|
1308
|
+
.studio-camera-kf,
|
|
1309
|
+
.studio-camera-kf-del {
|
|
1310
|
+
border: 0;
|
|
1311
|
+
background: none;
|
|
1312
|
+
color: inherit;
|
|
1313
|
+
font: inherit;
|
|
1314
|
+
cursor: pointer;
|
|
1315
|
+
padding: 0;
|
|
1316
|
+
}
|
|
1317
|
+
.studio-camera-kf-del {
|
|
1318
|
+
color: #ef4444;
|
|
1319
|
+
}
|
|
1099
1320
|
.studio-tl-total {
|
|
1100
1321
|
margin-top: 0.3rem;
|
|
1101
1322
|
padding: 0.2rem 0.4rem;
|
|
@@ -1885,6 +2106,81 @@ body.studio-player-popout #clotho-player-preview {
|
|
|
1885
2106
|
color: #fff;
|
|
1886
2107
|
border-color: #b91c1c;
|
|
1887
2108
|
}
|
|
2109
|
+
/* Camera rows: the same shape as an element row, tinted so a document-level
|
|
2110
|
+
track is not mistaken for one belonging to whatever element is above it. */
|
|
2111
|
+
.studio-tl-camera-row {
|
|
2112
|
+
border-bottom: 1px solid var(--color-border);
|
|
2113
|
+
min-height: 30px;
|
|
2114
|
+
}
|
|
2115
|
+
.studio-tl-camera-row.is-selected .studio-tl-gutter,
|
|
2116
|
+
.studio-tl-camera-row.is-selected .studio-tl-body {
|
|
2117
|
+
background-color: color-mix(
|
|
2118
|
+
in srgb,
|
|
2119
|
+
var(--color-accent) 10%,
|
|
2120
|
+
var(--color-surface-elevated)
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
.studio-tl-camera-gutter {
|
|
2124
|
+
gap: 0.35rem;
|
|
2125
|
+
color: #7c3aed;
|
|
2126
|
+
font-weight: 700;
|
|
2127
|
+
cursor: pointer;
|
|
2128
|
+
}
|
|
2129
|
+
.studio-tl-camera-gutter.is-sub {
|
|
2130
|
+
color: var(--color-fg-muted);
|
|
2131
|
+
font-weight: 400;
|
|
2132
|
+
padding-left: 1.4rem;
|
|
2133
|
+
}
|
|
2134
|
+
.studio-tl-camera-add {
|
|
2135
|
+
margin-left: auto;
|
|
2136
|
+
border: 1px solid var(--color-border);
|
|
2137
|
+
border-radius: 4px;
|
|
2138
|
+
background: none;
|
|
2139
|
+
color: inherit;
|
|
2140
|
+
font: inherit;
|
|
2141
|
+
line-height: 1;
|
|
2142
|
+
padding: 0 0.3rem;
|
|
2143
|
+
cursor: pointer;
|
|
2144
|
+
}
|
|
2145
|
+
.studio-tl-camera-track {
|
|
2146
|
+
position: relative;
|
|
2147
|
+
height: 100%;
|
|
2148
|
+
min-height: 30px;
|
|
2149
|
+
}
|
|
2150
|
+
.studio-tl-camera-empty {
|
|
2151
|
+
position: absolute;
|
|
2152
|
+
left: 0.5rem;
|
|
2153
|
+
top: 50%;
|
|
2154
|
+
transform: translateY(-50%);
|
|
2155
|
+
font-size: 0.68rem;
|
|
2156
|
+
color: var(--color-fg-muted);
|
|
2157
|
+
}
|
|
2158
|
+
.studio-tl-camera-focus {
|
|
2159
|
+
position: absolute;
|
|
2160
|
+
top: 5px;
|
|
2161
|
+
bottom: 5px;
|
|
2162
|
+
border-radius: 4px;
|
|
2163
|
+
border: 1px solid #7c3aed;
|
|
2164
|
+
background-color: color-mix(in srgb, #7c3aed 22%, transparent);
|
|
2165
|
+
cursor: grab;
|
|
2166
|
+
overflow: hidden;
|
|
2167
|
+
display: flex;
|
|
2168
|
+
align-items: center;
|
|
2169
|
+
}
|
|
2170
|
+
.studio-tl-camera-focus.is-selected {
|
|
2171
|
+
border-color: #ef4444;
|
|
2172
|
+
background-color: color-mix(in srgb, #ef4444 26%, transparent);
|
|
2173
|
+
}
|
|
2174
|
+
.studio-tl-camera-focus-label {
|
|
2175
|
+
padding: 0 0.35rem;
|
|
2176
|
+
font-size: 0.66rem;
|
|
2177
|
+
font-family: var(--font-mono);
|
|
2178
|
+
white-space: nowrap;
|
|
2179
|
+
pointer-events: none;
|
|
2180
|
+
}
|
|
2181
|
+
.studio-tl-camera-keyframe {
|
|
2182
|
+
color: #7c3aed;
|
|
2183
|
+
}
|
|
1888
2184
|
.studio-tl-playhead {
|
|
1889
2185
|
position: absolute;
|
|
1890
2186
|
top: 0;
|
|
@@ -2051,3 +2347,132 @@ body.studio-player-popout #clotho-player-preview {
|
|
|
2051
2347
|
margin-top: 0.4rem;
|
|
2052
2348
|
}
|
|
2053
2349
|
}
|
|
2350
|
+
|
|
2351
|
+
.studio-plugin-toolbar {
|
|
2352
|
+
display: contents;
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2355
|
+
.studio-plugin-panels,
|
|
2356
|
+
.studio-plugin-inspectors {
|
|
2357
|
+
display: grid;
|
|
2358
|
+
gap: 0.55rem;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
.studio-plugin-panels > section,
|
|
2362
|
+
.studio-plugin-inspectors > section {
|
|
2363
|
+
padding: 0.65rem;
|
|
2364
|
+
border: 1px solid var(--color-border);
|
|
2365
|
+
border-radius: 0.55rem;
|
|
2366
|
+
background: var(--color-surface);
|
|
2367
|
+
}
|
|
2368
|
+
|
|
2369
|
+
.studio-template-panel {
|
|
2370
|
+
display: grid;
|
|
2371
|
+
gap: 0.55rem;
|
|
2372
|
+
}
|
|
2373
|
+
|
|
2374
|
+
.studio-template-select {
|
|
2375
|
+
width: 100%;
|
|
2376
|
+
padding: 0.35rem 0.45rem;
|
|
2377
|
+
border: 1px solid var(--color-border);
|
|
2378
|
+
border-radius: 0.3rem;
|
|
2379
|
+
background: var(--color-surface);
|
|
2380
|
+
color: var(--color-fg);
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
.studio-template-status[data-error="true"] {
|
|
2384
|
+
color: var(--color-danger);
|
|
2385
|
+
}
|
|
2386
|
+
|
|
2387
|
+
.studio-checkpoint-card {
|
|
2388
|
+
margin-bottom: 0.7rem;
|
|
2389
|
+
padding: 0.65rem;
|
|
2390
|
+
border: 1px solid var(--color-border);
|
|
2391
|
+
border-radius: 0.5rem;
|
|
2392
|
+
background: var(--color-surface-raised, var(--color-surface));
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
.studio-responsive-grid {
|
|
2396
|
+
display: grid;
|
|
2397
|
+
gap: 0.6rem;
|
|
2398
|
+
margin-top: 0.65rem;
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2401
|
+
.studio-responsive-grid figure {
|
|
2402
|
+
margin: 0;
|
|
2403
|
+
padding: 0.4rem;
|
|
2404
|
+
border: 1px solid var(--color-border);
|
|
2405
|
+
border-radius: 0.45rem;
|
|
2406
|
+
overflow: hidden;
|
|
2407
|
+
background: var(--color-canvas);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
.studio-responsive-grid figcaption {
|
|
2411
|
+
margin-bottom: 0.35rem;
|
|
2412
|
+
color: var(--color-fg-muted);
|
|
2413
|
+
font-size: 0.7rem;
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
.studio-responsive-grid svg {
|
|
2417
|
+
display: block;
|
|
2418
|
+
width: 100%;
|
|
2419
|
+
height: auto;
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
.studio-profile {
|
|
2423
|
+
display: grid;
|
|
2424
|
+
gap: 0.35rem;
|
|
2425
|
+
margin: 0.55rem 0;
|
|
2426
|
+
}
|
|
2427
|
+
.studio-profile > div {
|
|
2428
|
+
display: flex;
|
|
2429
|
+
justify-content: space-between;
|
|
2430
|
+
gap: 0.75rem;
|
|
2431
|
+
}
|
|
2432
|
+
.studio-profile dt {
|
|
2433
|
+
color: var(--color-fg-muted);
|
|
2434
|
+
}
|
|
2435
|
+
.studio-profile dd {
|
|
2436
|
+
margin: 0;
|
|
2437
|
+
font-family: var(--font-mono);
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
.studio-lint-list {
|
|
2441
|
+
display: grid;
|
|
2442
|
+
gap: 0.35rem;
|
|
2443
|
+
padding: 0;
|
|
2444
|
+
list-style: none;
|
|
2445
|
+
}
|
|
2446
|
+
.studio-lint-list button {
|
|
2447
|
+
width: 100%;
|
|
2448
|
+
display: grid;
|
|
2449
|
+
gap: 0.2rem;
|
|
2450
|
+
padding: 0.45rem;
|
|
2451
|
+
border: 1px solid var(--color-border);
|
|
2452
|
+
border-radius: 0.4rem;
|
|
2453
|
+
background: var(--color-surface);
|
|
2454
|
+
color: var(--color-fg);
|
|
2455
|
+
text-align: left;
|
|
2456
|
+
}
|
|
2457
|
+
.studio-lint-list span {
|
|
2458
|
+
color: var(--color-fg-muted);
|
|
2459
|
+
font-size: 0.72rem;
|
|
2460
|
+
}
|
|
2461
|
+
.studio-lint-list em {
|
|
2462
|
+
color: var(--color-accent);
|
|
2463
|
+
font-size: 0.68rem;
|
|
2464
|
+
font-style: normal;
|
|
2465
|
+
}
|
|
2466
|
+
.studio-lint-compare {
|
|
2467
|
+
display: grid;
|
|
2468
|
+
grid-template-columns: 1fr 1fr;
|
|
2469
|
+
gap: 0.4rem;
|
|
2470
|
+
}
|
|
2471
|
+
.studio-lint-compare figure {
|
|
2472
|
+
min-width: 0;
|
|
2473
|
+
margin: 0;
|
|
2474
|
+
}
|
|
2475
|
+
.studio-lint-compare svg {
|
|
2476
|
+
width: 100%;
|
|
2477
|
+
height: auto;
|
|
2478
|
+
}
|
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, CameraFocus, Camera, CameraProperty, 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";
|
|
@@ -60,8 +50,11 @@ type Selection = {
|
|
|
60
50
|
} | {
|
|
61
51
|
kind: "effect";
|
|
62
52
|
effectId: string;
|
|
53
|
+
} | {
|
|
54
|
+
kind: "camera";
|
|
55
|
+
focusIndex?: number;
|
|
63
56
|
};
|
|
64
|
-
type HistoryKind = "meta" | "canvas" | "settings" | "add" | "delete" | "move" | "style" | "rotate" | "resize" | "reorder" | "track" | "appearance" | "chapter" | "effect" | "group" | "asset" | "other";
|
|
57
|
+
type HistoryKind = "meta" | "canvas" | "settings" | "add" | "delete" | "move" | "style" | "rotate" | "resize" | "reorder" | "track" | "appearance" | "chapter" | "effect" | "camera" | "group" | "layout" | "checkpoint" | "asset" | "other";
|
|
65
58
|
interface HistoryEntry {
|
|
66
59
|
snap: string;
|
|
67
60
|
label: string;
|
|
@@ -124,9 +117,58 @@ declare function updateEffect(id: string, patch: Partial<AnimationEffect>): void
|
|
|
124
117
|
declare function deleteEffect(id: string): void;
|
|
125
118
|
declare function updateDuration(ms: number): void;
|
|
126
119
|
|
|
120
|
+
declare function getCamera(): Camera;
|
|
121
|
+
/** Whether the document actually carries a camera, as opposed to defaults. */
|
|
122
|
+
declare function hasCamera(): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Which mechanism decides the view at `time`.
|
|
125
|
+
*
|
|
126
|
+
* The renderer's rule is that a focus entry that has already started wins, and the
|
|
127
|
+
* tracks supply the value otherwise. Direct manipulation on the canvas has to know
|
|
128
|
+
* which one it is editing — dragging the frame when a focus is in control would
|
|
129
|
+
* write track keyframes that the focus immediately overrides, and a control that
|
|
130
|
+
* silently does nothing is worse than one that is disabled.
|
|
131
|
+
*/
|
|
132
|
+
type CameraControl = {
|
|
133
|
+
kind: "none";
|
|
134
|
+
} | {
|
|
135
|
+
kind: "tracks";
|
|
136
|
+
} | {
|
|
137
|
+
kind: "focus";
|
|
138
|
+
index: number;
|
|
139
|
+
};
|
|
140
|
+
declare function cameraControlAt(time: number): CameraControl;
|
|
141
|
+
declare function setCameraStrokeScaling(value: Camera["strokeScaling"]): void;
|
|
142
|
+
/** Add or replace the keyframe at `time` on one camera property. */
|
|
143
|
+
declare function setCameraKeyframe(property: CameraProperty, time: number, value: number, ease?: CameraKeyframeEase): void;
|
|
144
|
+
type CameraKeyframeEase = NonNullable<Camera["tracks"][number]["keyframes"][number]["ease"]>;
|
|
145
|
+
/**
|
|
146
|
+
* Move a keyframe in time, keeping its value.
|
|
147
|
+
*
|
|
148
|
+
* Separate from `setCameraKeyframe` because a timeline drag has to remove the old
|
|
149
|
+
* time as well; doing it as remove-then-set would push two history entries for one
|
|
150
|
+
* gesture.
|
|
151
|
+
*/
|
|
152
|
+
declare function moveCameraKeyframe(property: CameraProperty, from: number, to: number): void;
|
|
153
|
+
declare function removeCameraKeyframe(property: CameraProperty, time: number): void;
|
|
154
|
+
declare function removeCameraTrack(property: CameraProperty): void;
|
|
155
|
+
declare function addCameraFocus(focus: CameraFocus): void;
|
|
156
|
+
/**
|
|
157
|
+
* Patch one focus entry.
|
|
158
|
+
*
|
|
159
|
+
* Sorting can move it, so the selection is re-pointed at the same entry rather than
|
|
160
|
+
* at whatever ends up at the old index.
|
|
161
|
+
*/
|
|
162
|
+
declare function updateCameraFocus(index: number, patch: Partial<CameraFocus>): void;
|
|
163
|
+
declare function deleteCameraFocus(index: number): void;
|
|
164
|
+
/** Remove the camera entirely, so the document renders as it did without one. */
|
|
165
|
+
declare function clearCamera(): void;
|
|
166
|
+
|
|
127
167
|
declare function updateMeta(patch: Partial<Pick<AnimationDocument, "title" | "description">>): void;
|
|
128
168
|
/** Update the locales offered to localized text elements in this document. */
|
|
129
169
|
declare function updateLocales(locales: string[]): void;
|
|
170
|
+
declare function updateData(data: Record<string, DataValue>): void;
|
|
171
|
+
declare function updateResponsive(responsive: NonNullable<AnimationDocument["responsive"]>): void;
|
|
130
172
|
declare function updateCanvas(patch: Partial<AnimationDocument["canvas"]>): void;
|
|
131
173
|
declare function updateSettings(patch: Partial<AnimationDocument["settings"]>): void;
|
|
132
174
|
declare function uniqueElementId(type: string): string;
|
|
@@ -152,6 +194,107 @@ declare function registerInlineAsset(bytes: Uint8Array, mime: string): string;
|
|
|
152
194
|
*/
|
|
153
195
|
declare function registerDataUriAsset(dataUri: string): string;
|
|
154
196
|
|
|
197
|
+
interface LayoutCollision {
|
|
198
|
+
readonly firstId: string;
|
|
199
|
+
readonly secondId: string;
|
|
200
|
+
}
|
|
201
|
+
declare function createLayout(elementIds: readonly string[], mode: LayoutMode): void;
|
|
202
|
+
declare function detachFromLayout(elementIds: readonly string[]): void;
|
|
203
|
+
declare function layoutIdsFor(elementIds: readonly string[]): string[];
|
|
204
|
+
declare function findLayoutCollisions(def: AnimationDocument): LayoutCollision[];
|
|
205
|
+
|
|
206
|
+
declare function addCheckpoint(checkpoint: Checkpoint): void;
|
|
207
|
+
declare function updateCheckpoint(id: string, patch: Partial<Checkpoint>): void;
|
|
208
|
+
declare function deleteCheckpoint(id: string): void;
|
|
209
|
+
declare function uniqueCheckpointId(): string;
|
|
210
|
+
|
|
211
|
+
type EditorPluginSlot = "toolbar" | "panel" | "inspector";
|
|
212
|
+
interface EditorPluginManifestLike {
|
|
213
|
+
id: string;
|
|
214
|
+
name: string;
|
|
215
|
+
capabilities: readonly string[];
|
|
216
|
+
editor?: {
|
|
217
|
+
toolbarItems?: readonly string[];
|
|
218
|
+
panels?: readonly string[];
|
|
219
|
+
inspectors?: readonly string[];
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
interface EditorPluginPermissions {
|
|
223
|
+
ui?: boolean;
|
|
224
|
+
documentRead?: boolean;
|
|
225
|
+
documentWrite?: boolean;
|
|
226
|
+
}
|
|
227
|
+
interface EditorPluginContext {
|
|
228
|
+
readonly pluginId: string;
|
|
229
|
+
getDocument(): AnimationDocument;
|
|
230
|
+
replaceDocument(document: AnimationDocument): void;
|
|
231
|
+
getSelection(): Selection;
|
|
232
|
+
setSelection(selection: Selection): void;
|
|
233
|
+
}
|
|
234
|
+
interface EditorPluginView {
|
|
235
|
+
id: string;
|
|
236
|
+
label: string;
|
|
237
|
+
mount(container: HTMLElement, context: EditorPluginContext): void | (() => void);
|
|
238
|
+
}
|
|
239
|
+
interface EditorPluginDefinition {
|
|
240
|
+
manifest: EditorPluginManifestLike;
|
|
241
|
+
toolbarItems?: Record<string, EditorPluginView>;
|
|
242
|
+
panels?: Record<string, EditorPluginView>;
|
|
243
|
+
inspectors?: Record<string, EditorPluginView>;
|
|
244
|
+
commands?: readonly PaletteCommand[];
|
|
245
|
+
}
|
|
246
|
+
type EditorPluginPermissionResolver = (plugin: EditorPluginManifestLike) => EditorPluginPermissions;
|
|
247
|
+
type DocumentImporter = (input: unknown) => AnimationDocument | Promise<AnimationDocument>;
|
|
248
|
+
interface EditorPluginHostState {
|
|
249
|
+
getDocument(): AnimationDocument | null;
|
|
250
|
+
replaceDocument(document: AnimationDocument): void;
|
|
251
|
+
getSelection(): Selection;
|
|
252
|
+
setSelection(selection: Selection): void;
|
|
253
|
+
}
|
|
254
|
+
interface EditorPluginMountResult {
|
|
255
|
+
commands: PaletteCommand[];
|
|
256
|
+
dispose(): void;
|
|
257
|
+
}
|
|
258
|
+
interface EditorPluginIssue {
|
|
259
|
+
pluginId: string;
|
|
260
|
+
message: string;
|
|
261
|
+
}
|
|
262
|
+
declare function validateEditorPlugin(plugin: EditorPluginDefinition): EditorPluginIssue[];
|
|
263
|
+
declare function createEditorPluginContext(pluginId: string, permissions: EditorPluginPermissions, state: EditorPluginHostState): EditorPluginContext;
|
|
264
|
+
declare function mountEditorPlugins(root: HTMLElement, plugins: readonly EditorPluginDefinition[], resolvePermissions: EditorPluginPermissionResolver, state: EditorPluginHostState): EditorPluginMountResult;
|
|
265
|
+
|
|
266
|
+
interface StoryEditorOptions {
|
|
267
|
+
manifest: StoryManifest;
|
|
268
|
+
onChange?(manifest: StoryManifest): void;
|
|
269
|
+
}
|
|
270
|
+
declare function replaceStoryNodeDocument(manifest: StoryManifest, nodeId: string, document: AnimationDocument): StoryManifest;
|
|
271
|
+
declare function appendStoryEdge(manifest: StoryManifest, edge: StoryEdge): StoryManifest;
|
|
272
|
+
declare function createStoryEditorPlugin(options: StoryEditorOptions): EditorPluginDefinition;
|
|
273
|
+
|
|
274
|
+
interface StudioMountProps {
|
|
275
|
+
initialId?: string;
|
|
276
|
+
repository?: AnimationRepository;
|
|
277
|
+
editorTitle?: string;
|
|
278
|
+
resolveImage?: ImageUploadResolver;
|
|
279
|
+
importDocument?: DocumentImporter;
|
|
280
|
+
plugins?: readonly EditorPluginDefinition[];
|
|
281
|
+
resolvePluginPermissions?: EditorPluginPermissionResolver;
|
|
282
|
+
/** Trusted build-time templates shown as a parameter panel. */
|
|
283
|
+
templates?: readonly AnimationTemplate[];
|
|
284
|
+
/** Optional multi-document Story Graph edited alongside the active node timeline. */
|
|
285
|
+
story?: StoryEditorOptions;
|
|
286
|
+
}
|
|
287
|
+
declare function StudioMount({ initialId, repository, editorTitle, resolveImage, importDocument, plugins, resolvePluginPermissions, templates, story, }: StudioMountProps): React.JSX.Element;
|
|
288
|
+
|
|
289
|
+
/** 검증된 애니메이션 문서를 읽기 쉬운 JSON으로 변환한다. */
|
|
290
|
+
declare function animationDocumentToJson(def: AnimationDocument): string;
|
|
291
|
+
/** 어떤 image 요소에서도 참조하지 않는 asset을 제거한 새 문서를 반환한다. */
|
|
292
|
+
declare function garbageCollectAnimationAssets(def: AnimationDocument): AnimationDocument;
|
|
293
|
+
/** 문서 ID를 운영체제에서 안전하게 사용할 수 있는 파일 이름으로 바꾼다. */
|
|
294
|
+
declare function animationDocumentFileName(def: AnimationDocument): string;
|
|
295
|
+
/** 현재 문서를 브라우저에서 JSON 파일로 내려받는다. */
|
|
296
|
+
declare function downloadAnimationJson(def: AnimationDocument): void;
|
|
297
|
+
|
|
155
298
|
declare function isGroup(el: AnimationElement): el is GroupElement;
|
|
156
299
|
/** Direct children of a group, in document order (which is also paint order). */
|
|
157
300
|
declare function childIdsOf(groupId: string): string[];
|
|
@@ -173,4 +316,42 @@ interface HostOptions {
|
|
|
173
316
|
declare function configureHost(options: HostOptions): void;
|
|
174
317
|
declare function placeholderImageUrl(): string;
|
|
175
318
|
|
|
176
|
-
|
|
319
|
+
declare function initialParameterValue(schema: ParameterSchema): unknown;
|
|
320
|
+
declare function parameterInputValue(schema: ParameterSchema, raw: string | boolean): unknown;
|
|
321
|
+
/** Built-in authoring panel for trusted templates registered by the host. */
|
|
322
|
+
declare function createTemplateEditorPlugin(templates: readonly AnimationTemplate[]): EditorPluginDefinition;
|
|
323
|
+
|
|
324
|
+
declare function createVisualRegressionPlugin(): EditorPluginDefinition;
|
|
325
|
+
|
|
326
|
+
declare const RESPONSIVE_VIEWPORTS: readonly [{
|
|
327
|
+
readonly id: "compact";
|
|
328
|
+
readonly label: "모바일";
|
|
329
|
+
readonly width: 375;
|
|
330
|
+
}, {
|
|
331
|
+
readonly id: "regular";
|
|
332
|
+
readonly label: "본문";
|
|
333
|
+
readonly width: 768;
|
|
334
|
+
}, {
|
|
335
|
+
readonly id: "wide";
|
|
336
|
+
readonly label: "넓은 화면";
|
|
337
|
+
readonly width: 1280;
|
|
338
|
+
}];
|
|
339
|
+
declare function addDefaultResponsiveVariants(document: AnimationDocument): AnimationDocument;
|
|
340
|
+
declare function createResponsiveInspectorPlugin(): EditorPluginDefinition;
|
|
341
|
+
|
|
342
|
+
interface SceneProfile {
|
|
343
|
+
elementCount: number;
|
|
344
|
+
trackCount: number;
|
|
345
|
+
keyframeCount: number;
|
|
346
|
+
sampleCount: number;
|
|
347
|
+
totalMs: number;
|
|
348
|
+
averageMs: number;
|
|
349
|
+
maxMs: number;
|
|
350
|
+
overBudget: boolean;
|
|
351
|
+
}
|
|
352
|
+
declare function profileAnimation(document: AnimationDocument, sampleCount?: number, frameBudgetMs?: number): SceneProfile;
|
|
353
|
+
declare function createPerformanceProfilerPlugin(): EditorPluginDefinition;
|
|
354
|
+
|
|
355
|
+
declare function createLinterPlugin(): EditorPluginDefinition;
|
|
356
|
+
|
|
357
|
+
export { type AnimationRepository, type AnimationSummary, type CameraControl, 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, addCameraFocus, addChapter, addCheckpoint, addDefaultResponsiveVariants, addEffect, addElement, animationDocumentFileName, animationDocumentToJson, apiBaseUrl, appendStoryEdge, beginTransient, cameraControlAt, canRedo, canUndo, childIdsOf, clearCamera, configureAnimationRepository, configureApi, configureHost, createEditorPluginContext, createLayout, createLinterPlugin, createLocalStorageRepository, createPerformanceProfilerPlugin, createResponsiveInspectorPlugin, createStoryEditorPlugin, createTemplateEditorPlugin, createVisualRegressionPlugin, deleteCameraFocus, deleteChapter, deleteCheckpoint, deleteEffect, deleteElement, detachFromLayout, downloadAnimationJson, endTransient, findLayoutCollisions, garbageCollectAnimationAssets, getCamera, getCurrentSnapshot, getCurrentTime, getDef, getHistory, getSelectedElementIds, getSelection, groupElements, hasCamera, initialParameterValue, isDirty, isDraft, isElementSelected, isGroup, jumpBack, jumpForward, layoutIdsFor, markClean, mountEditorPlugins, moveCameraKeyframe, moveElementToEnd, moveElementToFront, parameterInputValue, placeholderImageUrl, profileAnimation, promoteDraftToSaved, redo, registerDataUriAsset, registerExternalAsset, registerInlineAsset, removeAppearance, removeCameraKeyframe, removeCameraTrack, removeTrack, removeTrackKeyframe, reorderElement, replaceStoryNodeDocument, resetHistory, setCameraKeyframe, setCameraStrokeScaling, setCurrentTime, setDef, setDraft, setElementValueAtTime, setSelection, setTrackKeyframe, subscribe, toggleSelectionFor, undo, ungroupElement, uniqueChapterId, uniqueCheckpointId, uniqueEffectId, uniqueElementId, updateAppearance, updateCameraFocus, updateCanvas, updateChapter, updateCheckpoint, updateData, updateDuration, updateEffect, updateElementBase, updateLocales, updateMeta, updateResponsive, updateSettings, validateEditorPlugin };
|