Lynx/Modules/Runtime/API reference
@sigx/lynx-runtime · Stable

API reference#

Every export of @sigx/lynx-runtime — the background-thread renderer, cross-thread primitives, gesture builders, and the JSX attribute types for native Lynx elements.

The package has three entry points: the default . entry documented below, the ./hmr subpath (initHMR, registerHMRModule), and ./mt-hmr-bridge (a dev-only side-effect module with no exports). All exports work on both iOS and Android — this is a pure TypeScript background-thread renderer with no native module directories of its own.

TypeScript
import * as Runtime from '@sigx/lynx-runtime';

Most apps import these names from @sigx/lynx, which re-exports the entire surface.

Renderer#

render#

The renderer's render() function, produced by createRenderer<ShadowElement, ShadowElement>(nodeOps). Renders a vnode tree into a ShadowElement root, emitting background-to-main ops as it goes.

TypeScript
const render: (
  vnode: VNode | null,
  container: ShadowElement,
  appContext?: AppContext,
) => void;

Parameters

  • vnode — the vnode tree to render, or null to clear the container.
  • container — the ShadowElement root to render into.
  • appContext — optional app context from @sigx/runtime-core.

Most apps mount via defineApp().mount() rather than calling render directly.

lynxMount#

The MountFn for Lynx environments. Creates the page root (id 1), renders and flushes synchronously, and returns an unmount function. A second call on the same root (hot reload) triggers a full card reload. Auto-registered as the default mount via setDefaultMount when the package is imported.

TypeScript
const lynxMount: MountFn;
// (element, _container, appContext) => () => void

Returns — an unmount function that tears down the rendered tree.

nodeOps#

The sigx RuntimeRenderer adapter: createElement / createText / createComment / setText / insert / remove / patchProp and the rest. Each method builds the ShadowElement tree and pushes ops into the op queue. References no Lynx native globals — it runs entirely on the background thread.

TypeScript
const nodeOps: RendererOptions<ShadowElement, ShadowElement>;

Shadow tree#

ShadowElement#

A lightweight doubly-linked tree node living entirely on the background thread. It lets the renderer query parentNode / nextSibling synchronously while the real Lynx elements exist only on the main thread. Id 1 is reserved for the page root; regular elements start at id 2.

TypeScript
class ShadowElement {
  static nextId: number;
  id: number;
  type: string;
  parent: ShadowElement | null;
  firstChild: ShadowElement | null;
  lastChild: ShadowElement | null;
  prev: ShadowElement | null;
  next: ShadowElement | null;
  _style: Record<string, unknown>;
  _vShowHidden: boolean;
  _baseClass: string;
  _transitionClasses: Set<string>;
  _lastInputValue: string | undefined;
  constructor(type: string, forceId?: number);
  insertBefore(child: ShadowElement, anchor: ShadowElement | null): void;
  removeChild(child: ShadowElement): void;
}

createPageRoot#

Creates the page-root ShadowElement with the reserved id 1 (type 'page'). The main thread creates the real page element before the background thread runs.

TypeScript
function createPageRoot(): ShadowElement;

Returns — the page-root ShadowElement.

resetShadowState#

Resets ShadowElement.nextId to 2. Testing only.

TypeScript
function resetShadowState(): void;

Op queue#

The op queue is the background-to-main wire protocol: a flat array of opcodes and arguments, serialized to JSON and shipped via callLepusMethod('sigxPatchUpdate', { data }).

pushOp#

Pushes one op (opcode plus args) into the background op buffer as a flat sequence, for example pushOp(OP.CREATE, id, type).

TypeScript
function pushOp(...args: unknown[]): void;

takeOps#

Takes all buffered ops and resets the buffer.

TypeScript
function takeOps(): unknown[];

Returns — the flat array of buffered ops.

scheduleFlush#

Schedules a flush of the ops buffer at the end of the current microtask, coalescing multiple calls within one tick into a single cross-thread call.

TypeScript
function scheduleFlush(): void;

flushNow#

Immediately flushes all buffered ops synchronously. Used on initial mount so the first frame commits without a microtask delay.

TypeScript
function flushNow(): void;

waitForFlush#

Resolves once the most recent ops batch has been applied on the main thread; resolves immediately when nothing is in flight.

TypeScript
function waitForFlush(): Promise<void>;

Acks are tracked per batch — each send closes over its own resolver — so with several batches in flight, an earlier batch's ack can never resolve a later batch's promise.

pendingOps#

The quiescence probe: true while ops are buffered awaiting their microtask flush, scheduled but unsent, or sent with the main-thread ack still outstanding. false means the main thread has applied everything the background thread has emitted so far.

TypeScript
function pendingOps(): boolean;

Callers that stage work behind a quiescence point poll this between waitForFlush() waits. That is exactly what @sigx/lynx-navigation's pre-staged transitions do — hold a push animation until the incoming screen's mount and post-mount flushes have all landed.

Bound your own wait. waitForFlush() settles only when the host acks the batch; a dropped ack leaves it unresolved forever. Race it against a budget rather than awaiting it bare.

resetOpQueue#

Resets op-queue module state (buffer, scheduled flag, pending acks). Testing only.

TypeScript
function resetOpQueue(): void;

OP#

The flat-array operation codes — the background-to-main wire protocol. JSON-serializable numeric opcodes, re-exported from @sigx/lynx-runtime-internal.

TypeScript
const OP = {
  CREATE: 0, CREATE_TEXT: 1, INSERT: 2, REMOVE: 3, SET_PROP: 4,
  SET_TEXT: 5, SET_EVENT: 6, REMOVE_EVENT: 7, SET_STYLE: 8, SET_CLASS: 9,
  SET_ID: 10, SET_WORKLET_EVENT: 11, SET_MT_REF: 12, INIT_MT_REF: 13,
  RELEASE_MT_REF: 14, REGISTER_AV_BRIDGE: 15, UNREGISTER_AV_BRIDGE: 16,
  REGISTER_AV_STYLE_BINDING: 17, UNREGISTER_AV_STYLE_BINDING: 18,
  SET_GESTURE_DETECTOR: 19, REMOVE_GESTURE_DETECTOR: 20, INVOKE_UI_METHOD: 21,
} as const;

Event registry#

These functions manage the background-side registry of event handlers. State lives on globalThis.__SIGX_LYNX_EVENT_REGISTRY__ (non-enumerable) so multiple module instances share handlers.

register#

Registers an event handler and returns a unique sign string ('sigx:N'). The sign is sent to the main thread via __AddEvent so the main-thread script can route events back.

TypeScript
function register(handler: (data: unknown) => void): string;

Returns — the unique sign string for the handler.

updateHandler#

Updates the handler for an existing sign without changing the sign. Used on re-renders to point a stable sign at the freshest closure.

TypeScript
function updateHandler(sign: string, handler: (data: unknown) => void): void;

unregister#

Unregisters a handler by its sign.

TypeScript
function unregister(sign: string): void;

getHandler#

Gets the current handler for a sign.

TypeScript
function getHandler(sign: string): ((data: unknown) => void) | undefined;

Returns — the handler, or undefined if no handler is registered for the sign.

publishEvent#

Called by Lynx Native when an event fires on the background thread; looks up the handler by sign and invokes it with the event data.

TypeScript
function publishEvent(sign: string, data: unknown): void;

resetRegistry#

Resets the sign counter and clears all handlers. Testing only.

TypeScript
function resetRegistry(): void;

Hooks#

useMainThreadRef#

Creates a MainThreadRef giving synchronous access to a native element on the main thread. Bind it with main-thread:ref={ref}. Pushes INIT_MT_REF on create and RELEASE_MT_REF on the owning component's onUnmounted.

TypeScript
function useMainThreadRef<T = unknown>(initValue: T): MainThreadRef<T>;

Parameters

  • initValue — the value .current holds on the background thread (typically null).

Returns — a MainThreadRef<T> whose .current resolves to the live native element inside main-thread handlers.

useElementLayout#

Reactive access to an element's measured layout via Lynx 3.7+ bindlayoutchange. Wire onLayoutChange to bindlayoutchange={...}. For <text> line metrics use bindlayout instead.

TypeScript
function useElementLayout(): UseElementLayoutResult;

Returns — a UseElementLayoutResult: a reactive layout signal and the onLayoutChange handler.

useViewportRect#

An element's live rect relative to the viewport, transforms included — the only correct input for deciding where an anchored surface (dropdown, suggestion popup, tooltip) fits.

TypeScript
function useViewportRect(): {
  ref: MainThreadRef<MainThread.Element | null>;
  rect: SharedValue<ViewportRect | null>;
  measure: () => void;
};
TSX
const { ref, rect, measure } = useViewportRect();

return () => (
  <view main-thread:ref={ref} bindlayoutchange={() => measure()}>

  </view>
);

Why not useElementLayout. bindlayoutchange reports layout-page coordinates. They are produced by layout, so they know nothing about what happens after it — main-thread transforms (a sheet riding the keyboard lift, a screen mid-transition), scroll offsets, or a position: fixed ancestor. A surface that flips against the screen from those numbers places itself against where its anchor would be if nothing had moved it: a suggestion popup decides there is no room above and flips down, behind the keyboard.

The rule. Layout events give you size and a "something moved, re-measure" signal. Screen-space geometry comes from here, and feeds only the flip/clamp decision — keep the surface positioned relative to its container so it rides along with the transform between measurements.

Cost. The measurement is an async UI-method call on the main thread, so the rect lands a frame or two after measure(), and rect.value is null until the first one arrives. Measure eagerly (when the surface is about to open), not in a render path, and render against the layout frame as the first-paint fallback.

measureViewportRect(el, apply) is the direct form, for main-thread handlers that already hold the element — a tap that opens a menu. On Android, androidEnableTransformProps is what makes the result transform-aware; iOS reports post-transform geometry either way.

useSharedValue#

Allocates a SharedValue<T> whose main-thread mutations are observable on the background thread via sigx reactivity. Pushes INIT_MT_REF and REGISTER_AV_BRIDGE on create; UNREGISTER_AV_BRIDGE, RELEASE_MT_REF, and drops the background signal on unmount.

TypeScript
function useSharedValue<T = number>(initial: T): SharedValue<T>;

Parameters

  • initial — the initial value.

Returns — a SharedValue<T>.

useAnimatedStyle#

Binds a MainThreadRef element's style to a SharedValue via a named built-in mapper. The main thread applies the mapper output via setStyleProperties on every flush boundary where the shared value changed — no per-frame thread crossing. The static form registers once at setup; the reactive (accessor) form re-binds when the returned spec's signature changes, with null meaning unbind.

TypeScript
function useAnimatedStyle<N extends BuiltinMapperName>(
  elRef: MainThreadRef<MainThread.Element | null>,
  sv: SharedValue<unknown>,
  mapperName: N,
  params?: MapperParams[N],
): void;
function useAnimatedStyle(
  elRef: MainThreadRef<MainThread.Element | null>,
  spec: () => AnimatedStyleSpec | null,
): void;

Parameters

  • elRef — the main-thread ref of the element to style.
  • sv — the shared value driving the style (static form).
  • mapperName — a BuiltinMapperName (static form).
  • params — mapper params for the chosen mapper (static form).
  • spec — an accessor returning an AnimatedStyleSpec or null (reactive form).

Note: the width and height mappers trigger a native layout pass per frame.

useAnimatedMethod#

The imperative sibling of useAnimatedStyle. Binds a MainThreadRef's element to a SharedValue and has the main-thread runtime invoke a named UI method on every flush boundary where the value changed — same dirty-diffing and derived-value ordering as a style binding, and no thread crossing per frame.

TypeScript
function useAnimatedMethod(
  elRef: MainThreadRef<MainThread.Element | null>,
  sv: SharedValue<unknown>,
  methodName: string,
  opts?: { valueKey?: string; params?: Record<string, unknown> },
): void;
function useAnimatedMethod(
  elRef: MainThreadRef<MainThread.Element | null>,
  spec: () => AnimatedMethodSpec | null,
): void;

interface AnimatedMethodSpec {
  sv: SharedValue<unknown>;
  methodName: string;                      // e.g. 'setBottomInset'
  valueKey?: string;                       // default 'value'
  params?: Record<string, unknown>;        // the SV value wins on collision
}

The runtime invokes methodName on the element with { ...params, [valueKey]: value }. The invoke happens in the same flush pass as style bindings and after derived values fold, so binding a useDerivedValue result sees the fresh folded value in the same frame.

Reach for it when per-frame state is natively backed and a style write cannot express it without a layout pass. The first consumer is <list>'s setBottomInset, behind the bottomInset prop.

Parameters

  • elRef — the main-thread ref of the element to invoke on.
  • sv — the shared value driving the invoke (static form).
  • methodName — the native UI method (static form).
  • opts.valueKey / opts.params — where the value is written and what is merged around it.
  • spec — an accessor returning an AnimatedMethodSpec or null (reactive form). Use it when the shared value only becomes available after mount — a bottom sheet handing out its reveal SV via a callback prop on first render.
TSX
useAnimatedMethod(listRef, () =>
  revealSV.value
    ? { sv: revealSV.value, methodName: 'setBottomInset',
        valueKey: 'inset', params: { pin: true } }
    : null,
);

Two behaviours differ from a style binding:

  • A method binding stays dirty while its element is unmounted or unresolved, and applies on a later flush. A style binding can tolerate a dropped frame because the next write re-applies — but a producer like the keyboard lift may settle once and never write again, and that value must not strand.
  • Failures are fire-and-forget. An element whose host widget does not know the method degrades to a no-op — which is how web hosts without the native subclass behave.

The wire ops are REGISTER_AV_METHOD_BINDING / UNREGISTER_AV_METHOD_BINDING.

useGestureDetector#

Attaches a gesture (or composed gesture) to the element pointed at by elRef. Walks composed gestures into unique base gestures; on onMounted pushes SET_GESTURE_DETECTOR per base (op emit is deferred so the SET_MT_REF op applies first); on onUnmounted pushes REMOVE_GESTURE_DETECTOR.

TypeScript
function useGestureDetector(
  elRef: MainThreadRef<unknown>,
  gesture: AnyGesture | { build(): BaseGesture },
): void;

Parameters

  • elRef — the main-thread ref of the element to attach to.
  • gesture — a gesture from Gesture, or any builder/descriptor.

Note: block-native-event / block-native-event-areas route through Lynx's bind-event path and bypass the gesture arena, so they do not compose with useGestureDetector.

useDerivedValue#

A SharedValue computed on the main thread from one or more source SVs via a named reducer, recomputed on each flush where a source changed. Bind it to useAnimatedStyle like any SV; read .value on the background thread as usual.

TypeScript
function useDerivedValue<R extends DerivedReducerName>(
  sources: ReadonlyArray<SharedValue<number>>,
  reducer: R,
  params?: DerivedReducerParams[R],
): SharedValue<number>;

Built-in reducers: max, min, sum, and scale (sources[0] * factor + offset). Register your own on the main thread with registerReducer from @sigx/lynx-runtime-main.

The canonical use is composing two motions so an element sits above whichever is taller — a chat composer bar over max(keyboardLift, sheetHeight):

TSX
const lift = useDerivedValue([keyboardLift, sheetHeight], 'max');
useAnimatedStyle(barRef, lift, 'translateY', { factor: -1 });

Two separate translateY bindings would sum — transform outputs concatenate — so this is not a convenience, it is the only correct shape. Scaling a 0..1 progress into px is the other common case:

TSX
const px = useDerivedValue([progress], 'scale', { factor: travelPx });

Why a name rather than a closure. The recompute runs in the main-thread flush loop, which is plain MT code — it cannot invoke a captured worklet by value. A name is a primitive the op layer ships trivially.

Treat the result as read-only. It is not frozen, but the derive owns the value: any write is overwritten on the next recompute. Drive it through its sources.

useDerivedValueReactive(accessor) is the variant for a runtime-reactive factor — the accessor runs in an effect and re-registers on the same derived SV when sources or params change, so consumers never rebind. Returning null holds the last registration.

useAnimatedValue#

Deprecated since Phase 2.8 — an alias of useSharedValue, kept for one minor cycle. Migrate to useSharedValue.

TypeScript
const useAnimatedValue: <T = number>(initial: T) => SharedValue<T>;

Cross-thread dispatch#

runOnMainThread#

A background-to-main one-shot. Pass a 'main thread' function (replaced by the build transform with a { _wkltId, _c? } placeholder); returns a callable that ships { wkltId, args, captured } via callLepusMethod('sigxRunOnMT') and resolves with the main-thread return value. If given a real function (the transform did not run), it runs locally on the background thread.

TypeScript
function runOnMainThread<TArgs extends unknown[]>(
  worklet: WorkletPlaceholder | ((...args: TArgs) => unknown),
): (...args: TArgs) => Promise<unknown>;

Returns — a callable that dispatches to the main thread and resolves with its return value.

runOnBackground#

A main-to-background dispatch handle. The SWC transform replaces runOnBackground(fn) inside a 'main thread' body at build time. On the main thread it delegates to globalThis.runOnBackground (installed by @sigx/lynx-runtime-main) when given a JsFnHandle. Calling it on a raw function outside a worklet throws — that means the build transform did not run.

TypeScript
function runOnBackground<R, Fn extends (...args: never[]) => R>(
  fn: Fn,
): (...args: Parameters<Fn>) => Promise<R>;

Returns — a callable that dispatches to the background thread and resolves with its return value.

Errors — throws if invoked on a raw function outside a worklet; wire up @sigx/lynx-plugin's worklet loader to fix.

transformToWorklet#

Wraps a background function as a serializable JsFnHandle ({ _jsFnId, _fn }) so the SWC transform can place it in the worklet context's _jsFn slot for main-to-background dispatch. Stamps fn.toJSON so JSON.stringify replaces the body with a placeholder. Returns { _jsFnId, _error } if not given a function.

TypeScript
function transformToWorklet(
  fn: (...args: unknown[]) => unknown,
): JsFnHandle;

Returns — a JsFnHandle descriptor.

resetThreading#

A no-op kept for API compatibility with older tests. The runOnBackground module now exposes its own reset via resetRunOnBackgroundState.

TypeScript
function resetThreading(): void;

resetRunOnBackgroundState#

Resets the runOnBackground exec-id map and lastJsFnId. Testing only.

TypeScript
function resetRunOnBackgroundState(): void;

Animated bridge#

These functions back the background side of the shared-value bridge. Most apps use useSharedValue and useAnimatedStyle rather than these directly.

registerBgSink#

Allocates (or returns the existing) background-side signal mirror for a wvid, so effect(() => sv.value) re-runs reactively on main-thread publishes. Idempotent per wvid — it doesn't reset the value, so it survives HMR re-registration.

TypeScript
function registerBgSink<T>(wvid: number, initial: T): PrimitiveSignal<T>;

Returns — the background-side PrimitiveSignal<T> for the wvid.

unregisterBgSink#

Drops the background-side signal for a wvid (on component unmount). Subsequent ingest entries for that wvid become no-ops.

TypeScript
function unregisterBgSink(wvid: number): void;

ingestAvPublishes#

Ingests a batch of [wvid, value] tuples from the main-thread bridge, writing each into the corresponding background signal. Tuples for unregistered wvids are silently dropped. Routed here from bg-bridge.ts on Lynx.Sigx.AvPublish.

TypeScript
function ingestAvPublishes(updates: Array<[number, unknown]>): void;

resetBgAvBridge#

Drops every registered background sink. Testing only.

TypeScript
function resetBgAvBridge(): void;

bgAvSinkCount#

Returns the number of currently registered background sinks. Test hook.

TypeScript
function bgAvSinkCount(): number;

Returns — the count of registered sinks.

resetWvidCounter#

Resets the worklet-variable-id counter (nextWvid) to 1. Testing only.

TypeScript
function resetWvidCounter(): void;

resetAnimatedStyleBindingIds#

Resets the animated-style binding-id counter to 1. Testing only.

TypeScript
function resetAnimatedStyleBindingIds(): void;

Gestures#

Gesture#

Chainable gesture builders and composers, mirroring the @lynx-js/react gesture API.

TypeScript
const Gesture: {
  Pan(): PanBuilder;
  Fling(): FlingBuilder;
  Tap(): TapBuilder;
  LongPress(): LongPressBuilder;
  Pinch(): PinchBuilder;
  Rotation(): RotationBuilder;
  Native(): NativeBuilder;
  Race(...gs: (AnyGesture | { build(): BaseGesture })[]): ComposedGesture;
  Simultaneous(...gs: (AnyGesture | { build(): BaseGesture })[]): ComposedGesture;
  Exclusive(...gs: (AnyGesture | { build(): BaseGesture })[]): ComposedGesture;
};

The builder factories return chainable builders (the builder classes themselves are not exported). Builders chain:

  • CallbacksonBegin / onStart / onUpdate / onEnd / onFinalize.
  • RelationswaitFor / simultaneousWith / continueWith.
  • Per-type configPanBuilder.axis / minDistance; FlingBuilder.minVelocity / direction; TapBuilder.numberOfTaps / maxDistance / maxDuration; LongPressBuilder.minDuration / maxDistance (and the deprecated LongPressBuilder.duration).

Composers combine gestures: Race (first wins, via mutual waitFor), Simultaneous (mutual simultaneousWith), and Exclusive (sequential waitFor).

Pass the result to useGestureDetector. Note: native iOS long-press reads the minDuration config key (default 500ms); LongPressBuilder.duration is deprecated and writes both duration and minDuration.

GestureType#

Gesture type enum; values match the upstream GestureTypeInner from @lynx-js/react.

TypeScript
const GestureType = {
  COMPOSED: -1, PAN: 0, FLING: 1, DEFAULT: 2, TAP: 3, LONGPRESS: 4,
  ROTATION: 5, PINCH: 6, NATIVE: 7,
} as const;

resetGestureIdCounter#

Resets the global gesture-id counter (nextGestureId) to 1. Testing only.

TypeScript
function resetGestureIdCounter(): void;

HMR#

These are exported from the ./hmr subpath, not the package root. They are designed to be injected by @sigx/lynx-plugin's HMR loader.

initHMR#

The HMR entry point. Installs the onDefine component plugin using the app-side registerComponentPlugin (from @sigx/lynx, ensuring a single shared plugin array). Idempotent. On an HMR update, re-runs setup for existing instances and patches them in place; the optional setCurrentInstanceFn mirrors the renderer's instance-stack push/pop so context-dependent hooks (like useNav) resolve.

TypeScript
// import { initHMR } from '@sigx/lynx-runtime/hmr';
function initHMR(
  registerComponentPlugin: RegisterFn,
  setCurrentInstanceFn?: SetCurrentInstanceFn,
): void;

registerHMRModule#

The HMR entry point. Registers the current module for HMR tracking and resets its per-module component index. Called at the top of each transformed module by the HMR loader.

TypeScript
// import { registerHMRModule } from '@sigx/lynx-runtime/hmr';
function registerHMRModule(moduleId: string): void;

Classes#

MainThreadRef#

A ref whose .current value is managed on the main thread. On the background thread .current is the init snapshot; in main-thread event handlers and runOnMainThread callbacks .current is the real Lynx element handle (setStyleProperties / animate / invoke). _wvid uniquely identifies it across threads.

TypeScript
class MainThreadRef<T = unknown> {
  readonly _wvid: number;
  readonly _initValue: T;
  current: T;
  constructor(initValue: T);
}

SharedValue#

A main-thread-writeable, background-readable cross-thread value with sigx reactive tracking. The main thread mutates sv.current.value = newValue inside 'main thread' worklets; the background thread reads sv.value (reactive). Background writes are read-only (dev mode warns). Extends MainThreadRef so serialization recognizes it as a worklet ref.

TypeScript
class SharedValue<T = number> extends MainThreadRef<SharedValueState<T>> {
  constructor(initial: T);
  get value(): T;
  set value(_v: T);
}

AnimatedValue#

Deprecated since Phase 2.8 — an alias of SharedValue, kept for one minor cycle. Migrate to SharedValue.

TypeScript
// class AnimatedValue<T = number> extends MainThreadRef<SharedValueState<T>>
export { SharedValue as AnimatedValue };

Types#

LynxNode#

Host-node type alias for the renderer.

TypeScript
type LynxNode = ShadowElement;

LynxElement#

Host-element type alias for the renderer.

TypeScript
type LynxElement = ShadowElement;

OpCode#

Union of the numeric op codes (021). Re-exported from @sigx/lynx-runtime-internal.

TypeScript
type OpCode = (typeof OP)[keyof typeof OP];

MainThread#

The MainThread namespace exporting Element — the native element handle available via MainThreadRef.current inside main-thread event handlers and worklets.

TypeScript
namespace MainThread {
  interface Element {
    setStyleProperties(styles: Record<string, string | number>): void;
    setStyleProperty(name: string, value: string | number): void;
    getComputedStyleProperty(name: string): string;
    animate(
      keyframes: unknown,
      options?: unknown,
    ): { play(): void; pause(): void; cancel(): void } | null;
    setAttribute(key: string, value: unknown): void;
    invoke(methodName: string, params?: Record<string, unknown>): Promise<unknown>;
  }
}

MapperParams#

The param shapes per built-in animated-style mapper name. Re-exported from @sigx/lynx-runtime-internal.

TypeScript
interface MapperParams {
  translateX: { factor?: number } | RangeParams;
  translateY: { factor?: number } | RangeParams;
  translate: { factorX?: number; factorY?: number };
  scale: { offset?: number } | RangeParams;
  scaleX: { offset?: number } | RangeParams;
  scaleY: { offset?: number } | RangeParams;
  opacity: { factor?: number; offset?: number } | RangeParams; // clamp01
  rotate: Record<string, never>;
  width: { factor?: number } | RangeParams; // triggers layout per frame
  height: { factor?: number } | RangeParams; // triggers layout per frame
  paddingTop: { factor?: number } | RangeParams;
  paddingRight: { factor?: number } | RangeParams;
  paddingBottom: { factor?: number } | RangeParams;
  paddingLeft: { factor?: number } | RangeParams;
  marginTop: { factor?: number } | RangeParams;
  marginRight: { factor?: number } | RangeParams;
  marginBottom: { factor?: number } | RangeParams;
  marginLeft: { factor?: number } | RangeParams;
}

RangeParams#

Range-mapping params (linear interpolation from an input domain to an output range), usable as an alternative param shape for translateX/translateY, scale, opacity, and so on. Re-exported from @sigx/lynx-runtime-internal.

TypeScript
interface RangeParams {
  inputRange: number[];
  outputRange: number[];
  extrapolate?: 'clamp' | 'identity';
}

BuiltinMapperName#

Union of the built-in mapper names. Re-exported from @sigx/lynx-runtime-internal.

TypeScript
type BuiltinMapperName = keyof MapperParams;

AnimatedStyleMapper#

The signature of an animated-style mapper function (value to style record). Re-exported from @sigx/lynx-runtime-internal.

TypeScript
type AnimatedStyleMapper<P = unknown> = (
  value: unknown,
  params?: P,
) => Record<string, string | number>;

AnimatedStyleSpec#

The reactive binding spec returned by the useAnimatedStyle accessor form; null means no binding.

TypeScript
interface AnimatedStyleSpec {
  sv: SharedValue<unknown>;
  mapperName: BuiltinMapperName;
  params?: MapperParams[BuiltinMapperName];
}

SharedValueState#

The internal envelope stored under MainThreadRef.current for a SharedValue; wrapping in { value } lets main-thread worklets mutate the value without breaking ref identity.

TypeScript
interface SharedValueState<T> {
  value: T;
}

AnimatedValueState#

Deprecated since Phase 2.8 — an alias of SharedValueState.

TypeScript
type AnimatedValueState = SharedValueState;

ElementLayout#

A measured element layout in CSS pixels (edges relative to the page).

TypeScript
interface ElementLayout {
  width: number;
  height: number;
  top: number;
  right: number;
  bottom: number;
  left: number;
}

LayoutChangeEvent#

The bindlayoutchange event payload. The modern cross-platform path is detail; the deprecated Android-only path is params.

TypeScript
interface LayoutChangeEvent {
  type?: string;
  detail?: {
    id?: string;
    width: number;
    height: number;
    top: number;
    right?: number;
    bottom?: number;
    left: number;
  };
  params?: {
    width: number;
    height: number;
    left: number;
    top: number;
    right: number;
    bottom: number;
  };
}

UseElementLayoutResult#

The return shape of useElementLayout: a reactive layout signal and the handler to wire on bindlayoutchange.

TypeScript
interface UseElementLayoutResult {
  layout: Signal<{ value: ElementLayout | null }>;
  onLayoutChange: (e: LayoutChangeEvent) => void;
}

GestureTypeValue#

Union of the GestureType numeric values (-17).

TypeScript
type GestureTypeValue = (typeof GestureType)[keyof typeof GestureType];

GestureWorklet#

The worklet placeholder shape emitted by @lynx-js/react/transform for gesture callbacks.

TypeScript
interface GestureWorklet {
  _wkltId: string;
  _c?: Record<string, unknown>;
  _jsFn?: Record<string, unknown>;
  _execId?: number;
  _workletType?: string;
}

GestureCallback#

The source-level gesture callback type: a 'main thread' arrow function the SWC transform replaces with a GestureWorklet placeholder.

TypeScript
type GestureCallback = GestureWorklet | ((event: never) => void);

BaseGesture#

The serialized single-recognizer gesture descriptor produced by a builder's build().

TypeScript
interface BaseGesture {
  __isSerialized: true;
  type: number;
  id: number;
  callbacks: Record<string, GestureWorklet>;
  waitFor: BaseGesture[];
  simultaneousWith: BaseGesture[];
  continueWith: BaseGesture[];
  config?: Record<string, unknown>;
}

ComposedGesture#

The serialized composed gesture (Race / Simultaneous / Exclusive) wrapping child gestures.

TypeScript
interface ComposedGesture {
  __isSerialized: true;
  type: -1;
  gestures: AnyGesture[];
}

AnyGesture#

Union of base and composed gesture descriptors.

TypeScript
type AnyGesture = BaseGesture | ComposedGesture;

LynxEventHandler#

A generic Lynx JSX event handler type.

TypeScript
type LynxEventHandler<E = any> = (event: E) => void;

JSX attribute types#

Importing @sigx/lynx-runtime augments JSX.IntrinsicElements with the native Lynx elements. These interfaces describe the attributes each element accepts. There is no [key: string]: any catch-all, so component prop excess-property checking stays intact (data-* and aria-* are still allowed via template-literal types).

LynxCommonAttributes#

Attributes shared by all Lynx elements: id / class / style / ref / key, accessibility props, focus and gesture blocking, bind*/catch* plus onX event aliases, and Main-Thread-Script attributes (main-thread:ref, main-thread-bind* / main-thread-catch* events).

TypeScript
interface LynxCommonAttributes {
  id?: string;
  class?: string;
  style?: unknown;
  ref?: unknown;
  key?: unknown;
  flatten?: boolean;
  'accessibility-label'?: string;
  'accessibility-role'?: string;
  'accessibility-element'?: boolean;
  'ignore-focus'?: boolean;
  'block-native-event'?: boolean;
  'block-native-event-areas'?: unknown;
  // bind*/catch* tap/longpress/touch*/layoutchange; onTap/onLongpress/onTouch*/onLayoutchange
  'main-thread:ref'?: MainThreadRef<MainThread.Element | null>;
  // main-thread-bind*/main-thread-catch* tap/touch*/longpress/scroll
}

ViewAttributes#

JSX attributes for <view>.

TypeScript
interface ViewAttributes extends LynxCommonAttributes {
  children?: any;
}

TextAttributes#

JSX attributes for <text> — line clamping, native text selection (Lynx 3.7+), and text-layout events.

TypeScript
interface TextAttributes extends LynxCommonAttributes {
  children?: any;
  'number-of-lines'?: number;
  'text-overflow'?: 'clip' | 'ellipsis';
  'text-selection'?: boolean;
  'custom-text-selection'?: boolean;
  'custom-context-menu'?: boolean;
  // bindselectionchange / bindlayout / onSelectionchange / onLayout
}

ImageAttributes#

JSX attributes for <image>.

TypeScript
interface ImageAttributes extends LynxCommonAttributes {
  src?: string;
  placeholder?: string;
  mode?: 'cover' | 'contain' | 'stretch' | 'center' | 'repeat' | 'aspectFit' | 'aspectFill';
  alt?: string;
  'lazy-load'?: boolean;
  'auto-size'?: boolean;
  // bindload / binderror / onLoad / onError
}

ScrollViewAttributes#

JSX attributes for <scroll-view>.

TypeScript
interface ScrollViewAttributes extends LynxCommonAttributes {
  children?: any;
  'scroll-orientation'?: string;
  'scroll-x'?: boolean;
  'scroll-y'?: boolean;
  'enable-scroll'?: boolean;
  'scroll-left'?: number;
  'scroll-top'?: number;
  'upper-threshold'?: number;
  'lower-threshold'?: number;
  bounces?: boolean;
  'show-scrollbar'?: boolean;
  'paging-enabled'?: boolean;
  // bindscroll / bindscrolltoupper / bindscrolltolower / onScroll / onScrolltoupper / onScrolltolower
}

ListAttributes#

JSX attributes for <list>. Native <list> only accepts <list-item> children — the renderer skips comment and text anchors inside a list.

TypeScript
interface ListAttributes extends LynxCommonAttributes {
  children?: any;
  'scroll-orientation'?: string;
  'span-count'?: number;
  'list-type'?: 'single' | 'flow' | 'waterfall';
  'item-snap'?: 'start' | 'center' | 'end' | 'none';
  'sticky-top'?: number;
  'sticky-bottom'?: number;
  // bindscroll / bindscrolltoupper / bindscrolltolower / onScroll / onScrolltoupper / onScrolltolower
}

ListItemAttributes#

JSX attributes for <list-item>. item-key must be unique among siblings for the native recycler.

TypeScript
interface ListItemAttributes extends LynxCommonAttributes {
  children?: any;
  'item-key'?: string;
  'item-type'?: string | number;
  'sticky-top'?: number;
  'sticky-bottom'?: number;
  'full-span'?: boolean;
}

InputAttributes#

JSX attributes for <input>, including the sigx two-way model directive (handled by the platform model processor).

TypeScript
interface InputAttributes extends LynxCommonAttributes {
  value?: string;
  placeholder?: string;
  type?: 'text' | 'number' | 'password' | 'digit' | 'idcard';
  maxlength?: number;
  disabled?: boolean;
  focus?: boolean;
  'confirm-type'?: 'send' | 'search' | 'next' | 'go' | 'done';
  model?: (() => string) | Model<string>;
  'onUpdate:modelValue'?: (value: string) => void;
  // bindinput / bindblur / bindfocus / bindconfirm / onInput / onBlur / onFocus / onConfirm
}

TextAreaAttributes#

JSX attributes for <textarea>, including the sigx model directive.

TypeScript
interface TextAreaAttributes extends LynxCommonAttributes {
  value?: string;
  placeholder?: string;
  maxlength?: number;
  disabled?: boolean;
  focus?: boolean;
  'auto-height'?: boolean;
  model?: (() => string) | Model<string>;
  'onUpdate:modelValue'?: (value: string) => void;
  // bindinput / bindblur / bindfocus / onInput / onBlur / onFocus
}

PageAttributes#

JSX attributes for <page>.

TypeScript
interface PageAttributes extends LynxCommonAttributes {
  children?: any;
}

SvgAttributes#

JSX attributes for <svg>. Pass raw SVG markup via content or a URL via src — the element does not accept JSX children.

TypeScript
interface SvgAttributes extends LynxCommonAttributes {
  content?: string;
  src?: string;
  width?: number | string;
  height?: number | string;
  viewBox?: string;
}

FilterImageAttributes#

JSX attributes for <filter-image>.

TypeScript
interface FilterImageAttributes extends LynxCommonAttributes {
  src?: string;
  filter?: unknown;
  mode?: 'cover' | 'contain' | 'stretch' | 'center';
  // bindload / binderror / onLoad / onError
}