elements-kit 0.3.2 → 0.3.4

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 (43) hide show
  1. package/dist/element-Cbzkm_B5.mjs +425 -0
  2. package/dist/for.d.mts +1 -1
  3. package/dist/for.mjs +1 -1
  4. package/dist/{infer-LDn1TquI.d.mts → infer-K2Te9gn1.d.mts} +5 -5
  5. package/dist/integrations/react.d.mts +1 -1
  6. package/dist/jsx-runtime/index.d.mts +1 -1
  7. package/dist/jsx-runtime/index.mjs +1 -1
  8. package/dist/signals/index.d.mts +1 -1
  9. package/dist/signals/index.mjs +5 -3
  10. package/dist/slot-B8y0aEoz.d.mts +71 -0
  11. package/dist/slot-Cne__au7.mjs +127 -0
  12. package/dist/slot.d.mts +2 -2
  13. package/dist/slot.mjs +2 -2
  14. package/dist/utilities/active-element.d.mts +1 -1
  15. package/dist/utilities/async.d.mts +1 -1
  16. package/dist/utilities/debounced.d.mts +1 -1
  17. package/dist/utilities/dom-lifecycle.test.mjs +1 -0
  18. package/dist/utilities/element-rect.d.mts +1 -1
  19. package/dist/utilities/element-scroll.d.mts +1 -1
  20. package/dist/utilities/event-driven.d.mts +1 -1
  21. package/dist/utilities/event-listener.d.mts +1 -1
  22. package/dist/utilities/focus-within.d.mts +1 -1
  23. package/dist/utilities/hover.d.mts +1 -1
  24. package/dist/utilities/interval.d.mts +1 -1
  25. package/dist/utilities/location.d.mts +1 -1
  26. package/dist/utilities/media-devices.d.mts +1 -1
  27. package/dist/utilities/media-player.d.mts +1 -1
  28. package/dist/utilities/media-query.d.mts +1 -1
  29. package/dist/utilities/network.d.mts +1 -1
  30. package/dist/utilities/orientation.d.mts +1 -1
  31. package/dist/utilities/previous.d.mts +1 -1
  32. package/dist/utilities/promise.d.mts +1 -1
  33. package/dist/utilities/routing.d.mts +1 -1
  34. package/dist/utilities/search-params.d.mts +1 -1
  35. package/dist/utilities/storage.d.mts +1 -1
  36. package/dist/utilities/throttled.d.mts +1 -1
  37. package/dist/utilities/timeout.d.mts +1 -1
  38. package/dist/utilities/window-focus.d.mts +1 -1
  39. package/dist/utilities/window-size.d.mts +1 -1
  40. package/package.json +1 -1
  41. package/dist/element-BjpyY6qv.mjs +0 -277
  42. package/dist/slot-BnzxFBfO.mjs +0 -198
  43. package/dist/slot-CfafCBOW.d.mts +0 -121
@@ -0,0 +1,127 @@
1
+ import "./polyfill-CdZVCxdo.mjs";
2
+ //#region src/lib.ts
3
+ var UnsupportedChildError = class extends Error {
4
+ constructor(value) {
5
+ super(`Unsupported child type: ${typeof value}`);
6
+ this.name = "UnsupportedChildError";
7
+ }
8
+ };
9
+ function resolveNode(c) {
10
+ if (c instanceof Node) return c;
11
+ if (c === null || c === void 0 || typeof c === "boolean") return document.createComment("");
12
+ if (typeof c === "string" || typeof c === "number" || typeof c === "bigint" || typeof c === "symbol" || c instanceof Date || c instanceof RegExp) return document.createTextNode(String(c));
13
+ throw new UnsupportedChildError(c);
14
+ }
15
+ //#endregion
16
+ //#region src/slot.ts
17
+ /**
18
+ * A lightweight slot that reserves a region in the DOM using comment markers.
19
+ * Content between the markers can be replaced dynamically without wrapper elements.
20
+ */
21
+ var Slot = class {
22
+ #start;
23
+ #end;
24
+ #pending;
25
+ /**
26
+ * Render the slot as a DocumentFragment.
27
+ * If not yet mounted, inserts the comment markers and optional default content.
28
+ * If already mounted, extracts and returns the current content WITHOUT disposing
29
+ * it — the caller takes ownership of the returned nodes and is responsible for
30
+ * their disposal.
31
+ */
32
+ render(defaultContent) {
33
+ const fragment = document.createDocumentFragment();
34
+ if (this.isMounted()) {
35
+ const range = document.createRange();
36
+ range.setStartAfter(this.#start);
37
+ range.setEndBefore(this.#end);
38
+ fragment.appendChild(range.extractContents());
39
+ return fragment;
40
+ }
41
+ const start = this.#start ??= document.createComment("{");
42
+ const end = this.#end ??= document.createComment("}");
43
+ fragment.appendChild(start);
44
+ fragment.appendChild(end);
45
+ const initialContent = this.#pending ?? resolveNode(defaultContent);
46
+ if (initialContent) fragment.insertBefore(initialContent, end);
47
+ this.#pending = void 0;
48
+ return fragment;
49
+ }
50
+ /** Dispose reactive children and remove all content between the markers. */
51
+ clear() {
52
+ if (!this.#start || !this.#end) return;
53
+ let node = this.#start.nextSibling;
54
+ while (node && node !== this.#end) {
55
+ const next = node.nextSibling;
56
+ if (node instanceof Element) node[Symbol.dispose]?.();
57
+ node = next;
58
+ }
59
+ const range = document.createRange();
60
+ range.setStartAfter(this.#start);
61
+ range.setEndBefore(this.#end);
62
+ range.deleteContents();
63
+ }
64
+ /**
65
+ * Replace the slot's content with the given element.
66
+ * No-op if the slot is not mounted or the content is identical.
67
+ */
68
+ set(element) {
69
+ const parent = this.parent();
70
+ if (!parent) {
71
+ this.#pending = element;
72
+ return;
73
+ }
74
+ if (this.#isSame(element)) return;
75
+ this.clear();
76
+ parent.insertBefore(element, this.#end);
77
+ this.#pending = void 0;
78
+ }
79
+ /**
80
+ * Extract and return the current slot content as a DocumentFragment.
81
+ * Returns `null` if the slot is not mounted.
82
+ * Content is NOT disposed — the caller takes ownership and is responsible
83
+ * for disposal.
84
+ */
85
+ get() {
86
+ if (!this.isMounted()) return null;
87
+ const range = document.createRange();
88
+ range.setStartAfter(this.#start);
89
+ range.setEndBefore(this.#end);
90
+ return range.extractContents();
91
+ }
92
+ /** Returns the parent node if the slot is mounted, otherwise `null`. */
93
+ parent() {
94
+ return this.isMounted() ? this.#start.parentNode : null;
95
+ }
96
+ /** Whether the slot's comment markers are attached to the DOM. */
97
+ isMounted() {
98
+ return !!this.#start && this.#start.parentNode !== null && this.#start.parentNode === this.#end.parentNode;
99
+ }
100
+ #isSame(element) {
101
+ return this.#start.nextSibling === element && this.#end === element.nextSibling;
102
+ }
103
+ };
104
+ /**
105
+ * Symbol key for attaching a slot collection to a custom element instance.
106
+ * Prevents collisions with public Element properties and signals to the JSX
107
+ * runtime that this property holds slot wiring (not regular children).
108
+ *
109
+ * The value at `[SLOTS]` is a plain object whose keys are slot names and whose
110
+ * values are {@link Slot} instances. Declare with `as const` so TypeScript
111
+ * preserves the literal key union — this is what `ElementProps<typeof Cls>`
112
+ * uses to synthesize `slot:${K}` entries.
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * class Card extends HTMLElement {
117
+ * // ✅ literal keys flow through — "header" | "footer"
118
+ * [SLOTS] = { header: new Slot(), footer: new Slot() } as const;
119
+ * }
120
+ *
121
+ * // ❌ widens — no typed slot:* props
122
+ * // [SLOTS] = { header: new Slot(), footer: new Slot() };
123
+ * ```
124
+ */
125
+ const SLOTS = Symbol("slots");
126
+ //#endregion
127
+ export { Slot as n, resolveNode as r, SLOTS as t };
package/dist/slot.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { i as Slots, n as Slot, r as SlotInstance, t as SLOTS } from "./slot-CfafCBOW.mjs";
2
- export { SLOTS, Slot, SlotInstance, Slots };
1
+ import { n as Slot, t as SLOTS } from "./slot-B8y0aEoz.mjs";
2
+ export { SLOTS, Slot };
package/dist/slot.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as Slot, r as Slots, t as SLOTS } from "./slot-BnzxFBfO.mjs";
2
- export { SLOTS, Slot, Slots };
1
+ import { n as Slot, t as SLOTS } from "./slot-Cne__au7.mjs";
2
+ export { SLOTS, Slot };
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/active-element.d.ts
4
4
  declare const activeElement: Computed<Element | null>;
@@ -1,4 +1,4 @@
1
- import { b as MaybeReactive } from "../infer-LDn1TquI.mjs";
1
+ import { b as MaybeReactive } from "../infer-K2Te9gn1.mjs";
2
2
  import { ComputedPromise } from "./promise.mjs";
3
3
 
4
4
  //#region src/utilities/async.d.ts
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/debounced.d.ts
4
4
  /**
@@ -193,6 +193,7 @@ describe("dom-lifecycle", () => {
193
193
  });
194
194
  it("applies render-inert defaults: display:contents and role='none'", () => {
195
195
  const probe = makeProbe();
196
+ document.body.appendChild(probe);
196
197
  globalExpect(probe.style.display).toBe("contents");
197
198
  globalExpect(probe.getAttribute("role")).toBe("none");
198
199
  });
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/element-rect.d.ts
4
4
  type RectResult = {
@@ -1,4 +1,4 @@
1
- import { x as Signal } from "../infer-LDn1TquI.mjs";
1
+ import { x as Signal } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/element-scroll.d.ts
4
4
  type ElementScrollResult = {
@@ -1,4 +1,4 @@
1
- import { x as Signal, y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { x as Signal, y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/event-driven.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/event-listener.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/focus-within.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/hover.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/interval.d.ts
4
4
  type IntervalResult = {
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/location.d.ts
4
4
  type LocationResult = {
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/media-devices.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { x as Signal, y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { x as Signal, y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/media-player.d.ts
4
4
  type MediaPlayerResult<T extends HTMLMediaElement> = {
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/media-query.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/network.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/orientation.d.ts
4
4
  type OrientationResult = {
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/previous.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/promise.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/routing.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/search-params.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { x as Signal } from "../infer-LDn1TquI.mjs";
1
+ import { x as Signal } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/storage.d.ts
4
4
  type StorageOptions<T> = {
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/throttled.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/timeout.d.ts
4
4
  type TimeoutResult = {
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/window-focus.d.ts
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { y as Computed } from "../infer-LDn1TquI.mjs";
1
+ import { y as Computed } from "../infer-K2Te9gn1.mjs";
2
2
 
3
3
  //#region src/utilities/window-size.d.ts
4
4
  type WindowSizeResult = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elements-kit",
3
3
  "type": "module",
4
- "version": "0.3.2",
4
+ "version": "0.3.4",
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",
@@ -1,277 +0,0 @@
1
- import { c as effectScope, g as untracked, p as onCleanup, s as effect } from "./lib-CVfOddra.mjs";
2
- import "./polyfill-CdZVCxdo.mjs";
3
- import { isReactive, resolveProps } from "./signals/index.mjs";
4
- import { on } from "./utilities/event-listener.mjs";
5
- import { i as resolveNode$1, n as Slot, r as Slots, t as SLOTS } from "./slot-BnzxFBfO.mjs";
6
- import { ChildProperties, Properties, SVGNamespace } from "dom-expressions/src/constants.js";
7
- //#region src/jsx-runtime/constants.ts
8
- /**
9
- * IDL properties that take precedence over the default `setAttribute` path.
10
- *
11
- * Extends dom-expressions' base set with `defaultValue` — without it, JSX
12
- * `<input defaultValue="x" />` falls through to `setAttribute("defaultValue",
13
- * "x")` and creates a useless `defaultvalue` HTML attribute (native
14
- * `HTMLInputElement` has no such content attribute; its `defaultValue` IDL
15
- * property reflects the `value` content attribute instead).
16
- */
17
- const Properties$1 = new Set([...Properties, "defaultValue"]);
18
- const ReservedNameSpaces = new Set([
19
- "class",
20
- "on",
21
- "style",
22
- "prop"
23
- ]);
24
- //#endregion
25
- //#region src/jsx-runtime/children.ts
26
- function hasSlots(node) {
27
- return SLOTS in node;
28
- }
29
- function isChildrenProperty(node, key) {
30
- if (key === "children" && (node instanceof Element || node instanceof DocumentFragment)) return true;
31
- if (hasSlots(node)) {
32
- const slotName = key.replace(/^slot:/, "");
33
- if (Slots.has(node[SLOTS], slotName)) return true;
34
- }
35
- return key in node && node[key] instanceof Slot;
36
- }
37
- function applyChildren(node, key, value) {
38
- if (hasSlots(node)) {
39
- const slotName = key.replace(/^slot:/, "");
40
- if (Slots.has(node[SLOTS], slotName)) {
41
- applySlot(node[SLOTS][slotName], value);
42
- return;
43
- }
44
- }
45
- if (key === "children" && (node instanceof Element || node instanceof DocumentFragment)) {
46
- mountChildren(node, value);
47
- return;
48
- }
49
- if (key in node) {
50
- const slot = node[key];
51
- if (!(slot instanceof Slot)) return;
52
- applySlot(slot, value);
53
- }
54
- }
55
- function applySlot(slot, value) {
56
- effectScope(() => {
57
- let dispose;
58
- if (typeof value === "function") effect(() => slot.set(resolveChild(value())));
59
- else {
60
- const node = resolveChild(value);
61
- dispose = node[Symbol.dispose];
62
- slot.set(node);
63
- }
64
- onCleanup(() => {
65
- dispose?.();
66
- slot.clear();
67
- });
68
- });
69
- }
70
- function mountChildren(el, value) {
71
- for (const child of ensureFlatArray(value)) mountChild(el, child);
72
- }
73
- /**
74
- * Mounts a single child into `el`. Reactive functions become live slots; other
75
- * values append as-is. Each child owns its own `effectScope` so sibling
76
- * `onCleanup` registrations don't overwrite each other (the signals lib
77
- * supports only one onCleanup per subscriber).
78
- *
79
- * Also used by `createFunctionElement` when a component returns a reactive
80
- * getter or primitive — keeps the component's `effectScope` alive for the
81
- * lifetime of the fragment it mounts into.
82
- */
83
- function mountChild(el, child) {
84
- if (typeof child === "function") {
85
- const slot = Slot.new();
86
- el.appendChild(slot());
87
- effectScope(() => {
88
- effect(() => slot.set(resolveChild(child())));
89
- onCleanup(() => slot.clear());
90
- });
91
- return;
92
- }
93
- const node = resolveChild(child);
94
- const dispose = node[Symbol.dispose];
95
- el.appendChild(node);
96
- if (dispose) effectScope(() => {
97
- onCleanup(dispose);
98
- });
99
- }
100
- function resolveChild(value) {
101
- if (Array.isArray(value)) {
102
- const fragment = document.createDocumentFragment();
103
- for (const item of value) fragment.appendChild(resolveChild(item));
104
- return fragment;
105
- }
106
- if (typeof value === "function") return resolveChild(value());
107
- return resolveNode$1(value);
108
- }
109
- /** Normalises the children prop into a flat array. */
110
- function ensureFlatArray(raw) {
111
- return (Array.isArray(raw) ? raw : [raw]).flat(Infinity);
112
- }
113
- //#endregion
114
- //#region src/jsx-runtime/properties.ts
115
- function applyProps(node, props) {
116
- for (const [key, value] of Object.entries(props)) {
117
- if (isChildrenProperty(node, key)) {
118
- applyChildren(node, key, value);
119
- continue;
120
- }
121
- if (isReactive(value)) {
122
- if (isEventKey(key)) {
123
- effect(() => {
124
- on(node, eventName(key), value());
125
- });
126
- continue;
127
- }
128
- effect(() => setProp(node, key, value()));
129
- continue;
130
- }
131
- if (isEventKey(key)) {
132
- on(node, eventName(key), value);
133
- continue;
134
- }
135
- setProp(node, key, value);
136
- }
137
- }
138
- function setProp(node, key, value) {
139
- const colonIdx = key.indexOf(":");
140
- if (colonIdx > -1) {
141
- const ns = key.slice(0, colonIdx);
142
- const name = key.slice(colonIdx + 1);
143
- if (ReservedNameSpaces.has(ns)) {
144
- if (ns === "prop") {
145
- node[name] = value;
146
- return;
147
- }
148
- if (ns === "class") {
149
- node.classList.toggle(name, Boolean(value));
150
- return;
151
- }
152
- if (ns === "style") {
153
- if (value == null || value === false) node.style.removeProperty(name);
154
- else node.style.setProperty(name, String(value));
155
- return;
156
- }
157
- return;
158
- }
159
- const svgNs = SVGNamespace[ns];
160
- if (svgNs) {
161
- node.setAttributeNS(svgNs, key, String(value ?? ""));
162
- return;
163
- }
164
- }
165
- if (key === "class") {
166
- node.className = String(value ?? "");
167
- return;
168
- }
169
- if (key === "style") {
170
- applyStyle(node, value);
171
- return;
172
- }
173
- if (ChildProperties.has(key)) {
174
- node[key] = value ?? "";
175
- return;
176
- }
177
- if (!(node instanceof SVGElement) && Properties$1.has(key)) {
178
- node[key] = value;
179
- return;
180
- }
181
- if (node instanceof Element && node.nodeName.includes("-") && key in node) {
182
- try {
183
- node[key] = value;
184
- } catch {
185
- setAttribute(node, key, value);
186
- }
187
- return;
188
- }
189
- if (!(node instanceof Element)) {
190
- node[key] = value;
191
- return;
192
- }
193
- setAttribute(node, key, value);
194
- }
195
- function applyStyle(el, value) {
196
- const s = el.style;
197
- if (!s) return;
198
- if (typeof value === "string") s.cssText = value;
199
- else if (value && typeof value === "object") Object.assign(s, value);
200
- }
201
- function setAttribute(el, key, value) {
202
- if (value == null || value === false) el.removeAttribute(key);
203
- else el.setAttribute(key, value === true ? "" : String(value));
204
- }
205
- function isEventKey(key) {
206
- return key.startsWith("on:");
207
- }
208
- function eventName(key) {
209
- return key.slice(3);
210
- }
211
- //#endregion
212
- //#region src/jsx-runtime/element.ts
213
- function createElement(type, { ref, ...props } = {}) {
214
- if (typeof type === "function" && !type.prototype?.render) return createFunctionElement(type, props, ref);
215
- return createNodeElement(type, props, ref);
216
- }
217
- /** Runs all cleanup functions registered by JSX props/effects on `el`. */
218
- function disposeElement(el) {
219
- el[Symbol.dispose]?.();
220
- }
221
- function createFunctionElement(type, props, ref) {
222
- let el;
223
- let dispose;
224
- untracked(() => {
225
- dispose = effectScope(() => {
226
- el = type(resolveProps(props));
227
- if (typeof ref === "function" && el instanceof Element) ref(el);
228
- });
229
- });
230
- const result = el;
231
- if (result instanceof Element || result instanceof DocumentFragment) attachDisposables(result, new Set([dispose]));
232
- else dispose();
233
- return result;
234
- }
235
- function createNodeElement(type, props, ref) {
236
- const node = resolveNode(type);
237
- if (!node) return null;
238
- let el;
239
- let dispose;
240
- untracked(() => {
241
- dispose = effectScope(() => {
242
- applyProps(node, props);
243
- el = renderNode(node);
244
- if (typeof ref === "function" && el instanceof Element) ref(el);
245
- });
246
- });
247
- const result = el;
248
- if (result instanceof Element || result instanceof DocumentFragment) attachDisposables(result, new Set([dispose]));
249
- else dispose();
250
- return result;
251
- }
252
- function resolveNode(type) {
253
- if (typeof type === "string") return document.createElement(type);
254
- if (type instanceof Element || type instanceof DocumentFragment) return type;
255
- return new type();
256
- }
257
- function renderNode(node) {
258
- if (node instanceof Element || node instanceof DocumentFragment) return node;
259
- if (!node || typeof node.render !== "function") return null;
260
- return renderNode(node.render());
261
- }
262
- function hasOwnDisposable(el) {
263
- return Object.hasOwn(el, Symbol.dispose);
264
- }
265
- function attachDisposables(el, disposables) {
266
- const existingDispose = hasOwnDisposable(el) ? el[Symbol.dispose].bind(el) : null;
267
- Object.defineProperty(el, Symbol.dispose, {
268
- value() {
269
- existingDispose?.();
270
- disposables.forEach((fn) => fn());
271
- disposables.clear();
272
- },
273
- configurable: true
274
- });
275
- }
276
- //#endregion
277
- export { disposeElement as n, mountChild as r, createElement as t };