defuss 3.4.1 → 3.4.2
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 +904 -1
- package/dist/index.d.ts +16 -0
- package/dist/index.mjs +904 -1
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var dom = require('./dom-BzhVVZDv.cjs');
|
|
4
|
-
var mount = require('./mount-BOeNgYt6.cjs');
|
|
5
4
|
require('defuss-runtime');
|
|
5
|
+
var mount = require('./mount-BOeNgYt6.cjs');
|
|
6
6
|
|
|
7
7
|
const inDevMode = typeof process !== "undefined" && process.env ? process.env.NODE_ENV !== "production" : false;
|
|
8
8
|
|
|
@@ -145,6 +145,902 @@ const createTrans = (i18n) => ({
|
|
|
145
145
|
const Trans = createTrans(i18n);
|
|
146
146
|
const T = Trans;
|
|
147
147
|
|
|
148
|
+
const CAPTURE_ONLY_EVENTS = /* @__PURE__ */ new Set([
|
|
149
|
+
"focus",
|
|
150
|
+
"blur",
|
|
151
|
+
"scroll",
|
|
152
|
+
"mouseenter",
|
|
153
|
+
"mouseleave"
|
|
154
|
+
// Note: focusin/focusout DO bubble, so they're not included here
|
|
155
|
+
]);
|
|
156
|
+
const elementHandlerMap = /* @__PURE__ */ new WeakMap();
|
|
157
|
+
const bubbleDispatched = /* @__PURE__ */ new WeakMap();
|
|
158
|
+
const captureDispatched = /* @__PURE__ */ new WeakMap();
|
|
159
|
+
const activeDispatches = /* @__PURE__ */ new WeakMap();
|
|
160
|
+
const parseEventPropName = (propName) => {
|
|
161
|
+
if (!propName.startsWith("on")) return null;
|
|
162
|
+
const raw = propName.slice(2);
|
|
163
|
+
if (!raw) return null;
|
|
164
|
+
const lower = raw.toLowerCase();
|
|
165
|
+
const isCapture = lower.endsWith("capture");
|
|
166
|
+
const eventType = isCapture ? lower.slice(0, -"capture".length) : lower;
|
|
167
|
+
if (!eventType) return null;
|
|
168
|
+
return { eventType, capture: isCapture };
|
|
169
|
+
};
|
|
170
|
+
const getOrCreateElementHandlers = (el) => {
|
|
171
|
+
const existing = elementHandlerMap.get(el);
|
|
172
|
+
if (existing) return existing;
|
|
173
|
+
const created = /* @__PURE__ */ new Map();
|
|
174
|
+
elementHandlerMap.set(el, created);
|
|
175
|
+
return created;
|
|
176
|
+
};
|
|
177
|
+
const getEventPath = (event) => {
|
|
178
|
+
const composedPath = event.composedPath?.();
|
|
179
|
+
if (composedPath && composedPath.length > 0) return composedPath;
|
|
180
|
+
const path = [];
|
|
181
|
+
let node = event.target;
|
|
182
|
+
while (node) {
|
|
183
|
+
path.push(node);
|
|
184
|
+
const maybeNode = node;
|
|
185
|
+
if (typeof maybeNode === "object" && maybeNode && "parentNode" in maybeNode) {
|
|
186
|
+
node = maybeNode.parentNode;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
const doc = event.target?.ownerDocument;
|
|
192
|
+
if (doc && path[path.length - 1] !== doc) path.push(doc);
|
|
193
|
+
const win = doc?.defaultView;
|
|
194
|
+
if (win && path[path.length - 1] !== win) path.push(win);
|
|
195
|
+
return path;
|
|
196
|
+
};
|
|
197
|
+
const createPhaseHandler = (eventType, phase) => {
|
|
198
|
+
const dispatched = phase === "capture" ? captureDispatched : bubbleDispatched;
|
|
199
|
+
return (event) => {
|
|
200
|
+
const path = getEventPath(event).filter(
|
|
201
|
+
(t) => typeof t === "object" && t !== null && t.nodeType === 1
|
|
202
|
+
);
|
|
203
|
+
const ordered = phase === "capture" ? [...path].reverse() : path;
|
|
204
|
+
for (const target of ordered) {
|
|
205
|
+
const handlersByEvent = elementHandlerMap.get(target);
|
|
206
|
+
if (!handlersByEvent) continue;
|
|
207
|
+
const entry = handlersByEvent.get(eventType);
|
|
208
|
+
if (!entry) continue;
|
|
209
|
+
let targets = dispatched.get(event);
|
|
210
|
+
if (targets?.has(target)) continue;
|
|
211
|
+
if (!targets) {
|
|
212
|
+
targets = /* @__PURE__ */ new WeakSet();
|
|
213
|
+
dispatched.set(event, targets);
|
|
214
|
+
}
|
|
215
|
+
targets.add(target);
|
|
216
|
+
const dispatchKey = `${eventType}:${phase}`;
|
|
217
|
+
let activeSet = activeDispatches.get(target);
|
|
218
|
+
if (activeSet?.has(dispatchKey)) continue;
|
|
219
|
+
if (!activeSet) {
|
|
220
|
+
activeSet = /* @__PURE__ */ new Set();
|
|
221
|
+
activeDispatches.set(target, activeSet);
|
|
222
|
+
}
|
|
223
|
+
activeSet.add(dispatchKey);
|
|
224
|
+
try {
|
|
225
|
+
if (phase === "capture") {
|
|
226
|
+
if (entry.capture) {
|
|
227
|
+
entry.capture.call(target, event);
|
|
228
|
+
if (event.cancelBubble)
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
if (entry.captureSet) {
|
|
232
|
+
for (const handler of entry.captureSet) {
|
|
233
|
+
handler.call(target, event);
|
|
234
|
+
if (event.cancelBubble)
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
if (entry.bubble) {
|
|
240
|
+
entry.bubble.call(target, event);
|
|
241
|
+
if (event.cancelBubble)
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (entry.bubbleSet) {
|
|
245
|
+
for (const handler of entry.bubbleSet) {
|
|
246
|
+
handler.call(target, event);
|
|
247
|
+
if (event.cancelBubble)
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
} finally {
|
|
253
|
+
activeSet.delete(dispatchKey);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
};
|
|
258
|
+
const installedRootListeners = /* @__PURE__ */ new WeakMap();
|
|
259
|
+
const ensureRootListener = (root, eventType) => {
|
|
260
|
+
const installed = installedRootListeners.get(root) ?? /* @__PURE__ */ new Set();
|
|
261
|
+
installedRootListeners.set(root, installed);
|
|
262
|
+
const captureKey = `${eventType}:capture`;
|
|
263
|
+
if (!installed.has(captureKey)) {
|
|
264
|
+
root.addEventListener(
|
|
265
|
+
eventType,
|
|
266
|
+
createPhaseHandler(eventType, "capture"),
|
|
267
|
+
true
|
|
268
|
+
);
|
|
269
|
+
installed.add(captureKey);
|
|
270
|
+
}
|
|
271
|
+
const bubbleKey = `${eventType}:bubble`;
|
|
272
|
+
if (!installed.has(bubbleKey)) {
|
|
273
|
+
root.addEventListener(
|
|
274
|
+
eventType,
|
|
275
|
+
createPhaseHandler(eventType, "bubble"),
|
|
276
|
+
false
|
|
277
|
+
);
|
|
278
|
+
installed.add(bubbleKey);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
const getEventRoot = (element) => {
|
|
282
|
+
const root = element.getRootNode();
|
|
283
|
+
if (root && root.nodeType === 9) {
|
|
284
|
+
return root;
|
|
285
|
+
}
|
|
286
|
+
if (root && root.nodeType === 11 && "host" in root) {
|
|
287
|
+
return root;
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
};
|
|
291
|
+
const registerDelegatedEvent = (element, eventType, handler, options = {}) => {
|
|
292
|
+
const root = getEventRoot(element);
|
|
293
|
+
const capture = options.capture || CAPTURE_ONLY_EVENTS.has(eventType);
|
|
294
|
+
if (root) {
|
|
295
|
+
ensureRootListener(root, eventType);
|
|
296
|
+
} else if (element.ownerDocument) {
|
|
297
|
+
ensureRootListener(element.ownerDocument, eventType);
|
|
298
|
+
} else {
|
|
299
|
+
element.addEventListener(eventType, handler, capture);
|
|
300
|
+
}
|
|
301
|
+
const byEvent = getOrCreateElementHandlers(element);
|
|
302
|
+
const entry = byEvent.get(eventType) ?? {};
|
|
303
|
+
byEvent.set(eventType, entry);
|
|
304
|
+
if (options.multi) {
|
|
305
|
+
if (capture) {
|
|
306
|
+
if (!entry.captureSet) entry.captureSet = /* @__PURE__ */ new Set();
|
|
307
|
+
entry.captureSet.add(handler);
|
|
308
|
+
} else {
|
|
309
|
+
if (!entry.bubbleSet) entry.bubbleSet = /* @__PURE__ */ new Set();
|
|
310
|
+
entry.bubbleSet.add(handler);
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
if (capture) {
|
|
314
|
+
entry.capture = handler;
|
|
315
|
+
} else {
|
|
316
|
+
entry.bubble = handler;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
const clearDelegatedEvents = (target) => {
|
|
321
|
+
const byEvent = elementHandlerMap.get(target);
|
|
322
|
+
if (!byEvent) return;
|
|
323
|
+
byEvent.clear();
|
|
324
|
+
};
|
|
325
|
+
const clearDelegatedEventsDeep = (root) => {
|
|
326
|
+
clearDelegatedEvents(root);
|
|
327
|
+
const doc = root.ownerDocument;
|
|
328
|
+
if (!doc) return;
|
|
329
|
+
const walker = doc.createTreeWalker(
|
|
330
|
+
root,
|
|
331
|
+
1
|
|
332
|
+
/* NodeFilter.SHOW_ELEMENT */
|
|
333
|
+
);
|
|
334
|
+
let node = walker.nextNode();
|
|
335
|
+
while (node) {
|
|
336
|
+
clearDelegatedEvents(node);
|
|
337
|
+
node = walker.nextNode();
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
const getRegisteredEventKeys = (element) => {
|
|
341
|
+
const byEvent = elementHandlerMap.get(element);
|
|
342
|
+
if (!byEvent) return /* @__PURE__ */ new Set();
|
|
343
|
+
const keys = /* @__PURE__ */ new Set();
|
|
344
|
+
for (const [eventType, entry] of byEvent) {
|
|
345
|
+
if (entry.bubble || entry.bubbleSet?.size) keys.add(`${eventType}:bubble`);
|
|
346
|
+
if (entry.capture || entry.captureSet?.size)
|
|
347
|
+
keys.add(`${eventType}:capture`);
|
|
348
|
+
}
|
|
349
|
+
return keys;
|
|
350
|
+
};
|
|
351
|
+
const removeDelegatedEventByKey = (element, eventType, phase) => {
|
|
352
|
+
const byEvent = elementHandlerMap.get(element);
|
|
353
|
+
if (!byEvent) return;
|
|
354
|
+
const entry = byEvent.get(eventType);
|
|
355
|
+
if (!entry) return;
|
|
356
|
+
if (phase === "capture") {
|
|
357
|
+
entry.capture = void 0;
|
|
358
|
+
entry.captureSet = void 0;
|
|
359
|
+
} else {
|
|
360
|
+
entry.bubble = void 0;
|
|
361
|
+
entry.bubbleSet = void 0;
|
|
362
|
+
}
|
|
363
|
+
const isEmpty = !entry.capture && !entry.bubble && (!entry.captureSet || entry.captureSet.size === 0) && (!entry.bubbleSet || entry.bubbleSet.size === 0);
|
|
364
|
+
if (isEmpty) byEvent.delete(eventType);
|
|
365
|
+
};
|
|
366
|
+
const queueCallback = (cb) => (...args) => queueMicrotask(() => cb(...args));
|
|
367
|
+
const CLASS_ATTRIBUTE_NAME = "class";
|
|
368
|
+
const XLINK_ATTRIBUTE_NAME = "xlink";
|
|
369
|
+
const XMLNS_ATTRIBUTE_NAME = "xmlns";
|
|
370
|
+
const REF_ATTRIBUTE_NAME = "ref";
|
|
371
|
+
const DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE = "dangerouslySetInnerHTML";
|
|
372
|
+
const nsMap = {
|
|
373
|
+
[XMLNS_ATTRIBUTE_NAME]: "http://www.w3.org/2000/xmlns/",
|
|
374
|
+
[XLINK_ATTRIBUTE_NAME]: "http://www.w3.org/1999/xlink",
|
|
375
|
+
svg: "http://www.w3.org/2000/svg"
|
|
376
|
+
};
|
|
377
|
+
const isJSXComment = (node) => (
|
|
378
|
+
/* v8 ignore next */
|
|
379
|
+
node && typeof node === "object" && !node.attributes && !node.type && !node.children
|
|
380
|
+
);
|
|
381
|
+
const filterComments = (children) => children.filter((child) => !isJSXComment(child));
|
|
382
|
+
const createInPlaceErrorMessageVNode = (error) => ({
|
|
383
|
+
type: "p",
|
|
384
|
+
attributes: {},
|
|
385
|
+
children: [`FATAL ERROR: ${error?.message || error}`]
|
|
386
|
+
});
|
|
387
|
+
const jsx = (type, attributes, key, sourceInfo) => {
|
|
388
|
+
attributes = { ...attributes };
|
|
389
|
+
if (typeof key !== "undefined") {
|
|
390
|
+
attributes.key = key;
|
|
391
|
+
}
|
|
392
|
+
let children = (attributes?.children != null ? [].concat(
|
|
393
|
+
attributes.children
|
|
394
|
+
) : []).filter((c) => c !== null && c !== void 0 && typeof c !== "boolean");
|
|
395
|
+
delete attributes?.children;
|
|
396
|
+
children = filterComments(
|
|
397
|
+
// Implementation to flatten virtual node children structures like:
|
|
398
|
+
// [<p>1</p>, [<p>2</p>,<p>3</p>]] to: [<p>1</p>,<p>2</p>,<p>3</p>]
|
|
399
|
+
[].concat.apply(
|
|
400
|
+
[],
|
|
401
|
+
children
|
|
402
|
+
)
|
|
403
|
+
);
|
|
404
|
+
if (type === "fragment") {
|
|
405
|
+
return filterComments(children);
|
|
406
|
+
}
|
|
407
|
+
if (typeof type === "function" && type.constructor.name === "AsyncFunction") {
|
|
408
|
+
const fallback = attributes?.fallback;
|
|
409
|
+
const propsForAsyncFn = { ...attributes };
|
|
410
|
+
delete propsForAsyncFn.fallback;
|
|
411
|
+
const onMount = async (containerEl) => {
|
|
412
|
+
try {
|
|
413
|
+
const resolvedVNode = await type({
|
|
414
|
+
...propsForAsyncFn,
|
|
415
|
+
children
|
|
416
|
+
});
|
|
417
|
+
if (containerEl && resolvedVNode) {
|
|
418
|
+
const globals = {
|
|
419
|
+
window: containerEl.ownerDocument?.defaultView ?? globalThis
|
|
420
|
+
};
|
|
421
|
+
updateDomWithVdom(containerEl, resolvedVNode, globals);
|
|
422
|
+
}
|
|
423
|
+
} catch (error) {
|
|
424
|
+
console.error("[defuss] Async component error:", error);
|
|
425
|
+
if (containerEl) {
|
|
426
|
+
containerEl.textContent = `Error: ${error?.message || error}`;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
return {
|
|
431
|
+
type: "div",
|
|
432
|
+
attributes: {
|
|
433
|
+
key,
|
|
434
|
+
onMount
|
|
435
|
+
},
|
|
436
|
+
children: fallback ? [fallback] : [],
|
|
437
|
+
sourceInfo
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
if (typeof type === "function" && type.constructor.name !== "AsyncFunction") {
|
|
441
|
+
try {
|
|
442
|
+
const rendered = type({
|
|
443
|
+
children,
|
|
444
|
+
...attributes
|
|
445
|
+
});
|
|
446
|
+
if (rendered && typeof rendered === "object" && !Array.isArray(rendered) && sourceInfo) {
|
|
447
|
+
if (!rendered.componentProps) {
|
|
448
|
+
rendered.componentProps = { ...attributes };
|
|
449
|
+
} else {
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
if (typeof key !== "undefined" && rendered && typeof rendered === "object") {
|
|
453
|
+
if ("attributes" in rendered) {
|
|
454
|
+
rendered.attributes = {
|
|
455
|
+
...rendered.attributes,
|
|
456
|
+
key
|
|
457
|
+
};
|
|
458
|
+
} else if (Array.isArray(rendered) && rendered.length === 1) {
|
|
459
|
+
const only = rendered[0];
|
|
460
|
+
if (only && typeof only === "object" && "attributes" in only) {
|
|
461
|
+
only.attributes = {
|
|
462
|
+
...only.attributes,
|
|
463
|
+
key
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return rendered;
|
|
469
|
+
} catch (error) {
|
|
470
|
+
if (typeof error === "string") {
|
|
471
|
+
error = `[JsxError] in ${type.name}: ${error}`;
|
|
472
|
+
} else if (error instanceof Error) {
|
|
473
|
+
error.message = `[JsxError] in ${type.name}: ${error.message}`;
|
|
474
|
+
}
|
|
475
|
+
return createInPlaceErrorMessageVNode(error);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return {
|
|
479
|
+
type,
|
|
480
|
+
attributes,
|
|
481
|
+
children,
|
|
482
|
+
sourceInfo
|
|
483
|
+
};
|
|
484
|
+
};
|
|
485
|
+
const observeUnmount = (domNode, onUnmount) => {
|
|
486
|
+
if (!domNode || typeof onUnmount !== "function") {
|
|
487
|
+
throw new Error(
|
|
488
|
+
"Invalid arguments. Ensure domNode and onUnmount are valid."
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
if (typeof MutationObserver === "undefined") {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
let parentNode = domNode.parentNode;
|
|
495
|
+
if (!parentNode) {
|
|
496
|
+
throw new Error("The provided domNode does not have a parentNode.");
|
|
497
|
+
}
|
|
498
|
+
const observer = new MutationObserver((mutationsList) => {
|
|
499
|
+
for (const mutation of mutationsList) {
|
|
500
|
+
if (mutation.removedNodes.length > 0) {
|
|
501
|
+
for (const removedNode of mutation.removedNodes) {
|
|
502
|
+
if (removedNode === domNode) {
|
|
503
|
+
queueMicrotask(() => {
|
|
504
|
+
if (!domNode.isConnected) {
|
|
505
|
+
onUnmount();
|
|
506
|
+
observer.disconnect();
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
const newParent = domNode.parentNode;
|
|
510
|
+
if (newParent && newParent !== parentNode) {
|
|
511
|
+
parentNode = newParent;
|
|
512
|
+
observer.disconnect();
|
|
513
|
+
observer.observe(parentNode, { childList: true });
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
observer.observe(parentNode, { childList: true });
|
|
523
|
+
};
|
|
524
|
+
const handleLifecycleEventsForOnMount = (newEl) => {
|
|
525
|
+
if (typeof newEl?.$onMount === "function") {
|
|
526
|
+
newEl.$onMount(newEl);
|
|
527
|
+
newEl.$onMount = null;
|
|
528
|
+
}
|
|
529
|
+
if (typeof newEl?.$onUnmount === "function") {
|
|
530
|
+
observeUnmount(newEl, newEl.$onUnmount);
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
const getRenderer = (document2) => {
|
|
534
|
+
const renderer = {
|
|
535
|
+
hasElNamespace: (domElement) => domElement.namespaceURI === nsMap.svg,
|
|
536
|
+
hasSvgNamespace: (parentElement, type) => renderer.hasElNamespace(parentElement) && type !== "STYLE" && type !== "SCRIPT",
|
|
537
|
+
createElementOrElements: (virtualNode, parentDomElement) => {
|
|
538
|
+
if (Array.isArray(virtualNode)) {
|
|
539
|
+
return renderer.createChildElements(virtualNode, parentDomElement);
|
|
540
|
+
}
|
|
541
|
+
if (typeof virtualNode !== "undefined") {
|
|
542
|
+
return renderer.createElement(virtualNode, parentDomElement);
|
|
543
|
+
}
|
|
544
|
+
return renderer.createTextNode("", parentDomElement);
|
|
545
|
+
},
|
|
546
|
+
createElement: (virtualNode, parentDomElement) => {
|
|
547
|
+
let newEl;
|
|
548
|
+
try {
|
|
549
|
+
if (typeof virtualNode === "function" && virtualNode.constructor.name === "AsyncFunction") {
|
|
550
|
+
newEl = document2.createElement("div");
|
|
551
|
+
} else if (typeof virtualNode === "object" && virtualNode !== null && "type" in virtualNode) {
|
|
552
|
+
const vNode = virtualNode;
|
|
553
|
+
if (typeof vNode.type === "function") {
|
|
554
|
+
newEl = document2.createElement("div");
|
|
555
|
+
newEl.innerText = `FATAL ERROR: ${vNode.type._error}`;
|
|
556
|
+
} else if (
|
|
557
|
+
// SVG support
|
|
558
|
+
typeof vNode.type === "string" && vNode.type.toUpperCase() === "SVG" || parentDomElement && renderer.hasSvgNamespace(
|
|
559
|
+
parentDomElement,
|
|
560
|
+
typeof vNode.type === "string" ? vNode.type.toUpperCase() : ""
|
|
561
|
+
)
|
|
562
|
+
) {
|
|
563
|
+
newEl = document2.createElementNS(nsMap.svg, vNode.type);
|
|
564
|
+
} else {
|
|
565
|
+
newEl = document2.createElement(vNode.type);
|
|
566
|
+
}
|
|
567
|
+
if (vNode.attributes) {
|
|
568
|
+
renderer.setAttributes(vNode, newEl);
|
|
569
|
+
if (vNode.attributes.dangerouslySetInnerHTML) {
|
|
570
|
+
newEl.innerHTML = vNode.attributes.dangerouslySetInnerHTML.__html;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if (vNode.children && !vNode.attributes?.dangerouslySetInnerHTML) {
|
|
574
|
+
renderer.createChildElements(vNode.children, newEl);
|
|
575
|
+
}
|
|
576
|
+
} else {
|
|
577
|
+
if (typeof virtualNode === "string" || typeof virtualNode === "number") {
|
|
578
|
+
newEl = document2.createElement(String(virtualNode));
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (newEl && parentDomElement) {
|
|
582
|
+
parentDomElement.appendChild(newEl);
|
|
583
|
+
handleLifecycleEventsForOnMount(newEl);
|
|
584
|
+
}
|
|
585
|
+
} catch (e) {
|
|
586
|
+
console.error(
|
|
587
|
+
"Fatal error! Error happend while rendering the VDOM!",
|
|
588
|
+
e,
|
|
589
|
+
virtualNode
|
|
590
|
+
);
|
|
591
|
+
throw e;
|
|
592
|
+
}
|
|
593
|
+
return newEl;
|
|
594
|
+
},
|
|
595
|
+
createTextNode: (text, domElement) => {
|
|
596
|
+
const node = document2.createTextNode(text.toString());
|
|
597
|
+
if (domElement) {
|
|
598
|
+
domElement.appendChild(node);
|
|
599
|
+
}
|
|
600
|
+
return node;
|
|
601
|
+
},
|
|
602
|
+
createChildElements: (virtualChildren, domElement) => {
|
|
603
|
+
const children = [];
|
|
604
|
+
for (let i = 0; i < virtualChildren.length; i++) {
|
|
605
|
+
const virtualChild = virtualChildren[i];
|
|
606
|
+
if (typeof virtualChild === "boolean") {
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
if (virtualChild === null || typeof virtualChild !== "object" && typeof virtualChild !== "function") {
|
|
610
|
+
children.push(
|
|
611
|
+
renderer.createTextNode(
|
|
612
|
+
(typeof virtualChild === "undefined" || virtualChild === null ? "" : virtualChild).toString(),
|
|
613
|
+
domElement
|
|
614
|
+
)
|
|
615
|
+
);
|
|
616
|
+
} else {
|
|
617
|
+
children.push(
|
|
618
|
+
renderer.createElement(virtualChild, domElement)
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return children;
|
|
623
|
+
},
|
|
624
|
+
setAttribute: (name, value, domElement) => {
|
|
625
|
+
if (typeof value === "undefined") return;
|
|
626
|
+
if (name === DANGEROUSLY_SET_INNER_HTML_ATTRIBUTE) return;
|
|
627
|
+
if (name === "key") {
|
|
628
|
+
domElement._defussKey = String(value);
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
if (name === REF_ATTRIBUTE_NAME && typeof value !== "function") {
|
|
632
|
+
const ref = value;
|
|
633
|
+
ref.current = domElement;
|
|
634
|
+
domElement._defussRef = value;
|
|
635
|
+
domElement.$onUnmount = queueCallback(() => {
|
|
636
|
+
});
|
|
637
|
+
if (domElement.parentNode) {
|
|
638
|
+
observeUnmount(domElement, domElement.$onUnmount);
|
|
639
|
+
} else {
|
|
640
|
+
queueMicrotask(() => {
|
|
641
|
+
if (domElement.parentNode) {
|
|
642
|
+
observeUnmount(domElement, domElement.$onUnmount);
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
const parsed = parseEventPropName(name);
|
|
649
|
+
if (parsed && typeof value === "function") {
|
|
650
|
+
const { eventType, capture } = parsed;
|
|
651
|
+
if (eventType === "mount") {
|
|
652
|
+
domElement.$onMount = queueCallback(value);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
if (eventType === "unmount") {
|
|
656
|
+
if (domElement.$onUnmount) {
|
|
657
|
+
const existingUnmount = domElement.$onUnmount;
|
|
658
|
+
domElement.$onUnmount = () => {
|
|
659
|
+
existingUnmount();
|
|
660
|
+
value();
|
|
661
|
+
};
|
|
662
|
+
} else {
|
|
663
|
+
domElement.$onUnmount = queueCallback(value);
|
|
664
|
+
}
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
registerDelegatedEvent(
|
|
668
|
+
domElement,
|
|
669
|
+
eventType,
|
|
670
|
+
value,
|
|
671
|
+
{ capture }
|
|
672
|
+
);
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
if (name === "className") {
|
|
676
|
+
name = CLASS_ATTRIBUTE_NAME;
|
|
677
|
+
}
|
|
678
|
+
if (name === CLASS_ATTRIBUTE_NAME && Array.isArray(value)) {
|
|
679
|
+
value = value.filter((val) => !!val).join(" ");
|
|
680
|
+
}
|
|
681
|
+
const nsEndIndex = name.match(/[A-Z]/)?.index;
|
|
682
|
+
if (renderer.hasElNamespace(domElement) && nsEndIndex) {
|
|
683
|
+
const ns = name.substring(0, nsEndIndex).toLowerCase();
|
|
684
|
+
const attrName = name.substring(nsEndIndex, name.length).toLowerCase();
|
|
685
|
+
const namespace = nsMap[ns] || null;
|
|
686
|
+
domElement.setAttributeNS(
|
|
687
|
+
namespace,
|
|
688
|
+
ns === XLINK_ATTRIBUTE_NAME || ns === XMLNS_ATTRIBUTE_NAME ? `${ns}:${attrName}` : name,
|
|
689
|
+
String(value)
|
|
690
|
+
);
|
|
691
|
+
} else if (name === "style" && typeof value !== "string") {
|
|
692
|
+
const styleObj = value;
|
|
693
|
+
for (const prop of Object.keys(styleObj)) {
|
|
694
|
+
domElement.style[prop] = String(
|
|
695
|
+
styleObj[prop]
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
} else if (typeof value === "boolean") {
|
|
699
|
+
domElement[name] = value;
|
|
700
|
+
if (value) {
|
|
701
|
+
domElement.setAttribute(name, "");
|
|
702
|
+
} else {
|
|
703
|
+
domElement.removeAttribute(name);
|
|
704
|
+
}
|
|
705
|
+
} else if (
|
|
706
|
+
// Controlled input props: use property assignment for live value,
|
|
707
|
+
// AND setAttribute so SSG serialization (w3c-xmlserializer) includes it
|
|
708
|
+
(name === "value" || name === "checked" || name === "selectedIndex") && (domElement.nodeName === "INPUT" || domElement.nodeName === "TEXTAREA" || domElement.nodeName === "SELECT")
|
|
709
|
+
) {
|
|
710
|
+
domElement[name] = value;
|
|
711
|
+
if (name === "checked") {
|
|
712
|
+
if (value) {
|
|
713
|
+
domElement.setAttribute("checked", "");
|
|
714
|
+
} else {
|
|
715
|
+
domElement.removeAttribute("checked");
|
|
716
|
+
}
|
|
717
|
+
} else if (name === "value") {
|
|
718
|
+
domElement.setAttribute("value", String(value));
|
|
719
|
+
}
|
|
720
|
+
} else {
|
|
721
|
+
domElement.setAttribute(name, String(value));
|
|
722
|
+
}
|
|
723
|
+
},
|
|
724
|
+
setAttributes: (virtualNode, domElement) => {
|
|
725
|
+
const attrNames = Object.keys(virtualNode.attributes);
|
|
726
|
+
for (let i = 0; i < attrNames.length; i++) {
|
|
727
|
+
renderer.setAttribute(
|
|
728
|
+
attrNames[i],
|
|
729
|
+
virtualNode.attributes[attrNames[i]],
|
|
730
|
+
domElement
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
return renderer;
|
|
736
|
+
};
|
|
737
|
+
function isTextLike(value) {
|
|
738
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
739
|
+
}
|
|
740
|
+
function isVNode(value) {
|
|
741
|
+
return Boolean(
|
|
742
|
+
value && typeof value === "object" && "type" in value
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
function toValidChild(child) {
|
|
746
|
+
if (child == null) return child;
|
|
747
|
+
if (isTextLike(child)) return child;
|
|
748
|
+
if (isVNode(child)) return child;
|
|
749
|
+
return void 0;
|
|
750
|
+
}
|
|
751
|
+
function normalizeChildren(input) {
|
|
752
|
+
const raw = [];
|
|
753
|
+
const pushChild = (child) => {
|
|
754
|
+
if (Array.isArray(child)) {
|
|
755
|
+
child.forEach(pushChild);
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
const valid = toValidChild(child);
|
|
759
|
+
if (typeof valid === "undefined") return;
|
|
760
|
+
if (isVNode(valid) && (valid.type === "fragment" || valid.type === "Fragment")) {
|
|
761
|
+
const nested = Array.isArray(valid.children) ? valid.children : [];
|
|
762
|
+
nested.forEach(pushChild);
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (valid === null || typeof valid === "undefined" || typeof valid === "boolean")
|
|
766
|
+
return;
|
|
767
|
+
raw.push(valid);
|
|
768
|
+
};
|
|
769
|
+
pushChild(input);
|
|
770
|
+
const fused = [];
|
|
771
|
+
let buffer = null;
|
|
772
|
+
const flush = () => {
|
|
773
|
+
if (buffer !== null && buffer.length > 0) fused.push(buffer);
|
|
774
|
+
buffer = null;
|
|
775
|
+
};
|
|
776
|
+
for (const child of raw) {
|
|
777
|
+
if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
|
|
778
|
+
buffer = (buffer ?? "") + String(child);
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
flush();
|
|
782
|
+
fused.push(child);
|
|
783
|
+
}
|
|
784
|
+
flush();
|
|
785
|
+
return fused;
|
|
786
|
+
}
|
|
787
|
+
function getVNodeMatchKey(child) {
|
|
788
|
+
if (!child || typeof child !== "object") return null;
|
|
789
|
+
const key = child.attributes?.key;
|
|
790
|
+
if (typeof key === "string" || typeof key === "number")
|
|
791
|
+
return `k:${String(key)}`;
|
|
792
|
+
const id = child.attributes?.id;
|
|
793
|
+
if (typeof id === "string" && id.length > 0) return `id:${id}`;
|
|
794
|
+
return null;
|
|
795
|
+
}
|
|
796
|
+
function getDomMatchKeys(node) {
|
|
797
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return [];
|
|
798
|
+
const el = node;
|
|
799
|
+
const keys = [];
|
|
800
|
+
const internalKey = el._defussKey;
|
|
801
|
+
if (internalKey) keys.push(`k:${internalKey}`);
|
|
802
|
+
const attrKey = el.getAttribute("key");
|
|
803
|
+
if (attrKey) keys.push(`k:${attrKey}`);
|
|
804
|
+
const id = el.id;
|
|
805
|
+
if (id) keys.push(`id:${id}`);
|
|
806
|
+
return keys;
|
|
807
|
+
}
|
|
808
|
+
function areNodeAndChildMatching(domNode, child) {
|
|
809
|
+
if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
|
|
810
|
+
return domNode.nodeType === Node.TEXT_NODE;
|
|
811
|
+
}
|
|
812
|
+
if (child && typeof child === "object") {
|
|
813
|
+
if (domNode.nodeType !== Node.ELEMENT_NODE) return false;
|
|
814
|
+
const el = domNode;
|
|
815
|
+
const oldTag = el.tagName.toLowerCase();
|
|
816
|
+
const newTag = typeof child.type === "string" ? child.type.toLowerCase() : "";
|
|
817
|
+
if (!newTag || oldTag !== newTag) return false;
|
|
818
|
+
return true;
|
|
819
|
+
}
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
function createDomFromChild(child, globals) {
|
|
823
|
+
const renderer = getRenderer(globals.window.document);
|
|
824
|
+
if (child == null) return void 0;
|
|
825
|
+
if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
|
|
826
|
+
return [globals.window.document.createTextNode(String(child))];
|
|
827
|
+
}
|
|
828
|
+
const created = renderer.createElementOrElements(child);
|
|
829
|
+
if (!created) return void 0;
|
|
830
|
+
const nodes = Array.isArray(created) ? created : [created];
|
|
831
|
+
return nodes.filter(Boolean);
|
|
832
|
+
}
|
|
833
|
+
function shouldPreserveFormStateAttribute(el, attrName, vnode) {
|
|
834
|
+
const tag = el.tagName.toLowerCase();
|
|
835
|
+
const hasExplicit = Object.prototype.hasOwnProperty.call(
|
|
836
|
+
vnode.attributes ?? {},
|
|
837
|
+
attrName
|
|
838
|
+
);
|
|
839
|
+
if (hasExplicit) return false;
|
|
840
|
+
if (tag === "input") return attrName === "value" || attrName === "checked";
|
|
841
|
+
if (tag === "textarea") return attrName === "value";
|
|
842
|
+
if (tag === "select") return attrName === "value";
|
|
843
|
+
return false;
|
|
844
|
+
}
|
|
845
|
+
function patchElementInPlace(el, vnode, globals) {
|
|
846
|
+
const renderer = getRenderer(globals.window.document);
|
|
847
|
+
const existingAttrs = Array.from(el.attributes);
|
|
848
|
+
const nextAttrs = vnode.attributes ?? {};
|
|
849
|
+
for (const attr of existingAttrs) {
|
|
850
|
+
const { name } = attr;
|
|
851
|
+
if (name === "key") continue;
|
|
852
|
+
if (name.startsWith("on")) continue;
|
|
853
|
+
if (name === "class" && (Object.prototype.hasOwnProperty.call(nextAttrs, "class") || Object.prototype.hasOwnProperty.call(nextAttrs, "className"))) {
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
856
|
+
if (!Object.prototype.hasOwnProperty.call(nextAttrs, name)) {
|
|
857
|
+
if (shouldPreserveFormStateAttribute(el, name, vnode)) continue;
|
|
858
|
+
el.removeAttribute(name);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
const registeredKeys = getRegisteredEventKeys(el);
|
|
862
|
+
const nextEventKeys = /* @__PURE__ */ new Set();
|
|
863
|
+
for (const propName of Object.keys(nextAttrs)) {
|
|
864
|
+
const parsed = parseEventPropName(propName);
|
|
865
|
+
if (parsed) {
|
|
866
|
+
const phase = parsed.capture ? "capture" : "bubble";
|
|
867
|
+
nextEventKeys.add(`${parsed.eventType}:${phase}`);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
for (const key of registeredKeys) {
|
|
871
|
+
if (!nextEventKeys.has(key)) {
|
|
872
|
+
const [eventType, phase] = key.split(":");
|
|
873
|
+
removeDelegatedEventByKey(
|
|
874
|
+
el,
|
|
875
|
+
eventType,
|
|
876
|
+
phase
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
renderer.setAttributes(vnode, el);
|
|
881
|
+
handleLifecycleEventsForOnMount(el);
|
|
882
|
+
const d = vnode.attributes?.dangerouslySetInnerHTML;
|
|
883
|
+
if (d && typeof d === "object" && typeof d.__html === "string") {
|
|
884
|
+
el.innerHTML = d.__html;
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
const tag = el.tagName.toLowerCase();
|
|
888
|
+
if (tag === "textarea") {
|
|
889
|
+
const isControlled = Object.prototype.hasOwnProperty.call(
|
|
890
|
+
nextAttrs,
|
|
891
|
+
"value"
|
|
892
|
+
);
|
|
893
|
+
const isActive = el.ownerDocument?.activeElement === el;
|
|
894
|
+
if (isActive && !isControlled) return;
|
|
895
|
+
}
|
|
896
|
+
morphDomDirect(el, vnode.children ?? [], globals);
|
|
897
|
+
}
|
|
898
|
+
function morphNode(domNode, child, globals) {
|
|
899
|
+
if (typeof child === "string" || typeof child === "number" || typeof child === "boolean") {
|
|
900
|
+
const text = String(child);
|
|
901
|
+
if (domNode.nodeType === Node.TEXT_NODE) {
|
|
902
|
+
if (domNode.nodeValue !== text) domNode.nodeValue = text;
|
|
903
|
+
return domNode;
|
|
904
|
+
}
|
|
905
|
+
const next = globals.window.document.createTextNode(text);
|
|
906
|
+
domNode.parentNode?.replaceChild(next, domNode);
|
|
907
|
+
return next;
|
|
908
|
+
}
|
|
909
|
+
if (child && typeof child === "object") {
|
|
910
|
+
const newType = typeof child.type === "string" ? child.type : null;
|
|
911
|
+
if (!newType) return domNode;
|
|
912
|
+
if (domNode.nodeType !== Node.ELEMENT_NODE) {
|
|
913
|
+
const created = createDomFromChild(child, globals);
|
|
914
|
+
const first = Array.isArray(created) ? created[0] : created;
|
|
915
|
+
if (!first) return null;
|
|
916
|
+
domNode.parentNode?.replaceChild(first, domNode);
|
|
917
|
+
handleLifecycleEventsForOnMount(first);
|
|
918
|
+
return first;
|
|
919
|
+
}
|
|
920
|
+
const el = domNode;
|
|
921
|
+
const oldTag = el.tagName.toLowerCase();
|
|
922
|
+
const newTag = newType.toLowerCase();
|
|
923
|
+
if (oldTag !== newTag) {
|
|
924
|
+
const created = createDomFromChild(child, globals);
|
|
925
|
+
const first = Array.isArray(created) ? created[0] : created;
|
|
926
|
+
if (!first) return null;
|
|
927
|
+
el.parentNode?.replaceChild(first, el);
|
|
928
|
+
handleLifecycleEventsForOnMount(first);
|
|
929
|
+
return first;
|
|
930
|
+
}
|
|
931
|
+
patchElementInPlace(el, child, globals);
|
|
932
|
+
return el;
|
|
933
|
+
}
|
|
934
|
+
domNode.parentNode?.removeChild(domNode);
|
|
935
|
+
return null;
|
|
936
|
+
}
|
|
937
|
+
const renderingNodes = /* @__PURE__ */ new WeakSet();
|
|
938
|
+
const pendingMorphs = /* @__PURE__ */ new Map();
|
|
939
|
+
function isAncestorRendering(el) {
|
|
940
|
+
let current = el.parentElement;
|
|
941
|
+
while (current) {
|
|
942
|
+
if (renderingNodes.has(current)) return true;
|
|
943
|
+
current = current.parentElement;
|
|
944
|
+
}
|
|
945
|
+
return false;
|
|
946
|
+
}
|
|
947
|
+
function flushPendingMorphs() {
|
|
948
|
+
if (pendingMorphs.size === 0) return;
|
|
949
|
+
const snapshot = [...pendingMorphs.entries()];
|
|
950
|
+
pendingMorphs.clear();
|
|
951
|
+
for (const [el, { vdom, globals }] of snapshot) {
|
|
952
|
+
if (!el.isConnected) continue;
|
|
953
|
+
updateDomWithVdom(el, vdom, globals);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
function updateDomWithVdom(parentElement, newVDOM, globals) {
|
|
957
|
+
if (renderingNodes.has(parentElement) || isAncestorRendering(parentElement)) {
|
|
958
|
+
pendingMorphs.set(parentElement, { vdom: newVDOM, globals });
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
renderingNodes.add(parentElement);
|
|
962
|
+
try {
|
|
963
|
+
morphDomDirect(parentElement, newVDOM, globals);
|
|
964
|
+
} finally {
|
|
965
|
+
renderingNodes.delete(parentElement);
|
|
966
|
+
}
|
|
967
|
+
flushPendingMorphs();
|
|
968
|
+
}
|
|
969
|
+
function morphDomDirect(parentElement, newVDOM, globals) {
|
|
970
|
+
const el = parentElement;
|
|
971
|
+
const isCustomElement = el.tagName.includes("-");
|
|
972
|
+
const targetRoot = el.shadowRoot && !isCustomElement ? el.shadowRoot : parentElement;
|
|
973
|
+
const nextChildren = normalizeChildren(newVDOM);
|
|
974
|
+
const existing = Array.from(targetRoot.childNodes);
|
|
975
|
+
const keyedPool = /* @__PURE__ */ new Map();
|
|
976
|
+
const nodeKeys = /* @__PURE__ */ new WeakMap();
|
|
977
|
+
const unkeyedPool = [];
|
|
978
|
+
for (const node of existing) {
|
|
979
|
+
const keys = getDomMatchKeys(node);
|
|
980
|
+
if (keys.length > 0) {
|
|
981
|
+
nodeKeys.set(node, keys);
|
|
982
|
+
for (const k of keys) {
|
|
983
|
+
if (!keyedPool.has(k)) keyedPool.set(k, node);
|
|
984
|
+
}
|
|
985
|
+
} else {
|
|
986
|
+
unkeyedPool.push(node);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
const consumeKeyedNode = (node) => {
|
|
990
|
+
const keys = nodeKeys.get(node) ?? [];
|
|
991
|
+
for (const k of keys) keyedPool.delete(k);
|
|
992
|
+
};
|
|
993
|
+
const takeUnkeyedMatch = (child) => {
|
|
994
|
+
for (let i = 0; i < unkeyedPool.length; i++) {
|
|
995
|
+
const candidate = unkeyedPool[i];
|
|
996
|
+
if (areNodeAndChildMatching(candidate, child)) {
|
|
997
|
+
unkeyedPool.splice(i, 1);
|
|
998
|
+
return candidate;
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
return void 0;
|
|
1002
|
+
};
|
|
1003
|
+
let domIndex = 0;
|
|
1004
|
+
for (const child of nextChildren) {
|
|
1005
|
+
const key = getVNodeMatchKey(child);
|
|
1006
|
+
let match;
|
|
1007
|
+
if (key) {
|
|
1008
|
+
match = keyedPool.get(key);
|
|
1009
|
+
if (match) consumeKeyedNode(match);
|
|
1010
|
+
} else {
|
|
1011
|
+
match = takeUnkeyedMatch(child);
|
|
1012
|
+
}
|
|
1013
|
+
const anchor = targetRoot.childNodes[domIndex] ?? null;
|
|
1014
|
+
if (match) {
|
|
1015
|
+
if (match !== anchor) {
|
|
1016
|
+
targetRoot.insertBefore(match, anchor);
|
|
1017
|
+
}
|
|
1018
|
+
morphNode(match, child, globals);
|
|
1019
|
+
domIndex++;
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
const created = createDomFromChild(child, globals);
|
|
1023
|
+
if (!created || Array.isArray(created) && created.length === 0) continue;
|
|
1024
|
+
const nodes = Array.isArray(created) ? created : [created];
|
|
1025
|
+
for (const node of nodes) {
|
|
1026
|
+
targetRoot.insertBefore(node, anchor);
|
|
1027
|
+
handleLifecycleEventsForOnMount(node);
|
|
1028
|
+
domIndex++;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
const remaining = /* @__PURE__ */ new Set();
|
|
1032
|
+
for (const node of unkeyedPool) remaining.add(node);
|
|
1033
|
+
for (const node of keyedPool.values()) remaining.add(node);
|
|
1034
|
+
for (const node of remaining) {
|
|
1035
|
+
if (node.parentNode === targetRoot) {
|
|
1036
|
+
if (node instanceof HTMLElement) {
|
|
1037
|
+
clearDelegatedEventsDeep(node);
|
|
1038
|
+
}
|
|
1039
|
+
targetRoot.removeChild(node);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
|
|
148
1044
|
const tokenizePath = (path) => {
|
|
149
1045
|
const paramNameRegexp = /:([a-zA-Z0-9_]+)|\*/g;
|
|
150
1046
|
const groups = {};
|
|
@@ -314,6 +1210,9 @@ const setupRouter = (config = {
|
|
|
314
1210
|
{ invokeHandler: false },
|
|
315
1211
|
windowImpl
|
|
316
1212
|
);
|
|
1213
|
+
if (req.match) {
|
|
1214
|
+
state.currentRequest = req;
|
|
1215
|
+
}
|
|
317
1216
|
return req;
|
|
318
1217
|
},
|
|
319
1218
|
resolve(pathname) {
|
|
@@ -427,6 +1326,7 @@ const Route = ({
|
|
|
427
1326
|
path,
|
|
428
1327
|
exact,
|
|
429
1328
|
children,
|
|
1329
|
+
component: Component,
|
|
430
1330
|
router = Router
|
|
431
1331
|
}) => {
|
|
432
1332
|
router.add({
|
|
@@ -435,6 +1335,9 @@ const Route = ({
|
|
|
435
1335
|
});
|
|
436
1336
|
const req = router.match(path);
|
|
437
1337
|
if (!req.match) return null;
|
|
1338
|
+
if (Component) {
|
|
1339
|
+
return /* @__PURE__ */ jsx(Component, {});
|
|
1340
|
+
}
|
|
438
1341
|
return Array.isArray(children) ? children[0] : children || null;
|
|
439
1342
|
};
|
|
440
1343
|
|