@vizij/runtime-react 0.4.2 → 1.0.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/index.d.ts CHANGED
@@ -1,442 +1,132 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import * as react from 'react';
3
- import { ReactNode, PropsWithChildren } from 'react';
4
- import { ValueJSON } from '@vizij/value-json';
5
- import { IrGraph } from '@vizij/node-graph-authoring';
6
- import { RawValue, AnimatableValue } from '@vizij/utils';
7
- import { World, VizijBundleExtension, VizijStarredItem, VizijProps } from '@vizij/render';
1
+ import { ReactNode } from 'react';
2
+ import { VizijOptions, ValueJSON, Runtime, VizijDescription } from '@vizij/runtime';
3
+ import { VizijProps } from '@vizij/render';
8
4
 
9
- /** Value shape hint. Accepted through the public surface, unused by the device. */
10
- type ShapeJSON = Record<string, unknown>;
11
- /** Paths a graph reads/writes — metadata for output tracking and seeding. */
12
- type GraphSubscriptions = {
13
- inputs?: string[];
14
- outputs?: string[];
15
- };
16
- /** A Vizij graph spec handled structurally (nodes/edges arrays of records). */
17
- type GraphSpecLike = {
18
- nodes?: Array<Record<string, unknown>>;
19
- edges?: Array<Record<string, unknown>>;
20
- metadata?: unknown;
21
- [key: string]: unknown;
22
- };
23
- /** One graph source composed into the device's behavior. */
24
- type GraphRegistrationConfig = {
25
- id?: string;
26
- spec: GraphSpecLike;
27
- subs?: GraphSubscriptions;
28
- };
29
- /** Per-source merge options. Composition is last-writer-wins today (VIZ-53). */
30
- type MergeStrategyOptions = Record<string, unknown>;
31
- /** Player/instance setup carried by animation assets; consumed by the JS clip pipeline. */
32
- type AnimationSetup = {
33
- animation?: unknown;
34
- player?: Record<string, unknown>;
35
- instance?: Record<string, unknown>;
36
- };
37
- type PoseDefinition = {
38
- id: string;
39
- name?: string;
40
- description?: string;
41
- group?: string | null;
42
- groupId?: string | null;
43
- groupIds?: string[];
44
- values: Record<string, number | undefined>;
45
- };
46
- type PoseBlendMode = "average" | "additive";
47
- type PoseGroupDefinition = {
48
- id: string;
49
- name: string;
50
- path: string;
51
- blendMode?: PoseBlendMode;
52
- };
53
- type PoseRigConfig = {
54
- version: number;
55
- faceId?: string | null;
56
- title?: string;
57
- description?: string;
58
- poseGroups?: PoseGroupDefinition[];
59
- crossGroupBlendMode?: PoseBlendMode;
60
- neutralInputs: Record<string, number>;
61
- poses: PoseDefinition[];
62
- metadata?: Record<string, unknown> | {
63
- createdAt: string;
64
- updatedAt: string;
65
- author?: string;
66
- };
67
- };
68
- type RootBounds = {
69
- center: {
70
- x: number;
71
- y: number;
72
- };
73
- size: {
74
- x: number;
75
- y: number;
76
- };
77
- };
78
- type VizijGlbAsset = {
79
- kind: "url";
80
- src: string;
81
- aggressiveImport?: boolean;
82
- rootBounds?: RootBounds;
83
- } | {
84
- kind: "blob";
85
- blob: Blob;
86
- aggressiveImport?: boolean;
87
- rootBounds?: RootBounds;
88
- } | {
89
- kind: "world";
90
- world: World | Record<string, unknown>;
91
- animatables: Record<string, AnimatableValue> | Record<string, unknown>;
92
- bundle?: VizijBundleExtension | null;
93
- };
94
- type VizijGraphAsset = {
95
- id: string;
96
- spec?: GraphRegistrationConfig["spec"];
97
- ir?: IrGraph | null;
98
- subscriptions?: Partial<GraphSubscriptions>;
99
- inputMetadata?: VizijInputMetadata[];
100
- };
101
- type VizijInputMetadata = {
102
- id?: string;
103
- path: string;
104
- label?: string;
105
- source?: string;
106
- root?: string;
107
- defaultValue?: number;
108
- range?: {
109
- min?: number;
110
- max?: number;
111
- };
112
- [key: string]: unknown;
113
- };
114
- type AnimationKeyframeLike = {
115
- time?: number;
116
- value?: number;
117
- inTangent?: number | null;
118
- outTangent?: number | null;
119
- [key: string]: unknown;
120
- };
121
- type AnimationTrackLike = {
122
- channel: string;
123
- keyframes?: AnimationKeyframeLike[];
124
- interpolation?: "linear" | "step" | "cubic" | string;
125
- [key: string]: unknown;
126
- };
127
- type AnimationClipLike = {
128
- id?: string;
129
- name?: string;
130
- duration?: number;
131
- tracks?: AnimationTrackLike[];
132
- [key: string]: unknown;
133
- };
134
- type VizijAnimationAsset = {
135
- id: string;
136
- clip: AnimationClipLike;
137
- setup?: Partial<AnimationSetup>;
138
- weight?: number;
139
- };
140
- type VizijProgramAsset = {
141
- id: string;
142
- label?: string;
143
- graph: VizijGraphAsset;
144
- resetValues?: Record<string, number>;
145
- metadata?: Record<string, unknown>;
146
- };
147
- type VizijAssetBundle = {
148
- namespace?: string;
149
- faceId?: string;
150
- glb: VizijGlbAsset;
151
- rig?: VizijGraphAsset;
152
- pose?: {
153
- graph?: VizijGraphAsset;
154
- config?: PoseRigConfig;
155
- stageNeutralFilter?: (id: string, path: string) => boolean;
156
- };
157
- animations?: VizijAnimationAsset[];
158
- programs?: VizijProgramAsset[];
159
- /**
160
- * Designer-curated set of starred drivers/poses, resolved from the loaded
161
- * bundle's `starred` section. References real functionality by stable id
162
- * (driver = standard-input id, pose = pose id).
163
- */
164
- starred?: VizijStarredItem[];
165
- initialInputs?: Record<string, ValueJSON>;
166
- metadata?: Record<string, unknown>;
167
- bundle?: VizijBundleExtension | null;
168
- };
169
- type RuntimeError = {
170
- message: string;
171
- cause?: unknown;
172
- phase?: "assets" | "engine" | "registration" | "animation" | "bridge" | "driver" | "unknown";
173
- timestamp: number;
174
- };
175
- type VizijRuntimeStatus = {
176
- loading: boolean;
177
- ready: boolean;
178
- error: RuntimeError | null;
179
- errors: RuntimeError[];
180
- namespace: string;
181
- faceId?: string;
182
- rootId?: string | null;
183
- /** Namespaced output signal paths emitted by registered graphs. */
184
- outputPaths: string[];
185
- /** Approximate current stepping rate in Hz (smoothed). */
186
- stepHz?: number;
187
- controllers: {
188
- graphs: string[];
189
- anims: string[];
190
- };
191
- };
192
- type AnimateValueOptions = {
193
- duration?: number;
194
- easing?: ((t: number) => number) | "linear" | "easeInOut" | "easeOut" | "easeIn";
195
- namespace?: string;
196
- coordinate?: "input" | "renderer";
197
- };
198
- type PlayAnimationOptions = {
199
- weight?: number;
200
- speed?: number;
201
- reset?: boolean;
202
- };
203
- type StopAnimationOptions = {
204
- clearOutputs?: boolean;
205
- };
206
- type AnimationPlaybackState = {
207
- time: number;
208
- duration: number;
209
- playing: boolean;
210
- loop: boolean;
211
- speed: number;
212
- };
213
- type StopProgramOptions = {
214
- resetOutputs?: boolean;
215
- };
216
- type ProgramPlaybackState = {
217
- state: "playing" | "paused" | "stopped";
218
- };
219
- type InputDriverLifecycle = {
220
- start: () => void;
221
- stop: () => void;
222
- dispose: () => void;
223
- };
224
- type InputDriverContext = {
225
- setInput: (path: string, value: ValueJSON, shape?: ShapeJSON) => void;
226
- setRendererValue: (id: string, namespace: string, value: RawValue | ((prev: RawValue | undefined) => RawValue | undefined)) => void;
227
- namespace: string;
228
- faceId?: string;
229
- };
230
- type InputDriverFactory = (ctx: InputDriverContext) => InputDriverLifecycle;
231
- type RuntimeOutputWrite = {
232
- id: string;
233
- namespace: string;
234
- value: RawValue;
235
- currentValue?: RawValue;
236
- };
237
- type VizijRuntimeFaceProps = Omit<VizijProps, "rootId" | "namespace"> & {
238
- namespaceOverride?: string;
239
- };
240
- type VizijRuntimeContextValue = VizijRuntimeStatus & {
241
- assetBundle: VizijAssetBundle;
242
- setInput: (path: string, value: ValueJSON, shape?: ShapeJSON) => void;
243
- /** Current engine-store value of a path (read-your-own-write included). */
244
- getValueSnapshot: (path: string) => ValueJSON | undefined;
245
- /**
246
- * A snapshot of EVERY key currently in the device store, as path → Value in
247
- * arora's serde JSON shape (pass-through from the device; not `ValueJSON`).
248
- * `undefined` until the device exists. For mirrors/bridges that forward the
249
- * whole store (e.g. the standalone's native-store bridge), not for per-path
250
- * sampling — use `getValueSnapshot` for that.
251
- */
252
- getStoreSnapshot: () => Record<string, unknown> | undefined;
253
- /**
254
- * Notifies with each step's drained store changes (path → Value in arora's
255
- * serde JSON shape; `null` for a cleared key). The change-driven counterpart
256
- * to `getStoreSnapshot` for store bridges: seed from the snapshot, then stay
257
- * current from these. Returns an unsubscribe function.
258
- */
259
- subscribeToStoreChanges: (listener: (changes: Record<string, unknown>) => void) => () => void;
260
- /**
261
- * Notifies after each engine step, once the step's store changes have been
262
- * applied. Pair with `getValueSnapshot` to sample values step-aligned.
263
- * Returns an unsubscribe function.
264
- */
265
- subscribeToStep: (listener: () => void) => () => void;
266
- setGraphBundle: (bundle: RuntimeGraphBundle, options?: {
267
- tier?: "auto" | "assets" | "graphs";
268
- }) => void;
269
- setValue: (id: string, namespace: string, value: RawValue | ((prev: RawValue | undefined) => RawValue | undefined)) => void;
270
- stagePoseNeutral: (force?: boolean) => void;
271
- animateValue: (path: string, target: ValueJSON, options?: AnimateValueOptions) => Promise<void>;
272
- cancelAnimation: (path: string) => void;
273
- registerInputDriver: (id: string, factory: InputDriverFactory) => InputDriverLifecycle;
274
- playAnimation: (id: string, options?: PlayAnimationOptions) => Promise<void>;
275
- pauseAnimation: (id: string) => void;
276
- seekAnimation: (id: string, timeSeconds: number) => void;
277
- setAnimationLoop: (id: string, enabled: boolean) => void;
278
- getAnimationState: (id: string) => AnimationPlaybackState | null;
279
- stopAnimation: (id: string, options?: StopAnimationOptions) => void;
280
- playProgram: (id: string) => void;
281
- pauseProgram: (id: string) => void;
282
- stopProgram: (id: string, options?: StopProgramOptions) => void;
283
- getProgramState: (id: string) => ProgramPlaybackState | null;
284
- setAnimationActive: (active: boolean) => void;
285
- isAnimationActive: () => boolean;
286
- step: (dt: number, opts?: {
287
- forceRuntime?: boolean;
288
- }) => void;
289
- inputConstraints: Record<string, {
290
- min?: number;
291
- max?: number;
292
- defaultValue?: number;
293
- }>;
294
- };
295
- type VizijRuntimeProviderProps = {
296
- assetBundle: VizijAssetBundle;
297
- children: ReactNode;
298
- namespace?: string;
299
- faceId?: string;
300
- updateTier?: RuntimeUpdateTier;
301
- autoCreate?: boolean;
302
- autostart?: boolean;
303
- /**
304
- * Whether this provider's device paces itself: when true the device is
305
- * handed to its own `run()` loop at boot and the provider only pumps its
306
- * changes; when false the device advances solely on `step(dt,
307
- * { forceRuntime: true })` calls from the host. A device handed to `run()`
308
- * keeps its loop even if this later turns false.
309
- */
310
- driveRuntime?: boolean;
311
- mergeStrategy?: MergeStrategyOptions;
312
- onRegisterControllers?: (ids: {
313
- graphs: string[];
314
- anims: string[];
315
- }) => void;
316
- onStatusChange?: (status: VizijRuntimeStatus) => void;
317
- transformOutputWrite?: (write: RuntimeOutputWrite) => RuntimeOutputWrite | null;
318
- };
319
- type RuntimeUpdateTier = "auto" | "assets" | "graphs";
320
- type RuntimeUpdatePlan = {
321
- reloadAssets: boolean;
322
- reregisterGraphs: boolean;
323
- };
324
- type RuntimeGraphBundle = {
325
- rig?: VizijGraphAsset;
326
- pose?: VizijAssetBundle["pose"];
327
- animations?: VizijAnimationAsset[];
328
- programs?: VizijProgramAsset[];
329
- };
5
+ /** A face's GLB: a URL to fetch, or its bytes. */
6
+ type VizijSource = string | URL | Blob | ArrayBuffer | Uint8Array;
7
+ interface VizijRuntimeProviderProps {
8
+ /** The face to show. A different source reloads the face in place;
9
+ * `null` shows none: the provider takes its face down, and its children,
10
+ * which stay mounted, see no face (`useOptionalVizijRuntime()` is
11
+ * `null`). */
12
+ glb: VizijSource | null;
13
+ /** The id the face is loaded and shown under; one is derived from
14
+ * React's `useId()` when absent. */
15
+ vizijId?: string;
16
+ /** `loadVizij`'s options, passed through unchanged. Read at each load: a
17
+ * change shows from the next `glb`. */
18
+ options?: VizijOptions;
19
+ /** `true` (default): the provider steps the device, once per animation
20
+ * frame while the page is visible and on a timer while it is hidden.
21
+ * `false`: the device is stopped, and the page steps it
22
+ * (`runtime.step(dtMs)`). */
23
+ run?: boolean;
24
+ children?: ReactNode;
25
+ }
26
+ /**
27
+ * One face's lifecycle in React, over `@vizij/runtime`.
28
+ *
29
+ * It fetches the GLB, reads it with `describe`, waits for the page's canvas
30
+ * (`<VizijCanvas>`), loads the face with `loadVizij`, and hands its children
31
+ * the face's `Runtime` unwrapped (`useVizijRuntime`). A new `glb` reloads
32
+ * the face under the same id: the previous scene draws until the new one is
33
+ * ready, and the previous `Runtime` is stopped and disposed once the new one
34
+ * exists. Unmounting stops the device, unloads the face and disposes it; a
35
+ * `null` `glb` does the same and keeps the children mounted, so a page whose
36
+ * face comes and goes keeps its tree.
37
+ *
38
+ * Unless `run` is `false`, it steps the device: once per animation frame
39
+ * while the page is visible — one step per drawn frame, each by the time
40
+ * since the previous step — and every {@link HIDDEN_STEP_MS} while it is
41
+ * hidden, where the browser throttles timers and draws nothing. A page
42
+ * shown again keeps that timer until its first animation frame, so the
43
+ * device is never left unstepped between the two.
44
+ *
45
+ * It is the one caller of the runtime's `drainChanges`, whose cursor is one
46
+ * per `Runtime`. While something listens (`useVizijChanges`,
47
+ * `useVizijValues`) it drains once per animation frame and hands each batch
48
+ * to every listener; while nothing does, it does not drain. The runtime
49
+ * holds what is not drained as the latest value per key, so a batch is the
50
+ * net change since the previous drain, however long ago that was. The first
51
+ * batch after a (re)load is the whole store.
52
+ *
53
+ * It reports the face's stages to `@vizij/render` (`setVizijProgress`), for
54
+ * the loading view of the face's slot: the GLB's bytes as they arrive, then
55
+ * `loadVizij`, then the face's first frame. Unloading the face clears them.
56
+ *
57
+ * Showing the face is the page's `<Vizij>` slot, bound to this provider by
58
+ * `<VizijRuntimeFace>`.
59
+ */
60
+ declare function VizijRuntimeProvider({ glb, vizijId: givenId, options, run, children, }: VizijRuntimeProviderProps): ReactNode;
330
61
 
331
- type ProviderProps = PropsWithChildren<VizijRuntimeProviderProps>;
332
- declare function VizijRuntimeProvider({ assetBundle, children, namespace: namespaceProp, faceId: faceIdProp, updateTier, autoCreate, autostart, driveRuntime, mergeStrategy, onRegisterControllers, onStatusChange, transformOutputWrite, }: ProviderProps): react_jsx_runtime.JSX.Element;
62
+ type VizijRuntimeFaceProps = Omit<VizijProps, "vizijId">;
63
+ /** `<Vizij>` bound to the nearest provider's face: where it draws on the
64
+ * page's canvas. */
65
+ declare function VizijRuntimeFace(props: VizijRuntimeFaceProps): ReactNode;
333
66
 
334
- declare function VizijRuntimeFaceInner({ namespaceOverride, ...props }: VizijRuntimeFaceProps): react_jsx_runtime.JSX.Element | null;
335
- declare const VizijRuntimeFace: react.MemoExoticComponent<typeof VizijRuntimeFaceInner>;
67
+ /** A batch of store changes, as `Runtime.drainChanges` returns it: each
68
+ * changed key to its new value, `null` for a cleared key. */
69
+ type VizijChanges = Record<string, ValueJSON | null>;
70
+ type VizijRuntimeStatus = "loading" | "ready" | "error";
71
+ /** One face, as `VizijRuntimeProvider` hands it to its children. */
72
+ interface VizijRuntimeContextValue {
73
+ /** The id the face is loaded and shown under. */
74
+ vizijId: string;
75
+ /** `loading` until the face is drawn — its scene showing its device's
76
+ * pose — however long its GPU takes, and again while a new `glb` loads;
77
+ * `error` when loading failed. */
78
+ status: VizijRuntimeStatus;
79
+ error: Error | null;
80
+ /** The device's standing behavior error (`Runtime.behaviorError`): the
81
+ * message of its latest failed tick, `undefined` while healthy. */
82
+ behaviorError: string | undefined;
83
+ /** `@vizij/runtime`'s `Runtime` of the face, as it is: every device
84
+ * operation is called on it. `null` until the first load completes. */
85
+ runtime: Runtime | null;
86
+ /** `describe(glb)`: what the face's GLB declares — poses, rig inputs,
87
+ * programs, animations, metadata, bounds. `null` until read. */
88
+ description: VizijDescription | null;
89
+ }
336
90
 
91
+ /** The face of the nearest `VizijRuntimeProvider`; throws outside one. */
337
92
  declare function useVizijRuntime(): VizijRuntimeContextValue;
338
-
93
+ /** The face of the nearest `VizijRuntimeProvider`, or `null` outside one. */
339
94
  declare function useOptionalVizijRuntime(): VizijRuntimeContextValue | null;
340
-
341
- declare function useVizijOutputs(paths: string[]): Record<string, RawValue | undefined>;
342
-
343
- declare function useRigInput(path: string): [RawValue | undefined, (value: ValueJSON, shape?: ShapeJSON) => void];
344
-
345
- declare function resolveRuntimeUpdatePlan(previous: VizijAssetBundle | null, next: VizijAssetBundle, tier: RuntimeUpdateTier): RuntimeUpdatePlan;
346
-
347
- declare const POSE_WEIGHT_INPUT_PATH_PREFIX = "/poses/";
348
- declare const VISEME_POSE_KEYS: readonly ["a", "at", "b", "e", "e_2", "f", "i", "k", "m", "o", "o_2", "p", "r", "s", "t", "t_2", "u"];
349
- declare const EXPRESSIVE_EMOTION_POSE_KEYS: readonly ["concerned", "happy", "sad", "sleepy", "surprise"];
350
- declare const EMOTION_POSE_KEYS: readonly ["concerned", "happy", "neutral", "sad", "sleepy", "surprise", "angry"];
351
- type PoseSemanticKind = "emotion" | "viseme" | "other";
352
- declare function buildRigInputPath(faceId: string, path: string): string;
353
- declare function buildPoseWeightInputPathSegment(poseId: string | null | undefined): string;
354
- declare function buildPoseWeightRelativePath(poseId: string | null | undefined): string;
355
- declare function buildPoseWeightPathMap(poses: PoseDefinition[], faceId: string | null | undefined): Map<string, string>;
356
- declare function normalizePoseSemanticKey(value: string | null | undefined): string | null;
357
- declare function getPoseSemanticKey(pose: Pick<PoseDefinition, "id" | "name">): string | null;
358
- declare function resolvePoseMembership(pose: Pick<PoseDefinition, "group" | "groupId" | "groupIds">, groups: PoseGroupDefinition[] | undefined): {
359
- groupIds: string[];
360
- primaryGroupId: string | null;
361
- primaryGroupPath: string | null;
362
- groupPathsById: Record<string, string>;
363
- };
364
- declare function resolvePoseSemantics(pose: Pick<PoseDefinition, "id" | "name" | "group" | "groupId" | "groupIds">, groups: PoseGroupDefinition[] | undefined): {
365
- key: string | null;
366
- kind: PoseSemanticKind;
367
- membership: ReturnType<typeof resolvePoseMembership>;
368
- };
369
- declare function filterPosesBySemanticKind(poses: PoseDefinition[], groups: PoseGroupDefinition[] | undefined, kind: PoseSemanticKind): PoseDefinition[];
370
- declare function buildSemanticPoseWeightPathMap(poses: PoseDefinition[], groups: PoseGroupDefinition[] | undefined, faceId: string | null | undefined, kind: Exclude<PoseSemanticKind, "other">): Map<string, string>;
371
-
372
- type InputConstraint = {
373
- min?: number;
374
- max?: number;
375
- defaultValue?: number;
376
- };
377
- type FaceScalarControl = {
378
- path: string;
379
- min: number;
380
- max: number;
381
- defaultValue: number;
382
- };
383
- type ResolvedFaceControls = {
384
- faceId: string;
385
- gazeSource: "standard-vizij" | "standard" | "propsrig" | "coupled-gaze" | "none";
386
- blinkSource: "lids" | "blink" | "none";
387
- eyes: {
388
- leftX: FaceScalarControl | null;
389
- leftY: FaceScalarControl | null;
390
- rightX: FaceScalarControl | null;
391
- rightY: FaceScalarControl | null;
392
- };
393
- eyelids: {
394
- leftUpper: FaceScalarControl | null;
395
- rightUpper: FaceScalarControl | null;
396
- };
397
- blink: FaceScalarControl | null;
398
- };
399
- declare function resolveFaceControls(assetBundle: VizijAssetBundle, runtimeFaceId?: string | null, inputConstraints?: Record<string, InputConstraint>): ResolvedFaceControls;
400
- declare function mapNormalizedControlValue(control: FaceScalarControl, normalizedValue: number): number;
401
- declare function mapUnitControlValue(control: FaceScalarControl, unitValue: number): number;
402
-
403
95
  /**
404
- * Compose several Vizij graph specs into the ONE graph an Arora device runs.
405
- *
406
- * The device runs a single ProcessingGraph as its behavior, so the separate
407
- * graph sources become a union of nodes and edges here. Sources and their
408
- * provenance (see `graphSourcesRef` in VizijRuntimeProvider for details):
409
- * the **rig** graph shipped in the loaded GLB/asset bundle, the bundle's
410
- * **pose-driver** graph, and one source per **playing program** (bundle
411
- * programs and the authoring motiongraph, which publishes the editor's
412
- * graph as a program). Node ids
413
- * are prefixed `${sourceId}::` so sources can't collide; `params.path` is
414
- * deliberately NOT prefixed — path identity on the device's shared store is
415
- * the cross-graph contract (a pose output written to a store path is read by
416
- * a rig input node with the same path on the next tick).
417
- *
418
- * Output-path collisions across sources (two `output` nodes writing one
419
- * path) are warned and resolved last-writer-wins by evaluation order; there
420
- * is no additive merge for that case yet, and current bundles don't collide.
421
- * If a real bundle does, insert an explicit combiner node here instead of
422
- * widening this warning.
96
+ * Call `listener` with each batch of store changes the provider drains: at
97
+ * most once per animation frame, the first batch after a (re)load being the
98
+ * whole store. For a consumer that must not re-render per change — a
99
+ * sampler, a scrubber, a bridge to another system. The latest `listener` is
100
+ * called; it need not be stable.
423
101
  */
424
- type SpecRecord = Record<string, unknown>;
425
- /** A graph spec treated structurally (same tolerance as `utils/graph.ts`). */
426
- type ComposableSpec = SpecRecord;
427
- interface GraphSource {
428
- /** Stable id of the source graph (e.g. "rig", "pose", a program id). */
429
- sourceId: string;
430
- spec: ComposableSpec;
431
- }
102
+ declare function useVizijChanges(listener: (changes: VizijChanges) => void): void;
432
103
  /**
433
- * Union `sources` into one spec. Later sources evaluate after earlier ones,
434
- * so on an output-path collision the last source wins (warned).
104
+ * The current values of `paths` in the face's store — `null` for an unset
105
+ * key — re-rendering the component when one of them changes. Read from the
106
+ * runtime when it (re)loads, then kept current from the provider's batches.
435
107
  */
436
- declare function composeGraphSpecs(sources: GraphSource[]): ComposableSpec;
108
+ declare function useVizijValues(paths: string[]): Record<string, ValueJSON | null>;
437
109
 
438
- declare function collectInputPathMap(spec: GraphRegistrationConfig["spec"]): Record<string, string>;
439
-
440
- declare function resolveAnimationBridgeOutputPaths(channel: string, faceId?: string, rigInputMap?: Record<string, string>): string[];
110
+ type Easing = "linear" | "easeIn" | "easeOut" | "easeInOut" | ((t: number) => number);
111
+ interface AnimateValueOptions {
112
+ /** Seconds; default 0.35. `0` writes the target at once. */
113
+ duration?: number;
114
+ /** Default `linear`. */
115
+ easing?: Easing;
116
+ }
117
+ /**
118
+ * Animate a key of the face's store towards a number: a JS tween, one write
119
+ * per animation frame through `runtime.setValue`, eased, in the numeric kind
120
+ * the key holds (an `f32` key stays `f32`). A key nothing has written yet
121
+ * starts from the value the device lists it resting at. A newer tween on the
122
+ * same path replaces the running one; the component's tweens are cancelled
123
+ * when it unmounts, and a face's when it reloads. The promise resolves when
124
+ * the tween ends or is cancelled, and rejects when the key holds no number
125
+ * and rests at none.
126
+ */
127
+ declare function useAnimateValue(): {
128
+ animateValue(path: string, target: number, options?: AnimateValueOptions): Promise<void>;
129
+ cancelAnimation(path: string): void;
130
+ };
441
131
 
442
- export { type AnimateValueOptions, type AnimationClipLike, type AnimationKeyframeLike, type AnimationPlaybackState, type AnimationTrackLike, type ComposableSpec, EMOTION_POSE_KEYS, EXPRESSIVE_EMOTION_POSE_KEYS, type FaceScalarControl, type GraphSource, type InputDriverContext, type InputDriverFactory, type InputDriverLifecycle, POSE_WEIGHT_INPUT_PATH_PREFIX, type PlayAnimationOptions, type PoseDefinition, type PoseGroupDefinition, type PoseRigConfig, type ProgramPlaybackState, type RootBounds, type RuntimeGraphBundle, type RuntimeOutputWrite, type RuntimeUpdatePlan, type RuntimeUpdateTier, type StopProgramOptions, VISEME_POSE_KEYS, type VizijAnimationAsset, type VizijAssetBundle, type VizijGlbAsset, type VizijGraphAsset, type VizijProgramAsset, VizijRuntimeFace, type VizijRuntimeFaceProps, VizijRuntimeProvider, type VizijRuntimeProviderProps, type VizijRuntimeStatus, buildPoseWeightInputPathSegment, buildPoseWeightPathMap, buildPoseWeightRelativePath, buildRigInputPath, buildSemanticPoseWeightPathMap, collectInputPathMap, composeGraphSpecs, filterPosesBySemanticKind, getPoseSemanticKey, mapNormalizedControlValue, mapUnitControlValue, normalizePoseSemanticKey, resolveAnimationBridgeOutputPaths, resolveFaceControls, resolvePoseMembership, resolvePoseSemantics, resolveRuntimeUpdatePlan, useOptionalVizijRuntime, useRigInput, useVizijOutputs, useVizijRuntime };
132
+ export { type AnimateValueOptions, type Easing, type VizijChanges, type VizijRuntimeContextValue, VizijRuntimeFace, type VizijRuntimeFaceProps, VizijRuntimeProvider, type VizijRuntimeProviderProps, type VizijRuntimeStatus, type VizijSource, useAnimateValue, useOptionalVizijRuntime, useVizijChanges, useVizijRuntime, useVizijValues };