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.
- package/dist/element-Cbzkm_B5.mjs +425 -0
- package/dist/for.d.mts +1 -1
- package/dist/for.mjs +1 -1
- package/dist/{infer-LDn1TquI.d.mts → infer-K2Te9gn1.d.mts} +5 -5
- package/dist/integrations/react.d.mts +1 -1
- package/dist/jsx-runtime/index.d.mts +1 -1
- package/dist/jsx-runtime/index.mjs +1 -1
- package/dist/signals/index.d.mts +1 -1
- package/dist/signals/index.mjs +5 -3
- package/dist/slot-B8y0aEoz.d.mts +71 -0
- package/dist/slot-Cne__au7.mjs +127 -0
- package/dist/slot.d.mts +2 -2
- package/dist/slot.mjs +2 -2
- package/dist/utilities/active-element.d.mts +1 -1
- package/dist/utilities/async.d.mts +1 -1
- package/dist/utilities/debounced.d.mts +1 -1
- package/dist/utilities/dom-lifecycle.test.mjs +1 -0
- package/dist/utilities/element-rect.d.mts +1 -1
- package/dist/utilities/element-scroll.d.mts +1 -1
- package/dist/utilities/event-driven.d.mts +1 -1
- package/dist/utilities/event-listener.d.mts +1 -1
- package/dist/utilities/focus-within.d.mts +1 -1
- package/dist/utilities/hover.d.mts +1 -1
- package/dist/utilities/interval.d.mts +1 -1
- package/dist/utilities/location.d.mts +1 -1
- package/dist/utilities/media-devices.d.mts +1 -1
- package/dist/utilities/media-player.d.mts +1 -1
- package/dist/utilities/media-query.d.mts +1 -1
- package/dist/utilities/network.d.mts +1 -1
- package/dist/utilities/orientation.d.mts +1 -1
- package/dist/utilities/previous.d.mts +1 -1
- package/dist/utilities/promise.d.mts +1 -1
- package/dist/utilities/routing.d.mts +1 -1
- package/dist/utilities/search-params.d.mts +1 -1
- package/dist/utilities/storage.d.mts +1 -1
- package/dist/utilities/throttled.d.mts +1 -1
- package/dist/utilities/timeout.d.mts +1 -1
- package/dist/utilities/window-focus.d.mts +1 -1
- package/dist/utilities/window-size.d.mts +1 -1
- package/package.json +1 -1
- package/dist/element-BjpyY6qv.mjs +0 -277
- package/dist/slot-BnzxFBfO.mjs +0 -198
- 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 {
|
|
2
|
-
export { SLOTS, Slot
|
|
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,
|
|
2
|
-
export { SLOTS, Slot
|
|
1
|
+
import { n as Slot, t as SLOTS } from "./slot-Cne__au7.mjs";
|
|
2
|
+
export { SLOTS, Slot };
|
|
@@ -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
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elements-kit",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.3.
|
|
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 };
|