Skip to content
GitHubXDiscord

@triggery/signals

Read a signal from a Triggery condition without engaging signal-tracking on the host component. Compatible with @preact/signals-core, alien-signals, and any structurally-similar signal exposing peek() or .value.

npm bundle

pnpm add @triggery/core @triggery/react @triggery/signals @preact/signals-core

Peer deps: react >= 18.0.0. The signals library is your choice — @preact/signals-core and alien-signals both work.

ExportPurpose
useSignalCondition(trigger, name, signal, selector?)Register a signal-backed condition. Prefers peek(), falls back to .value.
import { signal } from '@preact/signals-core';
import { createTrigger } from '@triggery/core';
import { useSignalCondition } from '@triggery/signals';

const settings = signal({ sound: true, notifications: true });

const messageTrigger = createTrigger<{
  events: { 'new-message': { text: string } };
  conditions: { settings: { sound: boolean; notifications: boolean } };
  actions: { showToast: { body: string } };
}>({
  id: 'message-received',
  events: ['new-message'],
  required: ['settings'],
  handler({ event, conditions, actions }) {
    if (!conditions.settings.notifications) return;
    actions.showToast?.({ body: event.payload.text });
  },
});

function SettingsBridge() {
  useSignalCondition(messageTrigger, 'settings', settings);
  return null;
}

With a projection selector:

useSignalCondition(messageTrigger, 'settings', profile, (p) => p.settings);

Pull-only: the signal is read only when a trigger fires. The adapter prefers peek() (no dependency tracking) and falls back to .value if peek is missing. Either way, no subscriber is registered against the signal, so the host component never re-renders on signal updates.

If a component also needs to render the signal, use useSignal() from @preact/signals-react or the equivalent in your signal library — the two paths are orthogonal.

useSignalCondition<V, S, K>(
  trigger: Trigger<S>,
  name: K,
  signal: { peek?(): V; readonly value?: V },
  selector?: (value: V) => ConditionMap<S>[K],
): void