export { A as AttrSpec, a as attr } from './attrSelector-Cmu2ZoGO.js'; export { D as DelegateOptions, d as delegate, a as delegateCapture } from './delegate-CL9VTZFb.js'; import { ArraySignal } from './array-signal.js'; import { SafeHtml } from './jsx-runtime.js'; export { Fragment, isSafeHtml, raw } from './jsx-runtime.js'; export { M as MountResult, m as mount } from './mount-Bo2qOx25.js'; import { Signal } from '@preact/signals-core'; export { ReadonlySignal, Signal, batch, computed } from '@preact/signals-core'; export { S as Store, d as defineStore, r as resetAllStores } from './testing-DNEY7wi3.js'; import './bindings-CYwoJpQb.js'; /** * Re-exports of `@preact/signals-core`. Lets the rest of the codebase depend * on `'./reactive.js'` without naming the underlying lib, so swapping it out * later (or fronting it with a hand-rolled implementation) is a one-file * change. * * Two dev hook slots sit in front of the bare re-exports: * * - `signalFactory` replaces the constructor so writes to never-subscribed * signals can warn (`KERF_DEV_WARN_UNTRACKED_SIGNALS=1`). * * - `wrapEffect` wraps the user body so `delegate()` can detect that it's * running inside an effect (`KERF_DEV_WARN_DELEGATE_IN_EFFECT=1`). * * Both are `undefined` unless the consumer imported `kerfjs/dev`, so production * sees the bare `@preact/signals-core` exports behind one property read. * * ORDERING: `signalFactory` is resolved at signal-CREATION time, so signals * created before `kerfjs/dev` is installed stay plain and the untracked-signal * warning never sees them. Static imports hoist above a `await import()`, so a * module-scope signal in an imported module is created first. See * docs/11-dev-warnings.md for the install-ordering rules. */ declare function signal(value?: T): Signal; declare function effect(fn: () => void | (() => void)): () => void; /** * `each(items, render, cacheKey?)` — keyed list iteration with per-item memoization. * * Drops in as the body of a list-rendering JSX expression inside a `mount()` * render function. Returns a `SafeHtml` carrying a structured list segment, * so `mount()` can run a native keyed reconciler instead of the general- * purpose morph for these children. * * Two layers of optimization: * * 1. Per-item memoization. `render(item)` is skipped for items whose object * identity (and optional `cacheKey`) are unchanged since the previous * call. Their HTML strings come from a `WeakMap` keyed by item reference. * The immutable-update style ("replace the row object" instead of "mutate * it") is the idiomatic way to invalidate a row and is what the memo is * built around. A same-ref `arraySignal.update()` (mutate the object and * return it) also works — it bumps a per-item content version (KF-418, * `item-version.ts`) that the memo checks — so it re-renders the row in * every consumer, not just the list that drained the patch. * * 2. Structural handoff. `mount()` recognizes the list segment and bypasses * the parse-the-whole-table round trip: only fresh items get parsed (one * at a time, into the smallest detached element), and only changed rows * get patched in the live DOM. Unchanged rows are physically the same * nodes they were before — never visited. * * `cacheKey` is a passive comparator — it covers the case where external * state, not the item itself, drives what the row should render (e.g. a * "currently selected" id flips a CSS class on one row). Same item identity * but a different `cacheKey` return value means "the cached HTML is stale — * re-render this row." Not a reactive subscription: it's evaluated once per * mount-effect run and compared against the previous run's return value. If * you don't pass `cacheKey`, only object-identity changes invalidate the * cache. (Renamed from `key` for clarity — it shared a name with React's * `key` prop but has different semantics; the new name says what the * parameter actually does. Positional callers — the canonical form — are * unaffected.) * * Items must be objects (cache is a `WeakMap`); wrap primitives if you need * to iterate them. Each item's render output must produce exactly one * top-level element — the list reconciler binds one live DOM node per item. */ /** * Options for `each()`. Supplied in place of the bare `cacheKey` third * argument, which remains supported. */ interface EachOptions { /** * Passive per-item comparator — the same value the bare third argument * takes. Invalidates an item's cached HTML when external state changes what * the row should render. */ cacheKey?: (item: T, index: number) => unknown; /** * A stable identity for THIS list, unique within the mount. * * Without one, a list is identified by its call order ("the n-th `each()` * this render"), so any render that changes how many `each()` calls run * before it reassigns its identity — and the list is rebuilt from scratch, * losing row nodes, focus, scroll position and in-progress IME. Give a key * to any list that can be preceded by a conditional list. * * Keyed lists also do not consume a call-order slot, so keying a * *conditional* list additionally stabilizes its unkeyed siblings. */ key?: string; } declare function each(items: readonly T[] | ArraySignal, render: (item: T, index: number) => SafeHtml | string, cacheKey?: (item: T, index: number) => unknown): SafeHtml; declare function each(items: readonly T[] | ArraySignal, render: (item: T, index: number) => SafeHtml | string, options?: EachOptions): SafeHtml; /** * `morph(liveRoot, template)` — minimum-mutation DOM reconciliation. * * Public primitive (KF-150): one-shot reconciliation against an * already-populated element. `mount()` first paints by writing * `innerHTML`; `morph()` is the "I have a live tree and a template, * reconcile them in place" sibling. Use it for SSR hydration of static * fragments, page-refresh diffs, third-party widget remounts, etc. * * Replaces our previous dependency on `morphdom`. The algorithm is the * classic two-tree walk: match children by key (id, then data-key, then * positional same-tag), morph matches in place, insert / remove / clone * the rest. Specialized for what kerf needs: * * - `childrenOnly` is always true; the live root is never replaced. * - Per-element short-circuits: `data-morph-skip` (library-owned, leave * element AND subtree verbatim), `data-morph-skip-children` (KF-152 — * morph attrs on the element, leave its subtree verbatim — for * client-hydrated slots whose loading/state classes still need to flow * through), and `isEqualNode` (byte-identical, no work needed). * - **`data-morph-preserve`** protects a node at ITS OWN level only — an * ancestor the template drops still takes the whole subtree, preserved * descendants included (KF-386: intended, but easy to over-read, so it is * pinned by tests and stated in docs/4-render.md §4.3). * - **`data-morph-preserve`** (KF-151) is honored in the trailing-removal * pass: an unmatched live element with this attribute is skipped instead * of removed. Lets imperatively-injected nodes (autoplay `