@expressive/dom 0.3.0 → 0.5.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.js CHANGED
@@ -1,11 +1,11 @@
1
- import { a as untrack, c as dispose, d as claim$1, f as release, h as transition, i as track, l as enter, m as settle$1, n as latest, o as call, p as schedule, r as same, s as commit, u as afterFlush } from "./chunk-hot-BAqPvKEQ.js";
2
- import { a as createElement, i as childrenOf, n as PORTAL, o as isVNode, r as Portal, s as vnode, t as Fragment } from "./chunk-vnode-BG1Cv8F9.js";
1
+ import { a as untrack, c as enter, d as release, f as schedule, i as track, l as afterFlush, m as transition, n as latest, o as call, p as settle$1, r as same, s as dispose, u as claim$1 } from "./chunk-hot-Bj-g5ynf.js";
2
+ import { a as createElement, i as childrenOf, n as PORTAL, o as isVNode, r as Portal, s as vnode, t as Fragment } from "./chunk-vnode-wpCWQ_Zg.js";
3
3
  import "./jsx-runtime.js";
4
- import { Component, Context, State, has, map } from "@expressive/mvc";
4
+ import { Component, Context, Model, has, map, unbind } from "@expressive/mvc";
5
5
  import { watch } from "@expressive/mvc/observable";
6
- import { Fragment as Fragment$1, compose } from "@expressive/mvc/jsx-runtime";
6
+ import { Fragment as Fragment$1 } from "@expressive/mvc/jsx-runtime";
7
7
 
8
- //#region src/css.ts
8
+ //#region src/style/css.ts
9
9
  const unitless = /* @__PURE__ */ new Map();
10
10
  let probe;
11
11
  /**
@@ -58,7 +58,7 @@ const css = {
58
58
  };
59
59
 
60
60
  //#endregion
61
- //#region src/appearance-protocol.ts
61
+ //#region src/style/protocol.ts
62
62
  const registrations = /* @__PURE__ */ new WeakMap();
63
63
  const tokens = /* @__PURE__ */ new WeakMap();
64
64
  let root;
@@ -105,7 +105,7 @@ function appearanceToken(value) {
105
105
  }
106
106
 
107
107
  //#endregion
108
- //#region src/appearance.ts
108
+ //#region src/style/appearance.ts
109
109
  const bases = /* @__PURE__ */ new WeakMap();
110
110
  const chains = /* @__PURE__ */ new WeakMap();
111
111
  const contexts = /* @__PURE__ */ new WeakMap();
@@ -332,7 +332,7 @@ function isObject(value) {
332
332
  }
333
333
 
334
334
  //#endregion
335
- //#region src/declarations.ts
335
+ //#region src/style/declarations.ts
336
336
  function applyDeclarations(style, declarations, previous = {}) {
337
337
  const target = style;
338
338
  for (const key of Object.keys({
@@ -351,7 +351,7 @@ function applyDeclarations(style, declarations, previous = {}) {
351
351
  }
352
352
 
353
353
  //#endregion
354
- //#region src/stylesheet.ts
354
+ //#region src/style/stylesheet.ts
355
355
  const sheets = /* @__PURE__ */ new WeakMap();
356
356
  function style(type, rules) {
357
357
  style$1(type, rules);
@@ -403,31 +403,7 @@ function serialize(document, declarations) {
403
403
  }
404
404
 
405
405
  //#endregion
406
- //#region src/loader.ts
407
- const LOADS = /* @__PURE__ */ new WeakMap();
408
- function resolve(type, props, run) {
409
- const load = LOADS.get(type);
410
- if (load?.resolved) return vnode(load.resolved, props);
411
- if (load?.failed) {
412
- LOADS.delete(type);
413
- throw load.failed.error;
414
- }
415
- if (load) throw load.pending;
416
- const output = run();
417
- if (!output || typeof output.then != "function") return output;
418
- const next = {};
419
- LOADS.set(type, next);
420
- throw next.pending = output.then((module) => {
421
- const component = typeof module == "function" ? module : module?.default;
422
- if (typeof component == "function") next.resolved = component;
423
- else next.failed = { error: /* @__PURE__ */ new Error("Loader resolved no component.") };
424
- }, (error) => {
425
- next.failed = { error };
426
- });
427
- }
428
-
429
- //#endregion
430
- //#region src/commits.ts
406
+ //#region src/render/commits.ts
431
407
  const DETACHED = /* @__PURE__ */ new WeakMap();
432
408
  let batch;
433
409
  /** Run `run` once `fiber` is on the page: now, after the current batch, or when its detached root attaches. */
@@ -468,63 +444,7 @@ function deliver(entry) {
468
444
  }
469
445
 
470
446
  //#endregion
471
- //#region src/render.ts
472
- const roots = /* @__PURE__ */ new WeakMap();
473
- const SVG = "http://www.w3.org/2000/svg";
474
- const dirty = /* @__PURE__ */ new Set();
475
- const stashes = /* @__PURE__ */ new WeakMap();
476
- const CONTROLS = ["checked", "value"];
477
- const ENUMERATED = [
478
- "contentEditable",
479
- "contenteditable",
480
- "draggable",
481
- "spellcheck"
482
- ];
483
- const ALIASES = {
484
- autoFocus: "autofocus",
485
- contentEditable: "contenteditable",
486
- htmlFor: "for"
487
- };
488
- const focusing = [];
489
- const controlled = /* @__PURE__ */ new WeakMap();
490
- const restoring = /* @__PURE__ */ new WeakSet();
491
- let passiveRender = false;
492
- let holding;
493
- let depth = 0;
494
- let settling = false;
495
- let rendering;
496
- let touched = false;
497
- const observed = /* @__PURE__ */ new WeakMap();
498
- const tickets = /* @__PURE__ */ new WeakMap();
499
- function render(node, container) {
500
- roots.get(container)?.();
501
- container.replaceChildren();
502
- const context = new Context(Context.root);
503
- const fiber = range("fragment", container, null, context);
504
- try {
505
- pass(() => {
506
- const appearanceContext = appearanceRoot();
507
- reconcile(fiber, node, context, void 0, appearanceContext ? {
508
- context: appearanceContext,
509
- entries: []
510
- } : void 0);
511
- });
512
- } catch (error) {
513
- unmountFiber(fiber);
514
- context.pop();
515
- throw error;
516
- }
517
- let active = true;
518
- const unmount = () => {
519
- if (!active) return;
520
- active = false;
521
- unmountFiber(fiber);
522
- context.pop();
523
- roots.delete(container);
524
- };
525
- roots.set(container, unmount);
526
- return unmount;
527
- }
447
+ //#region src/render/fiber.ts
528
448
  function range(kind, parent, before, context) {
529
449
  const start = document.createComment(kind);
530
450
  const end = document.createComment(`/${kind}`);
@@ -538,33 +458,104 @@ function range(kind, parent, before, context) {
538
458
  children: []
539
459
  };
540
460
  }
541
- function makeScope(kind, context, update) {
461
+ function makeScope(context, update) {
542
462
  return {
543
463
  active: true,
544
- childContext: context,
545
464
  context,
546
- kind,
547
465
  subscriptions: [],
548
- update,
549
- useIndex: 0,
550
- uses: []
466
+ update
551
467
  };
552
468
  }
553
- function park(fiber) {
554
- move(fiber, fragment(), null);
469
+ function moveRange(start, end, target) {
470
+ let node = start;
471
+ while (node) {
472
+ const next = node.nextSibling;
473
+ target.appendChild(node);
474
+ if (node === end) break;
475
+ node = next;
476
+ }
555
477
  }
556
- function complete(fiber, work) {
557
- try {
558
- work();
559
- } catch (error) {
560
- if (holding && error === holding.thrown) {
561
- park(fiber);
562
- holding.fiber = fiber;
563
- } else unmountFiber(fiber);
564
- throw error;
478
+ function move(fiber, parent, before) {
479
+ if (fiber.start.parentNode === parent && fiber.end.nextSibling === before) return;
480
+ let node = fiber.start;
481
+ while (node) {
482
+ const next = node.nextSibling;
483
+ parent.insertBefore(node, before);
484
+ if (node === fiber.end) break;
485
+ node = next;
565
486
  }
566
- return fiber;
567
487
  }
488
+ function removeRange(start, end) {
489
+ let node = start;
490
+ while (true) {
491
+ const next = node.nextSibling;
492
+ node.remove();
493
+ if (node === end) break;
494
+ node = next;
495
+ }
496
+ }
497
+
498
+ //#endregion
499
+ //#region src/render/collection.ts
500
+ function mountCollection(value, parent, before, context, boundary, appearance) {
501
+ const fiber = range("collection", parent, before, context);
502
+ fiber.source = value;
503
+ fiber.value = value;
504
+ fiber.boundary = boundary;
505
+ fiber.appearance = appearance;
506
+ fiber.scope = makeScope(context, (passive) => runCollection(fiber, passive));
507
+ let first = true;
508
+ fiber.release = watch(value, (current) => {
509
+ fiber.value = current;
510
+ if (!first && fiber.scope?.active) schedule(fiber.scope);
511
+ first = false;
512
+ }, void 0, transition);
513
+ return complete(fiber, () => {
514
+ runCollection(fiber, passiveRender);
515
+ });
516
+ }
517
+ function runCollection(fiber, passive) {
518
+ attempt(fiber, passive, () => {
519
+ const value = fiber.value;
520
+ return value instanceof map.Managed ? [...value.values()] : [...value];
521
+ });
522
+ }
523
+ function patchCollection(fiber, appearance) {
524
+ if (fiber.appearance === appearance) return;
525
+ fiber.appearance = appearance;
526
+ runCollection(fiber, passiveRender);
527
+ }
528
+ function isCollection(value) {
529
+ return value instanceof has.List || value instanceof has.Pool || value instanceof map.Managed;
530
+ }
531
+
532
+ //#endregion
533
+ //#region src/node/loader.ts
534
+ const LOADS = /* @__PURE__ */ new WeakMap();
535
+ function resolve(type, props, run) {
536
+ const load = LOADS.get(type);
537
+ if (load?.resolved) return vnode(load.resolved, props);
538
+ if (load?.failed) {
539
+ LOADS.delete(type);
540
+ throw load.failed.error;
541
+ }
542
+ if (load) throw load.pending;
543
+ const output = run();
544
+ if (!output || typeof output.then != "function") return output;
545
+ const next = {};
546
+ LOADS.set(type, next);
547
+ throw next.pending = output.then((module) => {
548
+ const component = typeof module == "function" ? module : module?.default;
549
+ if (typeof component == "function") next.resolved = component;
550
+ else next.failed = { error: /* @__PURE__ */ new Error("Loader resolved no component.") };
551
+ }, (error) => {
552
+ next.failed = { error };
553
+ });
554
+ }
555
+
556
+ //#endregion
557
+ //#region src/style/claim.ts
558
+ const tickets = /* @__PURE__ */ new WeakMap();
568
559
  function componentProps(type, props, appearance) {
569
560
  const context = appearance?.context;
570
561
  if (!context || typeof type != "function") return {
@@ -588,256 +579,100 @@ function componentProps(type, props, appearance) {
588
579
  }
589
580
  };
590
581
  }
591
- function mount(value, parent, before, context, boundary, appearance) {
592
- if (typeof value == "string" || typeof value == "number" || typeof value == "bigint") {
593
- const text = document.createTextNode(String(value));
594
- parent.insertBefore(text, before);
595
- return {
596
- kind: "text",
597
- value,
598
- context,
599
- start: text,
600
- end: text,
601
- children: []
602
- };
603
- }
604
- if (renderable(value)) return mountComponent(value, parent, before, context, boundary, appearance);
605
- if (isCollection(value)) return mountCollection(value, parent, before, context, boundary, appearance);
606
- if (!isVNode(value)) throw new TypeError(`Cannot render ${String(value)}.`);
607
- if (value.type === Fragment$1) return mountFragment(value, parent, before, context, boundary, appearance);
608
- if (value.type === PORTAL) return mountPortal(value, parent, before, context, boundary, appearance);
609
- if (typeof value.type == "string") return mountElement(value, parent, before, context, boundary, appearance);
610
- if (typeof value.type != "function") throw new Error(`Cannot render ${String(value.type)}.`);
611
- if (value.type.prototype instanceof State) return mountOwnedComponent(value, parent, before, context, boundary, appearance);
612
- return mountFunction(value, parent, before, context, boundary, appearance);
613
- }
614
- function mountFragment(value, parent, before, context, boundary, appearance) {
615
- const fiber = range("fragment", parent, before, context);
616
- fiber.key = value.key;
617
- fiber.type = Fragment$1;
618
- fiber.appearance = appearance;
619
- return complete(fiber, () => {
620
- reconcile(fiber, value.props.children, context, boundary, appearance);
621
- });
622
- }
623
- function mountFunction(value, parent, before, context, boundary, appearance) {
624
- const fiber = range("function", parent, before, context);
625
- const resolved = componentProps(value.type, value.props, appearance);
626
- fiber.key = value.key;
627
- fiber.type = value.type;
628
- fiber.props = observe(resolved.props);
629
- fiber.boundary = boundary;
630
- fiber.appearance = resolved.appearance;
631
- fiber.scope = makeScope("function", context, (passive) => runFunction(fiber, passive));
632
- fiber.render = () => enter(fiber.scope, () => {
633
- const type = latest(fiber.type);
634
- return resolve(type, fiber.props, () => call(type, fiber.props));
582
+ function door(value) {
583
+ const collected = {
584
+ classes: [],
585
+ declarations: {},
586
+ tokens: []
587
+ };
588
+ const { classes, declarations, tokens } = collected;
589
+ collect(value, collected, 1);
590
+ if (!classes.length && !tokens.length && !Object.keys(declarations).length) return void 0;
591
+ const key = Object.freeze({});
592
+ tickets.set(key, {
593
+ classes,
594
+ tokens
635
595
  });
636
- track(fiber.type, fiber.scope);
637
- probing(fiber);
638
- return complete(fiber, () => {
639
- runFunction(fiber, passiveRender);
596
+ return Object.freeze({
597
+ ...declarations,
598
+ [Symbol("style")]: key
640
599
  });
641
600
  }
642
- function mountOwnedComponent(value, parent, before, context, boundary, appearance) {
643
- const resolved = componentProps(value.type, value.props, appearance);
644
- const Type = value.type;
645
- const props = observe(resolved.props);
646
- const instance = new Type(props, Type.prototype instanceof Component ? void 0 : () => props.is?.(instance));
647
- return mountComponent(instance, parent, before, context, boundary, resolved.appearance, true, value.key, props);
648
- }
649
- function runFunction(fiber, passive) {
650
- const result = attempt(fiber, passive, fiber.render);
651
- if (result === true) inserted(fiber, () => commit(fiber.scope));
652
- else return result;
653
- }
654
- function probing(fiber) {
655
- const scope = fiber.scope;
656
- scope.empty = () => !fiber.children.length;
657
- scope.probe = () => {
658
- try {
659
- scope.probed = { output: consume(fiber, fiber.render) };
660
- } catch (thrown) {
661
- if (isThenable(thrown)) return thrown;
662
- }
601
+ function claim(element, appearance, resolved, className, value) {
602
+ const collected = {
603
+ classes: [],
604
+ declarations: {},
605
+ tokens: []
663
606
  };
664
- }
665
- function mountComponent(instance, parent, before, context, inherited, appearance, owned = false, key, props = instance.props) {
666
- const fiber = range("component", parent, before, context);
667
- const childContext = context.push(instance);
668
- const element = owned ? props : {};
669
- const fallback = element.fallback !== void 0 ? element.fallback : instance.fallback;
670
- const ownBoundary = fallback !== void 0 && fallback !== false || element.catch || instance.catch ? {
671
- catch: element.catch || instance.catch ? (error) => {
672
- return (owned && fiber.props.catch || instance.catch).call(instance, error, instance);
673
- } : void 0,
674
- fallback: () => {
675
- const placed = owned ? fiber.props.fallback : void 0;
676
- return placed !== void 0 ? placed : instance.fallback;
677
- },
678
- owner: fiber,
679
- parent: inherited
680
- } : inherited;
681
- fiber.boundary = ownBoundary;
682
- if (ownBoundary !== inherited) fiber.ownBoundary = ownBoundary;
683
- fiber.childContext = childContext;
684
- fiber.instance = instance;
685
- fiber.key = owned ? key : instance.key;
686
- fiber.type = instance.constructor;
687
- fiber.props = props;
688
- fiber.owned = owned;
689
- fiber.appearance = appearance;
690
- fiber.scope = makeScope("component", childContext, (passive) => runComponent(fiber, passive));
691
- fiber.render = () => enter(fiber.scope, () => compose.call(fiber.value, fiber.props));
692
- probing(fiber);
693
- let first = true;
694
- let proxy = instance;
695
- fiber.release = watch(instance, (current, events) => {
696
- const { applied, scope } = fiber;
697
- proxy = current;
698
- fiber.applied = void 0;
699
- if (!first && scope.active) if (applied && events.includes("props")) transition(() => schedule(scope));
700
- else schedule(scope);
701
- first = false;
702
- }, void 0, transition);
703
- Object.defineProperty(fiber, "value", { get: () => proxy });
704
- try {
705
- complete(fiber, () => {
706
- runComponent(fiber, passiveRender);
707
- });
708
- } finally {
709
- if (owned && !fiber.dead) inserted(fiber, () => fiber.cleanup = instance.mount?.());
607
+ const entries = appearance?.entries || [];
608
+ let context = appearance?.context;
609
+ let reach = -1;
610
+ if (resolved) collect(createAppearanceToken(resolved), collected, 0);
611
+ appendClasses(collected.classes, className);
612
+ collect(value, collected, 0);
613
+ for (let index = entries.length - 1; index >= 0; index--) collect(entries[index].style, collected, entries[index].hops);
614
+ for (const { appearance, doors } of collected.tokens) {
615
+ for (const block of appearance.blocks || []) collected.classes.push(emitClass(block, doors, element.ownerDocument));
616
+ if (appearance.classes) collected.classes.push(...appearance.classes);
617
+ if (appearance.context && doors >= reach) {
618
+ context = appearance.context;
619
+ reach = doors;
620
+ }
710
621
  }
711
- return fiber;
712
- }
713
- function runComponent(fiber, passive) {
714
- const result = attempt(fiber, passive, fiber.render);
715
- if (result !== true) return result;
716
- }
717
- function mountCollection(value, parent, before, context, boundary, appearance) {
718
- const fiber = range("collection", parent, before, context);
719
- fiber.source = value;
720
- fiber.value = value;
721
- fiber.boundary = boundary;
722
- fiber.appearance = appearance;
723
- fiber.scope = makeScope("collection", context, (passive) => runCollection(fiber, passive));
724
- let first = true;
725
- fiber.release = watch(value, (current) => {
726
- fiber.value = current;
727
- if (!first && fiber.scope?.active) schedule(fiber.scope);
728
- first = false;
729
- }, void 0, transition);
730
- return complete(fiber, () => {
731
- runCollection(fiber, passiveRender);
732
- });
733
- }
734
- function runCollection(fiber, passive) {
735
- attempt(fiber, passive, () => {
736
- const value = fiber.value;
737
- return value instanceof map.Managed ? [...value.values()] : [...value];
738
- });
739
- }
740
- function mountPortal(value, parent, before, context, boundary, appearance) {
741
- const marker = document.createComment("portal");
742
- const container = target(value.props.into, parent);
743
- const portalStart = document.createComment("portal-root");
744
- const portalEnd = document.createComment("/portal-root");
745
- parent.insertBefore(marker, before);
746
- container.append(portalStart, portalEnd);
747
- const output = {
748
- kind: "portal",
749
- key: value.key,
750
- type: PORTAL,
751
- props: value.props,
622
+ return {
623
+ className: [...new Set(collected.classes)].join(" "),
752
624
  context,
753
- boundary,
754
- appearance,
755
- start: marker,
756
- end: marker,
757
- children: [],
758
- portalContainer: container,
759
- portalStart,
760
- portalEnd
625
+ declarations: collected.declarations
761
626
  };
762
- return complete(output, () => {
763
- reconcilePortal(output, value.props.children, context, boundary, appearance);
764
- });
765
- }
766
- function target(into, parent) {
767
- if (typeof into != "string") return into;
768
- const root = parent.getRootNode();
769
- const found = [...document.querySelectorAll(into)];
770
- if (root instanceof DocumentFragment) found.push(...root.querySelectorAll(into));
771
- if (found.length != 1) throw new Error(`Portal target "${into}" ${found.length ? "is ambiguous" : "was not found"}.`);
772
- return found[0];
773
627
  }
774
- function mountElement(value, parent, before, context, boundary, appearance) {
775
- const tag = value.type;
776
- let host = parent;
777
- for (let owner = stashes.get(host); owner; owner = stashes.get(host)) host = owner.end.parentNode;
778
- const element = (tag == "svg" || host instanceof SVGElement && host.localName != "foreignObject" ? SVG : void 0) ? document.createElementNS(SVG, tag) : document.createElement(tag);
779
- const fiber = {
780
- kind: "element",
781
- key: value.key,
782
- type: tag,
783
- props: {},
784
- context,
785
- boundary,
786
- start: element,
787
- end: element,
788
- children: [],
789
- events: /* @__PURE__ */ new Map()
628
+ function applyClaim(element, before, after) {
629
+ const previous = before || {
630
+ className: "",
631
+ declarations: {}
790
632
  };
791
- parent.insertBefore(element, before);
792
- complete(fiber, () => {
793
- patchProps(fiber, value.props, appearance);
794
- });
795
- if (value.props.autofocus || value.props.autoFocus) focusing.push(element);
796
- return fiber;
633
+ if (previous.className !== after.className) if (after.className) element.setAttribute("class", after.className);
634
+ else element.removeAttribute("class");
635
+ applyDeclarations(element.style, after.declarations, previous.declarations);
797
636
  }
798
- function pass(work) {
799
- depth++;
800
- try {
801
- return work();
802
- } finally {
803
- if (!--depth) {
804
- settle();
805
- focus();
806
- }
637
+ function collect(value, collected, doors) {
638
+ if (!value) return;
639
+ const token = appearanceToken(value);
640
+ if (token) {
641
+ collected.tokens.push({
642
+ appearance: token,
643
+ doors
644
+ });
645
+ Object.assign(collected.declarations, token.declarations);
646
+ return;
807
647
  }
808
- }
809
- function focus() {
810
- for (const element of focusing.splice(0)) if (element.isConnected) element.focus();
811
- }
812
- function attempt(fiber, passive, render) {
813
- const previous = passiveRender;
814
- const scope = fiber.scope;
815
- const probed = scope.probed;
816
- const empty = !fiber.children.length;
817
- scope.probed = void 0;
818
- passiveRender ||= passive;
819
- if (passive && !depth && empty && !fiber.stash) fiber.staging ||= fragment();
820
- const run = () => pass(() => {
821
- try {
822
- reconcile(fiber, probed ? probed.output : consume(fiber, render), scope.childContext, fiber.boundary, renderedAppearance(fiber));
823
- if (fiber.staging) {
824
- fiber.end.parentNode.insertBefore(fiber.staging, fiber.end);
825
- attach(fiber.staging);
826
- fiber.staging = void 0;
827
- }
828
- if (!fiber.recovering) unwait(fiber);
829
- fiber.retried = void 0;
830
- return true;
831
- } catch (thrown) {
832
- return suspend(fiber, thrown, passive, empty);
833
- }
834
- });
835
- try {
836
- return passive ? batched(run) : run();
837
- } finally {
838
- passiveRender = previous;
648
+ if (typeof value == "string") {
649
+ appendClasses(collected.classes, value);
650
+ return;
651
+ }
652
+ if (Array.isArray(value)) {
653
+ value.forEach((entry) => collect(entry, collected, doors));
654
+ return;
655
+ }
656
+ for (const symbol of Object.getOwnPropertySymbols(value)) {
657
+ const ticket = tickets.get(value[symbol]);
658
+ if (!ticket) continue;
659
+ collected.classes.push(...ticket.classes);
660
+ for (const carried of ticket.tokens) collected.tokens.push({
661
+ appearance: carried.appearance,
662
+ doors: carried.doors + doors
663
+ });
839
664
  }
665
+ for (const key of Object.keys(value)) collected.declarations[key] = value[key];
666
+ }
667
+ function appendClasses(classes, value) {
668
+ if (typeof value == "string") classes.push(...value.split(/\s+/).filter(Boolean));
840
669
  }
670
+
671
+ //#endregion
672
+ //#region src/render/style.ts
673
+ let rendering;
674
+ let touched = false;
675
+ const observed = /* @__PURE__ */ new WeakMap();
841
676
  function observe(props) {
842
677
  if (!("style" in props)) return props;
843
678
  let output = observed.get(props);
@@ -860,25 +695,6 @@ function observe(props) {
860
695
  }
861
696
  return output;
862
697
  }
863
- function door(value) {
864
- const collected = {
865
- classes: [],
866
- declarations: {},
867
- tokens: []
868
- };
869
- const { classes, declarations, tokens } = collected;
870
- collect(value, collected, 1);
871
- if (!classes.length && !tokens.length && !Object.keys(declarations).length) return void 0;
872
- const key = Object.freeze({});
873
- tickets.set(key, {
874
- classes,
875
- tokens
876
- });
877
- return Object.freeze({
878
- ...declarations,
879
- [Symbol("style")]: key
880
- });
881
- }
882
698
  function consume(fiber, render) {
883
699
  const previous = rendering;
884
700
  const read = touched;
@@ -893,275 +709,68 @@ function consume(fiber, render) {
893
709
  touched = read;
894
710
  }
895
711
  }
896
- function wait(fiber, boundary) {
897
- if (fiber.waitingOn !== boundary) unwait(fiber);
898
- fiber.waitingOn = boundary;
899
- (boundary.waiting ||= /* @__PURE__ */ new Set()).add(fiber);
900
- dirty.add(boundary);
712
+ function renderedAppearance(fiber) {
713
+ if (fiber.kind != "component" && fiber.kind != "function") return fiber.appearance;
714
+ const style = fiber.props?.style;
715
+ const entries = (fiber.appearance?.entries || []).map(({ hops, style }) => ({
716
+ hops: hops + 1,
717
+ style
718
+ }));
719
+ const inherited = fiber.appearance?.context || appearanceRoot();
720
+ const context = enterAppearance(inherited, latest(fiber.type));
721
+ if (context?.base && context !== inherited) entries.push({
722
+ hops: 0,
723
+ style: context.base
724
+ });
725
+ if (style && !fiber.consumed && !(fiber.instance && "style" in fiber.instance)) entries.push({
726
+ hops: 0,
727
+ style
728
+ });
729
+ return entries.length || context ? {
730
+ context,
731
+ entries
732
+ } : void 0;
901
733
  }
902
- function unwait(fiber) {
903
- const boundary = fiber.waitingOn;
904
- if (!boundary) return;
905
- fiber.waitingOn = void 0;
906
- boundary.waiting.delete(fiber);
907
- if (!boundary.owner.dead) dirty.add(boundary);
908
- }
909
- function settle() {
910
- if (settling) return;
911
- settling = true;
912
- try {
913
- for (const boundary of dirty) {
914
- dirty.delete(boundary);
915
- const owner = boundary.owner;
916
- const waiting = boundary.waiting.size > 0;
917
- if (!owner.dead && waiting != !!owner.stash) waiting ? hide(owner, boundary) : reveal(owner);
918
- }
919
- } finally {
920
- settling = false;
921
- }
922
- }
923
- function hide(owner, boundary) {
924
- const stash = document.createDocumentFragment();
925
- for (const child of owner.children) move(child, stash, null);
926
- owner.portals = portals(owner, []).map((portal) => {
927
- const content = document.createDocumentFragment();
928
- moveRange(portal.portalStart, portal.portalEnd, content);
929
- return [portal, content];
930
- });
931
- stashes.set(stash, owner);
932
- const context = owner.childContext;
933
- const placeholder = range("fragment", owner.end.parentNode, owner.end, context);
934
- owner.stash = stash;
935
- owner.placeholder = placeholder;
936
- reconcile(placeholder, boundary.fallback(), context, boundary.parent);
937
- }
938
- function reveal(owner) {
939
- unmountFiber(owner.placeholder);
940
- owner.end.parentNode.insertBefore(owner.stash, owner.end);
941
- for (const [portal, content] of owner.portals) if (!portal.dead) portal.portalContainer.append(content);
942
- owner.portals = void 0;
943
- owner.placeholder = void 0;
944
- owner.stash = void 0;
945
- }
946
- function portals(fiber, found) {
947
- for (const child of fiber.children) {
948
- if (child.kind == "portal") found.push(child);
949
- portals(child, found);
950
- }
951
- return found;
952
- }
953
- function moveRange(start, end, target) {
954
- let node = start;
955
- while (node) {
956
- const next = node.nextSibling;
957
- target.appendChild(node);
958
- if (node === end) break;
959
- node = next;
960
- }
961
- }
962
- function suspend(fiber, thrown, passive, empty) {
963
- const boundary = fiber.boundary;
964
- if (isThenable(thrown)) {
965
- if (!boundary) throw thrown;
966
- if (passive && empty && depth > 1) {
967
- if (holding?.thrown !== thrown) holding = { thrown };
968
- throw thrown;
969
- }
970
- holding = void 0;
971
- if (!passive) wait(fiber, boundary);
972
- const scope = fiber.scope;
973
- let held = scope.holds;
974
- scope.holds = void 0;
975
- const clear = () => {
976
- fiber.suspended.delete(clear);
977
- release(held);
978
- held = void 0;
979
- };
980
- (fiber.suspended ||= /* @__PURE__ */ new Set()).add(clear);
981
- const resume = (retry) => {
982
- fiber.suspended.delete(clear);
983
- if (!scope.active) return clear();
984
- if (held) (scope.holds ||= []).push(...held);
985
- held = void 0;
986
- retry();
987
- };
988
- thrown.then(() => resume(() => passive ? transition(() => schedule(scope)) : schedule(scope)), (error) => resume(() => pass(() => recover(fiber, error, fiber.boundary))));
989
- return thrown;
990
- }
991
- recover(fiber, thrown, fiber.boundary);
992
- }
993
- function recover(fiber, thrown, boundary) {
994
- const error = thrown instanceof Error ? thrown : new Error(String(thrown));
995
- while (boundary && !boundary.catch) boundary = boundary.parent;
996
- if (!boundary) throw error;
997
- const handler = boundary;
998
- const token = {};
999
- wait(fiber, handler);
1000
- fiber.recovering = token;
1001
- Promise.resolve(handler.catch(error)).then(() => {
1002
- if (fiber.recovering !== token) return;
1003
- fiber.recovering = void 0;
1004
- if (!fiber.scope.active || fiber.retried) return;
1005
- fiber.retried = true;
1006
- schedule(fiber.scope);
1007
- }, (next) => {
1008
- if (fiber.recovering === token && fiber.scope.active) pass(() => recover(fiber, next, handler.parent));
1009
- });
1010
- }
1011
- function isThenable(value) {
1012
- return !!value && typeof value.then == "function";
1013
- }
1014
- function reconcile(fiber, value, context, boundary, appearance) {
1015
- const detached = fiber.stash || fiber.staging;
1016
- if (detached) reconcileChildren(fiber, detached, null, value, context, boundary, appearance);
1017
- else reconcileChildren(fiber, fiber.end.parentNode, fiber.end, value, context, boundary, appearance);
1018
- }
1019
- function reconcilePortal(fiber, value, context, boundary, appearance) {
1020
- reconcileChildren(fiber, fiber.portalEnd.parentNode, fiber.portalEnd, value, context, boundary, appearance);
1021
- }
1022
- function reconcileChildren(owner, parent, before, value, context, boundary, appearance) {
1023
- const values = childrenOf(value);
1024
- const old = owner.children;
1025
- const keyed = /* @__PURE__ */ new Map();
1026
- const used = /* @__PURE__ */ new Set();
1027
- const next = [];
1028
- for (const child of old) if (child.key !== null && child.key !== void 0) keyed.set(child.key, child);
1029
- try {
1030
- for (let index = 0; index < values.length; index++) {
1031
- const value = source(values[index]);
1032
- const key = keyOf(value);
1033
- let child = key !== null && key !== void 0 ? keyed.get(key) : old[index]?.key == null ? old[index] : void 0;
1034
- if (child && used.has(child)) child = void 0;
1035
- if (child) used.add(child);
1036
- const fiber = patch(child, value, parent, before, context, boundary, appearance);
1037
- if (fiber !== child) used.delete(child);
1038
- next.push(fiber);
1039
- }
1040
- } catch (error) {
1041
- if (holding && error === holding.thrown) {
1042
- for (const fiber of next) if (!old.includes(fiber)) park(fiber);
1043
- if (holding.fiber) next.push(holding.fiber);
1044
- holding.fiber = void 0;
1045
- }
1046
- owner.children = [...next, ...old.filter((child) => !child.dead && !next.includes(child))];
1047
- throw error;
1048
- }
1049
- for (const child of old) if (!used.has(child)) unmountFiber(child);
1050
- let anchor = before;
1051
- for (let index = next.length - 1; index >= 0; index--) {
1052
- const child = next[index];
1053
- const root = child.start.getRootNode();
1054
- move(child, parent, anchor);
1055
- anchor = child.start;
1056
- if (child.start.getRootNode() !== root) attach(root);
1057
- }
1058
- owner.children = next;
1059
- }
1060
- function patch(old, value, parent, before, context, boundary, appearance) {
1061
- if (!old || !compatible(old, value)) return mount(value, parent, old?.start || before, context, boundary, appearance);
1062
- if (old.ownBoundary) old.ownBoundary.parent = boundary;
1063
- old.boundary = old.ownBoundary || boundary;
1064
- if (old.kind == "collection") {
1065
- if (old.appearance !== appearance) {
1066
- old.appearance = appearance;
1067
- runCollection(old, passiveRender);
1068
- }
1069
- return old;
1070
- }
1071
- if (old.kind == "text") {
1072
- const next = String(value);
1073
- if (old.start.nodeValue !== next) old.start.nodeValue = next;
1074
- old.value = value;
1075
- } else if (old.kind == "element") patchProps(old, value.props, appearance);
1076
- else if (old.kind == "fragment") {
1077
- old.context = context;
1078
- old.appearance = appearance;
1079
- reconcile(old, value.props.children, context, old.boundary, appearance);
1080
- } else if (old.kind == "function") {
1081
- const vnode = value;
1082
- const resolved = componentProps(vnode.type, vnode.props, appearance);
1083
- if (old.type !== vnode.type) {
1084
- untrack(old.type, old.scope);
1085
- old.type = vnode.type;
1086
- old.scope.hot = true;
1087
- track(old.type, old.scope);
1088
- }
1089
- old.appearance = resolved.appearance;
1090
- old.props = observe(resolved.props);
1091
- rerun(old, () => runFunction(old, passiveRender));
1092
- } else if (old.kind == "component") {
1093
- const resolved = isVNode(value) ? componentProps(value.type, value.props, appearance) : {
1094
- appearance,
1095
- props: old.props
1096
- };
1097
- old.appearance = resolved.appearance;
1098
- const props = isVNode(value) ? observe(resolved.props) : resolved.props;
1099
- if (isVNode(value) && props !== old.props) {
1100
- const instance = old.instance;
1101
- if (passiveRender) old.applied = true;
1102
- if (instance instanceof Component) instance.props = props;
1103
- else instance.set(merge(old.props, props));
1104
- }
1105
- old.props = props;
1106
- rerun(old, () => runComponent(old, passiveRender));
1107
- } else {
1108
- old.appearance = appearance;
1109
- const vnode = value;
1110
- old.props = vnode.props;
1111
- reconcilePortal(old, vnode.props.children, context, old.boundary, appearance);
1112
- }
1113
- return old;
1114
- }
1115
- function rerun(fiber, run) {
1116
- claim$1(fiber.scope);
1117
- run();
1118
- settle$1(fiber.scope);
1119
- }
1120
- function compatible(fiber, value) {
1121
- if (fiber.kind == "text") return [
1122
- "string",
1123
- "number",
1124
- "bigint"
1125
- ].includes(typeof value);
1126
- if (renderable(value)) return fiber.kind == "component" && fiber.instance === value;
1127
- if (isCollection(value)) return fiber.kind == "collection" && fiber.source === value;
1128
- if (!isVNode(value)) return false;
1129
- if (fiber.key !== value.key || !same(fiber.type, value.type)) return false;
1130
- if (fiber.kind == "portal") return fiber.props.into === value.props.into;
1131
- return true;
1132
- }
1133
- function source(value) {
1134
- if (value instanceof State) return value.is;
1135
- while (isCollection(value) && isCollection(Object.getPrototypeOf(value))) value = Object.getPrototypeOf(value);
1136
- return value;
1137
- }
1138
- function renderable(value) {
1139
- return value instanceof State && typeof value.render == "function";
1140
- }
1141
- function merge(previous, next) {
1142
- const output = {};
1143
- for (const key in previous) output[key] = void 0;
1144
- return {
1145
- ...output,
1146
- ...next
734
+
735
+ //#endregion
736
+ //#region src/render/element.ts
737
+ const SVG = "http://www.w3.org/2000/svg";
738
+ const CONTROLS = ["checked", "value"];
739
+ const ENUMERATED = [
740
+ "contentEditable",
741
+ "contenteditable",
742
+ "draggable",
743
+ "spellcheck"
744
+ ];
745
+ const ALIASES = {
746
+ autoFocus: "autofocus",
747
+ contentEditable: "contenteditable",
748
+ htmlFor: "for"
749
+ };
750
+ const controlled = /* @__PURE__ */ new WeakMap();
751
+ const restoring = /* @__PURE__ */ new WeakSet();
752
+ function mountElement(value, parent, before, context, boundary, appearance) {
753
+ const tag = value.type;
754
+ const host = hostOf(parent);
755
+ const element = (tag == "svg" || host instanceof SVGElement && host.localName != "foreignObject" ? SVG : void 0) ? document.createElementNS(SVG, tag) : document.createElement(tag);
756
+ const fiber = {
757
+ kind: "element",
758
+ key: value.key,
759
+ type: tag,
760
+ props: {},
761
+ context,
762
+ boundary,
763
+ start: element,
764
+ end: element,
765
+ children: [],
766
+ events: /* @__PURE__ */ new Map()
1147
767
  };
1148
- }
1149
- function isCollection(value) {
1150
- return value instanceof has.List || value instanceof has.Pool || value instanceof map.Managed;
1151
- }
1152
- function keyOf(value) {
1153
- if (renderable(value)) return value.key;
1154
- return isVNode(value) ? value.key : void 0;
1155
- }
1156
- function move(fiber, parent, before) {
1157
- if (fiber.start.parentNode === parent && fiber.end.nextSibling === before) return;
1158
- let node = fiber.start;
1159
- while (node) {
1160
- const next = node.nextSibling;
1161
- parent.insertBefore(node, before);
1162
- if (node === fiber.end) break;
1163
- node = next;
1164
- }
768
+ parent.insertBefore(element, before);
769
+ complete(fiber, () => {
770
+ patchProps(fiber, value.props, appearance);
771
+ });
772
+ if (value.props.autofocus || value.props.autoFocus) focusing.push(element);
773
+ return fiber;
1165
774
  }
1166
775
  function patchProps(fiber, next, appearance) {
1167
776
  const element = fiber.start;
@@ -1248,97 +857,6 @@ function patchProp(fiber, element, key, previous, next) {
1248
857
  } catch {}
1249
858
  element.setAttribute(name, next === true ? "" : String(next));
1250
859
  }
1251
- function applyClaim(element, before, after) {
1252
- const previous = before || {
1253
- className: "",
1254
- declarations: {}
1255
- };
1256
- if (previous.className !== after.className) if (after.className) element.setAttribute("class", after.className);
1257
- else element.removeAttribute("class");
1258
- applyDeclarations(element.style, after.declarations, previous.declarations);
1259
- }
1260
- function claim(element, appearance, resolved, className, value) {
1261
- const collected = {
1262
- classes: [],
1263
- declarations: {},
1264
- tokens: []
1265
- };
1266
- const entries = appearance?.entries || [];
1267
- let context = appearance?.context;
1268
- let reach = -1;
1269
- if (resolved) collect(createAppearanceToken(resolved), collected, 0);
1270
- appendClasses(collected.classes, className);
1271
- collect(value, collected, 0);
1272
- for (let index = entries.length - 1; index >= 0; index--) collect(entries[index].style, collected, entries[index].hops);
1273
- for (const { appearance, doors } of collected.tokens) {
1274
- for (const block of appearance.blocks || []) collected.classes.push(emitClass(block, doors, element.ownerDocument));
1275
- if (appearance.classes) collected.classes.push(...appearance.classes);
1276
- if (appearance.context && doors >= reach) {
1277
- context = appearance.context;
1278
- reach = doors;
1279
- }
1280
- }
1281
- return {
1282
- className: [...new Set(collected.classes)].join(" "),
1283
- context,
1284
- declarations: collected.declarations
1285
- };
1286
- }
1287
- function renderedAppearance(fiber) {
1288
- if (fiber.kind != "component" && fiber.kind != "function") return fiber.appearance;
1289
- const style = fiber.props?.style;
1290
- const entries = (fiber.appearance?.entries || []).map(({ hops, style }) => ({
1291
- hops: hops + 1,
1292
- style
1293
- }));
1294
- const inherited = fiber.appearance?.context || appearanceRoot();
1295
- const context = enterAppearance(inherited, latest(fiber.type));
1296
- if (context?.base && context !== inherited) entries.push({
1297
- hops: 0,
1298
- style: context.base
1299
- });
1300
- if (style && !fiber.consumed && !(fiber.instance && "style" in fiber.instance)) entries.push({
1301
- hops: 0,
1302
- style
1303
- });
1304
- return entries.length || context ? {
1305
- context,
1306
- entries
1307
- } : void 0;
1308
- }
1309
- function collect(value, collected, doors) {
1310
- if (!value) return;
1311
- const token = appearanceToken(value);
1312
- if (token) {
1313
- collected.tokens.push({
1314
- appearance: token,
1315
- doors
1316
- });
1317
- Object.assign(collected.declarations, token.declarations);
1318
- return;
1319
- }
1320
- if (typeof value == "string") {
1321
- appendClasses(collected.classes, value);
1322
- return;
1323
- }
1324
- if (Array.isArray(value)) {
1325
- value.forEach((entry) => collect(entry, collected, doors));
1326
- return;
1327
- }
1328
- for (const symbol of Object.getOwnPropertySymbols(value)) {
1329
- const ticket = tickets.get(value[symbol]);
1330
- if (!ticket) continue;
1331
- collected.classes.push(...ticket.classes);
1332
- for (const carried of ticket.tokens) collected.tokens.push({
1333
- appearance: carried.appearance,
1334
- doors: carried.doors + doors
1335
- });
1336
- }
1337
- for (const key of Object.keys(value)) collected.declarations[key] = value[key];
1338
- }
1339
- function appendClasses(classes, value) {
1340
- if (typeof value == "string") classes.push(...value.split(/\s+/).filter(Boolean));
1341
- }
1342
860
  function restoreTarget(event) {
1343
861
  const element = event.target;
1344
862
  const fiber = controlled.get(element);
@@ -1367,39 +885,554 @@ function applyRef(ref, value) {
1367
885
  if (typeof ref == "function") ref(value);
1368
886
  else if (ref && typeof ref == "object" && "current" in ref) ref.current = value;
1369
887
  }
1370
- function unmountFiber(fiber) {
1371
- fiber.dead = true;
1372
- unwait(fiber);
1373
- for (let index = fiber.children.length - 1; index >= 0; index--) unmountFiber(fiber.children[index]);
1374
- if (fiber.placeholder) unmountFiber(fiber.placeholder);
1375
- fiber.suspended?.forEach((clear) => clear());
1376
- if (fiber.kind == "function") untrack(fiber.type, fiber.scope);
1377
- if (fiber.scope) dispose(fiber.scope);
1378
- fiber.release?.();
1379
- if (fiber.kind == "element") {
1380
- applyRef(fiber.props?.ref, null);
1381
- for (const [id, listener] of fiber.events) {
1382
- const [name, capture] = id.split(":");
1383
- fiber.start.removeEventListener(name, listener, capture === "true");
888
+ function unmountElement(fiber) {
889
+ applyRef(fiber.props?.ref, null);
890
+ for (const [id, listener] of fiber.events) {
891
+ const [name, capture] = id.split(":");
892
+ fiber.start.removeEventListener(name, listener, capture === "true");
893
+ }
894
+ }
895
+
896
+ //#endregion
897
+ //#region src/render/portal.ts
898
+ function mountPortal(value, parent, before, context, boundary, appearance) {
899
+ const marker = document.createComment("portal");
900
+ const container = target(value.props.into, parent);
901
+ const portalStart = document.createComment("portal-root");
902
+ const portalEnd = document.createComment("/portal-root");
903
+ parent.insertBefore(marker, before);
904
+ container.append(portalStart, portalEnd);
905
+ const output = {
906
+ kind: "portal",
907
+ key: value.key,
908
+ type: PORTAL,
909
+ props: value.props,
910
+ context,
911
+ boundary,
912
+ appearance,
913
+ start: marker,
914
+ end: marker,
915
+ children: [],
916
+ portalContainer: container,
917
+ portalStart,
918
+ portalEnd
919
+ };
920
+ return complete(output, () => {
921
+ reconcilePortal(output, value.props.children, context, boundary, appearance);
922
+ });
923
+ }
924
+ function target(into, parent) {
925
+ if (typeof into != "string") return into;
926
+ const root = parent.getRootNode();
927
+ const found = [...document.querySelectorAll(into)];
928
+ if (root instanceof DocumentFragment) found.push(...root.querySelectorAll(into));
929
+ if (found.length != 1) throw new Error(`Portal target "${into}" ${found.length ? "is ambiguous" : "was not found"}.`);
930
+ return found[0];
931
+ }
932
+ function reconcilePortal(fiber, value, context, boundary, appearance) {
933
+ reconcileChildren(fiber, fiber.portalEnd.parentNode, fiber.portalEnd, value, context, boundary, appearance);
934
+ }
935
+ function patchPortal(fiber, value, context, appearance) {
936
+ fiber.appearance = appearance;
937
+ fiber.props = value.props;
938
+ reconcilePortal(fiber, value.props.children, context, fiber.boundary, appearance);
939
+ }
940
+ function unmountPortal(fiber) {
941
+ fiber.portalStart.remove();
942
+ fiber.portalEnd.remove();
943
+ }
944
+
945
+ //#endregion
946
+ //#region src/render/reconcile.ts
947
+ function reconcile(fiber, value, context, boundary, appearance) {
948
+ const detached = fiber.stash || fiber.staging;
949
+ if (detached) reconcileChildren(fiber, detached, null, value, context, boundary, appearance);
950
+ else reconcileChildren(fiber, fiber.end.parentNode, fiber.end, value, context, boundary, appearance);
951
+ }
952
+ function reconcileChildren(owner, parent, before, value, context, boundary, appearance) {
953
+ const values = childrenOf(value);
954
+ const old = owner.children;
955
+ const keyed = /* @__PURE__ */ new Map();
956
+ const used = /* @__PURE__ */ new Set();
957
+ const next = [];
958
+ for (const child of old) if (child.key !== null && child.key !== void 0) keyed.set(child.key, child);
959
+ try {
960
+ for (let index = 0; index < values.length; index++) {
961
+ const value = source(values[index]);
962
+ const key = keyOf(value);
963
+ let child = key !== null && key !== void 0 ? keyed.get(key) : old[index]?.key == null ? old[index] : void 0;
964
+ if (child && used.has(child)) child = void 0;
965
+ if (child) used.add(child);
966
+ const fiber = patch(child, value, parent, before, context, boundary, appearance);
967
+ if (fiber !== child) used.delete(child);
968
+ next.push(fiber);
1384
969
  }
970
+ } catch (error) {
971
+ gather(error, next, old);
972
+ owner.children = [...next, ...old.filter((child) => !child.dead && !next.includes(child))];
973
+ throw error;
1385
974
  }
1386
- if (fiber.kind == "component") {
1387
- if (typeof fiber.cleanup == "function") fiber.cleanup();
1388
- fiber.childContext?.pop();
1389
- if (fiber.owned && !fiber.instance.get(null)) fiber.instance.set(null);
1390
- } else if (fiber.kind == "portal") {
1391
- fiber.portalStart.remove();
1392
- fiber.portalEnd.remove();
975
+ for (const child of old) if (!used.has(child)) unmountFiber(child);
976
+ let anchor = before;
977
+ for (let index = next.length - 1; index >= 0; index--) {
978
+ const child = next[index];
979
+ const root = child.start.getRootNode();
980
+ move(child, parent, anchor);
981
+ anchor = child.start;
982
+ if (child.start.getRootNode() !== root) attach(root);
1393
983
  }
1394
- removeRange(fiber.start, fiber.end);
984
+ owner.children = next;
1395
985
  }
1396
- function removeRange(start, end) {
1397
- let node = start;
1398
- while (true) {
1399
- const next = node.nextSibling;
1400
- node.remove();
1401
- if (node === end) break;
1402
- node = next;
986
+ function patch(old, value, parent, before, context, boundary, appearance) {
987
+ if (!old || !compatible(old, value)) return mount(value, parent, old?.start || before, context, boundary, appearance);
988
+ if (old.ownBoundary) old.ownBoundary.parent = boundary;
989
+ old.boundary = old.ownBoundary || boundary;
990
+ if (old.kind == "collection") patchCollection(old, appearance);
991
+ else if (old.kind == "text") patchText(old, value);
992
+ else if (old.kind == "element") patchProps(old, value.props, appearance);
993
+ else if (old.kind == "fragment") patchFragment(old, value, context, appearance);
994
+ else if (old.kind == "function") patchFunction(old, value, appearance);
995
+ else if (old.kind == "component") patchComponent(old, value, appearance);
996
+ else patchPortal(old, value, context, appearance);
997
+ return old;
998
+ }
999
+ function compatible(fiber, value) {
1000
+ if (fiber.kind == "text") return [
1001
+ "string",
1002
+ "number",
1003
+ "bigint"
1004
+ ].includes(typeof value);
1005
+ if (renderable(value)) return fiber.kind == "component" && fiber.instance === value;
1006
+ if (isCollection(value)) return fiber.kind == "collection" && fiber.source === value;
1007
+ if (!isVNode(value)) return false;
1008
+ if (fiber.key !== value.key || !same(fiber.type, value.type)) return false;
1009
+ if (fiber.kind == "portal") return fiber.props.into === value.props.into;
1010
+ return true;
1011
+ }
1012
+ function source(value) {
1013
+ if (value instanceof Model) return value.is;
1014
+ while (isCollection(value) && isCollection(Object.getPrototypeOf(value))) value = Object.getPrototypeOf(value);
1015
+ return value;
1016
+ }
1017
+ function keyOf(value) {
1018
+ if (renderable(value)) return value.key;
1019
+ return isVNode(value) ? value.key : void 0;
1020
+ }
1021
+
1022
+ //#endregion
1023
+ //#region src/render/suspense.ts
1024
+ const dirty = /* @__PURE__ */ new Set();
1025
+ const stashes = /* @__PURE__ */ new WeakMap();
1026
+ let holding;
1027
+ let settling = false;
1028
+ function park(fiber) {
1029
+ move(fiber, fragment(), null);
1030
+ }
1031
+ function hold(fiber, error) {
1032
+ if (!holding || error !== holding.thrown) return false;
1033
+ park(fiber);
1034
+ holding.fiber = fiber;
1035
+ return true;
1036
+ }
1037
+ function gather(error, next, old) {
1038
+ if (!holding || error !== holding.thrown) return;
1039
+ for (const fiber of next) if (!old.includes(fiber)) park(fiber);
1040
+ if (holding.fiber) next.push(holding.fiber);
1041
+ holding.fiber = void 0;
1042
+ }
1043
+ function hostOf(parent) {
1044
+ let host = parent;
1045
+ for (let owner = stashes.get(host); owner; owner = stashes.get(host)) host = owner.end.parentNode;
1046
+ return host;
1047
+ }
1048
+ function wait(fiber, boundary) {
1049
+ if (fiber.waitingOn !== boundary) unwait(fiber);
1050
+ fiber.waitingOn = boundary;
1051
+ (boundary.waiting ||= /* @__PURE__ */ new Set()).add(fiber);
1052
+ dirty.add(boundary);
1053
+ }
1054
+ function unwait(fiber) {
1055
+ const boundary = fiber.waitingOn;
1056
+ if (!boundary) return;
1057
+ fiber.waitingOn = void 0;
1058
+ boundary.waiting.delete(fiber);
1059
+ if (!boundary.owner.dead) dirty.add(boundary);
1060
+ }
1061
+ function settle() {
1062
+ if (settling) return;
1063
+ settling = true;
1064
+ try {
1065
+ for (const boundary of dirty) {
1066
+ dirty.delete(boundary);
1067
+ const owner = boundary.owner;
1068
+ const waiting = boundary.waiting.size > 0;
1069
+ if (!owner.dead && waiting != !!owner.stash) waiting ? hide(owner, boundary) : reveal(owner);
1070
+ }
1071
+ } finally {
1072
+ settling = false;
1073
+ }
1074
+ }
1075
+ function hide(owner, boundary) {
1076
+ const stash = document.createDocumentFragment();
1077
+ for (const child of owner.children) move(child, stash, null);
1078
+ owner.portals = portals(owner, []).map((portal) => {
1079
+ const content = document.createDocumentFragment();
1080
+ moveRange(portal.portalStart, portal.portalEnd, content);
1081
+ return [portal, content];
1082
+ });
1083
+ stashes.set(stash, owner);
1084
+ const context = owner.childContext;
1085
+ const placeholder = range("fragment", owner.end.parentNode, owner.end, context);
1086
+ owner.stash = stash;
1087
+ owner.placeholder = placeholder;
1088
+ reconcile(placeholder, boundary.fallback(), context, boundary.parent);
1089
+ }
1090
+ function reveal(owner) {
1091
+ unmountFiber(owner.placeholder);
1092
+ owner.end.parentNode.insertBefore(owner.stash, owner.end);
1093
+ for (const [portal, content] of owner.portals) if (!portal.dead) portal.portalContainer.append(content);
1094
+ owner.portals = void 0;
1095
+ owner.placeholder = void 0;
1096
+ owner.stash = void 0;
1097
+ }
1098
+ function portals(fiber, found) {
1099
+ for (const child of fiber.children) {
1100
+ if (child.kind == "portal") found.push(child);
1101
+ portals(child, found);
1102
+ }
1103
+ return found;
1104
+ }
1105
+ function suspend(fiber, thrown, passive, empty) {
1106
+ const boundary = fiber.boundary;
1107
+ if (isThenable(thrown)) {
1108
+ if (!boundary) throw thrown;
1109
+ if (passive && empty && depth > 1) {
1110
+ if (holding?.thrown !== thrown) holding = { thrown };
1111
+ throw thrown;
1112
+ }
1113
+ holding = void 0;
1114
+ if (!passive) wait(fiber, boundary);
1115
+ const scope = fiber.scope;
1116
+ let held = scope.holds;
1117
+ scope.holds = void 0;
1118
+ const clear = () => {
1119
+ fiber.suspended.delete(clear);
1120
+ release(held);
1121
+ held = void 0;
1122
+ };
1123
+ (fiber.suspended ||= /* @__PURE__ */ new Set()).add(clear);
1124
+ const resume = (retry) => {
1125
+ fiber.suspended.delete(clear);
1126
+ if (!scope.active) return clear();
1127
+ if (held) (scope.holds ||= []).push(...held);
1128
+ held = void 0;
1129
+ retry();
1130
+ };
1131
+ thrown.then(() => resume(() => passive ? transition(() => schedule(scope)) : schedule(scope)), (error) => resume(() => pass(() => recover(fiber, error, fiber.boundary))));
1132
+ return thrown;
1133
+ }
1134
+ recover(fiber, thrown, fiber.boundary);
1135
+ }
1136
+ function recover(fiber, thrown, boundary) {
1137
+ const error = thrown instanceof Error ? thrown : new Error(String(thrown));
1138
+ while (boundary && !boundary.catch) boundary = boundary.parent;
1139
+ if (!boundary) throw error;
1140
+ const handler = boundary;
1141
+ const token = {};
1142
+ wait(fiber, handler);
1143
+ fiber.recovering = token;
1144
+ Promise.resolve(handler.catch(error)).then(() => {
1145
+ if (fiber.recovering !== token) return;
1146
+ fiber.recovering = void 0;
1147
+ if (!fiber.scope.active || fiber.retried) return;
1148
+ fiber.retried = true;
1149
+ schedule(fiber.scope);
1150
+ }, (next) => {
1151
+ if (fiber.recovering === token && fiber.scope.active) pass(() => recover(fiber, next, handler.parent));
1152
+ });
1153
+ }
1154
+ function isThenable(value) {
1155
+ return !!value && typeof value.then == "function";
1156
+ }
1157
+
1158
+ //#endregion
1159
+ //#region src/render/component.ts
1160
+ function mountFunction(value, parent, before, context, boundary, appearance) {
1161
+ const fiber = range("function", parent, before, context);
1162
+ const resolved = componentProps(value.type, value.props, appearance);
1163
+ fiber.key = value.key;
1164
+ fiber.type = value.type;
1165
+ fiber.props = observe(resolved.props);
1166
+ fiber.boundary = boundary;
1167
+ fiber.appearance = resolved.appearance;
1168
+ fiber.scope = makeScope(context, (passive) => run(fiber, passive));
1169
+ fiber.render = () => enter(fiber.scope, () => {
1170
+ const type = latest(fiber.type);
1171
+ return resolve(type, fiber.props, () => call(type, fiber.props));
1172
+ });
1173
+ track(fiber.type, fiber.scope);
1174
+ probing(fiber);
1175
+ return complete(fiber, () => {
1176
+ run(fiber, passiveRender);
1177
+ });
1178
+ }
1179
+ function mountOwnedComponent(value, parent, before, context, boundary, appearance) {
1180
+ const resolved = componentProps(value.type, value.props, appearance);
1181
+ const Type = value.type;
1182
+ const props = observe(resolved.props);
1183
+ return mountComponent(new Type(props), parent, before, context, boundary, resolved.appearance, true, value.key, props);
1184
+ }
1185
+ function mountComponent(instance, parent, before, context, inherited, appearance, owned = false, key, props = instance.props) {
1186
+ const fiber = range("component", parent, before, context);
1187
+ const childContext = context.push(instance);
1188
+ const element = owned ? props : {};
1189
+ const { fallback } = instance;
1190
+ const ownBoundary = fallback !== void 0 && fallback !== false || element.catch || instance.catch ? {
1191
+ catch: element.catch || instance.catch ? (error) => {
1192
+ return (owned && fiber.props.catch || instance.catch).call(instance, error, instance);
1193
+ } : void 0,
1194
+ fallback: () => instance.fallback,
1195
+ owner: fiber,
1196
+ parent: inherited
1197
+ } : inherited;
1198
+ fiber.boundary = ownBoundary;
1199
+ if (ownBoundary !== inherited) fiber.ownBoundary = ownBoundary;
1200
+ fiber.childContext = childContext;
1201
+ fiber.instance = instance;
1202
+ fiber.key = owned ? key : instance.key;
1203
+ fiber.type = instance.constructor;
1204
+ fiber.props = props;
1205
+ fiber.owned = owned;
1206
+ fiber.appearance = appearance;
1207
+ fiber.scope = makeScope(childContext, (passive) => run(fiber, passive));
1208
+ fiber.render = () => enter(fiber.scope, () => {
1209
+ return unbind(fiber.value.render).call(fiber.value, fiber.props);
1210
+ });
1211
+ probing(fiber);
1212
+ let first = true;
1213
+ let proxy = instance;
1214
+ fiber.release = watch(instance, (current, events) => {
1215
+ const { applied, scope } = fiber;
1216
+ proxy = current;
1217
+ fiber.applied = void 0;
1218
+ if (!first && scope.active) if (applied && events.includes("props")) transition(() => schedule(scope));
1219
+ else schedule(scope);
1220
+ first = false;
1221
+ }, void 0, transition);
1222
+ Object.defineProperty(fiber, "value", { get: () => proxy });
1223
+ try {
1224
+ complete(fiber, () => {
1225
+ run(fiber, passiveRender);
1226
+ });
1227
+ } finally {
1228
+ if (owned && !fiber.dead) inserted(fiber, () => fiber.cleanup = instance.mount?.());
1229
+ }
1230
+ return fiber;
1231
+ }
1232
+ function run(fiber, passive) {
1233
+ const result = attempt(fiber, passive, fiber.render);
1234
+ if (result !== true) return result;
1235
+ }
1236
+ function probing(fiber) {
1237
+ const scope = fiber.scope;
1238
+ scope.empty = () => !fiber.children.length;
1239
+ scope.probe = () => {
1240
+ try {
1241
+ scope.probed = { output: consume(fiber, fiber.render) };
1242
+ } catch (thrown) {
1243
+ if (isThenable(thrown)) return thrown;
1244
+ }
1245
+ };
1246
+ }
1247
+ function patchFunction(fiber, value, appearance) {
1248
+ const resolved = componentProps(value.type, value.props, appearance);
1249
+ if (fiber.type !== value.type) {
1250
+ untrack(fiber.type, fiber.scope);
1251
+ fiber.type = value.type;
1252
+ track(fiber.type, fiber.scope);
1253
+ }
1254
+ fiber.appearance = resolved.appearance;
1255
+ fiber.props = observe(resolved.props);
1256
+ rerun(fiber, () => run(fiber, passiveRender));
1257
+ }
1258
+ function patchComponent(fiber, value, appearance) {
1259
+ const resolved = isVNode(value) ? componentProps(value.type, value.props, appearance) : {
1260
+ appearance,
1261
+ props: fiber.props
1262
+ };
1263
+ fiber.appearance = resolved.appearance;
1264
+ const props = isVNode(value) ? observe(resolved.props) : resolved.props;
1265
+ if (isVNode(value) && props !== fiber.props) {
1266
+ const instance = fiber.instance;
1267
+ if (passiveRender) fiber.applied = true;
1268
+ instance.props = props;
1269
+ }
1270
+ fiber.props = props;
1271
+ rerun(fiber, () => run(fiber, passiveRender));
1272
+ }
1273
+ function rerun(fiber, run) {
1274
+ claim$1(fiber.scope);
1275
+ run();
1276
+ settle$1(fiber.scope);
1277
+ }
1278
+ function unmountComponent(fiber) {
1279
+ if (typeof fiber.cleanup == "function") fiber.cleanup();
1280
+ fiber.childContext?.pop();
1281
+ if (fiber.owned && !fiber.instance.get(null)) fiber.instance.set(null);
1282
+ }
1283
+ function renderable(value) {
1284
+ return value instanceof Component;
1285
+ }
1286
+
1287
+ //#endregion
1288
+ //#region src/render/mount.ts
1289
+ function complete(fiber, work) {
1290
+ try {
1291
+ work();
1292
+ } catch (error) {
1293
+ if (!hold(fiber, error)) unmountFiber(fiber);
1294
+ throw error;
1295
+ }
1296
+ return fiber;
1297
+ }
1298
+ function mount(value, parent, before, context, boundary, appearance) {
1299
+ if (typeof value == "string" || typeof value == "number" || typeof value == "bigint") {
1300
+ const text = document.createTextNode(String(value));
1301
+ parent.insertBefore(text, before);
1302
+ return {
1303
+ kind: "text",
1304
+ value,
1305
+ context,
1306
+ start: text,
1307
+ end: text,
1308
+ children: []
1309
+ };
1310
+ }
1311
+ if (renderable(value)) return mountComponent(value, parent, before, context, boundary, appearance);
1312
+ if (value instanceof Model) notRenderable(value.constructor);
1313
+ if (isCollection(value)) return mountCollection(value, parent, before, context, boundary, appearance);
1314
+ if (!isVNode(value)) throw new TypeError(`Cannot render ${String(value)}.`);
1315
+ if (value.type === Fragment$1) return mountFragment(value, parent, before, context, boundary, appearance);
1316
+ if (value.type === PORTAL) return mountPortal(value, parent, before, context, boundary, appearance);
1317
+ if (typeof value.type == "string") return mountElement(value, parent, before, context, boundary, appearance);
1318
+ if (typeof value.type != "function") throw new Error(`Cannot render ${String(value.type)}.`);
1319
+ if (value.type === Component || value.type.prototype instanceof Component) return mountOwnedComponent(value, parent, before, context, boundary, appearance);
1320
+ if (value.type.prototype instanceof Model) notRenderable(value.type);
1321
+ return mountFunction(value, parent, before, context, boundary, appearance);
1322
+ }
1323
+ function mountFragment(value, parent, before, context, boundary, appearance) {
1324
+ const fiber = range("fragment", parent, before, context);
1325
+ fiber.key = value.key;
1326
+ fiber.type = Fragment$1;
1327
+ fiber.appearance = appearance;
1328
+ return complete(fiber, () => {
1329
+ reconcile(fiber, value.props.children, context, boundary, appearance);
1330
+ });
1331
+ }
1332
+ function patchText(fiber, value) {
1333
+ const next = String(value);
1334
+ if (fiber.start.nodeValue !== next) fiber.start.nodeValue = next;
1335
+ fiber.value = value;
1336
+ }
1337
+ function patchFragment(fiber, value, context, appearance) {
1338
+ fiber.context = context;
1339
+ fiber.appearance = appearance;
1340
+ reconcile(fiber, value.props.children, context, fiber.boundary, appearance);
1341
+ }
1342
+ function unmountFiber(fiber) {
1343
+ fiber.dead = true;
1344
+ unwait(fiber);
1345
+ for (let index = fiber.children.length - 1; index >= 0; index--) unmountFiber(fiber.children[index]);
1346
+ if (fiber.placeholder) unmountFiber(fiber.placeholder);
1347
+ fiber.suspended?.forEach((clear) => clear());
1348
+ if (fiber.kind == "function") untrack(fiber.type, fiber.scope);
1349
+ if (fiber.scope) dispose(fiber.scope);
1350
+ fiber.release?.();
1351
+ if (fiber.kind == "element") unmountElement(fiber);
1352
+ else if (fiber.kind == "component") unmountComponent(fiber);
1353
+ else if (fiber.kind == "portal") unmountPortal(fiber);
1354
+ removeRange(fiber.start, fiber.end);
1355
+ }
1356
+ function notRenderable(type) {
1357
+ throw new Error(`${type.name} is a Model - extend Component to render it, or provide it with <Component for={${type.name}}>.`);
1358
+ }
1359
+
1360
+ //#endregion
1361
+ //#region src/render/render.ts
1362
+ const roots = /* @__PURE__ */ new WeakMap();
1363
+ const focusing = [];
1364
+ let passiveRender = false;
1365
+ let depth = 0;
1366
+ function render(node, container) {
1367
+ roots.get(container)?.();
1368
+ container.replaceChildren();
1369
+ const context = new Context(Context.root);
1370
+ const fiber = range("fragment", container, null, context);
1371
+ try {
1372
+ pass(() => {
1373
+ const appearanceContext = appearanceRoot();
1374
+ reconcile(fiber, node, context, void 0, appearanceContext ? {
1375
+ context: appearanceContext,
1376
+ entries: []
1377
+ } : void 0);
1378
+ });
1379
+ } catch (error) {
1380
+ unmountFiber(fiber);
1381
+ context.pop();
1382
+ throw error;
1383
+ }
1384
+ let active = true;
1385
+ const unmount = () => {
1386
+ if (!active) return;
1387
+ active = false;
1388
+ unmountFiber(fiber);
1389
+ context.pop();
1390
+ roots.delete(container);
1391
+ };
1392
+ roots.set(container, unmount);
1393
+ return unmount;
1394
+ }
1395
+ function pass(work) {
1396
+ depth++;
1397
+ try {
1398
+ return work();
1399
+ } finally {
1400
+ if (!--depth) {
1401
+ settle();
1402
+ focus();
1403
+ }
1404
+ }
1405
+ }
1406
+ function focus() {
1407
+ for (const element of focusing.splice(0)) if (element.isConnected) element.focus();
1408
+ }
1409
+ function attempt(fiber, passive, render) {
1410
+ const previous = passiveRender;
1411
+ const scope = fiber.scope;
1412
+ const probed = scope.probed;
1413
+ const empty = !fiber.children.length;
1414
+ scope.probed = void 0;
1415
+ passiveRender ||= passive;
1416
+ if (passive && !depth && empty && !fiber.stash) fiber.staging ||= fragment();
1417
+ const run = () => pass(() => {
1418
+ try {
1419
+ reconcile(fiber, probed ? probed.output : consume(fiber, render), scope.context, fiber.boundary, renderedAppearance(fiber));
1420
+ if (fiber.staging) {
1421
+ fiber.end.parentNode.insertBefore(fiber.staging, fiber.end);
1422
+ attach(fiber.staging);
1423
+ fiber.staging = void 0;
1424
+ }
1425
+ if (!fiber.recovering) unwait(fiber);
1426
+ fiber.retried = void 0;
1427
+ return true;
1428
+ } catch (thrown) {
1429
+ return suspend(fiber, thrown, passive, empty);
1430
+ }
1431
+ });
1432
+ try {
1433
+ return passive ? batched(run) : run();
1434
+ } finally {
1435
+ passiveRender = previous;
1403
1436
  }
1404
1437
  }
1405
1438