elements-kit 0.0.4 → 0.0.7

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-fdz3qoMP.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, d as onCleanup, m as untracked, o as effectScope, t as isReactive } from "./signals-fdz3qoMP.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$1 } 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;
@@ -69,21 +70,37 @@ function applyChildren(node, key, value) {
69
70
  }
70
71
  }
71
72
  function applySlot(slot, value) {
72
- if (typeof value === "function") {
73
- effect(() => slot.set(resolveChild(value())));
74
- return;
75
- }
76
- 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
+ });
77
86
  }
78
87
  function mountChildren(el, value) {
79
88
  for (const child of ensureFlatArray(value)) {
80
89
  if (typeof child === "function") {
81
90
  const slot = Slot.new();
82
91
  el.appendChild(slot());
83
- effect(() => slot.set(resolveChild(child())));
92
+ effectScope(() => {
93
+ effect(() => slot.set(resolveChild(child())));
94
+ onCleanup(() => slot.clear());
95
+ });
84
96
  continue;
85
97
  }
86
- 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
+ });
87
104
  }
88
105
  }
89
106
  function resolveChild(value) {
@@ -235,8 +252,8 @@ function createNodeElement(type, props, ref) {
235
252
  let dispose;
236
253
  untracked(() => {
237
254
  dispose = effectScope(() => {
238
- applyProps(node, props);
239
255
  el = renderNode(node);
256
+ applyProps(node, props);
240
257
  if (typeof ref === "function" && el instanceof Element) ref(el);
241
258
  });
242
259
  });
@@ -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
  /**
@@ -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-BO1ay29p.mjs";
2
- import { a as effect, f as signal, m as untracked, p as trigger } from "./signals-fdz3qoMP.mjs";
1
+ import { n as disposeElement } from "./element-Ddri9UFx.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
@@ -48,6 +48,11 @@ var For = class {
48
48
  fragment.appendChild(this.#start);
49
49
  fragment.appendChild(this.#end);
50
50
  effect(() => this.#reconcile());
51
+ onCleanup(() => {
52
+ for (const entry of this.#cache.values()) cleanEntry(entry);
53
+ this.#cache.clear();
54
+ this.#order = [];
55
+ });
51
56
  return fragment;
52
57
  }
53
58
  #reconcile() {
@@ -109,6 +114,14 @@ function insertEntry(parent, entry, before, rendered) {
109
114
  if (rendered) parent.insertBefore(rendered, before);
110
115
  parent.insertBefore(entry.end, before);
111
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
+ }
112
125
  function removeEntry(entry) {
113
126
  let node = entry.start.nextSibling;
114
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
@@ -20,6 +20,18 @@ declare function createElement(type: string | Element | DocumentFragment | Compo
20
20
  //#region src/jsx-runtime/ref.d.ts
21
21
  declare const $ref: unique symbol;
22
22
  //#endregion
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;
34
+ //#endregion
23
35
  //#region src/jsx-runtime/index.d.ts
24
36
  /** A value or a reactive zero-argument getter. */
25
37
  type FunctionMaybe<T> = JSX$1.FunctionMaybe<T>;
@@ -65,4 +77,4 @@ declare namespace JSX {
65
77
  };
66
78
  }
67
79
  //#endregion
68
- 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-BO1ay29p.mjs";
2
- export { createElement as h, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
1
+ import { t as createElement } from "../element-Ddri9UFx.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-CYOjSQUS.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-fdz3qoMP.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-CYOjSQUS.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-fdz3qoMP.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-CYOjSQUS.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-fdz3qoMP.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}.
@@ -872,9 +873,6 @@ function purgeDeps(sub) {
872
873
  while (dep !== void 0) dep = unlink(dep, sub);
873
874
  }
874
875
  //#endregion
875
- //#region src/polyfill.ts
876
- if (!Symbol.dispose) Object.defineProperty(Symbol, "dispose", { value: Symbol("dispose") });
877
- //#endregion
878
876
  //#region src/signals/index.ts
879
877
  function isReactive(value) {
880
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.4",
4
+ "version": "0.0.7",
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