vizij
v0.1.0
Published
Higher-level visualization and interaction components for robot and ai faces.
Readme
vizij
Higher-level visualization and interaction primitives for face/screen/group renderables. Sibling of @semio/scene; shares the same value-flow model.
Stores and contexts
vizij separates two concerns:
- Vizij structure — what exists in the world: animatable definitions, world tree, materials, slot config. Lives in a Zustand store, accessed via
VizijContext+useVizijStore. - Runtime values — the current value of every animatable. Lives in
useValuesStore(re-exported from@semio/utils). Read withuseValuesStore; write withuseValuesStore.getState().updateValues(...).
Render hooks (useFeatures) subscribe to useValuesStore directly. The vizij store does not own runtime values.
VizijValueWriterContext
vizij has no built-in gizmos that drive animatable values today, but the override seam is wired up so that adding one is a one-step change. The pattern mirrors @semio/scene's SceneValueWriterContext:
- The default writer hits
useValuesStore.updateValues(...)directly — correct for standalone consumers. - Host apps can override via
<VizijValueWriterContext.Provider>to add semantics. Studio does this inapps/studio/src/providers/studio.tsxto route writes through its animation-awaresetValueAction, producing keypoint updates in animation mode with a matching track and direct writes otherwise. The same writer instance is supplied to bothSceneValueWriterContextandVizijValueWriterContext.
Adding a gizmo that writes values
Use the hook; do not import useValuesStore directly from the gizmo:
import { useVizijValueWriter } from "vizij";
function MyVizijGizmo({ animatableId, namespace }) {
const { setValue } = useVizijValueWriter();
return (
<SomeDraggableThing
onChange={(next) => setValue(animatableId, namespace, next)}
/>
);
}This keeps the gizmo agnostic to whether it's running standalone or under a host that wants to intercept writes. The default writer is provided automatically — no Provider is required for the hook to return a usable value.
Override (host app)
import { useMemo } from "react";
import {
VizijContext,
VizijValueWriterContext,
type VizijValueWriter,
} from "vizij";
function HostProvider({ store, children }) {
const valueWriter = useMemo<VizijValueWriter>(
() => ({
setValue: (animatableId, namespace, value) =>
store.getState().setValue(animatableId, namespace, value),
}),
[store],
);
return (
<VizijContext.Provider value={store}>
<VizijValueWriterContext.Provider value={valueWriter}>
{children}
</VizijValueWriterContext.Provider>
</VizijContext.Provider>
);
}The writer is responsible for ensuring the value reaches useValuesStore — direct, batched, transformed, or routed through any other system the host needs.
Key APIs
| Export | Purpose |
|---|---|
| VizijContext | React context holding the vizij Zustand store. |
| useVizijStore(selector) | Subscribe to the vizij store. |
| createVizijStore(initial?) | Create an isolated vizij store. |
| useFeatures | Subscribe to runtime values for a feature. |
| VizijValueWriterContext | Override the gizmo value-write behavior. |
| useVizijValueWriter() | Read the current writer (returns the default if no Provider). |
| VizijValueWriter (type) | The writer interface: { setValue(id, namespace, value) }. |
Runtime values themselves (useValuesStore, mergeValueMaps) live in @semio/utils and are re-exported through @semio/animation.
