@wcstack/signals 4.0.4 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -140,11 +140,14 @@ import { signal, h, For, Index } from "@wcstack/signals/dom";
140
140
 
141
141
  const todos = signal([{ id: 1, text: "a" }, { id: 2, text: "b" }]);
142
142
 
143
- // For — `id` でキーイング。並び替えで行を再利用/移動。`each` は item と
144
- // index アクセサ(行が移動するとインデックスが変わる)を受け取る。
143
+ // For — `id` でキーイング。並び替えで行を再利用/移動。`each` は行を作ったときの item・
144
+ // index アクセサ(行が移動するとインデックスが変わる)・current アクセサ(その key の今の
145
+ // item)を受け取る。
145
146
  h("ul", null,
146
- For(todos, (t, index) => h("li", null, () => `${index()}: ${t.text}`), { key: (t) => t.id }),
147
+ For(todos, (t, index, current) => h("li", null, () => `${index()}: ${current().text}`), { key: (t) => t.id }),
147
148
  );
149
+ // 置き換えの更新でも行は使い回され、current() で新しい値が届く:
150
+ todos.set(todos.peek().map((t) => (t.id === 1 ? { ...t, text: "A" } : t)));
148
151
 
149
152
  // Index — 位置でキーイング(プリミティブ配列向け)。`each` は item を
150
153
  // アクセサ(スロットの値が変わる・スロット自体は不変)、index を固定値で受け取る。
@@ -155,8 +158,46 @@ h("ul", null,
155
158
  ```
156
159
 
157
160
  - `For` のキー既定は値の同一性(`===`)。オブジェクトは `{ key }` を渡す。キーは一意必須(重複は throw)。位置が安定なプリミティブ配列には `Index`。
161
+ - **key 付きの行は、key がある限り保たれる** — その key の下のオブジェクトが何であっても。並び替え・再取得・置き換えの更新のどれでも行(と DOM・focus・入力状態)は使い回される。だから第 1 引数は**行を作ったときの** item。変わりうる値は `current()` から読む(`() => current().text`)。`t.text` のままだと作ったときの値で止まる。
158
162
  - `each` は**単一**の Node を返すこと(1 行 = 1 ノード)。
159
163
 
164
+ ### 7. `@wcstack/router` の裏のページと、`<wcs-storage>` に残す値
165
+
166
+ router は、ルートに入ると中身を `<wcs-outlet>` に置き、出ると取り出し、次に入ると**同じノード**を戻す。`@wcstack/state` はその中身を binder プロトコルでバインドするが、signals に binder は無い。だから外からルートの中身へ `render()` しない — ノードは前回描いたものを持ったまま戻り、2 回目の描画はそれに足される。代わりに、ページごとに `SignalsElement` を作る: 接続したときに描き、外れたときに effect を破棄するので、ページはそのルートが表示されている間だけ生きる。ルートのパラメータは router 要素を bind して読む:
167
+
168
+ ```html
169
+ <wcs-router>
170
+ <template>
171
+ <wcs-route path="/"><catalog-page></catalog-page></wcs-route>
172
+ <wcs-route path="/products/:id(int)"><product-page></product-page></wcs-route>
173
+ </template>
174
+ </wcs-router>
175
+ <wcs-outlet></wcs-outlet>
176
+ ```
177
+
178
+ ```js
179
+ import "@wcstack/router/auto";
180
+ import { computed, h, bindNode, mountNode, signal, SignalsElement } from "@wcstack/signals/dom";
181
+
182
+ const router = bindNode(document.querySelector("wcs-router")); // 上の import で定義済み
183
+ const productId = computed(() => router.signals.typedParams.get()?.id ?? null);
184
+
185
+ class ProductPage extends SignalsElement {
186
+ render() {
187
+ return h("h2", null, () => `Product ${productId.get()}`);
188
+ }
189
+ }
190
+ customElements.define("product-page", ProductPage);
191
+ ```
192
+
193
+ `<wcs-storage>` に残す値: 要素は接続したときにキーを読み込むので、`mountNode` の直後には `value` の signal に保存値が入っている(空のキーなら `null`)。**`bindInput` の前に、そこから自分の signal をシードする** — `bindInput` の最初の実行は signal を要素へ書くので、空のシード(`[]`)は読み込みのたびに保存値の上に保存される。`#init=element` の signals 版([storage の README §5](../storage/README.ja.md))。
194
+
195
+ ```js
196
+ const store = mountNode("wcs-storage", { attrs: { key: "cart" } });
197
+ const cart = signal(store.signals.value.peek() ?? []); // 保存値か、新しいカート
198
+ store.bindInput("value", cart); // ここから先の変更が保存される
199
+ ```
200
+
160
201
  ### 4. 非同期リソース(switchMap)
161
202
 
162
203
  ```typescript
@@ -205,10 +246,10 @@ const log = streamResource((args, signal) => openLogStream(signal), {
205
246
 
206
247
  | エクスポート | シグネチャ | 備考 |
207
248
  |---|---|---|
208
- | `h` | `(tag, props?, ...children) => Node` | `tag` はタグ文字列・`Component`・`Fragment`。関数/signal の prop と child はリアクティブ。`onXxx` prop はイベントリスナ。 |
249
+ | `h` | `(tag, props?, ...children) => Node` | `tag` はタグ文字列・`Component`・`Fragment`。関数/signal の prop と child はリアクティブ。`on…` キーの関数はイベントリスナ: `onClick` → `click`(小文字化)、`onclick` / `"onadd-to-cart"` → 書いたままの名前(`click`・`add-to-cart`)。 |
209
250
  | `render` | `(child, container) => Node` | child(fragment/配列/リアクティブを解決)を container に追加。 |
210
251
  | `Fragment` | `symbol` | `h(Fragment, null, ...children)` でラッパ要素なしにグループ化。 |
211
- | `For<T>` | `(list, each, options?) => ListView` | keyed リスト。`list` は signal または `() => T[]`、`each(item, index: () => number)` は単一 Node を返す、`options.key(item, i)` 既定は値の同一性。キーで行を再利用/移動し、削除行を dispose。 |
252
+ | `For<T>` | `(list, each, options?) => ListView` | keyed リスト。`list` は signal または `() => T[]`、`each(item, index: () => number, current: () => T)` は単一 Node を返す(`item` は行を作ったときの値、`current()` はその key の今の item)、`options.key(item, i)` 既定は値の同一性。キーで行を再利用/移動し、削除行を dispose。 |
212
253
  | `Index<T>` | `(list, each) => ListView` | 位置キーのリスト。`each(item: () => T, index: number)` は単一 Node を返す。スロット単位で行を再利用(スロットの値は signal で更新)し、末尾で grow/shrink。 |
213
254
  | `SignalsElement` | `abstract` 基底(遅延 `extends HTMLElement`) | ライフサイクル基底。`render()` を実装、必要なら `getMountPoint()` を上書き。`HTMLElement` は遅延解決され、`./dom` モジュールは非 DOM 環境でも評価可能 — [SSR / 非DOM](#ssr--非dom-dom-エントリは-dom-無しで読み込める)参照。 |
214
255
  | `createSignalsElement` | `() => SignalsElementClass` | `SignalsElement` 基底を(memoize して)呼び出し時に構築。DOM が無ければ分かりやすい Error を投げる。SSR セーフな基底取得手段。 |
@@ -371,7 +412,7 @@ esbuild / tsc / Vite の設定例・検証用 `.tsx` 例・トラブルシュー
371
412
 
372
413
  ## 安定性(Stability)
373
414
 
374
- パッケージのバージョンは **1.x** ですが、公開サーフェスは **安定(stable)** なコアと **発展中 / 実験的(evolving / experimental)** なエッジに分かれています。破壊的変更は実験的な側に集中しており、安定サーフェスは semver に従います。
415
+ パッケージのバージョンは wcstack 全体と同じ(**4.x**。全パッケージを 1 つの版で公開します)ですが、公開サーフェスは **安定(stable)** なコアと **発展中 / 実験的(evolving / experimental)** なエッジに分かれています。破壊的変更は実験的な側に集中しており、安定サーフェスは semver に従います。
375
416
 
376
417
  | API グループ | エクスポート | 安定度 |
377
418
  |---|---|---|
@@ -382,7 +423,7 @@ esbuild / tsc / Vite の設定例・検証用 `.tsx` 例・トラブルシュー
382
423
  | **DOM レイヤ** | `h` / `render` / `Fragment` / `For` / `Index` / `setProp` / `SignalsElement` / `createSignalsElement` / `ListView` / `mountNode` | **Evolving / experimental** — 今すぐ使えるが、安定昇格までにシグネチャや要素ファクトリの形が変わりうる。 |
383
424
  | **開発モード** | `globalThis.__WCS_DEV__` と各警告コード | **Experimental** — 診断専用。警告の集合や文言はいつでも変わりうる。本番では一切動かない。 |
384
425
 
385
- **deprecation ポリシー。** **1.x** の系列内では、**安定**な API は後方互換を維持します: 非互換な変更は、導入の最低 1 マイナーリリース前に deprecation として告知します。**evolving / experimental** とマークされた API は、マイナーリリースで変わりうる(シグネチャ・型の形・警告文言)ので、現在の形に依存する場合は厳密なバージョンを pin してください。
426
+ **deprecation ポリシー。** 同じメジャーバージョンの中では、**安定**な API は後方互換を維持します: 非互換な変更は、導入の最低 1 マイナーリリース前に deprecation として告知します。**evolving / experimental** とマークされた API は、マイナーリリースで変わりうる(シグネチャ・型の形・警告文言)ので、現在の形に依存する場合は厳密なバージョンを pin してください。
386
427
 
387
428
  ## 注意・制限
388
429
 
package/README.md CHANGED
@@ -141,11 +141,14 @@ import { signal, h, For, Index } from "@wcstack/signals/dom";
141
141
 
142
142
  const todos = signal([{ id: 1, text: "a" }, { id: 2, text: "b" }]);
143
143
 
144
- // For — keyed by `id`. Rows are reused/moved on reorder; `each` receives the item
145
- // and an index ACCESSOR (the index changes when the row moves).
144
+ // For — keyed by `id`. Rows are reused/moved on reorder; `each` receives the item it
145
+ // was built for, an index ACCESSOR (the index changes when the row moves) and a CURRENT
146
+ // accessor — the item under the row's key now.
146
147
  h("ul", null,
147
- For(todos, (t, index) => h("li", null, () => `${index()}: ${t.text}`), { key: (t) => t.id }),
148
+ For(todos, (t, index, current) => h("li", null, () => `${index()}: ${current().text}`), { key: (t) => t.id }),
148
149
  );
150
+ // An immutable update keeps the row and reaches it through current():
151
+ todos.set(todos.peek().map((t) => (t.id === 1 ? { ...t, text: "A" } : t)));
149
152
 
150
153
  // Index — keyed by position (good for primitive arrays). `each` receives the item
151
154
  // as an ACCESSOR (the value at a slot changes; the slot does not) and a fixed index.
@@ -156,8 +159,46 @@ h("ul", null,
156
159
  ```
157
160
 
158
161
  - `For` keys default to value identity (`===`); pass `{ key }` for objects. Keys must be unique (a duplicate throws). Use `Index` for primitive lists where position is the stable identity.
162
+ - **A keyed row is kept while its key is**, whatever object the list now holds under it — a reorder, a re-fetch and an immutable update all reuse the row (and its DOM, focus, input state). So the first argument is the item **the row was built with**: read what can change through `current()` (`() => current().text`), or `t.text` stays what it was.
159
163
  - `each` must return a **single** Node (one row = one node).
160
164
 
165
+ ### 7. Pages behind `@wcstack/router`, and a value kept in `<wcs-storage>`
166
+
167
+ The router puts a route's content into `<wcs-outlet>` when the route is entered, takes it out when it is left, and puts **the same nodes** back on the next entry. `@wcstack/state` binds that content through the binder protocol; signals has no binder, so do not `render()` into route content from outside — the nodes come back with what you rendered last time, and a second render appends to it. Make each page a `SignalsElement` instead: it renders when it connects and disposes its effects when it disconnects, so a page is live exactly while its route is shown. Read the route's parameters by binding the router element:
168
+
169
+ ```html
170
+ <wcs-router>
171
+ <template>
172
+ <wcs-route path="/"><catalog-page></catalog-page></wcs-route>
173
+ <wcs-route path="/products/:id(int)"><product-page></product-page></wcs-route>
174
+ </template>
175
+ </wcs-router>
176
+ <wcs-outlet></wcs-outlet>
177
+ ```
178
+
179
+ ```js
180
+ import "@wcstack/router/auto";
181
+ import { computed, h, bindNode, mountNode, signal, SignalsElement } from "@wcstack/signals/dom";
182
+
183
+ const router = bindNode(document.querySelector("wcs-router")); // defined by the import above
184
+ const productId = computed(() => router.signals.typedParams.get()?.id ?? null);
185
+
186
+ class ProductPage extends SignalsElement {
187
+ render() {
188
+ return h("h2", null, () => `Product ${productId.get()}`);
189
+ }
190
+ }
191
+ customElements.define("product-page", ProductPage);
192
+ ```
193
+
194
+ A value kept in `<wcs-storage>`: the element loads its key when it connects, so right after `mountNode` its `value` signal holds what was saved (`null` for an empty key). **Seed your signal from it before `bindInput`** — `bindInput`'s first run writes the signal into the element, and an empty seed (`[]`) would be saved over the stored value on every load. This is the signals form of `#init=element` ([storage README §5](../storage/README.md#5-load-before-bind-initelement)).
195
+
196
+ ```js
197
+ const store = mountNode("wcs-storage", { attrs: { key: "cart" } });
198
+ const cart = signal(store.signals.value.peek() ?? []); // what was saved, or a fresh cart
199
+ store.bindInput("value", cart); // from now on, changes are saved
200
+ ```
201
+
161
202
  ### 4. Async resource (switchMap)
162
203
 
163
204
  ```typescript
@@ -206,10 +247,10 @@ const log = streamResource((args, signal) => openLogStream(signal), {
206
247
 
207
248
  | Export | Signature | Notes |
208
249
  |---|---|---|
209
- | `h` | `(tag, props?, ...children) => Node` | `tag` is a tag string, a `Component`, or `Fragment`. Function/signal props & children are reactive. `onXxx` props are event listeners. |
250
+ | `h` | `(tag, props?, ...children) => Node` | `tag` is a tag string, a `Component`, or `Fragment`. Function/signal props & children are reactive. A function under an `on…` key is an event listener: `onClick` → `click` (lowercased); `onclick` / `"onadd-to-cart"` → the name as written (`click`, `add-to-cart`). |
210
251
  | `render` | `(child, container) => Node` | Append a child (resolving fragments/arrays/reactives) into a container. |
211
252
  | `Fragment` | `symbol` | `h(Fragment, null, ...children)` groups without a wrapper element. |
212
- | `For<T>` | `(list, each, options?) => ListView` | Keyed list. `list` is a signal or `() => T[]`; `each(item, index: () => number)` returns one Node; `options.key(item, i)` defaults to value identity. Reuses/moves rows by key; disposes removed rows. |
253
+ | `For<T>` | `(list, each, options?) => ListView` | Keyed list. `list` is a signal or `() => T[]`; `each(item, index: () => number, current: () => T)` returns one Node (`item` is the item the row was built with, `current()` the item under its key now); `options.key(item, i)` defaults to value identity. Reuses/moves rows by key; disposes removed rows. |
213
254
  | `Index<T>` | `(list, each) => ListView` | Position-keyed list. `each(item: () => T, index: number)` returns one Node. Rows are reused per slot (the value at a slot updates via a signal); grows/shrinks at the tail. |
214
255
  | `SignalsElement` | `abstract` base (lazy `extends HTMLElement`) | Lifecycle base; implement `render()`, optionally `getMountPoint()`. `HTMLElement` is resolved lazily so the `./dom` module evaluates in non-DOM environments — see [SSR / non-DOM](#ssr--non-dom-the-dom-entry-loads-without-a-dom). |
215
256
  | `createSignalsElement` | `() => SignalsElementClass` | Build (memoized) the `SignalsElement` base at call time. Resolves `HTMLElement` when called; throws a clear error if no DOM. The SSR-safe way to obtain the base. |
@@ -373,13 +414,13 @@ A step-by-step guide (esbuild / tsc / Vite setups, a verifying `.tsx` example, t
373
414
  Both entries ship as production code-split bundles that import **one shared reactive-core chunk** — but that chunk is imported by **relative path** (`./core-*.esm.js`), so whether a buildless page ends up with one reactive instance depends on how the files are served.
374
415
 
375
416
  - **Map the single `/dom` entry (the recommended CDN form).** `@wcstack/signals/dom` re-exports the entire headless core (`signal` / `computed` / `effect` / `createRoot` / `onCleanup` / `flushSync` / `resource` / `streamResource` / `bindNode` / `nodeSource`) alongside the DOM helpers, so one specifier covers everything and the single instance is structural — nothing depends on chunk sharing. The signals demos in this repo all import from this one entry.
376
- - **Mapping both specifiers only works from a path-preserving origin.** `.` and `./dom` keep sharing the core only if their relative `./core-*.esm.js` import resolves to the **same URL** — i.e. the whole `dist/` is served as files (self-hosted, or version-pinned path URLs such as `https://cdn.jsdelivr.net/npm/@wcstack/signals@1.25.0/dist/index.esm.js` + `…/dist/dom.esm.js`, both pinned to the same version). A *transforming* ESM endpoint like `https://esm.run/@wcstack/signals` bundles each entry into its own self-contained file, so mapping both esm.run entries ships **two** reactive cores: a signal created through one is invisible to an effect from the other.
417
+ - **Mapping both specifiers only works from a path-preserving origin.** `.` and `./dom` keep sharing the core only if their relative `./core-*.esm.js` import resolves to the **same URL** — i.e. the whole `dist/` is served as files (self-hosted, or version-pinned path URLs such as `https://cdn.jsdelivr.net/npm/@wcstack/signals@4.1.0/dist/index.esm.js` + `…/dist/dom.esm.js`, both pinned to the same version). A *transforming* ESM endpoint like `https://esm.run/@wcstack/signals` bundles each entry into its own self-contained file, so mapping both esm.run entries ships **two** reactive cores: a signal created through one is invisible to an effect from the other.
377
418
 
378
419
  Bundler users dedupe via the module graph and may use either entry.
379
420
 
380
421
  ## Stability
381
422
 
382
- The package version is **1.x**, but the public surface is split into a **stable** core and an **evolving / experimental** edge. The breaking changes are concentrated on the experimental side; the stable surface follows semver.
423
+ The package is versioned with the rest of wcstack (**4.x**: every package is released with one version), but the public surface is split into a **stable** core and an **evolving / experimental** edge. The breaking changes are concentrated on the experimental side; the stable surface follows semver.
383
424
 
384
425
  | API group | Exports | Stability |
385
426
  |---|---|---|
@@ -390,7 +431,7 @@ The package version is **1.x**, but the public surface is split into a **stable*
390
431
  | **DOM layer** | `h` / `render` / `Fragment` / `For` / `Index` / `setProp` / `SignalsElement` / `createSignalsElement` / `ListView` / `mountNode` | **Evolving / experimental** — usable today; signatures and the element factory shape may adjust before they are promoted to stable. |
391
432
  | **Development mode** | `globalThis.__WCS_DEV__` + the warning codes | **Experimental** — diagnostics only; the set of warnings and their wording may change at any time. It never runs in production. |
392
433
 
393
- **Deprecation policy.** Within the **1.x** line, the **stable** APIs keep backward compatibility: any incompatible change is announced as a deprecation at least one minor release before it lands. APIs marked **evolving / experimental** may change in a minor release (signatures, type shapes, or warning wording) — pin an exact version if you depend on their current shape.
434
+ **Deprecation policy.** Within a major version, the **stable** APIs keep backward compatibility: any incompatible change is announced as a deprecation at least one minor release before it lands. APIs marked **evolving / experimental** may change in a minor release (signatures, type shapes, or warning wording) — pin an exact version if you depend on their current shape.
394
435
 
395
436
  ## Notes & limitations
396
437
 
package/dist/dom.d.ts CHANGED
@@ -258,7 +258,13 @@ declare function h(tag: string | typeof Fragment | Component, props?: Props, ...
258
258
  /** Append `child` into `container`, resolving fragments/arrays. */
259
259
  declare function render(child: Child, container: Node): Node;
260
260
  type ListAccessor<T> = ReadSignal<readonly T[]> | (() => readonly T[]);
261
- type ForEach<T> = (item: T, index: () => number) => Node;
261
+ /**
262
+ * `For`'s row builder. `item` is the item the row was built for — a plain value. A keyed row is
263
+ * kept while its key is (an immutable update hands it a new object under the same key), so read
264
+ * what changes through `current`, an accessor of the item under the row's key now
265
+ * (`() => current().text`). docs/seam-apps.md, signals-shop.
266
+ */
267
+ type ForEach<T> = (item: T, index: () => number, current: () => T) => Node;
262
268
  type IndexEach<T> = (item: () => T, index: number) => Node;
263
269
  /**
264
270
  * The return type of {@link For} / {@link Index}: a keyed list that owns an anchored
package/dist/dom.esm.js CHANGED
@@ -126,10 +126,13 @@ function isSettableProperty(el, key) {
126
126
  return result;
127
127
  }
128
128
  function bindProp(el, key, value) {
129
- // Event handlers (`onClick` → "click") are special-cased BEFORE the reactive
130
- // check: a function here is the listener, not a thunk to track.
131
- if (/^on[A-Z]/.test(key) && typeof value === "function") {
132
- const type = key.slice(2).toLowerCase();
129
+ // Event handlers are special-cased BEFORE the reactive check: a function here is the
130
+ // listener, not a thunk to track. `onClick` → "click" (lowercased); `onclick` /
131
+ // `onadd-to-cart` → the name as written ("click", "add-to-cart" — data-wcs's `on<event>:`
132
+ // form). A lowercase `onclick` used to fall through to the reactive path, so the handler
133
+ // ran at render and never on click (docs/seam-apps.md, signals-shop).
134
+ if (/^on[A-Za-z-]/.test(key) && typeof value === "function") {
135
+ const type = /^on[A-Z]/.test(key) ? key.slice(2).toLowerCase() : key.slice(2);
133
136
  const listener = value;
134
137
  el.addEventListener(type, listener);
135
138
  // Remove the listener when the owning scope is torn down (e.g. a dynamic
@@ -468,12 +471,13 @@ function For(list, each, options) {
468
471
  let prevOrder = [];
469
472
  const make = (item, i) => {
470
473
  const idx = signal(i);
474
+ const cur = signal(item);
471
475
  let node;
472
476
  const dispose = createRoot((d) => {
473
- node = each(item, () => idx.get());
477
+ node = each(item, () => idx.get(), () => cur.get());
474
478
  return d;
475
479
  });
476
- return { node, dispose, idx };
480
+ return { node, dispose, idx, cur };
477
481
  };
478
482
  effect(() => {
479
483
  const items = read() ?? [];
@@ -518,6 +522,7 @@ function For(list, each, options) {
518
522
  if (row.idx.peek() !== i) {
519
523
  row.idx.set(i); // position changed — refresh the index accessor
520
524
  }
525
+ row.cur.set(items[i]); // the item under the key now (a no-op when it is the same)
521
526
  }
522
527
  else {
523
528
  row = make(items[i], i);
@@ -1 +1 @@
1
- {"version":3,"file":"dom.esm.js","sources":["../src/dom.ts"],"sourcesContent":["// Fine-grained hyperscript (v1 design notes). The \"step before JSX\" (docs §4-1).\n//\n// `h(tag, props, ...children)` is the classic JSX factory shape, but it does NOT\n// build a virtual DOM and re-render. It creates a REAL DOM node once; any prop or\n// child given as a function (thunk) or signal is wired to a targeted `effect`, so\n// only that one binding updates when its signals change (Solid-style). This is\n// what keeps the package lightweight: no reconciler is shipped.\n//\n// JSX is intentionally NOT shipped. A consumer who wants it sets, in their own\n// tsconfig, `jsxFactory: \"h\"` + `jsxFragmentFactory: \"Fragment\"` (classic runtime)\n// — opting into a build step is their choice; the buildless path is calling `h`\n// directly. See docs/signals-state-design.md §4-1.\n//\n// OWNERSHIP: effects created here are owned by the enclosing reactive scope.\n// A reactive child's effect owns the prop/child effects of the subtree it builds,\n// so rebuilding that subtree disposes the previous one's effects (no leak). Mount\n// an app under `createRoot` so the whole tree can be torn down on unmount; a\n// dynamic child establishes its own scope automatically (it IS an effect).\n\nimport { signal, effect, onCleanup, createRoot, hasOwner, ReadSignal, WriteSignal } from \"./reactive.js\";\nimport { isDev, warnDev } from \"./dev.js\";\nimport { bindNode } from \"./bindNode.js\";\nimport type { BoundNode, NodeShape, DefaultNodeShape, WcBindableDescriptor } from \"./bindNode.js\";\n\n// `@wcstack/signals/dom` re-exports the headless core (signals, resource,\n// streamResource, bindNode, nodeSource) so UI code can import everything from one\n// module. Both built entries import a single shared `core-*.esm.js` chunk\n// (rollup.config.js `manualChunks`), so importing from BOTH `@wcstack/signals` and\n// `@wcstack/signals/dom` on a buildless page yields ONE reactive instance — the\n// tracking context is shared, not duplicated. `__tests__/packaging.test.ts` pins\n// this (both entries reference the same core chunk; a signal made via one entry is\n// observed by an effect from the other).\nexport {\n signal,\n computed,\n effect,\n createRoot,\n onCleanup,\n flushSync,\n} from \"./reactive.js\";\nexport type { ReadSignal, WriteSignal, EffectHandle, Cleanup, Equals } from \"./reactive.js\";\nexport { resource } from \"./resource.js\";\nexport type { ResourceState, ResourceOptions, ResourceSource } from \"./resource.js\";\nexport { streamResource } from \"./streamResource.js\";\nexport type {\n StreamResourceState,\n StreamResourceOptions,\n StreamSource,\n StreamProducer,\n StreamStatus,\n} from \"./streamResource.js\";\nexport { bindNode, nodeSource, DisposedError, isDisposedError } from \"./bindNode.js\";\nexport type {\n BoundNode,\n NodeShape,\n DefaultNodeShape,\n WcBindableDescriptor,\n WcBindableProperty,\n EventStreamOptions,\n} from \"./bindNode.js\";\n\nexport const Fragment = Symbol(\"signals.Fragment\");\n\nexport type Child = unknown;\nexport type Props = Record<string, unknown> | null;\n// h() always injects `children` into the props object it passes to a component, so\n// the parameter type makes that explicit (a component can declare `{ children }`).\nexport type Component = (\n props: Record<string, unknown> & { children?: Child[] },\n) => Node | Child[];\n\nfunction isReadSignal(value: unknown): value is ReadSignal<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { get?: unknown }).get === \"function\" &&\n typeof (value as { peek?: unknown }).peek === \"function\"\n );\n}\n\nexport function h(\n tag: string | typeof Fragment | Component,\n props?: Props,\n ...children: Child[]\n): Node {\n if (tag === Fragment) {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n }\n\n if (typeof tag === \"function\") {\n const result = tag({ ...(props ?? {}), children });\n return Array.isArray(result) ? wrapFragment(result) : result;\n }\n\n const el = createElement(tag);\n if (props) {\n for (const key in props) {\n bindProp(el, key, props[key]);\n }\n }\n appendChildren(el, children);\n return el;\n}\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\n// Tags created in the SVG namespace. Ambiguous names shared with HTML (`a`,\n// `title`, `script`, `style`) are intentionally EXCLUDED so ordinary HTML usage is\n// not broken; an SVG `<a>` / `<title>` must be created in an explicitly-namespaced\n// way by the caller. SVG DOM props are largely read-only, so `setProp`'s\n// settable-property check routes SVG attributes through `setAttribute` for free.\nconst SVG_TAGS = new Set([\n \"svg\", \"g\", \"path\", \"rect\", \"circle\", \"ellipse\", \"line\", \"polyline\", \"polygon\",\n \"text\", \"tspan\", \"defs\", \"use\", \"symbol\", \"marker\", \"linearGradient\",\n \"radialGradient\", \"stop\", \"clipPath\", \"mask\", \"pattern\", \"image\", \"foreignObject\",\n]);\n\nfunction createElement(tag: string): Element {\n return SVG_TAGS.has(tag)\n ? document.createElementNS(SVG_NS, tag)\n : document.createElement(tag);\n}\n\n/** Append `child` into `container`, resolving fragments/arrays. */\nexport function render(child: Child, container: Node): Node {\n appendChild(container, child);\n return container;\n}\n\nfunction wrapFragment(children: Child[]): DocumentFragment {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n}\n\n// --- props ------------------------------------------------------------------\n\n// Attribute names whose corresponding JS DOM property differs. `class` is handled\n// separately (it has reactive-falsy semantics in setProp), so it is not listed here.\nconst ATTR_TO_PROP: Record<string, string> = {\n for: \"htmlFor\",\n tabindex: \"tabIndex\",\n colspan: \"colSpan\",\n rowspan: \"rowSpan\",\n readonly: \"readOnly\",\n maxlength: \"maxLength\",\n minlength: \"minLength\",\n contenteditable: \"contentEditable\",\n};\n\n// True only if `key` resolves to a WRITABLE property on the element or its\n// prototype chain (a data property with `writable !== false`, or an accessor with a\n// setter). `key in el` is not enough: it also matches read-only members like\n// `firstChild` / `childNodes`, whose assignment throws in strict mode. The walk\n// starts at `el` itself so own instance fields (e.g. a custom element's properties)\n// are still matched, exactly as the previous `key in el` did — just without the\n// read-only false positives.\n//\n// MEMOIZATION: the prototype-chain walk runs on every bindProp/setProp. The result\n// depends only on the element's PROTOTYPE (its class) and the key, since DOM props\n// live on the prototype — not on per-instance own fields, which this library never\n// adds dynamically per element. So cache by `(prototype, key)`: a WeakMap keyed by\n// prototype (no leak — entries die with the class) holding a Map of key→result.\nconst settableCache = new WeakMap<object, Map<string, boolean>>();\n\nfunction computeSettable(el: Element, key: string): boolean {\n let obj: object | null = el;\n while (obj !== null) {\n const desc = Object.getOwnPropertyDescriptor(obj, key);\n if (desc) {\n return \"set\" in desc ? typeof desc.set === \"function\" : desc.writable !== false;\n }\n obj = Object.getPrototypeOf(obj);\n }\n return false;\n}\n\nfunction isSettableProperty(el: Element, key: string): boolean {\n // A real Element always has a prototype (HTMLElement.prototype → … → Object), so\n // `getPrototypeOf` is non-null here; use it as the cache key.\n const proto = Object.getPrototypeOf(el) as object;\n let byKey = settableCache.get(proto);\n if (byKey === undefined) {\n byKey = new Map<string, boolean>();\n settableCache.set(proto, byKey);\n }\n let result = byKey.get(key);\n if (result === undefined) {\n result = computeSettable(el, key);\n byKey.set(key, result);\n }\n return result;\n}\n\nfunction bindProp(el: Element, key: string, value: unknown): void {\n // Event handlers (`onClick` → \"click\") are special-cased BEFORE the reactive\n // check: a function here is the listener, not a thunk to track.\n if (/^on[A-Z]/.test(key) && typeof value === \"function\") {\n const type = key.slice(2).toLowerCase();\n const listener = value as EventListener;\n el.addEventListener(type, listener);\n // Remove the listener when the owning scope is torn down (e.g. a dynamic\n // child that rebuilds this subtree), so handlers don't accumulate.\n onCleanup(() => el.removeEventListener(type, listener));\n return;\n }\n\n if (typeof value === \"function\") {\n effect(() => setProp(el, key, (value as () => unknown)()));\n return;\n }\n\n if (isReadSignal(value)) {\n effect(() => setProp(el, key, value.get()));\n return;\n }\n\n setProp(el, key, value);\n}\n\nfunction setProp(el: Element, key: string, value: unknown): void {\n if (key === \"style\") {\n setStyle(el as HTMLElement, value);\n return;\n }\n if (key === \"class\" || key === \"className\") {\n // Set the `class` ATTRIBUTE, not the `className` property. On an SVGElement\n // `className` is a read-only `SVGAnimatedString`, so assigning it throws in\n // strict mode (ESM is always strict) — `setAttribute(\"class\", …)` works for both\n // HTML and SVG. Treat false like null → empty class (consistent with the\n // attribute path's false-removes-it rule), so `() => cond && \"active\"` yields \"\"\n // (not \"false\") when the condition is falsy.\n // STRING-ONLY: a non-null/non-false value is coerced via String(value). Array\n // (`[\"a\", \"b\"]`) and object (`{ active: true }`) class forms are NOT supported —\n // they would stringify to \"a,b\" / \"[object Object]\". Compose the class string in\n // the binding itself (e.g. `() => [a, b].join(\" \")`) and pass a string. This keeps\n // the core free of a class-merging convention.\n el.setAttribute(\"class\", value == null || value === false ? \"\" : String(value));\n return;\n }\n // Remap the handful of attribute names whose JS property differs, so `for` /\n // `tabindex` / `colspan` etc. reach the right property instead of falling through\n // to setAttribute (which works for some but not e.g. `htmlFor`).\n const propKey = ATTR_TO_PROP[key] ?? key;\n if (isSettableProperty(el, propKey)) {\n // Known, WRITABLE DOM property (value, checked, disabled, id, htmlFor, ...).\n // The settability check excludes read-only members (firstChild, childNodes, …)\n // that `key in el` would wrongly accept — assigning to those throws in strict\n // mode; we fall through to the attribute path for them instead.\n //\n // NORMALIZATION: null/undefined are coerced to \"\" before assignment. Without\n // this, a STRING prop (id/title/value/src) given a reactive null/undefined\n // lands as the literal \"null\"/\"undefined\" (e.g. img.src=\"null\" fires a real\n // request) — a correctness footgun. \"\" clears the prop instead. Safe for\n // non-string props too: boolean props coerce \"\"→false (same as null), numeric\n // props coerce \"\"→0 (same as null). We do NOT normalize `false`:\n // `el.disabled = false` is the intended boolean clear.\n (el as unknown as Record<string, unknown>)[propKey] = value == null ? \"\" : value;\n return;\n }\n if (value == null || value === false) {\n el.removeAttribute(key);\n return;\n }\n if (value === true) {\n el.setAttribute(key, \"\");\n return;\n }\n el.setAttribute(key, String(value));\n}\n\nfunction setStyle(el: HTMLElement, value: unknown): void {\n if (value == null) {\n el.removeAttribute(\"style\");\n return;\n }\n if (typeof value === \"string\") {\n el.style.cssText = value;\n return;\n }\n // Object form: the object fully describes the style. Reset first so keys present\n // in a previous run but absent now are removed — otherwise a reactive style that\n // drops a key (e.g. {color,fontWeight} → {color}) would leave the stale property\n // applied. The object is the source of truth, so wiping cssText is correct here.\n el.style.cssText = \"\";\n const style = el.style as CSSStyleDeclaration & Record<string, string>;\n const obj = value as Record<string, string>;\n for (const k in obj) {\n // A key with a hyphen is either kebab-case (`font-weight`) or a CSS custom\n // property (`--accent`). Neither works via property assignment (`style[k]` would\n // just set an inert expando), so route them through setProperty. camelCase keys\n // (`fontWeight`) keep the faster property path.\n if (k.includes(\"-\")) {\n style.setProperty(k, obj[k]);\n } else {\n style[k] = obj[k];\n }\n }\n}\n\n// --- children ---------------------------------------------------------------\n\nfunction appendChildren(parent: Node, children: Child[]): void {\n for (const child of children) {\n appendChild(parent, child);\n }\n}\n\nfunction appendChild(parent: Node, child: Child): void {\n if (child == null || typeof child === \"boolean\") {\n return; // null / undefined / boolean render nothing\n }\n if (Array.isArray(child)) {\n for (const c of child) {\n appendChild(parent, c);\n }\n return;\n }\n if (isListView(child)) {\n // A keyed list (For / Index): it manages its own anchored region with in-place\n // reconciliation, so it does NOT go through the wholesale insertReactive path.\n child.mount(parent);\n return;\n }\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n if (typeof child === \"function\") {\n insertReactive(parent, child as () => unknown);\n return;\n }\n if (isReadSignal(child)) {\n insertReactive(parent, () => child.get());\n return;\n }\n parent.appendChild(document.createTextNode(String(child)));\n}\n\n/**\n * A reactive insertion point. An anchor comment marks the position; on each run\n * the previous nodes are removed and the freshly-resolved nodes inserted before\n * the anchor. Using `anchor.parentNode` (not the original `parent`) keeps it\n * correct after the subtree is moved/mounted elsewhere.\n *\n * PRECONDITION: the Nodes returned by `accessor` are owned by this insertion point\n * — do not move them to another parent externally. On the next run they are\n * removed from wherever they currently are (`node.parentNode?.removeChild`), so an\n * externally-moved node would be yanked out of its new home without warning.\n *\n * OWNERSHIP: the `effect` below is owned by the enclosing reactive scope at call\n * time (the `currentOwner`). Used under `createRoot` / `SignalsElement` (the module\n * header's mount contract) it is disposed on teardown. Calling `h`/`render` with a\n * reactive child OUTSIDE any owner (no `createRoot`/`SignalsElement`) leaves this\n * effect un-owned and therefore never cleaned up — by design, per that contract.\n */\nfunction insertReactive(parent: Node, accessor: () => unknown): void {\n if (isDev() && !hasOwner()) {\n // A reactive child inserted with no enclosing owner: the effect below is never\n // disposed (the module header documents this as by-design, but it is a frequent\n // accidental leak). Warn once in dev so the un-owned mount is visible.\n warnDev(\n \"UNOWNED_INSERT\",\n \"\",\n \"reactive child inserted with no owner — its update effect will never be \" +\n \"disposed and may leak. Mount under createRoot / SignalsElement.\",\n );\n }\n const anchor = document.createComment(\"\");\n parent.appendChild(anchor);\n let current: Node[] = [];\n\n effect(() => {\n const value = accessor();\n // FAST PATH: a plain text result that replaces a plain text result. The common\n // reactive child is a string/number thunk (`() => \\`count: ${n.get()}\\``); the\n // wholesale path would remove the old Text node, allocate a new one, and re-insert\n // it on every change. When BOTH the previous and next renders are a single Text\n // node, mutate the existing node's `data` in place instead — no allocation, no\n // remove/insert, and the same DOM node identity is preserved across updates.\n if ((typeof value === \"string\" || typeof value === \"number\") && current.length === 1) {\n const node = current[0];\n if (node.nodeType === 3 /* TEXT_NODE */) {\n (node as Text).data = String(value);\n return;\n }\n }\n const next = toNodes(value);\n for (const node of current) {\n node.parentNode?.removeChild(node);\n }\n const host = anchor.parentNode;\n if (host) {\n for (const node of next) {\n host.insertBefore(node, anchor);\n }\n }\n current = next;\n });\n\n // On teardown, drop the references to the inserted Nodes. The disposed effect's\n // closure still captures `current`; if anything retains the effect after disposal\n // (e.g. a parent owner kept alive longer than the subtree), those Nodes would be\n // pinned via that closure even though they have left the DOM. Clearing the array\n // lets them be GC'd as soon as the enclosing owner tears this insertion point down.\n onCleanup(() => {\n current = [];\n });\n}\n\n// --- keyed lists: For / Index (migration-plan §9-3) --------------------------\n//\n// `insertReactive` rebuilds its whole subtree on every change. For lists that is\n// wasteful (and drops per-row state). `For` / `Index` instead keep a stable DOM row\n// per item and reconcile in place. Each row is built under its OWN `createRoot`, so\n// removing a row disposes exactly that row's effects/resources/listeners — the owner\n// tree (§8 (d)) is what makes this leak-free. The reconcile runs in a single\n// `effect` owned by the enclosing scope; an `onCleanup` disposes surviving rows when\n// that scope (e.g. the component) tears down.\n//\n// CONTRACT: `each` must return a SINGLE Node (one row = one node). Keys (For) must\n// be unique. `For` keys by value identity (=== / explicit `key`) and passes the\n// index as an accessor (it changes on move); `Index` keys by position and passes the\n// item as an accessor (the value at a slot changes, the slot does not).\n\nexport type ListAccessor<T> = ReadSignal<readonly T[]> | (() => readonly T[]);\nexport type ForEach<T> = (item: T, index: () => number) => Node;\nexport type IndexEach<T> = (item: () => T, index: number) => Node;\n\n/**\n * The return type of {@link For} / {@link Index}: a keyed list that owns an anchored\n * region and reconciles rows in place. Exported (D4) so consumers can annotate\n * helpers that build or pass around lists. `mount` is called by `h`/`render` when the\n * list is used as a child; `__wcsList` is the brand `appendChild` checks.\n */\nexport interface ListView {\n readonly __wcsList: true;\n mount(parent: Node): void;\n}\n\nfunction isListView(value: unknown): value is ListView {\n return typeof value === \"object\" && value !== null && (value as ListView).__wcsList === true;\n}\n\nfunction readList<T>(list: ListAccessor<T>): () => readonly T[] {\n return isReadSignal(list) ? () => (list as ReadSignal<readonly T[]>).get() : (list as () => readonly T[]);\n}\n\nexport interface ForOptions<T> {\n /** Derive a unique key per item. Default: the item value itself (identity). */\n key?: (item: T, index: number) => unknown;\n}\n\n// --- LIS-based DOM reorder ---------------------------------------------------\n//\n// `reconcileOrder` brings the live DOM under `host` (the contiguous region ending\n// at `anchor`) into `order` — the desired final node sequence — using the FEWEST\n// `insertBefore` moves, while producing EXACTLY the order a naive full re-place\n// would. The naive approach (walk and insert every out-of-place node) does up to\n// O(n) DOM moves on a full reverse or a head insert; here we instead keep the\n// largest set of reused rows that are ALREADY in the right relative order, and\n// move only the others (Solid's reconcileArrays / udomdiff idea).\n//\n// HOW: `prevOrder` is the node sequence the previous run left in the DOM. For each\n// node in the new `order`, a reused row maps to its index in `prevOrder`; a freshly\n// created row has no previous position. The longest increasing subsequence (LIS)\n// of those previous indices marks the reused rows that need NOT move (their pairwise\n// relative order is already correct). Every other node — fresh ones, and reused\n// ones outside the LIS — is inserted before its already-correct successor, walking\n// back-to-front so the \"successor\" reference is always a settled node or the anchor.\n\n/**\n * Indices into `arr` (with value -1 meaning \"no previous position\") whose values\n * form a longest strictly-increasing subsequence. Entries equal to -1 are treated\n * as never part of the subsequence (a fresh node always moves). Classic\n * patience-sorting LIS in O(n log n); returns the chosen indices in ascending order.\n */\nfunction longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n // `tails[k]` = index (into arr) of the smallest tail of an increasing\n // subsequence of length k+1. `prev[i]` = predecessor index, to rebuild the chain.\n const tails: number[] = [];\n const prev: number[] = new Array(n).fill(-1);\n for (let i = 0; i < n; i++) {\n const value = arr[i];\n if (value < 0) {\n continue; // fresh node: not eligible for the stable subsequence\n }\n // Binary search for the first tail whose value is >= this value, and replace it\n // (or extend the tails when this value beats every tail).\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (arr[tails[mid]] < value) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n if (lo > 0) {\n prev[i] = tails[lo - 1];\n }\n tails[lo] = i;\n }\n // Rebuild the index chain from the longest tail backwards.\n const result: number[] = [];\n let k = tails.length > 0 ? tails[tails.length - 1] : -1;\n while (k >= 0) {\n result.push(k);\n k = prev[k];\n }\n result.reverse();\n return result;\n}\n\nfunction reconcileOrder(\n host: Node,\n anchor: Node,\n order: Node[],\n prevOrder: Node[],\n): void {\n const n = order.length;\n if (n === 0) {\n return; // nothing to place (removals already happened)\n }\n\n // Map each previous node to its previous position, so a node in `order` can look\n // up where it used to be. A node absent from this map is FRESH (created this run,\n // or the first run where prevOrder is empty) and is encoded as -1 — it always moves.\n const prevIndex = new Map<Node, number>();\n for (let i = 0; i < prevOrder.length; i++) {\n prevIndex.set(prevOrder[i], i);\n }\n\n // previous-position sequence aligned to the new order. -1 marks a fresh node.\n const seq: number[] = new Array(n);\n for (let i = 0; i < n; i++) {\n const p = prevIndex.get(order[i]);\n seq[i] = p === undefined ? -1 : p;\n }\n\n // Rows whose relative order is already correct: leave them in place, move the rest.\n const lis = longestIncreasingSubsequence(seq);\n let lisPtr = lis.length - 1;\n\n // Walk back-to-front. `ref` is the node that must follow the one being placed; it\n // starts at the anchor (the region's tail) and becomes each placed node. A node in\n // the LIS is the maximal already-correctly-ordered set, so it is left untouched\n // (only adopted as the new `ref`). Every OTHER node is, by construction, out of\n // position relative to its settled successor and is inserted before `ref` — no\n // \"is it already in place?\" guard is needed (it never is, unlike the old\n // full-walk reconciler which visited correctly-placed nodes too).\n let ref: Node = anchor;\n for (let i = n - 1; i >= 0; i--) {\n const node = order[i];\n if (lisPtr >= 0 && lis[lisPtr] === i) {\n lisPtr--; // stable: do not move\n } else {\n host.insertBefore(node, ref);\n }\n ref = node;\n }\n}\n\n// Dev-only key sanity check (no effect in production — guarded by `isDev()` at the\n// call site so this is never reached when dev is off). Flags the silent-failure key\n// shapes: a nullish key (NaN / null / undefined collide under SameValueZero, so two\n// such items map to one row and a row is silently dropped), and — when no explicit\n// `key` was given — a non-primitive item used as its own identity key (every render\n// gets a fresh object reference, so the row is rebuilt instead of reused, silently\n// dropping per-row state). Warns once per distinct shape (deduped in warnDev).\nfunction checkKeyDev(key: unknown, item: unknown, hasExplicitKey: boolean): void {\n if (key == null || (typeof key === \"number\" && Number.isNaN(key))) {\n warnDev(\n \"NULLISH_KEY\",\n String(key),\n \"For: a key is null/undefined/NaN. Such keys collide under SameValueZero, \" +\n \"so rows silently merge/drop. Provide a stable unique `key`.\",\n { key },\n );\n return;\n }\n if (!hasExplicitKey && (typeof key === \"object\" || typeof key === \"function\")) {\n warnDev(\n \"NON_PRIMITIVE_KEY\",\n typeof key,\n \"For: a non-primitive item is used as its own key (no `key` option given). \" +\n \"Object identity changes across renders, so every row is rebuilt and per-row \" +\n \"state is lost. Pass `{ key: item => item.id }`.\",\n { item },\n );\n }\n}\n\nexport function For<T>(list: ListAccessor<T>, each: ForEach<T>, options?: ForOptions<T>): ListView {\n const read = readList(list);\n const keyOf = options?.key;\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"for\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n idx: WriteSignal<number>;\n }\n let rows = new Map<unknown, Row>();\n // The node order placed by the previous reconcile run. Empty on first run.\n // Used to find which reused rows already sit in increasing relative order so\n // only the rest are moved (LIS reorder, see reconcileOrder).\n let prevOrder: Node[] = [];\n\n const make = (item: T, i: number): Row => {\n const idx = signal(i);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(item, () => idx.get());\n return d;\n });\n return { node, dispose, idx };\n };\n\n effect(() => {\n const items = read() ?? [];\n\n // Key-uniqueness PRE-PASS (no side effects): throwing here, before any row is\n // created or moved, keeps a duplicate-key error from leaving half-built rows\n // orphaned (make() runs createRoot) and the DOM mid-reorder. Keys are reused\n // below so keyOf runs once per item.\n const keys: unknown[] = [];\n const seen = new Set<unknown>();\n const dev = isDev();\n for (let i = 0; i < items.length; i++) {\n const k = keyOf ? keyOf(items[i], i) : items[i];\n if (dev) {\n checkKeyDev(k, items[i], keyOf !== undefined);\n }\n if (seen.has(k)) {\n if (dev) {\n // The throw below still halts (production behaviour unchanged); the warn\n // adds the offending key + a pointer to the cause so the silent\n // \"updates stopped\" symptom is diagnosable.\n warnDev(\n \"DUPLICATE_KEY\",\n String(k),\n `For: duplicate key \"${String(k)}\" at index ${i} — keys must be unique. ` +\n \"Rendering throws and the list stops updating until keys are fixed.\",\n { key: k, index: i },\n );\n }\n throw new Error(`For: duplicate key \"${String(k)}\" — keys must be unique.`);\n }\n seen.add(k);\n keys.push(k);\n }\n\n const next = new Map<unknown, Row>();\n const order: Node[] = [];\n\n // Rows freshly created in THIS run (not reused from `rows`). If a later\n // `make()` — i.e. a user `each` — throws mid-loop, the rows already built\n // here are owned by their own detached `createRoot` and are not yet tracked\n // in any surviving map, so they would leak. Dispose them before re-throwing,\n // leaving the old `rows` map untouched (it is recoverable on the next run).\n const fresh: Row[] = [];\n try {\n for (let i = 0; i < items.length; i++) {\n const k = keys[i];\n let row = rows.get(k);\n if (row) {\n if (row.idx.peek() !== i) {\n row.idx.set(i); // position changed — refresh the index accessor\n }\n } else {\n row = make(items[i], i);\n fresh.push(row);\n }\n next.set(k, row);\n order.push(row.node);\n }\n } catch (err) {\n for (const row of fresh) {\n row.dispose();\n }\n throw err;\n }\n\n // The LIVE parent (`anchor.parentNode`, not the mount arg) so the region\n // stays correct after being moved (e.g. built inside a Fragment, then\n // appended elsewhere). `host` is null only if the anchor was detached\n // without disposing this scope (a misuse) — then there is nothing to\n // place into. Resolved before the removal phase so the wholesale-removal\n // fast path below can use it.\n const host = anchor.parentNode;\n\n // Dispose rows whose key vanished. `remove()` no-ops if already detached.\n if (rows.size > 0 && next.size === fresh.length) {\n // ZERO-REUSE run: no existing key survives (clear, or a full replacement\n // with disjoint keys), so EVERY current row is removed. When the host\n // contains exactly this list's region — first child is the region's\n // first row, last child is the anchor, and the child count matches\n // rows + anchor — detach them all with a single native\n // `textContent = \"\"` and re-append the anchor, instead of one\n // `remove()` per row (the dominant cost of clearing large lists).\n // Any deviation (foreign sibling, externally detached row, shared\n // host) fails the guard and falls back to the per-row path.\n // Disposal always runs per row; only the DOM detachment is batched.\n if (\n host !== null &&\n host.lastChild === anchor &&\n prevOrder.length > 0 &&\n host.firstChild === prevOrder[0] &&\n host.childNodes.length === rows.size + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows.values()) {\n row.dispose();\n }\n } else {\n for (const row of rows.values()) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n } else {\n for (const [k, row] of rows) {\n if (!next.has(k)) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n }\n if (host) {\n reconcileOrder(host, anchor, order, prevOrder);\n }\n\n // Snapshot this run's final order so the NEXT run's reconcile can detect\n // which rows kept their relative position (the LIS basis below). Capturing\n // the array we just placed avoids re-deriving it from the map.\n prevOrder = order;\n rows = next;\n });\n\n onCleanup(() => {\n for (const row of rows.values()) {\n row.dispose();\n }\n rows.clear();\n });\n },\n };\n}\n\nexport function Index<T>(list: ListAccessor<T>, each: IndexEach<T>): ListView {\n const read = readList(list);\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"index\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n item: WriteSignal<T>;\n }\n const rows: Row[] = [];\n\n effect(() => {\n const items = read() ?? [];\n // Live parent (see `For`), null only if the anchor was detached undisposed.\n const host = anchor.parentNode;\n\n for (let i = 0; i < items.length; i++) {\n if (i < rows.length) {\n // Slot reused: just push the new value into the row's item signal. The\n // signal's equality guard skips the update when the value is unchanged.\n rows[i].item.set(items[i]);\n } else {\n const item = signal(items[i]);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(() => item.get(), i);\n return d;\n });\n rows.push({ node, dispose, item });\n // Positions never move for index keying, so append at the tail (before\n // the anchor) in order. ORDERING CONTRACT (shared with For and the other\n // anchored insertions): the list owns the contiguous region ENDING at its\n // anchor comment. New rows go immediately before the anchor, so the list's\n // own rows always stay correctly ordered and grouped, and static siblings\n // before the anchor (or another list with its own anchor) are never\n // disturbed. Do NOT splice unrelated nodes into the middle of this region.\n host?.insertBefore(node, anchor);\n }\n }\n\n // Trailing slots that no longer exist: dispose and drop.\n if (items.length < rows.length) {\n // WHOLESALE CLEAR (same idea as For's zero-reuse fast path): every slot\n // vanishes and the host holds exactly this list's region (all rows +\n // the anchor), so one native `textContent = \"\"` replaces per-row\n // `remove()`. Guard failures (foreign sibling, detached row, shared\n // host) fall back to the per-row path. Disposal still runs per row.\n if (\n items.length === 0 &&\n host !== null &&\n host.lastChild === anchor &&\n host.firstChild === rows[0].node &&\n host.childNodes.length === rows.length + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows) {\n row.dispose();\n }\n } else {\n for (let i = items.length; i < rows.length; i++) {\n (rows[i].node as ChildNode).remove();\n rows[i].dispose();\n }\n }\n rows.length = items.length;\n }\n });\n\n onCleanup(() => {\n for (const row of rows) {\n row.dispose();\n }\n rows.length = 0;\n });\n },\n };\n}\n\n// --- custom element lifecycle (docs §8 (e)) ---------------------------------\n//\n// The exit point for ownership: a custom element that mounts a signals view under\n// `createRoot` on connect and disposes that root on disconnect. This wires the\n// reactive ownership tree to the real DOM lifecycle — every effect, resource and\n// listener created in `render()` is torn down when the element leaves the DOM, and\n// rebuilt fresh on reconnect. Subclasses only implement `render()`.\n//\n// SCOPE (v1 intentional constraints — drive these reactively, not via this base):\n// - No attribute reactivity. There is no `attributeChangedCallback`/\n// `observedAttributes` wiring: this base does NOT turn HTML attributes into\n// signals. Feed reactive inputs as signals/props from the code that constructs\n// the view (or have a subclass map attributes to signals itself).\n// - Shadow DOM is opt-in and subclass-owned. The default mount point is light DOM\n// (`this`); a subclass that wants encapsulation overrides `getMountPoint()` to\n// return a shadow root it created (e.g. `this.attachShadow(...)` in its\n// constructor). This base never calls attachShadow implicitly.\n// - Mount/unmount only: render() runs once per connect and the whole subtree is\n// disposed on disconnect — there is no partial/incremental re-render hook here\n// (fine-grained updates come from the signals wired inside render()).\n\n// TYPE-ONLY shape of the lifecycle base. `declare abstract class` emits NO runtime\n// code (so it does not reference `HTMLElement` at module-evaluation time — the whole\n// point of the lazy factory below), but it gives the exported `SignalsElement` value\n// and `createSignalsElement()`'s return a precise type that preserves the original\n// contract: `render` is `protected abstract` (a subclass MUST implement it and may\n// only reach it from within), and `getMountPoint` is `protected` (overridable). This\n// is the same surface the previous concrete `abstract class SignalsElement` exposed.\n// (Used only via `typeof` below; the lint rule does not see that as a value use.)\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare abstract class SignalsElementType extends HTMLElement {\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node;\n connectedCallback(): void;\n disconnectedCallback(): void;\n}\n\n/**\n * The lifecycle base contract: the abstract constructor type of the `SignalsElement`\n * base. Abstract, so `new SignalsElement()` is rejected (the base has an unimplemented\n * `render`) while `class X extends SignalsElement` is allowed. Returned by\n * {@link createSignalsElement} and the type of the {@link SignalsElement} value.\n */\nexport type SignalsElementClass = typeof SignalsElementType;\n\n// Memoized base class. Built lazily on first access so the `./dom` module can be\n// EVALUATED in a non-DOM environment (SSR pre-pass, a worker without a DOM shim)\n// without a top-level `class … extends HTMLElement` blowing up with\n// `ReferenceError: HTMLElement is not defined`. The class body is only constructed\n// when the consumer actually reaches for the base — at which point a DOM is required\n// and its absence yields a clear, actionable error instead of a raw ReferenceError.\nlet cachedBase: SignalsElementClass | null = null;\n\n/**\n * Build (once, memoized) the `SignalsElement` lifecycle base class. Resolves\n * `HTMLElement` at CALL TIME, so importing `@wcstack/signals/dom` no longer requires\n * a DOM at module-evaluation time — only *calling* this (or subclassing\n * {@link SignalsElement}) does.\n *\n * Contract:\n * - The `.` entry (`@wcstack/signals`) is non-DOM: it evaluates and runs in SSR,\n * Node, and Web Workers with no DOM globals.\n * - The `./dom` entry (`@wcstack/signals/dom`) may now also be *evaluated* without a\n * DOM (so an SSR pre-pass that imports it for the headless re-exports does not\n * crash). The DOM-touching surface — `h`/`render`/`For`/`Index` and this base —\n * still requires DOM globals when actually used.\n *\n * @throws a clear `Error` (not a raw `ReferenceError`) when no `HTMLElement` global is\n * present, naming the offending entry so the failure is self-explanatory.\n */\nexport function createSignalsElement(): SignalsElementClass {\n if (cachedBase !== null) {\n return cachedBase;\n }\n if (typeof HTMLElement === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: SignalsElement requires a DOM (HTMLElement is not defined). \" +\n \"The `./dom` entry's element/render surface is browser-only; in SSR/Node/worker \" +\n \"code import the headless core from `@wcstack/signals` instead, or inject a DOM \" +\n \"(e.g. happy-dom) before constructing custom elements.\",\n );\n }\n\n abstract class SignalsElementBase extends HTMLElement {\n private _dispose: (() => void) | null = null;\n\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node {\n return this;\n }\n\n connectedCallback(): void {\n if (this._dispose !== null) {\n return; // already mounted (defensive against a redundant connect)\n }\n const mount = this.getMountPoint();\n // If render() throws, createRoot disposes any effects it built before the throw,\n // so nothing leaks; _dispose stays null (the element is simply not mounted) and\n // a later disconnectedCallback safely no-ops. The error propagates to the caller.\n this._dispose = createRoot((dispose) => {\n mount.appendChild(this.render());\n return dispose;\n });\n }\n\n disconnectedCallback(): void {\n if (this._dispose === null) {\n return; // not mounted\n }\n this._dispose();\n this._dispose = null;\n const mount = this.getMountPoint();\n while (mount.firstChild) {\n mount.removeChild(mount.firstChild);\n }\n }\n }\n\n cachedBase = SignalsElementBase as unknown as SignalsElementClass;\n return cachedBase;\n}\n\n// `SignalsElement` is the ergonomic name to `extends`. It is a lazily-resolved alias\n// for the class built by `createSignalsElement()`: a Proxy that forwards construct /\n// get / has / getPrototypeOf to the real (memoized) base, building it on first touch.\n// This keeps `class X extends SignalsElement { … }` working exactly as before WHILE\n// deferring the `HTMLElement` reference to subclass-definition time (in a real DOM),\n// instead of `./dom` module-evaluation time (which may be a non-DOM SSR pre-pass).\n//\n// BREAKING note: the value is now a Proxy, not the class object literal. Subclassing,\n// `instanceof`, and static/prototype access all still work; a consumer that relied on\n// `SignalsElement` being a *frozen* concrete class reference (uncommon) should call\n// `createSignalsElement()` to obtain the real class.\n// The Proxy target is a never-called placeholder (every operation is intercepted by a\n// trap below); it only needs to be constructable/callable so `new` / `extends` and the\n// `apply` trap engage. It is intentionally a no-op and never executed.\n/* v8 ignore next */\nconst signalsElementTarget = function (): void {};\nexport const SignalsElement: SignalsElementClass = new Proxy(signalsElementTarget as unknown as SignalsElementClass, {\n construct(_target, args, newTarget): object {\n return Reflect.construct(createSignalsElement(), args, newTarget);\n },\n get(_target, prop, receiver): unknown {\n return Reflect.get(createSignalsElement(), prop, receiver);\n },\n has(_target, prop): boolean {\n return Reflect.has(createSignalsElement(), prop);\n },\n apply(): never {\n throw new TypeError(\"SignalsElement is a class and cannot be invoked without `new`/`extends`.\");\n },\n getPrototypeOf(): object | null {\n return Reflect.getPrototypeOf(createSignalsElement());\n },\n});\n\nfunction toNodes(value: unknown): Node[] {\n const out: Node[] = [];\n const visit = (v: unknown): void => {\n if (v == null || typeof v === \"boolean\") {\n return;\n }\n if (Array.isArray(v)) {\n v.forEach(visit);\n return;\n }\n if (v instanceof Node) {\n out.push(v);\n return;\n }\n out.push(document.createTextNode(String(v)));\n };\n visit(value);\n return out;\n}\n\n// --- mountNode: create + bind + mount a headless wc-bindable node -------------\n//\n// `bindNode` adapts an EXISTING element, which forces its caller to guarantee the\n// custom element class is already registered (the descriptor is read from\n// `el.constructor.wcBindable` at call time — an un-upgraded element has none).\n// `mountNode` closes that gap for the common signals shape where the app OWNS its\n// headless IO nodes: it creates the element AFTER the definition exists (so it is\n// upgraded at construction), binds it, then connects it. The recommended pairing\n// is a side-effect import of the package's `/auto` entry in the same module —\n// module evaluation order then guarantees the definition:\n//\n// import \"@wcstack/fetch/auto\";\n// const fetcher = mountNode(\"wcs-fetch\", { attrs: { url: \"/api/people\" } });\n// fetcher.signals.value.get();\n//\n// The internal order is deliberate: attributes are set BEFORE connect (shells read\n// their config in `connectedCallback`), and the adapter subscribes BEFORE connect,\n// so an event fired from `connectedCallback` is already observed — the missed-event\n// window is structurally zero, not merely closed by bindNode's re-seed. Like\n// `bindNode`, the adapter is NOT auto-registered with a reactive owner; teardown is\n// explicit via `unmount()` — to which `dispose()` is aliased, see MountedNode —\n// (compose with `onCleanup(() => m.unmount())` if the node should die with a\n// scope). See docs/signals-definition-timing.md for the full definition-timing\n// contract (optional packages via dynamic import, the remaining whenDefined /\n// <wcs-defined> territory).\n\nexport interface MountNodeOptions {\n /**\n * Attributes set on the element BEFORE it is connected (declarative pre-connect\n * config, e.g. `{ url: \"/api\", timeout: 5000 }`). HTML boolean-attribute\n * semantics: `true` sets an empty attribute, `false` omits it; other values are\n * stringified.\n */\n attrs?: Record<string, string | number | boolean>;\n /** Parent to append the element to. Default: `document.body`. */\n parent?: Node;\n /**\n * Explicit wc-bindable descriptor forwarded to `bindNode`. When given, the\n * tag-definition check is skipped — the escape hatch for binding a\n * non-custom-element tag, mirroring `bindNode`'s second parameter.\n */\n descriptor?: WcBindableDescriptor;\n}\n\nexport interface MountedNode<S extends NodeShape = DefaultNodeShape> extends BoundNode<S> {\n /** The created element (connected until `unmount()`). */\n readonly el: HTMLElement;\n /**\n * Full teardown: dispose the adapter AND remove the element from the DOM\n * (disconnect stops the shell's IO). Idempotent. On a `MountedNode`,\n * `dispose()` is an alias of this — mountNode owns the element's lifecycle,\n * so the package-wide teardown verb must not leave a connected element with\n * live IO behind (a silent leak for callers habituated to `bindNode`).\n */\n unmount(): void;\n}\n\nexport function mountNode<S extends NodeShape = DefaultNodeShape>(\n tagName: string,\n options: MountNodeOptions = {},\n): MountedNode<S> {\n // Call-time DOM guard (not module-time): `./dom` must evaluate in non-DOM realms\n // (SSR pre-pass / worker) — same contract (and message shape) as `createSignalsElement`.\n if (typeof document === \"undefined\" || typeof customElements === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: mountNode requires a DOM (document/customElements is not defined). \" +\n \"It creates and connects a live element, so it is browser-only; inject a DOM \" +\n \"(e.g. happy-dom) before calling, or keep headless work on `@wcstack/signals`.\",\n );\n }\n const { attrs, parent, descriptor } = options;\n // Custom element names are lowercase; the registry is exact-key while\n // createElement ASCII-lowercases — normalize once so mountNode(el.tagName)\n // (uppercase in HTML documents) hits the same definition the element would.\n const tag = tagName.toLowerCase();\n // Fail loud with the actual cause. Without this, bindNode's generic \"no\n // wc-bindable descriptor\" error hides that the tag simply isn't defined yet.\n if (!descriptor && !customElements.get(tag)) {\n throw new Error(\n `mountNode: \"<${tag}>\" is not defined. Import its defining module first (e.g. a side-effect ` +\n `\\`import \"@wcstack/<pkg>/auto\"\\` in this module — evaluation order then guarantees the definition). ` +\n `For a tag loaded by someone else, await customElements.whenDefined(\"${tag}\") or gate with ` +\n `<wcs-defined> before mounting. Binding a non-custom-element tag requires an explicit \\`descriptor\\`.`,\n );\n }\n\n const el = document.createElement(tag);\n if (attrs) {\n for (const [name, value] of Object.entries(attrs)) {\n if (value === false) {\n continue; // boolean-attribute semantics: false = absent\n }\n el.setAttribute(name, value === true ? \"\" : String(value));\n }\n }\n const bound = bindNode<S>(el, descriptor);\n (parent ?? document.body).appendChild(el);\n const unmount = (): void => {\n bound.dispose();\n el.remove();\n };\n return {\n ...bound,\n el,\n unmount,\n // Override the inherited adapter-only dispose(): on a MountedNode it would be\n // a silent PARTIAL teardown (signals inert, but the created element stays\n // connected with its shell's IO still running). mountNode owns the element,\n // so dispose === unmount.\n dispose: unmount,\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dom.esm.js","sources":["../src/dom.ts"],"sourcesContent":["// Fine-grained hyperscript (v1 design notes). The \"step before JSX\" (docs §4-1).\n//\n// `h(tag, props, ...children)` is the classic JSX factory shape, but it does NOT\n// build a virtual DOM and re-render. It creates a REAL DOM node once; any prop or\n// child given as a function (thunk) or signal is wired to a targeted `effect`, so\n// only that one binding updates when its signals change (Solid-style). This is\n// what keeps the package lightweight: no reconciler is shipped.\n//\n// JSX is intentionally NOT shipped. A consumer who wants it sets, in their own\n// tsconfig, `jsxFactory: \"h\"` + `jsxFragmentFactory: \"Fragment\"` (classic runtime)\n// — opting into a build step is their choice; the buildless path is calling `h`\n// directly. See docs/signals-state-design.md §4-1.\n//\n// OWNERSHIP: effects created here are owned by the enclosing reactive scope.\n// A reactive child's effect owns the prop/child effects of the subtree it builds,\n// so rebuilding that subtree disposes the previous one's effects (no leak). Mount\n// an app under `createRoot` so the whole tree can be torn down on unmount; a\n// dynamic child establishes its own scope automatically (it IS an effect).\n\nimport { signal, effect, onCleanup, createRoot, hasOwner, ReadSignal, WriteSignal } from \"./reactive.js\";\nimport { isDev, warnDev } from \"./dev.js\";\nimport { bindNode } from \"./bindNode.js\";\nimport type { BoundNode, NodeShape, DefaultNodeShape, WcBindableDescriptor } from \"./bindNode.js\";\n\n// `@wcstack/signals/dom` re-exports the headless core (signals, resource,\n// streamResource, bindNode, nodeSource) so UI code can import everything from one\n// module. Both built entries import a single shared `core-*.esm.js` chunk\n// (rollup.config.js `manualChunks`), so importing from BOTH `@wcstack/signals` and\n// `@wcstack/signals/dom` on a buildless page yields ONE reactive instance — the\n// tracking context is shared, not duplicated. `__tests__/packaging.test.ts` pins\n// this (both entries reference the same core chunk; a signal made via one entry is\n// observed by an effect from the other).\nexport {\n signal,\n computed,\n effect,\n createRoot,\n onCleanup,\n flushSync,\n} from \"./reactive.js\";\nexport type { ReadSignal, WriteSignal, EffectHandle, Cleanup, Equals } from \"./reactive.js\";\nexport { resource } from \"./resource.js\";\nexport type { ResourceState, ResourceOptions, ResourceSource } from \"./resource.js\";\nexport { streamResource } from \"./streamResource.js\";\nexport type {\n StreamResourceState,\n StreamResourceOptions,\n StreamSource,\n StreamProducer,\n StreamStatus,\n} from \"./streamResource.js\";\nexport { bindNode, nodeSource, DisposedError, isDisposedError } from \"./bindNode.js\";\nexport type {\n BoundNode,\n NodeShape,\n DefaultNodeShape,\n WcBindableDescriptor,\n WcBindableProperty,\n EventStreamOptions,\n} from \"./bindNode.js\";\n\nexport const Fragment = Symbol(\"signals.Fragment\");\n\nexport type Child = unknown;\nexport type Props = Record<string, unknown> | null;\n// h() always injects `children` into the props object it passes to a component, so\n// the parameter type makes that explicit (a component can declare `{ children }`).\nexport type Component = (\n props: Record<string, unknown> & { children?: Child[] },\n) => Node | Child[];\n\nfunction isReadSignal(value: unknown): value is ReadSignal<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { get?: unknown }).get === \"function\" &&\n typeof (value as { peek?: unknown }).peek === \"function\"\n );\n}\n\nexport function h(\n tag: string | typeof Fragment | Component,\n props?: Props,\n ...children: Child[]\n): Node {\n if (tag === Fragment) {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n }\n\n if (typeof tag === \"function\") {\n const result = tag({ ...(props ?? {}), children });\n return Array.isArray(result) ? wrapFragment(result) : result;\n }\n\n const el = createElement(tag);\n if (props) {\n for (const key in props) {\n bindProp(el, key, props[key]);\n }\n }\n appendChildren(el, children);\n return el;\n}\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\n// Tags created in the SVG namespace. Ambiguous names shared with HTML (`a`,\n// `title`, `script`, `style`) are intentionally EXCLUDED so ordinary HTML usage is\n// not broken; an SVG `<a>` / `<title>` must be created in an explicitly-namespaced\n// way by the caller. SVG DOM props are largely read-only, so `setProp`'s\n// settable-property check routes SVG attributes through `setAttribute` for free.\nconst SVG_TAGS = new Set([\n \"svg\", \"g\", \"path\", \"rect\", \"circle\", \"ellipse\", \"line\", \"polyline\", \"polygon\",\n \"text\", \"tspan\", \"defs\", \"use\", \"symbol\", \"marker\", \"linearGradient\",\n \"radialGradient\", \"stop\", \"clipPath\", \"mask\", \"pattern\", \"image\", \"foreignObject\",\n]);\n\nfunction createElement(tag: string): Element {\n return SVG_TAGS.has(tag)\n ? document.createElementNS(SVG_NS, tag)\n : document.createElement(tag);\n}\n\n/** Append `child` into `container`, resolving fragments/arrays. */\nexport function render(child: Child, container: Node): Node {\n appendChild(container, child);\n return container;\n}\n\nfunction wrapFragment(children: Child[]): DocumentFragment {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n}\n\n// --- props ------------------------------------------------------------------\n\n// Attribute names whose corresponding JS DOM property differs. `class` is handled\n// separately (it has reactive-falsy semantics in setProp), so it is not listed here.\nconst ATTR_TO_PROP: Record<string, string> = {\n for: \"htmlFor\",\n tabindex: \"tabIndex\",\n colspan: \"colSpan\",\n rowspan: \"rowSpan\",\n readonly: \"readOnly\",\n maxlength: \"maxLength\",\n minlength: \"minLength\",\n contenteditable: \"contentEditable\",\n};\n\n// True only if `key` resolves to a WRITABLE property on the element or its\n// prototype chain (a data property with `writable !== false`, or an accessor with a\n// setter). `key in el` is not enough: it also matches read-only members like\n// `firstChild` / `childNodes`, whose assignment throws in strict mode. The walk\n// starts at `el` itself so own instance fields (e.g. a custom element's properties)\n// are still matched, exactly as the previous `key in el` did — just without the\n// read-only false positives.\n//\n// MEMOIZATION: the prototype-chain walk runs on every bindProp/setProp. The result\n// depends only on the element's PROTOTYPE (its class) and the key, since DOM props\n// live on the prototype — not on per-instance own fields, which this library never\n// adds dynamically per element. So cache by `(prototype, key)`: a WeakMap keyed by\n// prototype (no leak — entries die with the class) holding a Map of key→result.\nconst settableCache = new WeakMap<object, Map<string, boolean>>();\n\nfunction computeSettable(el: Element, key: string): boolean {\n let obj: object | null = el;\n while (obj !== null) {\n const desc = Object.getOwnPropertyDescriptor(obj, key);\n if (desc) {\n return \"set\" in desc ? typeof desc.set === \"function\" : desc.writable !== false;\n }\n obj = Object.getPrototypeOf(obj);\n }\n return false;\n}\n\nfunction isSettableProperty(el: Element, key: string): boolean {\n // A real Element always has a prototype (HTMLElement.prototype → … → Object), so\n // `getPrototypeOf` is non-null here; use it as the cache key.\n const proto = Object.getPrototypeOf(el) as object;\n let byKey = settableCache.get(proto);\n if (byKey === undefined) {\n byKey = new Map<string, boolean>();\n settableCache.set(proto, byKey);\n }\n let result = byKey.get(key);\n if (result === undefined) {\n result = computeSettable(el, key);\n byKey.set(key, result);\n }\n return result;\n}\n\nfunction bindProp(el: Element, key: string, value: unknown): void {\n // Event handlers are special-cased BEFORE the reactive check: a function here is the\n // listener, not a thunk to track. `onClick` → \"click\" (lowercased); `onclick` /\n // `onadd-to-cart` → the name as written (\"click\", \"add-to-cart\" — data-wcs's `on<event>:`\n // form). A lowercase `onclick` used to fall through to the reactive path, so the handler\n // ran at render and never on click (docs/seam-apps.md, signals-shop).\n if (/^on[A-Za-z-]/.test(key) && typeof value === \"function\") {\n const type = /^on[A-Z]/.test(key) ? key.slice(2).toLowerCase() : key.slice(2);\n const listener = value as EventListener;\n el.addEventListener(type, listener);\n // Remove the listener when the owning scope is torn down (e.g. a dynamic\n // child that rebuilds this subtree), so handlers don't accumulate.\n onCleanup(() => el.removeEventListener(type, listener));\n return;\n }\n\n if (typeof value === \"function\") {\n effect(() => setProp(el, key, (value as () => unknown)()));\n return;\n }\n\n if (isReadSignal(value)) {\n effect(() => setProp(el, key, value.get()));\n return;\n }\n\n setProp(el, key, value);\n}\n\nfunction setProp(el: Element, key: string, value: unknown): void {\n if (key === \"style\") {\n setStyle(el as HTMLElement, value);\n return;\n }\n if (key === \"class\" || key === \"className\") {\n // Set the `class` ATTRIBUTE, not the `className` property. On an SVGElement\n // `className` is a read-only `SVGAnimatedString`, so assigning it throws in\n // strict mode (ESM is always strict) — `setAttribute(\"class\", …)` works for both\n // HTML and SVG. Treat false like null → empty class (consistent with the\n // attribute path's false-removes-it rule), so `() => cond && \"active\"` yields \"\"\n // (not \"false\") when the condition is falsy.\n // STRING-ONLY: a non-null/non-false value is coerced via String(value). Array\n // (`[\"a\", \"b\"]`) and object (`{ active: true }`) class forms are NOT supported —\n // they would stringify to \"a,b\" / \"[object Object]\". Compose the class string in\n // the binding itself (e.g. `() => [a, b].join(\" \")`) and pass a string. This keeps\n // the core free of a class-merging convention.\n el.setAttribute(\"class\", value == null || value === false ? \"\" : String(value));\n return;\n }\n // Remap the handful of attribute names whose JS property differs, so `for` /\n // `tabindex` / `colspan` etc. reach the right property instead of falling through\n // to setAttribute (which works for some but not e.g. `htmlFor`).\n const propKey = ATTR_TO_PROP[key] ?? key;\n if (isSettableProperty(el, propKey)) {\n // Known, WRITABLE DOM property (value, checked, disabled, id, htmlFor, ...).\n // The settability check excludes read-only members (firstChild, childNodes, …)\n // that `key in el` would wrongly accept — assigning to those throws in strict\n // mode; we fall through to the attribute path for them instead.\n //\n // NORMALIZATION: null/undefined are coerced to \"\" before assignment. Without\n // this, a STRING prop (id/title/value/src) given a reactive null/undefined\n // lands as the literal \"null\"/\"undefined\" (e.g. img.src=\"null\" fires a real\n // request) — a correctness footgun. \"\" clears the prop instead. Safe for\n // non-string props too: boolean props coerce \"\"→false (same as null), numeric\n // props coerce \"\"→0 (same as null). We do NOT normalize `false`:\n // `el.disabled = false` is the intended boolean clear.\n (el as unknown as Record<string, unknown>)[propKey] = value == null ? \"\" : value;\n return;\n }\n if (value == null || value === false) {\n el.removeAttribute(key);\n return;\n }\n if (value === true) {\n el.setAttribute(key, \"\");\n return;\n }\n el.setAttribute(key, String(value));\n}\n\nfunction setStyle(el: HTMLElement, value: unknown): void {\n if (value == null) {\n el.removeAttribute(\"style\");\n return;\n }\n if (typeof value === \"string\") {\n el.style.cssText = value;\n return;\n }\n // Object form: the object fully describes the style. Reset first so keys present\n // in a previous run but absent now are removed — otherwise a reactive style that\n // drops a key (e.g. {color,fontWeight} → {color}) would leave the stale property\n // applied. The object is the source of truth, so wiping cssText is correct here.\n el.style.cssText = \"\";\n const style = el.style as CSSStyleDeclaration & Record<string, string>;\n const obj = value as Record<string, string>;\n for (const k in obj) {\n // A key with a hyphen is either kebab-case (`font-weight`) or a CSS custom\n // property (`--accent`). Neither works via property assignment (`style[k]` would\n // just set an inert expando), so route them through setProperty. camelCase keys\n // (`fontWeight`) keep the faster property path.\n if (k.includes(\"-\")) {\n style.setProperty(k, obj[k]);\n } else {\n style[k] = obj[k];\n }\n }\n}\n\n// --- children ---------------------------------------------------------------\n\nfunction appendChildren(parent: Node, children: Child[]): void {\n for (const child of children) {\n appendChild(parent, child);\n }\n}\n\nfunction appendChild(parent: Node, child: Child): void {\n if (child == null || typeof child === \"boolean\") {\n return; // null / undefined / boolean render nothing\n }\n if (Array.isArray(child)) {\n for (const c of child) {\n appendChild(parent, c);\n }\n return;\n }\n if (isListView(child)) {\n // A keyed list (For / Index): it manages its own anchored region with in-place\n // reconciliation, so it does NOT go through the wholesale insertReactive path.\n child.mount(parent);\n return;\n }\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n if (typeof child === \"function\") {\n insertReactive(parent, child as () => unknown);\n return;\n }\n if (isReadSignal(child)) {\n insertReactive(parent, () => child.get());\n return;\n }\n parent.appendChild(document.createTextNode(String(child)));\n}\n\n/**\n * A reactive insertion point. An anchor comment marks the position; on each run\n * the previous nodes are removed and the freshly-resolved nodes inserted before\n * the anchor. Using `anchor.parentNode` (not the original `parent`) keeps it\n * correct after the subtree is moved/mounted elsewhere.\n *\n * PRECONDITION: the Nodes returned by `accessor` are owned by this insertion point\n * — do not move them to another parent externally. On the next run they are\n * removed from wherever they currently are (`node.parentNode?.removeChild`), so an\n * externally-moved node would be yanked out of its new home without warning.\n *\n * OWNERSHIP: the `effect` below is owned by the enclosing reactive scope at call\n * time (the `currentOwner`). Used under `createRoot` / `SignalsElement` (the module\n * header's mount contract) it is disposed on teardown. Calling `h`/`render` with a\n * reactive child OUTSIDE any owner (no `createRoot`/`SignalsElement`) leaves this\n * effect un-owned and therefore never cleaned up — by design, per that contract.\n */\nfunction insertReactive(parent: Node, accessor: () => unknown): void {\n if (isDev() && !hasOwner()) {\n // A reactive child inserted with no enclosing owner: the effect below is never\n // disposed (the module header documents this as by-design, but it is a frequent\n // accidental leak). Warn once in dev so the un-owned mount is visible.\n warnDev(\n \"UNOWNED_INSERT\",\n \"\",\n \"reactive child inserted with no owner — its update effect will never be \" +\n \"disposed and may leak. Mount under createRoot / SignalsElement.\",\n );\n }\n const anchor = document.createComment(\"\");\n parent.appendChild(anchor);\n let current: Node[] = [];\n\n effect(() => {\n const value = accessor();\n // FAST PATH: a plain text result that replaces a plain text result. The common\n // reactive child is a string/number thunk (`() => \\`count: ${n.get()}\\``); the\n // wholesale path would remove the old Text node, allocate a new one, and re-insert\n // it on every change. When BOTH the previous and next renders are a single Text\n // node, mutate the existing node's `data` in place instead — no allocation, no\n // remove/insert, and the same DOM node identity is preserved across updates.\n if ((typeof value === \"string\" || typeof value === \"number\") && current.length === 1) {\n const node = current[0];\n if (node.nodeType === 3 /* TEXT_NODE */) {\n (node as Text).data = String(value);\n return;\n }\n }\n const next = toNodes(value);\n for (const node of current) {\n node.parentNode?.removeChild(node);\n }\n const host = anchor.parentNode;\n if (host) {\n for (const node of next) {\n host.insertBefore(node, anchor);\n }\n }\n current = next;\n });\n\n // On teardown, drop the references to the inserted Nodes. The disposed effect's\n // closure still captures `current`; if anything retains the effect after disposal\n // (e.g. a parent owner kept alive longer than the subtree), those Nodes would be\n // pinned via that closure even though they have left the DOM. Clearing the array\n // lets them be GC'd as soon as the enclosing owner tears this insertion point down.\n onCleanup(() => {\n current = [];\n });\n}\n\n// --- keyed lists: For / Index (migration-plan §9-3) --------------------------\n//\n// `insertReactive` rebuilds its whole subtree on every change. For lists that is\n// wasteful (and drops per-row state). `For` / `Index` instead keep a stable DOM row\n// per item and reconcile in place. Each row is built under its OWN `createRoot`, so\n// removing a row disposes exactly that row's effects/resources/listeners — the owner\n// tree (§8 (d)) is what makes this leak-free. The reconcile runs in a single\n// `effect` owned by the enclosing scope; an `onCleanup` disposes surviving rows when\n// that scope (e.g. the component) tears down.\n//\n// CONTRACT: `each` must return a SINGLE Node (one row = one node). Keys (For) must\n// be unique. `For` keys by value identity (=== / explicit `key`) and passes the\n// index as an accessor (it changes on move); `Index` keys by position and passes the\n// item as an accessor (the value at a slot changes, the slot does not).\n\nexport type ListAccessor<T> = ReadSignal<readonly T[]> | (() => readonly T[]);\n/**\n * `For`'s row builder. `item` is the item the row was built for — a plain value. A keyed row is\n * kept while its key is (an immutable update hands it a new object under the same key), so read\n * what changes through `current`, an accessor of the item under the row's key now\n * (`() => current().text`). docs/seam-apps.md, signals-shop.\n */\nexport type ForEach<T> = (item: T, index: () => number, current: () => T) => Node;\nexport type IndexEach<T> = (item: () => T, index: number) => Node;\n\n/**\n * The return type of {@link For} / {@link Index}: a keyed list that owns an anchored\n * region and reconciles rows in place. Exported (D4) so consumers can annotate\n * helpers that build or pass around lists. `mount` is called by `h`/`render` when the\n * list is used as a child; `__wcsList` is the brand `appendChild` checks.\n */\nexport interface ListView {\n readonly __wcsList: true;\n mount(parent: Node): void;\n}\n\nfunction isListView(value: unknown): value is ListView {\n return typeof value === \"object\" && value !== null && (value as ListView).__wcsList === true;\n}\n\nfunction readList<T>(list: ListAccessor<T>): () => readonly T[] {\n return isReadSignal(list) ? () => (list as ReadSignal<readonly T[]>).get() : (list as () => readonly T[]);\n}\n\nexport interface ForOptions<T> {\n /** Derive a unique key per item. Default: the item value itself (identity). */\n key?: (item: T, index: number) => unknown;\n}\n\n// --- LIS-based DOM reorder ---------------------------------------------------\n//\n// `reconcileOrder` brings the live DOM under `host` (the contiguous region ending\n// at `anchor`) into `order` — the desired final node sequence — using the FEWEST\n// `insertBefore` moves, while producing EXACTLY the order a naive full re-place\n// would. The naive approach (walk and insert every out-of-place node) does up to\n// O(n) DOM moves on a full reverse or a head insert; here we instead keep the\n// largest set of reused rows that are ALREADY in the right relative order, and\n// move only the others (Solid's reconcileArrays / udomdiff idea).\n//\n// HOW: `prevOrder` is the node sequence the previous run left in the DOM. For each\n// node in the new `order`, a reused row maps to its index in `prevOrder`; a freshly\n// created row has no previous position. The longest increasing subsequence (LIS)\n// of those previous indices marks the reused rows that need NOT move (their pairwise\n// relative order is already correct). Every other node — fresh ones, and reused\n// ones outside the LIS — is inserted before its already-correct successor, walking\n// back-to-front so the \"successor\" reference is always a settled node or the anchor.\n\n/**\n * Indices into `arr` (with value -1 meaning \"no previous position\") whose values\n * form a longest strictly-increasing subsequence. Entries equal to -1 are treated\n * as never part of the subsequence (a fresh node always moves). Classic\n * patience-sorting LIS in O(n log n); returns the chosen indices in ascending order.\n */\nfunction longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n // `tails[k]` = index (into arr) of the smallest tail of an increasing\n // subsequence of length k+1. `prev[i]` = predecessor index, to rebuild the chain.\n const tails: number[] = [];\n const prev: number[] = new Array(n).fill(-1);\n for (let i = 0; i < n; i++) {\n const value = arr[i];\n if (value < 0) {\n continue; // fresh node: not eligible for the stable subsequence\n }\n // Binary search for the first tail whose value is >= this value, and replace it\n // (or extend the tails when this value beats every tail).\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (arr[tails[mid]] < value) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n if (lo > 0) {\n prev[i] = tails[lo - 1];\n }\n tails[lo] = i;\n }\n // Rebuild the index chain from the longest tail backwards.\n const result: number[] = [];\n let k = tails.length > 0 ? tails[tails.length - 1] : -1;\n while (k >= 0) {\n result.push(k);\n k = prev[k];\n }\n result.reverse();\n return result;\n}\n\nfunction reconcileOrder(\n host: Node,\n anchor: Node,\n order: Node[],\n prevOrder: Node[],\n): void {\n const n = order.length;\n if (n === 0) {\n return; // nothing to place (removals already happened)\n }\n\n // Map each previous node to its previous position, so a node in `order` can look\n // up where it used to be. A node absent from this map is FRESH (created this run,\n // or the first run where prevOrder is empty) and is encoded as -1 — it always moves.\n const prevIndex = new Map<Node, number>();\n for (let i = 0; i < prevOrder.length; i++) {\n prevIndex.set(prevOrder[i], i);\n }\n\n // previous-position sequence aligned to the new order. -1 marks a fresh node.\n const seq: number[] = new Array(n);\n for (let i = 0; i < n; i++) {\n const p = prevIndex.get(order[i]);\n seq[i] = p === undefined ? -1 : p;\n }\n\n // Rows whose relative order is already correct: leave them in place, move the rest.\n const lis = longestIncreasingSubsequence(seq);\n let lisPtr = lis.length - 1;\n\n // Walk back-to-front. `ref` is the node that must follow the one being placed; it\n // starts at the anchor (the region's tail) and becomes each placed node. A node in\n // the LIS is the maximal already-correctly-ordered set, so it is left untouched\n // (only adopted as the new `ref`). Every OTHER node is, by construction, out of\n // position relative to its settled successor and is inserted before `ref` — no\n // \"is it already in place?\" guard is needed (it never is, unlike the old\n // full-walk reconciler which visited correctly-placed nodes too).\n let ref: Node = anchor;\n for (let i = n - 1; i >= 0; i--) {\n const node = order[i];\n if (lisPtr >= 0 && lis[lisPtr] === i) {\n lisPtr--; // stable: do not move\n } else {\n host.insertBefore(node, ref);\n }\n ref = node;\n }\n}\n\n// Dev-only key sanity check (no effect in production — guarded by `isDev()` at the\n// call site so this is never reached when dev is off). Flags the silent-failure key\n// shapes: a nullish key (NaN / null / undefined collide under SameValueZero, so two\n// such items map to one row and a row is silently dropped), and — when no explicit\n// `key` was given — a non-primitive item used as its own identity key (every render\n// gets a fresh object reference, so the row is rebuilt instead of reused, silently\n// dropping per-row state). Warns once per distinct shape (deduped in warnDev).\nfunction checkKeyDev(key: unknown, item: unknown, hasExplicitKey: boolean): void {\n if (key == null || (typeof key === \"number\" && Number.isNaN(key))) {\n warnDev(\n \"NULLISH_KEY\",\n String(key),\n \"For: a key is null/undefined/NaN. Such keys collide under SameValueZero, \" +\n \"so rows silently merge/drop. Provide a stable unique `key`.\",\n { key },\n );\n return;\n }\n if (!hasExplicitKey && (typeof key === \"object\" || typeof key === \"function\")) {\n warnDev(\n \"NON_PRIMITIVE_KEY\",\n typeof key,\n \"For: a non-primitive item is used as its own key (no `key` option given). \" +\n \"Object identity changes across renders, so every row is rebuilt and per-row \" +\n \"state is lost. Pass `{ key: item => item.id }`.\",\n { item },\n );\n }\n}\n\nexport function For<T>(list: ListAccessor<T>, each: ForEach<T>, options?: ForOptions<T>): ListView {\n const read = readList(list);\n const keyOf = options?.key;\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"for\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n idx: WriteSignal<number>;\n /** The item under the row's key now (`each`'s `current`). */\n cur: WriteSignal<T>;\n }\n let rows = new Map<unknown, Row>();\n // The node order placed by the previous reconcile run. Empty on first run.\n // Used to find which reused rows already sit in increasing relative order so\n // only the rest are moved (LIS reorder, see reconcileOrder).\n let prevOrder: Node[] = [];\n\n const make = (item: T, i: number): Row => {\n const idx = signal(i);\n const cur = signal(item);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(item, () => idx.get(), () => cur.get());\n return d;\n });\n return { node, dispose, idx, cur };\n };\n\n effect(() => {\n const items = read() ?? [];\n\n // Key-uniqueness PRE-PASS (no side effects): throwing here, before any row is\n // created or moved, keeps a duplicate-key error from leaving half-built rows\n // orphaned (make() runs createRoot) and the DOM mid-reorder. Keys are reused\n // below so keyOf runs once per item.\n const keys: unknown[] = [];\n const seen = new Set<unknown>();\n const dev = isDev();\n for (let i = 0; i < items.length; i++) {\n const k = keyOf ? keyOf(items[i], i) : items[i];\n if (dev) {\n checkKeyDev(k, items[i], keyOf !== undefined);\n }\n if (seen.has(k)) {\n if (dev) {\n // The throw below still halts (production behaviour unchanged); the warn\n // adds the offending key + a pointer to the cause so the silent\n // \"updates stopped\" symptom is diagnosable.\n warnDev(\n \"DUPLICATE_KEY\",\n String(k),\n `For: duplicate key \"${String(k)}\" at index ${i} — keys must be unique. ` +\n \"Rendering throws and the list stops updating until keys are fixed.\",\n { key: k, index: i },\n );\n }\n throw new Error(`For: duplicate key \"${String(k)}\" — keys must be unique.`);\n }\n seen.add(k);\n keys.push(k);\n }\n\n const next = new Map<unknown, Row>();\n const order: Node[] = [];\n\n // Rows freshly created in THIS run (not reused from `rows`). If a later\n // `make()` — i.e. a user `each` — throws mid-loop, the rows already built\n // here are owned by their own detached `createRoot` and are not yet tracked\n // in any surviving map, so they would leak. Dispose them before re-throwing,\n // leaving the old `rows` map untouched (it is recoverable on the next run).\n const fresh: Row[] = [];\n try {\n for (let i = 0; i < items.length; i++) {\n const k = keys[i];\n let row = rows.get(k);\n if (row) {\n if (row.idx.peek() !== i) {\n row.idx.set(i); // position changed — refresh the index accessor\n }\n row.cur.set(items[i]); // the item under the key now (a no-op when it is the same)\n } else {\n row = make(items[i], i);\n fresh.push(row);\n }\n next.set(k, row);\n order.push(row.node);\n }\n } catch (err) {\n for (const row of fresh) {\n row.dispose();\n }\n throw err;\n }\n\n // The LIVE parent (`anchor.parentNode`, not the mount arg) so the region\n // stays correct after being moved (e.g. built inside a Fragment, then\n // appended elsewhere). `host` is null only if the anchor was detached\n // without disposing this scope (a misuse) — then there is nothing to\n // place into. Resolved before the removal phase so the wholesale-removal\n // fast path below can use it.\n const host = anchor.parentNode;\n\n // Dispose rows whose key vanished. `remove()` no-ops if already detached.\n if (rows.size > 0 && next.size === fresh.length) {\n // ZERO-REUSE run: no existing key survives (clear, or a full replacement\n // with disjoint keys), so EVERY current row is removed. When the host\n // contains exactly this list's region — first child is the region's\n // first row, last child is the anchor, and the child count matches\n // rows + anchor — detach them all with a single native\n // `textContent = \"\"` and re-append the anchor, instead of one\n // `remove()` per row (the dominant cost of clearing large lists).\n // Any deviation (foreign sibling, externally detached row, shared\n // host) fails the guard and falls back to the per-row path.\n // Disposal always runs per row; only the DOM detachment is batched.\n if (\n host !== null &&\n host.lastChild === anchor &&\n prevOrder.length > 0 &&\n host.firstChild === prevOrder[0] &&\n host.childNodes.length === rows.size + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows.values()) {\n row.dispose();\n }\n } else {\n for (const row of rows.values()) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n } else {\n for (const [k, row] of rows) {\n if (!next.has(k)) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n }\n if (host) {\n reconcileOrder(host, anchor, order, prevOrder);\n }\n\n // Snapshot this run's final order so the NEXT run's reconcile can detect\n // which rows kept their relative position (the LIS basis below). Capturing\n // the array we just placed avoids re-deriving it from the map.\n prevOrder = order;\n rows = next;\n });\n\n onCleanup(() => {\n for (const row of rows.values()) {\n row.dispose();\n }\n rows.clear();\n });\n },\n };\n}\n\nexport function Index<T>(list: ListAccessor<T>, each: IndexEach<T>): ListView {\n const read = readList(list);\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"index\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n item: WriteSignal<T>;\n }\n const rows: Row[] = [];\n\n effect(() => {\n const items = read() ?? [];\n // Live parent (see `For`), null only if the anchor was detached undisposed.\n const host = anchor.parentNode;\n\n for (let i = 0; i < items.length; i++) {\n if (i < rows.length) {\n // Slot reused: just push the new value into the row's item signal. The\n // signal's equality guard skips the update when the value is unchanged.\n rows[i].item.set(items[i]);\n } else {\n const item = signal(items[i]);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(() => item.get(), i);\n return d;\n });\n rows.push({ node, dispose, item });\n // Positions never move for index keying, so append at the tail (before\n // the anchor) in order. ORDERING CONTRACT (shared with For and the other\n // anchored insertions): the list owns the contiguous region ENDING at its\n // anchor comment. New rows go immediately before the anchor, so the list's\n // own rows always stay correctly ordered and grouped, and static siblings\n // before the anchor (or another list with its own anchor) are never\n // disturbed. Do NOT splice unrelated nodes into the middle of this region.\n host?.insertBefore(node, anchor);\n }\n }\n\n // Trailing slots that no longer exist: dispose and drop.\n if (items.length < rows.length) {\n // WHOLESALE CLEAR (same idea as For's zero-reuse fast path): every slot\n // vanishes and the host holds exactly this list's region (all rows +\n // the anchor), so one native `textContent = \"\"` replaces per-row\n // `remove()`. Guard failures (foreign sibling, detached row, shared\n // host) fall back to the per-row path. Disposal still runs per row.\n if (\n items.length === 0 &&\n host !== null &&\n host.lastChild === anchor &&\n host.firstChild === rows[0].node &&\n host.childNodes.length === rows.length + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows) {\n row.dispose();\n }\n } else {\n for (let i = items.length; i < rows.length; i++) {\n (rows[i].node as ChildNode).remove();\n rows[i].dispose();\n }\n }\n rows.length = items.length;\n }\n });\n\n onCleanup(() => {\n for (const row of rows) {\n row.dispose();\n }\n rows.length = 0;\n });\n },\n };\n}\n\n// --- custom element lifecycle (docs §8 (e)) ---------------------------------\n//\n// The exit point for ownership: a custom element that mounts a signals view under\n// `createRoot` on connect and disposes that root on disconnect. This wires the\n// reactive ownership tree to the real DOM lifecycle — every effect, resource and\n// listener created in `render()` is torn down when the element leaves the DOM, and\n// rebuilt fresh on reconnect. Subclasses only implement `render()`.\n//\n// SCOPE (v1 intentional constraints — drive these reactively, not via this base):\n// - No attribute reactivity. There is no `attributeChangedCallback`/\n// `observedAttributes` wiring: this base does NOT turn HTML attributes into\n// signals. Feed reactive inputs as signals/props from the code that constructs\n// the view (or have a subclass map attributes to signals itself).\n// - Shadow DOM is opt-in and subclass-owned. The default mount point is light DOM\n// (`this`); a subclass that wants encapsulation overrides `getMountPoint()` to\n// return a shadow root it created (e.g. `this.attachShadow(...)` in its\n// constructor). This base never calls attachShadow implicitly.\n// - Mount/unmount only: render() runs once per connect and the whole subtree is\n// disposed on disconnect — there is no partial/incremental re-render hook here\n// (fine-grained updates come from the signals wired inside render()).\n\n// TYPE-ONLY shape of the lifecycle base. `declare abstract class` emits NO runtime\n// code (so it does not reference `HTMLElement` at module-evaluation time — the whole\n// point of the lazy factory below), but it gives the exported `SignalsElement` value\n// and `createSignalsElement()`'s return a precise type that preserves the original\n// contract: `render` is `protected abstract` (a subclass MUST implement it and may\n// only reach it from within), and `getMountPoint` is `protected` (overridable). This\n// is the same surface the previous concrete `abstract class SignalsElement` exposed.\n// (Used only via `typeof` below; the lint rule does not see that as a value use.)\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare abstract class SignalsElementType extends HTMLElement {\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node;\n connectedCallback(): void;\n disconnectedCallback(): void;\n}\n\n/**\n * The lifecycle base contract: the abstract constructor type of the `SignalsElement`\n * base. Abstract, so `new SignalsElement()` is rejected (the base has an unimplemented\n * `render`) while `class X extends SignalsElement` is allowed. Returned by\n * {@link createSignalsElement} and the type of the {@link SignalsElement} value.\n */\nexport type SignalsElementClass = typeof SignalsElementType;\n\n// Memoized base class. Built lazily on first access so the `./dom` module can be\n// EVALUATED in a non-DOM environment (SSR pre-pass, a worker without a DOM shim)\n// without a top-level `class … extends HTMLElement` blowing up with\n// `ReferenceError: HTMLElement is not defined`. The class body is only constructed\n// when the consumer actually reaches for the base — at which point a DOM is required\n// and its absence yields a clear, actionable error instead of a raw ReferenceError.\nlet cachedBase: SignalsElementClass | null = null;\n\n/**\n * Build (once, memoized) the `SignalsElement` lifecycle base class. Resolves\n * `HTMLElement` at CALL TIME, so importing `@wcstack/signals/dom` no longer requires\n * a DOM at module-evaluation time — only *calling* this (or subclassing\n * {@link SignalsElement}) does.\n *\n * Contract:\n * - The `.` entry (`@wcstack/signals`) is non-DOM: it evaluates and runs in SSR,\n * Node, and Web Workers with no DOM globals.\n * - The `./dom` entry (`@wcstack/signals/dom`) may now also be *evaluated* without a\n * DOM (so an SSR pre-pass that imports it for the headless re-exports does not\n * crash). The DOM-touching surface — `h`/`render`/`For`/`Index` and this base —\n * still requires DOM globals when actually used.\n *\n * @throws a clear `Error` (not a raw `ReferenceError`) when no `HTMLElement` global is\n * present, naming the offending entry so the failure is self-explanatory.\n */\nexport function createSignalsElement(): SignalsElementClass {\n if (cachedBase !== null) {\n return cachedBase;\n }\n if (typeof HTMLElement === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: SignalsElement requires a DOM (HTMLElement is not defined). \" +\n \"The `./dom` entry's element/render surface is browser-only; in SSR/Node/worker \" +\n \"code import the headless core from `@wcstack/signals` instead, or inject a DOM \" +\n \"(e.g. happy-dom) before constructing custom elements.\",\n );\n }\n\n abstract class SignalsElementBase extends HTMLElement {\n private _dispose: (() => void) | null = null;\n\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node {\n return this;\n }\n\n connectedCallback(): void {\n if (this._dispose !== null) {\n return; // already mounted (defensive against a redundant connect)\n }\n const mount = this.getMountPoint();\n // If render() throws, createRoot disposes any effects it built before the throw,\n // so nothing leaks; _dispose stays null (the element is simply not mounted) and\n // a later disconnectedCallback safely no-ops. The error propagates to the caller.\n this._dispose = createRoot((dispose) => {\n mount.appendChild(this.render());\n return dispose;\n });\n }\n\n disconnectedCallback(): void {\n if (this._dispose === null) {\n return; // not mounted\n }\n this._dispose();\n this._dispose = null;\n const mount = this.getMountPoint();\n while (mount.firstChild) {\n mount.removeChild(mount.firstChild);\n }\n }\n }\n\n cachedBase = SignalsElementBase as unknown as SignalsElementClass;\n return cachedBase;\n}\n\n// `SignalsElement` is the ergonomic name to `extends`. It is a lazily-resolved alias\n// for the class built by `createSignalsElement()`: a Proxy that forwards construct /\n// get / has / getPrototypeOf to the real (memoized) base, building it on first touch.\n// This keeps `class X extends SignalsElement { … }` working exactly as before WHILE\n// deferring the `HTMLElement` reference to subclass-definition time (in a real DOM),\n// instead of `./dom` module-evaluation time (which may be a non-DOM SSR pre-pass).\n//\n// BREAKING note: the value is now a Proxy, not the class object literal. Subclassing,\n// `instanceof`, and static/prototype access all still work; a consumer that relied on\n// `SignalsElement` being a *frozen* concrete class reference (uncommon) should call\n// `createSignalsElement()` to obtain the real class.\n// The Proxy target is a never-called placeholder (every operation is intercepted by a\n// trap below); it only needs to be constructable/callable so `new` / `extends` and the\n// `apply` trap engage. It is intentionally a no-op and never executed.\n/* v8 ignore next */\nconst signalsElementTarget = function (): void {};\nexport const SignalsElement: SignalsElementClass = new Proxy(signalsElementTarget as unknown as SignalsElementClass, {\n construct(_target, args, newTarget): object {\n return Reflect.construct(createSignalsElement(), args, newTarget);\n },\n get(_target, prop, receiver): unknown {\n return Reflect.get(createSignalsElement(), prop, receiver);\n },\n has(_target, prop): boolean {\n return Reflect.has(createSignalsElement(), prop);\n },\n apply(): never {\n throw new TypeError(\"SignalsElement is a class and cannot be invoked without `new`/`extends`.\");\n },\n getPrototypeOf(): object | null {\n return Reflect.getPrototypeOf(createSignalsElement());\n },\n});\n\nfunction toNodes(value: unknown): Node[] {\n const out: Node[] = [];\n const visit = (v: unknown): void => {\n if (v == null || typeof v === \"boolean\") {\n return;\n }\n if (Array.isArray(v)) {\n v.forEach(visit);\n return;\n }\n if (v instanceof Node) {\n out.push(v);\n return;\n }\n out.push(document.createTextNode(String(v)));\n };\n visit(value);\n return out;\n}\n\n// --- mountNode: create + bind + mount a headless wc-bindable node -------------\n//\n// `bindNode` adapts an EXISTING element, which forces its caller to guarantee the\n// custom element class is already registered (the descriptor is read from\n// `el.constructor.wcBindable` at call time — an un-upgraded element has none).\n// `mountNode` closes that gap for the common signals shape where the app OWNS its\n// headless IO nodes: it creates the element AFTER the definition exists (so it is\n// upgraded at construction), binds it, then connects it. The recommended pairing\n// is a side-effect import of the package's `/auto` entry in the same module —\n// module evaluation order then guarantees the definition:\n//\n// import \"@wcstack/fetch/auto\";\n// const fetcher = mountNode(\"wcs-fetch\", { attrs: { url: \"/api/people\" } });\n// fetcher.signals.value.get();\n//\n// The internal order is deliberate: attributes are set BEFORE connect (shells read\n// their config in `connectedCallback`), and the adapter subscribes BEFORE connect,\n// so an event fired from `connectedCallback` is already observed — the missed-event\n// window is structurally zero, not merely closed by bindNode's re-seed. Like\n// `bindNode`, the adapter is NOT auto-registered with a reactive owner; teardown is\n// explicit via `unmount()` — to which `dispose()` is aliased, see MountedNode —\n// (compose with `onCleanup(() => m.unmount())` if the node should die with a\n// scope). See docs/signals-definition-timing.md for the full definition-timing\n// contract (optional packages via dynamic import, the remaining whenDefined /\n// <wcs-defined> territory).\n\nexport interface MountNodeOptions {\n /**\n * Attributes set on the element BEFORE it is connected (declarative pre-connect\n * config, e.g. `{ url: \"/api\", timeout: 5000 }`). HTML boolean-attribute\n * semantics: `true` sets an empty attribute, `false` omits it; other values are\n * stringified.\n */\n attrs?: Record<string, string | number | boolean>;\n /** Parent to append the element to. Default: `document.body`. */\n parent?: Node;\n /**\n * Explicit wc-bindable descriptor forwarded to `bindNode`. When given, the\n * tag-definition check is skipped — the escape hatch for binding a\n * non-custom-element tag, mirroring `bindNode`'s second parameter.\n */\n descriptor?: WcBindableDescriptor;\n}\n\nexport interface MountedNode<S extends NodeShape = DefaultNodeShape> extends BoundNode<S> {\n /** The created element (connected until `unmount()`). */\n readonly el: HTMLElement;\n /**\n * Full teardown: dispose the adapter AND remove the element from the DOM\n * (disconnect stops the shell's IO). Idempotent. On a `MountedNode`,\n * `dispose()` is an alias of this — mountNode owns the element's lifecycle,\n * so the package-wide teardown verb must not leave a connected element with\n * live IO behind (a silent leak for callers habituated to `bindNode`).\n */\n unmount(): void;\n}\n\nexport function mountNode<S extends NodeShape = DefaultNodeShape>(\n tagName: string,\n options: MountNodeOptions = {},\n): MountedNode<S> {\n // Call-time DOM guard (not module-time): `./dom` must evaluate in non-DOM realms\n // (SSR pre-pass / worker) — same contract (and message shape) as `createSignalsElement`.\n if (typeof document === \"undefined\" || typeof customElements === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: mountNode requires a DOM (document/customElements is not defined). \" +\n \"It creates and connects a live element, so it is browser-only; inject a DOM \" +\n \"(e.g. happy-dom) before calling, or keep headless work on `@wcstack/signals`.\",\n );\n }\n const { attrs, parent, descriptor } = options;\n // Custom element names are lowercase; the registry is exact-key while\n // createElement ASCII-lowercases — normalize once so mountNode(el.tagName)\n // (uppercase in HTML documents) hits the same definition the element would.\n const tag = tagName.toLowerCase();\n // Fail loud with the actual cause. Without this, bindNode's generic \"no\n // wc-bindable descriptor\" error hides that the tag simply isn't defined yet.\n if (!descriptor && !customElements.get(tag)) {\n throw new Error(\n `mountNode: \"<${tag}>\" is not defined. Import its defining module first (e.g. a side-effect ` +\n `\\`import \"@wcstack/<pkg>/auto\"\\` in this module — evaluation order then guarantees the definition). ` +\n `For a tag loaded by someone else, await customElements.whenDefined(\"${tag}\") or gate with ` +\n `<wcs-defined> before mounting. Binding a non-custom-element tag requires an explicit \\`descriptor\\`.`,\n );\n }\n\n const el = document.createElement(tag);\n if (attrs) {\n for (const [name, value] of Object.entries(attrs)) {\n if (value === false) {\n continue; // boolean-attribute semantics: false = absent\n }\n el.setAttribute(name, value === true ? \"\" : String(value));\n }\n }\n const bound = bindNode<S>(el, descriptor);\n (parent ?? document.body).appendChild(el);\n const unmount = (): void => {\n bound.dispose();\n el.remove();\n };\n return {\n ...bound,\n el,\n unmount,\n // Override the inherited adapter-only dispose(): on a MountedNode it would be\n // a silent PARTIAL teardown (signals inert, but the created element stays\n // connected with its shell's IO still running). mountNode owns the element,\n // so dispose === unmount.\n dispose: unmount,\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{e,o as t,b as o,g as s,h as l,w as a,s as u,a as p}from"./core-CUHdCgQ2.esm.min.js";export{D as DisposedError,c as computed,f as flushSync,i as isDisposedError,n as nodeSource,r as resource,d as streamResource}from"./core-CUHdCgQ2.esm.min.js";const m=Symbol("signals.Fragment");function h(e){return"object"==typeof e&&null!==e&&"function"==typeof e.get&&"function"==typeof e.peek}function g(e,t,...n){if(e===m){const e=document.createDocumentFragment();return N(e,n),e}if("function"==typeof e){const o=e({...t??{},children:n});return Array.isArray(o)?function(e){const t=document.createDocumentFragment();return N(t,e),t}(o):o}const o=function(e){return w.has(e)?document.createElementNS(y,e):document.createElement(e)}(e);if(t)for(const e in t)C(o,e,t[e]);return N(o,n),o}const y="http://www.w3.org/2000/svg",w=new Set(["svg","g","path","rect","circle","ellipse","line","polyline","polygon","text","tspan","defs","use","symbol","marker","linearGradient","radialGradient","stop","clipPath","mask","pattern","image","foreignObject"]);function b(e,t){return x(t,e),t}const v={for:"htmlFor",tabindex:"tabIndex",colspan:"colSpan",rowspan:"rowSpan",readonly:"readOnly",maxlength:"maxLength",minlength:"minLength",contenteditable:"contentEditable"},k=new WeakMap;function E(e,t){const n=Object.getPrototypeOf(e);let o=k.get(n);void 0===o&&(o=new Map,k.set(n,o));let s=o.get(t);return void 0===s&&(s=function(e,t){let n=e;for(;null!==n;){const e=Object.getOwnPropertyDescriptor(n,t);if(e)return"set"in e?"function"==typeof e.set:!1!==e.writable;n=Object.getPrototypeOf(n)}return!1}(e,t),o.set(t,s)),s}function C(n,o,s){if(/^on[A-Z]/.test(o)&&"function"==typeof s){const e=o.slice(2).toLowerCase(),r=s;return n.addEventListener(e,r),void t(()=>n.removeEventListener(e,r))}"function"!=typeof s?h(s)?e(()=>S(n,o,s.get())):S(n,o,s):e(()=>S(n,o,s()))}function S(e,t,n){if("style"===t)return void function(e,t){if(null==t)return void e.removeAttribute("style");if("string"==typeof t)return void(e.style.cssText=t);e.style.cssText="";const n=e.style,o=t;for(const e in o)e.includes("-")?n.setProperty(e,o[e]):n[e]=o[e]}(e,n);if("class"===t||"className"===t)return void e.setAttribute("class",null==n||!1===n?"":String(n));const o=v[t]??t;E(e,o)?e[o]=null==n?"":n:null!=n&&!1!==n?!0!==n?e.setAttribute(t,String(n)):e.setAttribute(t,""):e.removeAttribute(t)}function N(e,t){for(const n of t)x(e,n)}function x(e,t){var n;if(null!=t&&"boolean"!=typeof t)if(Array.isArray(t))for(const n of t)x(e,n);else"object"!=typeof(n=t)||null===n||!0!==n.__wcsList?t instanceof Node?e.appendChild(t):"function"!=typeof t?h(t)?O(e,()=>t.get()):e.appendChild(document.createTextNode(String(t))):O(e,t):t.mount(e)}function O(n,o){s()&&!l()&&a("UNOWNED_INSERT","","reactive child inserted with no owner — its update effect will never be disposed and may leak. Mount under createRoot / SignalsElement.");const r=document.createComment("");n.appendChild(r);let i=[];e(()=>{const e=o();if(("string"==typeof e||"number"==typeof e)&&1===i.length){const t=i[0];if(3===t.nodeType)return void(t.data=String(e))}const t=function(e){const t=[],n=e=>{null!=e&&"boolean"!=typeof e&&(Array.isArray(e)?e.forEach(n):e instanceof Node?t.push(e):t.push(document.createTextNode(String(e))))};return n(e),t}(e);for(const e of i)e.parentNode?.removeChild(e);const n=r.parentNode;if(n)for(const e of t)n.insertBefore(e,r);i=t}),t(()=>{i=[]})}function M(e){return h(e)?()=>e.get():e}function _(e,t,n,o){const s=n.length;if(0===s)return;const r=new Map;for(let e=0;e<o.length;e++)r.set(o[e],e);const i=new Array(s);for(let e=0;e<s;e++){const t=r.get(n[e]);i[e]=void 0===t?-1:t}const c=function(e){const t=e.length,n=[],o=new Array(t).fill(-1);for(let s=0;s<t;s++){const t=e[s];if(t<0)continue;let r=0,i=n.length;for(;r<i;){const o=r+i>>1;e[n[o]]<t?r=o+1:i=o}r>0&&(o[s]=n[r-1]),n[r]=s}const s=[];let r=n.length>0?n[n.length-1]:-1;for(;r>=0;)s.push(r),r=o[r];return s.reverse(),s}(i);let l=c.length-1,a=t;for(let t=s-1;t>=0;t--){const o=n[t];l>=0&&c[l]===t?l--:e.insertBefore(o,a),a=o}}function A(e,t,n){null==e||"number"==typeof e&&Number.isNaN(e)?a("NULLISH_KEY",String(e),"For: a key is null/undefined/NaN. Such keys collide under SameValueZero, so rows silently merge/drop. Provide a stable unique `key`.",{key:e}):n||"object"!=typeof e&&"function"!=typeof e||a("NON_PRIMITIVE_KEY",typeof e,"For: a non-primitive item is used as its own key (no `key` option given). Object identity changes across renders, so every row is rebuilt and per-row state is lost. Pass `{ key: item => item.id }`.",{item:t})}function L(n,o,r){const i=M(n),c=r?.key;return{__wcsList:!0,mount(n){const r=document.createComment("for");n.appendChild(r);let l=new Map,d=[];const f=(e,t)=>{const n=u(t);let s;const r=p(t=>(s=o(e,()=>n.get()),t));return{node:s,dispose:r,idx:n}};e(()=>{const e=i()??[],t=[],n=new Set,o=s();for(let s=0;s<e.length;s++){const r=c?c(e[s],s):e[s];if(o&&A(r,e[s],void 0!==c),n.has(r))throw o&&a("DUPLICATE_KEY",String(r),`For: duplicate key "${String(r)}" at index ${s} — keys must be unique. Rendering throws and the list stops updating until keys are fixed.`,{key:r,index:s}),new Error(`For: duplicate key "${String(r)}" — keys must be unique.`);n.add(r),t.push(r)}const u=new Map,p=[],m=[];try{for(let n=0;n<e.length;n++){const o=t[n];let s=l.get(o);s?s.idx.peek()!==n&&s.idx.set(n):(s=f(e[n],n),m.push(s)),u.set(o,s),p.push(s.node)}}catch(e){for(const e of m)e.dispose();throw e}const h=r.parentNode;if(l.size>0&&u.size===m.length)if(null!==h&&h.lastChild===r&&d.length>0&&h.firstChild===d[0]&&h.childNodes.length===l.size+1){h.textContent="",h.appendChild(r);for(const e of l.values())e.dispose()}else for(const e of l.values())e.node.remove(),e.dispose();else for(const[e,t]of l)u.has(e)||(t.node.remove(),t.dispose());h&&_(h,r,p,d),d=p,l=u}),t(()=>{for(const e of l.values())e.dispose();l.clear()})}}}function P(n,o){const s=M(n);return{__wcsList:!0,mount(n){const r=document.createComment("index");n.appendChild(r);const i=[];e(()=>{const e=s()??[],t=r.parentNode;for(let n=0;n<e.length;n++)if(n<i.length)i[n].item.set(e[n]);else{const s=u(e[n]);let c;const l=p(e=>(c=o(()=>s.get(),n),e));i.push({node:c,dispose:l,item:s}),t?.insertBefore(c,r)}if(e.length<i.length){if(0===e.length&&null!==t&&t.lastChild===r&&t.firstChild===i[0].node&&t.childNodes.length===i.length+1){t.textContent="",t.appendChild(r);for(const e of i)e.dispose()}else for(let t=e.length;t<i.length;t++)i[t].node.remove(),i[t].dispose();i.length=e.length}}),t(()=>{for(const e of i)e.dispose();i.length=0})}}}let j=null;function T(){if(null!==j)return j;if("undefined"==typeof HTMLElement)throw new Error("@wcstack/signals/dom: SignalsElement requires a DOM (HTMLElement is not defined). The `./dom` entry's element/render surface is browser-only; in SSR/Node/worker code import the headless core from `@wcstack/signals` instead, or inject a DOM (e.g. happy-dom) before constructing custom elements.");class e extends HTMLElement{_dispose=null;getMountPoint(){return this}connectedCallback(){if(null!==this._dispose)return;const e=this.getMountPoint();this._dispose=p(t=>(e.appendChild(this.render()),t))}disconnectedCallback(){if(null===this._dispose)return;this._dispose(),this._dispose=null;const e=this.getMountPoint();for(;e.firstChild;)e.removeChild(e.firstChild)}}return j=e,j}const R=new Proxy(function(){},{construct:(e,t,n)=>Reflect.construct(T(),t,n),get:(e,t,n)=>Reflect.get(T(),t,n),has:(e,t)=>Reflect.has(T(),t),apply(){throw new TypeError("SignalsElement is a class and cannot be invoked without `new`/`extends`.")},getPrototypeOf:()=>Reflect.getPrototypeOf(T())});function F(e,t={}){if("undefined"==typeof document||"undefined"==typeof customElements)throw new Error("@wcstack/signals/dom: mountNode requires a DOM (document/customElements is not defined). It creates and connects a live element, so it is browser-only; inject a DOM (e.g. happy-dom) before calling, or keep headless work on `@wcstack/signals`.");const{attrs:n,parent:s,descriptor:r}=t,i=e.toLowerCase();if(!r&&!customElements.get(i))throw new Error(`mountNode: "<${i}>" is not defined. Import its defining module first (e.g. a side-effect \`import "@wcstack/<pkg>/auto"\` in this module — evaluation order then guarantees the definition). For a tag loaded by someone else, await customElements.whenDefined("${i}") or gate with <wcs-defined> before mounting. Binding a non-custom-element tag requires an explicit \`descriptor\`.`);const c=document.createElement(i);if(n)for(const[e,t]of Object.entries(n))!1!==t&&c.setAttribute(e,!0===t?"":String(t));const l=o(c,r);(s??document.body).appendChild(c);const a=()=>{l.dispose(),c.remove()};return{...l,el:c,unmount:a,dispose:a}}export{L as For,m as Fragment,P as Index,R as SignalsElement,o as bindNode,p as createRoot,T as createSignalsElement,e as effect,g as h,F as mountNode,t as onCleanup,b as render,u as signal};
1
+ import{e,o as t,b as o,g as s,h as l,w as a,s as u,a as p}from"./core-CUHdCgQ2.esm.min.js";export{D as DisposedError,c as computed,f as flushSync,i as isDisposedError,n as nodeSource,r as resource,d as streamResource}from"./core-CUHdCgQ2.esm.min.js";const m=Symbol("signals.Fragment");function h(e){return"object"==typeof e&&null!==e&&"function"==typeof e.get&&"function"==typeof e.peek}function g(e,t,...n){if(e===m){const e=document.createDocumentFragment();return N(e,n),e}if("function"==typeof e){const o=e({...t??{},children:n});return Array.isArray(o)?function(e){const t=document.createDocumentFragment();return N(t,e),t}(o):o}const o=function(e){return w.has(e)?document.createElementNS(y,e):document.createElement(e)}(e);if(t)for(const e in t)C(o,e,t[e]);return N(o,n),o}const y="http://www.w3.org/2000/svg",w=new Set(["svg","g","path","rect","circle","ellipse","line","polyline","polygon","text","tspan","defs","use","symbol","marker","linearGradient","radialGradient","stop","clipPath","mask","pattern","image","foreignObject"]);function b(e,t){return x(t,e),t}const v={for:"htmlFor",tabindex:"tabIndex",colspan:"colSpan",rowspan:"rowSpan",readonly:"readOnly",maxlength:"maxLength",minlength:"minLength",contenteditable:"contentEditable"},k=new WeakMap;function E(e,t){const n=Object.getPrototypeOf(e);let o=k.get(n);void 0===o&&(o=new Map,k.set(n,o));let s=o.get(t);return void 0===s&&(s=function(e,t){let n=e;for(;null!==n;){const e=Object.getOwnPropertyDescriptor(n,t);if(e)return"set"in e?"function"==typeof e.set:!1!==e.writable;n=Object.getPrototypeOf(n)}return!1}(e,t),o.set(t,s)),s}function C(n,o,s){if(/^on[A-Za-z-]/.test(o)&&"function"==typeof s){const e=/^on[A-Z]/.test(o)?o.slice(2).toLowerCase():o.slice(2),r=s;return n.addEventListener(e,r),void t(()=>n.removeEventListener(e,r))}"function"!=typeof s?h(s)?e(()=>S(n,o,s.get())):S(n,o,s):e(()=>S(n,o,s()))}function S(e,t,n){if("style"===t)return void function(e,t){if(null==t)return void e.removeAttribute("style");if("string"==typeof t)return void(e.style.cssText=t);e.style.cssText="";const n=e.style,o=t;for(const e in o)e.includes("-")?n.setProperty(e,o[e]):n[e]=o[e]}(e,n);if("class"===t||"className"===t)return void e.setAttribute("class",null==n||!1===n?"":String(n));const o=v[t]??t;E(e,o)?e[o]=null==n?"":n:null!=n&&!1!==n?!0!==n?e.setAttribute(t,String(n)):e.setAttribute(t,""):e.removeAttribute(t)}function N(e,t){for(const n of t)x(e,n)}function x(e,t){var n;if(null!=t&&"boolean"!=typeof t)if(Array.isArray(t))for(const n of t)x(e,n);else"object"!=typeof(n=t)||null===n||!0!==n.__wcsList?t instanceof Node?e.appendChild(t):"function"!=typeof t?h(t)?O(e,()=>t.get()):e.appendChild(document.createTextNode(String(t))):O(e,t):t.mount(e)}function O(n,o){s()&&!l()&&a("UNOWNED_INSERT","","reactive child inserted with no owner — its update effect will never be disposed and may leak. Mount under createRoot / SignalsElement.");const r=document.createComment("");n.appendChild(r);let i=[];e(()=>{const e=o();if(("string"==typeof e||"number"==typeof e)&&1===i.length){const t=i[0];if(3===t.nodeType)return void(t.data=String(e))}const t=function(e){const t=[],n=e=>{null!=e&&"boolean"!=typeof e&&(Array.isArray(e)?e.forEach(n):e instanceof Node?t.push(e):t.push(document.createTextNode(String(e))))};return n(e),t}(e);for(const e of i)e.parentNode?.removeChild(e);const n=r.parentNode;if(n)for(const e of t)n.insertBefore(e,r);i=t}),t(()=>{i=[]})}function A(e){return h(e)?()=>e.get():e}function M(e,t,n,o){const s=n.length;if(0===s)return;const r=new Map;for(let e=0;e<o.length;e++)r.set(o[e],e);const i=new Array(s);for(let e=0;e<s;e++){const t=r.get(n[e]);i[e]=void 0===t?-1:t}const c=function(e){const t=e.length,n=[],o=new Array(t).fill(-1);for(let s=0;s<t;s++){const t=e[s];if(t<0)continue;let r=0,i=n.length;for(;r<i;){const o=r+i>>1;e[n[o]]<t?r=o+1:i=o}r>0&&(o[s]=n[r-1]),n[r]=s}const s=[];let r=n.length>0?n[n.length-1]:-1;for(;r>=0;)s.push(r),r=o[r];return s.reverse(),s}(i);let l=c.length-1,a=t;for(let t=s-1;t>=0;t--){const o=n[t];l>=0&&c[l]===t?l--:e.insertBefore(o,a),a=o}}function _(e,t,n){null==e||"number"==typeof e&&Number.isNaN(e)?a("NULLISH_KEY",String(e),"For: a key is null/undefined/NaN. Such keys collide under SameValueZero, so rows silently merge/drop. Provide a stable unique `key`.",{key:e}):n||"object"!=typeof e&&"function"!=typeof e||a("NON_PRIMITIVE_KEY",typeof e,"For: a non-primitive item is used as its own key (no `key` option given). Object identity changes across renders, so every row is rebuilt and per-row state is lost. Pass `{ key: item => item.id }`.",{item:t})}function L(n,o,r){const i=A(n),c=r?.key;return{__wcsList:!0,mount(n){const r=document.createComment("for");n.appendChild(r);let l=new Map,d=[];const f=(e,t)=>{const n=u(t),s=u(e);let r;const i=p(t=>(r=o(e,()=>n.get(),()=>s.get()),t));return{node:r,dispose:i,idx:n,cur:s}};e(()=>{const e=i()??[],t=[],n=new Set,o=s();for(let s=0;s<e.length;s++){const r=c?c(e[s],s):e[s];if(o&&_(r,e[s],void 0!==c),n.has(r))throw o&&a("DUPLICATE_KEY",String(r),`For: duplicate key "${String(r)}" at index ${s} — keys must be unique. Rendering throws and the list stops updating until keys are fixed.`,{key:r,index:s}),new Error(`For: duplicate key "${String(r)}" — keys must be unique.`);n.add(r),t.push(r)}const u=new Map,p=[],m=[];try{for(let n=0;n<e.length;n++){const o=t[n];let s=l.get(o);s?(s.idx.peek()!==n&&s.idx.set(n),s.cur.set(e[n])):(s=f(e[n],n),m.push(s)),u.set(o,s),p.push(s.node)}}catch(e){for(const e of m)e.dispose();throw e}const h=r.parentNode;if(l.size>0&&u.size===m.length)if(null!==h&&h.lastChild===r&&d.length>0&&h.firstChild===d[0]&&h.childNodes.length===l.size+1){h.textContent="",h.appendChild(r);for(const e of l.values())e.dispose()}else for(const e of l.values())e.node.remove(),e.dispose();else for(const[e,t]of l)u.has(e)||(t.node.remove(),t.dispose());h&&M(h,r,p,d),d=p,l=u}),t(()=>{for(const e of l.values())e.dispose();l.clear()})}}}function P(n,o){const s=A(n);return{__wcsList:!0,mount(n){const r=document.createComment("index");n.appendChild(r);const i=[];e(()=>{const e=s()??[],t=r.parentNode;for(let n=0;n<e.length;n++)if(n<i.length)i[n].item.set(e[n]);else{const s=u(e[n]);let c;const l=p(e=>(c=o(()=>s.get(),n),e));i.push({node:c,dispose:l,item:s}),t?.insertBefore(c,r)}if(e.length<i.length){if(0===e.length&&null!==t&&t.lastChild===r&&t.firstChild===i[0].node&&t.childNodes.length===i.length+1){t.textContent="",t.appendChild(r);for(const e of i)e.dispose()}else for(let t=e.length;t<i.length;t++)i[t].node.remove(),i[t].dispose();i.length=e.length}}),t(()=>{for(const e of i)e.dispose();i.length=0})}}}let j=null;function T(){if(null!==j)return j;if("undefined"==typeof HTMLElement)throw new Error("@wcstack/signals/dom: SignalsElement requires a DOM (HTMLElement is not defined). The `./dom` entry's element/render surface is browser-only; in SSR/Node/worker code import the headless core from `@wcstack/signals` instead, or inject a DOM (e.g. happy-dom) before constructing custom elements.");class e extends HTMLElement{_dispose=null;getMountPoint(){return this}connectedCallback(){if(null!==this._dispose)return;const e=this.getMountPoint();this._dispose=p(t=>(e.appendChild(this.render()),t))}disconnectedCallback(){if(null===this._dispose)return;this._dispose(),this._dispose=null;const e=this.getMountPoint();for(;e.firstChild;)e.removeChild(e.firstChild)}}return j=e,j}const R=new Proxy(function(){},{construct:(e,t,n)=>Reflect.construct(T(),t,n),get:(e,t,n)=>Reflect.get(T(),t,n),has:(e,t)=>Reflect.has(T(),t),apply(){throw new TypeError("SignalsElement is a class and cannot be invoked without `new`/`extends`.")},getPrototypeOf:()=>Reflect.getPrototypeOf(T())});function F(e,t={}){if("undefined"==typeof document||"undefined"==typeof customElements)throw new Error("@wcstack/signals/dom: mountNode requires a DOM (document/customElements is not defined). It creates and connects a live element, so it is browser-only; inject a DOM (e.g. happy-dom) before calling, or keep headless work on `@wcstack/signals`.");const{attrs:n,parent:s,descriptor:r}=t,i=e.toLowerCase();if(!r&&!customElements.get(i))throw new Error(`mountNode: "<${i}>" is not defined. Import its defining module first (e.g. a side-effect \`import "@wcstack/<pkg>/auto"\` in this module — evaluation order then guarantees the definition). For a tag loaded by someone else, await customElements.whenDefined("${i}") or gate with <wcs-defined> before mounting. Binding a non-custom-element tag requires an explicit \`descriptor\`.`);const c=document.createElement(i);if(n)for(const[e,t]of Object.entries(n))!1!==t&&c.setAttribute(e,!0===t?"":String(t));const l=o(c,r);(s??document.body).appendChild(c);const a=()=>{l.dispose(),c.remove()};return{...l,el:c,unmount:a,dispose:a}}export{L as For,m as Fragment,P as Index,R as SignalsElement,o as bindNode,p as createRoot,T as createSignalsElement,e as effect,g as h,F as mountNode,t as onCleanup,b as render,u as signal};
2
2
  //# sourceMappingURL=dom.esm.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dom.esm.min.js","sources":["../src/dom.ts"],"sourcesContent":["// Fine-grained hyperscript (v1 design notes). The \"step before JSX\" (docs §4-1).\n//\n// `h(tag, props, ...children)` is the classic JSX factory shape, but it does NOT\n// build a virtual DOM and re-render. It creates a REAL DOM node once; any prop or\n// child given as a function (thunk) or signal is wired to a targeted `effect`, so\n// only that one binding updates when its signals change (Solid-style). This is\n// what keeps the package lightweight: no reconciler is shipped.\n//\n// JSX is intentionally NOT shipped. A consumer who wants it sets, in their own\n// tsconfig, `jsxFactory: \"h\"` + `jsxFragmentFactory: \"Fragment\"` (classic runtime)\n// — opting into a build step is their choice; the buildless path is calling `h`\n// directly. See docs/signals-state-design.md §4-1.\n//\n// OWNERSHIP: effects created here are owned by the enclosing reactive scope.\n// A reactive child's effect owns the prop/child effects of the subtree it builds,\n// so rebuilding that subtree disposes the previous one's effects (no leak). Mount\n// an app under `createRoot` so the whole tree can be torn down on unmount; a\n// dynamic child establishes its own scope automatically (it IS an effect).\n\nimport { signal, effect, onCleanup, createRoot, hasOwner, ReadSignal, WriteSignal } from \"./reactive.js\";\nimport { isDev, warnDev } from \"./dev.js\";\nimport { bindNode } from \"./bindNode.js\";\nimport type { BoundNode, NodeShape, DefaultNodeShape, WcBindableDescriptor } from \"./bindNode.js\";\n\n// `@wcstack/signals/dom` re-exports the headless core (signals, resource,\n// streamResource, bindNode, nodeSource) so UI code can import everything from one\n// module. Both built entries import a single shared `core-*.esm.js` chunk\n// (rollup.config.js `manualChunks`), so importing from BOTH `@wcstack/signals` and\n// `@wcstack/signals/dom` on a buildless page yields ONE reactive instance — the\n// tracking context is shared, not duplicated. `__tests__/packaging.test.ts` pins\n// this (both entries reference the same core chunk; a signal made via one entry is\n// observed by an effect from the other).\nexport {\n signal,\n computed,\n effect,\n createRoot,\n onCleanup,\n flushSync,\n} from \"./reactive.js\";\nexport type { ReadSignal, WriteSignal, EffectHandle, Cleanup, Equals } from \"./reactive.js\";\nexport { resource } from \"./resource.js\";\nexport type { ResourceState, ResourceOptions, ResourceSource } from \"./resource.js\";\nexport { streamResource } from \"./streamResource.js\";\nexport type {\n StreamResourceState,\n StreamResourceOptions,\n StreamSource,\n StreamProducer,\n StreamStatus,\n} from \"./streamResource.js\";\nexport { bindNode, nodeSource, DisposedError, isDisposedError } from \"./bindNode.js\";\nexport type {\n BoundNode,\n NodeShape,\n DefaultNodeShape,\n WcBindableDescriptor,\n WcBindableProperty,\n EventStreamOptions,\n} from \"./bindNode.js\";\n\nexport const Fragment = Symbol(\"signals.Fragment\");\n\nexport type Child = unknown;\nexport type Props = Record<string, unknown> | null;\n// h() always injects `children` into the props object it passes to a component, so\n// the parameter type makes that explicit (a component can declare `{ children }`).\nexport type Component = (\n props: Record<string, unknown> & { children?: Child[] },\n) => Node | Child[];\n\nfunction isReadSignal(value: unknown): value is ReadSignal<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { get?: unknown }).get === \"function\" &&\n typeof (value as { peek?: unknown }).peek === \"function\"\n );\n}\n\nexport function h(\n tag: string | typeof Fragment | Component,\n props?: Props,\n ...children: Child[]\n): Node {\n if (tag === Fragment) {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n }\n\n if (typeof tag === \"function\") {\n const result = tag({ ...(props ?? {}), children });\n return Array.isArray(result) ? wrapFragment(result) : result;\n }\n\n const el = createElement(tag);\n if (props) {\n for (const key in props) {\n bindProp(el, key, props[key]);\n }\n }\n appendChildren(el, children);\n return el;\n}\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\n// Tags created in the SVG namespace. Ambiguous names shared with HTML (`a`,\n// `title`, `script`, `style`) are intentionally EXCLUDED so ordinary HTML usage is\n// not broken; an SVG `<a>` / `<title>` must be created in an explicitly-namespaced\n// way by the caller. SVG DOM props are largely read-only, so `setProp`'s\n// settable-property check routes SVG attributes through `setAttribute` for free.\nconst SVG_TAGS = new Set([\n \"svg\", \"g\", \"path\", \"rect\", \"circle\", \"ellipse\", \"line\", \"polyline\", \"polygon\",\n \"text\", \"tspan\", \"defs\", \"use\", \"symbol\", \"marker\", \"linearGradient\",\n \"radialGradient\", \"stop\", \"clipPath\", \"mask\", \"pattern\", \"image\", \"foreignObject\",\n]);\n\nfunction createElement(tag: string): Element {\n return SVG_TAGS.has(tag)\n ? document.createElementNS(SVG_NS, tag)\n : document.createElement(tag);\n}\n\n/** Append `child` into `container`, resolving fragments/arrays. */\nexport function render(child: Child, container: Node): Node {\n appendChild(container, child);\n return container;\n}\n\nfunction wrapFragment(children: Child[]): DocumentFragment {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n}\n\n// --- props ------------------------------------------------------------------\n\n// Attribute names whose corresponding JS DOM property differs. `class` is handled\n// separately (it has reactive-falsy semantics in setProp), so it is not listed here.\nconst ATTR_TO_PROP: Record<string, string> = {\n for: \"htmlFor\",\n tabindex: \"tabIndex\",\n colspan: \"colSpan\",\n rowspan: \"rowSpan\",\n readonly: \"readOnly\",\n maxlength: \"maxLength\",\n minlength: \"minLength\",\n contenteditable: \"contentEditable\",\n};\n\n// True only if `key` resolves to a WRITABLE property on the element or its\n// prototype chain (a data property with `writable !== false`, or an accessor with a\n// setter). `key in el` is not enough: it also matches read-only members like\n// `firstChild` / `childNodes`, whose assignment throws in strict mode. The walk\n// starts at `el` itself so own instance fields (e.g. a custom element's properties)\n// are still matched, exactly as the previous `key in el` did — just without the\n// read-only false positives.\n//\n// MEMOIZATION: the prototype-chain walk runs on every bindProp/setProp. The result\n// depends only on the element's PROTOTYPE (its class) and the key, since DOM props\n// live on the prototype — not on per-instance own fields, which this library never\n// adds dynamically per element. So cache by `(prototype, key)`: a WeakMap keyed by\n// prototype (no leak — entries die with the class) holding a Map of key→result.\nconst settableCache = new WeakMap<object, Map<string, boolean>>();\n\nfunction computeSettable(el: Element, key: string): boolean {\n let obj: object | null = el;\n while (obj !== null) {\n const desc = Object.getOwnPropertyDescriptor(obj, key);\n if (desc) {\n return \"set\" in desc ? typeof desc.set === \"function\" : desc.writable !== false;\n }\n obj = Object.getPrototypeOf(obj);\n }\n return false;\n}\n\nfunction isSettableProperty(el: Element, key: string): boolean {\n // A real Element always has a prototype (HTMLElement.prototype → … → Object), so\n // `getPrototypeOf` is non-null here; use it as the cache key.\n const proto = Object.getPrototypeOf(el) as object;\n let byKey = settableCache.get(proto);\n if (byKey === undefined) {\n byKey = new Map<string, boolean>();\n settableCache.set(proto, byKey);\n }\n let result = byKey.get(key);\n if (result === undefined) {\n result = computeSettable(el, key);\n byKey.set(key, result);\n }\n return result;\n}\n\nfunction bindProp(el: Element, key: string, value: unknown): void {\n // Event handlers (`onClick` → \"click\") are special-cased BEFORE the reactive\n // check: a function here is the listener, not a thunk to track.\n if (/^on[A-Z]/.test(key) && typeof value === \"function\") {\n const type = key.slice(2).toLowerCase();\n const listener = value as EventListener;\n el.addEventListener(type, listener);\n // Remove the listener when the owning scope is torn down (e.g. a dynamic\n // child that rebuilds this subtree), so handlers don't accumulate.\n onCleanup(() => el.removeEventListener(type, listener));\n return;\n }\n\n if (typeof value === \"function\") {\n effect(() => setProp(el, key, (value as () => unknown)()));\n return;\n }\n\n if (isReadSignal(value)) {\n effect(() => setProp(el, key, value.get()));\n return;\n }\n\n setProp(el, key, value);\n}\n\nfunction setProp(el: Element, key: string, value: unknown): void {\n if (key === \"style\") {\n setStyle(el as HTMLElement, value);\n return;\n }\n if (key === \"class\" || key === \"className\") {\n // Set the `class` ATTRIBUTE, not the `className` property. On an SVGElement\n // `className` is a read-only `SVGAnimatedString`, so assigning it throws in\n // strict mode (ESM is always strict) — `setAttribute(\"class\", …)` works for both\n // HTML and SVG. Treat false like null → empty class (consistent with the\n // attribute path's false-removes-it rule), so `() => cond && \"active\"` yields \"\"\n // (not \"false\") when the condition is falsy.\n // STRING-ONLY: a non-null/non-false value is coerced via String(value). Array\n // (`[\"a\", \"b\"]`) and object (`{ active: true }`) class forms are NOT supported —\n // they would stringify to \"a,b\" / \"[object Object]\". Compose the class string in\n // the binding itself (e.g. `() => [a, b].join(\" \")`) and pass a string. This keeps\n // the core free of a class-merging convention.\n el.setAttribute(\"class\", value == null || value === false ? \"\" : String(value));\n return;\n }\n // Remap the handful of attribute names whose JS property differs, so `for` /\n // `tabindex` / `colspan` etc. reach the right property instead of falling through\n // to setAttribute (which works for some but not e.g. `htmlFor`).\n const propKey = ATTR_TO_PROP[key] ?? key;\n if (isSettableProperty(el, propKey)) {\n // Known, WRITABLE DOM property (value, checked, disabled, id, htmlFor, ...).\n // The settability check excludes read-only members (firstChild, childNodes, …)\n // that `key in el` would wrongly accept — assigning to those throws in strict\n // mode; we fall through to the attribute path for them instead.\n //\n // NORMALIZATION: null/undefined are coerced to \"\" before assignment. Without\n // this, a STRING prop (id/title/value/src) given a reactive null/undefined\n // lands as the literal \"null\"/\"undefined\" (e.g. img.src=\"null\" fires a real\n // request) — a correctness footgun. \"\" clears the prop instead. Safe for\n // non-string props too: boolean props coerce \"\"→false (same as null), numeric\n // props coerce \"\"→0 (same as null). We do NOT normalize `false`:\n // `el.disabled = false` is the intended boolean clear.\n (el as unknown as Record<string, unknown>)[propKey] = value == null ? \"\" : value;\n return;\n }\n if (value == null || value === false) {\n el.removeAttribute(key);\n return;\n }\n if (value === true) {\n el.setAttribute(key, \"\");\n return;\n }\n el.setAttribute(key, String(value));\n}\n\nfunction setStyle(el: HTMLElement, value: unknown): void {\n if (value == null) {\n el.removeAttribute(\"style\");\n return;\n }\n if (typeof value === \"string\") {\n el.style.cssText = value;\n return;\n }\n // Object form: the object fully describes the style. Reset first so keys present\n // in a previous run but absent now are removed — otherwise a reactive style that\n // drops a key (e.g. {color,fontWeight} → {color}) would leave the stale property\n // applied. The object is the source of truth, so wiping cssText is correct here.\n el.style.cssText = \"\";\n const style = el.style as CSSStyleDeclaration & Record<string, string>;\n const obj = value as Record<string, string>;\n for (const k in obj) {\n // A key with a hyphen is either kebab-case (`font-weight`) or a CSS custom\n // property (`--accent`). Neither works via property assignment (`style[k]` would\n // just set an inert expando), so route them through setProperty. camelCase keys\n // (`fontWeight`) keep the faster property path.\n if (k.includes(\"-\")) {\n style.setProperty(k, obj[k]);\n } else {\n style[k] = obj[k];\n }\n }\n}\n\n// --- children ---------------------------------------------------------------\n\nfunction appendChildren(parent: Node, children: Child[]): void {\n for (const child of children) {\n appendChild(parent, child);\n }\n}\n\nfunction appendChild(parent: Node, child: Child): void {\n if (child == null || typeof child === \"boolean\") {\n return; // null / undefined / boolean render nothing\n }\n if (Array.isArray(child)) {\n for (const c of child) {\n appendChild(parent, c);\n }\n return;\n }\n if (isListView(child)) {\n // A keyed list (For / Index): it manages its own anchored region with in-place\n // reconciliation, so it does NOT go through the wholesale insertReactive path.\n child.mount(parent);\n return;\n }\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n if (typeof child === \"function\") {\n insertReactive(parent, child as () => unknown);\n return;\n }\n if (isReadSignal(child)) {\n insertReactive(parent, () => child.get());\n return;\n }\n parent.appendChild(document.createTextNode(String(child)));\n}\n\n/**\n * A reactive insertion point. An anchor comment marks the position; on each run\n * the previous nodes are removed and the freshly-resolved nodes inserted before\n * the anchor. Using `anchor.parentNode` (not the original `parent`) keeps it\n * correct after the subtree is moved/mounted elsewhere.\n *\n * PRECONDITION: the Nodes returned by `accessor` are owned by this insertion point\n * — do not move them to another parent externally. On the next run they are\n * removed from wherever they currently are (`node.parentNode?.removeChild`), so an\n * externally-moved node would be yanked out of its new home without warning.\n *\n * OWNERSHIP: the `effect` below is owned by the enclosing reactive scope at call\n * time (the `currentOwner`). Used under `createRoot` / `SignalsElement` (the module\n * header's mount contract) it is disposed on teardown. Calling `h`/`render` with a\n * reactive child OUTSIDE any owner (no `createRoot`/`SignalsElement`) leaves this\n * effect un-owned and therefore never cleaned up — by design, per that contract.\n */\nfunction insertReactive(parent: Node, accessor: () => unknown): void {\n if (isDev() && !hasOwner()) {\n // A reactive child inserted with no enclosing owner: the effect below is never\n // disposed (the module header documents this as by-design, but it is a frequent\n // accidental leak). Warn once in dev so the un-owned mount is visible.\n warnDev(\n \"UNOWNED_INSERT\",\n \"\",\n \"reactive child inserted with no owner — its update effect will never be \" +\n \"disposed and may leak. Mount under createRoot / SignalsElement.\",\n );\n }\n const anchor = document.createComment(\"\");\n parent.appendChild(anchor);\n let current: Node[] = [];\n\n effect(() => {\n const value = accessor();\n // FAST PATH: a plain text result that replaces a plain text result. The common\n // reactive child is a string/number thunk (`() => \\`count: ${n.get()}\\``); the\n // wholesale path would remove the old Text node, allocate a new one, and re-insert\n // it on every change. When BOTH the previous and next renders are a single Text\n // node, mutate the existing node's `data` in place instead — no allocation, no\n // remove/insert, and the same DOM node identity is preserved across updates.\n if ((typeof value === \"string\" || typeof value === \"number\") && current.length === 1) {\n const node = current[0];\n if (node.nodeType === 3 /* TEXT_NODE */) {\n (node as Text).data = String(value);\n return;\n }\n }\n const next = toNodes(value);\n for (const node of current) {\n node.parentNode?.removeChild(node);\n }\n const host = anchor.parentNode;\n if (host) {\n for (const node of next) {\n host.insertBefore(node, anchor);\n }\n }\n current = next;\n });\n\n // On teardown, drop the references to the inserted Nodes. The disposed effect's\n // closure still captures `current`; if anything retains the effect after disposal\n // (e.g. a parent owner kept alive longer than the subtree), those Nodes would be\n // pinned via that closure even though they have left the DOM. Clearing the array\n // lets them be GC'd as soon as the enclosing owner tears this insertion point down.\n onCleanup(() => {\n current = [];\n });\n}\n\n// --- keyed lists: For / Index (migration-plan §9-3) --------------------------\n//\n// `insertReactive` rebuilds its whole subtree on every change. For lists that is\n// wasteful (and drops per-row state). `For` / `Index` instead keep a stable DOM row\n// per item and reconcile in place. Each row is built under its OWN `createRoot`, so\n// removing a row disposes exactly that row's effects/resources/listeners — the owner\n// tree (§8 (d)) is what makes this leak-free. The reconcile runs in a single\n// `effect` owned by the enclosing scope; an `onCleanup` disposes surviving rows when\n// that scope (e.g. the component) tears down.\n//\n// CONTRACT: `each` must return a SINGLE Node (one row = one node). Keys (For) must\n// be unique. `For` keys by value identity (=== / explicit `key`) and passes the\n// index as an accessor (it changes on move); `Index` keys by position and passes the\n// item as an accessor (the value at a slot changes, the slot does not).\n\nexport type ListAccessor<T> = ReadSignal<readonly T[]> | (() => readonly T[]);\nexport type ForEach<T> = (item: T, index: () => number) => Node;\nexport type IndexEach<T> = (item: () => T, index: number) => Node;\n\n/**\n * The return type of {@link For} / {@link Index}: a keyed list that owns an anchored\n * region and reconciles rows in place. Exported (D4) so consumers can annotate\n * helpers that build or pass around lists. `mount` is called by `h`/`render` when the\n * list is used as a child; `__wcsList` is the brand `appendChild` checks.\n */\nexport interface ListView {\n readonly __wcsList: true;\n mount(parent: Node): void;\n}\n\nfunction isListView(value: unknown): value is ListView {\n return typeof value === \"object\" && value !== null && (value as ListView).__wcsList === true;\n}\n\nfunction readList<T>(list: ListAccessor<T>): () => readonly T[] {\n return isReadSignal(list) ? () => (list as ReadSignal<readonly T[]>).get() : (list as () => readonly T[]);\n}\n\nexport interface ForOptions<T> {\n /** Derive a unique key per item. Default: the item value itself (identity). */\n key?: (item: T, index: number) => unknown;\n}\n\n// --- LIS-based DOM reorder ---------------------------------------------------\n//\n// `reconcileOrder` brings the live DOM under `host` (the contiguous region ending\n// at `anchor`) into `order` — the desired final node sequence — using the FEWEST\n// `insertBefore` moves, while producing EXACTLY the order a naive full re-place\n// would. The naive approach (walk and insert every out-of-place node) does up to\n// O(n) DOM moves on a full reverse or a head insert; here we instead keep the\n// largest set of reused rows that are ALREADY in the right relative order, and\n// move only the others (Solid's reconcileArrays / udomdiff idea).\n//\n// HOW: `prevOrder` is the node sequence the previous run left in the DOM. For each\n// node in the new `order`, a reused row maps to its index in `prevOrder`; a freshly\n// created row has no previous position. The longest increasing subsequence (LIS)\n// of those previous indices marks the reused rows that need NOT move (their pairwise\n// relative order is already correct). Every other node — fresh ones, and reused\n// ones outside the LIS — is inserted before its already-correct successor, walking\n// back-to-front so the \"successor\" reference is always a settled node or the anchor.\n\n/**\n * Indices into `arr` (with value -1 meaning \"no previous position\") whose values\n * form a longest strictly-increasing subsequence. Entries equal to -1 are treated\n * as never part of the subsequence (a fresh node always moves). Classic\n * patience-sorting LIS in O(n log n); returns the chosen indices in ascending order.\n */\nfunction longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n // `tails[k]` = index (into arr) of the smallest tail of an increasing\n // subsequence of length k+1. `prev[i]` = predecessor index, to rebuild the chain.\n const tails: number[] = [];\n const prev: number[] = new Array(n).fill(-1);\n for (let i = 0; i < n; i++) {\n const value = arr[i];\n if (value < 0) {\n continue; // fresh node: not eligible for the stable subsequence\n }\n // Binary search for the first tail whose value is >= this value, and replace it\n // (or extend the tails when this value beats every tail).\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (arr[tails[mid]] < value) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n if (lo > 0) {\n prev[i] = tails[lo - 1];\n }\n tails[lo] = i;\n }\n // Rebuild the index chain from the longest tail backwards.\n const result: number[] = [];\n let k = tails.length > 0 ? tails[tails.length - 1] : -1;\n while (k >= 0) {\n result.push(k);\n k = prev[k];\n }\n result.reverse();\n return result;\n}\n\nfunction reconcileOrder(\n host: Node,\n anchor: Node,\n order: Node[],\n prevOrder: Node[],\n): void {\n const n = order.length;\n if (n === 0) {\n return; // nothing to place (removals already happened)\n }\n\n // Map each previous node to its previous position, so a node in `order` can look\n // up where it used to be. A node absent from this map is FRESH (created this run,\n // or the first run where prevOrder is empty) and is encoded as -1 — it always moves.\n const prevIndex = new Map<Node, number>();\n for (let i = 0; i < prevOrder.length; i++) {\n prevIndex.set(prevOrder[i], i);\n }\n\n // previous-position sequence aligned to the new order. -1 marks a fresh node.\n const seq: number[] = new Array(n);\n for (let i = 0; i < n; i++) {\n const p = prevIndex.get(order[i]);\n seq[i] = p === undefined ? -1 : p;\n }\n\n // Rows whose relative order is already correct: leave them in place, move the rest.\n const lis = longestIncreasingSubsequence(seq);\n let lisPtr = lis.length - 1;\n\n // Walk back-to-front. `ref` is the node that must follow the one being placed; it\n // starts at the anchor (the region's tail) and becomes each placed node. A node in\n // the LIS is the maximal already-correctly-ordered set, so it is left untouched\n // (only adopted as the new `ref`). Every OTHER node is, by construction, out of\n // position relative to its settled successor and is inserted before `ref` — no\n // \"is it already in place?\" guard is needed (it never is, unlike the old\n // full-walk reconciler which visited correctly-placed nodes too).\n let ref: Node = anchor;\n for (let i = n - 1; i >= 0; i--) {\n const node = order[i];\n if (lisPtr >= 0 && lis[lisPtr] === i) {\n lisPtr--; // stable: do not move\n } else {\n host.insertBefore(node, ref);\n }\n ref = node;\n }\n}\n\n// Dev-only key sanity check (no effect in production — guarded by `isDev()` at the\n// call site so this is never reached when dev is off). Flags the silent-failure key\n// shapes: a nullish key (NaN / null / undefined collide under SameValueZero, so two\n// such items map to one row and a row is silently dropped), and — when no explicit\n// `key` was given — a non-primitive item used as its own identity key (every render\n// gets a fresh object reference, so the row is rebuilt instead of reused, silently\n// dropping per-row state). Warns once per distinct shape (deduped in warnDev).\nfunction checkKeyDev(key: unknown, item: unknown, hasExplicitKey: boolean): void {\n if (key == null || (typeof key === \"number\" && Number.isNaN(key))) {\n warnDev(\n \"NULLISH_KEY\",\n String(key),\n \"For: a key is null/undefined/NaN. Such keys collide under SameValueZero, \" +\n \"so rows silently merge/drop. Provide a stable unique `key`.\",\n { key },\n );\n return;\n }\n if (!hasExplicitKey && (typeof key === \"object\" || typeof key === \"function\")) {\n warnDev(\n \"NON_PRIMITIVE_KEY\",\n typeof key,\n \"For: a non-primitive item is used as its own key (no `key` option given). \" +\n \"Object identity changes across renders, so every row is rebuilt and per-row \" +\n \"state is lost. Pass `{ key: item => item.id }`.\",\n { item },\n );\n }\n}\n\nexport function For<T>(list: ListAccessor<T>, each: ForEach<T>, options?: ForOptions<T>): ListView {\n const read = readList(list);\n const keyOf = options?.key;\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"for\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n idx: WriteSignal<number>;\n }\n let rows = new Map<unknown, Row>();\n // The node order placed by the previous reconcile run. Empty on first run.\n // Used to find which reused rows already sit in increasing relative order so\n // only the rest are moved (LIS reorder, see reconcileOrder).\n let prevOrder: Node[] = [];\n\n const make = (item: T, i: number): Row => {\n const idx = signal(i);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(item, () => idx.get());\n return d;\n });\n return { node, dispose, idx };\n };\n\n effect(() => {\n const items = read() ?? [];\n\n // Key-uniqueness PRE-PASS (no side effects): throwing here, before any row is\n // created or moved, keeps a duplicate-key error from leaving half-built rows\n // orphaned (make() runs createRoot) and the DOM mid-reorder. Keys are reused\n // below so keyOf runs once per item.\n const keys: unknown[] = [];\n const seen = new Set<unknown>();\n const dev = isDev();\n for (let i = 0; i < items.length; i++) {\n const k = keyOf ? keyOf(items[i], i) : items[i];\n if (dev) {\n checkKeyDev(k, items[i], keyOf !== undefined);\n }\n if (seen.has(k)) {\n if (dev) {\n // The throw below still halts (production behaviour unchanged); the warn\n // adds the offending key + a pointer to the cause so the silent\n // \"updates stopped\" symptom is diagnosable.\n warnDev(\n \"DUPLICATE_KEY\",\n String(k),\n `For: duplicate key \"${String(k)}\" at index ${i} — keys must be unique. ` +\n \"Rendering throws and the list stops updating until keys are fixed.\",\n { key: k, index: i },\n );\n }\n throw new Error(`For: duplicate key \"${String(k)}\" — keys must be unique.`);\n }\n seen.add(k);\n keys.push(k);\n }\n\n const next = new Map<unknown, Row>();\n const order: Node[] = [];\n\n // Rows freshly created in THIS run (not reused from `rows`). If a later\n // `make()` — i.e. a user `each` — throws mid-loop, the rows already built\n // here are owned by their own detached `createRoot` and are not yet tracked\n // in any surviving map, so they would leak. Dispose them before re-throwing,\n // leaving the old `rows` map untouched (it is recoverable on the next run).\n const fresh: Row[] = [];\n try {\n for (let i = 0; i < items.length; i++) {\n const k = keys[i];\n let row = rows.get(k);\n if (row) {\n if (row.idx.peek() !== i) {\n row.idx.set(i); // position changed — refresh the index accessor\n }\n } else {\n row = make(items[i], i);\n fresh.push(row);\n }\n next.set(k, row);\n order.push(row.node);\n }\n } catch (err) {\n for (const row of fresh) {\n row.dispose();\n }\n throw err;\n }\n\n // The LIVE parent (`anchor.parentNode`, not the mount arg) so the region\n // stays correct after being moved (e.g. built inside a Fragment, then\n // appended elsewhere). `host` is null only if the anchor was detached\n // without disposing this scope (a misuse) — then there is nothing to\n // place into. Resolved before the removal phase so the wholesale-removal\n // fast path below can use it.\n const host = anchor.parentNode;\n\n // Dispose rows whose key vanished. `remove()` no-ops if already detached.\n if (rows.size > 0 && next.size === fresh.length) {\n // ZERO-REUSE run: no existing key survives (clear, or a full replacement\n // with disjoint keys), so EVERY current row is removed. When the host\n // contains exactly this list's region — first child is the region's\n // first row, last child is the anchor, and the child count matches\n // rows + anchor — detach them all with a single native\n // `textContent = \"\"` and re-append the anchor, instead of one\n // `remove()` per row (the dominant cost of clearing large lists).\n // Any deviation (foreign sibling, externally detached row, shared\n // host) fails the guard and falls back to the per-row path.\n // Disposal always runs per row; only the DOM detachment is batched.\n if (\n host !== null &&\n host.lastChild === anchor &&\n prevOrder.length > 0 &&\n host.firstChild === prevOrder[0] &&\n host.childNodes.length === rows.size + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows.values()) {\n row.dispose();\n }\n } else {\n for (const row of rows.values()) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n } else {\n for (const [k, row] of rows) {\n if (!next.has(k)) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n }\n if (host) {\n reconcileOrder(host, anchor, order, prevOrder);\n }\n\n // Snapshot this run's final order so the NEXT run's reconcile can detect\n // which rows kept their relative position (the LIS basis below). Capturing\n // the array we just placed avoids re-deriving it from the map.\n prevOrder = order;\n rows = next;\n });\n\n onCleanup(() => {\n for (const row of rows.values()) {\n row.dispose();\n }\n rows.clear();\n });\n },\n };\n}\n\nexport function Index<T>(list: ListAccessor<T>, each: IndexEach<T>): ListView {\n const read = readList(list);\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"index\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n item: WriteSignal<T>;\n }\n const rows: Row[] = [];\n\n effect(() => {\n const items = read() ?? [];\n // Live parent (see `For`), null only if the anchor was detached undisposed.\n const host = anchor.parentNode;\n\n for (let i = 0; i < items.length; i++) {\n if (i < rows.length) {\n // Slot reused: just push the new value into the row's item signal. The\n // signal's equality guard skips the update when the value is unchanged.\n rows[i].item.set(items[i]);\n } else {\n const item = signal(items[i]);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(() => item.get(), i);\n return d;\n });\n rows.push({ node, dispose, item });\n // Positions never move for index keying, so append at the tail (before\n // the anchor) in order. ORDERING CONTRACT (shared with For and the other\n // anchored insertions): the list owns the contiguous region ENDING at its\n // anchor comment. New rows go immediately before the anchor, so the list's\n // own rows always stay correctly ordered and grouped, and static siblings\n // before the anchor (or another list with its own anchor) are never\n // disturbed. Do NOT splice unrelated nodes into the middle of this region.\n host?.insertBefore(node, anchor);\n }\n }\n\n // Trailing slots that no longer exist: dispose and drop.\n if (items.length < rows.length) {\n // WHOLESALE CLEAR (same idea as For's zero-reuse fast path): every slot\n // vanishes and the host holds exactly this list's region (all rows +\n // the anchor), so one native `textContent = \"\"` replaces per-row\n // `remove()`. Guard failures (foreign sibling, detached row, shared\n // host) fall back to the per-row path. Disposal still runs per row.\n if (\n items.length === 0 &&\n host !== null &&\n host.lastChild === anchor &&\n host.firstChild === rows[0].node &&\n host.childNodes.length === rows.length + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows) {\n row.dispose();\n }\n } else {\n for (let i = items.length; i < rows.length; i++) {\n (rows[i].node as ChildNode).remove();\n rows[i].dispose();\n }\n }\n rows.length = items.length;\n }\n });\n\n onCleanup(() => {\n for (const row of rows) {\n row.dispose();\n }\n rows.length = 0;\n });\n },\n };\n}\n\n// --- custom element lifecycle (docs §8 (e)) ---------------------------------\n//\n// The exit point for ownership: a custom element that mounts a signals view under\n// `createRoot` on connect and disposes that root on disconnect. This wires the\n// reactive ownership tree to the real DOM lifecycle — every effect, resource and\n// listener created in `render()` is torn down when the element leaves the DOM, and\n// rebuilt fresh on reconnect. Subclasses only implement `render()`.\n//\n// SCOPE (v1 intentional constraints — drive these reactively, not via this base):\n// - No attribute reactivity. There is no `attributeChangedCallback`/\n// `observedAttributes` wiring: this base does NOT turn HTML attributes into\n// signals. Feed reactive inputs as signals/props from the code that constructs\n// the view (or have a subclass map attributes to signals itself).\n// - Shadow DOM is opt-in and subclass-owned. The default mount point is light DOM\n// (`this`); a subclass that wants encapsulation overrides `getMountPoint()` to\n// return a shadow root it created (e.g. `this.attachShadow(...)` in its\n// constructor). This base never calls attachShadow implicitly.\n// - Mount/unmount only: render() runs once per connect and the whole subtree is\n// disposed on disconnect — there is no partial/incremental re-render hook here\n// (fine-grained updates come from the signals wired inside render()).\n\n// TYPE-ONLY shape of the lifecycle base. `declare abstract class` emits NO runtime\n// code (so it does not reference `HTMLElement` at module-evaluation time — the whole\n// point of the lazy factory below), but it gives the exported `SignalsElement` value\n// and `createSignalsElement()`'s return a precise type that preserves the original\n// contract: `render` is `protected abstract` (a subclass MUST implement it and may\n// only reach it from within), and `getMountPoint` is `protected` (overridable). This\n// is the same surface the previous concrete `abstract class SignalsElement` exposed.\n// (Used only via `typeof` below; the lint rule does not see that as a value use.)\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare abstract class SignalsElementType extends HTMLElement {\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node;\n connectedCallback(): void;\n disconnectedCallback(): void;\n}\n\n/**\n * The lifecycle base contract: the abstract constructor type of the `SignalsElement`\n * base. Abstract, so `new SignalsElement()` is rejected (the base has an unimplemented\n * `render`) while `class X extends SignalsElement` is allowed. Returned by\n * {@link createSignalsElement} and the type of the {@link SignalsElement} value.\n */\nexport type SignalsElementClass = typeof SignalsElementType;\n\n// Memoized base class. Built lazily on first access so the `./dom` module can be\n// EVALUATED in a non-DOM environment (SSR pre-pass, a worker without a DOM shim)\n// without a top-level `class … extends HTMLElement` blowing up with\n// `ReferenceError: HTMLElement is not defined`. The class body is only constructed\n// when the consumer actually reaches for the base — at which point a DOM is required\n// and its absence yields a clear, actionable error instead of a raw ReferenceError.\nlet cachedBase: SignalsElementClass | null = null;\n\n/**\n * Build (once, memoized) the `SignalsElement` lifecycle base class. Resolves\n * `HTMLElement` at CALL TIME, so importing `@wcstack/signals/dom` no longer requires\n * a DOM at module-evaluation time — only *calling* this (or subclassing\n * {@link SignalsElement}) does.\n *\n * Contract:\n * - The `.` entry (`@wcstack/signals`) is non-DOM: it evaluates and runs in SSR,\n * Node, and Web Workers with no DOM globals.\n * - The `./dom` entry (`@wcstack/signals/dom`) may now also be *evaluated* without a\n * DOM (so an SSR pre-pass that imports it for the headless re-exports does not\n * crash). The DOM-touching surface — `h`/`render`/`For`/`Index` and this base —\n * still requires DOM globals when actually used.\n *\n * @throws a clear `Error` (not a raw `ReferenceError`) when no `HTMLElement` global is\n * present, naming the offending entry so the failure is self-explanatory.\n */\nexport function createSignalsElement(): SignalsElementClass {\n if (cachedBase !== null) {\n return cachedBase;\n }\n if (typeof HTMLElement === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: SignalsElement requires a DOM (HTMLElement is not defined). \" +\n \"The `./dom` entry's element/render surface is browser-only; in SSR/Node/worker \" +\n \"code import the headless core from `@wcstack/signals` instead, or inject a DOM \" +\n \"(e.g. happy-dom) before constructing custom elements.\",\n );\n }\n\n abstract class SignalsElementBase extends HTMLElement {\n private _dispose: (() => void) | null = null;\n\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node {\n return this;\n }\n\n connectedCallback(): void {\n if (this._dispose !== null) {\n return; // already mounted (defensive against a redundant connect)\n }\n const mount = this.getMountPoint();\n // If render() throws, createRoot disposes any effects it built before the throw,\n // so nothing leaks; _dispose stays null (the element is simply not mounted) and\n // a later disconnectedCallback safely no-ops. The error propagates to the caller.\n this._dispose = createRoot((dispose) => {\n mount.appendChild(this.render());\n return dispose;\n });\n }\n\n disconnectedCallback(): void {\n if (this._dispose === null) {\n return; // not mounted\n }\n this._dispose();\n this._dispose = null;\n const mount = this.getMountPoint();\n while (mount.firstChild) {\n mount.removeChild(mount.firstChild);\n }\n }\n }\n\n cachedBase = SignalsElementBase as unknown as SignalsElementClass;\n return cachedBase;\n}\n\n// `SignalsElement` is the ergonomic name to `extends`. It is a lazily-resolved alias\n// for the class built by `createSignalsElement()`: a Proxy that forwards construct /\n// get / has / getPrototypeOf to the real (memoized) base, building it on first touch.\n// This keeps `class X extends SignalsElement { … }` working exactly as before WHILE\n// deferring the `HTMLElement` reference to subclass-definition time (in a real DOM),\n// instead of `./dom` module-evaluation time (which may be a non-DOM SSR pre-pass).\n//\n// BREAKING note: the value is now a Proxy, not the class object literal. Subclassing,\n// `instanceof`, and static/prototype access all still work; a consumer that relied on\n// `SignalsElement` being a *frozen* concrete class reference (uncommon) should call\n// `createSignalsElement()` to obtain the real class.\n// The Proxy target is a never-called placeholder (every operation is intercepted by a\n// trap below); it only needs to be constructable/callable so `new` / `extends` and the\n// `apply` trap engage. It is intentionally a no-op and never executed.\n/* v8 ignore next */\nconst signalsElementTarget = function (): void {};\nexport const SignalsElement: SignalsElementClass = new Proxy(signalsElementTarget as unknown as SignalsElementClass, {\n construct(_target, args, newTarget): object {\n return Reflect.construct(createSignalsElement(), args, newTarget);\n },\n get(_target, prop, receiver): unknown {\n return Reflect.get(createSignalsElement(), prop, receiver);\n },\n has(_target, prop): boolean {\n return Reflect.has(createSignalsElement(), prop);\n },\n apply(): never {\n throw new TypeError(\"SignalsElement is a class and cannot be invoked without `new`/`extends`.\");\n },\n getPrototypeOf(): object | null {\n return Reflect.getPrototypeOf(createSignalsElement());\n },\n});\n\nfunction toNodes(value: unknown): Node[] {\n const out: Node[] = [];\n const visit = (v: unknown): void => {\n if (v == null || typeof v === \"boolean\") {\n return;\n }\n if (Array.isArray(v)) {\n v.forEach(visit);\n return;\n }\n if (v instanceof Node) {\n out.push(v);\n return;\n }\n out.push(document.createTextNode(String(v)));\n };\n visit(value);\n return out;\n}\n\n// --- mountNode: create + bind + mount a headless wc-bindable node -------------\n//\n// `bindNode` adapts an EXISTING element, which forces its caller to guarantee the\n// custom element class is already registered (the descriptor is read from\n// `el.constructor.wcBindable` at call time — an un-upgraded element has none).\n// `mountNode` closes that gap for the common signals shape where the app OWNS its\n// headless IO nodes: it creates the element AFTER the definition exists (so it is\n// upgraded at construction), binds it, then connects it. The recommended pairing\n// is a side-effect import of the package's `/auto` entry in the same module —\n// module evaluation order then guarantees the definition:\n//\n// import \"@wcstack/fetch/auto\";\n// const fetcher = mountNode(\"wcs-fetch\", { attrs: { url: \"/api/people\" } });\n// fetcher.signals.value.get();\n//\n// The internal order is deliberate: attributes are set BEFORE connect (shells read\n// their config in `connectedCallback`), and the adapter subscribes BEFORE connect,\n// so an event fired from `connectedCallback` is already observed — the missed-event\n// window is structurally zero, not merely closed by bindNode's re-seed. Like\n// `bindNode`, the adapter is NOT auto-registered with a reactive owner; teardown is\n// explicit via `unmount()` — to which `dispose()` is aliased, see MountedNode —\n// (compose with `onCleanup(() => m.unmount())` if the node should die with a\n// scope). See docs/signals-definition-timing.md for the full definition-timing\n// contract (optional packages via dynamic import, the remaining whenDefined /\n// <wcs-defined> territory).\n\nexport interface MountNodeOptions {\n /**\n * Attributes set on the element BEFORE it is connected (declarative pre-connect\n * config, e.g. `{ url: \"/api\", timeout: 5000 }`). HTML boolean-attribute\n * semantics: `true` sets an empty attribute, `false` omits it; other values are\n * stringified.\n */\n attrs?: Record<string, string | number | boolean>;\n /** Parent to append the element to. Default: `document.body`. */\n parent?: Node;\n /**\n * Explicit wc-bindable descriptor forwarded to `bindNode`. When given, the\n * tag-definition check is skipped — the escape hatch for binding a\n * non-custom-element tag, mirroring `bindNode`'s second parameter.\n */\n descriptor?: WcBindableDescriptor;\n}\n\nexport interface MountedNode<S extends NodeShape = DefaultNodeShape> extends BoundNode<S> {\n /** The created element (connected until `unmount()`). */\n readonly el: HTMLElement;\n /**\n * Full teardown: dispose the adapter AND remove the element from the DOM\n * (disconnect stops the shell's IO). Idempotent. On a `MountedNode`,\n * `dispose()` is an alias of this — mountNode owns the element's lifecycle,\n * so the package-wide teardown verb must not leave a connected element with\n * live IO behind (a silent leak for callers habituated to `bindNode`).\n */\n unmount(): void;\n}\n\nexport function mountNode<S extends NodeShape = DefaultNodeShape>(\n tagName: string,\n options: MountNodeOptions = {},\n): MountedNode<S> {\n // Call-time DOM guard (not module-time): `./dom` must evaluate in non-DOM realms\n // (SSR pre-pass / worker) — same contract (and message shape) as `createSignalsElement`.\n if (typeof document === \"undefined\" || typeof customElements === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: mountNode requires a DOM (document/customElements is not defined). \" +\n \"It creates and connects a live element, so it is browser-only; inject a DOM \" +\n \"(e.g. happy-dom) before calling, or keep headless work on `@wcstack/signals`.\",\n );\n }\n const { attrs, parent, descriptor } = options;\n // Custom element names are lowercase; the registry is exact-key while\n // createElement ASCII-lowercases — normalize once so mountNode(el.tagName)\n // (uppercase in HTML documents) hits the same definition the element would.\n const tag = tagName.toLowerCase();\n // Fail loud with the actual cause. Without this, bindNode's generic \"no\n // wc-bindable descriptor\" error hides that the tag simply isn't defined yet.\n if (!descriptor && !customElements.get(tag)) {\n throw new Error(\n `mountNode: \"<${tag}>\" is not defined. Import its defining module first (e.g. a side-effect ` +\n `\\`import \"@wcstack/<pkg>/auto\"\\` in this module — evaluation order then guarantees the definition). ` +\n `For a tag loaded by someone else, await customElements.whenDefined(\"${tag}\") or gate with ` +\n `<wcs-defined> before mounting. Binding a non-custom-element tag requires an explicit \\`descriptor\\`.`,\n );\n }\n\n const el = document.createElement(tag);\n if (attrs) {\n for (const [name, value] of Object.entries(attrs)) {\n if (value === false) {\n continue; // boolean-attribute semantics: false = absent\n }\n el.setAttribute(name, value === true ? \"\" : String(value));\n }\n }\n const bound = bindNode<S>(el, descriptor);\n (parent ?? document.body).appendChild(el);\n const unmount = (): void => {\n bound.dispose();\n el.remove();\n };\n return {\n ...bound,\n el,\n unmount,\n // Override the inherited adapter-only dispose(): on a MountedNode it would be\n // a silent PARTIAL teardown (signals inert, but the created element stays\n // connected with its shell's IO still running). mountNode owns the element,\n // so dispose === unmount.\n dispose: unmount,\n };\n}\n"],"names":["Fragment","Symbol","isReadSignal","value","get","peek","h","tag","props","children","frag","document","createDocumentFragment","appendChildren","result","Array","isArray","wrapFragment","el","SVG_TAGS","has","createElementNS","SVG_NS","createElement","key","bindProp","Set","render","child","container","appendChild","ATTR_TO_PROP","for","tabindex","colspan","rowspan","readonly","maxlength","minlength","contenteditable","settableCache","WeakMap","isSettableProperty","proto","Object","getPrototypeOf","byKey","undefined","Map","set","obj","desc","getOwnPropertyDescriptor","writable","computeSettable","test","type","slice","toLowerCase","listener","addEventListener","onCleanup","removeEventListener","effect","setProp","removeAttribute","style","cssText","k","includes","setProperty","setStyle","setAttribute","String","propKey","parent","c","__wcsList","Node","insertReactive","createTextNode","mount","accessor","isDev","hasOwner","warnDev","anchor","createComment","current","length","node","nodeType","data","next","out","visit","v","forEach","push","toNodes","parentNode","removeChild","host","insertBefore","readList","list","reconcileOrder","order","prevOrder","n","prevIndex","i","seq","p","lis","arr","tails","prev","fill","lo","hi","mid","reverse","longestIncreasingSubsequence","lisPtr","ref","checkKeyDev","item","hasExplicitKey","Number","isNaN","For","each","options","read","keyOf","rows","make","idx","signal","dispose","createRoot","d","items","keys","seen","dev","index","Error","add","fresh","row","err","size","lastChild","firstChild","childNodes","textContent","values","remove","clear","Index","cachedBase","createSignalsElement","HTMLElement","SignalsElementBase","_dispose","getMountPoint","this","connectedCallback","disconnectedCallback","SignalsElement","Proxy","construct","_target","args","newTarget","Reflect","prop","receiver","apply","TypeError","mountNode","tagName","customElements","attrs","descriptor","name","entries","bound","bindNode","body","unmount"],"mappings":"gQA6DaA,EAAWC,OAAO,oBAU/B,SAASC,EAAaC,GACpB,MACmB,iBAAVA,GACG,OAAVA,GAC4C,mBAApCA,EAA4BC,KACU,mBAAtCD,EAA6BE,IAEzC,CAEM,SAAUC,EACdC,EACAC,KACGC,GAEH,GAAIF,IAAQP,EAAU,CACpB,MAAMU,EAAOC,SAASC,yBAEtB,OADAC,EAAeH,EAAMD,GACdC,CACT,CAEA,GAAmB,mBAARH,EAAoB,CAC7B,MAAMO,EAASP,EAAI,IAAMC,GAAS,CAAA,EAAKC,aACvC,OAAOM,MAAMC,QAAQF,GAsCzB,SAAsBL,GACpB,MAAMC,EAAOC,SAASC,yBAEtB,OADAC,EAAeH,EAAMD,GACdC,CACT,CA1CmCO,CAAaH,GAAUA,CACxD,CAEA,MAAMI,EAuBR,SAAuBX,GACrB,OAAOY,EAASC,IAAIb,GAChBI,SAASU,gBAAgBC,EAAQf,GACjCI,SAASY,cAAchB,EAC7B,CA3BagB,CAAchB,GACzB,GAAIC,EACF,IAAK,MAAMgB,KAAOhB,EAChBiB,EAASP,EAAIM,EAAKhB,EAAMgB,IAI5B,OADAX,EAAeK,EAAIT,GACZS,CACT,CAEA,MAAMI,EAAS,6BAOTH,EAAW,IAAIO,IAAI,CACvB,MAAO,IAAK,OAAQ,OAAQ,SAAU,UAAW,OAAQ,WAAY,UACrE,OAAQ,QAAS,OAAQ,MAAO,SAAU,SAAU,iBACpD,iBAAkB,OAAQ,WAAY,OAAQ,UAAW,QAAS,kBAU9D,SAAUC,EAAOC,EAAcC,GAEnC,OADAC,EAAYD,EAAWD,GAChBC,CACT,CAYA,MAAME,EAAuC,CAC3CC,IAAK,UACLC,SAAU,WACVC,QAAS,UACTC,QAAS,UACTC,SAAU,WACVC,UAAW,YACXC,UAAW,YACXC,gBAAiB,mBAgBbC,EAAgB,IAAIC,QAc1B,SAASC,EAAmBxB,EAAaM,GAGvC,MAAMmB,EAAQC,OAAOC,eAAe3B,GACpC,IAAI4B,EAAQN,EAAcpC,IAAIuC,QAChBI,IAAVD,IACFA,EAAQ,IAAIE,IACZR,EAAcS,IAAIN,EAAOG,IAE3B,IAAIhC,EAASgC,EAAM1C,IAAIoB,GAKvB,YAJeuB,IAAXjC,IACFA,EAvBJ,SAAyBI,EAAaM,GACpC,IAAI0B,EAAqBhC,EACzB,KAAe,OAARgC,GAAc,CACnB,MAAMC,EAAOP,OAAOQ,yBAAyBF,EAAK1B,GAClD,GAAI2B,EACF,MAAO,QAASA,EAA2B,mBAAbA,EAAKF,KAAuC,IAAlBE,EAAKE,SAE/DH,EAAMN,OAAOC,eAAeK,EAC9B,CACA,OAAO,CACT,CAaaI,CAAgBpC,EAAIM,GAC7BsB,EAAMG,IAAIzB,EAAKV,IAEVA,CACT,CAEA,SAASW,EAASP,EAAaM,EAAarB,GAG1C,GAAI,WAAWoD,KAAK/B,IAAyB,mBAAVrB,EAAsB,CACvD,MAAMqD,EAAOhC,EAAIiC,MAAM,GAAGC,cACpBC,EAAWxD,EAKjB,OAJAe,EAAG0C,iBAAiBJ,EAAMG,QAG1BE,EAAU,IAAM3C,EAAG4C,oBAAoBN,EAAMG,GAE/C,CAEqB,mBAAVxD,EAKPD,EAAaC,GACf4D,EAAO,IAAMC,EAAQ9C,EAAIM,EAAKrB,EAAMC,QAItC4D,EAAQ9C,EAAIM,EAAKrB,GATf4D,EAAO,IAAMC,EAAQ9C,EAAIM,EAAMrB,KAUnC,CAEA,SAAS6D,EAAQ9C,EAAaM,EAAarB,GACzC,GAAY,UAARqB,EAEF,YAgDJ,SAAkBN,EAAiBf,GACjC,GAAa,MAATA,EAEF,YADAe,EAAG+C,gBAAgB,SAGrB,GAAqB,iBAAV9D,EAET,YADAe,EAAGgD,MAAMC,QAAUhE,GAOrBe,EAAGgD,MAAMC,QAAU,GACnB,MAAMD,EAAQhD,EAAGgD,MACXhB,EAAM/C,EACZ,IAAK,MAAMiE,KAAKlB,EAKVkB,EAAEC,SAAS,KACbH,EAAMI,YAAYF,EAAGlB,EAAIkB,IAEzBF,EAAME,GAAKlB,EAAIkB,EAGrB,CA5EIG,CAASrD,EAAmBf,GAG9B,GAAY,UAARqB,GAA2B,cAARA,EAarB,YADAN,EAAGsD,aAAa,QAAkB,MAATrE,IAA2B,IAAVA,EAAkB,GAAKsE,OAAOtE,IAM1E,MAAMuE,EAAU3C,EAAaP,IAAQA,EACjCkB,EAAmBxB,EAAIwD,GAaxBxD,EAA0CwD,GAAoB,MAATvE,EAAgB,GAAKA,EAGhE,MAATA,IAA2B,IAAVA,GAIP,IAAVA,EAIJe,EAAGsD,aAAahD,EAAKiD,OAAOtE,IAH1Be,EAAGsD,aAAahD,EAAK,IAJrBN,EAAG+C,gBAAgBzC,EAQvB,CAiCA,SAASX,EAAe8D,EAAclE,GACpC,IAAK,MAAMmB,KAASnB,EAClBqB,EAAY6C,EAAQ/C,EAExB,CAEA,SAASE,EAAY6C,EAAc/C,GAoInC,IAAoBzB,EAnIlB,GAAa,MAATyB,GAAkC,kBAAVA,EAG5B,GAAIb,MAAMC,QAAQY,GAChB,IAAK,MAAMgD,KAAKhD,EACdE,EAAY6C,EAAQC,OA+HA,iBADNzE,EA1HHyB,IA2H+B,OAAVzB,IAAoD,IAAjCA,EAAmB0E,UArHtEjD,aAAiBkD,KACnBH,EAAO7C,YAAYF,GAGA,mBAAVA,EAIP1B,EAAa0B,GACfmD,EAAeJ,EAAQ,IAAM/C,EAAMxB,OAGrCuE,EAAO7C,YAAYnB,SAASqE,eAAeP,OAAO7C,KAPhDmD,EAAeJ,EAAQ/C,GARvBA,EAAMqD,MAAMN,EAgBhB,CAmBA,SAASI,EAAeJ,EAAcO,GAChCC,MAAYC,KAIdC,EACE,iBACA,GACA,2IAIJ,MAAMC,EAAS3E,SAAS4E,cAAc,IACtCZ,EAAO7C,YAAYwD,GACnB,IAAIE,EAAkB,GAEtBzB,EAAO,KACL,MAAM5D,EAAQ+E,IAOd,IAAsB,iBAAV/E,GAAuC,iBAAVA,IAA0C,IAAnBqF,EAAQC,OAAc,CACpF,MAAMC,EAAOF,EAAQ,GACrB,GAAsB,IAAlBE,EAAKC,SAEP,YADCD,EAAcE,KAAOnB,OAAOtE,GAGjC,CACA,MAAM0F,EAsmBV,SAAiB1F,GACf,MAAM2F,EAAc,GACdC,EAASC,IACJ,MAALA,GAA0B,kBAANA,IAGpBjF,MAAMC,QAAQgF,GAChBA,EAAEC,QAAQF,GAGRC,aAAalB,KACfgB,EAAII,KAAKF,GAGXF,EAAII,KAAKvF,SAASqE,eAAeP,OAAOuB,OAG1C,OADAD,EAAM5F,GACC2F,CACT,CAxnBiBK,CAAQhG,GACrB,IAAK,MAAMuF,KAAQF,EACjBE,EAAKU,YAAYC,YAAYX,GAE/B,MAAMY,EAAOhB,EAAOc,WACpB,GAAIE,EACF,IAAK,MAAMZ,KAAQG,EACjBS,EAAKC,aAAab,EAAMJ,GAG5BE,EAAUK,IAQZhC,EAAU,KACR2B,EAAU,IAEd,CAoCA,SAASgB,EAAYC,GACnB,OAAOvG,EAAauG,GAAQ,IAAOA,EAAkCrG,MAASqG,CAChF,CAsEA,SAASC,EACPJ,EACAhB,EACAqB,EACAC,GAEA,MAAMC,EAAIF,EAAMlB,OAChB,GAAU,IAANoB,EACF,OAMF,MAAMC,EAAY,IAAI9D,IACtB,IAAK,IAAI+D,EAAI,EAAGA,EAAIH,EAAUnB,OAAQsB,IACpCD,EAAU7D,IAAI2D,EAAUG,GAAIA,GAI9B,MAAMC,EAAgB,IAAIjG,MAAM8F,GAChC,IAAK,IAAIE,EAAI,EAAGA,EAAIF,EAAGE,IAAK,CAC1B,MAAME,EAAIH,EAAU1G,IAAIuG,EAAMI,IAC9BC,EAAID,QAAWhE,IAANkE,GAAkB,EAAKA,CAClC,CAGA,MAAMC,EAlER,SAAsCC,GACpC,MAAMN,EAAIM,EAAI1B,OAGR2B,EAAkB,GAClBC,EAAiB,IAAItG,MAAM8F,GAAGS,MAAK,GACzC,IAAK,IAAIP,EAAI,EAAGA,EAAIF,EAAGE,IAAK,CAC1B,MAAM5G,EAAQgH,EAAIJ,GAClB,GAAI5G,EAAQ,EACV,SAIF,IAAIoH,EAAK,EACLC,EAAKJ,EAAM3B,OACf,KAAO8B,EAAKC,GAAI,CACd,MAAMC,EAAOF,EAAKC,GAAO,EACrBL,EAAIC,EAAMK,IAAQtH,EACpBoH,EAAKE,EAAM,EAEXD,EAAKC,CAET,CACIF,EAAK,IACPF,EAAKN,GAAKK,EAAMG,EAAK,IAEvBH,EAAMG,GAAMR,CACd,CAEA,MAAMjG,EAAmB,GACzB,IAAIsD,EAAIgD,EAAM3B,OAAS,EAAI2B,EAAMA,EAAM3B,OAAS,IAAK,EACrD,KAAOrB,GAAK,GACVtD,EAAOoF,KAAK9B,GACZA,EAAIiD,EAAKjD,GAGX,OADAtD,EAAO4G,UACA5G,CACT,CA6Bc6G,CAA6BX,GACzC,IAAIY,EAASV,EAAIzB,OAAS,EAStBoC,EAAYvC,EAChB,IAAK,IAAIyB,EAAIF,EAAI,EAAGE,GAAK,EAAGA,IAAK,CAC/B,MAAMrB,EAAOiB,EAAMI,GACfa,GAAU,GAAKV,EAAIU,KAAYb,EACjCa,IAEAtB,EAAKC,aAAab,EAAMmC,GAE1BA,EAAMnC,CACR,CACF,CASA,SAASoC,EAAYtG,EAAcuG,EAAeC,GACrC,MAAPxG,GAA+B,iBAARA,GAAoByG,OAAOC,MAAM1G,GAC1D6D,EACE,cACAZ,OAAOjD,GACP,uIAEA,CAAEA,QAIDwG,GAAkC,iBAARxG,GAAmC,mBAARA,GACxD6D,EACE,2BACO7D,EACP,wMAGA,CAAEuG,QAGR,UAEgBI,EAAO1B,EAAuB2B,EAAkBC,GAC9D,MAAMC,EAAO9B,EAASC,GAChB8B,EAAQF,GAAS7G,IACvB,MAAO,CACLqD,WAAW,EACX,KAAAI,CAAMN,GACJ,MAAMW,EAAS3E,SAAS4E,cAAc,OACtCZ,EAAO7C,YAAYwD,GAOnB,IAAIkD,EAAO,IAAIxF,IAIX4D,EAAoB,GAExB,MAAM6B,EAAO,CAACV,EAAShB,KACrB,MAAM2B,EAAMC,EAAO5B,GACnB,IAAIrB,EACJ,MAAMkD,EAAUC,EAAYC,IAC1BpD,EAAO0C,EAAKL,EAAM,IAAMW,EAAItI,OACrB0I,IAET,MAAO,CAAEpD,OAAMkD,UAASF,QAG1B3E,EAAO,KACL,MAAMgF,EAAQT,KAAU,GAMlBU,EAAkB,GAClBC,EAAO,IAAIvH,IACXwH,EAAM/D,IACZ,IAAK,IAAI4B,EAAI,EAAGA,EAAIgC,EAAMtD,OAAQsB,IAAK,CACrC,MAAM3C,EAAImE,EAAQA,EAAMQ,EAAMhC,GAAIA,GAAKgC,EAAMhC,GAI7C,GAHImC,GACFpB,EAAY1D,EAAG2E,EAAMhC,QAAchE,IAAVwF,GAEvBU,EAAK7H,IAAIgD,GAaX,MAZI8E,GAIF7D,EACE,gBACAZ,OAAOL,GACP,uBAAuBK,OAAOL,gBAAgB2C,8FAE9C,CAAEvF,IAAK4C,EAAG+E,MAAOpC,IAGf,IAAIqC,MAAM,uBAAuB3E,OAAOL,8BAEhD6E,EAAKI,IAAIjF,GACT4E,EAAK9C,KAAK9B,EACZ,CAEA,MAAMyB,EAAO,IAAI7C,IACX2D,EAAgB,GAOhB2C,EAAe,GACrB,IACE,IAAK,IAAIvC,EAAI,EAAGA,EAAIgC,EAAMtD,OAAQsB,IAAK,CACrC,MAAM3C,EAAI4E,EAAKjC,GACf,IAAIwC,EAAMf,EAAKpI,IAAIgE,GACfmF,EACEA,EAAIb,IAAIrI,SAAW0G,GACrBwC,EAAIb,IAAIzF,IAAI8D,IAGdwC,EAAMd,EAAKM,EAAMhC,GAAIA,GACrBuC,EAAMpD,KAAKqD,IAEb1D,EAAK5C,IAAImB,EAAGmF,GACZ5C,EAAMT,KAAKqD,EAAI7D,KACjB,CACF,CAAE,MAAO8D,GACP,IAAK,MAAMD,KAAOD,EAChBC,EAAIX,UAEN,MAAMY,CACR,CAQA,MAAMlD,EAAOhB,EAAOc,WAGpB,GAAIoC,EAAKiB,KAAO,GAAK5D,EAAK4D,OAASH,EAAM7D,OAWvC,GACW,OAATa,GACAA,EAAKoD,YAAcpE,GACnBsB,EAAUnB,OAAS,GACnBa,EAAKqD,aAAe/C,EAAU,IAC9BN,EAAKsD,WAAWnE,SAAW+C,EAAKiB,KAAO,EACvC,CACAnD,EAAKuD,YAAc,GACnBvD,EAAKxE,YAAYwD,GACjB,IAAK,MAAMiE,KAAOf,EAAKsB,SACrBP,EAAIX,SAER,MACE,IAAK,MAAMW,KAAOf,EAAKsB,SACpBP,EAAI7D,KAAmBqE,SACxBR,EAAIX,eAIR,IAAK,MAAOxE,EAAGmF,KAAQf,EAChB3C,EAAKzE,IAAIgD,KACXmF,EAAI7D,KAAmBqE,SACxBR,EAAIX,WAINtC,GACFI,EAAeJ,EAAMhB,EAAQqB,EAAOC,GAMtCA,EAAYD,EACZ6B,EAAO3C,IAGThC,EAAU,KACR,IAAK,MAAM0F,KAAOf,EAAKsB,SACrBP,EAAIX,UAENJ,EAAKwB,SAET,EAEJ,CAEM,SAAUC,EAASxD,EAAuB2B,GAC9C,MAAME,EAAO9B,EAASC,GACtB,MAAO,CACL5B,WAAW,EACX,KAAAI,CAAMN,GACJ,MAAMW,EAAS3E,SAAS4E,cAAc,SACtCZ,EAAO7C,YAAYwD,GAOnB,MAAMkD,EAAc,GAEpBzE,EAAO,KACL,MAAMgF,EAAQT,KAAU,GAElBhC,EAAOhB,EAAOc,WAEpB,IAAK,IAAIW,EAAI,EAAGA,EAAIgC,EAAMtD,OAAQsB,IAChC,GAAIA,EAAIyB,EAAK/C,OAGX+C,EAAKzB,GAAGgB,KAAK9E,IAAI8F,EAAMhC,QAClB,CACL,MAAMgB,EAAOY,EAAOI,EAAMhC,IAC1B,IAAIrB,EACJ,MAAMkD,EAAUC,EAAYC,IAC1BpD,EAAO0C,EAAK,IAAML,EAAK3H,MAAO2G,GACvB+B,IAETN,EAAKtC,KAAK,CAAER,OAAMkD,UAASb,SAQ3BzB,GAAMC,aAAab,EAAMJ,EAC3B,CAIF,GAAIyD,EAAMtD,OAAS+C,EAAK/C,OAAQ,CAM9B,GACmB,IAAjBsD,EAAMtD,QACG,OAATa,GACAA,EAAKoD,YAAcpE,GACnBgB,EAAKqD,aAAenB,EAAK,GAAG9C,MAC5BY,EAAKsD,WAAWnE,SAAW+C,EAAK/C,OAAS,EACzC,CACAa,EAAKuD,YAAc,GACnBvD,EAAKxE,YAAYwD,GACjB,IAAK,MAAMiE,KAAOf,EAChBe,EAAIX,SAER,MACE,IAAK,IAAI7B,EAAIgC,EAAMtD,OAAQsB,EAAIyB,EAAK/C,OAAQsB,IACzCyB,EAAKzB,GAAGrB,KAAmBqE,SAC5BvB,EAAKzB,GAAG6B,UAGZJ,EAAK/C,OAASsD,EAAMtD,MACtB,IAGF5B,EAAU,KACR,IAAK,MAAM0F,KAAOf,EAChBe,EAAIX,UAENJ,EAAK/C,OAAS,GAElB,EAEJ,CAuDA,IAAIyE,EAAyC,cAmB7BC,IACd,GAAmB,OAAfD,EACF,OAAOA,EAET,GAA2B,oBAAhBE,YACT,MAAM,IAAIhB,MACR,ySAOJ,MAAeiB,UAA2BD,YAChCE,SAAgC,KAM9B,aAAAC,GACR,OAAOC,IACT,CAEA,iBAAAC,GACE,GAAsB,OAAlBD,KAAKF,SACP,OAEF,MAAMrF,EAAQuF,KAAKD,gBAInBC,KAAKF,SAAWzB,EAAYD,IAC1B3D,EAAMnD,YAAY0I,KAAK7I,UAChBiH,GAEX,CAEA,oBAAA8B,GACE,GAAsB,OAAlBF,KAAKF,SACP,OAEFE,KAAKF,WACLE,KAAKF,SAAW,KAChB,MAAMrF,EAAQuF,KAAKD,gBACnB,KAAOtF,EAAM0E,YACX1E,EAAMoB,YAAYpB,EAAM0E,WAE5B,EAIF,OADAO,EAAaG,EACNH,CACT,CAiBA,MACaS,EAAsC,IAAIC,MAD1B,WAAmB,EACqE,CACnHC,UAAS,CAACC,EAASC,EAAMC,IAChBC,QAAQJ,UAAUV,IAAwBY,EAAMC,GAEzD5K,IAAG,CAAC0K,EAASI,EAAMC,IACVF,QAAQ7K,IAAI+J,IAAwBe,EAAMC,GAEnD/J,IAAG,CAAC0J,EAASI,IACJD,QAAQ7J,IAAI+I,IAAwBe,GAE7C,KAAAE,GACE,MAAM,IAAIC,UAAU,2EACtB,EACAxI,eAAc,IACLoI,QAAQpI,eAAesH,gBAiFlBmB,EACdC,EACAlD,EAA4B,IAI5B,GAAwB,oBAAb1H,UAAsD,oBAAnB6K,eAC5C,MAAM,IAAIpC,MACR,sPAKJ,MAAMqC,MAAEA,EAAK9G,OAAEA,EAAM+G,WAAEA,GAAerD,EAIhC9H,EAAMgL,EAAQ7H,cAGpB,IAAKgI,IAAeF,eAAepL,IAAIG,GACrC,MAAM,IAAI6I,MACR,gBAAgB7I,oPAEyDA,yHAK7E,MAAMW,EAAKP,SAASY,cAAchB,GAClC,GAAIkL,EACF,IAAK,MAAOE,EAAMxL,KAAUyC,OAAOgJ,QAAQH,IAC3B,IAAVtL,GAGJe,EAAGsD,aAAamH,GAAgB,IAAVxL,EAAiB,GAAKsE,OAAOtE,IAGvD,MAAM0L,EAAQC,EAAY5K,EAAIwK,IAC7B/G,GAAUhE,SAASoL,MAAMjK,YAAYZ,GACtC,MAAM8K,EAAU,KACdH,EAAMjD,UACN1H,EAAG6I,UAEL,MAAO,IACF8B,EACH3K,KACA8K,UAKApD,QAASoD,EAEb"}
1
+ {"version":3,"file":"dom.esm.min.js","sources":["../src/dom.ts"],"sourcesContent":["// Fine-grained hyperscript (v1 design notes). The \"step before JSX\" (docs §4-1).\n//\n// `h(tag, props, ...children)` is the classic JSX factory shape, but it does NOT\n// build a virtual DOM and re-render. It creates a REAL DOM node once; any prop or\n// child given as a function (thunk) or signal is wired to a targeted `effect`, so\n// only that one binding updates when its signals change (Solid-style). This is\n// what keeps the package lightweight: no reconciler is shipped.\n//\n// JSX is intentionally NOT shipped. A consumer who wants it sets, in their own\n// tsconfig, `jsxFactory: \"h\"` + `jsxFragmentFactory: \"Fragment\"` (classic runtime)\n// — opting into a build step is their choice; the buildless path is calling `h`\n// directly. See docs/signals-state-design.md §4-1.\n//\n// OWNERSHIP: effects created here are owned by the enclosing reactive scope.\n// A reactive child's effect owns the prop/child effects of the subtree it builds,\n// so rebuilding that subtree disposes the previous one's effects (no leak). Mount\n// an app under `createRoot` so the whole tree can be torn down on unmount; a\n// dynamic child establishes its own scope automatically (it IS an effect).\n\nimport { signal, effect, onCleanup, createRoot, hasOwner, ReadSignal, WriteSignal } from \"./reactive.js\";\nimport { isDev, warnDev } from \"./dev.js\";\nimport { bindNode } from \"./bindNode.js\";\nimport type { BoundNode, NodeShape, DefaultNodeShape, WcBindableDescriptor } from \"./bindNode.js\";\n\n// `@wcstack/signals/dom` re-exports the headless core (signals, resource,\n// streamResource, bindNode, nodeSource) so UI code can import everything from one\n// module. Both built entries import a single shared `core-*.esm.js` chunk\n// (rollup.config.js `manualChunks`), so importing from BOTH `@wcstack/signals` and\n// `@wcstack/signals/dom` on a buildless page yields ONE reactive instance — the\n// tracking context is shared, not duplicated. `__tests__/packaging.test.ts` pins\n// this (both entries reference the same core chunk; a signal made via one entry is\n// observed by an effect from the other).\nexport {\n signal,\n computed,\n effect,\n createRoot,\n onCleanup,\n flushSync,\n} from \"./reactive.js\";\nexport type { ReadSignal, WriteSignal, EffectHandle, Cleanup, Equals } from \"./reactive.js\";\nexport { resource } from \"./resource.js\";\nexport type { ResourceState, ResourceOptions, ResourceSource } from \"./resource.js\";\nexport { streamResource } from \"./streamResource.js\";\nexport type {\n StreamResourceState,\n StreamResourceOptions,\n StreamSource,\n StreamProducer,\n StreamStatus,\n} from \"./streamResource.js\";\nexport { bindNode, nodeSource, DisposedError, isDisposedError } from \"./bindNode.js\";\nexport type {\n BoundNode,\n NodeShape,\n DefaultNodeShape,\n WcBindableDescriptor,\n WcBindableProperty,\n EventStreamOptions,\n} from \"./bindNode.js\";\n\nexport const Fragment = Symbol(\"signals.Fragment\");\n\nexport type Child = unknown;\nexport type Props = Record<string, unknown> | null;\n// h() always injects `children` into the props object it passes to a component, so\n// the parameter type makes that explicit (a component can declare `{ children }`).\nexport type Component = (\n props: Record<string, unknown> & { children?: Child[] },\n) => Node | Child[];\n\nfunction isReadSignal(value: unknown): value is ReadSignal<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { get?: unknown }).get === \"function\" &&\n typeof (value as { peek?: unknown }).peek === \"function\"\n );\n}\n\nexport function h(\n tag: string | typeof Fragment | Component,\n props?: Props,\n ...children: Child[]\n): Node {\n if (tag === Fragment) {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n }\n\n if (typeof tag === \"function\") {\n const result = tag({ ...(props ?? {}), children });\n return Array.isArray(result) ? wrapFragment(result) : result;\n }\n\n const el = createElement(tag);\n if (props) {\n for (const key in props) {\n bindProp(el, key, props[key]);\n }\n }\n appendChildren(el, children);\n return el;\n}\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\n// Tags created in the SVG namespace. Ambiguous names shared with HTML (`a`,\n// `title`, `script`, `style`) are intentionally EXCLUDED so ordinary HTML usage is\n// not broken; an SVG `<a>` / `<title>` must be created in an explicitly-namespaced\n// way by the caller. SVG DOM props are largely read-only, so `setProp`'s\n// settable-property check routes SVG attributes through `setAttribute` for free.\nconst SVG_TAGS = new Set([\n \"svg\", \"g\", \"path\", \"rect\", \"circle\", \"ellipse\", \"line\", \"polyline\", \"polygon\",\n \"text\", \"tspan\", \"defs\", \"use\", \"symbol\", \"marker\", \"linearGradient\",\n \"radialGradient\", \"stop\", \"clipPath\", \"mask\", \"pattern\", \"image\", \"foreignObject\",\n]);\n\nfunction createElement(tag: string): Element {\n return SVG_TAGS.has(tag)\n ? document.createElementNS(SVG_NS, tag)\n : document.createElement(tag);\n}\n\n/** Append `child` into `container`, resolving fragments/arrays. */\nexport function render(child: Child, container: Node): Node {\n appendChild(container, child);\n return container;\n}\n\nfunction wrapFragment(children: Child[]): DocumentFragment {\n const frag = document.createDocumentFragment();\n appendChildren(frag, children);\n return frag;\n}\n\n// --- props ------------------------------------------------------------------\n\n// Attribute names whose corresponding JS DOM property differs. `class` is handled\n// separately (it has reactive-falsy semantics in setProp), so it is not listed here.\nconst ATTR_TO_PROP: Record<string, string> = {\n for: \"htmlFor\",\n tabindex: \"tabIndex\",\n colspan: \"colSpan\",\n rowspan: \"rowSpan\",\n readonly: \"readOnly\",\n maxlength: \"maxLength\",\n minlength: \"minLength\",\n contenteditable: \"contentEditable\",\n};\n\n// True only if `key` resolves to a WRITABLE property on the element or its\n// prototype chain (a data property with `writable !== false`, or an accessor with a\n// setter). `key in el` is not enough: it also matches read-only members like\n// `firstChild` / `childNodes`, whose assignment throws in strict mode. The walk\n// starts at `el` itself so own instance fields (e.g. a custom element's properties)\n// are still matched, exactly as the previous `key in el` did — just without the\n// read-only false positives.\n//\n// MEMOIZATION: the prototype-chain walk runs on every bindProp/setProp. The result\n// depends only on the element's PROTOTYPE (its class) and the key, since DOM props\n// live on the prototype — not on per-instance own fields, which this library never\n// adds dynamically per element. So cache by `(prototype, key)`: a WeakMap keyed by\n// prototype (no leak — entries die with the class) holding a Map of key→result.\nconst settableCache = new WeakMap<object, Map<string, boolean>>();\n\nfunction computeSettable(el: Element, key: string): boolean {\n let obj: object | null = el;\n while (obj !== null) {\n const desc = Object.getOwnPropertyDescriptor(obj, key);\n if (desc) {\n return \"set\" in desc ? typeof desc.set === \"function\" : desc.writable !== false;\n }\n obj = Object.getPrototypeOf(obj);\n }\n return false;\n}\n\nfunction isSettableProperty(el: Element, key: string): boolean {\n // A real Element always has a prototype (HTMLElement.prototype → … → Object), so\n // `getPrototypeOf` is non-null here; use it as the cache key.\n const proto = Object.getPrototypeOf(el) as object;\n let byKey = settableCache.get(proto);\n if (byKey === undefined) {\n byKey = new Map<string, boolean>();\n settableCache.set(proto, byKey);\n }\n let result = byKey.get(key);\n if (result === undefined) {\n result = computeSettable(el, key);\n byKey.set(key, result);\n }\n return result;\n}\n\nfunction bindProp(el: Element, key: string, value: unknown): void {\n // Event handlers are special-cased BEFORE the reactive check: a function here is the\n // listener, not a thunk to track. `onClick` → \"click\" (lowercased); `onclick` /\n // `onadd-to-cart` → the name as written (\"click\", \"add-to-cart\" — data-wcs's `on<event>:`\n // form). A lowercase `onclick` used to fall through to the reactive path, so the handler\n // ran at render and never on click (docs/seam-apps.md, signals-shop).\n if (/^on[A-Za-z-]/.test(key) && typeof value === \"function\") {\n const type = /^on[A-Z]/.test(key) ? key.slice(2).toLowerCase() : key.slice(2);\n const listener = value as EventListener;\n el.addEventListener(type, listener);\n // Remove the listener when the owning scope is torn down (e.g. a dynamic\n // child that rebuilds this subtree), so handlers don't accumulate.\n onCleanup(() => el.removeEventListener(type, listener));\n return;\n }\n\n if (typeof value === \"function\") {\n effect(() => setProp(el, key, (value as () => unknown)()));\n return;\n }\n\n if (isReadSignal(value)) {\n effect(() => setProp(el, key, value.get()));\n return;\n }\n\n setProp(el, key, value);\n}\n\nfunction setProp(el: Element, key: string, value: unknown): void {\n if (key === \"style\") {\n setStyle(el as HTMLElement, value);\n return;\n }\n if (key === \"class\" || key === \"className\") {\n // Set the `class` ATTRIBUTE, not the `className` property. On an SVGElement\n // `className` is a read-only `SVGAnimatedString`, so assigning it throws in\n // strict mode (ESM is always strict) — `setAttribute(\"class\", …)` works for both\n // HTML and SVG. Treat false like null → empty class (consistent with the\n // attribute path's false-removes-it rule), so `() => cond && \"active\"` yields \"\"\n // (not \"false\") when the condition is falsy.\n // STRING-ONLY: a non-null/non-false value is coerced via String(value). Array\n // (`[\"a\", \"b\"]`) and object (`{ active: true }`) class forms are NOT supported —\n // they would stringify to \"a,b\" / \"[object Object]\". Compose the class string in\n // the binding itself (e.g. `() => [a, b].join(\" \")`) and pass a string. This keeps\n // the core free of a class-merging convention.\n el.setAttribute(\"class\", value == null || value === false ? \"\" : String(value));\n return;\n }\n // Remap the handful of attribute names whose JS property differs, so `for` /\n // `tabindex` / `colspan` etc. reach the right property instead of falling through\n // to setAttribute (which works for some but not e.g. `htmlFor`).\n const propKey = ATTR_TO_PROP[key] ?? key;\n if (isSettableProperty(el, propKey)) {\n // Known, WRITABLE DOM property (value, checked, disabled, id, htmlFor, ...).\n // The settability check excludes read-only members (firstChild, childNodes, …)\n // that `key in el` would wrongly accept — assigning to those throws in strict\n // mode; we fall through to the attribute path for them instead.\n //\n // NORMALIZATION: null/undefined are coerced to \"\" before assignment. Without\n // this, a STRING prop (id/title/value/src) given a reactive null/undefined\n // lands as the literal \"null\"/\"undefined\" (e.g. img.src=\"null\" fires a real\n // request) — a correctness footgun. \"\" clears the prop instead. Safe for\n // non-string props too: boolean props coerce \"\"→false (same as null), numeric\n // props coerce \"\"→0 (same as null). We do NOT normalize `false`:\n // `el.disabled = false` is the intended boolean clear.\n (el as unknown as Record<string, unknown>)[propKey] = value == null ? \"\" : value;\n return;\n }\n if (value == null || value === false) {\n el.removeAttribute(key);\n return;\n }\n if (value === true) {\n el.setAttribute(key, \"\");\n return;\n }\n el.setAttribute(key, String(value));\n}\n\nfunction setStyle(el: HTMLElement, value: unknown): void {\n if (value == null) {\n el.removeAttribute(\"style\");\n return;\n }\n if (typeof value === \"string\") {\n el.style.cssText = value;\n return;\n }\n // Object form: the object fully describes the style. Reset first so keys present\n // in a previous run but absent now are removed — otherwise a reactive style that\n // drops a key (e.g. {color,fontWeight} → {color}) would leave the stale property\n // applied. The object is the source of truth, so wiping cssText is correct here.\n el.style.cssText = \"\";\n const style = el.style as CSSStyleDeclaration & Record<string, string>;\n const obj = value as Record<string, string>;\n for (const k in obj) {\n // A key with a hyphen is either kebab-case (`font-weight`) or a CSS custom\n // property (`--accent`). Neither works via property assignment (`style[k]` would\n // just set an inert expando), so route them through setProperty. camelCase keys\n // (`fontWeight`) keep the faster property path.\n if (k.includes(\"-\")) {\n style.setProperty(k, obj[k]);\n } else {\n style[k] = obj[k];\n }\n }\n}\n\n// --- children ---------------------------------------------------------------\n\nfunction appendChildren(parent: Node, children: Child[]): void {\n for (const child of children) {\n appendChild(parent, child);\n }\n}\n\nfunction appendChild(parent: Node, child: Child): void {\n if (child == null || typeof child === \"boolean\") {\n return; // null / undefined / boolean render nothing\n }\n if (Array.isArray(child)) {\n for (const c of child) {\n appendChild(parent, c);\n }\n return;\n }\n if (isListView(child)) {\n // A keyed list (For / Index): it manages its own anchored region with in-place\n // reconciliation, so it does NOT go through the wholesale insertReactive path.\n child.mount(parent);\n return;\n }\n if (child instanceof Node) {\n parent.appendChild(child);\n return;\n }\n if (typeof child === \"function\") {\n insertReactive(parent, child as () => unknown);\n return;\n }\n if (isReadSignal(child)) {\n insertReactive(parent, () => child.get());\n return;\n }\n parent.appendChild(document.createTextNode(String(child)));\n}\n\n/**\n * A reactive insertion point. An anchor comment marks the position; on each run\n * the previous nodes are removed and the freshly-resolved nodes inserted before\n * the anchor. Using `anchor.parentNode` (not the original `parent`) keeps it\n * correct after the subtree is moved/mounted elsewhere.\n *\n * PRECONDITION: the Nodes returned by `accessor` are owned by this insertion point\n * — do not move them to another parent externally. On the next run they are\n * removed from wherever they currently are (`node.parentNode?.removeChild`), so an\n * externally-moved node would be yanked out of its new home without warning.\n *\n * OWNERSHIP: the `effect` below is owned by the enclosing reactive scope at call\n * time (the `currentOwner`). Used under `createRoot` / `SignalsElement` (the module\n * header's mount contract) it is disposed on teardown. Calling `h`/`render` with a\n * reactive child OUTSIDE any owner (no `createRoot`/`SignalsElement`) leaves this\n * effect un-owned and therefore never cleaned up — by design, per that contract.\n */\nfunction insertReactive(parent: Node, accessor: () => unknown): void {\n if (isDev() && !hasOwner()) {\n // A reactive child inserted with no enclosing owner: the effect below is never\n // disposed (the module header documents this as by-design, but it is a frequent\n // accidental leak). Warn once in dev so the un-owned mount is visible.\n warnDev(\n \"UNOWNED_INSERT\",\n \"\",\n \"reactive child inserted with no owner — its update effect will never be \" +\n \"disposed and may leak. Mount under createRoot / SignalsElement.\",\n );\n }\n const anchor = document.createComment(\"\");\n parent.appendChild(anchor);\n let current: Node[] = [];\n\n effect(() => {\n const value = accessor();\n // FAST PATH: a plain text result that replaces a plain text result. The common\n // reactive child is a string/number thunk (`() => \\`count: ${n.get()}\\``); the\n // wholesale path would remove the old Text node, allocate a new one, and re-insert\n // it on every change. When BOTH the previous and next renders are a single Text\n // node, mutate the existing node's `data` in place instead — no allocation, no\n // remove/insert, and the same DOM node identity is preserved across updates.\n if ((typeof value === \"string\" || typeof value === \"number\") && current.length === 1) {\n const node = current[0];\n if (node.nodeType === 3 /* TEXT_NODE */) {\n (node as Text).data = String(value);\n return;\n }\n }\n const next = toNodes(value);\n for (const node of current) {\n node.parentNode?.removeChild(node);\n }\n const host = anchor.parentNode;\n if (host) {\n for (const node of next) {\n host.insertBefore(node, anchor);\n }\n }\n current = next;\n });\n\n // On teardown, drop the references to the inserted Nodes. The disposed effect's\n // closure still captures `current`; if anything retains the effect after disposal\n // (e.g. a parent owner kept alive longer than the subtree), those Nodes would be\n // pinned via that closure even though they have left the DOM. Clearing the array\n // lets them be GC'd as soon as the enclosing owner tears this insertion point down.\n onCleanup(() => {\n current = [];\n });\n}\n\n// --- keyed lists: For / Index (migration-plan §9-3) --------------------------\n//\n// `insertReactive` rebuilds its whole subtree on every change. For lists that is\n// wasteful (and drops per-row state). `For` / `Index` instead keep a stable DOM row\n// per item and reconcile in place. Each row is built under its OWN `createRoot`, so\n// removing a row disposes exactly that row's effects/resources/listeners — the owner\n// tree (§8 (d)) is what makes this leak-free. The reconcile runs in a single\n// `effect` owned by the enclosing scope; an `onCleanup` disposes surviving rows when\n// that scope (e.g. the component) tears down.\n//\n// CONTRACT: `each` must return a SINGLE Node (one row = one node). Keys (For) must\n// be unique. `For` keys by value identity (=== / explicit `key`) and passes the\n// index as an accessor (it changes on move); `Index` keys by position and passes the\n// item as an accessor (the value at a slot changes, the slot does not).\n\nexport type ListAccessor<T> = ReadSignal<readonly T[]> | (() => readonly T[]);\n/**\n * `For`'s row builder. `item` is the item the row was built for — a plain value. A keyed row is\n * kept while its key is (an immutable update hands it a new object under the same key), so read\n * what changes through `current`, an accessor of the item under the row's key now\n * (`() => current().text`). docs/seam-apps.md, signals-shop.\n */\nexport type ForEach<T> = (item: T, index: () => number, current: () => T) => Node;\nexport type IndexEach<T> = (item: () => T, index: number) => Node;\n\n/**\n * The return type of {@link For} / {@link Index}: a keyed list that owns an anchored\n * region and reconciles rows in place. Exported (D4) so consumers can annotate\n * helpers that build or pass around lists. `mount` is called by `h`/`render` when the\n * list is used as a child; `__wcsList` is the brand `appendChild` checks.\n */\nexport interface ListView {\n readonly __wcsList: true;\n mount(parent: Node): void;\n}\n\nfunction isListView(value: unknown): value is ListView {\n return typeof value === \"object\" && value !== null && (value as ListView).__wcsList === true;\n}\n\nfunction readList<T>(list: ListAccessor<T>): () => readonly T[] {\n return isReadSignal(list) ? () => (list as ReadSignal<readonly T[]>).get() : (list as () => readonly T[]);\n}\n\nexport interface ForOptions<T> {\n /** Derive a unique key per item. Default: the item value itself (identity). */\n key?: (item: T, index: number) => unknown;\n}\n\n// --- LIS-based DOM reorder ---------------------------------------------------\n//\n// `reconcileOrder` brings the live DOM under `host` (the contiguous region ending\n// at `anchor`) into `order` — the desired final node sequence — using the FEWEST\n// `insertBefore` moves, while producing EXACTLY the order a naive full re-place\n// would. The naive approach (walk and insert every out-of-place node) does up to\n// O(n) DOM moves on a full reverse or a head insert; here we instead keep the\n// largest set of reused rows that are ALREADY in the right relative order, and\n// move only the others (Solid's reconcileArrays / udomdiff idea).\n//\n// HOW: `prevOrder` is the node sequence the previous run left in the DOM. For each\n// node in the new `order`, a reused row maps to its index in `prevOrder`; a freshly\n// created row has no previous position. The longest increasing subsequence (LIS)\n// of those previous indices marks the reused rows that need NOT move (their pairwise\n// relative order is already correct). Every other node — fresh ones, and reused\n// ones outside the LIS — is inserted before its already-correct successor, walking\n// back-to-front so the \"successor\" reference is always a settled node or the anchor.\n\n/**\n * Indices into `arr` (with value -1 meaning \"no previous position\") whose values\n * form a longest strictly-increasing subsequence. Entries equal to -1 are treated\n * as never part of the subsequence (a fresh node always moves). Classic\n * patience-sorting LIS in O(n log n); returns the chosen indices in ascending order.\n */\nfunction longestIncreasingSubsequence(arr: number[]): number[] {\n const n = arr.length;\n // `tails[k]` = index (into arr) of the smallest tail of an increasing\n // subsequence of length k+1. `prev[i]` = predecessor index, to rebuild the chain.\n const tails: number[] = [];\n const prev: number[] = new Array(n).fill(-1);\n for (let i = 0; i < n; i++) {\n const value = arr[i];\n if (value < 0) {\n continue; // fresh node: not eligible for the stable subsequence\n }\n // Binary search for the first tail whose value is >= this value, and replace it\n // (or extend the tails when this value beats every tail).\n let lo = 0;\n let hi = tails.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if (arr[tails[mid]] < value) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n if (lo > 0) {\n prev[i] = tails[lo - 1];\n }\n tails[lo] = i;\n }\n // Rebuild the index chain from the longest tail backwards.\n const result: number[] = [];\n let k = tails.length > 0 ? tails[tails.length - 1] : -1;\n while (k >= 0) {\n result.push(k);\n k = prev[k];\n }\n result.reverse();\n return result;\n}\n\nfunction reconcileOrder(\n host: Node,\n anchor: Node,\n order: Node[],\n prevOrder: Node[],\n): void {\n const n = order.length;\n if (n === 0) {\n return; // nothing to place (removals already happened)\n }\n\n // Map each previous node to its previous position, so a node in `order` can look\n // up where it used to be. A node absent from this map is FRESH (created this run,\n // or the first run where prevOrder is empty) and is encoded as -1 — it always moves.\n const prevIndex = new Map<Node, number>();\n for (let i = 0; i < prevOrder.length; i++) {\n prevIndex.set(prevOrder[i], i);\n }\n\n // previous-position sequence aligned to the new order. -1 marks a fresh node.\n const seq: number[] = new Array(n);\n for (let i = 0; i < n; i++) {\n const p = prevIndex.get(order[i]);\n seq[i] = p === undefined ? -1 : p;\n }\n\n // Rows whose relative order is already correct: leave them in place, move the rest.\n const lis = longestIncreasingSubsequence(seq);\n let lisPtr = lis.length - 1;\n\n // Walk back-to-front. `ref` is the node that must follow the one being placed; it\n // starts at the anchor (the region's tail) and becomes each placed node. A node in\n // the LIS is the maximal already-correctly-ordered set, so it is left untouched\n // (only adopted as the new `ref`). Every OTHER node is, by construction, out of\n // position relative to its settled successor and is inserted before `ref` — no\n // \"is it already in place?\" guard is needed (it never is, unlike the old\n // full-walk reconciler which visited correctly-placed nodes too).\n let ref: Node = anchor;\n for (let i = n - 1; i >= 0; i--) {\n const node = order[i];\n if (lisPtr >= 0 && lis[lisPtr] === i) {\n lisPtr--; // stable: do not move\n } else {\n host.insertBefore(node, ref);\n }\n ref = node;\n }\n}\n\n// Dev-only key sanity check (no effect in production — guarded by `isDev()` at the\n// call site so this is never reached when dev is off). Flags the silent-failure key\n// shapes: a nullish key (NaN / null / undefined collide under SameValueZero, so two\n// such items map to one row and a row is silently dropped), and — when no explicit\n// `key` was given — a non-primitive item used as its own identity key (every render\n// gets a fresh object reference, so the row is rebuilt instead of reused, silently\n// dropping per-row state). Warns once per distinct shape (deduped in warnDev).\nfunction checkKeyDev(key: unknown, item: unknown, hasExplicitKey: boolean): void {\n if (key == null || (typeof key === \"number\" && Number.isNaN(key))) {\n warnDev(\n \"NULLISH_KEY\",\n String(key),\n \"For: a key is null/undefined/NaN. Such keys collide under SameValueZero, \" +\n \"so rows silently merge/drop. Provide a stable unique `key`.\",\n { key },\n );\n return;\n }\n if (!hasExplicitKey && (typeof key === \"object\" || typeof key === \"function\")) {\n warnDev(\n \"NON_PRIMITIVE_KEY\",\n typeof key,\n \"For: a non-primitive item is used as its own key (no `key` option given). \" +\n \"Object identity changes across renders, so every row is rebuilt and per-row \" +\n \"state is lost. Pass `{ key: item => item.id }`.\",\n { item },\n );\n }\n}\n\nexport function For<T>(list: ListAccessor<T>, each: ForEach<T>, options?: ForOptions<T>): ListView {\n const read = readList(list);\n const keyOf = options?.key;\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"for\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n idx: WriteSignal<number>;\n /** The item under the row's key now (`each`'s `current`). */\n cur: WriteSignal<T>;\n }\n let rows = new Map<unknown, Row>();\n // The node order placed by the previous reconcile run. Empty on first run.\n // Used to find which reused rows already sit in increasing relative order so\n // only the rest are moved (LIS reorder, see reconcileOrder).\n let prevOrder: Node[] = [];\n\n const make = (item: T, i: number): Row => {\n const idx = signal(i);\n const cur = signal(item);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(item, () => idx.get(), () => cur.get());\n return d;\n });\n return { node, dispose, idx, cur };\n };\n\n effect(() => {\n const items = read() ?? [];\n\n // Key-uniqueness PRE-PASS (no side effects): throwing here, before any row is\n // created or moved, keeps a duplicate-key error from leaving half-built rows\n // orphaned (make() runs createRoot) and the DOM mid-reorder. Keys are reused\n // below so keyOf runs once per item.\n const keys: unknown[] = [];\n const seen = new Set<unknown>();\n const dev = isDev();\n for (let i = 0; i < items.length; i++) {\n const k = keyOf ? keyOf(items[i], i) : items[i];\n if (dev) {\n checkKeyDev(k, items[i], keyOf !== undefined);\n }\n if (seen.has(k)) {\n if (dev) {\n // The throw below still halts (production behaviour unchanged); the warn\n // adds the offending key + a pointer to the cause so the silent\n // \"updates stopped\" symptom is diagnosable.\n warnDev(\n \"DUPLICATE_KEY\",\n String(k),\n `For: duplicate key \"${String(k)}\" at index ${i} — keys must be unique. ` +\n \"Rendering throws and the list stops updating until keys are fixed.\",\n { key: k, index: i },\n );\n }\n throw new Error(`For: duplicate key \"${String(k)}\" — keys must be unique.`);\n }\n seen.add(k);\n keys.push(k);\n }\n\n const next = new Map<unknown, Row>();\n const order: Node[] = [];\n\n // Rows freshly created in THIS run (not reused from `rows`). If a later\n // `make()` — i.e. a user `each` — throws mid-loop, the rows already built\n // here are owned by their own detached `createRoot` and are not yet tracked\n // in any surviving map, so they would leak. Dispose them before re-throwing,\n // leaving the old `rows` map untouched (it is recoverable on the next run).\n const fresh: Row[] = [];\n try {\n for (let i = 0; i < items.length; i++) {\n const k = keys[i];\n let row = rows.get(k);\n if (row) {\n if (row.idx.peek() !== i) {\n row.idx.set(i); // position changed — refresh the index accessor\n }\n row.cur.set(items[i]); // the item under the key now (a no-op when it is the same)\n } else {\n row = make(items[i], i);\n fresh.push(row);\n }\n next.set(k, row);\n order.push(row.node);\n }\n } catch (err) {\n for (const row of fresh) {\n row.dispose();\n }\n throw err;\n }\n\n // The LIVE parent (`anchor.parentNode`, not the mount arg) so the region\n // stays correct after being moved (e.g. built inside a Fragment, then\n // appended elsewhere). `host` is null only if the anchor was detached\n // without disposing this scope (a misuse) — then there is nothing to\n // place into. Resolved before the removal phase so the wholesale-removal\n // fast path below can use it.\n const host = anchor.parentNode;\n\n // Dispose rows whose key vanished. `remove()` no-ops if already detached.\n if (rows.size > 0 && next.size === fresh.length) {\n // ZERO-REUSE run: no existing key survives (clear, or a full replacement\n // with disjoint keys), so EVERY current row is removed. When the host\n // contains exactly this list's region — first child is the region's\n // first row, last child is the anchor, and the child count matches\n // rows + anchor — detach them all with a single native\n // `textContent = \"\"` and re-append the anchor, instead of one\n // `remove()` per row (the dominant cost of clearing large lists).\n // Any deviation (foreign sibling, externally detached row, shared\n // host) fails the guard and falls back to the per-row path.\n // Disposal always runs per row; only the DOM detachment is batched.\n if (\n host !== null &&\n host.lastChild === anchor &&\n prevOrder.length > 0 &&\n host.firstChild === prevOrder[0] &&\n host.childNodes.length === rows.size + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows.values()) {\n row.dispose();\n }\n } else {\n for (const row of rows.values()) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n } else {\n for (const [k, row] of rows) {\n if (!next.has(k)) {\n (row.node as ChildNode).remove();\n row.dispose();\n }\n }\n }\n if (host) {\n reconcileOrder(host, anchor, order, prevOrder);\n }\n\n // Snapshot this run's final order so the NEXT run's reconcile can detect\n // which rows kept their relative position (the LIS basis below). Capturing\n // the array we just placed avoids re-deriving it from the map.\n prevOrder = order;\n rows = next;\n });\n\n onCleanup(() => {\n for (const row of rows.values()) {\n row.dispose();\n }\n rows.clear();\n });\n },\n };\n}\n\nexport function Index<T>(list: ListAccessor<T>, each: IndexEach<T>): ListView {\n const read = readList(list);\n return {\n __wcsList: true,\n mount(parent: Node): void {\n const anchor = document.createComment(\"index\");\n parent.appendChild(anchor);\n\n interface Row {\n node: Node;\n dispose: () => void;\n item: WriteSignal<T>;\n }\n const rows: Row[] = [];\n\n effect(() => {\n const items = read() ?? [];\n // Live parent (see `For`), null only if the anchor was detached undisposed.\n const host = anchor.parentNode;\n\n for (let i = 0; i < items.length; i++) {\n if (i < rows.length) {\n // Slot reused: just push the new value into the row's item signal. The\n // signal's equality guard skips the update when the value is unchanged.\n rows[i].item.set(items[i]);\n } else {\n const item = signal(items[i]);\n let node!: Node;\n const dispose = createRoot((d) => {\n node = each(() => item.get(), i);\n return d;\n });\n rows.push({ node, dispose, item });\n // Positions never move for index keying, so append at the tail (before\n // the anchor) in order. ORDERING CONTRACT (shared with For and the other\n // anchored insertions): the list owns the contiguous region ENDING at its\n // anchor comment. New rows go immediately before the anchor, so the list's\n // own rows always stay correctly ordered and grouped, and static siblings\n // before the anchor (or another list with its own anchor) are never\n // disturbed. Do NOT splice unrelated nodes into the middle of this region.\n host?.insertBefore(node, anchor);\n }\n }\n\n // Trailing slots that no longer exist: dispose and drop.\n if (items.length < rows.length) {\n // WHOLESALE CLEAR (same idea as For's zero-reuse fast path): every slot\n // vanishes and the host holds exactly this list's region (all rows +\n // the anchor), so one native `textContent = \"\"` replaces per-row\n // `remove()`. Guard failures (foreign sibling, detached row, shared\n // host) fall back to the per-row path. Disposal still runs per row.\n if (\n items.length === 0 &&\n host !== null &&\n host.lastChild === anchor &&\n host.firstChild === rows[0].node &&\n host.childNodes.length === rows.length + 1\n ) {\n host.textContent = \"\";\n host.appendChild(anchor);\n for (const row of rows) {\n row.dispose();\n }\n } else {\n for (let i = items.length; i < rows.length; i++) {\n (rows[i].node as ChildNode).remove();\n rows[i].dispose();\n }\n }\n rows.length = items.length;\n }\n });\n\n onCleanup(() => {\n for (const row of rows) {\n row.dispose();\n }\n rows.length = 0;\n });\n },\n };\n}\n\n// --- custom element lifecycle (docs §8 (e)) ---------------------------------\n//\n// The exit point for ownership: a custom element that mounts a signals view under\n// `createRoot` on connect and disposes that root on disconnect. This wires the\n// reactive ownership tree to the real DOM lifecycle — every effect, resource and\n// listener created in `render()` is torn down when the element leaves the DOM, and\n// rebuilt fresh on reconnect. Subclasses only implement `render()`.\n//\n// SCOPE (v1 intentional constraints — drive these reactively, not via this base):\n// - No attribute reactivity. There is no `attributeChangedCallback`/\n// `observedAttributes` wiring: this base does NOT turn HTML attributes into\n// signals. Feed reactive inputs as signals/props from the code that constructs\n// the view (or have a subclass map attributes to signals itself).\n// - Shadow DOM is opt-in and subclass-owned. The default mount point is light DOM\n// (`this`); a subclass that wants encapsulation overrides `getMountPoint()` to\n// return a shadow root it created (e.g. `this.attachShadow(...)` in its\n// constructor). This base never calls attachShadow implicitly.\n// - Mount/unmount only: render() runs once per connect and the whole subtree is\n// disposed on disconnect — there is no partial/incremental re-render hook here\n// (fine-grained updates come from the signals wired inside render()).\n\n// TYPE-ONLY shape of the lifecycle base. `declare abstract class` emits NO runtime\n// code (so it does not reference `HTMLElement` at module-evaluation time — the whole\n// point of the lazy factory below), but it gives the exported `SignalsElement` value\n// and `createSignalsElement()`'s return a precise type that preserves the original\n// contract: `render` is `protected abstract` (a subclass MUST implement it and may\n// only reach it from within), and `getMountPoint` is `protected` (overridable). This\n// is the same surface the previous concrete `abstract class SignalsElement` exposed.\n// (Used only via `typeof` below; the lint rule does not see that as a value use.)\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare abstract class SignalsElementType extends HTMLElement {\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node;\n connectedCallback(): void;\n disconnectedCallback(): void;\n}\n\n/**\n * The lifecycle base contract: the abstract constructor type of the `SignalsElement`\n * base. Abstract, so `new SignalsElement()` is rejected (the base has an unimplemented\n * `render`) while `class X extends SignalsElement` is allowed. Returned by\n * {@link createSignalsElement} and the type of the {@link SignalsElement} value.\n */\nexport type SignalsElementClass = typeof SignalsElementType;\n\n// Memoized base class. Built lazily on first access so the `./dom` module can be\n// EVALUATED in a non-DOM environment (SSR pre-pass, a worker without a DOM shim)\n// without a top-level `class … extends HTMLElement` blowing up with\n// `ReferenceError: HTMLElement is not defined`. The class body is only constructed\n// when the consumer actually reaches for the base — at which point a DOM is required\n// and its absence yields a clear, actionable error instead of a raw ReferenceError.\nlet cachedBase: SignalsElementClass | null = null;\n\n/**\n * Build (once, memoized) the `SignalsElement` lifecycle base class. Resolves\n * `HTMLElement` at CALL TIME, so importing `@wcstack/signals/dom` no longer requires\n * a DOM at module-evaluation time — only *calling* this (or subclassing\n * {@link SignalsElement}) does.\n *\n * Contract:\n * - The `.` entry (`@wcstack/signals`) is non-DOM: it evaluates and runs in SSR,\n * Node, and Web Workers with no DOM globals.\n * - The `./dom` entry (`@wcstack/signals/dom`) may now also be *evaluated* without a\n * DOM (so an SSR pre-pass that imports it for the headless re-exports does not\n * crash). The DOM-touching surface — `h`/`render`/`For`/`Index` and this base —\n * still requires DOM globals when actually used.\n *\n * @throws a clear `Error` (not a raw `ReferenceError`) when no `HTMLElement` global is\n * present, naming the offending entry so the failure is self-explanatory.\n */\nexport function createSignalsElement(): SignalsElementClass {\n if (cachedBase !== null) {\n return cachedBase;\n }\n if (typeof HTMLElement === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: SignalsElement requires a DOM (HTMLElement is not defined). \" +\n \"The `./dom` entry's element/render surface is browser-only; in SSR/Node/worker \" +\n \"code import the headless core from `@wcstack/signals` instead, or inject a DOM \" +\n \"(e.g. happy-dom) before constructing custom elements.\",\n );\n }\n\n abstract class SignalsElementBase extends HTMLElement {\n private _dispose: (() => void) | null = null;\n\n /** Build the view with `h` + signals. Runs inside an ownership root. */\n protected abstract render(): Node;\n\n /** Mount target. Override to return a shadow root; default is light DOM. */\n protected getMountPoint(): Node {\n return this;\n }\n\n connectedCallback(): void {\n if (this._dispose !== null) {\n return; // already mounted (defensive against a redundant connect)\n }\n const mount = this.getMountPoint();\n // If render() throws, createRoot disposes any effects it built before the throw,\n // so nothing leaks; _dispose stays null (the element is simply not mounted) and\n // a later disconnectedCallback safely no-ops. The error propagates to the caller.\n this._dispose = createRoot((dispose) => {\n mount.appendChild(this.render());\n return dispose;\n });\n }\n\n disconnectedCallback(): void {\n if (this._dispose === null) {\n return; // not mounted\n }\n this._dispose();\n this._dispose = null;\n const mount = this.getMountPoint();\n while (mount.firstChild) {\n mount.removeChild(mount.firstChild);\n }\n }\n }\n\n cachedBase = SignalsElementBase as unknown as SignalsElementClass;\n return cachedBase;\n}\n\n// `SignalsElement` is the ergonomic name to `extends`. It is a lazily-resolved alias\n// for the class built by `createSignalsElement()`: a Proxy that forwards construct /\n// get / has / getPrototypeOf to the real (memoized) base, building it on first touch.\n// This keeps `class X extends SignalsElement { … }` working exactly as before WHILE\n// deferring the `HTMLElement` reference to subclass-definition time (in a real DOM),\n// instead of `./dom` module-evaluation time (which may be a non-DOM SSR pre-pass).\n//\n// BREAKING note: the value is now a Proxy, not the class object literal. Subclassing,\n// `instanceof`, and static/prototype access all still work; a consumer that relied on\n// `SignalsElement` being a *frozen* concrete class reference (uncommon) should call\n// `createSignalsElement()` to obtain the real class.\n// The Proxy target is a never-called placeholder (every operation is intercepted by a\n// trap below); it only needs to be constructable/callable so `new` / `extends` and the\n// `apply` trap engage. It is intentionally a no-op and never executed.\n/* v8 ignore next */\nconst signalsElementTarget = function (): void {};\nexport const SignalsElement: SignalsElementClass = new Proxy(signalsElementTarget as unknown as SignalsElementClass, {\n construct(_target, args, newTarget): object {\n return Reflect.construct(createSignalsElement(), args, newTarget);\n },\n get(_target, prop, receiver): unknown {\n return Reflect.get(createSignalsElement(), prop, receiver);\n },\n has(_target, prop): boolean {\n return Reflect.has(createSignalsElement(), prop);\n },\n apply(): never {\n throw new TypeError(\"SignalsElement is a class and cannot be invoked without `new`/`extends`.\");\n },\n getPrototypeOf(): object | null {\n return Reflect.getPrototypeOf(createSignalsElement());\n },\n});\n\nfunction toNodes(value: unknown): Node[] {\n const out: Node[] = [];\n const visit = (v: unknown): void => {\n if (v == null || typeof v === \"boolean\") {\n return;\n }\n if (Array.isArray(v)) {\n v.forEach(visit);\n return;\n }\n if (v instanceof Node) {\n out.push(v);\n return;\n }\n out.push(document.createTextNode(String(v)));\n };\n visit(value);\n return out;\n}\n\n// --- mountNode: create + bind + mount a headless wc-bindable node -------------\n//\n// `bindNode` adapts an EXISTING element, which forces its caller to guarantee the\n// custom element class is already registered (the descriptor is read from\n// `el.constructor.wcBindable` at call time — an un-upgraded element has none).\n// `mountNode` closes that gap for the common signals shape where the app OWNS its\n// headless IO nodes: it creates the element AFTER the definition exists (so it is\n// upgraded at construction), binds it, then connects it. The recommended pairing\n// is a side-effect import of the package's `/auto` entry in the same module —\n// module evaluation order then guarantees the definition:\n//\n// import \"@wcstack/fetch/auto\";\n// const fetcher = mountNode(\"wcs-fetch\", { attrs: { url: \"/api/people\" } });\n// fetcher.signals.value.get();\n//\n// The internal order is deliberate: attributes are set BEFORE connect (shells read\n// their config in `connectedCallback`), and the adapter subscribes BEFORE connect,\n// so an event fired from `connectedCallback` is already observed — the missed-event\n// window is structurally zero, not merely closed by bindNode's re-seed. Like\n// `bindNode`, the adapter is NOT auto-registered with a reactive owner; teardown is\n// explicit via `unmount()` — to which `dispose()` is aliased, see MountedNode —\n// (compose with `onCleanup(() => m.unmount())` if the node should die with a\n// scope). See docs/signals-definition-timing.md for the full definition-timing\n// contract (optional packages via dynamic import, the remaining whenDefined /\n// <wcs-defined> territory).\n\nexport interface MountNodeOptions {\n /**\n * Attributes set on the element BEFORE it is connected (declarative pre-connect\n * config, e.g. `{ url: \"/api\", timeout: 5000 }`). HTML boolean-attribute\n * semantics: `true` sets an empty attribute, `false` omits it; other values are\n * stringified.\n */\n attrs?: Record<string, string | number | boolean>;\n /** Parent to append the element to. Default: `document.body`. */\n parent?: Node;\n /**\n * Explicit wc-bindable descriptor forwarded to `bindNode`. When given, the\n * tag-definition check is skipped — the escape hatch for binding a\n * non-custom-element tag, mirroring `bindNode`'s second parameter.\n */\n descriptor?: WcBindableDescriptor;\n}\n\nexport interface MountedNode<S extends NodeShape = DefaultNodeShape> extends BoundNode<S> {\n /** The created element (connected until `unmount()`). */\n readonly el: HTMLElement;\n /**\n * Full teardown: dispose the adapter AND remove the element from the DOM\n * (disconnect stops the shell's IO). Idempotent. On a `MountedNode`,\n * `dispose()` is an alias of this — mountNode owns the element's lifecycle,\n * so the package-wide teardown verb must not leave a connected element with\n * live IO behind (a silent leak for callers habituated to `bindNode`).\n */\n unmount(): void;\n}\n\nexport function mountNode<S extends NodeShape = DefaultNodeShape>(\n tagName: string,\n options: MountNodeOptions = {},\n): MountedNode<S> {\n // Call-time DOM guard (not module-time): `./dom` must evaluate in non-DOM realms\n // (SSR pre-pass / worker) — same contract (and message shape) as `createSignalsElement`.\n if (typeof document === \"undefined\" || typeof customElements === \"undefined\") {\n throw new Error(\n \"@wcstack/signals/dom: mountNode requires a DOM (document/customElements is not defined). \" +\n \"It creates and connects a live element, so it is browser-only; inject a DOM \" +\n \"(e.g. happy-dom) before calling, or keep headless work on `@wcstack/signals`.\",\n );\n }\n const { attrs, parent, descriptor } = options;\n // Custom element names are lowercase; the registry is exact-key while\n // createElement ASCII-lowercases — normalize once so mountNode(el.tagName)\n // (uppercase in HTML documents) hits the same definition the element would.\n const tag = tagName.toLowerCase();\n // Fail loud with the actual cause. Without this, bindNode's generic \"no\n // wc-bindable descriptor\" error hides that the tag simply isn't defined yet.\n if (!descriptor && !customElements.get(tag)) {\n throw new Error(\n `mountNode: \"<${tag}>\" is not defined. Import its defining module first (e.g. a side-effect ` +\n `\\`import \"@wcstack/<pkg>/auto\"\\` in this module — evaluation order then guarantees the definition). ` +\n `For a tag loaded by someone else, await customElements.whenDefined(\"${tag}\") or gate with ` +\n `<wcs-defined> before mounting. Binding a non-custom-element tag requires an explicit \\`descriptor\\`.`,\n );\n }\n\n const el = document.createElement(tag);\n if (attrs) {\n for (const [name, value] of Object.entries(attrs)) {\n if (value === false) {\n continue; // boolean-attribute semantics: false = absent\n }\n el.setAttribute(name, value === true ? \"\" : String(value));\n }\n }\n const bound = bindNode<S>(el, descriptor);\n (parent ?? document.body).appendChild(el);\n const unmount = (): void => {\n bound.dispose();\n el.remove();\n };\n return {\n ...bound,\n el,\n unmount,\n // Override the inherited adapter-only dispose(): on a MountedNode it would be\n // a silent PARTIAL teardown (signals inert, but the created element stays\n // connected with its shell's IO still running). mountNode owns the element,\n // so dispose === unmount.\n dispose: unmount,\n };\n}\n"],"names":["Fragment","Symbol","isReadSignal","value","get","peek","h","tag","props","children","frag","document","createDocumentFragment","appendChildren","result","Array","isArray","wrapFragment","el","SVG_TAGS","has","createElementNS","SVG_NS","createElement","key","bindProp","Set","render","child","container","appendChild","ATTR_TO_PROP","for","tabindex","colspan","rowspan","readonly","maxlength","minlength","contenteditable","settableCache","WeakMap","isSettableProperty","proto","Object","getPrototypeOf","byKey","undefined","Map","set","obj","desc","getOwnPropertyDescriptor","writable","computeSettable","test","type","slice","toLowerCase","listener","addEventListener","onCleanup","removeEventListener","effect","setProp","removeAttribute","style","cssText","k","includes","setProperty","setStyle","setAttribute","String","propKey","parent","c","__wcsList","Node","insertReactive","createTextNode","mount","accessor","isDev","hasOwner","warnDev","anchor","createComment","current","length","node","nodeType","data","next","out","visit","v","forEach","push","toNodes","parentNode","removeChild","host","insertBefore","readList","list","reconcileOrder","order","prevOrder","n","prevIndex","i","seq","p","lis","arr","tails","prev","fill","lo","hi","mid","reverse","longestIncreasingSubsequence","lisPtr","ref","checkKeyDev","item","hasExplicitKey","Number","isNaN","For","each","options","read","keyOf","rows","make","idx","signal","cur","dispose","createRoot","d","items","keys","seen","dev","index","Error","add","fresh","row","err","size","lastChild","firstChild","childNodes","textContent","values","remove","clear","Index","cachedBase","createSignalsElement","HTMLElement","SignalsElementBase","_dispose","getMountPoint","this","connectedCallback","disconnectedCallback","SignalsElement","Proxy","construct","_target","args","newTarget","Reflect","prop","receiver","apply","TypeError","mountNode","tagName","customElements","attrs","descriptor","name","entries","bound","bindNode","body","unmount"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wcstack/signals",
3
- "version": "4.0.4",
3
+ "version": "4.1.0",
4
4
  "description": "Signals-based lightweight reactive core with async-IO resource adapters and a wc-bindable → signal bridge for Web Components. Zero runtime dependencies.",
5
5
  "type": "module",
6
6
  "sideEffects": false,