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