ilha 0.14.7 → 0.14.9
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/define.js +1 -1
- package/dist/index.js +42 -36
- package/dist/{mount-rXNnaIWf.js → mount-BzNrfVW4.js} +357 -70
- package/package.json +2 -2
package/dist/define.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as makeFiber, a as interpret, c as handleOwner, d as structuralEqual, f as untrack, g as getFiber, h as closeFiber, i as runSetup, l as instr, m as clearFiberView, n as renderToString, o as atom, p as wrapHandle, r as unsafe, s as batch, t as mount, u as isAtomHandle } from "./mount-
|
|
1
|
+
import { _ as makeFiber, a as interpret, c as handleOwner, d as structuralEqual, f as untrack, g as getFiber, h as closeFiber, i as runSetup, l as instr, m as clearFiberView, n as renderToString, o as atom, p as wrapHandle, r as unsafe, s as batch, t as mount, u as isAtomHandle } from "./mount-BzNrfVW4.js";
|
|
2
2
|
import { d as errorView, g as isString, i as Fragment, p as isFunction, t as h } from "./vnode-M-oJMKcv.js";
|
|
3
3
|
import * as Atom from "effect/reactivity/Atom";
|
|
4
4
|
import * as Effect from "effect/Effect";
|
|
@@ -241,6 +241,18 @@ const watch = Object.assign(watchSource, { once: watchOnce });
|
|
|
241
241
|
const sharedCache = /* @__PURE__ */ new Map();
|
|
242
242
|
const liveRefetchers = /* @__PURE__ */ new Map();
|
|
243
243
|
const cells$1 = /* @__PURE__ */ new WeakMap();
|
|
244
|
+
/** Unmount: stop every client cell of one fiber (all keys it ever used). */
|
|
245
|
+
const releaseCells = (byKey) => {
|
|
246
|
+
for (const [key, entry] of byKey) {
|
|
247
|
+
const c = entry;
|
|
248
|
+
c.alive = false;
|
|
249
|
+
c.ctrl?.abort();
|
|
250
|
+
const live = liveRefetchers.get(key);
|
|
251
|
+
live?.delete(c.onInvalidate);
|
|
252
|
+
if (live && live.size === 0) liveRefetchers.delete(key);
|
|
253
|
+
}
|
|
254
|
+
byKey.clear();
|
|
255
|
+
};
|
|
244
256
|
const entryFor = (key) => sharedCache.get(key);
|
|
245
257
|
/** Drop the cached value for `key` and refetch it in live components. */
|
|
246
258
|
const invalidate = (key) => {
|
|
@@ -325,10 +337,13 @@ const resource = (key, fetcher, opts) => {
|
|
|
325
337
|
}
|
|
326
338
|
let cell = byKey.get(key);
|
|
327
339
|
if (!cell) {
|
|
328
|
-
|
|
340
|
+
const fresh = {
|
|
329
341
|
alive: true,
|
|
330
342
|
ctrl: null,
|
|
331
|
-
|
|
343
|
+
onInvalidate: () => {
|
|
344
|
+
fresh.revalidate();
|
|
345
|
+
},
|
|
346
|
+
revalidate: () => {},
|
|
332
347
|
sink: {
|
|
333
348
|
data,
|
|
334
349
|
error,
|
|
@@ -336,7 +351,14 @@ const resource = (key, fetcher, opts) => {
|
|
|
336
351
|
},
|
|
337
352
|
started: false
|
|
338
353
|
};
|
|
354
|
+
cell = fresh;
|
|
339
355
|
byKey.set(key, cell);
|
|
356
|
+
let live = liveRefetchers.get(key);
|
|
357
|
+
if (!live) {
|
|
358
|
+
live = /* @__PURE__ */ new Set();
|
|
359
|
+
liveRefetchers.set(key, live);
|
|
360
|
+
}
|
|
361
|
+
live.add(cell.onInvalidate);
|
|
340
362
|
}
|
|
341
363
|
cell.sink = {
|
|
342
364
|
data,
|
|
@@ -411,6 +433,9 @@ const resource = (key, fetcher, opts) => {
|
|
|
411
433
|
await start();
|
|
412
434
|
} catch {}
|
|
413
435
|
};
|
|
436
|
+
c.revalidate = () => {
|
|
437
|
+
settleStart();
|
|
438
|
+
};
|
|
414
439
|
if (!c.started) {
|
|
415
440
|
c.started = true;
|
|
416
441
|
const swr = opts?.staleWhileRevalidate ?? true;
|
|
@@ -439,28 +464,9 @@ const resource = (key, fetcher, opts) => {
|
|
|
439
464
|
}
|
|
440
465
|
}
|
|
441
466
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
let live = liveRefetchers.get(key);
|
|
446
|
-
if (!live) {
|
|
447
|
-
live = /* @__PURE__ */ new Set();
|
|
448
|
-
liveRefetchers.set(key, live);
|
|
449
|
-
}
|
|
450
|
-
const onInvalidate = () => {
|
|
451
|
-
settleStart();
|
|
452
|
-
};
|
|
453
|
-
live.add(onInvalidate);
|
|
454
|
-
return () => {
|
|
455
|
-
c.alive = false;
|
|
456
|
-
c.ctrl?.abort();
|
|
457
|
-
const s = liveRefetchers.get(key);
|
|
458
|
-
s?.delete(onInvalidate);
|
|
459
|
-
if (s && s.size === 0) liveRefetchers.delete(key);
|
|
460
|
-
if (fiberCells.get(key) === c) fiberCells.delete(key);
|
|
461
|
-
};
|
|
462
|
-
});
|
|
463
|
-
}
|
|
467
|
+
watch.once(() => () => {
|
|
468
|
+
releaseCells(fiberCells);
|
|
469
|
+
});
|
|
464
470
|
return {
|
|
465
471
|
data,
|
|
466
472
|
error,
|
|
@@ -488,22 +494,22 @@ const connect = ({ cell: c, decode, event, retryBase, url }) => {
|
|
|
488
494
|
for (const sink of c.sinks.values()) sink.latest.set(value);
|
|
489
495
|
for (const push of c.targets) push(value);
|
|
490
496
|
};
|
|
497
|
+
const onMessage = (ev) => {
|
|
498
|
+
const raw = ev.data;
|
|
499
|
+
if (!isString(raw)) return;
|
|
500
|
+
let value;
|
|
501
|
+
try {
|
|
502
|
+
value = decode(raw);
|
|
503
|
+
} catch {
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
emit(value);
|
|
507
|
+
};
|
|
491
508
|
const open = () => {
|
|
492
509
|
if (disposed) return;
|
|
493
510
|
setStatus(c, attempt === 0 ? "connecting" : "retrying");
|
|
494
511
|
const es = new EventSource(url);
|
|
495
512
|
source = es;
|
|
496
|
-
const onMessage = (ev) => {
|
|
497
|
-
const raw = ev.data;
|
|
498
|
-
if (!isString(raw)) return;
|
|
499
|
-
let value;
|
|
500
|
-
try {
|
|
501
|
-
value = decode(raw);
|
|
502
|
-
} catch {
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
emit(value);
|
|
506
|
-
};
|
|
507
513
|
const onOpen = () => {
|
|
508
514
|
attempt = 0;
|
|
509
515
|
setStatus(c, "open");
|
|
@@ -512,39 +512,71 @@ const eventTypeFromProp = (key) => {
|
|
|
512
512
|
return type.length >= 3 ? type : void 0;
|
|
513
513
|
};
|
|
514
514
|
const isEventProp = (key) => eventTypeFromProp(key) !== void 0;
|
|
515
|
+
const dispatch = (el, type, ev) => {
|
|
516
|
+
const fiber = el.__ilhaFiber;
|
|
517
|
+
if (!fiber || fiber.closed) return;
|
|
518
|
+
const fn = el.__ilhaHandlers?.get(type);
|
|
519
|
+
if (!isFunction(fn)) return;
|
|
520
|
+
const out = fn(ev);
|
|
521
|
+
if (Effect$1.isEffect(out)) fiber.run(out);
|
|
522
|
+
};
|
|
523
|
+
/** One native listener per type; it reads the latest handler at dispatch. */
|
|
524
|
+
const listen = (el, type) => {
|
|
525
|
+
el.__ilhaEvents ??= /* @__PURE__ */ new Set();
|
|
526
|
+
if (el.__ilhaEvents.has(type)) return;
|
|
527
|
+
el.__ilhaEvents.add(type);
|
|
528
|
+
el.addEventListener(type, (ev) => {
|
|
529
|
+
dispatch(el, type, ev);
|
|
530
|
+
});
|
|
531
|
+
};
|
|
532
|
+
const bindSsrActions = (el, props, fiber) => {
|
|
533
|
+
const seen = /* @__PURE__ */ new Set();
|
|
534
|
+
for (const key of Object.keys(props)) {
|
|
535
|
+
const type = eventTypeFromProp(key);
|
|
536
|
+
if (!type || seen.has(type)) continue;
|
|
537
|
+
seen.add(type);
|
|
538
|
+
const fn = props[key];
|
|
539
|
+
if (!isFunction(fn)) continue;
|
|
540
|
+
const branded = fn[ACTION_CALL$1];
|
|
541
|
+
const rec = branded?.k ? {
|
|
542
|
+
a: branded.a ?? [],
|
|
543
|
+
k: branded.k
|
|
544
|
+
} : void 0;
|
|
545
|
+
if (!rec) continue;
|
|
546
|
+
const id = `${type}:${fiber.runtime.ssrEventI}`;
|
|
547
|
+
fiber.runtime.ssrEventI += 1;
|
|
548
|
+
fiber.runtime.ssrActions[id] = rec;
|
|
549
|
+
const existing = el.dataset.ilhaOn;
|
|
550
|
+
el.dataset.ilhaOn = existing ? `${existing},${id}` : id;
|
|
551
|
+
}
|
|
552
|
+
};
|
|
515
553
|
const bindEvents = (node, props, fiber) => {
|
|
516
554
|
const el = node;
|
|
517
|
-
|
|
518
|
-
|
|
555
|
+
if (fiber.runtime.ssr) {
|
|
556
|
+
bindSsrActions(el, props, fiber);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
519
560
|
for (const key of Object.keys(props)) {
|
|
520
561
|
const type = eventTypeFromProp(key);
|
|
521
|
-
if (!type)
|
|
522
|
-
if (el.__ilhaEvents.has(type)) continue;
|
|
523
|
-
el.__ilhaEvents.add(type);
|
|
524
|
-
if (fiber.runtime.ssr) {
|
|
525
|
-
const fn = props[key];
|
|
526
|
-
if (!isFunction(fn)) continue;
|
|
527
|
-
const branded = fn[ACTION_CALL$1];
|
|
528
|
-
const rec = branded?.k ? {
|
|
529
|
-
a: branded.a ?? [],
|
|
530
|
-
k: branded.k
|
|
531
|
-
} : void 0;
|
|
532
|
-
if (!rec) continue;
|
|
533
|
-
const id = `${type}:${fiber.runtime.ssrEventI}`;
|
|
534
|
-
fiber.runtime.ssrEventI += 1;
|
|
535
|
-
fiber.runtime.ssrActions[id] = rec;
|
|
536
|
-
const existing = el.dataset.ilhaOn;
|
|
537
|
-
el.dataset.ilhaOn = existing ? `${existing},${id}` : id;
|
|
538
|
-
continue;
|
|
539
|
-
}
|
|
540
|
-
el.addEventListener(type, (ev) => {
|
|
541
|
-
if (fiber.closed) return;
|
|
542
|
-
const fn = el.__ilhaProps?.[key];
|
|
543
|
-
if (!isFunction(fn)) return;
|
|
544
|
-
const out = fn(ev);
|
|
545
|
-
if (Effect$1.isEffect(out)) fiber.run(out);
|
|
546
|
-
});
|
|
562
|
+
if (type && !handlers.has(type)) handlers.set(type, props[key]);
|
|
547
563
|
}
|
|
564
|
+
el.__ilhaHandlers = handlers;
|
|
565
|
+
el.__ilhaFiber = fiber;
|
|
566
|
+
for (const type of handlers.keys()) listen(el, type);
|
|
567
|
+
};
|
|
568
|
+
/**
|
|
569
|
+
* The morph kept `live` in place of the freshly rendered `fresh`: hand the
|
|
570
|
+
* render's handlers to the live node, so closures never go stale and handlers
|
|
571
|
+
* added on a later render still fire.
|
|
572
|
+
*/
|
|
573
|
+
const adoptEvents = (live, fresh) => {
|
|
574
|
+
const from = fresh;
|
|
575
|
+
if (!from.__ilhaFiber) return;
|
|
576
|
+
const to = live;
|
|
577
|
+
to.__ilhaHandlers = from.__ilhaHandlers;
|
|
578
|
+
to.__ilhaFiber = from.__ilhaFiber;
|
|
579
|
+
for (const type of from.__ilhaHandlers?.keys() ?? []) listen(to, type);
|
|
548
580
|
};
|
|
549
581
|
|
|
550
582
|
//#endregion
|
|
@@ -556,14 +588,17 @@ const morphKeyOf = (el) => {
|
|
|
556
588
|
const s = el.getAttribute(SLOT_ATTR);
|
|
557
589
|
return s === null ? null : `s:${s}`;
|
|
558
590
|
};
|
|
591
|
+
/** Whether `data-morph-preserve` on `el` lists `token`. */
|
|
592
|
+
const hasPreserveToken = (el, token) => {
|
|
593
|
+
const custom = el.getAttribute(PRESERVE_ATTR);
|
|
594
|
+
if (custom === null) return false;
|
|
595
|
+
for (const listed of custom.split(/\s+/u)) if (listed === token) return true;
|
|
596
|
+
return false;
|
|
597
|
+
};
|
|
559
598
|
const shouldPreserveMorphAttr = (el, name) => {
|
|
560
599
|
if (name === "value" || name === "checked" || name === "selected") return true;
|
|
561
600
|
if (name === PRESERVE_ATTR) return el.hasAttribute(PRESERVE_ATTR);
|
|
562
|
-
|
|
563
|
-
if (custom !== null) {
|
|
564
|
-
for (const token of custom.split(/\s+/u)) if (token === name) return true;
|
|
565
|
-
}
|
|
566
|
-
return false;
|
|
601
|
+
return hasPreserveToken(el, name);
|
|
567
602
|
};
|
|
568
603
|
const syncAttributes = (from, to) => {
|
|
569
604
|
for (const { name, value } of to.attributes) {
|
|
@@ -578,9 +613,26 @@ const syncAttributes = (from, to) => {
|
|
|
578
613
|
if (!to.hasAttribute(name)) from.removeAttribute(name);
|
|
579
614
|
}
|
|
580
615
|
};
|
|
616
|
+
/** Deepest focused element, looking through open shadow roots. */
|
|
617
|
+
const deepActiveElement = () => {
|
|
618
|
+
let active = document.activeElement;
|
|
619
|
+
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
620
|
+
return active;
|
|
621
|
+
};
|
|
622
|
+
const snapshotRanges = (active) => {
|
|
623
|
+
if (!active.isContentEditable) return null;
|
|
624
|
+
const sel = document.getSelection();
|
|
625
|
+
if (!sel || sel.rangeCount === 0) return null;
|
|
626
|
+
const ranges = [];
|
|
627
|
+
for (let i = 0; i < sel.rangeCount; i += 1) {
|
|
628
|
+
const range = sel.getRangeAt(i);
|
|
629
|
+
if (active.contains(range.startContainer)) ranges.push(range.cloneRange());
|
|
630
|
+
}
|
|
631
|
+
return ranges.length > 0 ? ranges : null;
|
|
632
|
+
};
|
|
581
633
|
const snapshotFocus = () => {
|
|
582
634
|
if (globalThis.document === void 0) return null;
|
|
583
|
-
const active =
|
|
635
|
+
const active = deepActiveElement();
|
|
584
636
|
if (!(active instanceof HTMLElement) || active === document.body) return null;
|
|
585
637
|
let selection = null;
|
|
586
638
|
try {
|
|
@@ -592,13 +644,23 @@ const snapshotFocus = () => {
|
|
|
592
644
|
} catch {}
|
|
593
645
|
return {
|
|
594
646
|
active,
|
|
647
|
+
ranges: snapshotRanges(active),
|
|
595
648
|
selection
|
|
596
649
|
};
|
|
597
650
|
};
|
|
651
|
+
const restoreRanges = (ranges) => {
|
|
652
|
+
const sel = document.getSelection();
|
|
653
|
+
if (!sel || !ranges.every((r) => r.startContainer.isConnected)) return;
|
|
654
|
+
sel.removeAllRanges();
|
|
655
|
+
for (const r of ranges) sel.addRange(r);
|
|
656
|
+
};
|
|
598
657
|
const restoreFocus = (snapshot) => {
|
|
599
658
|
if (!snapshot || !snapshot.active.isConnected) return;
|
|
600
659
|
try {
|
|
601
|
-
if (
|
|
660
|
+
if (deepActiveElement() !== snapshot.active) {
|
|
661
|
+
snapshot.active.focus({ preventScroll: true });
|
|
662
|
+
if (snapshot.ranges) restoreRanges(snapshot.ranges);
|
|
663
|
+
}
|
|
602
664
|
const sel = snapshot.selection;
|
|
603
665
|
if (sel && sel.start !== null) {
|
|
604
666
|
const el = snapshot.active;
|
|
@@ -606,6 +668,122 @@ const restoreFocus = (snapshot) => {
|
|
|
606
668
|
}
|
|
607
669
|
} catch {}
|
|
608
670
|
};
|
|
671
|
+
const STAND_IN_ATTR = "data-ilha-reuse";
|
|
672
|
+
const standIns = /* @__PURE__ */ new WeakMap();
|
|
673
|
+
/** Live nodes with an outstanding stand-in: the morph must not consume them. */
|
|
674
|
+
const claimed = /* @__PURE__ */ new WeakSet();
|
|
675
|
+
/** Placeholder for a connected live node inside a scratch render tree. */
|
|
676
|
+
const standInFor = (live) => {
|
|
677
|
+
const el = document.createElementNS(live.namespaceURI, live.localName);
|
|
678
|
+
for (const name of [SLOT_ATTR, KEY_ATTR]) {
|
|
679
|
+
const v = live.getAttribute(name);
|
|
680
|
+
if (v !== null) el.setAttribute(name, v);
|
|
681
|
+
}
|
|
682
|
+
el.setAttribute(STAND_IN_ATTR, "");
|
|
683
|
+
standIns.set(el, live);
|
|
684
|
+
claimed.add(live);
|
|
685
|
+
return el;
|
|
686
|
+
};
|
|
687
|
+
const liveOf = (node) => {
|
|
688
|
+
const live = standIns.get(node);
|
|
689
|
+
if (!live) return node;
|
|
690
|
+
claimed.delete(live);
|
|
691
|
+
return live;
|
|
692
|
+
};
|
|
693
|
+
/**
|
|
694
|
+
* Insert `node` before `ref`. Connected nodes move with `moveBefore` where the
|
|
695
|
+
* browser has it, so they keep focus, iframe, dialog, and element state.
|
|
696
|
+
*/
|
|
697
|
+
const place = (parent, node, ref) => {
|
|
698
|
+
if (node === ref || node.parentNode === parent && node.nextSibling === ref) return;
|
|
699
|
+
if (node.isConnected && parent.isConnected && parent.moveBefore) try {
|
|
700
|
+
parent.moveBefore(node, ref);
|
|
701
|
+
return;
|
|
702
|
+
} catch {}
|
|
703
|
+
if (ref) ref.before(node);
|
|
704
|
+
else parent.append(node);
|
|
705
|
+
};
|
|
706
|
+
/** Swap stand-ins nested in `node` (now in the document) for live nodes. */
|
|
707
|
+
const resolveNested = (node) => {
|
|
708
|
+
if (!(node instanceof Element) || !node.firstElementChild) return;
|
|
709
|
+
const nested = node.querySelectorAll(`[${STAND_IN_ATTR}]`);
|
|
710
|
+
for (const s of nested) {
|
|
711
|
+
const live = liveOf(s);
|
|
712
|
+
if (live !== s && s.parentNode) {
|
|
713
|
+
place(s.parentNode, live, s);
|
|
714
|
+
s.remove();
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
/**
|
|
719
|
+
* Put a rendered node into the live tree: stand-ins become their live nodes,
|
|
720
|
+
* and stand-ins nested in fresh subtrees resolve once the subtree is attached.
|
|
721
|
+
*/
|
|
722
|
+
const insertRendered = (parent, node, ref) => {
|
|
723
|
+
const live = liveOf(node);
|
|
724
|
+
place(parent, live, ref);
|
|
725
|
+
if (live === node) resolveNested(node);
|
|
726
|
+
};
|
|
727
|
+
/** Longest increasing run of old indexes: those nodes never move. */
|
|
728
|
+
const stableSet = (nodes, oldIndex) => {
|
|
729
|
+
const tails = [];
|
|
730
|
+
const prev = [];
|
|
731
|
+
for (let i = 0; i < nodes.length; i += 1) {
|
|
732
|
+
const node = nodes[i];
|
|
733
|
+
const idx = node ? oldIndex.get(node) : void 0;
|
|
734
|
+
if (idx === void 0) {
|
|
735
|
+
prev.push(-1);
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
let lo = 0;
|
|
739
|
+
let hi = tails.length;
|
|
740
|
+
while (lo < hi) {
|
|
741
|
+
const mid = Math.floor((lo + hi) / 2);
|
|
742
|
+
const tail = nodes[tails[mid] ?? 0];
|
|
743
|
+
if ((tail ? oldIndex.get(tail) ?? 0 : 0) < idx) lo = mid + 1;
|
|
744
|
+
else hi = mid;
|
|
745
|
+
}
|
|
746
|
+
prev.push(lo > 0 ? tails[lo - 1] ?? -1 : -1);
|
|
747
|
+
tails[lo] = i;
|
|
748
|
+
}
|
|
749
|
+
const stable = /* @__PURE__ */ new Set();
|
|
750
|
+
let k = tails.length > 0 ? tails.at(-1) ?? -1 : -1;
|
|
751
|
+
while (k >= 0) {
|
|
752
|
+
const node = nodes[k];
|
|
753
|
+
if (node) stable.add(node);
|
|
754
|
+
k = prev[k] ?? -1;
|
|
755
|
+
}
|
|
756
|
+
return stable;
|
|
757
|
+
};
|
|
758
|
+
/**
|
|
759
|
+
* Make `parent`'s children exactly `nodes` with the fewest moves. Nodes that
|
|
760
|
+
* keep their relative order stay attached; removed nodes leave first.
|
|
761
|
+
*/
|
|
762
|
+
const placeChildren = (parent, rendered) => {
|
|
763
|
+
const focus = snapshotFocus();
|
|
764
|
+
const nodes = rendered.map(liveOf);
|
|
765
|
+
const wanted = new Set(nodes);
|
|
766
|
+
const oldIndex = /* @__PURE__ */ new Map();
|
|
767
|
+
let child = parent.firstChild;
|
|
768
|
+
while (child) {
|
|
769
|
+
const next = child.nextSibling;
|
|
770
|
+
if (wanted.has(child)) oldIndex.set(child, oldIndex.size);
|
|
771
|
+
else child.remove();
|
|
772
|
+
child = next;
|
|
773
|
+
}
|
|
774
|
+
const stable = stableSet(nodes, oldIndex);
|
|
775
|
+
let next = null;
|
|
776
|
+
for (let i = nodes.length - 1; i >= 0; i -= 1) {
|
|
777
|
+
const node = nodes[i];
|
|
778
|
+
if (!node) continue;
|
|
779
|
+
if (!stable.has(node)) {
|
|
780
|
+
place(parent, node, next);
|
|
781
|
+
if (!oldIndex.has(node)) resolveNested(node);
|
|
782
|
+
}
|
|
783
|
+
next = node;
|
|
784
|
+
}
|
|
785
|
+
restoreFocus(focus);
|
|
786
|
+
};
|
|
609
787
|
const buildKeyedIndex = (parent) => {
|
|
610
788
|
let fromKeyed = null;
|
|
611
789
|
for (const child of parent.children) {
|
|
@@ -667,18 +845,43 @@ const morphSelect = (fromEl, toEl, api) => {
|
|
|
667
845
|
if (prev && o.selected !== prev.live) o.selected = prev.live;
|
|
668
846
|
}
|
|
669
847
|
};
|
|
848
|
+
/** Rendered element → the live element the morph kept in its place. */
|
|
849
|
+
const adoptedBy = /* @__PURE__ */ new WeakMap();
|
|
850
|
+
/** The element a rendered element ended up as in the document. */
|
|
851
|
+
const committedElement = (el) => adoptedBy.get(el) ?? el;
|
|
852
|
+
/** `live` stays in the document for `fresh`: move the render's bindings. */
|
|
853
|
+
const adopt = (live, fresh) => {
|
|
854
|
+
adoptedBy.set(fresh, live);
|
|
855
|
+
adoptEvents(live, fresh);
|
|
856
|
+
};
|
|
857
|
+
/**
|
|
858
|
+
* A contenteditable the render leaves empty is uncontrolled: the user's
|
|
859
|
+
* content (and caret) survives, like an uncontrolled textarea.
|
|
860
|
+
*/
|
|
861
|
+
const isUncontrolledEditable = (from, to) => {
|
|
862
|
+
const mode = to.getAttribute("contenteditable");
|
|
863
|
+
return mode !== null && mode !== "false" && !to.hasChildNodes() && from.getAttribute("contenteditable") === mode;
|
|
864
|
+
};
|
|
865
|
+
/** Swap `fromNode` for a rendered node without ever detaching live nodes. */
|
|
866
|
+
const replaceRendered = (fromNode, toNode) => {
|
|
867
|
+
const parent = fromNode.parentNode;
|
|
868
|
+
if (!parent) return;
|
|
869
|
+
insertRendered(parent, toNode, fromNode);
|
|
870
|
+
fromNode.remove();
|
|
871
|
+
};
|
|
670
872
|
const morphElementPair = (fromEl, toEl, api) => {
|
|
671
873
|
if (fromEl.localName !== toEl.localName) {
|
|
672
|
-
fromEl
|
|
874
|
+
replaceRendered(fromEl, toEl);
|
|
673
875
|
return;
|
|
674
876
|
}
|
|
675
877
|
const toSlot = toEl.getAttribute(SLOT_ATTR);
|
|
676
878
|
const fromSlot = fromEl.getAttribute(SLOT_ATTR);
|
|
677
879
|
if (toSlot !== null && fromSlot === toSlot) return;
|
|
678
880
|
if (toSlot !== null) {
|
|
679
|
-
fromEl
|
|
881
|
+
replaceRendered(fromEl, toEl);
|
|
680
882
|
return;
|
|
681
883
|
}
|
|
884
|
+
adopt(fromEl, toEl);
|
|
682
885
|
if (fromEl.localName === "input") {
|
|
683
886
|
morphInput(fromEl, toEl);
|
|
684
887
|
return;
|
|
@@ -687,10 +890,18 @@ const morphElementPair = (fromEl, toEl, api) => {
|
|
|
687
890
|
morphSelect(fromEl, toEl, api);
|
|
688
891
|
return;
|
|
689
892
|
}
|
|
893
|
+
const keepChildren = hasPreserveToken(fromEl, "children") || hasPreserveToken(toEl, "children") || isUncontrolledEditable(fromEl, toEl);
|
|
690
894
|
syncAttributes(fromEl, toEl);
|
|
895
|
+
if (keepChildren) return;
|
|
691
896
|
if (fromEl.localName === "textarea") morphTextarea(fromEl, toEl);
|
|
692
897
|
else api.morphChildren(fromEl, toEl);
|
|
693
898
|
};
|
|
899
|
+
/** Keyed node the new render drops and no stand-in still needs. */
|
|
900
|
+
const isStaleKeyed = (node, toKeys) => {
|
|
901
|
+
if (!(node instanceof Element) || claimed.has(node)) return false;
|
|
902
|
+
const key = morphKeyOf(node);
|
|
903
|
+
return key !== null && !toKeys.has(key);
|
|
904
|
+
};
|
|
694
905
|
const alignKeyedNode = (fromParent, fromNode, toNode, fromKeyed, toKeys) => {
|
|
695
906
|
const toKey = toNode.nodeType === 1 ? morphKeyOf(toNode) : null;
|
|
696
907
|
let current = fromNode;
|
|
@@ -698,9 +909,13 @@ const alignKeyedNode = (fromParent, fromNode, toNode, fromKeyed, toKeys) => {
|
|
|
698
909
|
const match = fromKeyed.get(toKey);
|
|
699
910
|
if (match) {
|
|
700
911
|
fromKeyed.delete(toKey);
|
|
912
|
+
while (current && current !== match && isStaleKeyed(current, toKeys)) {
|
|
913
|
+
const next = current.nextSibling;
|
|
914
|
+
current.remove();
|
|
915
|
+
current = next ?? void 0;
|
|
916
|
+
}
|
|
701
917
|
if (match !== current) {
|
|
702
|
-
|
|
703
|
-
if (!current) fromParent.append(match);
|
|
918
|
+
place(fromParent, match, current ?? null);
|
|
704
919
|
current = match;
|
|
705
920
|
}
|
|
706
921
|
}
|
|
@@ -708,12 +923,31 @@ const alignKeyedNode = (fromParent, fromNode, toNode, fromKeyed, toKeys) => {
|
|
|
708
923
|
if (current instanceof Element) {
|
|
709
924
|
const fromKey = morphKeyOf(current);
|
|
710
925
|
if (fromKey !== null && fromKey !== toKey && toKeys.has(fromKey)) {
|
|
711
|
-
|
|
926
|
+
insertRendered(fromParent, toNode, current);
|
|
712
927
|
return "continue";
|
|
713
928
|
}
|
|
714
929
|
}
|
|
715
930
|
return current;
|
|
716
931
|
};
|
|
932
|
+
const morphChild = ({ api, fromParent, fromNode, toNode }) => {
|
|
933
|
+
if (standIns.has(toNode)) {
|
|
934
|
+
insertRendered(fromParent, toNode, fromNode ?? null);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
if (!fromNode || claimed.has(fromNode)) {
|
|
938
|
+
insertRendered(fromParent, toNode, fromNode ?? null);
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
if (fromNode.nodeType !== toNode.nodeType) {
|
|
942
|
+
replaceRendered(fromNode, toNode);
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
if (fromNode.nodeType === 3 || fromNode.nodeType === 8) {
|
|
946
|
+
if (fromNode.nodeValue !== toNode.nodeValue) fromNode.nodeValue = toNode.nodeValue;
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
if (fromNode.nodeType === 1) morphElementPair(fromNode, toNode, api);
|
|
950
|
+
};
|
|
717
951
|
const api = { morphChildren: (fromParent, toParent) => {
|
|
718
952
|
const toNodes = [...toParent.childNodes];
|
|
719
953
|
const fromKeyed = buildKeyedIndex(fromParent);
|
|
@@ -727,19 +961,12 @@ const api = { morphChildren: (fromParent, toParent) => {
|
|
|
727
961
|
if (aligned === "continue") continue;
|
|
728
962
|
fromNode = aligned;
|
|
729
963
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
continue;
|
|
737
|
-
}
|
|
738
|
-
if (fromNode.nodeType === 3 || fromNode.nodeType === 8) {
|
|
739
|
-
if (fromNode.nodeValue !== toNode.nodeValue) fromNode.nodeValue = toNode.nodeValue;
|
|
740
|
-
continue;
|
|
741
|
-
}
|
|
742
|
-
if (fromNode.nodeType === 1) morphElementPair(fromNode, toNode, api);
|
|
964
|
+
morphChild({
|
|
965
|
+
api,
|
|
966
|
+
fromNode,
|
|
967
|
+
fromParent,
|
|
968
|
+
toNode
|
|
969
|
+
});
|
|
743
970
|
}
|
|
744
971
|
while (fromParent.childNodes.length > toNodes.length) fromParent.lastChild?.remove();
|
|
745
972
|
} };
|
|
@@ -897,6 +1124,21 @@ const sweepComponentSlots = (fiber) => {
|
|
|
897
1124
|
}
|
|
898
1125
|
slots.length = cframe.i;
|
|
899
1126
|
};
|
|
1127
|
+
const sweepIslandSlots = (fiber) => {
|
|
1128
|
+
const frame = fiber.islandFrame;
|
|
1129
|
+
if (!frame) return;
|
|
1130
|
+
const active = new Set(frame.slots.slice(0, frame.i));
|
|
1131
|
+
const keep = [];
|
|
1132
|
+
for (const h of fiber.holes) {
|
|
1133
|
+
if (h.islandSlot && !active.has(h.islandSlot)) {
|
|
1134
|
+
h.dispose();
|
|
1135
|
+
continue;
|
|
1136
|
+
}
|
|
1137
|
+
keep.push(h);
|
|
1138
|
+
}
|
|
1139
|
+
fiber.holes = keep;
|
|
1140
|
+
frame.slots.length = Math.min(frame.slots.length, frame.i);
|
|
1141
|
+
};
|
|
900
1142
|
const findReusableAtomHost = (fiber, atom) => {
|
|
901
1143
|
for (const h of fiber.holes) if (h.atom === atom && h.host?.isConnected && h.holeFiber && !h.holeFiber.closed) return {
|
|
902
1144
|
hole: h.holeFiber,
|
|
@@ -933,14 +1175,28 @@ const isSkippedPropKey = (k) => k === "children" || k === "key" || k === "ref" |
|
|
|
933
1175
|
* keyed reconciliation. Host differences live in `PaintOps`.
|
|
934
1176
|
*/
|
|
935
1177
|
const createPainter = (ops) => {
|
|
1178
|
+
let paintDepth = 0;
|
|
1179
|
+
const pendingRefs = [];
|
|
1180
|
+
const commit = (fn) => {
|
|
1181
|
+
paintDepth += 1;
|
|
1182
|
+
try {
|
|
1183
|
+
fn();
|
|
1184
|
+
} finally {
|
|
1185
|
+
paintDepth -= 1;
|
|
1186
|
+
if (paintDepth === 0) for (const run of pendingRefs.splice(0)) run();
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
936
1189
|
const applyFormControl = (el, key, v, fiber) => {
|
|
937
|
-
const setProp = (x) => ops.setFormControl(el, key, x);
|
|
1190
|
+
const setProp = (x) => ops.setFormControl(ops.committed(el), key, x);
|
|
938
1191
|
if (isAtomHandle(v)) {
|
|
939
1192
|
const memo = el;
|
|
940
1193
|
if (memo.__ilhaVal === v) return;
|
|
941
1194
|
memo.__ilhaVal = v;
|
|
942
1195
|
const unsub = fiber.registry.subscribe(v.atom, setProp, { immediate: true });
|
|
943
|
-
fiber.holes.push({ dispose:
|
|
1196
|
+
fiber.holes.push({ dispose: () => {
|
|
1197
|
+
unsub();
|
|
1198
|
+
if (memo.__ilhaVal === v) memo.__ilhaVal = void 0;
|
|
1199
|
+
} });
|
|
944
1200
|
} else setProp(v);
|
|
945
1201
|
};
|
|
946
1202
|
const trackHole = (parent, hole, extra, meta) => {
|
|
@@ -986,7 +1242,9 @@ const createPainter = (ops) => {
|
|
|
986
1242
|
const { ref } = props;
|
|
987
1243
|
if (isFunction(ref)) {
|
|
988
1244
|
const refFn = ref;
|
|
989
|
-
refFn(ops.asElement(el));
|
|
1245
|
+
const attach = () => refFn(ops.asElement(ops.committed(el)));
|
|
1246
|
+
if (paintDepth > 0) pendingRefs.push(attach);
|
|
1247
|
+
else attach();
|
|
990
1248
|
fiber.holes.push({ dispose: () => refFn(null) });
|
|
991
1249
|
}
|
|
992
1250
|
};
|
|
@@ -1015,7 +1273,7 @@ const createPainter = (ops) => {
|
|
|
1015
1273
|
nodes: [host]
|
|
1016
1274
|
};
|
|
1017
1275
|
},
|
|
1018
|
-
paintHole: (fiber, view) => {
|
|
1276
|
+
paintHole: (fiber, view) => commit(() => {
|
|
1019
1277
|
if (view === KEEP) return;
|
|
1020
1278
|
let frame = fiber.islandFrame;
|
|
1021
1279
|
if (!frame) {
|
|
@@ -1036,15 +1294,18 @@ const createPainter = (ops) => {
|
|
|
1036
1294
|
}
|
|
1037
1295
|
cframe.i = 0;
|
|
1038
1296
|
const list = Array.isArray(view) ? view : null;
|
|
1039
|
-
if (list && list.length > 0 && list.every((v) => isVNode(v) && v.key !== null && v.key !== void 0)) {
|
|
1297
|
+
if (list && list.length > 0 && list.every((v) => isVNode(v) && isFunction(v.type) && v.key !== null && v.key !== void 0)) {
|
|
1040
1298
|
paintFns.keyedPaintHole(fiber, list);
|
|
1299
|
+
sweepComponentSlots(fiber);
|
|
1300
|
+
sweepIslandSlots(fiber);
|
|
1041
1301
|
return;
|
|
1042
1302
|
}
|
|
1043
1303
|
const kept = /* @__PURE__ */ new Set();
|
|
1044
1304
|
for (const s of cframe.slots) if (s && !s.hole.closed) kept.add(s.hole);
|
|
1305
|
+
const keptIslands = new Set(frame.slots);
|
|
1045
1306
|
const keep = [];
|
|
1046
1307
|
for (const h of fiber.holes) {
|
|
1047
|
-
if (h.holeFiber && kept.has(h.holeFiber)) {
|
|
1308
|
+
if (h.holeFiber && kept.has(h.holeFiber) || h.islandSlot && keptIslands.has(h.islandSlot)) {
|
|
1048
1309
|
keep.push(h);
|
|
1049
1310
|
continue;
|
|
1050
1311
|
}
|
|
@@ -1061,11 +1322,12 @@ const createPainter = (ops) => {
|
|
|
1061
1322
|
api.insert(fiber, fresh);
|
|
1062
1323
|
}
|
|
1063
1324
|
sweepComponentSlots(fiber);
|
|
1064
|
-
|
|
1325
|
+
sweepIslandSlots(fiber);
|
|
1326
|
+
})
|
|
1065
1327
|
};
|
|
1066
1328
|
const materializeAtom = (view, fiber) => {
|
|
1067
1329
|
const reused = findReusableAtomHost(fiber, view.atom);
|
|
1068
|
-
if (reused) return [ops.
|
|
1330
|
+
if (reused) return [ops.reuseNode(reused.host)];
|
|
1069
1331
|
const { fiber: hole, nodes } = api.openHole(fiber);
|
|
1070
1332
|
const [host] = nodes;
|
|
1071
1333
|
if (!host) return nodes;
|
|
@@ -1114,9 +1376,16 @@ const createPainter = (ops) => {
|
|
|
1114
1376
|
const existing = frame.slots[i];
|
|
1115
1377
|
if (existing && existing.type === type && existing.host.isConnected && isFunction(existing.updateProps)) {
|
|
1116
1378
|
existing.updateProps(props);
|
|
1117
|
-
return [ops.
|
|
1379
|
+
return [ops.reuseNode(existing.host)];
|
|
1380
|
+
}
|
|
1381
|
+
if (existing) {
|
|
1382
|
+
const idx = fiber.holes.findIndex((h) => h.islandSlot === existing);
|
|
1383
|
+
if (idx === -1) existing.unmount?.();
|
|
1384
|
+
else {
|
|
1385
|
+
const [removed] = fiber.holes.splice(idx, 1);
|
|
1386
|
+
removed?.dispose();
|
|
1387
|
+
}
|
|
1118
1388
|
}
|
|
1119
|
-
existing?.unmount?.();
|
|
1120
1389
|
const tag = isString(type[ISLAND_SLOT_TAG]) ? type[ISLAND_SLOT_TAG] : "div";
|
|
1121
1390
|
const el = ops.createElement(tag);
|
|
1122
1391
|
el.dataset.ilha = "";
|
|
@@ -1136,6 +1405,7 @@ const createPainter = (ops) => {
|
|
|
1136
1405
|
handle?.unmount?.();
|
|
1137
1406
|
if (frame.slots[i] === slot) frame.slots[i] = void 0;
|
|
1138
1407
|
},
|
|
1408
|
+
islandSlot: slot,
|
|
1139
1409
|
keepOnMorph: true
|
|
1140
1410
|
});
|
|
1141
1411
|
}
|
|
@@ -1158,7 +1428,7 @@ const createPainter = (ops) => {
|
|
|
1158
1428
|
if (existing.type === type && !hole.closed) {
|
|
1159
1429
|
hole.propsBox = { current: props };
|
|
1160
1430
|
runSetup(hole, () => run(props));
|
|
1161
|
-
return [ops.
|
|
1431
|
+
return [ops.reuseNode(hole.root)];
|
|
1162
1432
|
}
|
|
1163
1433
|
if (!hole.closed) {
|
|
1164
1434
|
const idx = fiber.holes.findIndex((h) => h.holeFiber === hole);
|
|
@@ -1199,7 +1469,7 @@ const createPainter = (ops) => {
|
|
|
1199
1469
|
if (reuse.propsBox) reuse.propsBox.current = props;
|
|
1200
1470
|
const next = withFiber(fiber, () => run(reuse.propsBox?.current ?? props));
|
|
1201
1471
|
if (next && !isThenable(next) && !isSetupFn(next)) reuse.paint(next);
|
|
1202
|
-
return [ops.
|
|
1472
|
+
return [ops.reuseNode(reuse.root)];
|
|
1203
1473
|
}
|
|
1204
1474
|
if (!k) return materializeUnkeyedComponent(run, type, props, fiber);
|
|
1205
1475
|
const { fiber: khole, nodes: knodes } = api.openHole(fiber);
|
|
@@ -1275,11 +1545,11 @@ const createPainter = (ops) => {
|
|
|
1275
1545
|
nodes.push(...made);
|
|
1276
1546
|
}
|
|
1277
1547
|
fiber.keyedHoles = next;
|
|
1278
|
-
ops.
|
|
1279
|
-
api.insert(fiber, nodes);
|
|
1548
|
+
ops.placeChildren(fiber.root, nodes);
|
|
1280
1549
|
};
|
|
1281
1550
|
return {
|
|
1282
1551
|
applyProps: api.applyProps,
|
|
1552
|
+
commit,
|
|
1283
1553
|
disposeHoles: (fiber, opts) => disposeHoles(fiber, opts),
|
|
1284
1554
|
insert: api.insert,
|
|
1285
1555
|
materialize: api.materialize,
|
|
@@ -1291,7 +1561,7 @@ const createPainter = (ops) => {
|
|
|
1291
1561
|
//#region src/paint.ts
|
|
1292
1562
|
const noopDisconnect = () => {};
|
|
1293
1563
|
const core$1 = createPainter({
|
|
1294
|
-
appendRoot: (root, node) => root
|
|
1564
|
+
appendRoot: (root, node) => insertRendered(root, node, null),
|
|
1295
1565
|
asElement: (el) => el,
|
|
1296
1566
|
asNode: (host) => host,
|
|
1297
1567
|
asRoot: (el) => el,
|
|
@@ -1299,6 +1569,7 @@ const core$1 = createPainter({
|
|
|
1299
1569
|
clearRoot: (root) => {
|
|
1300
1570
|
if (root instanceof Element) root.replaceChildren();
|
|
1301
1571
|
},
|
|
1572
|
+
committed: committedElement,
|
|
1302
1573
|
createElement: (tag, ns) => ns ? document.createElementNS(ns, tag) : document.createElement(tag),
|
|
1303
1574
|
createRaw: (html, parent) => {
|
|
1304
1575
|
const range = document.createRange();
|
|
@@ -1313,6 +1584,10 @@ const core$1 = createPainter({
|
|
|
1313
1584
|
},
|
|
1314
1585
|
createText: (text) => document.createTextNode(text),
|
|
1315
1586
|
disconnect: noopDisconnect,
|
|
1587
|
+
placeChildren: (root, nodes) => {
|
|
1588
|
+
if (root instanceof Element) placeChildren(root, nodes);
|
|
1589
|
+
},
|
|
1590
|
+
reuseNode: (host) => host instanceof Element && host.isConnected ? standInFor(host) : host,
|
|
1316
1591
|
setFormControl: (el, key, v) => {
|
|
1317
1592
|
const node = el;
|
|
1318
1593
|
if (key === "value") {
|
|
@@ -1371,7 +1646,7 @@ const paintHydrate = (fiber, view) => {
|
|
|
1371
1646
|
root: el
|
|
1372
1647
|
};
|
|
1373
1648
|
el.replaceChildren();
|
|
1374
|
-
for (const c of view.children) for (const n of core$1.materialize(c, childFiber)) el
|
|
1649
|
+
for (const c of view.children) for (const n of core$1.materialize(c, childFiber)) insertRendered(el, n, null);
|
|
1375
1650
|
};
|
|
1376
1651
|
const paintMorphLive = (fiber, view) => {
|
|
1377
1652
|
if (!fiber.liveEl) return;
|
|
@@ -1389,7 +1664,7 @@ const paintMorphLive = (fiber, view) => {
|
|
|
1389
1664
|
refreshAllAtomHosts(fiber);
|
|
1390
1665
|
pruneDisconnectedAtomHoles(fiber);
|
|
1391
1666
|
};
|
|
1392
|
-
const
|
|
1667
|
+
const paintRoot = (fiber, view) => {
|
|
1393
1668
|
fiber.islandFrame ??= {
|
|
1394
1669
|
i: 0,
|
|
1395
1670
|
slots: []
|
|
@@ -1420,6 +1695,11 @@ const paint$1 = (fiber, view) => {
|
|
|
1420
1695
|
const first = fiber.root instanceof Element ? fiber.root.firstElementChild : null;
|
|
1421
1696
|
if (first) fiber.liveEl = first;
|
|
1422
1697
|
};
|
|
1698
|
+
const paint$1 = (fiber, view) => {
|
|
1699
|
+
core$1.commit(() => {
|
|
1700
|
+
paintRoot(fiber, view);
|
|
1701
|
+
});
|
|
1702
|
+
};
|
|
1423
1703
|
const paintError$1 = (fiber, e) => {
|
|
1424
1704
|
console.error(e);
|
|
1425
1705
|
paint$1(fiber, errorView(e));
|
|
@@ -1642,6 +1922,7 @@ const ssrOps = {
|
|
|
1642
1922
|
asRoot: (el) => ssrAs(el),
|
|
1643
1923
|
bindEvents: bindSsrEvents,
|
|
1644
1924
|
clearRoot: (root) => ssrAs(root).replaceChildren(),
|
|
1925
|
+
committed: (el) => el,
|
|
1645
1926
|
createElement: createSsrElement,
|
|
1646
1927
|
createRaw: (html, _parent) => [createSsrRaw(html)],
|
|
1647
1928
|
createSlotHost: (slotId) => {
|
|
@@ -1654,6 +1935,12 @@ const ssrOps = {
|
|
|
1654
1935
|
disconnect: (el) => {
|
|
1655
1936
|
el.isConnected = false;
|
|
1656
1937
|
},
|
|
1938
|
+
placeChildren: (root, nodes) => {
|
|
1939
|
+
const host = ssrAs(root);
|
|
1940
|
+
host.replaceChildren();
|
|
1941
|
+
for (const n of nodes) host.append(n);
|
|
1942
|
+
},
|
|
1943
|
+
reuseNode: (host) => ssrAs(host),
|
|
1657
1944
|
setFormControl: (el, key, v) => {
|
|
1658
1945
|
if (key === "value") el.setAttribute("value", String(v ?? ""));
|
|
1659
1946
|
else if (v) el.setAttribute(key, "");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ilha",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.9",
|
|
4
4
|
"description": "Generator-first island UI on Effect",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"typecheck": "tsc -p tsconfig.types.json --noEmit"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
|
-
"@happy-dom/global-registrator": "^20.
|
|
67
|
+
"@happy-dom/global-registrator": "^20.14.5",
|
|
68
68
|
"effect": "^4.0.0-rc.118"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|