Preact
Preact adapter — same API surface as React, built with preact/compat.
@stainless-code/preact-layers mirrors the React adapter API. The core is re-exported; every export name matches React except the package and peer.
Install
npm install @stainless-code/preact-layerspnpm add @stainless-code/preact-layersyarn add @stainless-code/preact-layersbun add @stainless-code/preact-layersPeer: preact >=10.19.0 (useSyncExternalStore via preact/compat)
Delta from React
| Topic | Preact |
|---|---|
| Package | @stainless-code/preact-layers |
| Peer | preact (not react) |
| JSX runtime | Built with h — no react/jsx-runtime dependency |
| API names | Identical — StackProvider, useLayerClient, useStack, useLayer, useLayerState, StackOutlet, StackSubscribe, useStackHandles, useMutationFlow, useLayerGroup, createStackHook |
Client
import { StackProvider, StackOutlet } from "@stainless-code/preact-layers";
function App() {
return (
<StackProvider>
<StackOutlet stack="confirm" />
</StackProvider>
);
}
Confirm dialog
import {
layerOptions,
useLayer,
type LayerComponentProps,
} from "@stainless-code/preact-layers";
type ConfirmPayload = { title: string };
type ConfirmResponse = boolean;
function ConfirmDialog({
call,
payload,
}: LayerComponentProps<ConfirmPayload, ConfirmResponse>) {
return (
<div role="dialog">
<h2>{payload.title}</h2>
<button onClick={() => void call.end(true)}>Yes</button>
<button onClick={() => void call.end(false)}>No</button>
</div>
);
}
const confirm = layerOptions<ConfirmPayload, ConfirmResponse>({
stack: "confirm",
key: ["confirm", "remove"],
component: ConfirmDialog,
});
function RemoveButton() {
const c = useLayer(confirm);
return (
<button
onClick={() => void c.open({ title: "Remove item?" })}
>
Remove
</button>
);
}import {
layerOptions,
useLayer,
} from "@stainless-code/preact-layers";
function ConfirmDialog({
call,
payload,
}) {
return (
<div role="dialog">
<h2>{payload.title}</h2>
<button onClick={() => void call.end(true)}>Yes</button>
<button onClick={() => void call.end(false)}>No</button>
</div>
);
}
const confirm = layerOptions({
stack: "confirm",
key: ["confirm", "remove"],
component: ConfirmDialog,
});
function RemoveButton() {
const c = useLayer(confirm);
return (
<button
onClick={() => void c.open({ title: "Remove item?" })}
>
Remove
</button>
);
}Primitives
Same options-bag contract as React — useStack({ stack, select, compare }), useLayer(options) to drive, useLayerState({ key, stack, … }) to observe.
Ergonomic APIs
Same as React — see React for useStackHandles, StackSubscribe, useMutationFlow, useLayerGroup, and createStackHook.