@glissade/core 0.14.0 → 0.15.0-pre.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/clips.d.ts +1 -1
- package/dist/i18n.d.ts +55 -11
- package/dist/i18n.js +99 -16
- package/dist/index.d.ts +10 -8
- package/dist/index.js +4 -3
- package/dist/sidecar.js +1 -1
- package/dist/studioHost.d.ts +1 -1
- package/dist/targetRef.js +12 -1
- package/dist/track.d.ts +19 -1
- package/package.json +1 -1
package/dist/clips.d.ts
CHANGED
package/dist/i18n.d.ts
CHANGED
|
@@ -30,8 +30,13 @@ interface LocalizeOptions {
|
|
|
30
30
|
* Message ids ALREADY consumed outside the doc — the free-standing `t()` ids
|
|
31
31
|
* resolved at module-eval / createScene() time (`getConsumedMessageIds()`).
|
|
32
32
|
* `localize` folds these into the "matched keys" set so the orphaned-key check
|
|
33
|
-
* (FIX 5) doesn't flag a legitimate `t()` key as unmatched. Omit when there
|
|
34
|
-
* no ambient `t()` usage (then only node-id keys count as matched).
|
|
33
|
+
* (0.14 FIX 5) doesn't flag a legitimate `t()` key as unmatched. Omit when there
|
|
34
|
+
* is no ambient `t()` usage (then only node-id keys count as matched).
|
|
35
|
+
*
|
|
36
|
+
* 0.15 FIX 2: this set ALSO drives the key-collision guard — a table key that is
|
|
37
|
+
* BOTH a `t()` id (in here) AND a node-id with a string track is ambiguous (the
|
|
38
|
+
* two id-spaces would silently fight over the same key, with the node-track swap
|
|
39
|
+
* winning), so `localize` throws a `LocalizationError` rather than guess.
|
|
35
40
|
*/
|
|
36
41
|
consumedIds?: ReadonlySet<string> | undefined;
|
|
37
42
|
}
|
|
@@ -49,27 +54,66 @@ declare class LocalizationError extends Error {
|
|
|
49
54
|
* Pure: no playhead, no time, no filesystem. The base-locale table (or an empty
|
|
50
55
|
* table) leaves the doc structurally identical to the input.
|
|
51
56
|
*
|
|
52
|
-
*
|
|
57
|
+
* 0.14 FIX 5: a table key matching NO consumed id (neither a string-track
|
|
53
58
|
* node-id NOR a `t()` id passed via `opts.consumedIds`) is a stale/typo'd key that
|
|
54
59
|
* would silently never localize anything — so `localize` throws a `LocalizationError`
|
|
55
60
|
* naming every orphaned key (the inverse of `t()`'s hard-fail). A fully-matched
|
|
56
61
|
* table is silent.
|
|
62
|
+
*
|
|
63
|
+
* 0.15 FIX 1 (multi-cue collapse): broadcasting one table string across EVERY key
|
|
64
|
+
* of a string track freezes a single caption over a multi-cue track (>1 distinct
|
|
65
|
+
* keyed value). A multi-cue caption must be regenerated per-locale (locale-tagged
|
|
66
|
+
* narration), never collapsed — so a matched track with >1 distinct key value
|
|
67
|
+
* HARD-THROWS, naming the id. A single-value / single-key track localizes fine.
|
|
68
|
+
*
|
|
69
|
+
* 0.15 FIX 2 (key collision): a table key that is BOTH a node-id-with-a-string-
|
|
70
|
+
* track AND a `t()` id (`opts.consumedIds`) is ambiguous — the two id-spaces would
|
|
71
|
+
* silently fight over the same flat key. `localize` HARD-THROWS on any such key
|
|
72
|
+
* rather than let the node-track swap silently win. The flat `messages.<locale>.json`
|
|
73
|
+
* shape is UNCHANGED; this is a pure additive guard.
|
|
57
74
|
*/
|
|
58
75
|
declare function localize(doc: Timeline, table: MessageTable, opts: LocalizeOptions): Timeline;
|
|
59
76
|
/**
|
|
60
|
-
* Install the ambient message table consulted by `t()
|
|
61
|
-
* scene construction (the render entry injects it from
|
|
62
|
-
* `undefined` to clear it (the base-locale / no-flag path leaves
|
|
63
|
-
* Resets the consumed-id set (a fresh table = a fresh resolution pass).
|
|
77
|
+
* Install the ambient message table consulted by `t()` on the PROCESS-GLOBAL
|
|
78
|
+
* scope. Called ONCE before scene construction (the render entry injects it from
|
|
79
|
+
* `--locale`). Pass `undefined` to clear it (the base-locale / no-flag path leaves
|
|
80
|
+
* it unset). Resets the consumed-id set (a fresh table = a fresh resolution pass).
|
|
81
|
+
*
|
|
82
|
+
* 0.15 FIX 3: for CONCURRENT renders of different locales, prefer
|
|
83
|
+
* `runWithMessageTable` — this global setter races across interleaved flows.
|
|
64
84
|
*/
|
|
65
85
|
declare function setMessageTable(table: MessageTable | undefined): void;
|
|
86
|
+
/**
|
|
87
|
+
* Run `fn` with `table` installed as the ambient message table for the DURATION
|
|
88
|
+
* of `fn`'s async flow only — isolated from the process-global scope and from any
|
|
89
|
+
* other concurrent flow (0.15 FIX 3). `t()` inside `fn` (and anything it awaits)
|
|
90
|
+
* resolves against `table`; `t()` outside it is unaffected. Resolves to `fn`'s
|
|
91
|
+
* result. The render entry can scope the whole `loadSceneModule`→`localize` flow
|
|
92
|
+
* per locale with this so parallel embedders never cross-contaminate. The
|
|
93
|
+
* consumed-id set is collected per scope and is readable with
|
|
94
|
+
* `getConsumedMessageIds()` inside `fn`.
|
|
95
|
+
*
|
|
96
|
+
* Async because the AsyncLocalStorage class is loaded via a dynamic `node` import
|
|
97
|
+
* on first use (so this prepare/render-path module never statically pulls in
|
|
98
|
+
* `node:async_hooks`); the ALS context still spans `fn` and everything it awaits.
|
|
99
|
+
*/
|
|
100
|
+
declare function runWithMessageTable<T>(table: MessageTable | undefined, fn: () => T | Promise<T>): Promise<T>;
|
|
66
101
|
/** The currently installed ambient message table (undefined when none is set). */
|
|
67
102
|
declare function getMessageTable(): MessageTable | undefined;
|
|
103
|
+
/**
|
|
104
|
+
* Run `fn` while PRESERVING the process-global ambient scope across it (0.15 FIX 3).
|
|
105
|
+
* `fn` may freely call `setMessageTable` / `loadSceneModule` (which clobbers the
|
|
106
|
+
* global table) — the table + consumed-id set are snapshotted before and restored
|
|
107
|
+
* after, so a no-locale helper (the audio-mix gather) can't leave a leaked or
|
|
108
|
+
* cleared table visible to a concurrent locale's flow. Awaits/returns `fn`'s result.
|
|
109
|
+
*/
|
|
110
|
+
declare function preservingMessageTable<T>(fn: () => Promise<T>): Promise<T>;
|
|
68
111
|
/**
|
|
69
112
|
* The set of ids `t()` has resolved against the ambient table since the last
|
|
70
|
-
* `setMessageTable
|
|
71
|
-
*
|
|
72
|
-
*
|
|
113
|
+
* `setMessageTable` (or, inside a `runWithMessageTable` flow, since that scope
|
|
114
|
+
* began). The render entry passes this to `localize` so a key consumed by a
|
|
115
|
+
* free-standing `t()` (which `localize` can't see — it isn't a doc track) isn't
|
|
116
|
+
* reported as an orphaned table key (0.14 FIX 5).
|
|
73
117
|
*/
|
|
74
118
|
declare function getConsumedMessageIds(): ReadonlySet<string>;
|
|
75
119
|
/**
|
|
@@ -84,4 +128,4 @@ declare function getConsumedMessageIds(): ReadonlySet<string>;
|
|
|
84
128
|
*/
|
|
85
129
|
declare function t(id: string): string;
|
|
86
130
|
//#endregion
|
|
87
|
-
export { LocaleManifest, LocalizationError, LocalizeOptions, MessageTable, ParityError, getConsumedMessageIds, getMessageTable, localize, requireParity, setMessageTable, t };
|
|
131
|
+
export { LocaleManifest, LocalizationError, LocalizeOptions, MessageTable, ParityError, getConsumedMessageIds, getMessageTable, localize, preservingMessageTable, requireParity, runWithMessageTable, setMessageTable, t };
|
package/dist/i18n.js
CHANGED
|
@@ -17,6 +17,14 @@ var ParityError = class extends Error {
|
|
|
17
17
|
* (or zero) is trivially in parity.
|
|
18
18
|
*/
|
|
19
19
|
function requireParity(...manifests) {
|
|
20
|
+
for (const m of manifests) if (new Set(m.ids).size !== m.ids.length) {
|
|
21
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22
|
+
const dups = [];
|
|
23
|
+
for (const id of m.ids) if (seen.has(id)) dups.push(id);
|
|
24
|
+
else seen.add(id);
|
|
25
|
+
const uniqueDups = [...new Set(dups)].sort();
|
|
26
|
+
throw new ParityError(`locale '${m.locale}' declares duplicate id(s): ${uniqueDups.map((id) => `'${id}'`).join(", ")} — each message id must appear once per manifest.`);
|
|
27
|
+
}
|
|
20
28
|
if (manifests.length < 2) return;
|
|
21
29
|
const union = /* @__PURE__ */ new Set();
|
|
22
30
|
for (const m of manifests) for (const id of m.ids) union.add(id);
|
|
@@ -56,11 +64,23 @@ function nodeIdOf(target) {
|
|
|
56
64
|
* Pure: no playhead, no time, no filesystem. The base-locale table (or an empty
|
|
57
65
|
* table) leaves the doc structurally identical to the input.
|
|
58
66
|
*
|
|
59
|
-
*
|
|
67
|
+
* 0.14 FIX 5: a table key matching NO consumed id (neither a string-track
|
|
60
68
|
* node-id NOR a `t()` id passed via `opts.consumedIds`) is a stale/typo'd key that
|
|
61
69
|
* would silently never localize anything — so `localize` throws a `LocalizationError`
|
|
62
70
|
* naming every orphaned key (the inverse of `t()`'s hard-fail). A fully-matched
|
|
63
71
|
* table is silent.
|
|
72
|
+
*
|
|
73
|
+
* 0.15 FIX 1 (multi-cue collapse): broadcasting one table string across EVERY key
|
|
74
|
+
* of a string track freezes a single caption over a multi-cue track (>1 distinct
|
|
75
|
+
* keyed value). A multi-cue caption must be regenerated per-locale (locale-tagged
|
|
76
|
+
* narration), never collapsed — so a matched track with >1 distinct key value
|
|
77
|
+
* HARD-THROWS, naming the id. A single-value / single-key track localizes fine.
|
|
78
|
+
*
|
|
79
|
+
* 0.15 FIX 2 (key collision): a table key that is BOTH a node-id-with-a-string-
|
|
80
|
+
* track AND a `t()` id (`opts.consumedIds`) is ambiguous — the two id-spaces would
|
|
81
|
+
* silently fight over the same flat key. `localize` HARD-THROWS on any such key
|
|
82
|
+
* rather than let the node-track swap silently win. The flat `messages.<locale>.json`
|
|
83
|
+
* shape is UNCHANGED; this is a pure additive guard.
|
|
64
84
|
*/
|
|
65
85
|
function localize(doc, table, opts) {
|
|
66
86
|
let changed = false;
|
|
@@ -69,6 +89,9 @@ function localize(doc, table, opts) {
|
|
|
69
89
|
if (tr.type !== "string") return tr;
|
|
70
90
|
const id = nodeIdOf(tr.target);
|
|
71
91
|
if (!(id in table)) return tr;
|
|
92
|
+
if (opts.consumedIds?.has(id)) throw new LocalizationError(`message table for locale '${opts.locale}' has an AMBIGUOUS key '${id}' — it matches BOTH a string track on node '${id}' AND a free-standing t('${id}') id. The flat table can't serve both id-spaces from one key. Rename one of them so the key resolves a single target.`);
|
|
93
|
+
const distinctValues = new Set(tr.keys.map((k) => k.value));
|
|
94
|
+
if (distinctValues.size > 1) throw new LocalizationError(`message table for locale '${opts.locale}' targets node '${id}', whose string track has ${distinctValues.size} distinct keyed values (a multi-cue caption). Broadcasting one table string would freeze a single caption over the whole track. Regenerate this locale's narration (a locale-tagged '<base>.${opts.locale}.narration.timing.json') instead of localizing the multi-cue track via the message table.`);
|
|
72
95
|
consumed.add(id);
|
|
73
96
|
const localized = table[id];
|
|
74
97
|
changed = true;
|
|
@@ -88,30 +111,88 @@ function localize(doc, table, opts) {
|
|
|
88
111
|
tracks
|
|
89
112
|
};
|
|
90
113
|
}
|
|
91
|
-
|
|
92
|
-
|
|
114
|
+
const globalScope = {
|
|
115
|
+
table: void 0,
|
|
116
|
+
consumedIds: /* @__PURE__ */ new Set()
|
|
117
|
+
};
|
|
118
|
+
let ambientStore;
|
|
119
|
+
/** The scope `t()` should read: the ALS-scoped one if active, else the global one. */
|
|
120
|
+
function activeScope() {
|
|
121
|
+
return ambientStore?.getStore() ?? globalScope;
|
|
122
|
+
}
|
|
93
123
|
/**
|
|
94
|
-
* Install the ambient message table consulted by `t()
|
|
95
|
-
* scene construction (the render entry injects it from
|
|
96
|
-
* `undefined` to clear it (the base-locale / no-flag path leaves
|
|
97
|
-
* Resets the consumed-id set (a fresh table = a fresh resolution pass).
|
|
124
|
+
* Install the ambient message table consulted by `t()` on the PROCESS-GLOBAL
|
|
125
|
+
* scope. Called ONCE before scene construction (the render entry injects it from
|
|
126
|
+
* `--locale`). Pass `undefined` to clear it (the base-locale / no-flag path leaves
|
|
127
|
+
* it unset). Resets the consumed-id set (a fresh table = a fresh resolution pass).
|
|
128
|
+
*
|
|
129
|
+
* 0.15 FIX 3: for CONCURRENT renders of different locales, prefer
|
|
130
|
+
* `runWithMessageTable` — this global setter races across interleaved flows.
|
|
98
131
|
*/
|
|
99
132
|
function setMessageTable(table) {
|
|
100
|
-
|
|
101
|
-
consumedIds = /* @__PURE__ */ new Set();
|
|
133
|
+
globalScope.table = table;
|
|
134
|
+
globalScope.consumedIds = /* @__PURE__ */ new Set();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Run `fn` with `table` installed as the ambient message table for the DURATION
|
|
138
|
+
* of `fn`'s async flow only — isolated from the process-global scope and from any
|
|
139
|
+
* other concurrent flow (0.15 FIX 3). `t()` inside `fn` (and anything it awaits)
|
|
140
|
+
* resolves against `table`; `t()` outside it is unaffected. Resolves to `fn`'s
|
|
141
|
+
* result. The render entry can scope the whole `loadSceneModule`→`localize` flow
|
|
142
|
+
* per locale with this so parallel embedders never cross-contaminate. The
|
|
143
|
+
* consumed-id set is collected per scope and is readable with
|
|
144
|
+
* `getConsumedMessageIds()` inside `fn`.
|
|
145
|
+
*
|
|
146
|
+
* Async because the AsyncLocalStorage class is loaded via a dynamic `node` import
|
|
147
|
+
* on first use (so this prepare/render-path module never statically pulls in
|
|
148
|
+
* `node:async_hooks`); the ALS context still spans `fn` and everything it awaits.
|
|
149
|
+
*/
|
|
150
|
+
async function runWithMessageTable(table, fn) {
|
|
151
|
+
if (ambientStore === void 0) {
|
|
152
|
+
const { AsyncLocalStorage } = await import("node:async_hooks");
|
|
153
|
+
ambientStore ??= new AsyncLocalStorage();
|
|
154
|
+
}
|
|
155
|
+
return ambientStore.run({
|
|
156
|
+
table,
|
|
157
|
+
consumedIds: /* @__PURE__ */ new Set()
|
|
158
|
+
}, fn);
|
|
102
159
|
}
|
|
103
160
|
/** The currently installed ambient message table (undefined when none is set). */
|
|
104
161
|
function getMessageTable() {
|
|
105
|
-
return
|
|
162
|
+
return activeScope().table;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Run `fn` while PRESERVING the process-global ambient scope across it (0.15 FIX 3).
|
|
166
|
+
* `fn` may freely call `setMessageTable` / `loadSceneModule` (which clobbers the
|
|
167
|
+
* global table) — the table + consumed-id set are snapshotted before and restored
|
|
168
|
+
* after, so a no-locale helper (the audio-mix gather) can't leave a leaked or
|
|
169
|
+
* cleared table visible to a concurrent locale's flow. Awaits/returns `fn`'s result.
|
|
170
|
+
*/
|
|
171
|
+
function preservingMessageTable(fn) {
|
|
172
|
+
const savedTable = globalScope.table;
|
|
173
|
+
const savedConsumed = globalScope.consumedIds;
|
|
174
|
+
const restore = () => {
|
|
175
|
+
globalScope.table = savedTable;
|
|
176
|
+
globalScope.consumedIds = savedConsumed;
|
|
177
|
+
};
|
|
178
|
+
let promise;
|
|
179
|
+
try {
|
|
180
|
+
promise = fn();
|
|
181
|
+
} catch (err) {
|
|
182
|
+
restore();
|
|
183
|
+
throw err;
|
|
184
|
+
}
|
|
185
|
+
return promise.finally(restore);
|
|
106
186
|
}
|
|
107
187
|
/**
|
|
108
188
|
* The set of ids `t()` has resolved against the ambient table since the last
|
|
109
|
-
* `setMessageTable
|
|
110
|
-
*
|
|
111
|
-
*
|
|
189
|
+
* `setMessageTable` (or, inside a `runWithMessageTable` flow, since that scope
|
|
190
|
+
* began). The render entry passes this to `localize` so a key consumed by a
|
|
191
|
+
* free-standing `t()` (which `localize` can't see — it isn't a doc track) isn't
|
|
192
|
+
* reported as an orphaned table key (0.14 FIX 5).
|
|
112
193
|
*/
|
|
113
194
|
function getConsumedMessageIds() {
|
|
114
|
-
return consumedIds;
|
|
195
|
+
return activeScope().consumedIds;
|
|
115
196
|
}
|
|
116
197
|
/**
|
|
117
198
|
* Resolve a free-standing message `id` against the ambient table — build-time
|
|
@@ -124,11 +205,13 @@ function getConsumedMessageIds() {
|
|
|
124
205
|
* so an un-localized build renders its keys as authored and stays byte-identical.
|
|
125
206
|
*/
|
|
126
207
|
function t(id) {
|
|
208
|
+
const scope = activeScope();
|
|
209
|
+
const ambientTable = scope.table;
|
|
127
210
|
if (ambientTable === void 0) return id;
|
|
128
211
|
const value = ambientTable[id];
|
|
129
|
-
if (value !== void 0) consumedIds.add(id);
|
|
212
|
+
if (value !== void 0) scope.consumedIds.add(id);
|
|
130
213
|
if (value === void 0) throw new LocalizationError(`t('${id}'): no message for id '${id}' in the active message table (have: ${Object.keys(ambientTable).map((k) => `'${k}'`).join(", ") || "<empty>"})`);
|
|
131
214
|
return value;
|
|
132
215
|
}
|
|
133
216
|
//#endregion
|
|
134
|
-
export { LocalizationError, ParityError, getConsumedMessageIds, getMessageTable, localize, requireParity, setMessageTable, t };
|
|
217
|
+
export { LocalizationError, ParityError, getConsumedMessageIds, getMessageTable, localize, preservingMessageTable, requireParity, runWithMessageTable, setMessageTable, t };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as cubicBezierDerivative, A as getValueType, B as vec2Type, C as UnknownValueTypeError, D as Vec2, E as ValueTypeInferenceError, F as registerValueType, G as springEasing, H as SpringConfig, I as reprOf, J as DEFAULT_EASE, K as springEasingDerivative, L as stringType, M as numberType, N as paintType, O as booleanType, P as pathType, Q as cubicBezier, R as vec2ArcType, S as PathValue, T as ValueTypeId, U as SpringEase, V as RetargetSpring, W as spring, X as EasingFn, Y as EaseSpec, Z as UnknownEasingError, _ as MeshInterpolation, a as key, b as Paint, c as sampleTrack, d as track, et as easingDerivatives, f as validateTrack, g as HandoffKind, h as GradientInterpolation, i as TrackValidationError, j as inferValueType, k as colorType, l as springTo, m as ColorStop, n as KeyOpts, nt as namedEasing, o as resolveEase, p as velocityAt, q as springPresets, r as Track, s as resolveEaseDerivative, t as Key, tt as easings, u as stagger, v as MeshPaint, w as ValueType, x as PathContour, y as MeshPoint, z as vec2Equals } from "./track.js";
|
|
2
2
|
import { a as isEditableNodeId, i as UnresolvableTargetError, n as TargetCarrier, o as resolveTweenTarget, r as TweenTarget, s as targetNodeId, t as TARGET_PATH } from "./targetRef.js";
|
|
3
3
|
import { _ as setDevWarning, a as FontFaceRef, c as Marker, d as TimelineValidationError, f as audioOffsetSamples, g as emitDevWarning, h as DevWarning, i as CompiledTimeline, l as Timeline, m as isDurationEditable, n as AudioClip, o as GainEnvelope, p as compileTimeline, r as ChildEntry, s as Json, t as AssetRef, u as TimelineInit } from "./timeline.js";
|
|
4
4
|
import { _ as setSidecarTrack, a as SidecarOrphan, c as SidecarVersionError, d as emptySidecar, f as hashKeys, g as normalizeEditedKeys, h as migrateSidecar, i as SidecarDocV1, l as assignKeyIds, m as mergeSidecarDetailed, n as OrphanReason, o as SidecarTimelineEntry, p as mergeSidecar, r as SidecarDoc, s as SidecarTrackEntry, t as MergeResult, u as deleteSidecarTrack } from "./sidecar.js";
|
|
@@ -310,12 +310,14 @@ interface BindTarget {
|
|
|
310
310
|
bindSource(fn: () => unknown): void;
|
|
311
311
|
unbindSource(): void;
|
|
312
312
|
/**
|
|
313
|
-
* The value type this target accepts; a track
|
|
314
|
-
*
|
|
315
|
-
*
|
|
316
|
-
*
|
|
317
|
-
*
|
|
318
|
-
*
|
|
313
|
+
* The value type this target accepts; a track whose REPRESENTATION (its
|
|
314
|
+
* `repr`, single-hop) differs is a bind error. So a `vec2-arc` track (repr
|
|
315
|
+
* 'vec2') binds to a plain `'vec2'` target, and a custom `cents` (repr
|
|
316
|
+
* 'number') binds to a `'number'` target — the extension door (0.15). An
|
|
317
|
+
* ARRAY is for GENUINE polymorphism — distinct reprs admitted at one prop
|
|
318
|
+
* (e.g. a Shape `fill` accepts both `color` and `paint`). UNDEFINED means the
|
|
319
|
+
* target opted OUT of the guard (an untagged custom-node prop — back-compat
|
|
320
|
+
* with 0.13, which had no guard): any track binds without a type check.
|
|
319
321
|
*/
|
|
320
322
|
readonly expects: ValueTypeId | readonly ValueTypeId[] | undefined;
|
|
321
323
|
}
|
|
@@ -390,4 +392,4 @@ interface CheckpointedSim {
|
|
|
390
392
|
}
|
|
391
393
|
declare function bakeCheckpointed<W, S = W>(cfg: CheckpointedBakeConfig<W, S>): CheckpointedSim;
|
|
392
394
|
//#endregion
|
|
393
|
-
export { type AssetRef, type AudioClip, type BakeConfig, BakeError, type BindTarget, BindTypeMismatchError, type BindableSignal, type BoundTimeline, type CheckpointedBakeConfig, type CheckpointedSim, type ChildEntry, CircularDependencyError, ColorParseError, type ColorStop, type CompiledTimeline, type CoverageReport, type CurveSampler, DEFAULT_EASE, type DevWarning, type EaseSpec, type EasingFn, type Equals, type FontFaceRef, type FontMode, type FontRegistry, type FontUsage, FontValidationError, type GainEnvelope, type GradientInterpolation, type HandoffKind, type Json, type Key, type KeyOpts, type Marker, type MergeResult, type MeshInterpolation, type MeshPaint, type MeshPoint, type MissingGlyphs, type OkLab, type OrphanReason, type Paint, type PathContour, type PathValue, type Playhead, type Position, PositionError, type ReadonlySignal, type ResolvedFace, type RetargetSpring, type Rgba, type Rng, type Scheduler, type SidecarDoc, type SidecarDocV1, type SidecarOrphan, type SidecarTimelineEntry, type SidecarTrackEntry, SidecarVersionError, type Signal, type SignalOptions, type SpringConfig, type SpringEase, TARGET_PATH, type TargetCarrier, type Timeline, type TimelineBuilder, type TimelineInit, TimelineValidationError, type Track, TrackValidationError, type TweenOpts, type TweenTarget, UnboundTargetError, UnknownEasingError, UnknownValueTypeError, UnresolvableTargetError, type ValidateFontsOptions, type ValueType, type ValueTypeId, ValueTypeInferenceError, type Vec2, type Vec2Component, type Vec2Signal, WriteDuringEvaluationError, assignKeyIds, audioOffsetSamples, bake, bakeCheckpointed, batch, beginReadPhase, bindTimeline, booleanType, buildFontRegistry, buildTimeline, colorType, compileTimeline, computed, createPlayhead, cubicBezier, cubicBezierDerivative, deleteSidecarTrack, easingDerivatives, easings, emitDevWarning, emptySidecar, endReadPhase, evaluateAt, formatColor, getTimelineCallbacks, getValueType, hashKeys, inReadPhase, inferValueType, isDurationEditable, isEditableNodeId, isExemptFamily, key, lerpColor, mergeSidecar, mergeSidecarDetailed, migrateSidecar, namedEasing, normalizeEditedKeys, numberType, oklabToRgba, paintType, parseCmap, parseColor, pathType, random, registerValueType, resolveEase, resolveEaseDerivative, resolveTweenTarget, rgbaToOklab, sampleTrack, setDevWarning, setScheduler, setSidecarTrack, signal, spring, springEasing, springEasingDerivative, springPresets, springTo, stagger, stringType, synchronousScheduler, targetNodeId, timeline, track, untracked, validateFonts, validateTrack, vec2ArcType, vec2Equals, vec2Signal, vec2Type, velocityAt };
|
|
395
|
+
export { type AssetRef, type AudioClip, type BakeConfig, BakeError, type BindTarget, BindTypeMismatchError, type BindableSignal, type BoundTimeline, type CheckpointedBakeConfig, type CheckpointedSim, type ChildEntry, CircularDependencyError, ColorParseError, type ColorStop, type CompiledTimeline, type CoverageReport, type CurveSampler, DEFAULT_EASE, type DevWarning, type EaseSpec, type EasingFn, type Equals, type FontFaceRef, type FontMode, type FontRegistry, type FontUsage, FontValidationError, type GainEnvelope, type GradientInterpolation, type HandoffKind, type Json, type Key, type KeyOpts, type Marker, type MergeResult, type MeshInterpolation, type MeshPaint, type MeshPoint, type MissingGlyphs, type OkLab, type OrphanReason, type Paint, type PathContour, type PathValue, type Playhead, type Position, PositionError, type ReadonlySignal, type ResolvedFace, type RetargetSpring, type Rgba, type Rng, type Scheduler, type SidecarDoc, type SidecarDocV1, type SidecarOrphan, type SidecarTimelineEntry, type SidecarTrackEntry, SidecarVersionError, type Signal, type SignalOptions, type SpringConfig, type SpringEase, TARGET_PATH, type TargetCarrier, type Timeline, type TimelineBuilder, type TimelineInit, TimelineValidationError, type Track, TrackValidationError, type TweenOpts, type TweenTarget, UnboundTargetError, UnknownEasingError, UnknownValueTypeError, UnresolvableTargetError, type ValidateFontsOptions, type ValueType, type ValueTypeId, ValueTypeInferenceError, type Vec2, type Vec2Component, type Vec2Signal, WriteDuringEvaluationError, assignKeyIds, audioOffsetSamples, bake, bakeCheckpointed, batch, beginReadPhase, bindTimeline, booleanType, buildFontRegistry, buildTimeline, colorType, compileTimeline, computed, createPlayhead, cubicBezier, cubicBezierDerivative, deleteSidecarTrack, easingDerivatives, easings, emitDevWarning, emptySidecar, endReadPhase, evaluateAt, formatColor, getTimelineCallbacks, getValueType, hashKeys, inReadPhase, inferValueType, isDurationEditable, isEditableNodeId, isExemptFamily, key, lerpColor, mergeSidecar, mergeSidecarDetailed, migrateSidecar, namedEasing, normalizeEditedKeys, numberType, oklabToRgba, paintType, parseCmap, parseColor, pathType, random, registerValueType, reprOf, resolveEase, resolveEaseDerivative, resolveTweenTarget, rgbaToOklab, sampleTrack, setDevWarning, setScheduler, setSidecarTrack, signal, spring, springEasing, springEasingDerivative, springPresets, springTo, stagger, stringType, synchronousScheduler, targetNodeId, timeline, track, untracked, validateFonts, validateTrack, vec2ArcType, vec2Equals, vec2Signal, vec2Type, velocityAt };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as vec2Type, B as springEasing, C as paintType, D as stringType, E as reprOf, F as parseColor, G as cubicBezier, H as springPresets, I as rgbaToOklab, J as easings, K as cubicBezierDerivative, L as emitDevWarning, M as formatColor, N as lerpColor, O as vec2ArcType, P as oklabToRgba, R as setDevWarning, S as numberType, T as registerValueType, U as DEFAULT_EASE, V as springEasingDerivative, W as UnknownEasingError, Y as namedEasing, _ as ValueTypeInferenceError, a as targetNodeId, b as getValueType, c as resolveEase, d as springTo, f as stagger, g as UnknownValueTypeError, h as velocityAt, i as resolveTweenTarget, j as ColorParseError, k as vec2Equals, l as resolveEaseDerivative, m as validateTrack, n as UnresolvableTargetError, o as TrackValidationError, p as track, q as easingDerivatives, r as isEditableNodeId, s as key, t as TARGET_PATH, u as sampleTrack, v as booleanType, w as pathType, x as inferValueType, y as colorType, z as spring } from "./targetRef.js";
|
|
2
2
|
import { t as parseCmap } from "./cmap.js";
|
|
3
3
|
import { a as hashKeys, c as migrateSidecar, d as TimelineValidationError, f as audioOffsetSamples, h as timeline$1, i as emptySidecar, l as normalizeEditedKeys, m as isDurationEditable, n as assignKeyIds, o as mergeSidecar, p as compileTimeline, r as deleteSidecarTrack, s as mergeSidecarDetailed, t as SidecarVersionError, u as setSidecarTrack } from "./sidecar.js";
|
|
4
4
|
//#region src/ticker.ts
|
|
@@ -855,7 +855,8 @@ function bindTimeline(compiled, resolve, playhead = createPlayhead()) {
|
|
|
855
855
|
const got = tr.type;
|
|
856
856
|
const expects = sig.expects;
|
|
857
857
|
if (expects !== void 0) {
|
|
858
|
-
|
|
858
|
+
const gotRepr = reprOf(got);
|
|
859
|
+
if (!(Array.isArray(expects) ? expects : [expects]).some((e) => reprOf(e) === gotRepr)) throw new BindTypeMismatchError(target, got, expects);
|
|
859
860
|
}
|
|
860
861
|
sig.bindSource(() => sampleTrack(tr, playhead()));
|
|
861
862
|
bound.push(sig);
|
|
@@ -1006,4 +1007,4 @@ function bakeCheckpointed(cfg) {
|
|
|
1006
1007
|
};
|
|
1007
1008
|
}
|
|
1008
1009
|
//#endregion
|
|
1009
|
-
export { BakeError, BindTypeMismatchError, CircularDependencyError, ColorParseError, DEFAULT_EASE, FontValidationError, PositionError, SidecarVersionError, TARGET_PATH, TimelineValidationError, TrackValidationError, UnboundTargetError, UnknownEasingError, UnknownValueTypeError, UnresolvableTargetError, ValueTypeInferenceError, WriteDuringEvaluationError, assignKeyIds, audioOffsetSamples, bake, bakeCheckpointed, batch, beginReadPhase, bindTimeline, booleanType, buildFontRegistry, buildTimeline, colorType, compileTimeline, computed, createPlayhead, cubicBezier, cubicBezierDerivative, deleteSidecarTrack, easingDerivatives, easings, emitDevWarning, emptySidecar, endReadPhase, evaluateAt, formatColor, getTimelineCallbacks, getValueType, hashKeys, inReadPhase, inferValueType, isDurationEditable, isEditableNodeId, isExemptFamily, key, lerpColor, mergeSidecar, mergeSidecarDetailed, migrateSidecar, namedEasing, normalizeEditedKeys, numberType, oklabToRgba, paintType, parseCmap, parseColor, pathType, random, registerValueType, resolveEase, resolveEaseDerivative, resolveTweenTarget, rgbaToOklab, sampleTrack, setDevWarning, setScheduler, setSidecarTrack, signal, spring, springEasing, springEasingDerivative, springPresets, springTo, stagger, stringType, synchronousScheduler, targetNodeId, timeline, track, untracked, validateFonts, validateTrack, vec2ArcType, vec2Equals, vec2Signal, vec2Type, velocityAt };
|
|
1010
|
+
export { BakeError, BindTypeMismatchError, CircularDependencyError, ColorParseError, DEFAULT_EASE, FontValidationError, PositionError, SidecarVersionError, TARGET_PATH, TimelineValidationError, TrackValidationError, UnboundTargetError, UnknownEasingError, UnknownValueTypeError, UnresolvableTargetError, ValueTypeInferenceError, WriteDuringEvaluationError, assignKeyIds, audioOffsetSamples, bake, bakeCheckpointed, batch, beginReadPhase, bindTimeline, booleanType, buildFontRegistry, buildTimeline, colorType, compileTimeline, computed, createPlayhead, cubicBezier, cubicBezierDerivative, deleteSidecarTrack, easingDerivatives, easings, emitDevWarning, emptySidecar, endReadPhase, evaluateAt, formatColor, getTimelineCallbacks, getValueType, hashKeys, inReadPhase, inferValueType, isDurationEditable, isEditableNodeId, isExemptFamily, key, lerpColor, mergeSidecar, mergeSidecarDetailed, migrateSidecar, namedEasing, normalizeEditedKeys, numberType, oklabToRgba, paintType, parseCmap, parseColor, pathType, random, registerValueType, reprOf, resolveEase, resolveEaseDerivative, resolveTweenTarget, rgbaToOklab, sampleTrack, setDevWarning, setScheduler, setSidecarTrack, signal, spring, springEasing, springEasingDerivative, springPresets, springTo, stagger, stringType, synchronousScheduler, targetNodeId, timeline, track, untracked, validateFonts, validateTrack, vec2ArcType, vec2Equals, vec2Signal, vec2Type, velocityAt };
|
package/dist/sidecar.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { L as emitDevWarning, a as targetNodeId, m as validateTrack, o as TrackValidationError, r as isEditableNodeId, z as spring } from "./targetRef.js";
|
|
2
2
|
//#region src/timeline.ts
|
|
3
3
|
/**
|
|
4
4
|
* The Timeline document (DESIGN.md §2.3) — the serializable animation source
|
package/dist/studioHost.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { T as ValueTypeId, Y as EaseSpec, t as Key } from "./track.js";
|
|
2
2
|
import { a as isEditableNodeId, s as targetNodeId } from "./targetRef.js";
|
|
3
3
|
import { l as Timeline } from "./timeline.js";
|
|
4
4
|
import { a as SidecarOrphan, r as SidecarDoc } from "./sidecar.js";
|
package/dist/targetRef.js
CHANGED
|
@@ -490,6 +490,16 @@ function getValueType(id) {
|
|
|
490
490
|
if (!vt) throw new UnknownValueTypeError(id);
|
|
491
491
|
return vt;
|
|
492
492
|
}
|
|
493
|
+
/**
|
|
494
|
+
* Resolve a value-type id to its REPRESENTATION (the bind guard's compatibility
|
|
495
|
+
* key, §2.2): a type's `repr` (the built-in it's representationally compatible
|
|
496
|
+
* with), else the id itself. SINGLE-HOP — `repr` is never chained, so a custom
|
|
497
|
+
* type's repr must be a base type. An UNREGISTERED id resolves to itself (the
|
|
498
|
+
* guard's job is repr-compat, not existence — `getValueType` enforces that).
|
|
499
|
+
*/
|
|
500
|
+
function reprOf(id) {
|
|
501
|
+
return registry.get(id)?.repr ?? id;
|
|
502
|
+
}
|
|
493
503
|
const numberType = {
|
|
494
504
|
id: "number",
|
|
495
505
|
lerp: (a, b, t) => a + (b - a) * t,
|
|
@@ -514,6 +524,7 @@ const vec2Type = {
|
|
|
514
524
|
/** vec2 swept along a circular arc: polar lerp of radius + shortest-path angle (§2.2). */
|
|
515
525
|
const vec2ArcType = {
|
|
516
526
|
id: "vec2-arc",
|
|
527
|
+
repr: "vec2",
|
|
517
528
|
lerp: (a, b, t) => {
|
|
518
529
|
const ra = Math.hypot(a[0], a[1]);
|
|
519
530
|
const rb = Math.hypot(b[0], b[1]);
|
|
@@ -1019,4 +1030,4 @@ function resolveTweenTarget(target) {
|
|
|
1019
1030
|
return path;
|
|
1020
1031
|
}
|
|
1021
1032
|
//#endregion
|
|
1022
|
-
export {
|
|
1033
|
+
export { vec2Type as A, springEasing as B, paintType as C, stringType as D, reprOf as E, parseColor as F, cubicBezier as G, springPresets as H, rgbaToOklab as I, easings as J, cubicBezierDerivative as K, emitDevWarning as L, formatColor as M, lerpColor as N, vec2ArcType as O, oklabToRgba as P, setDevWarning as R, numberType as S, registerValueType as T, DEFAULT_EASE as U, springEasingDerivative as V, UnknownEasingError as W, namedEasing as Y, ValueTypeInferenceError as _, targetNodeId as a, getValueType as b, resolveEase as c, springTo as d, stagger as f, UnknownValueTypeError as g, velocityAt as h, resolveTweenTarget as i, ColorParseError as j, vec2Equals as k, resolveEaseDerivative as l, validateTrack as m, UnresolvableTargetError as n, TrackValidationError as o, track as p, easingDerivatives as q, isEditableNodeId as r, key as s, TARGET_PATH as t, sampleTrack as u, booleanType as v, pathType as w, inferValueType as x, colorType as y, spring as z };
|
package/dist/track.d.ts
CHANGED
|
@@ -145,6 +145,16 @@ type PathValue = PathContour[];
|
|
|
145
145
|
type HandoffKind = 'cut' | 'decay' | 'spring' | 'blend-from-frozen';
|
|
146
146
|
interface ValueType<T> {
|
|
147
147
|
id: string;
|
|
148
|
+
/**
|
|
149
|
+
* The built-in value type this type is REPRESENTATIONALLY compatible with —
|
|
150
|
+
* the bind guard (binding.ts) matches a track to a target when their reprs
|
|
151
|
+
* agree, not just their ids. A custom type that is "a number under a different
|
|
152
|
+
* id" (e.g. a `cents` type) sets `repr: 'number'` so it binds to `number`
|
|
153
|
+
* props (and vice versa); `vec2-arc` sets `repr: 'vec2'`. SINGLE-HOP only:
|
|
154
|
+
* `repr` must name a base type that has no `repr` of its own (no chaining).
|
|
155
|
+
* Omitted ⇒ the type is its own repr.
|
|
156
|
+
*/
|
|
157
|
+
repr?: ValueTypeId;
|
|
148
158
|
lerp(a: T, b: T, t: number): T;
|
|
149
159
|
/** Accepts easedT outside [0,1] (spring overshoot)? Otherwise clamped. */
|
|
150
160
|
extrapolates: boolean;
|
|
@@ -165,6 +175,14 @@ declare class UnknownValueTypeError extends Error {
|
|
|
165
175
|
constructor(id: string);
|
|
166
176
|
}
|
|
167
177
|
declare function getValueType<T = unknown>(id: ValueTypeId): ValueType<T>;
|
|
178
|
+
/**
|
|
179
|
+
* Resolve a value-type id to its REPRESENTATION (the bind guard's compatibility
|
|
180
|
+
* key, §2.2): a type's `repr` (the built-in it's representationally compatible
|
|
181
|
+
* with), else the id itself. SINGLE-HOP — `repr` is never chained, so a custom
|
|
182
|
+
* type's repr must be a base type. An UNREGISTERED id resolves to itself (the
|
|
183
|
+
* guard's job is repr-compat, not existence — `getValueType` enforces that).
|
|
184
|
+
*/
|
|
185
|
+
declare function reprOf(id: ValueTypeId): ValueTypeId;
|
|
168
186
|
declare const numberType: ValueType<number>;
|
|
169
187
|
declare const vec2Equals: (a: Vec2, b: Vec2) => boolean;
|
|
170
188
|
declare const vec2Type: ValueType<Vec2>;
|
|
@@ -326,4 +344,4 @@ declare function velocityAt<T>(tr: Track<T>, t: number): T | null;
|
|
|
326
344
|
/** Pure sample of a track at time t (§2.4). */
|
|
327
345
|
declare function sampleTrack<T>(tr: Track<T>, t: number): T;
|
|
328
346
|
//#endregion
|
|
329
|
-
export {
|
|
347
|
+
export { cubicBezierDerivative as $, getValueType as A, vec2Type as B, UnknownValueTypeError as C, Vec2 as D, ValueTypeInferenceError as E, registerValueType as F, springEasing as G, SpringConfig as H, reprOf as I, DEFAULT_EASE as J, springEasingDerivative as K, stringType as L, numberType as M, paintType as N, booleanType as O, pathType as P, cubicBezier as Q, vec2ArcType as R, PathValue as S, ValueTypeId as T, SpringEase as U, RetargetSpring as V, spring as W, EasingFn as X, EaseSpec as Y, UnknownEasingError as Z, MeshInterpolation as _, key as a, Paint as b, sampleTrack as c, track as d, easingDerivatives as et, validateTrack as f, HandoffKind as g, GradientInterpolation as h, TrackValidationError as i, inferValueType as j, colorType as k, springTo as l, ColorStop as m, KeyOpts as n, namedEasing as nt, resolveEase as o, velocityAt as p, springPresets as q, Track as r, resolveEaseDerivative as s, Key as t, easings as tt, stagger as u, MeshPaint as v, ValueType as w, PathContour as x, MeshPoint as y, vec2Equals as z };
|
package/package.json
CHANGED