elements-kit 0.0.17 → 0.0.19

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.
Files changed (103) hide show
  1. package/README.md +97 -19
  2. package/dist/attributes.d.mts +1 -1
  3. package/dist/{define-CjbTZ3VG.d.mts → custom-elements-bVYOkHKt.d.mts} +2 -2
  4. package/dist/custom-elements.d.mts +2 -74
  5. package/dist/custom-elements.mjs +2 -91
  6. package/dist/{element-CGVy_8TW.mjs → element-DxmInKJw.mjs} +32 -20
  7. package/dist/for.d.mts +1 -1
  8. package/dist/for.mjs +3 -2
  9. package/dist/infer-Dv5Wk-7E.d.mts +618 -0
  10. package/dist/integrations/react.d.mts +1 -1
  11. package/dist/integrations/react.mjs +6 -4
  12. package/dist/jsx-runtime/index.d.mts +2 -73
  13. package/dist/jsx-runtime/index.mjs +8 -14
  14. package/dist/{signals-J8dK_rA4.mjs → lib-D6duEs38.mjs} +1 -105
  15. package/dist/render.d.mts +21 -0
  16. package/dist/render.mjs +32 -0
  17. package/dist/scope-DM2gzOkb.mjs +45 -0
  18. package/dist/signals/index.d.mts +1 -1
  19. package/dist/signals/index.mjs +115 -1
  20. package/dist/{slot-C7GQZe-r.d.mts → slot-B5_VHB7E.d.mts} +10 -0
  21. package/dist/slot.d.mts +1 -1
  22. package/dist/{test.BmQO5GaM-DfGStnii.mjs → test.BmQO5GaM-BeO5pvCo.mjs} +1 -1
  23. package/dist/utilities/_observe.mjs +2 -1
  24. package/dist/utilities/active-element.d.mts +1 -1
  25. package/dist/utilities/active-element.mjs +2 -1
  26. package/dist/utilities/active-element.test.mjs +1 -1
  27. package/dist/utilities/async.d.mts +1 -1
  28. package/dist/utilities/async.mjs +2 -1
  29. package/dist/utilities/async.test.mjs +3 -2
  30. package/dist/utilities/debounced.d.mts +1 -1
  31. package/dist/utilities/debounced.mjs +2 -1
  32. package/dist/utilities/debounced.test.mjs +3 -2
  33. package/dist/utilities/element-rect.d.mts +1 -1
  34. package/dist/utilities/element-rect.mjs +2 -1
  35. package/dist/utilities/element-rect.test.mjs +3 -2
  36. package/dist/utilities/element-scroll.d.mts +1 -1
  37. package/dist/utilities/element-scroll.test.mjs +3 -2
  38. package/dist/utilities/event-driven.d.mts +1 -1
  39. package/dist/utilities/event-driven.mjs +2 -1
  40. package/dist/utilities/event-listener.d.mts +1 -1
  41. package/dist/utilities/event-listener.mjs +2 -1
  42. package/dist/utilities/event-listener.test.mjs +3 -2
  43. package/dist/utilities/focus-within.d.mts +1 -1
  44. package/dist/utilities/focus-within.mjs +2 -1
  45. package/dist/utilities/focus-within.test.mjs +3 -2
  46. package/dist/utilities/hover.d.mts +1 -1
  47. package/dist/utilities/hover.mjs +2 -1
  48. package/dist/utilities/hover.test.mjs +3 -2
  49. package/dist/utilities/intersection-observer.test.mjs +3 -2
  50. package/dist/utilities/interval.d.mts +1 -1
  51. package/dist/utilities/interval.mjs +2 -1
  52. package/dist/utilities/interval.test.mjs +3 -2
  53. package/dist/utilities/location.d.mts +1 -1
  54. package/dist/utilities/location.mjs +2 -1
  55. package/dist/utilities/location.test.mjs +1 -1
  56. package/dist/utilities/long-press.test.mjs +3 -2
  57. package/dist/utilities/media-devices.d.mts +1 -1
  58. package/dist/utilities/media-devices.mjs +2 -1
  59. package/dist/utilities/media-devices.test.mjs +3 -2
  60. package/dist/utilities/media-player.d.mts +1 -1
  61. package/dist/utilities/media-player.test.mjs +3 -2
  62. package/dist/utilities/media-query.d.mts +1 -1
  63. package/dist/utilities/media-query.mjs +2 -1
  64. package/dist/utilities/mutation-observer.test.mjs +3 -2
  65. package/dist/utilities/network.d.mts +1 -1
  66. package/dist/utilities/network.mjs +2 -1
  67. package/dist/utilities/network.test.mjs +1 -1
  68. package/dist/utilities/on-click-outside.test.mjs +3 -2
  69. package/dist/utilities/orientation.d.mts +1 -1
  70. package/dist/utilities/orientation.mjs +2 -1
  71. package/dist/utilities/previous.d.mts +1 -1
  72. package/dist/utilities/previous.mjs +2 -1
  73. package/dist/utilities/previous.test.mjs +3 -2
  74. package/dist/utilities/promise.d.mts +1 -1
  75. package/dist/utilities/promise.mjs +2 -1
  76. package/dist/utilities/promise.test.mjs +3 -2
  77. package/dist/utilities/retry.mjs +2 -1
  78. package/dist/utilities/retry.test.mjs +3 -2
  79. package/dist/utilities/routing.d.mts +1 -1
  80. package/dist/utilities/routing.mjs +2 -1
  81. package/dist/utilities/routing.test.mjs +1 -1
  82. package/dist/utilities/search-params.d.mts +1 -1
  83. package/dist/utilities/search-params.test.mjs +3 -2
  84. package/dist/utilities/ssr.test.mjs +1 -1
  85. package/dist/utilities/storage.d.mts +1 -1
  86. package/dist/utilities/storage.test.mjs +3 -2
  87. package/dist/utilities/throttled.d.mts +1 -1
  88. package/dist/utilities/throttled.mjs +2 -1
  89. package/dist/utilities/throttled.test.mjs +3 -2
  90. package/dist/utilities/timeout.d.mts +1 -1
  91. package/dist/utilities/timeout.mjs +2 -1
  92. package/dist/utilities/timeout.test.mjs +3 -2
  93. package/dist/utilities/window-focus.d.mts +1 -1
  94. package/dist/utilities/window-focus.mjs +2 -1
  95. package/dist/utilities/window-size.d.mts +1 -1
  96. package/dist/utilities/window-size.mjs +2 -1
  97. package/dist/utilities/window-size.test.mjs +1 -1
  98. package/package.json +6 -1
  99. package/dist/index-DydGTqZU.d.mts +0 -315
  100. package/dist/infer-BfzRJoCn.d.mts +0 -203
  101. package/dist/polyfill-BVNd6ogU.d.mts +0 -9
  102. /package/dist/{attributes-Dtn68R1u.d.mts → attributes-aiRoArZz.d.mts} +0 -0
  103. /package/dist/{magic-string.es-i62WTP6J.mjs → magic-string.es-cTgJnTCj.mjs} +0 -0
package/README.md CHANGED
@@ -25,8 +25,8 @@ class CounterElement extends HTMLElement {
25
25
  this.appendChild(
26
26
  <section>
27
27
  <p>Count: <strong>{() => this.count}</strong> — Doubled: <strong>{this.doubled}</strong></p>
28
- <button onClick={() => this.count++}>+1</button>{" "}
29
- <button onClick={() => this.count--}>−1</button>
28
+ <button on:click={() => this.count++}>+1</button>{" "}
29
+ <button on:click={() => this.count--}>−1</button>
30
30
  </section> as Element,
31
31
  );
32
32
  }
@@ -43,11 +43,14 @@ Every feature is a separate subpath export — import only what you use.
43
43
 
44
44
  | Entry | Purpose |
45
45
  |-------|---------|
46
- | `elements-kit` | `For` and core re-exports |
47
- | `elements-kit/signals` | `signal`, `computed`, `effect`, `effectScope`, `batch`, `untracked`, `trigger`, `onCleanup`, `@reactive` |
48
- | `elements-kit/attributes` | `@attributes` decorator + `ATTRIBUTES` symbol for custom elements |
49
- | `elements-kit/slot` | `Slot` class comment-marker DOM regions |
50
- | `elements-kit/jsx-runtime` | JSX factory (configure via `jsxImportSource`) |
46
+ | `elements-kit` | `For` component and core re-exports |
47
+ | `elements-kit/signals` | `signal`, `computed`, `effect`, `effectScope`, `batch`, `untracked`, `trigger`, `onCleanup`, `MaybeReactive`, `resolve`, `resolveProps`, `@reactive` |
48
+ | `elements-kit/render` | `render(target, setup)` mount a node with a scoped lifetime; returns `unmount` |
49
+ | `elements-kit/attributes` | `@attributes` decorator + `ATTRIBUTES` symbol |
50
+ | `elements-kit/slot` | `Slot`, `Slots`, `SLOTS` symbol — comment-marker DOM regions |
51
+ | `elements-kit/custom-elements` | `defineElement`, `CustomElementRegistry` |
52
+ | `elements-kit/for` | `For` keyed-list component |
53
+ | `elements-kit/jsx-runtime` | JSX factory + type helpers (`ElementProps`, `Props`, `ComponentProps`, `MaybeReactiveProps`, `ReactiveProps`, `Require`) — configure via `jsxImportSource` |
51
54
  | `elements-kit/integrations/react` | `useSignal`, `useScope` React bridge hooks |
52
55
  | `elements-kit/utilities/*` | Reactive browser-API utilities — see [src/utilities/README.md](src/utilities/README.md) |
53
56
 
@@ -166,7 +169,7 @@ JSX compiles directly to `document.createElement`. No virtual DOM, no diffing.
166
169
 
167
170
  ```tsx
168
171
  // This:
169
- const el = <button onClick={() => count(count() + 1)}>{count}</button>;
172
+ const el = <button on:click={() => count(count() + 1)}>{count}</button>;
170
173
 
171
174
  // Is equivalent to:
172
175
  const el = document.createElement("button");
@@ -190,8 +193,7 @@ const name = signal("Alice");
190
193
  | Syntax | Effect |
191
194
  |--------|--------|
192
195
  | `{signal}` / `{() => fn()}` | Live-bound reactive child |
193
- | `onClick={fn}` | Event listener (camelCase `onclick`) |
194
- | `on:click={fn}` | Explicit event namespace |
196
+ | `on:click={fn}` | Event listener (case-preserving event name) |
195
197
  | `class:active={bool}` | Reactive `classList.toggle` |
196
198
  | `style:color={value}` | Reactive inline style property |
197
199
  | `prop:foo={val}` | Force property assignment (skips `setAttribute`) |
@@ -204,6 +206,7 @@ Any class with a `render()` method returning an `Element` is a component. Compon
204
206
 
205
207
  ```tsx
206
208
  import { reactive, computed } from "elements-kit/signals";
209
+ import { render } from "elements-kit/render";
207
210
 
208
211
  class Counter {
209
212
  @reactive() count = 0;
@@ -213,13 +216,13 @@ class Counter {
213
216
  return (
214
217
  <section>
215
218
  <p>{() => this.count} × 2 = {this.doubled}</p>
216
- <button onClick={() => this.count++}>+1</button>
219
+ <button on:click={() => this.count++}>+1</button>
217
220
  </section>
218
221
  ) as Element;
219
222
  }
220
223
  }
221
224
 
222
- document.getElementById("app")!.appendChild(new Counter().render());
225
+ const unmount = render(document.getElementById("app")!, () => <Counter/>);
223
226
  ```
224
227
 
225
228
  ---
@@ -228,9 +231,10 @@ document.getElementById("app")!.appendChild(new Counter().render());
228
231
 
229
232
  ElementsKit enhances native `HTMLElement` subclasses — start with the platform, add only what you need.
230
233
 
231
- ```ts
234
+ ```tsx
232
235
  import { reactive, computed } from "elements-kit/signals";
233
236
  import { attributes, ATTRIBUTES as attr } from "elements-kit/attributes";
237
+ import { render } from "elements-kit/render";
234
238
 
235
239
  @attributes
236
240
  class CounterElement extends HTMLElement {
@@ -243,13 +247,20 @@ class CounterElement extends HTMLElement {
243
247
  @reactive() count = 0;
244
248
  doubled = computed(() => this.count * 2);
245
249
 
250
+ #unmount?: () => void;
251
+
246
252
  connectedCallback() {
247
- this.appendChild(
253
+ this.#unmount = render(this, () => (
248
254
  <section>
249
255
  <p>{() => this.count} × 2 = {this.doubled}</p>
250
- <button onClick={() => this.count++}>+1</button>
251
- </section> as Element,
252
- );
256
+ <button on:click={() => this.count++}>+1</button>
257
+ </section>
258
+ ));
259
+ }
260
+
261
+ disconnectedCallback() {
262
+ this.#unmount?.();
263
+ this.#unmount = undefined;
253
264
  }
254
265
  }
255
266
 
@@ -258,6 +269,26 @@ customElements.define("x-counter", CounterElement);
258
269
 
259
270
  `<x-counter count="5" />` — attribute bound, reactive, works in any HTML context.
260
271
 
272
+ ### Typed JSX for custom elements
273
+
274
+ Register the tag and augment the `CustomElementRegistry` interface — JSX infers the full prop shape (attributes, events, slots, children) from the class itself.
275
+
276
+ ```ts
277
+ import { defineElement } from "elements-kit/custom-elements";
278
+
279
+ defineElement("x-counter", CounterElement);
280
+
281
+ declare module "elements-kit/custom-elements" {
282
+ interface CustomElementRegistry {
283
+ "x-counter": typeof CounterElement;
284
+ }
285
+ }
286
+
287
+ // Now `<x-counter count={5} />` is fully typed — no hand-written `declare global` block.
288
+ ```
289
+
290
+ See [Types](docs/src/content/docs/elements/types.mdx) for the full set of prop-inference helpers.
291
+
261
292
  ---
262
293
 
263
294
  ## React Integration
@@ -408,7 +439,7 @@ effect(() => console.log(fetchTodo.state, fetchTodo.value));
408
439
 
409
440
  ## `For` — Keyed List Rendering
410
441
 
411
- Reconciles a reactive array into the DOM. Each item renders once per key — no full re-renders on reorder, add, or remove.
442
+ Reconciles a reactive array into the DOM. Each item renders once per key — no full re-renders on reorder, add, or remove. `T` is inferred from `each`.
412
443
 
413
444
  ```tsx
414
445
  import { For } from "elements-kit/for";
@@ -427,6 +458,34 @@ import { For } from "elements-kit/for";
427
458
 
428
459
  ---
429
460
 
461
+ ## Prop types
462
+
463
+ Six type helpers derive JSX prop shapes from your components — no parallel `declare global` block to maintain. Full guide at [docs/src/content/docs/elements/types.mdx](docs/src/content/docs/elements/types.mdx).
464
+
465
+ | Helper | For |
466
+ | ------ | --- |
467
+ | `ElementProps<typeof Cls>` | `HTMLElement` subclass — full surface (attrs, events, slots, children) |
468
+ | `Props<C>` | Class instance, constructor, or function component — unified |
469
+ | `ComponentProps<typeof Cls>` | Class components with `constructor(props: P)` |
470
+ | `MaybeReactiveProps<P>` | Caller-facing — wrap every prop in `MaybeReactive` (what parents pass) |
471
+ | `ReactiveProps<P>` | Component-facing — every prop becomes a `Computed<T>` getter (what function components receive) |
472
+ | `MaybeReactive<T>` | Scalar value-or-getter (from `elements-kit/signals`) |
473
+ | `Require<P, K>` | Promote optional keys to required |
474
+
475
+ The JSX runtime auto-wraps function-component props — each key arrives as a callable getter that subscribes on read. Pair the signature with `ReactiveProps<P>` and read `props.x()`:
476
+
477
+ ```tsx
478
+ import type { ReactiveProps } from "elements-kit/jsx-runtime";
479
+
480
+ function Greeting(props: ReactiveProps<{ name: string }>) {
481
+ return <p>Hello, {props.name}</p>;
482
+ }
483
+ ```
484
+
485
+ `resolveProps` stays exported for non-JSX call sites or nested prop bags.
486
+
487
+ ---
488
+
430
489
  ## `@reactive()` Decorator
431
490
 
432
491
  Makes any class field reactive — reads subscribe, writes trigger updates.
@@ -465,6 +524,26 @@ class MyElement extends HTMLElement {
465
524
  }
466
525
  ```
467
526
 
527
+ For typed slots, attach a `[SLOTS]` instance field — pass the key list with `as const` so TS can narrow:
528
+
529
+ ```ts
530
+ import { SLOTS, Slots } from "elements-kit/slot";
531
+
532
+ class Card extends HTMLElement {
533
+ [SLOTS] = Slots.new(["header", "footer"] as const);
534
+ }
535
+ // ElementProps<typeof Card> now includes `slot:header` / `slot:footer`
536
+ ```
537
+
538
+ For typed events, declare a `static events` map:
539
+
540
+ ```ts
541
+ class XPicker extends HTMLElement {
542
+ declare static events: { commit: CustomEvent<number> };
543
+ }
544
+ // ElementProps<typeof XPicker> now includes `on:commit`
545
+ ```
546
+
468
547
  ---
469
548
 
470
549
  ## Roadmap
@@ -473,4 +552,3 @@ class MyElement extends HTMLElement {
473
552
  - [ ] UI library — pre-built reactive components built on ElementsKit primitives
474
553
  - [ ] More framework integrations (Vue, Solid, Angular, …)
475
554
  - [ ] Tutorial — building a full app from scratch
476
- - [ ] Complete TypeScript strict-mode coverage
@@ -1,2 +1,2 @@
1
- import { a as Attributes, c as observedAttributes, i as AttributeTarget, n as AttrChangeHandler, o as attributes, r as AttributeDecorated, s as dispatchAttrChange, t as ATTRIBUTES } from "./attributes-Dtn68R1u.mjs";
1
+ import { a as Attributes, c as observedAttributes, i as AttributeTarget, n as AttrChangeHandler, o as attributes, r as AttributeDecorated, s as dispatchAttrChange, t as ATTRIBUTES } from "./attributes-aiRoArZz.mjs";
2
2
  export { ATTRIBUTES, AttrChangeHandler, AttributeDecorated, AttributeTarget, Attributes, attributes, dispatchAttrChange, observedAttributes };
@@ -1,11 +1,11 @@
1
- //#region src/define.d.ts
1
+ //#region src/custom-elements.d.ts
2
2
  /**
3
3
  * Registry of custom-element tags to their constructors.
4
4
  * Users augment this interface to add typed JSX support for their elements:
5
5
  *
6
6
  * @example
7
7
  * ```ts
8
- * declare module "elements-kit" {
8
+ * declare module "elements-kit/custom-elements" {
9
9
  * interface CustomElementRegistry {
10
10
  * "x-range": typeof XRange;
11
11
  * }
@@ -1,74 +1,2 @@
1
- import { n as defineElement, t as CustomElementRegistry } from "./define-CjbTZ3VG.mjs";
2
-
3
- //#region src/custom-elements.d.ts
4
- /**
5
- * Runs `setup` inside a fresh `effectScope` and returns both its result and
6
- * the scope's dispose handle.
7
- *
8
- * Use this wherever you need to run reactive code with an explicit lifetime
9
- * outside the JSX element flow — most commonly inside a custom element's
10
- * `connectedCallback`. `onCleanup`, nested `effect`s and any other
11
- * scope-bound registrations made in `setup` are owned by the returned
12
- * `dispose`.
13
- *
14
- * `untracked` detaches the new scope from any enclosing effect so it isn't
15
- * torn down when that effect re-runs — its lifetime is solely the caller's
16
- * responsibility.
17
- *
18
- * @example
19
- * ```ts
20
- * class Clock extends HTMLElement {
21
- * #dispose?: () => void;
22
- *
23
- * connectedCallback() {
24
- * const { dispose } = renderScope(() => {
25
- * const id = setInterval(() => (this.textContent = String(Date.now())), 1000);
26
- * onCleanup(() => clearInterval(id));
27
- * });
28
- * this.#dispose = dispose;
29
- * }
30
- *
31
- * disconnectedCallback() {
32
- * this.#dispose?.();
33
- * this.#dispose = undefined;
34
- * }
35
- * }
36
- * ```
37
- */
38
- declare function renderScope<T>(setup: () => T): {
39
- result: T;
40
- dispose: () => void;
41
- };
42
- /**
43
- * Runs `setup` inside an `effectScope` tied to `el`'s connected lifetime.
44
- *
45
- * Call from `connectedCallback`. Effects, `onCleanup` registrations, and
46
- * reactive reads inside `setup` belong to this scope. Pair with
47
- * {@link disconnectedScope} from `disconnectedCallback` to dispose.
48
- *
49
- * Safe to call more than once (e.g. if the element is reconnected after
50
- * disconnection): the previous scope is disposed first.
51
- *
52
- * @example
53
- * ```ts
54
- * class Clock extends HTMLElement {
55
- * connectedCallback() {
56
- * connectedScope(this, () => {
57
- * const id = setInterval(() => this.textContent = String(Date.now()), 1000);
58
- * onCleanup(() => clearInterval(id));
59
- * });
60
- * }
61
- * disconnectedCallback() {
62
- * disconnectedScope(this);
63
- * }
64
- * }
65
- * ```
66
- */
67
- declare function connectedScope(el: HTMLElement, setup: () => void): void;
68
- /**
69
- * Disposes the scope previously created by {@link connectedScope} for `el`.
70
- * No-op if there is no active scope.
71
- */
72
- declare function disconnectedScope(el: HTMLElement): void;
73
- //#endregion
74
- export { type CustomElementRegistry, connectedScope, defineElement, disconnectedScope, renderScope };
1
+ import { n as defineElement, t as CustomElementRegistry } from "./custom-elements-bVYOkHKt.mjs";
2
+ export { CustomElementRegistry, defineElement };
@@ -1,5 +1,4 @@
1
- import { b as untracked, f as effectScope } from "./signals-J8dK_rA4.mjs";
2
- //#region src/define.ts
1
+ //#region src/custom-elements.ts
3
2
  /**
4
3
  * Register a custom element with the browser and return its class.
5
4
  * Pair with a module augmentation of `CustomElementRegistry` to get typed JSX.
@@ -9,92 +8,4 @@ function defineElement(tag, cls, options) {
9
8
  return cls;
10
9
  }
11
10
  //#endregion
12
- //#region src/custom-elements.ts
13
- /**
14
- * Runs `setup` inside a fresh `effectScope` and returns both its result and
15
- * the scope's dispose handle.
16
- *
17
- * Use this wherever you need to run reactive code with an explicit lifetime
18
- * outside the JSX element flow — most commonly inside a custom element's
19
- * `connectedCallback`. `onCleanup`, nested `effect`s and any other
20
- * scope-bound registrations made in `setup` are owned by the returned
21
- * `dispose`.
22
- *
23
- * `untracked` detaches the new scope from any enclosing effect so it isn't
24
- * torn down when that effect re-runs — its lifetime is solely the caller's
25
- * responsibility.
26
- *
27
- * @example
28
- * ```ts
29
- * class Clock extends HTMLElement {
30
- * #dispose?: () => void;
31
- *
32
- * connectedCallback() {
33
- * const { dispose } = renderScope(() => {
34
- * const id = setInterval(() => (this.textContent = String(Date.now())), 1000);
35
- * onCleanup(() => clearInterval(id));
36
- * });
37
- * this.#dispose = dispose;
38
- * }
39
- *
40
- * disconnectedCallback() {
41
- * this.#dispose?.();
42
- * this.#dispose = undefined;
43
- * }
44
- * }
45
- * ```
46
- */
47
- function renderScope(setup) {
48
- let result;
49
- let dispose;
50
- untracked(() => {
51
- dispose = effectScope(() => {
52
- result = setup();
53
- });
54
- });
55
- return {
56
- result,
57
- dispose
58
- };
59
- }
60
- const scopes = /* @__PURE__ */ new WeakMap();
61
- /**
62
- * Runs `setup` inside an `effectScope` tied to `el`'s connected lifetime.
63
- *
64
- * Call from `connectedCallback`. Effects, `onCleanup` registrations, and
65
- * reactive reads inside `setup` belong to this scope. Pair with
66
- * {@link disconnectedScope} from `disconnectedCallback` to dispose.
67
- *
68
- * Safe to call more than once (e.g. if the element is reconnected after
69
- * disconnection): the previous scope is disposed first.
70
- *
71
- * @example
72
- * ```ts
73
- * class Clock extends HTMLElement {
74
- * connectedCallback() {
75
- * connectedScope(this, () => {
76
- * const id = setInterval(() => this.textContent = String(Date.now()), 1000);
77
- * onCleanup(() => clearInterval(id));
78
- * });
79
- * }
80
- * disconnectedCallback() {
81
- * disconnectedScope(this);
82
- * }
83
- * }
84
- * ```
85
- */
86
- function connectedScope(el, setup) {
87
- scopes.get(el)?.();
88
- const { dispose } = renderScope(setup);
89
- scopes.set(el, dispose);
90
- }
91
- /**
92
- * Disposes the scope previously created by {@link connectedScope} for `el`.
93
- * No-op if there is no active scope.
94
- */
95
- function disconnectedScope(el) {
96
- scopes.get(el)?.();
97
- scopes.delete(el);
98
- }
99
- //#endregion
100
- export { connectedScope, defineElement, disconnectedScope, renderScope };
11
+ export { defineElement };
@@ -1,5 +1,6 @@
1
- import { _ as onCleanup, b as untracked, d as effect, f as effectScope, t as isReactive } from "./signals-J8dK_rA4.mjs";
1
+ import { c as effectScope, g as untracked, p as onCleanup, s as effect } from "./lib-D6duEs38.mjs";
2
2
  import "./polyfill-B1lNNcum.mjs";
3
+ import { isReactive, resolveProps } from "./signals/index.mjs";
3
4
  import { on } from "./utilities/event-listener.mjs";
4
5
  import { i as resolveNode$1, n as Slot, r as Slots, t as SLOTS } from "./slot-Kb61AcgW.mjs";
5
6
  //#region \0rolldown/runtime.js
@@ -85,23 +86,34 @@ function applySlot(slot, value) {
85
86
  });
86
87
  }
87
88
  function mountChildren(el, value) {
88
- for (const child of ensureFlatArray(value)) {
89
- if (typeof child === "function") {
90
- const slot = Slot.new();
91
- el.appendChild(slot());
92
- effectScope(() => {
93
- effect(() => slot.set(resolveChild(child())));
94
- onCleanup(() => slot.clear());
95
- });
96
- continue;
97
- }
98
- const node = resolveChild(child);
99
- const dispose = node[Symbol.dispose];
100
- el.appendChild(node);
101
- if (dispose) effectScope(() => {
102
- onCleanup(dispose);
89
+ for (const child of ensureFlatArray(value)) mountChild(el, child);
90
+ }
91
+ /**
92
+ * Mounts a single child into `el`. Reactive functions become live slots; other
93
+ * values append as-is. Each child owns its own `effectScope` so sibling
94
+ * `onCleanup` registrations don't overwrite each other (the signals lib
95
+ * supports only one onCleanup per subscriber).
96
+ *
97
+ * Also used by `createFunctionElement` when a component returns a reactive
98
+ * getter or primitive — keeps the component's `effectScope` alive for the
99
+ * lifetime of the fragment it mounts into.
100
+ */
101
+ function mountChild(el, child) {
102
+ if (typeof child === "function") {
103
+ const slot = Slot.new();
104
+ el.appendChild(slot());
105
+ effectScope(() => {
106
+ effect(() => slot.set(resolveChild(child())));
107
+ onCleanup(() => slot.clear());
103
108
  });
109
+ return;
104
110
  }
111
+ const node = resolveChild(child);
112
+ const dispose = node[Symbol.dispose];
113
+ el.appendChild(node);
114
+ if (dispose) effectScope(() => {
115
+ onCleanup(dispose);
116
+ });
105
117
  }
106
118
  function resolveChild(value) {
107
119
  if (Array.isArray(value)) {
@@ -209,10 +221,10 @@ function setAttribute(el, key, value) {
209
221
  else el.setAttribute(key, value === true ? "" : String(value));
210
222
  }
211
223
  function isEventKey(key) {
212
- return key.startsWith("on:") || key.length > 2 && key.startsWith("on") && key[2] >= "A" && key[2] <= "Z";
224
+ return key.startsWith("on:");
213
225
  }
214
226
  function eventName(key) {
215
- return key.startsWith("on:") ? key.slice(3) : key[2].toLowerCase() + key.slice(3);
227
+ return key.slice(3);
216
228
  }
217
229
  //#endregion
218
230
  //#region src/jsx-runtime/element.ts
@@ -229,7 +241,7 @@ function createFunctionElement(type, props, ref) {
229
241
  let dispose;
230
242
  untracked(() => {
231
243
  dispose = effectScope(() => {
232
- el = type(props);
244
+ el = type(resolveProps(props));
233
245
  if (typeof ref === "function" && el instanceof Element) ref(el);
234
246
  });
235
247
  });
@@ -280,4 +292,4 @@ function attachDisposables(el, disposables) {
280
292
  });
281
293
  }
282
294
  //#endregion
283
- export { disposeElement as n, createElement as t };
295
+ export { disposeElement as n, mountChild as r, createElement as t };
package/dist/for.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Props, o as Require } from "./infer-BfzRJoCn.mjs";
1
+ import { i as Props, s as Require } from "./infer-Dv5Wk-7E.mjs";
2
2
 
3
3
  //#region src/for.d.ts
4
4
  type KeyFn<T> = (item: T, index: number) => string | number;
package/dist/for.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { n as disposeElement } from "./element-CGVy_8TW.mjs";
2
- import { _ as onCleanup, b as untracked, d as effect, f as effectScope, v as signal, y as trigger } from "./signals-J8dK_rA4.mjs";
1
+ import { n as disposeElement } from "./element-DxmInKJw.mjs";
2
+ import { c as effectScope, g as untracked, h as trigger, m as signal, p as onCleanup, s as effect } from "./lib-D6duEs38.mjs";
3
+ import "./signals/index.mjs";
3
4
  //#region src/for.ts
4
5
  var For = class {
5
6
  constructor(_props) {}