# Signal-valued inputs

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

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

```tsx
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.

### Declared, shallow resolution

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>>`.

### Custom receivers

Use [`resolveSignalValue`](/reference/functions/resolve-signal-value/) at the declared
boundary of an ordinary custom component:

```tsx
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.

## API details from source

<span id="api-SignalValue"></span>

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

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

Related API: [SignalValue](/reference/types/signal-inputs/#signalvalue), [Signal](/reference/types/canvas-runtime/#signal).

### See also

[Signal](/reference/types/canvas-runtime/#signal)

[resolveSignalValue](/reference/functions/resolve-signal-value/)

[usePlayback](/reference/hooks/use-playback/)

[View source — packages/core/src/lib/signals/types.ts:55](/source/packages/core/src/lib/signals/types-ts/#L55)

## Implementation guidance for agents

Read the [Authoring, signals, and lifecycle companion](/agents/topics/lifecycle/) for ownership, adaptation, failure modes, and verification. [Agent start](/agents/) provides the version-selection workflow.

## Complete minimal examples

- [Read and update signals](/minimal-examples/lifecycle/signals/): Use writable, readonly, and computed values with synchronous batching. [Plain source](/minimal/lifecycle/signals.ts)
## Documentation version

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