elements-kit 0.0.3 → 0.0.6

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.
@@ -58,7 +58,11 @@ type Attributes<T> = Record<string, AttrChangeHandler<T>>;
58
58
  * @param cls The custom element class constructor
59
59
  * @returns Array of unique attribute names to observe
60
60
  */
61
- declare function observedAttributes(cls: any): string[];
61
+ declare function observedAttributes(cls: {
62
+ [ATTRIBUTES]?: Record<string, unknown>;
63
+ observedAttributes?: string[];
64
+ prototype: unknown;
65
+ }): string[];
62
66
  /**
63
67
  * A class decorator that automatically wires up `observedAttributes` and `attributeChangedCallback`
64
68
  * from a static `[ATTRIBUTES]` map.
@@ -1,4 +1,4 @@
1
- import { c as ReactiveElementOf } from "../index-DJejH8Ff.mjs";
1
+ import { c as ReactiveElementOf } from "../index-Ukqj0EcT.mjs";
2
2
 
3
3
  //#region src/builder/dom.d.ts
4
4
  interface Lifecycle {
@@ -1,2 +1,2 @@
1
- import { a as EFFECT, c as ReactiveElementOf, d as builder, f as toNode, i as DISPOSE, l as VALUE, n as Chain, o as ElementBuilder, r as DISPOSABLES, s as ReactiveElement, t as Builder, u as ValueOrReactive } from "../index-DJejH8Ff.mjs";
1
+ import { a as EFFECT, c as ReactiveElementOf, d as builder, f as toNode, i as DISPOSE, l as VALUE, n as Chain, o as ElementBuilder, r as DISPOSABLES, s as ReactiveElement, t as Builder, u as ValueOrReactive } from "../index-Ukqj0EcT.mjs";
2
2
  export { Builder, Chain, DISPOSABLES, DISPOSE, EFFECT, ElementBuilder, ReactiveElement, ReactiveElementOf, VALUE, ValueOrReactive, builder, toNode };
@@ -1,6 +1,7 @@
1
- import { a as effect, t as isReactive } from "../signals-Cr7xgAJH.mjs";
1
+ import { a as effect, t as isReactive } from "../signals-CLAPw8kk.mjs";
2
+ import "../polyfill-B1lNNcum.mjs";
2
3
  import { Slot } from "../slot.mjs";
3
- import { t as resolveNode } from "../lib-B2drrxlV.mjs";
4
+ import { t as resolveNode } from "../lib-DNd01_aS.mjs";
4
5
  //#region src/builder/index.ts
5
6
  const DISPOSABLES = Symbol("disposables");
6
7
  const DISPOSE = Symbol.dispose;
@@ -76,13 +77,14 @@ var ChainContext = class {
76
77
  this.key = key;
77
78
  }
78
79
  setter(value) {
80
+ const chain = this.chain;
79
81
  if (isReactive(value)) {
80
82
  this.builder[DISPOSABLES].add(effect(() => {
81
- this.chain[this.key] = value();
83
+ chain[this.key] = value();
82
84
  }));
83
85
  return this.builder;
84
86
  }
85
- this.chain[this.key] = value;
87
+ chain[this.key] = value;
86
88
  return this.builder;
87
89
  }
88
90
  };
@@ -91,7 +93,7 @@ function setterOrValue(builder, chainParent, key) {
91
93
  const context = new ChainContext(builder, chainParent, key);
92
94
  return new Proxy(context.setter.bind(context), {
93
95
  apply(target, _thisArg, argArray) {
94
- return target.apply(builder, argArray);
96
+ return target(argArray[0]);
95
97
  },
96
98
  get(_, subkey) {
97
99
  if (isObject(chain)) return setterOrValue(builder, chain, subkey);
@@ -1,6 +1,7 @@
1
- import { a as effect, t as isReactive } from "./signals-Cr7xgAJH.mjs";
1
+ import { a as effect, d as onCleanup, m as untracked, o as effectScope, t as isReactive } from "./signals-CLAPw8kk.mjs";
2
+ import "./polyfill-B1lNNcum.mjs";
2
3
  import { $slots, Slot, Slots } from "./slot.mjs";
3
- import { t as resolveNode } from "./lib-B2drrxlV.mjs";
4
+ import { t as resolveNode$1 } from "./lib-DNd01_aS.mjs";
4
5
  //#region \0rolldown/runtime.js
5
6
  var __defProp = Object.defineProperty;
6
7
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -53,35 +54,54 @@ function isChildrenProperty(node, key) {
53
54
  function applyChildren(node, key, value) {
54
55
  if (hasSlots(node)) {
55
56
  const slotName = key.replace(/^slot:/, "");
56
- if (Slots.has(node[$slots], slotName)) return applySlot(node[$slots][slotName], value);
57
+ if (Slots.has(node[$slots], slotName)) {
58
+ applySlot(node[$slots][slotName], value);
59
+ return;
60
+ }
61
+ }
62
+ if (key === "children" && (node instanceof Element || node instanceof DocumentFragment)) {
63
+ mountChildren(node, value);
64
+ return;
57
65
  }
58
- if (key === "children" && (node instanceof Element || node instanceof DocumentFragment)) return mountChildren(node, value);
59
66
  if (key in node) {
60
67
  const slot = node[key];
61
68
  if (!(slot instanceof Slot)) return;
62
- return applySlot(slot, value);
69
+ applySlot(slot, value);
63
70
  }
64
71
  }
65
- /**
66
- * Sets a Slot's content from a Child value.
67
- */
68
72
  function applySlot(slot, value) {
69
- if (typeof value === "function") return effect(() => slot.set(resolveChild(value())));
70
- slot.set(resolveChild(value));
73
+ effectScope(() => {
74
+ let dispose;
75
+ if (typeof value === "function") effect(() => slot.set(resolveChild(value())));
76
+ else {
77
+ const node = resolveChild(value);
78
+ dispose = node[Symbol.dispose];
79
+ slot.set(node);
80
+ }
81
+ onCleanup(() => {
82
+ dispose?.();
83
+ slot.clear();
84
+ });
85
+ });
71
86
  }
72
87
  function mountChildren(el, value) {
73
- const children = ensureFlatArray(value);
74
- const disposers = [];
75
- for (const child of children) {
88
+ for (const child of ensureFlatArray(value)) {
76
89
  if (typeof child === "function") {
77
90
  const slot = Slot.new();
78
91
  el.appendChild(slot());
79
- disposers.push(effect(() => slot.set(resolveChild(child()))));
92
+ effectScope(() => {
93
+ effect(() => slot.set(resolveChild(child())));
94
+ onCleanup(() => slot.clear());
95
+ });
80
96
  continue;
81
97
  }
82
- el.appendChild(resolveChild(child));
98
+ const node = resolveChild(child);
99
+ const dispose = node[Symbol.dispose];
100
+ el.appendChild(node);
101
+ if (dispose) effectScope(() => {
102
+ onCleanup(dispose);
103
+ });
83
104
  }
84
- return disposers.length > 0 ? () => disposers.forEach((d) => d()) : void 0;
85
105
  }
86
106
  function resolveChild(value) {
87
107
  if (Array.isArray(value)) {
@@ -90,7 +110,7 @@ function resolveChild(value) {
90
110
  return fragment;
91
111
  }
92
112
  if (typeof value === "function") return resolveChild(value());
93
- return resolveNode(value);
113
+ return resolveNode$1(value);
94
114
  }
95
115
  /** Normalises the children prop into a flat array. */
96
116
  function ensureFlatArray(raw) {
@@ -99,36 +119,27 @@ function ensureFlatArray(raw) {
99
119
  //#endregion
100
120
  //#region src/jsx-runtime/properties.ts
101
121
  function applyProps(node, props) {
102
- const disposables = /* @__PURE__ */ new Set();
103
122
  for (const [key, value] of Object.entries(props)) {
104
123
  if (isChildrenProperty(node, key)) {
105
- const disposable = applyChildren(node, key, value);
106
- if (disposable) disposables.add(disposable);
124
+ applyChildren(node, key, value);
107
125
  continue;
108
126
  }
109
127
  if (isReactive(value)) {
110
128
  if (isEventKey(key)) {
111
- let cleanup;
112
- const dispose = effect(() => {
113
- if (cleanup) cleanup();
114
- cleanup = setEvent(node, key, value());
115
- });
116
- disposables.add(() => {
117
- dispose();
118
- if (cleanup) cleanup();
129
+ effect(() => {
130
+ onCleanup(setEvent(node, key, value()));
119
131
  });
120
132
  continue;
121
133
  }
122
- disposables.add(effect(() => setProp(node, key, value())));
134
+ effect(() => setProp(node, key, value()));
123
135
  continue;
124
136
  }
125
137
  if (isEventKey(key)) {
126
- disposables.add(setEvent(node, key, value));
138
+ onCleanup(setEvent(node, key, value));
127
139
  continue;
128
140
  }
129
141
  setProp(node, key, value);
130
142
  }
131
- return disposables;
132
143
  }
133
144
  function setProp(node, key, value) {
134
145
  const colonIdx = key.indexOf(":");
@@ -210,36 +221,57 @@ function setEvent(el, key, handler) {
210
221
  const $ref = Symbol("ref");
211
222
  //#endregion
212
223
  //#region src/jsx-runtime/element.ts
213
- function createElement(type, { [$ref]: ref, ...props } = {}) {
214
- if (typeof type === "function" && !type.prototype?.render) {
215
- const el = type(props);
216
- if (typeof ref === "function" && el instanceof Element) ref(el);
217
- return el;
218
- }
219
- const node = resolveElement(type);
220
- if (!node) return null;
221
- const disposables = applyProps(node, props);
222
- if (disposables.size > 0) attachDisposables(node, disposables);
223
- const el = _render(node);
224
- if (typeof ref === "function" && el instanceof Element) ref(el);
225
- return el;
224
+ function createElement(type, rawProps = {}) {
225
+ const ref = rawProps[$ref];
226
+ const props = Object.fromEntries(Object.entries(rawProps));
227
+ if (typeof type === "function" && !type.prototype?.render) return createFunctionElement(type, props, ref);
228
+ return createNodeElement(type, props, ref);
226
229
  }
227
- function _render(node) {
228
- if (node instanceof Element || node instanceof DocumentFragment) return node;
229
- if (!node || typeof node.render !== "function") return null;
230
- return _render(node.render());
230
+ /** Runs all cleanup functions registered by JSX props/effects on `el`. */
231
+ function disposeElement(el) {
232
+ el[Symbol.dispose]?.();
233
+ }
234
+ function createFunctionElement(type, props, ref) {
235
+ let el;
236
+ let dispose;
237
+ untracked(() => {
238
+ dispose = effectScope(() => {
239
+ el = type(props);
240
+ if (typeof ref === "function" && el instanceof Element) ref(el);
241
+ });
242
+ });
243
+ const result = el;
244
+ if (result instanceof Element || result instanceof DocumentFragment) attachDisposables(result, new Set([dispose]));
245
+ else dispose();
246
+ return result;
247
+ }
248
+ function createNodeElement(type, props, ref) {
249
+ const node = resolveNode(type);
250
+ if (!node) return null;
251
+ let el;
252
+ let dispose;
253
+ untracked(() => {
254
+ dispose = effectScope(() => {
255
+ applyProps(node, props);
256
+ el = renderNode(node);
257
+ if (typeof ref === "function" && el instanceof Element) ref(el);
258
+ });
259
+ });
260
+ const result = el;
261
+ if (result instanceof Element || result instanceof DocumentFragment) attachDisposables(result, new Set([dispose]));
262
+ else dispose();
263
+ return result;
231
264
  }
232
- /**
233
- * Resolves the `type` argument of createElement into a concrete DOM node:
234
- * - string → document.createElement(type)
235
- * - Element → the element itself (apply props to an existing node)
236
- * - class component → new type()
237
- */
238
- function resolveElement(type) {
265
+ function resolveNode(type) {
239
266
  if (typeof type === "string") return document.createElement(type);
240
267
  if (type instanceof Element || type instanceof DocumentFragment) return type;
241
268
  return new type();
242
269
  }
270
+ function renderNode(node) {
271
+ if (node instanceof Element || node instanceof DocumentFragment) return node;
272
+ if (!node || typeof node.render !== "function") return null;
273
+ return renderNode(node.render());
274
+ }
243
275
  function hasOwnDisposable(el) {
244
276
  return Object.hasOwn(el, Symbol.dispose);
245
277
  }
@@ -254,9 +286,5 @@ function attachDisposables(el, disposables) {
254
286
  configurable: true
255
287
  });
256
288
  }
257
- /** Runs all cleanup functions registered by JSX props/effects on `el`. */
258
- function disposeElement(el) {
259
- el[Symbol.dispose]?.();
260
- }
261
289
  //#endregion
262
290
  export { disposeElement as n, createElement as t };
@@ -1,4 +1,4 @@
1
- import { u as ValueOrReactive } from "./index-DJejH8Ff.mjs";
1
+ import { u as ValueOrReactive } from "./index-Ukqj0EcT.mjs";
2
2
 
3
3
  //#region src/signals/lib.d.ts
4
4
  /**
@@ -42,14 +42,8 @@ declare function isEffectScope(fn: () => void): boolean;
42
42
  * count(); // → 1
43
43
  * ```
44
44
  */
45
- declare function signal<T>(): {
46
- (): T | undefined;
47
- (value: T | undefined): void;
48
- };
49
- declare function signal<T>(initialValue: T): {
50
- (): T;
51
- (value: T): void;
52
- };
45
+ declare function signal<T>(): Updater<T> & Computed<T>;
46
+ declare function signal<T>(initialValue: T): Updater<T> & Computed<T>;
53
47
  /**
54
48
  * Creates a lazily-evaluated computed value.
55
49
  *
@@ -201,11 +195,11 @@ declare function batch(fn: () => void): void;
201
195
  * const logCount = effect(() => {
202
196
  * console.log('triggered by a:', a());
203
197
  * // read b without subscribing – effect won't re-run when b changes
204
- * console.log('current b:', untracked(() => b()));
198
+ * console.log('current b:', untracked(b));
205
199
  * });
206
200
  * ```
207
201
  */
208
- declare function untracked<T>(fn: () => T): T;
202
+ declare function untracked<T>(fn: Computed<T>): T;
209
203
  /**
210
204
  * Manually triggers all subscribers of every signal read inside `fn`.
211
205
  *
@@ -220,10 +214,10 @@ declare function untracked<T>(fn: () => T): T;
220
214
  *
221
215
  * // Mutate in place (referential equality won't detect the change):
222
216
  * items().push(4);
223
- * trigger(() => items()); // manually notify subscribers
217
+ * trigger(items); // manually notify subscribers
224
218
  * ```
225
219
  */
226
- declare function trigger(fn: () => void): void;
220
+ declare function trigger<T = void>(fn: Computed<T>): void;
227
221
  //#endregion
228
222
  //#region src/signals/index.d.ts
229
223
  declare function isReactive<T>(value: ValueOrReactive<T>): value is () => T;
@@ -1,4 +1,4 @@
1
- import { t as PrimitiveNodeType } from "./polyfill-BEL-HWkO.mjs";
1
+ import { t as PrimitiveNodeType } from "./polyfill-BW_B2r6i.mjs";
2
2
 
3
3
  //#region src/builder/index.d.ts
4
4
  declare const DISPOSABLES: unique symbol;
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { n as disposeElement } from "./element-CCHXkEsj.mjs";
2
- import { a as effect, f as signal, m as untracked } from "./signals-Cr7xgAJH.mjs";
1
+ import { n as disposeElement } from "./element-01J9cXGm.mjs";
2
+ import { a as effect, d as onCleanup, f as signal, m as untracked, p as trigger } from "./signals-CLAPw8kk.mjs";
3
3
  //#region src/components/for.ts
4
4
  /**
5
5
  * Keyed list renderer. Reconciles a reactive array into the DOM using a key
@@ -30,6 +30,10 @@ var For = class {
30
30
  return this.#each();
31
31
  }
32
32
  set each(v) {
33
+ if (v === untracked(this.#each)) {
34
+ trigger(this.#each);
35
+ return;
36
+ }
33
37
  this.#each(v);
34
38
  }
35
39
  by = (_, i) => i;
@@ -44,6 +48,11 @@ var For = class {
44
48
  fragment.appendChild(this.#start);
45
49
  fragment.appendChild(this.#end);
46
50
  effect(() => this.#reconcile());
51
+ onCleanup(() => {
52
+ for (const entry of this.#cache.values()) cleanEntry(entry);
53
+ this.#cache.clear();
54
+ this.#order = [];
55
+ });
47
56
  return fragment;
48
57
  }
49
58
  #reconcile() {
@@ -105,6 +114,14 @@ function insertEntry(parent, entry, before, rendered) {
105
114
  if (rendered) parent.insertBefore(rendered, before);
106
115
  parent.insertBefore(entry.end, before);
107
116
  }
117
+ function cleanEntry(entry) {
118
+ let node = entry.start.nextSibling;
119
+ while (node && node !== entry.end) {
120
+ const next = node.nextSibling;
121
+ if (node instanceof Element) disposeElement(node);
122
+ node = next;
123
+ }
124
+ }
108
125
  function removeEntry(entry) {
109
126
  let node = entry.start.nextSibling;
110
127
  while (node && node !== entry.end) {
@@ -1,4 +1,4 @@
1
- import { t as PrimitiveNodeType } from "../polyfill-BEL-HWkO.mjs";
1
+ import { t as PrimitiveNodeType } from "../polyfill-BW_B2r6i.mjs";
2
2
  import { JSX as JSX$1 } from "dom-expressions/src/jsx-h";
3
3
 
4
4
  //#region src/jsx-runtime/types.d.ts
@@ -8,19 +8,29 @@ interface ComponentInstance {
8
8
  }
9
9
  /** A class whose constructor returns a ComponentInstance. */
10
10
  type ComponentClass = new (...args: any[]) => ComponentInstance;
11
+ type ComponentFn = (props: Record<string | symbol, unknown>) => null | Element | DocumentFragment;
11
12
  /** Anything that can appear as a JSX child. */
12
13
  type Child = PrimitiveNodeType | AnyFn | Child[];
13
14
  /** A function that renders props into an element or fragment. */
14
15
  type AnyFn = (...args: any[]) => any;
15
16
  //#endregion
17
+ //#region src/jsx-runtime/element.d.ts
18
+ declare function createElement(type: string | Element | DocumentFragment | ComponentClass | ComponentFn, rawProps?: Record<string | symbol, unknown>): Element | DocumentFragment | null;
19
+ //#endregion
16
20
  //#region src/jsx-runtime/ref.d.ts
17
21
  declare const $ref: unique symbol;
18
22
  //#endregion
19
- //#region src/jsx-runtime/element.d.ts
20
- declare function createElement(type: string | Element | DocumentFragment | ComponentClass | ((props: Record<string | symbol, unknown>) => null | Element | DocumentFragment), {
21
- [$ref]: ref,
22
- ...props
23
- }?: Record<string | symbol, unknown>): Element | DocumentFragment | null;
23
+ //#region src/components/fragment.d.ts
24
+ /**
25
+ * Used by the JSX transform for `<>...</>` fragments.
26
+ *
27
+ * createElement wraps this in effectScope + attachDisposables, so children's
28
+ * Symbol.dispose functions are collected via onCleanup and fired when the
29
+ * fragment's own dispose is called.
30
+ */
31
+ declare function Fragment(props: {
32
+ children?: unknown;
33
+ }): DocumentFragment;
24
34
  //#endregion
25
35
  //#region src/jsx-runtime/index.d.ts
26
36
  /** A value or a reactive zero-argument getter. */
@@ -67,4 +77,4 @@ declare namespace JSX {
67
77
  };
68
78
  }
69
79
  //#endregion
70
- export { Attrs, FunctionMaybe, JSX, SlotProps, createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
80
+ export { Attrs, Fragment, FunctionMaybe, JSX, SlotProps, createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -1,2 +1,27 @@
1
- import { t as createElement } from "../element-CCHXkEsj.mjs";
2
- export { createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
1
+ import { t as createElement } from "../element-01J9cXGm.mjs";
2
+ import { d as onCleanup } from "../signals-CLAPw8kk.mjs";
3
+ //#region src/components/fragment.ts
4
+ /**
5
+ * Used by the JSX transform for `<>...</>` fragments.
6
+ *
7
+ * createElement wraps this in effectScope + attachDisposables, so children's
8
+ * Symbol.dispose functions are collected via onCleanup and fired when the
9
+ * fragment's own dispose is called.
10
+ */
11
+ function Fragment(props) {
12
+ const fragment = document.createDocumentFragment();
13
+ const raw = props.children;
14
+ if (raw == null) return fragment;
15
+ const nodes = Array.isArray(raw) ? raw.flat(Infinity) : [raw];
16
+ const disposes = [];
17
+ for (const child of nodes) {
18
+ if (!(child instanceof Node)) continue;
19
+ const dispose = child[Symbol.dispose];
20
+ if (dispose) disposes.push(dispose);
21
+ fragment.appendChild(child);
22
+ }
23
+ if (disposes.length) onCleanup(() => disposes.forEach((fn) => fn()));
24
+ return fragment;
25
+ }
26
+ //#endregion
27
+ export { Fragment, createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -0,0 +1,4 @@
1
+ //#region src/polyfill.ts
2
+ if (!Symbol.dispose) Object.defineProperty(Symbol, "dispose", { value: Symbol("dispose") });
3
+ //#endregion
4
+ export {};
@@ -1,2 +1,2 @@
1
- import { _ as untracked, a as reactive, c as effect, d as isEffect, f as isEffectScope, g as trigger, h as signal, i as isReactive, l as effectScope, m as onCleanup, n as Signal, o as batch, p as isSignal, r as Updater, s as computed, t as Computed, u as isComputed } from "../index-C6xwOPCO.mjs";
1
+ import { _ as untracked, a as reactive, c as effect, d as isEffect, f as isEffectScope, g as trigger, h as signal, i as isReactive, l as effectScope, m as onCleanup, n as Signal, o as batch, p as isSignal, r as Updater, s as computed, t as Computed, u as isComputed } from "../index-BGKVkZ6y.mjs";
2
2
  export { Computed, Signal, Updater, batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, signal, trigger, untracked };
@@ -1,2 +1,2 @@
1
- import { a as effect, c as isEffect, d as onCleanup, f as signal, i as computed, l as isEffectScope, m as untracked, n as reactive, o as effectScope, p as trigger, r as batch, s as isComputed, t as isReactive, u as isSignal } from "../signals-Cr7xgAJH.mjs";
1
+ import { a as effect, c as isEffect, d as onCleanup, f as signal, i as computed, l as isEffectScope, m as untracked, n as reactive, o as effectScope, p as trigger, r as batch, s as isComputed, t as isReactive, u as isSignal } from "../signals-CLAPw8kk.mjs";
2
2
  export { batch, computed, effect, effectScope, isComputed, isEffect, isEffectScope, isReactive, isSignal, onCleanup, reactive, signal, trigger, untracked };
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../../index-C6xwOPCO.mjs";
1
+ import { t as Computed } from "../../index-BGKVkZ6y.mjs";
2
2
 
3
3
  //#region src/signals/lib/media.d.ts
4
4
  declare const isBrowser: boolean;
@@ -1,4 +1,4 @@
1
- import { d as onCleanup, f as signal } from "../../signals-Cr7xgAJH.mjs";
1
+ import { d as onCleanup, f as signal } from "../../signals-CLAPw8kk.mjs";
2
2
  //#region src/signals/lib/media.ts
3
3
  const isBrowser = typeof window !== "undefined";
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { t as Computed } from "../../index-C6xwOPCO.mjs";
1
+ import { t as Computed } from "../../index-BGKVkZ6y.mjs";
2
2
 
3
3
  //#region src/signals/lib/react.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { a as effect, f as signal, o as effectScope } from "../../signals-Cr7xgAJH.mjs";
1
+ import { a as effect, f as signal, o as effectScope } from "../../signals-CLAPw8kk.mjs";
2
2
  import { useEffect, useMemo, useRef, useSyncExternalStore } from "react";
3
3
  //#region src/signals/lib/react.ts
4
4
  /**
@@ -1,3 +1,4 @@
1
+ import "./polyfill-B1lNNcum.mjs";
1
2
  //#region src/signals/system.ts
2
3
  /**
3
4
  * Bitmask flags that encode the current state of a {@link ReactiveNode}.
@@ -275,40 +276,6 @@ function createReactiveSystem({ update, notify, unwatched }) {
275
276
  }
276
277
  //#endregion
277
278
  //#region src/signals/lib.ts
278
- /**
279
- * @module signals
280
- *
281
- * High-level reactive primitives built on top of the low-level graph engine in
282
- * `./system`.
283
- *
284
- * The API surface intentionally mirrors alien-signals but extends it with
285
- * first-class **cleanup support** via {@link onCleanup}.
286
- *
287
- * ### Primitives
288
- * | Export | Role |
289
- * |--------|------|
290
- * | {@link signal} | Mutable reactive value. |
291
- * | {@link computed} | Derived, lazily-evaluated value. |
292
- * | {@link effect} | Side-effect that re-runs when its deps change. |
293
- * | {@link effectScope} | Ownership scope that groups and disposes nested effects together. |
294
- * | {@link onCleanup} | Register a teardown callback inside the currently running effect. |
295
- * | {@link batch} | Defer flush until all synchronous mutations are done. |
296
- * | {@link untracked} | Read signals without creating dependency links. |
297
- * | {@link trigger} | Manually re-trigger subscribers of signals read inside `fn`. |
298
- *
299
- * ### Cleanup model
300
- * `onCleanup(fn)` registers a callback that fires:
301
- * 1. **Before each re-run** – so resources set up in the previous run are torn
302
- * down before the effect body executes again.
303
- * 2. **On disposal** – whether the effect is stopped explicitly (calling the
304
- * handle returned by `effect()`) or implicitly (an owning `effectScope` is
305
- * disposed, cascading through all nested effects).
306
- *
307
- * Because `onCleanup` reads `activeSub` (the same module-level variable that
308
- * signals use for dependency tracking), it works correctly when called from
309
- * deeply nested helper functions during effect execution – no prop-drilling
310
- * required.
311
- */
312
279
  /** Monotonically increasing counter; incremented on each tracking run to stamp links. */
313
280
  let cycle = 0;
314
281
  /** Depth counter for nested `batch` calls; flush is deferred while > 0. */
@@ -634,7 +601,7 @@ function batch(fn) {
634
601
  * const logCount = effect(() => {
635
602
  * console.log('triggered by a:', a());
636
603
  * // read b without subscribing – effect won't re-run when b changes
637
- * console.log('current b:', untracked(() => b()));
604
+ * console.log('current b:', untracked(b));
638
605
  * });
639
606
  * ```
640
607
  */
@@ -660,33 +627,35 @@ function untracked(fn) {
660
627
  *
661
628
  * // Mutate in place (referential equality won't detect the change):
662
629
  * items().push(4);
663
- * trigger(() => items()); // manually notify subscribers
630
+ * trigger(items); // manually notify subscribers
664
631
  * ```
665
632
  */
666
633
  function trigger(fn) {
667
- const sub = {
668
- deps: void 0,
669
- depsTail: void 0,
670
- flags: ReactiveFlags.Watching
671
- };
672
- const prevSub = setActiveSub(sub);
673
- try {
674
- fn();
675
- } finally {
676
- activeSub = prevSub;
677
- let link = sub.deps;
678
- while (link !== void 0) {
679
- const dep = link.dep;
680
- link = unlink(link, sub);
681
- const subs = dep.subs;
682
- if (subs !== void 0) {
683
- sub.flags = ReactiveFlags.None;
684
- propagate(subs);
685
- shallowPropagate(subs);
634
+ return untracked(() => {
635
+ const sub = {
636
+ deps: void 0,
637
+ depsTail: void 0,
638
+ flags: ReactiveFlags.Watching
639
+ };
640
+ const prevSub = setActiveSub(sub);
641
+ try {
642
+ fn();
643
+ } finally {
644
+ activeSub = prevSub;
645
+ let link = sub.deps;
646
+ while (link !== void 0) {
647
+ const dep = link.dep;
648
+ link = unlink(link, sub);
649
+ const subs = dep.subs;
650
+ if (subs !== void 0) {
651
+ sub.flags = ReactiveFlags.None;
652
+ propagate(subs);
653
+ shallowPropagate(subs);
654
+ }
686
655
  }
656
+ if (!batchDepth) flush();
687
657
  }
688
- if (!batchDepth) flush();
689
- }
658
+ });
690
659
  }
691
660
  /**
692
661
  * Recomputes a computed node and returns whether its value changed.
@@ -904,9 +873,6 @@ function purgeDeps(sub) {
904
873
  while (dep !== void 0) dep = unlink(dep, sub);
905
874
  }
906
875
  //#endregion
907
- //#region src/polyfill.ts
908
- if (!Symbol.dispose) Object.defineProperty(Symbol, "dispose", { value: Symbol("dispose") });
909
- //#endregion
910
876
  //#region src/signals/index.ts
911
877
  function isReactive(value) {
912
878
  return isSignal(value) || isComputed(value);
package/dist/slot.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { o as ElementBuilder } from "./index-DJejH8Ff.mjs";
1
+ import { o as ElementBuilder } from "./index-Ukqj0EcT.mjs";
2
2
 
3
3
  //#region src/slot.d.ts
4
4
  /**
@@ -13,12 +13,27 @@ declare class Slot {
13
13
  * If not yet mounted, inserts the comment markers and optional default content.
14
14
  * If already mounted, extracts and returns the current content.
15
15
  */
16
+ /**
17
+ * Render the slot as a DocumentFragment.
18
+ * If not yet mounted, inserts the comment markers and optional default content.
19
+ * If already mounted, extracts and returns the current content WITHOUT disposing
20
+ * it — the caller takes ownership of the returned nodes and is responsible for
21
+ * their disposal.
22
+ */
16
23
  slot(defaultContent?: string | Node | ElementBuilder): DocumentFragment;
24
+ /** Dispose reactive children and remove all content between the markers. */
25
+ clear(): void;
17
26
  /**
18
27
  * Replace the slot's content with the given element.
19
28
  * No-op if the slot is not mounted or the content is identical.
20
29
  */
21
30
  set(element: Node): void;
31
+ /**
32
+ * Extract and return the current slot content as a DocumentFragment.
33
+ * Returns `null` if the slot is not mounted.
34
+ * Content is NOT disposed — the caller takes ownership and is responsible
35
+ * for disposal.
36
+ */
22
37
  get(): DocumentFragment | null;
23
38
  /** Returns the parent node if the slot is mounted, otherwise `null`. */
24
39
  parent(): ParentNode | null;
package/dist/slot.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import "./polyfill-B1lNNcum.mjs";
1
2
  //#region src/slot.ts
2
3
  /**
3
4
  * A lightweight slot that reserves a region in the DOM using comment markers.
@@ -11,6 +12,13 @@ var Slot = class Slot {
11
12
  * If not yet mounted, inserts the comment markers and optional default content.
12
13
  * If already mounted, extracts and returns the current content.
13
14
  */
15
+ /**
16
+ * Render the slot as a DocumentFragment.
17
+ * If not yet mounted, inserts the comment markers and optional default content.
18
+ * If already mounted, extracts and returns the current content WITHOUT disposing
19
+ * it — the caller takes ownership of the returned nodes and is responsible for
20
+ * their disposal.
21
+ */
14
22
  slot(defaultContent) {
15
23
  const fragment = document.createDocumentFragment();
16
24
  if (this.isMounted()) {
@@ -28,6 +36,19 @@ var Slot = class Slot {
28
36
  }
29
37
  return fragment;
30
38
  }
39
+ /** Dispose reactive children and remove all content between the markers. */
40
+ clear() {
41
+ let node = this.start.nextSibling;
42
+ while (node && node !== this.end) {
43
+ const next = node.nextSibling;
44
+ if (node instanceof Element) node[Symbol.dispose]?.();
45
+ node = next;
46
+ }
47
+ const range = document.createRange();
48
+ range.setStartAfter(this.start);
49
+ range.setEndBefore(this.end);
50
+ range.deleteContents();
51
+ }
31
52
  /**
32
53
  * Replace the slot's content with the given element.
33
54
  * No-op if the slot is not mounted or the content is identical.
@@ -36,12 +57,15 @@ var Slot = class Slot {
36
57
  const parent = this.parent();
37
58
  if (!parent) return;
38
59
  if (this.isSame(element)) return;
39
- const range = document.createRange();
40
- range.setStartAfter(this.start);
41
- range.setEndBefore(this.end);
42
- range.deleteContents();
60
+ this.clear();
43
61
  parent.insertBefore(element, this.end);
44
62
  }
63
+ /**
64
+ * Extract and return the current slot content as a DocumentFragment.
65
+ * Returns `null` if the slot is not mounted.
66
+ * Content is NOT disposed — the caller takes ownership and is responsible
67
+ * for disposal.
68
+ */
45
69
  get() {
46
70
  if (!this.isMounted()) return null;
47
71
  const range = document.createRange();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elements-kit",
3
3
  "type": "module",
4
- "version": "0.0.3",
4
+ "version": "0.0.6",
5
5
  "description": "A lightweight reactive UI library that transforms native HTMLElements into reactive components with signals. Ideal for framework-agnostic applications and web components.",
6
6
  "keywords": [
7
7
  "webcomponents",
File without changes