defuss-morph 0.1.1 → 0.3.0

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/index.mjs CHANGED
@@ -9,8 +9,7 @@ const CAPTURE_ONLY_EVENTS = /* @__PURE__ */ new Set([
9
9
  // Note: focusin/focusout DO bubble, so they're not included here
10
10
  ]);
11
11
  const elementHandlerMap = /* @__PURE__ */ new WeakMap();
12
- const bubbleDispatched = /* @__PURE__ */ new WeakMap();
13
- const captureDispatched = /* @__PURE__ */ new WeakMap();
12
+ const slotListeners = /* @__PURE__ */ new WeakMap();
14
13
  const activeDispatches = /* @__PURE__ */ new WeakMap();
15
14
  const parseEventPropName = (propName) => {
16
15
  if (!propName.startsWith("on")) return null;
@@ -29,147 +28,64 @@ const getOrCreateElementHandlers = (el) => {
29
28
  elementHandlerMap.set(el, created);
30
29
  return created;
31
30
  };
32
- const getEventPath = (event) => {
33
- const composedPath = event.composedPath?.();
34
- if (composedPath && composedPath.length > 0) return composedPath;
35
- const path = [];
36
- let node = event.target;
37
- while (node) {
38
- path.push(node);
39
- const maybeNode = node;
40
- if (typeof maybeNode === "object" && maybeNode && "parentNode" in maybeNode) {
41
- node = maybeNode.parentNode;
42
- continue;
43
- }
44
- break;
31
+ const runSlot = (target, eventType, phase, event) => {
32
+ const handler = elementHandlerMap.get(target)?.get(eventType)?.[phase];
33
+ if (!handler) return;
34
+ const dispatchKey = `${eventType}:${phase}`;
35
+ let active = activeDispatches.get(target);
36
+ if (active?.has(dispatchKey)) return;
37
+ if (!active) {
38
+ active = /* @__PURE__ */ new Set();
39
+ activeDispatches.set(target, active);
40
+ }
41
+ active.add(dispatchKey);
42
+ try {
43
+ handler.call(target, event);
44
+ } finally {
45
+ active.delete(dispatchKey);
45
46
  }
46
- const doc = event.target?.ownerDocument;
47
- if (doc && path[path.length - 1] !== doc) path.push(doc);
48
- const win = doc?.defaultView;
49
- if (win && path[path.length - 1] !== win) path.push(win);
50
- return path;
51
47
  };
52
- const createPhaseHandler = (eventType, phase) => {
53
- const dispatched = phase === "capture" ? captureDispatched : bubbleDispatched;
54
- return (event) => {
55
- const path = getEventPath(event).filter(
56
- (t) => typeof t === "object" && t !== null && t.nodeType === 1
57
- );
58
- const ordered = phase === "capture" ? [...path].reverse() : path;
59
- for (const target of ordered) {
60
- const handlersByEvent = elementHandlerMap.get(target);
61
- if (!handlersByEvent) continue;
62
- const entry = handlersByEvent.get(eventType);
63
- if (!entry) continue;
64
- let targets = dispatched.get(event);
65
- if (targets?.has(target)) continue;
66
- if (!targets) {
67
- targets = /* @__PURE__ */ new WeakSet();
68
- dispatched.set(event, targets);
69
- }
70
- targets.add(target);
71
- const dispatchKey = `${eventType}:${phase}`;
72
- let activeSet = activeDispatches.get(target);
73
- if (activeSet?.has(dispatchKey)) continue;
74
- if (!activeSet) {
75
- activeSet = /* @__PURE__ */ new Set();
76
- activeDispatches.set(target, activeSet);
77
- }
78
- activeSet.add(dispatchKey);
79
- try {
80
- if (phase === "capture") {
81
- if (entry.capture) {
82
- entry.capture.call(target, event);
83
- if (event.cancelBubble)
84
- return;
85
- }
86
- if (entry.captureSet) {
87
- for (const handler of entry.captureSet) {
88
- handler.call(target, event);
89
- if (event.cancelBubble)
90
- return;
91
- }
92
- }
93
- } else {
94
- if (entry.bubble) {
95
- entry.bubble.call(target, event);
96
- if (event.cancelBubble)
97
- return;
98
- }
99
- if (entry.bubbleSet) {
100
- for (const handler of entry.bubbleSet) {
101
- handler.call(target, event);
102
- if (event.cancelBubble)
103
- return;
104
- }
105
- }
106
- }
107
- } finally {
108
- activeSet.delete(dispatchKey);
109
- }
48
+ const setSlot = (target, eventType, phase, entry, handler) => {
49
+ entry[phase] = handler;
50
+ const key = `${eventType}:${phase}`;
51
+ const capture = phase === "capture";
52
+ let byKey = slotListeners.get(target);
53
+ const installed = byKey?.get(key);
54
+ if (handler && !installed) {
55
+ if (!byKey) {
56
+ byKey = /* @__PURE__ */ new Map();
57
+ slotListeners.set(target, byKey);
110
58
  }
111
- };
112
- };
113
- const installedRootListeners = /* @__PURE__ */ new WeakMap();
114
- const ensureRootListener = (root, eventType) => {
115
- const installed = installedRootListeners.get(root) ?? /* @__PURE__ */ new Set();
116
- installedRootListeners.set(root, installed);
117
- const captureKey = `${eventType}:capture`;
118
- if (!installed.has(captureKey)) {
119
- root.addEventListener(
120
- eventType,
121
- createPhaseHandler(eventType, "capture"),
122
- true
123
- );
124
- installed.add(captureKey);
125
- }
126
- const bubbleKey = `${eventType}:bubble`;
127
- if (!installed.has(bubbleKey)) {
128
- root.addEventListener(
129
- eventType,
130
- createPhaseHandler(eventType, "bubble"),
131
- false
132
- );
133
- installed.add(bubbleKey);
59
+ const trampoline = (event) => runSlot(target, eventType, phase, event);
60
+ byKey.set(key, trampoline);
61
+ target.addEventListener(eventType, trampoline, capture);
62
+ } else if (!handler && installed) {
63
+ byKey.delete(key);
64
+ target.removeEventListener(eventType, installed, capture);
134
65
  }
135
66
  };
136
- const getEventRoot = (element) => {
137
- const root = element.getRootNode();
138
- if (root && root.nodeType === 9) {
139
- return root;
140
- }
141
- if (root && root.nodeType === 11 && "host" in root) {
142
- return root;
143
- }
144
- return null;
67
+ const clearPhase = (target, eventType, entry, phase) => {
68
+ setSlot(target, eventType, phase, entry, void 0);
69
+ const setKey = phase === "capture" ? "captureSet" : "bubbleSet";
70
+ for (const handler of entry[setKey] ?? [])
71
+ target.removeEventListener(eventType, handler, phase === "capture");
72
+ entry[setKey] = void 0;
145
73
  };
146
74
  const registerDelegatedEvent = (element, eventType, handler, options = {}) => {
147
- const root = getEventRoot(element);
148
75
  const capture = options.capture || CAPTURE_ONLY_EVENTS.has(eventType);
149
- if (root) {
150
- ensureRootListener(root, eventType);
151
- } else if (element.ownerDocument) {
152
- ensureRootListener(element.ownerDocument, eventType);
153
- } else {
154
- element.addEventListener(eventType, handler, capture);
155
- }
76
+ const phase = capture ? "capture" : "bubble";
156
77
  const byEvent = getOrCreateElementHandlers(element);
157
78
  const entry = byEvent.get(eventType) ?? {};
158
79
  byEvent.set(eventType, entry);
159
80
  if (options.multi) {
160
- if (capture) {
161
- if (!entry.captureSet) entry.captureSet = /* @__PURE__ */ new Set();
162
- entry.captureSet.add(handler);
163
- } else {
164
- if (!entry.bubbleSet) entry.bubbleSet = /* @__PURE__ */ new Set();
165
- entry.bubbleSet.add(handler);
81
+ const setKey = capture ? "captureSet" : "bubbleSet";
82
+ const set = entry[setKey] ??= /* @__PURE__ */ new Set();
83
+ if (!set.has(handler)) {
84
+ set.add(handler);
85
+ element.addEventListener(eventType, handler, capture);
166
86
  }
167
87
  } else {
168
- if (capture) {
169
- entry.capture = handler;
170
- } else {
171
- entry.bubble = handler;
172
- }
88
+ setSlot(element, eventType, phase, entry, handler);
173
89
  }
174
90
  };
175
91
  const isEntryEmpty = (entry) => !entry.capture && !entry.bubble && (!entry.captureSet || entry.captureSet.size === 0) && (!entry.bubbleSet || entry.bubbleSet.size === 0);
@@ -179,34 +95,38 @@ const removeDelegatedEvent = (target, eventType, handler, _options = {}) => {
179
95
  const entry = byEvent.get(eventType);
180
96
  if (!entry) return;
181
97
  if (handler) {
182
- if (entry.captureSet) {
183
- entry.captureSet.delete(handler);
184
- }
185
- if (entry.bubbleSet) {
186
- entry.bubbleSet.delete(handler);
187
- }
188
- if (entry.capture === handler) {
189
- entry.capture = void 0;
190
- }
191
- if (entry.bubble === handler) {
192
- entry.bubble = void 0;
98
+ for (const phase of ["capture", "bubble"]) {
99
+ const set = phase === "capture" ? entry.captureSet : entry.bubbleSet;
100
+ if (set?.delete(handler))
101
+ target.removeEventListener(eventType, handler, phase === "capture");
102
+ if (entry[phase] === handler)
103
+ setSlot(target, eventType, phase, entry, void 0);
193
104
  }
194
- target.removeEventListener(eventType, handler, true);
195
- target.removeEventListener(eventType, handler, false);
196
105
  } else {
197
- entry.capture = void 0;
198
- entry.bubble = void 0;
199
- entry.captureSet = void 0;
200
- entry.bubbleSet = void 0;
106
+ clearPhase(target, eventType, entry, "capture");
107
+ clearPhase(target, eventType, entry, "bubble");
201
108
  }
202
109
  if (isEntryEmpty(entry)) {
203
110
  byEvent.delete(eventType);
204
111
  }
205
112
  };
113
+ const clearHooks = /* @__PURE__ */ new Set();
114
+ const onClearDelegatedEvents = (hook) => {
115
+ clearHooks.add(hook);
116
+ return () => {
117
+ clearHooks.delete(hook);
118
+ };
119
+ };
206
120
  const clearDelegatedEvents = (target) => {
207
121
  const byEvent = elementHandlerMap.get(target);
208
- if (!byEvent) return;
209
- byEvent.clear();
122
+ if (byEvent) {
123
+ for (const [eventType, entry] of byEvent) {
124
+ clearPhase(target, eventType, entry, "capture");
125
+ clearPhase(target, eventType, entry, "bubble");
126
+ }
127
+ byEvent.clear();
128
+ }
129
+ for (const hook of clearHooks) hook(target);
210
130
  };
211
131
  const clearDelegatedEventsDeep = (root) => {
212
132
  clearDelegatedEvents(root);
@@ -244,16 +164,113 @@ const removeDelegatedEventByKey = (element, eventType, phase) => {
244
164
  if (!byEvent) return;
245
165
  const entry = byEvent.get(eventType);
246
166
  if (!entry) return;
247
- if (phase === "capture") {
248
- entry.capture = void 0;
249
- entry.captureSet = void 0;
250
- } else {
251
- entry.bubble = void 0;
252
- entry.bubbleSet = void 0;
253
- }
167
+ clearPhase(element, eventType, entry, phase);
254
168
  if (isEntryEmpty(entry)) byEvent.delete(eventType);
255
169
  };
256
170
 
171
+ const FROM_DOM_MARKER = /* @__PURE__ */ Symbol("defuss-morph.from-dom");
172
+ const COMMENT_TYPE = "#comment";
173
+ const isCommentVNode = (value) => !!value && typeof value === "object" && value.type === COMMENT_TYPE;
174
+ const HTML_BOOLEAN_ATTRIBUTES = /* @__PURE__ */ new Set([
175
+ "allowfullscreen",
176
+ "async",
177
+ "autofocus",
178
+ "autoplay",
179
+ "checked",
180
+ "controls",
181
+ "default",
182
+ "defer",
183
+ "disabled",
184
+ "formnovalidate",
185
+ "hidden",
186
+ "inert",
187
+ "ismap",
188
+ "itemscope",
189
+ "loop",
190
+ "multiple",
191
+ "muted",
192
+ "nomodule",
193
+ "novalidate",
194
+ "open",
195
+ "playsinline",
196
+ "readonly",
197
+ "required",
198
+ "reversed",
199
+ "selected"
200
+ ]);
201
+ const domAttributeToVNodeValue = (attr) => HTML_BOOLEAN_ATTRIBUTES.has(attr.name.toLowerCase()) ? true : attr.value;
202
+ function parseDOM(input, type, Parser) {
203
+ return new Parser().parseFromString(input, type);
204
+ }
205
+ function isSVG(input, Parser) {
206
+ const doc = parseDOM(input, "image/svg+xml", Parser);
207
+ if (!doc.documentElement) return false;
208
+ return doc.documentElement.nodeName.toLowerCase() === "svg";
209
+ }
210
+ function isHTML(input, Parser) {
211
+ const doc = parseDOM(input, "text/html", Parser);
212
+ return doc.documentElement.querySelectorAll("*").length > 2;
213
+ }
214
+ const isMarkup = (input, Parser) => input.indexOf("<") > -1 && input.indexOf(">") > -1 && (isHTML(input, Parser) || isSVG(input, Parser));
215
+ function renderMarkup(markup, Parser, doc) {
216
+ const parsed = doc ? doc : parseDOM(markup, getMimeType(markup, Parser), Parser);
217
+ if (parsed.body) return Array.from(parsed.body.childNodes);
218
+ return parsed.documentElement ? [parsed.documentElement] : [];
219
+ }
220
+ function getMimeType(input, Parser) {
221
+ if (isSVG(input, Parser)) {
222
+ return "image/svg+xml";
223
+ }
224
+ return "text/html";
225
+ }
226
+ const templateContent = (element) => element.localName === "template" ? element.content : void 0;
227
+ function domNodeToVNode(node) {
228
+ if (node.nodeType === 3) {
229
+ return node.nodeValue || "";
230
+ }
231
+ if (node.nodeType === 1) {
232
+ const element = node;
233
+ const attributes = {};
234
+ for (let i = 0; i < element.attributes.length; i++) {
235
+ const attr = element.attributes[i];
236
+ attributes[attr.name] = domAttributeToVNodeValue(attr);
237
+ }
238
+ const children = [];
239
+ for (let child = (templateContent(element) ?? element).firstChild; child; child = child.nextSibling) {
240
+ children.push(domNodeToVNode(child));
241
+ }
242
+ attributes[FROM_DOM_MARKER] = true;
243
+ return { type: element.localName, attributes, children };
244
+ }
245
+ if (node.nodeType === 8) {
246
+ return { type: COMMENT_TYPE, value: node.nodeValue ?? "" };
247
+ }
248
+ return "";
249
+ }
250
+ const inertDocuments = /* @__PURE__ */ new WeakMap();
251
+ const DOCUMENT_START = /^\s*(?:<!--[\s\S]*?-->\s*)*<(?:!doctype|html|head|body)[\s>/]/i;
252
+ function htmlStringToVNodes(html, Parser) {
253
+ if (DOCUMENT_START.test(html)) {
254
+ return toVNodes(new Parser().parseFromString(html, "text/html").body.childNodes);
255
+ }
256
+ let inert = inertDocuments.get(Parser);
257
+ if (!inert) {
258
+ inert = new Parser().parseFromString("", "text/html");
259
+ inertDocuments.set(Parser, inert);
260
+ }
261
+ const template = inert.createElement("template");
262
+ template.innerHTML = html;
263
+ return toVNodes(template.content.childNodes);
264
+ }
265
+ function toVNodes(nodes) {
266
+ const vNodes = [];
267
+ for (let i = 0; i < nodes.length; i++) {
268
+ const vnode = domNodeToVNode(nodes[i]);
269
+ if (vnode !== "") vNodes.push(vnode);
270
+ }
271
+ return vNodes;
272
+ }
273
+
257
274
  const CLASS_ATTRIBUTE_NAME = "class";
258
275
  const XLINK_ATTRIBUTE_NAME = "xlink";
259
276
  const XMLNS_ATTRIBUTE_NAME = "xmlns";
@@ -303,13 +320,18 @@ const observeUnmount = (domNode, onUnmount) => {
303
320
  });
304
321
  observer.observe(parentNode, { childList: true });
305
322
  };
323
+ const unmountObserved = /* @__PURE__ */ new WeakSet();
306
324
  const handleLifecycleEventsForOnMount = (newEl) => {
307
325
  if (typeof newEl?.$onMount === "function") {
308
326
  newEl.$onMount(newEl);
309
327
  newEl.$onMount = null;
310
328
  }
311
- if (typeof newEl?.$onUnmount === "function") {
312
- observeUnmount(newEl, newEl.$onUnmount);
329
+ if (typeof newEl?.$onUnmount === "function" && !unmountObserved.has(newEl)) {
330
+ unmountObserved.add(newEl);
331
+ observeUnmount(newEl, () => {
332
+ unmountObserved.delete(newEl);
333
+ newEl.$onUnmount?.(newEl);
334
+ });
313
335
  }
314
336
  };
315
337
  const getRenderer = (document) => {
@@ -320,6 +342,9 @@ const getRenderer = (document) => {
320
342
  if (Array.isArray(virtualNode)) {
321
343
  return renderer.createChildElements(virtualNode, parentDomElement);
322
344
  }
345
+ if (typeof virtualNode === "string" || typeof virtualNode === "number") {
346
+ return renderer.createTextNode(String(virtualNode), parentDomElement);
347
+ }
323
348
  if (typeof virtualNode !== "undefined") {
324
349
  return renderer.createElement(virtualNode, parentDomElement);
325
350
  }
@@ -327,50 +352,45 @@ const getRenderer = (document) => {
327
352
  },
328
353
  createElement: (virtualNode, parentDomElement) => {
329
354
  let newEl;
330
- try {
331
- if (typeof virtualNode === "function" && virtualNode.constructor.name === "AsyncFunction") {
355
+ if (isCommentVNode(virtualNode)) {
356
+ const comment = document.createComment(virtualNode.value ?? "");
357
+ parentDomElement?.appendChild(comment);
358
+ return comment;
359
+ }
360
+ if (typeof virtualNode === "function" && virtualNode.constructor.name === "AsyncFunction") {
361
+ newEl = document.createElement("div");
362
+ } else if (typeof virtualNode === "object" && virtualNode !== null && "type" in virtualNode) {
363
+ const vNode = virtualNode;
364
+ if (typeof vNode.type === "function") {
332
365
  newEl = document.createElement("div");
333
- } else if (typeof virtualNode === "object" && virtualNode !== null && "type" in virtualNode) {
334
- const vNode = virtualNode;
335
- if (typeof vNode.type === "function") {
336
- newEl = document.createElement("div");
337
- newEl.innerText = `FATAL ERROR: ${vNode.type._error}`;
338
- } else if (
339
- // SVG support
340
- typeof vNode.type === "string" && vNode.type.toUpperCase() === "SVG" || parentDomElement && renderer.hasSvgNamespace(
341
- parentDomElement,
342
- typeof vNode.type === "string" ? vNode.type.toUpperCase() : ""
343
- )
344
- ) {
345
- newEl = document.createElementNS(nsMap.svg, vNode.type);
346
- } else {
347
- newEl = document.createElement(vNode.type);
348
- }
349
- if (vNode.attributes) {
350
- renderer.setAttributes(vNode, newEl);
351
- if (vNode.attributes.dangerouslySetInnerHTML) {
352
- newEl.innerHTML = vNode.attributes.dangerouslySetInnerHTML.__html;
353
- }
354
- }
355
- if (vNode.children && !vNode.attributes?.dangerouslySetInnerHTML) {
356
- renderer.createChildElements(vNode.children, newEl);
357
- }
366
+ newEl.innerText = `FATAL ERROR: ${vNode.type._error}`;
367
+ } else if (
368
+ // SVG support
369
+ typeof vNode.type === "string" && vNode.type.toUpperCase() === "SVG" || parentDomElement && renderer.hasSvgNamespace(
370
+ parentDomElement,
371
+ typeof vNode.type === "string" ? vNode.type.toUpperCase() : ""
372
+ )
373
+ ) {
374
+ newEl = document.createElementNS(nsMap.svg, vNode.type);
358
375
  } else {
359
- if (typeof virtualNode === "string" || typeof virtualNode === "number") {
360
- newEl = document.createElement(String(virtualNode));
376
+ newEl = document.createElement(vNode.type);
377
+ }
378
+ if (vNode.attributes) {
379
+ renderer.setAttributes(vNode, newEl);
380
+ if (vNode.attributes.dangerouslySetInnerHTML) {
381
+ newEl.innerHTML = vNode.attributes.dangerouslySetInnerHTML.__html;
361
382
  }
362
383
  }
363
- if (newEl && parentDomElement) {
364
- parentDomElement.appendChild(newEl);
365
- handleLifecycleEventsForOnMount(newEl);
384
+ if (vNode.children && !vNode.attributes?.dangerouslySetInnerHTML) {
385
+ renderer.createChildElements(
386
+ vNode.children,
387
+ templateContent(newEl) ?? newEl
388
+ );
366
389
  }
367
- } catch (e) {
368
- console.error(
369
- "Fatal error! Error happend while rendering the VDOM!",
370
- e,
371
- virtualNode
372
- );
373
- throw e;
390
+ }
391
+ if (newEl && parentDomElement) {
392
+ parentDomElement.appendChild(newEl);
393
+ handleLifecycleEventsForOnMount(newEl);
374
394
  }
375
395
  return newEl;
376
396
  },
@@ -411,20 +431,8 @@ const getRenderer = (document) => {
411
431
  return;
412
432
  }
413
433
  if (name === REF_ATTRIBUTE_NAME && typeof value !== "function") {
414
- const ref = value;
415
- ref.current = domElement;
434
+ value.current = domElement;
416
435
  domElement._defussRef = value;
417
- domElement.$onUnmount = queueCallback(() => {
418
- });
419
- if (domElement.parentNode) {
420
- observeUnmount(domElement, domElement.$onUnmount);
421
- } else {
422
- queueMicrotask(() => {
423
- if (domElement.parentNode) {
424
- observeUnmount(domElement, domElement.$onUnmount);
425
- }
426
- });
427
- }
428
436
  return;
429
437
  }
430
438
  const parsed = parseEventPropName(name);
@@ -435,15 +443,7 @@ const getRenderer = (document) => {
435
443
  return;
436
444
  }
437
445
  if (eventType === "unmount") {
438
- if (domElement.$onUnmount) {
439
- const existingUnmount = domElement.$onUnmount;
440
- domElement.$onUnmount = () => {
441
- existingUnmount();
442
- value();
443
- };
444
- } else {
445
- domElement.$onUnmount = queueCallback(value);
446
- }
446
+ domElement.$onUnmount = queueCallback(value);
447
447
  return;
448
448
  }
449
449
  registerDelegatedEvent(
@@ -517,95 +517,29 @@ const getRenderer = (document) => {
517
517
  return renderer;
518
518
  };
519
519
 
520
- const FROM_DOM_MARKER = Symbol("defuss-morph.from-dom");
521
- const HTML_BOOLEAN_ATTRIBUTES = /* @__PURE__ */ new Set([
522
- "allowfullscreen",
523
- "async",
524
- "autofocus",
525
- "autoplay",
526
- "checked",
527
- "controls",
528
- "default",
529
- "defer",
530
- "disabled",
531
- "formnovalidate",
532
- "hidden",
533
- "inert",
534
- "ismap",
535
- "itemscope",
536
- "loop",
537
- "multiple",
538
- "muted",
539
- "nomodule",
540
- "novalidate",
541
- "open",
542
- "playsinline",
543
- "readonly",
544
- "required",
545
- "reversed",
546
- "selected"
547
- ]);
548
- const domAttributeToVNodeValue = (attr) => HTML_BOOLEAN_ATTRIBUTES.has(attr.name.toLowerCase()) ? true : attr.value;
549
- function parseDOM(input, type, Parser) {
550
- return new Parser().parseFromString(input, type);
551
- }
552
- function isSVG(input, Parser) {
553
- const doc = parseDOM(input, "image/svg+xml", Parser);
554
- if (!doc.documentElement) return false;
555
- return doc.documentElement.nodeName.toLowerCase() === "svg";
556
- }
557
- function isHTML(input, Parser) {
558
- const doc = parseDOM(input, "text/html", Parser);
559
- return doc.documentElement.querySelectorAll("*").length > 2;
560
- }
561
- const isMarkup = (input, Parser) => input.indexOf("<") > -1 && input.indexOf(">") > -1 && (isHTML(input, Parser) || isSVG(input, Parser));
562
- function renderMarkup(markup, Parser, doc) {
563
- const parsed = doc ? doc : parseDOM(markup, getMimeType(markup, Parser), Parser);
564
- if (parsed.body) return Array.from(parsed.body.childNodes);
565
- return parsed.documentElement ? [parsed.documentElement] : [];
566
- }
567
- function getMimeType(input, Parser) {
568
- if (isSVG(input, Parser)) {
569
- return "image/svg+xml";
570
- }
571
- return "text/html";
572
- }
573
- function domNodeToVNode(node) {
574
- if (node.nodeType === 3) {
575
- return node.textContent || "";
576
- }
577
- if (node.nodeType === 1) {
578
- const element = node;
579
- const attributes = {};
580
- for (let i = 0; i < element.attributes.length; i++) {
581
- const attr = element.attributes[i];
582
- attributes[attr.name] = domAttributeToVNodeValue(attr);
583
- }
584
- const children = [];
585
- for (let i = 0; i < element.childNodes.length; i++) {
586
- const childVNode = domNodeToVNode(element.childNodes[i]);
587
- children.push(childVNode);
520
+ const longestIncreasingRun = (values) => {
521
+ const n = values.length;
522
+ const marked = new Uint8Array(n);
523
+ const tails = new Int32Array(n);
524
+ const previous = new Int32Array(n);
525
+ let length = 0;
526
+ for (let i = 0; i < n; i++) {
527
+ const value = values[i];
528
+ if (value < 0) continue;
529
+ let low = 0;
530
+ let high = length;
531
+ while (low < high) {
532
+ const mid = low + high >> 1;
533
+ if (values[tails[mid]] < value) low = mid + 1;
534
+ else high = mid;
588
535
  }
589
- return {
590
- type: element.tagName.toLowerCase(),
591
- attributes: { ...attributes, [FROM_DOM_MARKER]: true },
592
- children
593
- };
536
+ previous[i] = low > 0 ? tails[low - 1] : -1;
537
+ tails[low] = i;
538
+ if (low === length) length++;
594
539
  }
595
- return "";
596
- }
597
- function htmlStringToVNodes(html, Parser) {
598
- const parser = new Parser();
599
- const doc = parser.parseFromString(html, "text/html");
600
- const vNodes = [];
601
- for (let i = 0; i < doc.body.childNodes.length; i++) {
602
- const vnode = domNodeToVNode(doc.body.childNodes[i]);
603
- if (vnode !== "") {
604
- vNodes.push(vnode);
605
- }
606
- }
607
- return vNodes;
608
- }
540
+ for (let i = length > 0 ? tails[length - 1] : -1; i >= 0; i = previous[i]) marked[i] = 1;
541
+ return marked;
542
+ };
609
543
 
610
544
  const areDomNodesEqual = (oldNode, newNode) => {
611
545
  if (oldNode === newNode) return true;
@@ -623,15 +557,15 @@ const areDomNodesEqual = (oldNode, newNode) => {
623
557
  if (oldAttr.value !== newAttrValue) return false;
624
558
  }
625
559
  }
626
- if (oldNode.nodeType === 3) {
627
- if (oldNode.textContent !== newNode.textContent) return false;
560
+ if (oldNode.nodeType === 3 || oldNode.nodeType === 8) {
561
+ if (oldNode.nodeValue !== newNode.nodeValue) return false;
628
562
  }
629
563
  return true;
630
564
  };
631
565
  function isTextLike(value) {
632
566
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
633
567
  }
634
- function isVNode(value) {
568
+ function isVNode$1(value) {
635
569
  return Boolean(
636
570
  value && typeof value === "object" && "type" in value
637
571
  );
@@ -639,7 +573,7 @@ function isVNode(value) {
639
573
  function toValidChild(child, lenient = false) {
640
574
  if (child == null) return child;
641
575
  if (isTextLike(child)) return child;
642
- if (isVNode(child)) return child;
576
+ if (isVNode$1(child)) return child;
643
577
  if (lenient && child && typeof child === "object" && "attributes" in child)
644
578
  return child;
645
579
  return void 0;
@@ -653,7 +587,7 @@ function normalizeChildren(input, lenient = false) {
653
587
  }
654
588
  const valid = toValidChild(child, lenient);
655
589
  if (typeof valid === "undefined") return;
656
- if (isVNode(valid) && (valid.type === "fragment" || valid.type === "Fragment")) {
590
+ if (isVNode$1(valid) && (valid.type === "fragment" || valid.type === "Fragment")) {
657
591
  const nested = Array.isArray(valid.children) ? valid.children : [];
658
592
  nested.forEach(pushChild);
659
593
  return;
@@ -711,6 +645,7 @@ function areNodeAndChildMatching(domNode, child) {
711
645
  if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
712
646
  return domNode.nodeType === 3;
713
647
  }
648
+ if (isCommentVNode(child)) return domNode.nodeType === 8;
714
649
  if (child && typeof child === "object") {
715
650
  if (domNode.nodeType !== 1) return false;
716
651
  const el = domNode;
@@ -796,6 +731,11 @@ function patchElementInPlace(el, vnode, globals, mergeAttributes = false) {
796
731
  return;
797
732
  morphDomDirect(el, vnode.children ?? [], globals);
798
733
  }
734
+ function replaceNode(old, next) {
735
+ if (old.nodeType === 1)
736
+ clearDelegatedEventsDeep(old);
737
+ old.parentNode?.replaceChild(next, old);
738
+ }
799
739
  function morphNode(domNode, child, globals, mergeAttributes = false) {
800
740
  if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
801
741
  const text = String(child);
@@ -804,7 +744,17 @@ function morphNode(domNode, child, globals, mergeAttributes = false) {
804
744
  return domNode;
805
745
  }
806
746
  const next = globals.window.document.createTextNode(text);
807
- domNode.parentNode?.replaceChild(next, domNode);
747
+ replaceNode(domNode, next);
748
+ return next;
749
+ }
750
+ if (isCommentVNode(child)) {
751
+ const data = child.value ?? "";
752
+ if (domNode.nodeType === 8) {
753
+ if (domNode.nodeValue !== data) domNode.nodeValue = data;
754
+ return domNode;
755
+ }
756
+ const next = globals.window.document.createComment(data);
757
+ replaceNode(domNode, next);
808
758
  return next;
809
759
  }
810
760
  if (child && typeof child === "object") {
@@ -825,13 +775,15 @@ function morphNode(domNode, child, globals, mergeAttributes = false) {
825
775
  const created = createDomFromChild(child, globals);
826
776
  const first = Array.isArray(created) ? created[0] : created;
827
777
  if (!first) return null;
828
- el.parentNode?.replaceChild(first, el);
778
+ replaceNode(el, first);
829
779
  handleLifecycleEventsForOnMount(first);
830
780
  return first;
831
781
  }
832
782
  patchElementInPlace(el, child, globals, mergeAttributes);
833
783
  return el;
834
784
  }
785
+ if (domNode.nodeType === 1)
786
+ clearDelegatedEventsDeep(domNode);
835
787
  domNode.parentNode?.removeChild(domNode);
836
788
  return null;
837
789
  }
@@ -886,6 +838,7 @@ function morphDiff(targetRoot, patchItems, globals) {
886
838
  }
887
839
  for (const item of patchItems) {
888
840
  if (typeof item === "string" && item.trim() === "") continue;
841
+ if (isCommentVNode(item)) continue;
889
842
  const key = getVNodeMatchKey(item);
890
843
  if (!key) {
891
844
  throw new Error(
@@ -910,68 +863,130 @@ function morphDiff(targetRoot, patchItems, globals) {
910
863
  }
911
864
  }
912
865
  }
866
+ function moveNode(parent, node, anchor) {
867
+ if (typeof parent.moveBefore === "function") {
868
+ try {
869
+ parent.moveBefore(node, anchor);
870
+ return;
871
+ } catch {
872
+ }
873
+ }
874
+ const doc = node.ownerDocument;
875
+ const active = doc?.activeElement;
876
+ const holdsFocus = !!active && active !== doc.body && node.contains(active);
877
+ let selection;
878
+ if (holdsFocus) {
879
+ try {
880
+ if (active.selectionStart !== null && active.selectionStart !== void 0) {
881
+ selection = [active.selectionStart, active.selectionEnd ?? active.selectionStart, active.selectionDirection ?? "none"];
882
+ }
883
+ } catch {
884
+ selection = void 0;
885
+ }
886
+ }
887
+ parent.insertBefore(node, anchor);
888
+ if (holdsFocus && active.isConnected && doc.activeElement !== active) {
889
+ active.focus({ preventScroll: true });
890
+ if (selection) active.setSelectionRange(...selection);
891
+ }
892
+ }
893
+ function patchByPosition(targetRoot, nextChildren, globals) {
894
+ const live = targetRoot.childNodes;
895
+ if (live.length !== nextChildren.length) return false;
896
+ for (let c = 0; c < nextChildren.length; c++) {
897
+ const node = live[c];
898
+ const child = nextChildren[c];
899
+ if (getVNodeMatchKey(child) !== null || !areNodeAndChildMatching(node, child)) return false;
900
+ if (node.nodeType === 1 && getDomMatchKeys(node).length > 0) return false;
901
+ }
902
+ for (let c = 0; c < nextChildren.length; c++) morphNode(live[c], nextChildren[c], globals);
903
+ return true;
904
+ }
913
905
  function morphDomDirect(parentElement, newVDOM, globals, mode = "replace") {
914
906
  const el = parentElement;
915
907
  const isCustomElement = el.tagName.includes("-");
916
- const targetRoot = el.shadowRoot && !isCustomElement ? el.shadowRoot : parentElement;
908
+ const targetRoot = templateContent(parentElement) ?? (el.shadowRoot && !isCustomElement ? el.shadowRoot : parentElement);
917
909
  const nextChildren = normalizeChildren(newVDOM, mode === "diff");
918
910
  if (mode === "diff") {
919
911
  morphDiff(targetRoot, nextChildren, globals);
920
912
  return;
921
913
  }
914
+ if (patchByPosition(targetRoot, nextChildren, globals)) return;
922
915
  const existing = Array.from(targetRoot.childNodes);
923
916
  const keyedPool = /* @__PURE__ */ new Map();
924
- const nodeKeys = /* @__PURE__ */ new WeakMap();
917
+ const nodeKeys = [];
925
918
  const unkeyedPool = [];
926
- for (const node of existing) {
927
- const keys = getDomMatchKeys(node);
919
+ for (let i = 0; i < existing.length; i++) {
920
+ const keys = getDomMatchKeys(existing[i]);
928
921
  if (keys.length > 0) {
929
- nodeKeys.set(node, keys);
922
+ nodeKeys[i] = keys;
930
923
  let addedToKeyedPool = false;
931
924
  for (const k of keys) {
932
925
  if (!keyedPool.has(k)) {
933
- keyedPool.set(k, node);
926
+ keyedPool.set(k, i);
934
927
  addedToKeyedPool = true;
935
928
  }
936
929
  }
937
930
  if (!addedToKeyedPool) {
938
- unkeyedPool.push(node);
931
+ unkeyedPool.push(i);
939
932
  }
940
933
  } else {
941
- unkeyedPool.push(node);
934
+ unkeyedPool.push(i);
942
935
  }
943
936
  }
944
- const consumeKeyedNode = (node) => {
945
- const keys = nodeKeys.get(node) ?? [];
946
- for (const k of keys) keyedPool.delete(k);
937
+ const consumeKeyedNode = (i) => {
938
+ for (const k of nodeKeys[i] ?? []) {
939
+ if (keyedPool.get(k) === i) keyedPool.delete(k);
940
+ }
947
941
  };
948
942
  const takeUnkeyedMatch = (child) => {
949
- for (let i = 0; i < unkeyedPool.length; i++) {
950
- const candidate = unkeyedPool[i];
951
- if (areNodeAndChildMatching(candidate, child)) {
952
- unkeyedPool.splice(i, 1);
953
- return candidate;
943
+ for (let j = 0; j < unkeyedPool.length; j++) {
944
+ const i = unkeyedPool[j];
945
+ if (areNodeAndChildMatching(existing[i], child)) {
946
+ unkeyedPool.splice(j, 1);
947
+ return i;
954
948
  }
955
949
  }
956
- return void 0;
950
+ return -1;
957
951
  };
958
- let domIndex = 0;
959
- for (const child of nextChildren) {
952
+ const count = nextChildren.length;
953
+ const matched = new Int32Array(count);
954
+ let inOrder = true;
955
+ let previous = -1;
956
+ for (let c = 0; c < count; c++) {
957
+ const child = nextChildren[c];
960
958
  const key = getVNodeMatchKey(child);
961
- let match;
959
+ let i = -1;
962
960
  if (key) {
963
- match = keyedPool.get(key);
964
- if (match) consumeKeyedNode(match);
961
+ const hit = keyedPool.get(key);
962
+ if (hit !== void 0) {
963
+ i = hit;
964
+ consumeKeyedNode(hit);
965
+ }
965
966
  } else {
966
- match = takeUnkeyedMatch(child);
967
+ i = takeUnkeyedMatch(child);
967
968
  }
968
- const anchor = targetRoot.childNodes[domIndex] ?? null;
969
- if (match) {
970
- if (match !== anchor) {
971
- targetRoot.insertBefore(match, anchor);
972
- }
969
+ matched[c] = i;
970
+ if (i >= 0) {
971
+ if (i < previous) inOrder = false;
972
+ previous = i;
973
+ }
974
+ }
975
+ const stays = inOrder ? null : longestIncreasingRun(matched);
976
+ const staying = (c) => matched[c] >= 0 && (stays === null || stays[c] === 1);
977
+ let anchorAt = 0;
978
+ while (anchorAt < count && !staying(anchorAt)) anchorAt++;
979
+ for (let c = 0; c < count; c++) {
980
+ if (anchorAt <= c) {
981
+ anchorAt = c + 1;
982
+ while (anchorAt < count && !staying(anchorAt)) anchorAt++;
983
+ }
984
+ const anchor = anchorAt < count ? existing[matched[anchorAt]] : null;
985
+ const child = nextChildren[c];
986
+ if (matched[c] >= 0) {
987
+ const match = existing[matched[c]];
988
+ if (!staying(c)) moveNode(targetRoot, match, anchor);
973
989
  morphNode(match, child, globals);
974
- domIndex++;
975
990
  continue;
976
991
  }
977
992
  const created = createDomFromChild(child, globals);
@@ -980,12 +995,11 @@ function morphDomDirect(parentElement, newVDOM, globals, mode = "replace") {
980
995
  for (const node of nodes) {
981
996
  targetRoot.insertBefore(node, anchor);
982
997
  handleLifecycleEventsForOnMount(node);
983
- domIndex++;
984
998
  }
985
999
  }
986
1000
  const remaining = /* @__PURE__ */ new Set();
987
- for (const node of unkeyedPool) remaining.add(node);
988
- for (const node of keyedPool.values()) remaining.add(node);
1001
+ for (const i of unkeyedPool) remaining.add(existing[i]);
1002
+ for (const i of keyedPool.values()) remaining.add(existing[i]);
989
1003
  for (const node of remaining) {
990
1004
  if (node.parentNode === targetRoot) {
991
1005
  if (node.nodeType === 1) {
@@ -998,7 +1012,10 @@ function morphDomDirect(parentElement, newVDOM, globals, mode = "replace") {
998
1012
  function replaceDomWithVdom(parentElement, newVDOM, globals) {
999
1013
  const resolvedGlobals = resolveGlobals(parentElement, globals);
1000
1014
  while (parentElement.firstChild) {
1001
- parentElement.removeChild(parentElement.firstChild);
1015
+ const child = parentElement.firstChild;
1016
+ if (child.nodeType === 1)
1017
+ clearDelegatedEventsDeep(child);
1018
+ parentElement.removeChild(child);
1002
1019
  }
1003
1020
  const renderer = getRenderer(resolvedGlobals.window.document);
1004
1021
  const newDom = renderer.createElementOrElements(
@@ -1102,7 +1119,9 @@ const performCrossfade = async (element, updateCallback, duration, easing) => {
1102
1119
  const doc = element.ownerDocument;
1103
1120
  try {
1104
1121
  const rect = element.getBoundingClientRect();
1105
- snapshot.style.cssText = `position:absolute;top:${rect.top}px;left:${rect.left}px;width:${rect.width}px;height:${rect.height}px;opacity:1;transition:opacity ${duration}ms ${easing};z-index:1000;`;
1122
+ const top = rect.top + (doc.defaultView?.scrollY ?? 0);
1123
+ const left = rect.left + (doc.defaultView?.scrollX ?? 0);
1124
+ snapshot.style.cssText = `position:absolute;top:${top}px;left:${left}px;width:${rect.width}px;height:${rect.height}px;opacity:1;transition:opacity ${duration}ms ${easing};z-index:1000;`;
1106
1125
  element.style.opacity = "0";
1107
1126
  element.style.transition = `opacity ${duration}ms ${easing}`;
1108
1127
  doc.body.appendChild(snapshot);
@@ -1178,7 +1197,7 @@ const morph = (el, newContent, options = {}) => {
1178
1197
  const transitionTarget = config.target === "self" ? el : el.parentElement;
1179
1198
  if (!transitionTarget) {
1180
1199
  apply(newContent);
1181
- return;
1200
+ return Promise.resolve();
1182
1201
  }
1183
1202
  const slot2 = { content: newContent };
1184
1203
  inflightTransitions.set(el, slot2);
@@ -1201,4 +1220,144 @@ const morph = (el, newContent, options = {}) => {
1201
1220
  apply(newContent);
1202
1221
  };
1203
1222
 
1204
- export { CAPTURE_ONLY_EVENTS, CLASS_ATTRIBUTE_NAME, DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE, DEFAULT_TRANSITION_CONFIG, FROM_DOM_MARKER, REF_ATTRIBUTE_NAME, XLINK_ATTRIBUTE_NAME, XMLNS_ATTRIBUTE_NAME, applyStyles, areDomNodesEqual, clearDelegatedEvents, clearDelegatedEventsDeep, domNodeToVNode, getMimeType, getRegisteredEventKeys, getRegisteredEventTypes, getRenderer, getTransitionStyles, handleLifecycleEventsForOnMount, htmlStringToVNodes, isHTML, isMarkup, isSVG, morph, nsMap, observeUnmount, parseDOM, parseEventPropName, performTransition, queueCallback, registerDelegatedEvent, removeDelegatedEvent, removeDelegatedEventByKey, renderMarkup, replaceDomWithVdom, resolveGlobals, updateDomWithVdom };
1223
+ const toChildren$1 = (children) => children === void 0 ? [] : Array.isArray(children) ? children.flat(Infinity) : [children];
1224
+ const isVNode = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && "type" in value;
1225
+ const Fragment = (props) => toChildren$1(props?.children);
1226
+ function jsx(type, props, key) {
1227
+ const { children, ...attributes } = props ?? {};
1228
+ const resolvedKey = key ?? attributes.key;
1229
+ if (resolvedKey !== void 0) attributes.key = resolvedKey;
1230
+ if (typeof type === "function") {
1231
+ const result = type(children === void 0 ? attributes : { ...attributes, children });
1232
+ return resolvedKey !== void 0 && isVNode(result) && result.attributes?.key === void 0 ? { ...result, attributes: { ...result.attributes, key: resolvedKey } } : result;
1233
+ }
1234
+ return { type, attributes, children: toChildren$1(children) };
1235
+ }
1236
+ const jsxs = jsx;
1237
+ const jsxDEV = (type, props, key) => jsx(type, props, key);
1238
+ function h(type, props, ...children) {
1239
+ return jsx(type, children.length === 0 ? props : { ...props, children: children.length === 1 ? children[0] : children });
1240
+ }
1241
+
1242
+ const createRef = (state) => ({
1243
+ current: null,
1244
+ state
1245
+ });
1246
+ const isRef = (value) => typeof value === "object" && value !== null && "current" in value;
1247
+
1248
+ const isElement = (value) => typeof value === "object" && value !== null && value.nodeType === 1;
1249
+ const toStores = (store, caller) => {
1250
+ const stores = Array.isArray(store) ? store : [store];
1251
+ stores.forEach((candidate, index) => {
1252
+ if (typeof candidate?.subscribe !== "function") {
1253
+ throw new TypeError(`${caller}: store${Array.isArray(store) ? ` ${index}` : ""} has no subscribe() method`);
1254
+ }
1255
+ });
1256
+ return stores;
1257
+ };
1258
+ const listen = (stores, update) => {
1259
+ const unsubscribes = stores.map((store) => {
1260
+ const result = store.subscribe(() => update());
1261
+ if (typeof result === "function") return result;
1262
+ return () => result?.unsubscribe?.();
1263
+ });
1264
+ return () => {
1265
+ for (const unsubscribe of unsubscribes) unsubscribe();
1266
+ };
1267
+ };
1268
+ const resolveTarget = (target) => {
1269
+ if (isElement(target)) return () => [target];
1270
+ if (isRef(target)) {
1271
+ if (!isElement(target.current)) {
1272
+ throw new TypeError(
1273
+ "reactive: the ref has no element yet; call reactive() after the element is rendered (in onMount or later)"
1274
+ );
1275
+ }
1276
+ return () => isElement(target.current) ? [target.current] : [];
1277
+ }
1278
+ if (target && typeof target.length === "number") {
1279
+ const elements = Array.from(target).filter(isElement);
1280
+ return () => elements;
1281
+ }
1282
+ throw new TypeError("reactive: the target must be an element, a ref or a list of elements");
1283
+ };
1284
+ function reactive(config, target) {
1285
+ const stores = toStores(config?.store, "reactive");
1286
+ if (typeof config.render !== "function") throw new TypeError("reactive: config.render must be a function");
1287
+ const elements = resolveTarget(target);
1288
+ if (config.signal?.aborted || elements().length === 0) return () => {
1289
+ };
1290
+ const update = () => {
1291
+ for (const el of elements()) morph(el, config.render());
1292
+ };
1293
+ update();
1294
+ const unsubscribe = listen(stores, update);
1295
+ let disposed = false;
1296
+ const dispose = () => {
1297
+ if (disposed) return;
1298
+ disposed = true;
1299
+ unsubscribe();
1300
+ config.signal?.removeEventListener("abort", dispose);
1301
+ config.cleanup?.();
1302
+ };
1303
+ config.signal?.addEventListener("abort", dispose, { once: true });
1304
+ return dispose;
1305
+ }
1306
+ const mounted = /* @__PURE__ */ new WeakMap();
1307
+ const toChildren = (content) => {
1308
+ if (typeof content === "string") {
1309
+ if (!/[<&]/.test(content)) return content === "" ? [] : [content];
1310
+ const Parser = globalThis.DOMParser;
1311
+ if (!Parser) {
1312
+ throw new TypeError("Reactive: rendering an HTML string needs a global DOMParser; return JSX/VNodes, or call reactive()");
1313
+ }
1314
+ return htmlStringToVNodes(content, Parser);
1315
+ }
1316
+ return Array.isArray(content) ? content.flat(Infinity) : [content];
1317
+ };
1318
+ function Reactive(props) {
1319
+ const { store, render, cleanup, tag = "div", onMount, onUnmount, children: _children, ...attributes } = props;
1320
+ const stores = toStores(store, "Reactive");
1321
+ if (typeof render !== "function") throw new TypeError("Reactive: the render prop must be a function");
1322
+ return {
1323
+ type: tag,
1324
+ attributes: {
1325
+ ...attributes,
1326
+ // morph runs onMount in a microtask after inserting the wrapper, and again after every patch of it by a
1327
+ // parent re-render: the subscription moves to this render's stores and render function, and one render here
1328
+ // picks up a store change made between the render that built the wrapper and this callback. VERIFIED:
1329
+ // reactive.test.ts ("picks up a store change made before its mount callback ran", "keeps one subscription")
1330
+ onMount: (el) => {
1331
+ mounted.get(el)?.unsubscribe();
1332
+ mounted.set(el, { unsubscribe: listen(stores, () => morph(el, render())), cleanup });
1333
+ morph(el, render());
1334
+ if (typeof onMount === "function") onMount(el);
1335
+ },
1336
+ onUnmount: (el) => {
1337
+ const entry = mounted.get(el);
1338
+ mounted.delete(el);
1339
+ entry?.unsubscribe();
1340
+ entry?.cleanup?.();
1341
+ if (typeof onUnmount === "function") onUnmount(el);
1342
+ }
1343
+ },
1344
+ children: toChildren(render())
1345
+ };
1346
+ }
1347
+ const installReactive = (df$) => {
1348
+ const fn = df$?.fn;
1349
+ if (typeof fn !== "object" || fn === null) {
1350
+ throw new TypeError("installReactive: expected defuss-query's df$ (a df$ with a df$.fn prototype)");
1351
+ }
1352
+ Object.defineProperty(fn, "reactive", {
1353
+ configurable: true,
1354
+ writable: true,
1355
+ value: function(config) {
1356
+ reactive(config, this);
1357
+ return this;
1358
+ }
1359
+ });
1360
+ return df$;
1361
+ };
1362
+
1363
+ export { CAPTURE_ONLY_EVENTS, CLASS_ATTRIBUTE_NAME, COMMENT_TYPE, DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE, DEFAULT_TRANSITION_CONFIG, FROM_DOM_MARKER, Fragment, REF_ATTRIBUTE_NAME, Reactive, XLINK_ATTRIBUTE_NAME, XMLNS_ATTRIBUTE_NAME, applyStyles, areDomNodesEqual, clearDelegatedEvents, clearDelegatedEventsDeep, createRef, domNodeToVNode, getMimeType, getRegisteredEventKeys, getRegisteredEventTypes, getRenderer, getTransitionStyles, h, handleLifecycleEventsForOnMount, htmlStringToVNodes, installReactive, isCommentVNode, isHTML, isMarkup, isRef, isSVG, jsx, jsxDEV, jsxs, morph, nsMap, observeUnmount, onClearDelegatedEvents, parseDOM, parseEventPropName, performTransition, queueCallback, reactive, registerDelegatedEvent, removeDelegatedEvent, removeDelegatedEventByKey, renderMarkup, replaceDomWithVdom, resolveGlobals, templateContent, updateDomWithVdom };