Skip to content

Signal-valued inputs

Read as Markdown

Pibbl-provided components accept signals wherever reactive replacement is meaningful: drawing and layout geometry, style fields, text, animation inputs, and applicable official render-layer, Three.js, particles, physics, and visualization inputs. Plain values take the same direct path as before.

SignalValue<T> is T | Signal<T>. A receiving component resolves the input and therefore owns its dependency:

import {
Rectangle,
Text,
resolveSignalValue,
useSignal,
type SignalValue,
} from "@pibbl/core";
const left = useSignal(10);
const color = useSignal("red");
const label = useSignal("Current");
<Rectangle style={{ left, fill: color, width: 50, height: 50 }} />;
<Text>{label}</Text>;

Passing left.get() remains valid. That explicit read intentionally makes the enclosing component the consumer and passes a plain number downstream.

Resolution follows each component’s published input schema. Pibbl can resolve a whole-object signal such as style={styleSignal} or individual declared fields such as style={{ left: xSignal }}. Text and structural child grammars resolve signals encountered while walking their own declared arrays and finite iterables.

Pibbl never recursively searches arbitrary application data. A signal inside a dataset row, event payload, callback closure, custom metadata object, or nested descriptor is ordinary application data unless that exact descriptor schema explicitly opts into a shallow signal-valued field. A signal returned by another signal is not unwrapped again.

Event handlers and callbacks are selected as values and are not invoked by input resolution. APIs that intentionally require the signal object itself use an exact prop such as valueSignal: WritableSignal<T> rather than SignalValue<WritableSignal<T>>.

Use resolveSignalValue at the declared boundary of an ordinary custom component:

interface Point {
readonly x: number;
readonly y: number;
}
interface SeriesProps {
data: SignalValue<readonly Point[]>;
}
function drawSeries(data: readonly Point[]) {
return <Text>{data.length}</Text>;
}
function Series(props: SeriesProps) {
const data = resolveSignalValue(props.data);
return drawSeries(data);
}

The helper resolves exactly one plain-or-signal value. It performs no wrapper allocation and no deep inspection. Call it while the receiving component is evaluating so Pibbl attributes the dependency to that component.

Layout and pure measurement preserve the same ownership rule. Mounted layout prepasses transfer declared reads to the eventual receiving child; standalone measureElement() reads untracked and creates no persistent consumer.

A literal value or a signal supplying that value to a receiver-owned input.

type SignalValue<T> = T | Signal<T>

Related API: SignalValue, Signal.

Signal

resolveSignalValue

usePlayback

View source — packages/core/src/lib/signals/types.ts:55

Read the Authoring, signals, and lifecycle companion for ownership, adaptation, failure modes, and verification. Agent start provides the version-selection workflow.

Documentation built with @pibbl/core 0.0.2, revision 380919b. ALPHA — NOT FOR PRODUCTION USE.