API reference
Every public export of @pocketjs/core, grouped by import path. Signatures are TypeScript-style; defaults are noted in parentheses. For conceptual walkthroughs see Components, Reactivity, Animation, and Input & focus.
| Import path | Exports |
|---|---|
@pocketjs/core |
mount, render, host/runtime helpers, types |
@pocketjs/core/components |
View, Text, Image, Show, For, Index, Switch, Match, Screen, Focusable, FocusScope, FocusGrid, ActionHandler, Portal, Modal, ActionBar |
@pocketjs/core/reactivity |
createSignal, createEffect, createMemo, onMount, onCleanup, batch, untrack |
@pocketjs/core/animation |
animate, spring, cancelAnim |
@pocketjs/core/hooks |
useFrame, useButtonPress, useSpriteAnimation, pushButtonHandlerBlock |
@pocketjs/core/input |
BTN, focusNode, getFocused, pushFocusScope, pushFocusGrid |
@pocketjs/core
The runtime entry point: mount an app, tear it down, and reach the lower-level host, sweep, style, and pack utilities.
mount
function mount(code: () => unknown, opts?: MountOptions): () => voidApp-level entry point for demo/application bundles. Resolves ops from opts.ops or globalThis.ui, loads opts.dcpak (when given), uploads the pack's images on injected hosts, feeds the default generated style table (opts.styles ?? STYLE_IDS), and mounts code. Returns a disposer that unmounts and destroys the app subtree. Throws if neither opts.ops nor globalThis.ui is present.
render
function render(code: () => unknown, opts?: RenderOptions): () => voidLower-level mount: detects and installs the host, wires the style resolver, registers opts.styles, feeds styles/atlases from the pack on injected hosts, builds the app + overlay layers, installs the per-frame handler, and mounts code. Returns a disposer. mount calls render; call render directly when you supply your own ops/styles.
RenderOptions / MountOptions
MountOptions is an alias of RenderOptions.
| Field | Type | Description |
|---|---|---|
ops |
HostOps |
web/wasm/test hosts inject their op surface here; omit on PSP (globalThis.ui). |
styles |
Record<string, number> |
class-literal → styleId table (styles.generated.ts). |
dcpak |
ArrayBuffer |
app pack; defaults to globalThis.__dcpak when present. |
Host helpers
function detectHost(injected?: HostOps): Host
function installHost(host: Host): void
function getOps(): HostOpsdetectHost resolves the active host — injected ops win, otherwise globalThis.ui (PSP/QuickJS); throws when neither exists. installHost sets the active host (called by render). getOps returns the installed op surface. See Native contract for the full HostOps surface.
HostOps
The synchronous ui.* op surface. Handles are generation-tagged positive i32 ids; 0 means "none". Each op is documented in full on the Native contract page; the summary:
| Op | Signature | Purpose |
|---|---|---|
createNode |
(type: number) => number |
New node (spec NODE_TYPE) → id. |
destroyNode |
(id: number) => void |
Destroy subtree; free anim tracks; clear focus. |
insertBefore |
(parent, child, anchorOr0) => void |
Move/insert; anchor 0 = append. |
removeChild |
(parent, child) => void |
Detach but keep the node alive. |
setStyle |
(id, styleId) => void |
Apply a compiled style; -1 clears. |
setProp |
(id, propId, value) => void |
Set one spec PROP. |
setText / replaceText |
(id, str) => void |
Text-node content. |
uploadTexture |
(buf, w, h, psm) => number |
Upload a pow2 image (≤512) → handle. |
setImage |
(id, texHandle) => void |
Bind an image; <0 clears. |
animate |
(id, propId, to, durMs, easing, delayMs) => number |
Start a tween → animId. |
cancelAnim |
(animId) => void |
Stop a tween. |
setFocus |
(idOr0) => void |
Focus a node; 0 clears. |
loadStyles |
(buf) => void |
web/test only — feed the style table. |
loadFontAtlas |
(buf) => void |
web/test only — feed one baked atlas. |
measureText |
(str, fontSlot) => number |
Measured width in px. |
Host
interface Host {
ops: HostOps;
kind: "psp" | "injected";
strict: boolean;
}strict hosts (web/wasm/test) throw on an unknown class or texture; the PSP host is non-strict and counts silently (see missCounters).
End-of-frame sweep
function retain(node: NodeMirror): void
function release(node: NodeMirror): void
function runSweep(): voidretain keeps a detached subtree alive across frames (skips the sweep); release undoes it so a still-detached node re-enters the next sweep. runSweep destroys every subtree removed during the frame and still detached — the runtime already calls it once per frame after user code and input, so remove-then-reinsert (Solid moves) never destroys live nodes. Reach for these only when hand-managing detached subtrees.
registerTexture
function registerTexture(key: string, handle: number): voidBind an image key (the src string) to an uploadTexture handle so <Image src="key"> resolves through the renderer's texture registry.
missCounters
const missCounters: { unknownClass: number; unknownTexture: number }On the non-strict PSP host, an unknown class or texture increments a counter instead of throwing. Read it to diagnose missing styles/images without crashing hardware.
Styles
function registerStyles(table: Record<string, number>): void
function resolveStyle(cls: string): number | undefinedregisterStyles loads a class-literal → styleId table (the compiler's STYLE_IDS); it also registers a token-sorted alias so "a b" resolves the id for "b a". resolveStyle returns the styleId for a class string, or undefined if the compiler never saw it (or the token reordering is ambiguous). See Styling and Tailwind subset.
Data pack (dcpak)
function dcpakEntries(prefix?: string): string[]
function dcpakGet(key: string): Uint8Array
function loadPack(ab: ArrayBuffer): void
function resetPack(): voiddcpakEntries lists entry keys starting with prefix (default: all keys), sorted. dcpakGet returns a fresh copy of a blob's bytes, throwing on a missing key. loadPack explicitly loads a pack (web host after fetch, or tests), replacing any prior. resetPack drops the cached parsed pack. See Build pipeline.
NodeMirror
interface NodeMirror {
id: number; // native generation-tagged node id
type: number; // spec NODE_TYPE ordinal
parent: NodeMirror | null;
children: NodeMirror[];
text?: string; // text nodes only
focusable?: boolean; // focus traversal membership
onPress?: (() => void) | undefined; // CIRCLE handler while focused
}The JS mirror of a native node. A ref receives one; animate, spring, focusNode, pushFocusScope, and pushFocusGrid all accept one.
@pocketjs/core/components
Platform primitives and higher-level components. Control-flow components (Show, For, Index, Switch, Match) are re-exported from Solid unchanged.
Primitives
function View(props: ViewProps): JSX.Element
function Text(props: TextProps): JSX.Element
function Image(props: ImageProps): JSX.ElementThe three host tags, wrapped React Native-style. View is the flex container/box, Text renders baked-font text, Image draws an uploaded texture by src key.
ViewProps
| Prop | Type | Description |
|---|---|---|
class |
string |
Tailwind-subset class literal. |
style |
Record<string, number | string> |
Inline spec props (escape hatch). |
onPress |
() => void |
Fired on CIRCLE while focused. |
focusable |
boolean |
Joins d-pad focus traversal. |
ref |
(node: NodeMirror) => void | NodeMirror |
Node handle. |
children |
JSX.Element |
Child nodes. |
TextProps — class, style, ref, children.
ImageProps — class, src (string), style, ref.
Screen
function Screen(props: ScreenProps): JSX.Element // ScreenProps extends ViewPropsA full-screen root View. Defaults class to "relative flex-col w-full h-full bg-slate-50 overflow-hidden" when none is given.
Focusable
interface FocusableProps extends ViewProps { onPress?: () => void }
function Focusable(props: FocusableProps): JSX.ElementA View with focusable: true. Use onPress for the CIRCLE action.
FocusScope
interface FocusScopeProps extends ViewProps, FocusScopeOptions {
active?: boolean | (() => boolean);
}
function FocusScope(props: FocusScopeProps): JSX.ElementRestricts d-pad traversal and CIRCLE to its subtree while active (default true). Adds autoFocus / restoreFocus from FocusScopeOptions. Internally pushes/pops via pushFocusScope.
FocusGrid
interface FocusGridProps extends ViewProps, FocusGridOptions {
active?: boolean | (() => boolean);
}
function FocusGrid(props: FocusGridProps): JSX.ElementGives its subtree row/column d-pad semantics while active. Requires columns; wrap (default false) wraps at row ends. Internally pushes/pops via pushFocusGrid.
ActionHandler
interface ActionHandlerProps extends ButtonPressOptions {
button: number; // BTN mask
onPress: (pressed: number, buttons: number) => void;
children?: JSX.Element;
}
function ActionHandler(props: ActionHandlerProps): JSX.ElementDeclarative wrapper over useButtonPress: fires onPress on the button edge. Inherits allowWhenBlocked and active from ButtonPressOptions. Renders children (or nothing).
Portal
interface PortalProps { children?: JSX.Element | (() => JSX.Element) }
function Portal(props: PortalProps): JSX.ElementRenders children into the full-screen overlay root (above the app layer, zIndex 1000) instead of the local tree. Cleans up its host node on unmount.
Modal
interface ModalProps {
class?: string;
panelClass?: string;
open?: boolean | (() => boolean);
children?: JSX.Element;
}
function Modal(props: ModalProps): JSX.ElementA portalled backdrop + focus-scoped panel. While open, it blocks background button handlers (pushButtonHandlerBlock) and fades/scales the panel in. class styles the centering frame; panelClass styles the panel.
ActionBar
function ActionBar(props: ActionBarProps): JSX.Element // ActionBarProps extends ViewPropsA portalled bottom bar. Defaults to a pinned left-3 right-3 bottom-3 row when no class is given.
Control flow (re-exported from Solid)
| Component | Usage | Purpose |
|---|---|---|
Show |
<Show when={cond} fallback={…}>…</Show> |
Conditional render. |
For |
<For each={list}>{(item, i) => …}</For> |
List keyed by reference. |
Index |
<Index each={list}>{(item, i) => …}</Index> |
List keyed by index. |
Switch / Match |
<Switch fallback={…}><Match when={c}>…</Match></Switch> |
Multi-branch. |
See the Solid control-flow docs for full prop shapes; behavior is unchanged.
@pocketjs/core/reactivity
Solid's reactivity, re-exported unchanged. Full docs live at solidjs.com; summary below.
| Export | Signature | Purpose |
|---|---|---|
createSignal |
createSignal<T>(value?, opts?) => [get: () => T, set: (v) => T] |
Reactive atom. |
createEffect |
createEffect(fn: (prev) => T, value?) => void |
Run on dependency change. |
createMemo |
createMemo(fn: (prev) => T, value?) => () => T |
Cached derived value. |
onMount |
onMount(fn: () => void) => void |
Run once after first render. |
onCleanup |
onCleanup(fn: () => void) => void |
Run on owner disposal. |
batch |
batch(fn: () => T) => T |
Coalesce updates. |
untrack |
untrack(fn: () => T) => T |
Read without tracking. |
See Reactivity.
@pocketjs/core/animation
Typed motion over ops.animate. JS declares the tween once; the Rust core ticks it per vblank at a fixed dt = 1/60 s. prop is a spec PROP name and must be animatable (e.g. opacity, translateY, scale, and color props) — non-animatable props throw. See Animation.
animate
function animate(
node: NodeMirror | number,
prop: PropName,
to: number | string,
opts?: AnimateOptions,
): number // returns animIdTweens prop from its current value to to. For color props, to is a packed u32 ABGR or a '#rrggbb' / '#rrggbbaa' string. Returns an animId for cancelAnim.
AnimateOptions
| Field | Type | Default | Description |
|---|---|---|---|
dur |
number |
200 |
Duration in ms (ignored by spring easings). |
easing |
EasingName | number |
"out" |
Named easing or raw ENUMS.Easing ordinal. |
delay |
number |
0 |
Delay in ms before the tween starts. |
EasingName — "linear" | "in" | "out" | "in-out" | "out-back" | "spring" | "spring-bouncy".
spring
function spring(
node: NodeMirror | number,
prop: PropName,
to: number | string,
preset?: "default" | "bouncy",
): numberSprings prop to to; duration comes from the physics, not a timer. preset (default "default") selects the base or bouncy spring. Returns an animId.
cancelAnim
function cancelAnim(animId: number): voidStops a running animation by the id animate/spring returned.
@pocketjs/core/hooks
Component-scoped per-frame hooks. Each cleans up on owner disposal via onCleanup. See Reactivity and Input & focus.
useFrame
function useFrame(callback: (buttons: number) => void): voidRegisters callback to run once per host frame with the current spec BTN bitmask.
useButtonPress
function useButtonPress(
mask: number,
callback: (pressed: number, buttons: number) => void,
opts?: ButtonPressOptions,
): voidEdge-detects a button: fires callback on the frame a button in mask transitions from up to down. pressed is the just-pressed bitmask; buttons is the full held mask.
ButtonPressOptions
| Field | Type | Default | Description |
|---|---|---|---|
allowWhenBlocked |
boolean |
false |
Keep firing while a modal/system block owns input. |
active |
boolean | (() => boolean) |
true |
Gate the handler on/off. |
useSpriteAnimation
function useSpriteAnimation(
frames: readonly string[],
opts?: SpriteAnimationOptions,
): Accessor<string>Cycles through frames (image src keys), returning an accessor for the current frame. Throws if frames is empty. opts.frameStep (default 1, min 1) holds each sprite frame for that many host frames.
pushButtonHandlerBlock
function pushButtonHandlerBlock(): () => voidPushes a global block so background useButtonPress handlers (those without allowWhenBlocked) stop firing; the returned disposer pops it. Modal uses this internally.
@pocketjs/core/input
Programmatic focus, the button bitmask, and the imperative focus-scope/grid stack. Prefer the FocusScope / FocusGrid components in app code. See Input & focus.
BTN
PSP button bitmask (identical on every host; web/Bun hosts remap keys).
| Member | Value | Member | Value |
|---|---|---|---|
SELECT |
0x0001 |
LTRIGGER |
0x0100 |
START |
0x0008 |
RTRIGGER |
0x0200 |
UP |
0x0010 |
TRIANGLE |
0x1000 |
RIGHT |
0x0020 |
CIRCLE |
0x2000 |
DOWN |
0x0040 |
CROSS |
0x4000 |
LEFT |
0x0080 |
SQUARE |
0x8000 |
focusNode
function focusNode(node: NodeMirror | null): voidProgrammatically focus a node (or clear focus with null). Applies the native focus: style variant.
getFocused
function getFocused(): NodeMirror | nullReturns the currently focused node, or null.
pushFocusScope
function pushFocusScope(node: NodeMirror, opts?: FocusScopeOptions): () => voidRestricts d-pad traversal and CIRCLE to node's subtree; returns a disposer that pops the scope and restores prior focus. Backs the FocusScope component.
FocusScopeOptions
| Field | Type | Default | Description |
|---|---|---|---|
autoFocus |
boolean |
true |
Focus the first focusable on push. |
restoreFocus |
boolean |
true |
Restore the previously focused node on pop. |
pushFocusGrid
function pushFocusGrid(node: NodeMirror, opts: FocusGridOptions): () => voidGives node's subtree row/column d-pad semantics; returns a disposer that pops the grid. Backs the FocusGrid component.
FocusGridOptions
| Field | Type | Default | Description |
|---|---|---|---|
columns |
number |
— | Grid column count (min 1). Required. |
wrap |
boolean |
false |
Wrap focus at row ends. |
Try any of these live in the playground, or start from Getting started.