sinwan 1.0.0 → 1.1.1

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.
Files changed (54) hide show
  1. package/dist/cjs/index.development.js +1012 -112
  2. package/dist/cjs/index.development.js.map +16 -14
  3. package/dist/cjs/index.production.min.js +2 -2
  4. package/dist/cjs/index.production.min.js.map +16 -14
  5. package/dist/cjs/renderer/index.development.js +467 -29
  6. package/dist/cjs/renderer/index.development.js.map +11 -9
  7. package/dist/cjs/renderer/index.production.min.js +2 -2
  8. package/dist/cjs/renderer/index.production.min.js.map +11 -9
  9. package/dist/cjs/server/index.development.js +573 -48
  10. package/dist/cjs/server/index.development.js.map +10 -7
  11. package/dist/cjs/server/index.production.min.js +2 -2
  12. package/dist/cjs/server/index.production.min.js.map +10 -7
  13. package/dist/component/control-flow.d.ts +54 -1
  14. package/dist/component/control-flow.d.ts.map +1 -1
  15. package/dist/component/index.d.ts +2 -2
  16. package/dist/component/index.d.ts.map +1 -1
  17. package/dist/esm/index.development.js +1010 -110
  18. package/dist/esm/index.development.js.map +16 -14
  19. package/dist/esm/index.production.min.js +2 -2
  20. package/dist/esm/index.production.min.js.map +16 -14
  21. package/dist/esm/renderer/index.development.js +467 -29
  22. package/dist/esm/renderer/index.development.js.map +11 -9
  23. package/dist/esm/renderer/index.production.min.js +2 -2
  24. package/dist/esm/renderer/index.production.min.js.map +11 -9
  25. package/dist/esm/server/index.development.js +573 -48
  26. package/dist/esm/server/index.development.js.map +10 -7
  27. package/dist/esm/server/index.production.min.js +2 -2
  28. package/dist/esm/server/index.production.min.js.map +10 -7
  29. package/dist/hydration/walk.d.ts.map +1 -1
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/reactivity/index.d.ts +1 -0
  33. package/dist/reactivity/index.d.ts.map +1 -1
  34. package/dist/reactivity/normalization.d.ts +19 -0
  35. package/dist/reactivity/normalization.d.ts.map +1 -0
  36. package/dist/renderer/attributes.d.ts +11 -0
  37. package/dist/renderer/attributes.d.ts.map +1 -1
  38. package/dist/renderer/index.d.ts +1 -1
  39. package/dist/renderer/index.d.ts.map +1 -1
  40. package/dist/renderer/render-children.d.ts.map +1 -1
  41. package/dist/renderer/render-control-flow.d.ts +3 -3
  42. package/dist/renderer/render-control-flow.d.ts.map +1 -1
  43. package/dist/renderer/render-element.d.ts.map +1 -1
  44. package/dist/renderer/types.d.ts +8 -1
  45. package/dist/renderer/types.d.ts.map +1 -1
  46. package/dist/renderer/unmount.d.ts.map +1 -1
  47. package/dist/server/attribute-utils.d.ts +2 -0
  48. package/dist/server/attribute-utils.d.ts.map +1 -0
  49. package/dist/server/hydration-markers.d.ts.map +1 -1
  50. package/dist/server/renderer.d.ts.map +1 -1
  51. package/dist/server/stream.d.ts.map +1 -1
  52. package/dist/types.d.ts +2 -2
  53. package/dist/types.d.ts.map +1 -1
  54. package/package.json +5 -5
@@ -383,7 +383,6 @@ function signal(initial) {
383
383
  function isSignal(value) {
384
384
  return value != null && typeof value === "object" && SIGNAL_BRAND in value;
385
385
  }
386
-
387
386
  // src/reactivity/computed.ts
388
387
  var COMPUTED_BRAND = Symbol("Sinwan:computed");
389
388
 
@@ -435,7 +434,32 @@ function computed(getter) {
435
434
  function isComputed(value) {
436
435
  return value != null && typeof value === "object" && COMPUTED_BRAND in value;
437
436
  }
438
-
437
+ // src/reactivity/batch.ts
438
+ var batchDepth = 0;
439
+ function batch(fn) {
440
+ batchDepth++;
441
+ try {
442
+ fn();
443
+ } finally {
444
+ batchDepth--;
445
+ if (batchDepth === 0) {
446
+ flushSync();
447
+ }
448
+ }
449
+ }
450
+ // src/reactivity/normalization.ts
451
+ function isReactive(value) {
452
+ return isSignal(value) || isComputed(value) || typeof value === "function";
453
+ }
454
+ function resolve(value) {
455
+ if (isSignal(value) || isComputed(value)) {
456
+ return value.value;
457
+ }
458
+ if (typeof value === "function") {
459
+ return value();
460
+ }
461
+ return value;
462
+ }
439
463
  // src/renderer/events.ts
440
464
  function isEventProp(key) {
441
465
  return key.length > 2 && key[0] === "o" && key[1] === "n" && key[2] >= "A" && key[2] <= "Z";
@@ -577,10 +601,11 @@ function applyAttributes(el, props) {
577
601
  for (const [key, value] of Object.entries(props)) {
578
602
  if (SKIP_PROPS.has(key) || isEventProp(key))
579
603
  continue;
580
- if (isSignal(value) || isComputed(value)) {
604
+ if (isReactive(value)) {
605
+ const state = { previousStyleProps: new Set };
581
606
  let initialized = false;
582
607
  const dispose = effect(() => {
583
- setSingleAttribute(el, key, value.value);
608
+ setSingleAttribute(el, key, resolve(value), state);
584
609
  if (initialized) {
585
610
  queueUpdatedHooks(owner);
586
611
  }
@@ -593,10 +618,10 @@ function applyAttributes(el, props) {
593
618
  }
594
619
  return disposers;
595
620
  }
596
- function setSingleAttribute(el, key, value) {
597
- const attrName = PROP_ALIASES[key] ?? key;
621
+ function setSingleAttribute(el, key, value, state) {
622
+ const attrName = resolveAttributeName(key);
598
623
  if (attrName === "style" && typeof value === "object" && value !== null) {
599
- applyStyle(el, value);
624
+ applyStyle(el, value, state);
600
625
  return;
601
626
  }
602
627
  if (attrName === "class" && typeof value === "object" && value !== null) {
@@ -605,6 +630,9 @@ function setSingleAttribute(el, key, value) {
605
630
  }
606
631
  if (value == null || value === false) {
607
632
  domOps.removeAttribute(el, attrName);
633
+ if (attrName === "style" && state) {
634
+ state.previousStyleProps.clear();
635
+ }
608
636
  if (DOM_PROPERTIES.has(attrName)) {
609
637
  domOps.setProperty(el, attrName, attrName === "value" ? "" : false);
610
638
  }
@@ -612,25 +640,59 @@ function setSingleAttribute(el, key, value) {
612
640
  }
613
641
  if (value === true) {
614
642
  domOps.setAttribute(el, attrName, "");
643
+ if (attrName === "style" && state) {
644
+ state.previousStyleProps.clear();
645
+ }
615
646
  if (DOM_PROPERTIES.has(attrName)) {
616
647
  domOps.setProperty(el, attrName, true);
617
648
  }
618
649
  return;
619
650
  }
620
651
  if (DOM_PROPERTIES.has(attrName)) {
652
+ if (attrName === "style" && state) {
653
+ state.previousStyleProps.clear();
654
+ }
621
655
  domOps.setProperty(el, attrName, value);
622
656
  return;
623
657
  }
658
+ if (attrName === "style" && state) {
659
+ state.previousStyleProps.clear();
660
+ }
624
661
  domOps.setAttribute(el, attrName, String(value));
625
662
  }
626
- function applyStyle(el, styles) {
663
+ function resolveAttributeName(key) {
664
+ return PROP_ALIASES[key] ?? key;
665
+ }
666
+ function applyStyle(el, styles, state) {
667
+ const nextProps = new Set;
627
668
  for (const [prop, val] of Object.entries(styles)) {
669
+ nextProps.add(prop);
670
+ if (val == null) {
671
+ removeStyleProperty(el, prop);
672
+ continue;
673
+ }
628
674
  if (prop.includes("-")) {
629
- el.style.setProperty(prop, val);
675
+ el.style.setProperty(prop, String(val));
630
676
  } else {
631
677
  el.style[prop] = val;
632
678
  }
633
679
  }
680
+ if (!state) {
681
+ return;
682
+ }
683
+ for (const previousProp of state.previousStyleProps) {
684
+ if (!nextProps.has(previousProp)) {
685
+ removeStyleProperty(el, previousProp);
686
+ }
687
+ }
688
+ state.previousStyleProps = nextProps;
689
+ }
690
+ function removeStyleProperty(el, prop) {
691
+ if (prop.includes("-")) {
692
+ el.style.removeProperty(prop);
693
+ } else {
694
+ el.style[prop] = "";
695
+ }
634
696
  }
635
697
  function applyClass(el, value) {
636
698
  let classStr;
@@ -647,6 +709,12 @@ function applyClass(el, value) {
647
709
  // src/component/control-flow.ts
648
710
  var SHOW_TYPE = Symbol.for("Sinwan.Show");
649
711
  var FOR_TYPE = Symbol.for("Sinwan.For");
712
+ var SWITCH_TYPE = Symbol.for("Sinwan.Switch");
713
+ var MATCH_TYPE = Symbol.for("Sinwan.Match");
714
+ var INDEX_TYPE = Symbol.for("Sinwan.Index");
715
+ var KEY_TYPE = Symbol.for("Sinwan.Key");
716
+ var DYNAMIC_TYPE = Symbol.for("Sinwan.Dynamic");
717
+ var PORTAL_TYPE = Symbol.for("Sinwan.Portal");
650
718
  function Show(props) {
651
719
  return {
652
720
  tag: SHOW_TYPE,
@@ -661,12 +729,114 @@ function For(props) {
661
729
  children: []
662
730
  };
663
731
  }
732
+ function Switch(props) {
733
+ return {
734
+ tag: SWITCH_TYPE,
735
+ props,
736
+ children: []
737
+ };
738
+ }
739
+ function Match(props) {
740
+ return {
741
+ tag: MATCH_TYPE,
742
+ props,
743
+ children: []
744
+ };
745
+ }
746
+ function Index(props) {
747
+ return {
748
+ tag: INDEX_TYPE,
749
+ props,
750
+ children: []
751
+ };
752
+ }
753
+ function Key(props) {
754
+ return {
755
+ tag: KEY_TYPE,
756
+ props,
757
+ children: []
758
+ };
759
+ }
760
+ function Dynamic(props) {
761
+ return {
762
+ tag: DYNAMIC_TYPE,
763
+ props,
764
+ children: []
765
+ };
766
+ }
767
+ function Visible(props) {
768
+ const {
769
+ when,
770
+ as = "span",
771
+ style,
772
+ children,
773
+ ...rest
774
+ } = props;
775
+ const visibleStyle = computed(() => {
776
+ const base = readReactive(style);
777
+ const visible = Boolean(readReactive(when));
778
+ if (typeof base === "string") {
779
+ return visible ? base : appendHiddenDisplay(base);
780
+ }
781
+ const styleObject = base && typeof base === "object" ? { ...base } : {};
782
+ styleObject.display = visible ? styleObject.display : "none";
783
+ return styleObject;
784
+ });
785
+ return {
786
+ tag: as,
787
+ props: {
788
+ ...rest,
789
+ style: visibleStyle,
790
+ children
791
+ },
792
+ children: normalizeChildren2(children)
793
+ };
794
+ }
795
+ function Portal(props) {
796
+ return {
797
+ tag: PORTAL_TYPE,
798
+ props,
799
+ children: []
800
+ };
801
+ }
664
802
  function isShowElement(element) {
665
803
  return element.tag === SHOW_TYPE;
666
804
  }
667
805
  function isForElement(element) {
668
806
  return element.tag === FOR_TYPE;
669
807
  }
808
+ function isSwitchElement(element) {
809
+ return element.tag === SWITCH_TYPE;
810
+ }
811
+ function isMatchElement(element) {
812
+ return element.tag === MATCH_TYPE;
813
+ }
814
+ function isIndexElement(element) {
815
+ return element.tag === INDEX_TYPE;
816
+ }
817
+ function isKeyElement(element) {
818
+ return element.tag === KEY_TYPE;
819
+ }
820
+ function isDynamicElement(element) {
821
+ return element.tag === DYNAMIC_TYPE;
822
+ }
823
+ function isPortalElement(element) {
824
+ return element.tag === PORTAL_TYPE;
825
+ }
826
+ function normalizeChildren2(children) {
827
+ if (children == null || typeof children === "boolean") {
828
+ return [];
829
+ }
830
+ return Array.isArray(children) ? children : [children];
831
+ }
832
+ function readReactive(value) {
833
+ return resolve(value);
834
+ }
835
+ function appendHiddenDisplay(style) {
836
+ const trimmed = style.trim();
837
+ const separator = trimmed.length > 0 && !trimmed.endsWith(";") ? ";" : "";
838
+ return `${trimmed}${separator}display:none`;
839
+ }
670
840
 
671
841
  // src/renderer/unmount.ts
672
842
  function getMountedDomNodes(node) {
@@ -689,6 +859,8 @@ function getMountedDomNodes(node) {
689
859
  ];
690
860
  case "component":
691
861
  return node.children.flatMap((child) => getMountedDomNodes(child));
862
+ case "portal":
863
+ return [node.anchor];
692
864
  }
693
865
  }
694
866
  function unmountNode(node) {
@@ -733,6 +905,13 @@ function unmountNode(node) {
733
905
  unmountNode(child);
734
906
  }
735
907
  break;
908
+ case "portal":
909
+ node.dispose();
910
+ for (const child of node.children) {
911
+ removeMountedNode(child);
912
+ }
913
+ node.children = [];
914
+ break;
736
915
  }
737
916
  }
738
917
  function removeMountedNode(node) {
@@ -747,6 +926,9 @@ function removeMountedNode(node) {
747
926
 
748
927
  // src/renderer/render-control-flow.ts
749
928
  function renderControlFlowToDOM(element, parent, anchor, namespace) {
929
+ if (isPortalElement(element)) {
930
+ return renderPortal(element, parent, anchor, namespace);
931
+ }
750
932
  const startAnchor = domOps.createComment("Sinwan-b");
751
933
  const endAnchor = domOps.createComment("/Sinwan-b");
752
934
  insertNode(parent, startAnchor, anchor);
@@ -764,6 +946,14 @@ function renderControlFlowToDOM(element, parent, anchor, namespace) {
764
946
  disposeEffect = renderShowBlock(element, block, parent, namespace, owner);
765
947
  } else if (isForElement(element)) {
766
948
  disposeEffect = renderForBlock(element, block, parent, namespace, owner);
949
+ } else if (isSwitchElement(element)) {
950
+ disposeEffect = renderSwitchBlock(element, block, parent, namespace, owner);
951
+ } else if (isIndexElement(element)) {
952
+ disposeEffect = renderIndexBlock(element, block, parent, namespace, owner);
953
+ } else if (isKeyElement(element)) {
954
+ disposeEffect = renderKeyBlock(element, block, parent, namespace, owner);
955
+ } else if (isDynamicElement(element)) {
956
+ disposeEffect = renderDynamicBlock(element, block, parent, namespace, owner);
767
957
  }
768
958
  return block;
769
959
  }
@@ -771,7 +961,7 @@ function renderShowBlock(element, block, parent, namespace, owner) {
771
961
  let initialized = false;
772
962
  return effect(() => {
773
963
  clearChildren(block);
774
- const when = readReactive(element.props.when);
964
+ const when = readReactive2(element.props.when);
775
965
  const content = withOptionalInstance(owner, () => when ? resolveShowChildren(element, when) : element.props.fallback);
776
966
  block.children = renderBlockContent(content, parent, block.endAnchor, namespace, owner);
777
967
  if (initialized) {
@@ -785,7 +975,7 @@ function renderForBlock(element, block, parent, namespace, owner) {
785
975
  let records = [];
786
976
  return effect(() => {
787
977
  const props = element.props;
788
- const items = readReactive(props.each);
978
+ const items = readReactive2(props.each);
789
979
  const list = Array.isArray(items) ? items : [];
790
980
  const renderChild = props.children;
791
981
  if (typeof renderChild !== "function") {
@@ -797,6 +987,19 @@ function renderForBlock(element, block, parent, namespace, owner) {
797
987
  initialized = true;
798
988
  return;
799
989
  }
990
+ if (list.length === 0) {
991
+ clearChildren(block);
992
+ records = [];
993
+ block.children = renderBlockContent(props.fallback, parent, block.endAnchor, namespace, owner);
994
+ if (initialized) {
995
+ fireMountedAndQueueUpdated(owner);
996
+ }
997
+ initialized = true;
998
+ return;
999
+ }
1000
+ if (records.length === 0 && block.children.length > 0) {
1001
+ clearChildren(block);
1002
+ }
800
1003
  const oldByKey = new Map;
801
1004
  for (const record of records) {
802
1005
  oldByKey.set(record.key, record);
@@ -836,6 +1039,137 @@ function renderForBlock(element, block, parent, namespace, owner) {
836
1039
  initialized = true;
837
1040
  });
838
1041
  }
1042
+ function renderSwitchBlock(element, block, parent, namespace, owner) {
1043
+ let initialized = false;
1044
+ return effect(() => {
1045
+ clearChildren(block);
1046
+ const content = withOptionalInstance(owner, () => resolveSwitchContent(element));
1047
+ block.children = renderBlockContent(content, parent, block.endAnchor, namespace, owner);
1048
+ if (initialized) {
1049
+ fireMountedAndQueueUpdated(owner);
1050
+ }
1051
+ initialized = true;
1052
+ });
1053
+ }
1054
+ function renderIndexBlock(element, block, parent, namespace, owner) {
1055
+ let initialized = false;
1056
+ let records = [];
1057
+ return effect(() => {
1058
+ const props = element.props;
1059
+ const items = readReactive2(props.each);
1060
+ const list = Array.isArray(items) ? items : [];
1061
+ const renderChild = props.children;
1062
+ if (typeof renderChild !== "function") {
1063
+ clearChildren(block);
1064
+ records = [];
1065
+ if (initialized) {
1066
+ queueUpdatedHooks(owner);
1067
+ }
1068
+ initialized = true;
1069
+ return;
1070
+ }
1071
+ if (list.length === 0) {
1072
+ clearChildren(block);
1073
+ records = [];
1074
+ block.children = renderBlockContent(props.fallback, parent, block.endAnchor, namespace, owner);
1075
+ if (initialized) {
1076
+ fireMountedAndQueueUpdated(owner);
1077
+ }
1078
+ initialized = true;
1079
+ return;
1080
+ }
1081
+ if (records.length === 0 && block.children.length > 0) {
1082
+ clearChildren(block);
1083
+ }
1084
+ for (let index = 0;index < list.length; index++) {
1085
+ const existing = records[index];
1086
+ if (existing) {
1087
+ existing.item.value = list[index];
1088
+ continue;
1089
+ }
1090
+ const itemSignal = signal(list[index]);
1091
+ const record = {
1092
+ item: itemSignal,
1093
+ mounted: withOptionalInstance(owner, () => renderNodeToDOM(renderChild(() => itemSignal.value, index), parent, block.endAnchor, namespace))
1094
+ };
1095
+ records.push(record);
1096
+ }
1097
+ while (records.length > list.length) {
1098
+ const removed = records.pop();
1099
+ removeMountedNode(removed.mounted);
1100
+ }
1101
+ block.children = records.map((record) => record.mounted);
1102
+ if (initialized) {
1103
+ fireMountedAndQueueUpdated(owner);
1104
+ }
1105
+ initialized = true;
1106
+ });
1107
+ }
1108
+ function renderKeyBlock(element, block, parent, namespace, owner) {
1109
+ let initialized = false;
1110
+ let hasKey = false;
1111
+ let currentKey;
1112
+ return effect(() => {
1113
+ const key = readReactive2(element.props.when);
1114
+ if (hasKey && Object.is(currentKey, key)) {
1115
+ return;
1116
+ }
1117
+ currentKey = key;
1118
+ hasKey = true;
1119
+ clearChildren(block);
1120
+ const content = withOptionalInstance(owner, () => resolveKeyChildren(element, key));
1121
+ block.children = renderBlockContent(content, parent, block.endAnchor, namespace, owner);
1122
+ if (initialized) {
1123
+ fireMountedAndQueueUpdated(owner);
1124
+ }
1125
+ initialized = true;
1126
+ });
1127
+ }
1128
+ function renderDynamicBlock(element, block, parent, namespace, owner) {
1129
+ let initialized = false;
1130
+ let hasTag = false;
1131
+ let currentTag;
1132
+ return effect(() => {
1133
+ const tag = readReactive2(element.props.component);
1134
+ if (hasTag && Object.is(currentTag, tag)) {
1135
+ return;
1136
+ }
1137
+ currentTag = tag;
1138
+ hasTag = true;
1139
+ clearChildren(block);
1140
+ const content = tag ? createDynamicElement(element, tag) : null;
1141
+ block.children = renderBlockContent(content, parent, block.endAnchor, namespace, owner);
1142
+ if (initialized) {
1143
+ fireMountedAndQueueUpdated(owner);
1144
+ }
1145
+ initialized = true;
1146
+ });
1147
+ }
1148
+ function renderPortal(element, parent, anchor, namespace) {
1149
+ const placeholder = domOps.createComment("Sinwan-p");
1150
+ insertNode(parent, placeholder, anchor);
1151
+ const owner = getCurrentInstance();
1152
+ let disposeEffect = () => {};
1153
+ const portal = {
1154
+ type: "portal",
1155
+ anchor: placeholder,
1156
+ children: [],
1157
+ dispose: () => disposeEffect()
1158
+ };
1159
+ let initialized = false;
1160
+ disposeEffect = effect(() => {
1161
+ clearPortalChildren(portal);
1162
+ const target = resolvePortalTarget(element.props.mount);
1163
+ if (target) {
1164
+ portal.children = renderBlockContent(element.props.children ?? element.children, target, null, namespace, owner);
1165
+ }
1166
+ if (initialized) {
1167
+ fireMountedAndQueueUpdated(owner);
1168
+ }
1169
+ initialized = true;
1170
+ });
1171
+ return portal;
1172
+ }
839
1173
  function resolveShowChildren(element, value) {
840
1174
  const children = element.props.children ?? element.children;
841
1175
  if (typeof children === "function") {
@@ -843,6 +1177,47 @@ function resolveShowChildren(element, value) {
843
1177
  }
844
1178
  return children;
845
1179
  }
1180
+ function resolveSwitchContent(element) {
1181
+ const props = element.props;
1182
+ const children = normalizeContent(props.children ?? element.children);
1183
+ for (const child of children) {
1184
+ const match = getMatchElement(child);
1185
+ if (!match) {
1186
+ continue;
1187
+ }
1188
+ const when = readReactive2(match.props.when);
1189
+ if (when) {
1190
+ return resolveMatchChildren(match, when);
1191
+ }
1192
+ }
1193
+ return props.fallback;
1194
+ }
1195
+ function resolveMatchChildren(element, value) {
1196
+ const children = element.props.children ?? element.children;
1197
+ if (typeof children === "function") {
1198
+ return children(value);
1199
+ }
1200
+ return children;
1201
+ }
1202
+ function resolveKeyChildren(element, value) {
1203
+ const children = element.props.children ?? element.children;
1204
+ if (typeof children === "function") {
1205
+ return children(value);
1206
+ }
1207
+ return children;
1208
+ }
1209
+ function createDynamicElement(element, tag) {
1210
+ if (typeof tag !== "string" && typeof tag !== "function") {
1211
+ return null;
1212
+ }
1213
+ const { component, ...props } = element.props;
1214
+ const children = normalizeContent(props.children ?? element.children);
1215
+ return {
1216
+ tag,
1217
+ props,
1218
+ children
1219
+ };
1220
+ }
846
1221
  function renderBlockContent(content, parent, anchor, namespace, owner) {
847
1222
  if (content == null || typeof content === "boolean") {
848
1223
  return [];
@@ -856,6 +1231,12 @@ function clearChildren(block) {
856
1231
  }
857
1232
  block.children = [];
858
1233
  }
1234
+ function clearPortalChildren(portal) {
1235
+ for (const child of portal.children) {
1236
+ removeMountedNode(child);
1237
+ }
1238
+ portal.children = [];
1239
+ }
859
1240
  function moveBeforeEnd(parent, mounted, endAnchor) {
860
1241
  for (const node of getMountedDomNodes(mounted)) {
861
1242
  domOps.insertBefore(parent, node, endAnchor);
@@ -870,8 +1251,42 @@ function fireMountedAndQueueUpdated(owner) {
870
1251
  function withOptionalInstance(owner, fn) {
871
1252
  return owner ? withInstance(owner, fn) : fn();
872
1253
  }
873
- function readReactive(value) {
874
- return isSignal(value) || isComputed(value) ? value.value : value;
1254
+ function readReactive2(value) {
1255
+ return resolve(value);
1256
+ }
1257
+ function normalizeContent(content) {
1258
+ if (content == null || typeof content === "boolean") {
1259
+ return [];
1260
+ }
1261
+ return Array.isArray(content) ? content : [content];
1262
+ }
1263
+ function isElementLike(value) {
1264
+ return value != null && typeof value === "object" && "tag" in value;
1265
+ }
1266
+ function getMatchElement(value) {
1267
+ if (!isElementLike(value)) {
1268
+ return null;
1269
+ }
1270
+ if (isMatchElement(value)) {
1271
+ return value;
1272
+ }
1273
+ return value.tag === Match ? Match(value.props) : null;
1274
+ }
1275
+ function resolvePortalTarget(value) {
1276
+ const target = readReactive2(value);
1277
+ if (target == null) {
1278
+ return typeof document === "undefined" ? null : document.body;
1279
+ }
1280
+ if (typeof target === "string") {
1281
+ return document.querySelector(target);
1282
+ }
1283
+ if (typeof target === "function") {
1284
+ return target();
1285
+ }
1286
+ if (typeof target === "object" && "nodeType" in target) {
1287
+ return target;
1288
+ }
1289
+ return null;
875
1290
  }
876
1291
  function insertNode(parent, child, anchor) {
877
1292
  if (anchor) {
@@ -905,10 +1320,13 @@ function renderElementToDOM(element, parent, anchor = null, namespace = null) {
905
1320
  if (tag === "" || tag === Fragment) {
906
1321
  return renderFragmentToDOM(children, parent, anchor, namespace);
907
1322
  }
908
- if (tag === Show || tag === For) {
1323
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1324
+ return renderElementToDOM(tag(props), parent, anchor, namespace);
1325
+ }
1326
+ if (tag === Visible) {
909
1327
  return renderElementToDOM(tag(props), parent, anchor, namespace);
910
1328
  }
911
- if (isShowElement(element) || isForElement(element)) {
1329
+ if (isShowElement(element) || isForElement(element) || isSwitchElement(element) || isIndexElement(element) || isKeyElement(element) || isDynamicElement(element) || isPortalElement(element)) {
912
1330
  return renderControlFlowToDOM(element, parent, anchor, namespace);
913
1331
  }
914
1332
  if (typeof tag === "function") {
@@ -1055,19 +1473,8 @@ function renderNodeToDOM(node, parent, anchor = null, namespace = null) {
1055
1473
  insertNode2(parent, text2, anchor);
1056
1474
  return { type: "text", node: text2 };
1057
1475
  }
1058
- if (isSignal(node) || isComputed(node)) {
1059
- const text2 = domOps.createTextNode(String(node.value));
1060
- insertNode2(parent, text2, anchor);
1061
- const owner = getCurrentInstance();
1062
- let initialized = false;
1063
- const dispose = effect(() => {
1064
- domOps.setTextContent(text2, String(node.value));
1065
- if (initialized) {
1066
- queueUpdatedHooks(owner);
1067
- }
1068
- initialized = true;
1069
- });
1070
- return { type: "reactive-text", node: text2, dispose };
1476
+ if (isReactive(node)) {
1477
+ return renderReactiveNodeToDOM(node, parent, anchor, namespace);
1071
1478
  }
1072
1479
  if (Array.isArray(node)) {
1073
1480
  return renderArrayToDOM(node, parent, anchor, namespace);
@@ -1104,6 +1511,37 @@ function renderChildrenToDOM(children, parent, namespace = null) {
1104
1511
  }
1105
1512
  return mounted;
1106
1513
  }
1514
+ function renderReactiveNodeToDOM(reactive, parent, anchor, namespace) {
1515
+ const startAnchor = domOps.createComment("Sinwan-r");
1516
+ const endAnchor = domOps.createComment("/Sinwan-r");
1517
+ insertNode2(parent, startAnchor, anchor);
1518
+ insertNode2(parent, endAnchor, anchor);
1519
+ const owner = getCurrentInstance();
1520
+ let mountedContent = null;
1521
+ let initialized = false;
1522
+ const block = {
1523
+ type: "reactive-block",
1524
+ startAnchor,
1525
+ endAnchor,
1526
+ children: [],
1527
+ dispose: () => {}
1528
+ };
1529
+ block.dispose = effect(() => {
1530
+ if (mountedContent) {
1531
+ removeMountedNode(mountedContent);
1532
+ }
1533
+ const value = resolve(reactive);
1534
+ mountedContent = renderNodeToDOM(value, parent, endAnchor, namespace);
1535
+ block.children = [mountedContent];
1536
+ if (initialized) {
1537
+ if (owner)
1538
+ fireMountedHooks(owner);
1539
+ queueUpdatedHooks(owner);
1540
+ }
1541
+ initialized = true;
1542
+ });
1543
+ return block;
1544
+ }
1107
1545
  function insertNode2(parent, child, anchor) {
1108
1546
  if (anchor) {
1109
1547
  domOps.insertBefore(parent, child, anchor);
@@ -1221,13 +1659,44 @@ function isSafeHtml(value) {
1221
1659
  return value instanceof HtmlEscapedString;
1222
1660
  }
1223
1661
 
1224
- // src/server/renderer.ts
1225
- var componentCache = new WeakMap;
1226
- var pageRegistry = new Map;
1227
- function registerPage(name, page) {
1228
- pageRegistry.set(name, page);
1229
- }
1230
- function getPage(name) {
1662
+ // src/server/attribute-utils.ts
1663
+ var PROP_ALIASES2 = {
1664
+ className: "class",
1665
+ htmlFor: "for",
1666
+ tabIndex: "tabindex",
1667
+ crossOrigin: "crossorigin"
1668
+ };
1669
+ function renderServerAttribute(key, value) {
1670
+ const attrName = PROP_ALIASES2[key] ?? key;
1671
+ if (value == null || value === false) {
1672
+ return "";
1673
+ }
1674
+ if (value === true) {
1675
+ return ` ${attrName}`;
1676
+ }
1677
+ const attrValue = attrName === "class" && typeof value === "object" ? stringifyClass(value) : attrName === "style" && typeof value === "object" ? stringifyStyle(value) : String(value);
1678
+ return ` ${attrName}="${escapeHtml(attrValue)}"`;
1679
+ }
1680
+ function stringifyClass(value) {
1681
+ if (Array.isArray(value)) {
1682
+ return value.filter(Boolean).join(" ");
1683
+ }
1684
+ return Object.entries(value).filter(([, enabled]) => Boolean(enabled)).map(([name]) => name).join(" ");
1685
+ }
1686
+ function stringifyStyle(value) {
1687
+ return Object.entries(value).filter(([, val]) => val != null && val !== false).map(([prop, val]) => `${toKebabCase(prop)}:${String(val)}`).join(";");
1688
+ }
1689
+ function toKebabCase(value) {
1690
+ return value.includes("-") ? value : value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
1691
+ }
1692
+
1693
+ // src/server/renderer.ts
1694
+ var componentCache = new WeakMap;
1695
+ var pageRegistry = new Map;
1696
+ function registerPage(name, page) {
1697
+ pageRegistry.set(name, page);
1698
+ }
1699
+ function getPage(name) {
1231
1700
  return pageRegistry.get(name);
1232
1701
  }
1233
1702
  function hasPage(name) {
@@ -1268,13 +1737,41 @@ async function renderToString(node) {
1268
1737
  }
1269
1738
  async function renderElement(element) {
1270
1739
  const { tag, props, children } = element;
1740
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1741
+ return renderElement(tag(props));
1742
+ }
1743
+ if (tag === Visible) {
1744
+ return renderElement(tag(props));
1745
+ }
1271
1746
  if (isShowElement(element)) {
1272
- const when = readReactive2(props.when);
1747
+ const when = readReactive3(props.when);
1273
1748
  return renderToString(when ? resolveShowChildren2(element, when) : props.fallback);
1274
1749
  }
1275
1750
  if (isForElement(element)) {
1276
1751
  return renderForElement(element);
1277
1752
  }
1753
+ if (isSwitchElement(element)) {
1754
+ return renderToString(resolveSwitchContent2(element));
1755
+ }
1756
+ if (isMatchElement(element)) {
1757
+ const when = readReactive3(props.when);
1758
+ return renderToString(when ? resolveMatchChildren2(element, when) : null);
1759
+ }
1760
+ if (isIndexElement(element)) {
1761
+ return renderIndexElement(element);
1762
+ }
1763
+ if (isKeyElement(element)) {
1764
+ const key = readReactive3(props.when);
1765
+ return renderToString(resolveKeyChildren2(element, key));
1766
+ }
1767
+ if (isDynamicElement(element)) {
1768
+ const tag2 = readReactive3(props.component);
1769
+ const dynamic = createDynamicElement2(element, tag2);
1770
+ return dynamic ? renderElement(dynamic) : "";
1771
+ }
1772
+ if (isPortalElement(element)) {
1773
+ return "";
1774
+ }
1278
1775
  if (typeof tag === "function") {
1279
1776
  const result = await tag(props);
1280
1777
  return renderToString(result);
@@ -1314,17 +1811,10 @@ function renderAttributes(props) {
1314
1811
  if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
1315
1812
  continue;
1316
1813
  }
1317
- const resolvedValue = readReactive2(value);
1814
+ const resolvedValue = readReactive3(value);
1318
1815
  if (resolvedValue == null || resolvedValue === false)
1319
1816
  continue;
1320
- const attrName = key === "className" ? "class" : key;
1321
- const finalName = attrName === "htmlFor" ? "for" : attrName;
1322
- if (resolvedValue === true) {
1323
- attrs += ` ${finalName}`;
1324
- continue;
1325
- }
1326
- const attrValue = escapeHtml(String(resolvedValue));
1327
- attrs += ` ${finalName}="${attrValue}"`;
1817
+ attrs += renderServerAttribute(key, resolvedValue);
1328
1818
  }
1329
1819
  return attrs;
1330
1820
  }
@@ -1340,13 +1830,69 @@ function isSlots(children) {
1340
1830
  }
1341
1831
  async function renderForElement(element) {
1342
1832
  const props = element.props;
1343
- const each = readReactive2(props.each);
1833
+ const each = readReactive3(props.each);
1344
1834
  if (!Array.isArray(each) || typeof props.children !== "function") {
1345
- return "";
1835
+ return props.fallback ? renderToString(props.fallback) : "";
1836
+ }
1837
+ if (each.length === 0) {
1838
+ return props.fallback ? renderToString(props.fallback) : "";
1346
1839
  }
1347
1840
  const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(item, () => index))));
1348
1841
  return rendered.join("");
1349
1842
  }
1843
+ async function renderIndexElement(element) {
1844
+ const props = element.props;
1845
+ const each = readReactive3(props.each);
1846
+ if (!Array.isArray(each) || typeof props.children !== "function") {
1847
+ return props.fallback ? renderToString(props.fallback) : "";
1848
+ }
1849
+ if (each.length === 0) {
1850
+ return props.fallback ? renderToString(props.fallback) : "";
1851
+ }
1852
+ const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(() => item, index))));
1853
+ return rendered.join("");
1854
+ }
1855
+ function resolveSwitchContent2(element) {
1856
+ const props = element.props;
1857
+ const children = normalizeContent2(props.children ?? element.children);
1858
+ for (const child of children) {
1859
+ const match = getMatchElement2(child);
1860
+ if (!match) {
1861
+ continue;
1862
+ }
1863
+ const when = readReactive3(match.props.when);
1864
+ if (when) {
1865
+ return resolveMatchChildren2(match, when);
1866
+ }
1867
+ }
1868
+ return props.fallback;
1869
+ }
1870
+ function resolveMatchChildren2(element, value) {
1871
+ const children = element.props.children ?? element.children;
1872
+ if (typeof children === "function") {
1873
+ return children(value);
1874
+ }
1875
+ return children;
1876
+ }
1877
+ function resolveKeyChildren2(element, value) {
1878
+ const children = element.props.children ?? element.children;
1879
+ if (typeof children === "function") {
1880
+ return children(value);
1881
+ }
1882
+ return children;
1883
+ }
1884
+ function createDynamicElement2(element, tag) {
1885
+ if (typeof tag !== "string" && typeof tag !== "function") {
1886
+ return null;
1887
+ }
1888
+ const { component, ...props } = element.props;
1889
+ const children = normalizeContent2(props.children ?? element.children);
1890
+ return {
1891
+ tag,
1892
+ props,
1893
+ children
1894
+ };
1895
+ }
1350
1896
  function resolveShowChildren2(element, value) {
1351
1897
  const children = element.props.children ?? element.children;
1352
1898
  if (typeof children === "function") {
@@ -1354,9 +1900,27 @@ function resolveShowChildren2(element, value) {
1354
1900
  }
1355
1901
  return children;
1356
1902
  }
1357
- function readReactive2(value) {
1903
+ function readReactive3(value) {
1358
1904
  return isSignal(value) || isComputed(value) ? value.value : value;
1359
1905
  }
1906
+ function normalizeContent2(content) {
1907
+ if (content == null || typeof content === "boolean") {
1908
+ return [];
1909
+ }
1910
+ return Array.isArray(content) ? content : [content];
1911
+ }
1912
+ function isElementLike2(value) {
1913
+ return value != null && typeof value === "object" && "tag" in value;
1914
+ }
1915
+ function getMatchElement2(value) {
1916
+ if (!isElementLike2(value)) {
1917
+ return null;
1918
+ }
1919
+ if (isMatchElement(value)) {
1920
+ return value;
1921
+ }
1922
+ return value.tag === Match ? Match(value.props) : null;
1923
+ }
1360
1924
  // src/hydration/markers.ts
1361
1925
  var COMP_ID_ATTR = "data-sinwan-id";
1362
1926
  var COMP_ID_PREFIX = "c";
@@ -1481,8 +2045,16 @@ async function streamNode(node, controller, encoder) {
1481
2045
  }
1482
2046
  async function streamElement(element, controller, encoder) {
1483
2047
  const { tag, props, children } = element;
2048
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
2049
+ await streamElement(tag(props), controller, encoder);
2050
+ return;
2051
+ }
2052
+ if (tag === Visible) {
2053
+ await streamElement(tag(props), controller, encoder);
2054
+ return;
2055
+ }
1484
2056
  if (isShowElement(element)) {
1485
- const when = readReactive3(props.when);
2057
+ const when = readReactive4(props.when);
1486
2058
  await streamNode(when ? resolveShowChildren3(element, when) : props.fallback, controller, encoder);
1487
2059
  return;
1488
2060
  }
@@ -1490,6 +2062,35 @@ async function streamElement(element, controller, encoder) {
1490
2062
  await streamForElement(element, controller, encoder);
1491
2063
  return;
1492
2064
  }
2065
+ if (isSwitchElement(element)) {
2066
+ await streamNode(resolveSwitchContent3(element), controller, encoder);
2067
+ return;
2068
+ }
2069
+ if (isMatchElement(element)) {
2070
+ const when = readReactive4(props.when);
2071
+ await streamNode(when ? resolveMatchChildren3(element, when) : null, controller, encoder);
2072
+ return;
2073
+ }
2074
+ if (isIndexElement(element)) {
2075
+ await streamIndexElement(element, controller, encoder);
2076
+ return;
2077
+ }
2078
+ if (isKeyElement(element)) {
2079
+ const key = readReactive4(props.when);
2080
+ await streamNode(resolveKeyChildren3(element, key), controller, encoder);
2081
+ return;
2082
+ }
2083
+ if (isDynamicElement(element)) {
2084
+ const dynamicTag = readReactive4(props.component);
2085
+ const dynamic = createDynamicElement3(element, dynamicTag);
2086
+ if (dynamic) {
2087
+ await streamElement(dynamic, controller, encoder);
2088
+ }
2089
+ return;
2090
+ }
2091
+ if (isPortalElement(element)) {
2092
+ return;
2093
+ }
1493
2094
  if (typeof tag === "function") {
1494
2095
  const result = await tag(props);
1495
2096
  await streamNode(result, controller, encoder);
@@ -1524,16 +2125,10 @@ function renderAttributes2(props) {
1524
2125
  if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
1525
2126
  continue;
1526
2127
  }
1527
- const resolvedValue = readReactive3(value);
2128
+ const resolvedValue = readReactive4(value);
1528
2129
  if (resolvedValue == null || resolvedValue === false)
1529
2130
  continue;
1530
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1531
- if (resolvedValue === true) {
1532
- attrs += ` ${attrName}`;
1533
- continue;
1534
- }
1535
- const attrValue = escapeHtml(String(resolvedValue));
1536
- attrs += ` ${attrName}="${attrValue}"`;
2131
+ attrs += renderServerAttribute(key, resolvedValue);
1537
2132
  }
1538
2133
  return attrs;
1539
2134
  }
@@ -1578,12 +2173,16 @@ async function streamHydratableElement(element, controller, encoder, ctx, isComp
1578
2173
  }
1579
2174
  return;
1580
2175
  }
1581
- if (tag === Show || tag === For) {
2176
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
2177
+ await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
2178
+ return;
2179
+ }
2180
+ if (tag === Visible) {
1582
2181
  await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
1583
2182
  return;
1584
2183
  }
1585
2184
  if (isShowElement(element)) {
1586
- const when = readReactive3(props.when);
2185
+ const when = readReactive4(props.when);
1587
2186
  await streamHydratableNodeToController(when ? resolveShowChildren3(element, when) : props.fallback, controller, encoder, ctx, isComponentRoot);
1588
2187
  return;
1589
2188
  }
@@ -1591,6 +2190,35 @@ async function streamHydratableElement(element, controller, encoder, ctx, isComp
1591
2190
  await streamHydratableForElement(element, controller, encoder, ctx);
1592
2191
  return;
1593
2192
  }
2193
+ if (isSwitchElement(element)) {
2194
+ await streamHydratableNodeToController(resolveSwitchContent3(element), controller, encoder, ctx, isComponentRoot);
2195
+ return;
2196
+ }
2197
+ if (isMatchElement(element)) {
2198
+ const when = readReactive4(props.when);
2199
+ await streamHydratableNodeToController(when ? resolveMatchChildren3(element, when) : null, controller, encoder, ctx, isComponentRoot);
2200
+ return;
2201
+ }
2202
+ if (isIndexElement(element)) {
2203
+ await streamHydratableIndexElement(element, controller, encoder, ctx);
2204
+ return;
2205
+ }
2206
+ if (isKeyElement(element)) {
2207
+ const key = readReactive4(props.when);
2208
+ await streamHydratableNodeToController(resolveKeyChildren3(element, key), controller, encoder, ctx, isComponentRoot);
2209
+ return;
2210
+ }
2211
+ if (isDynamicElement(element)) {
2212
+ const dynamicTag = readReactive4(props.component);
2213
+ const dynamic = createDynamicElement3(element, dynamicTag);
2214
+ if (dynamic) {
2215
+ await streamHydratableElement(dynamic, controller, encoder, ctx, isComponentRoot);
2216
+ }
2217
+ return;
2218
+ }
2219
+ if (isPortalElement(element)) {
2220
+ return;
2221
+ }
1594
2222
  if (typeof tag === "function") {
1595
2223
  await streamHydratableComponent(tag, props, controller, encoder, ctx, true);
1596
2224
  return;
@@ -1633,14 +2261,42 @@ async function streamHydratableIntrinsic(tag, props, children, controller, encod
1633
2261
  }
1634
2262
  async function streamHydratableForElement(element, controller, encoder, ctx) {
1635
2263
  const props = element.props;
1636
- const each = readReactive3(props.each);
2264
+ const each = readReactive4(props.each);
1637
2265
  if (!Array.isArray(each) || typeof props.children !== "function") {
2266
+ if (props.fallback) {
2267
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
2268
+ }
2269
+ return;
2270
+ }
2271
+ if (each.length === 0) {
2272
+ if (props.fallback) {
2273
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
2274
+ }
1638
2275
  return;
1639
2276
  }
1640
2277
  for (let index = 0;index < each.length; index++) {
1641
2278
  await streamHydratableNodeToController(props.children(each[index], () => index), controller, encoder, ctx);
1642
2279
  }
1643
2280
  }
2281
+ async function streamHydratableIndexElement(element, controller, encoder, ctx) {
2282
+ const props = element.props;
2283
+ const each = readReactive4(props.each);
2284
+ if (!Array.isArray(each) || typeof props.children !== "function") {
2285
+ if (props.fallback) {
2286
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
2287
+ }
2288
+ return;
2289
+ }
2290
+ if (each.length === 0) {
2291
+ if (props.fallback) {
2292
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
2293
+ }
2294
+ return;
2295
+ }
2296
+ for (let index = 0;index < each.length; index++) {
2297
+ await streamHydratableNodeToController(props.children(() => each[index], index), controller, encoder, ctx);
2298
+ }
2299
+ }
1644
2300
  function renderHydratableAttributes(props, ctx, isComponentRoot) {
1645
2301
  let attrs = "";
1646
2302
  if (isComponentRoot) {
@@ -1655,15 +2311,10 @@ function renderHydratableAttributes(props, ctx, isComponentRoot) {
1655
2311
  eventParts.push(`${toEventName(key)}:${ctx.eventIndex++}`);
1656
2312
  continue;
1657
2313
  }
1658
- const resolvedValue = readReactive3(value);
2314
+ const resolvedValue = readReactive4(value);
1659
2315
  if (resolvedValue == null || resolvedValue === false)
1660
2316
  continue;
1661
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1662
- if (resolvedValue === true) {
1663
- attrs += ` ${attrName}`;
1664
- continue;
1665
- }
1666
- attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
2317
+ attrs += renderServerAttribute(key, resolvedValue);
1667
2318
  }
1668
2319
  if (eventParts.length > 0) {
1669
2320
  attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
@@ -1675,14 +2326,42 @@ function enqueue(controller, encoder, html) {
1675
2326
  }
1676
2327
  async function streamForElement(element, controller, encoder) {
1677
2328
  const props = element.props;
1678
- const each = readReactive3(props.each);
2329
+ const each = readReactive4(props.each);
1679
2330
  if (!Array.isArray(each) || typeof props.children !== "function") {
2331
+ if (props.fallback) {
2332
+ await streamNode(props.fallback, controller, encoder);
2333
+ }
2334
+ return;
2335
+ }
2336
+ if (each.length === 0) {
2337
+ if (props.fallback) {
2338
+ await streamNode(props.fallback, controller, encoder);
2339
+ }
1680
2340
  return;
1681
2341
  }
1682
2342
  for (let index = 0;index < each.length; index++) {
1683
2343
  await streamNode(props.children(each[index], () => index), controller, encoder);
1684
2344
  }
1685
2345
  }
2346
+ async function streamIndexElement(element, controller, encoder) {
2347
+ const props = element.props;
2348
+ const each = readReactive4(props.each);
2349
+ if (!Array.isArray(each) || typeof props.children !== "function") {
2350
+ if (props.fallback) {
2351
+ await streamNode(props.fallback, controller, encoder);
2352
+ }
2353
+ return;
2354
+ }
2355
+ if (each.length === 0) {
2356
+ if (props.fallback) {
2357
+ await streamNode(props.fallback, controller, encoder);
2358
+ }
2359
+ return;
2360
+ }
2361
+ for (let index = 0;index < each.length; index++) {
2362
+ await streamNode(props.children(() => each[index], index), controller, encoder);
2363
+ }
2364
+ }
1686
2365
  function resolveShowChildren3(element, value) {
1687
2366
  const children = element.props.children ?? element.children;
1688
2367
  if (typeof children === "function") {
@@ -1690,9 +2369,68 @@ function resolveShowChildren3(element, value) {
1690
2369
  }
1691
2370
  return children;
1692
2371
  }
1693
- function readReactive3(value) {
2372
+ function resolveSwitchContent3(element) {
2373
+ const props = element.props;
2374
+ const children = normalizeContent3(props.children ?? element.children);
2375
+ for (const child of children) {
2376
+ const match = getMatchElement3(child);
2377
+ if (!match) {
2378
+ continue;
2379
+ }
2380
+ const when = readReactive4(match.props.when);
2381
+ if (when) {
2382
+ return resolveMatchChildren3(match, when);
2383
+ }
2384
+ }
2385
+ return props.fallback;
2386
+ }
2387
+ function resolveMatchChildren3(element, value) {
2388
+ const children = element.props.children ?? element.children;
2389
+ if (typeof children === "function") {
2390
+ return children(value);
2391
+ }
2392
+ return children;
2393
+ }
2394
+ function resolveKeyChildren3(element, value) {
2395
+ const children = element.props.children ?? element.children;
2396
+ if (typeof children === "function") {
2397
+ return children(value);
2398
+ }
2399
+ return children;
2400
+ }
2401
+ function createDynamicElement3(element, tag) {
2402
+ if (typeof tag !== "string" && typeof tag !== "function") {
2403
+ return null;
2404
+ }
2405
+ const { component, ...props } = element.props;
2406
+ const children = normalizeContent3(props.children ?? element.children);
2407
+ return {
2408
+ tag,
2409
+ props,
2410
+ children
2411
+ };
2412
+ }
2413
+ function readReactive4(value) {
1694
2414
  return isSignal(value) || isComputed(value) ? value.value : value;
1695
2415
  }
2416
+ function normalizeContent3(content) {
2417
+ if (content == null || typeof content === "boolean") {
2418
+ return [];
2419
+ }
2420
+ return Array.isArray(content) ? content : [content];
2421
+ }
2422
+ function isElementLike3(value) {
2423
+ return value != null && typeof value === "object" && "tag" in value;
2424
+ }
2425
+ function getMatchElement3(value) {
2426
+ if (!isElementLike3(value)) {
2427
+ return null;
2428
+ }
2429
+ if (isMatchElement(value)) {
2430
+ return value;
2431
+ }
2432
+ return value.tag === Match ? Match(value.props) : null;
2433
+ }
1696
2434
  // src/server/hydration-markers.ts
1697
2435
  function createHydrationContext() {
1698
2436
  return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
@@ -1762,17 +2500,42 @@ function renderElementH(element, ctx, isComponentRoot) {
1762
2500
  if (tag === "") {
1763
2501
  return children.map((child) => renderNodeH(child, ctx)).join("");
1764
2502
  }
1765
- if (tag === Show || tag === For) {
2503
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
2504
+ return renderElementH(tag(props), ctx, isComponentRoot);
2505
+ }
2506
+ if (tag === Visible) {
1766
2507
  return renderElementH(tag(props), ctx, isComponentRoot);
1767
2508
  }
1768
2509
  if (isShowElement(element)) {
1769
- const when = readReactive4(props.when);
2510
+ const when = readReactive5(props.when);
1770
2511
  const content = when ? resolveShowChildren4(element, when) : props.fallback;
1771
2512
  return renderNodeMaybeRoot(content, ctx, isComponentRoot);
1772
2513
  }
1773
2514
  if (isForElement(element)) {
1774
2515
  return renderForElementH(element, ctx);
1775
2516
  }
2517
+ if (isSwitchElement(element)) {
2518
+ return renderNodeMaybeRoot(resolveSwitchContent4(element), ctx, isComponentRoot);
2519
+ }
2520
+ if (isMatchElement(element)) {
2521
+ const when = readReactive5(props.when);
2522
+ return renderNodeMaybeRoot(when ? resolveMatchChildren4(element, when) : null, ctx, isComponentRoot);
2523
+ }
2524
+ if (isIndexElement(element)) {
2525
+ return renderIndexElementH(element, ctx);
2526
+ }
2527
+ if (isKeyElement(element)) {
2528
+ const key = readReactive5(props.when);
2529
+ return renderNodeMaybeRoot(resolveKeyChildren4(element, key), ctx, isComponentRoot);
2530
+ }
2531
+ if (isDynamicElement(element)) {
2532
+ const dynamicTag = readReactive5(props.component);
2533
+ const dynamic = createDynamicElement4(element, dynamicTag);
2534
+ return dynamic ? renderElementH(dynamic, ctx, isComponentRoot) : "";
2535
+ }
2536
+ if (isPortalElement(element)) {
2537
+ return "";
2538
+ }
1776
2539
  if (typeof tag === "function") {
1777
2540
  return renderComponentH(tag, props, ctx);
1778
2541
  }
@@ -1819,13 +2582,7 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
1819
2582
  if (isSignal(value) || isComputed(value)) {
1820
2583
  resolvedValue = value.value;
1821
2584
  }
1822
- if (resolvedValue === true) {
1823
- const attrName2 = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1824
- attrs += ` ${attrName2}`;
1825
- continue;
1826
- }
1827
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1828
- attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
2585
+ attrs += renderServerAttribute(key, resolvedValue);
1829
2586
  }
1830
2587
  if (eventParts.length > 0) {
1831
2588
  attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
@@ -1848,12 +2605,26 @@ function renderNodeMaybeRoot(node, ctx, isComponentRoot) {
1848
2605
  }
1849
2606
  function renderForElementH(element, ctx) {
1850
2607
  const props = element.props;
1851
- const each = readReactive4(props.each);
2608
+ const each = readReactive5(props.each);
1852
2609
  if (!Array.isArray(each) || typeof props.children !== "function") {
1853
- return "";
2610
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
2611
+ }
2612
+ if (each.length === 0) {
2613
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1854
2614
  }
1855
2615
  return each.map((item, index) => renderNodeH(props.children(item, () => index), ctx)).join("");
1856
2616
  }
2617
+ function renderIndexElementH(element, ctx) {
2618
+ const props = element.props;
2619
+ const each = readReactive5(props.each);
2620
+ if (!Array.isArray(each) || typeof props.children !== "function") {
2621
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
2622
+ }
2623
+ if (each.length === 0) {
2624
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
2625
+ }
2626
+ return each.map((item, index) => renderNodeH(props.children(() => item, index), ctx)).join("");
2627
+ }
1857
2628
  function resolveShowChildren4(element, value) {
1858
2629
  const children = element.props.children ?? element.children;
1859
2630
  if (typeof children === "function") {
@@ -1861,9 +2632,68 @@ function resolveShowChildren4(element, value) {
1861
2632
  }
1862
2633
  return children;
1863
2634
  }
1864
- function readReactive4(value) {
2635
+ function resolveSwitchContent4(element) {
2636
+ const props = element.props;
2637
+ const children = normalizeContent4(props.children ?? element.children);
2638
+ for (const child of children) {
2639
+ const match = getMatchElement4(child);
2640
+ if (!match) {
2641
+ continue;
2642
+ }
2643
+ const when = readReactive5(match.props.when);
2644
+ if (when) {
2645
+ return resolveMatchChildren4(match, when);
2646
+ }
2647
+ }
2648
+ return props.fallback;
2649
+ }
2650
+ function resolveMatchChildren4(element, value) {
2651
+ const children = element.props.children ?? element.children;
2652
+ if (typeof children === "function") {
2653
+ return children(value);
2654
+ }
2655
+ return children;
2656
+ }
2657
+ function resolveKeyChildren4(element, value) {
2658
+ const children = element.props.children ?? element.children;
2659
+ if (typeof children === "function") {
2660
+ return children(value);
2661
+ }
2662
+ return children;
2663
+ }
2664
+ function createDynamicElement4(element, tag) {
2665
+ if (typeof tag !== "string" && typeof tag !== "function") {
2666
+ return null;
2667
+ }
2668
+ const { component, ...props } = element.props;
2669
+ const children = normalizeContent4(props.children ?? element.children);
2670
+ return {
2671
+ tag,
2672
+ props,
2673
+ children
2674
+ };
2675
+ }
2676
+ function readReactive5(value) {
1865
2677
  return isSignal(value) || isComputed(value) ? value.value : value;
1866
2678
  }
2679
+ function normalizeContent4(content) {
2680
+ if (content == null || typeof content === "boolean") {
2681
+ return [];
2682
+ }
2683
+ return Array.isArray(content) ? content : [content];
2684
+ }
2685
+ function isElementLike4(value) {
2686
+ return value != null && typeof value === "object" && "tag" in value;
2687
+ }
2688
+ function getMatchElement4(value) {
2689
+ if (!isElementLike4(value)) {
2690
+ return null;
2691
+ }
2692
+ if (isMatchElement(value)) {
2693
+ return value;
2694
+ }
2695
+ return value.tag === Match ? Match(value.props) : null;
2696
+ }
1867
2697
  // src/index.ts
1868
2698
  var exports_src = {};
1869
2699
  __export(exports_src, {
@@ -1910,25 +2740,19 @@ __export(exports_src, {
1910
2740
  createComponent: () => createComponent,
1911
2741
  computed: () => computed,
1912
2742
  batch: () => batch,
2743
+ Visible: () => Visible,
2744
+ Switch: () => Switch,
1913
2745
  Show: () => Show,
2746
+ Portal: () => Portal,
2747
+ Match: () => Match,
2748
+ Key: () => Key,
2749
+ Index: () => Index,
1914
2750
  HtmlEscapedString: () => HtmlEscapedString,
1915
2751
  Fragment: () => Fragment,
1916
- For: () => For
2752
+ For: () => For,
2753
+ Dynamic: () => Dynamic
1917
2754
  });
1918
2755
  module.exports = __toCommonJS(exports_src);
1919
- // src/reactivity/batch.ts
1920
- var batchDepth = 0;
1921
- function batch(fn) {
1922
- batchDepth++;
1923
- try {
1924
- fn();
1925
- } finally {
1926
- batchDepth--;
1927
- if (batchDepth === 0) {
1928
- flushSync();
1929
- }
1930
- }
1931
- }
1932
2756
  // src/component/lifecycle.ts
1933
2757
  function onMounted(fn) {
1934
2758
  const instance = getCurrentInstance();
@@ -2081,10 +2905,16 @@ function hydrateElement(element, cursor) {
2081
2905
  if (tag === "") {
2082
2906
  return hydrateArray(children, cursor);
2083
2907
  }
2084
- if (tag === Show || tag === For) {
2908
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
2909
+ return hydrateElement(tag(props), cursor);
2910
+ }
2911
+ if (tag === Visible) {
2085
2912
  return hydrateElement(tag(props), cursor);
2086
2913
  }
2087
- if (isShowElement(element) || isForElement(element)) {
2914
+ if (isPortalElement(element)) {
2915
+ return renderControlFlowToDOM(element, cursor.parent, cursor.current, null);
2916
+ }
2917
+ if (isShowElement(element) || isForElement(element) || isSwitchElement(element) || isIndexElement(element) || isKeyElement(element) || isDynamicElement(element)) {
2088
2918
  return hydrateControlFlow(element, cursor);
2089
2919
  }
2090
2920
  if (typeof tag === "function") {
@@ -2127,20 +2957,13 @@ function hydrateAttributes(el, props) {
2127
2957
  const disposers = [];
2128
2958
  const owner = getCurrentInstance();
2129
2959
  for (const [key, value] of Object.entries(props)) {
2130
- if (key === "children" || key === "key" || key === "ref" || isEventProp(key))
2960
+ if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key))
2131
2961
  continue;
2132
2962
  if (isSignal(value) || isComputed(value)) {
2963
+ const state = { previousStyleProps: new Set };
2133
2964
  let initialized = false;
2134
2965
  const dispose = effect(() => {
2135
- const v = value.value;
2136
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
2137
- if (v == null || v === false) {
2138
- el.removeAttribute(attrName);
2139
- } else if (v === true) {
2140
- el.setAttribute(attrName, "");
2141
- } else {
2142
- el.setAttribute(attrName, String(v));
2143
- }
2966
+ setSingleAttribute(el, key, value.value, state);
2144
2967
  if (initialized) {
2145
2968
  queueUpdatedHooks(owner);
2146
2969
  }
@@ -2153,16 +2976,34 @@ function hydrateAttributes(el, props) {
2153
2976
  }
2154
2977
  function hydrateControlFlow(element, cursor) {
2155
2978
  if (isShowElement(element)) {
2156
- const when = readReactive5(element.props.when);
2979
+ const when = readReactive6(element.props.when);
2157
2980
  const content = when ? resolveShowChildren5(element, when) : element.props.fallback;
2158
2981
  return hydrateContent(content, cursor);
2159
2982
  }
2160
2983
  if (isForElement(element)) {
2161
2984
  const props = element.props;
2162
- const items = readReactive5(props.each);
2163
- const children = Array.isArray(items) && typeof props.children === "function" ? items.map((item, index) => props.children(item, () => index)) : [];
2985
+ const items = readReactive6(props.each);
2986
+ const children = Array.isArray(items) && typeof props.children === "function" ? items.map((item, index) => props.children(item, () => index)) : props.fallback ? [props.fallback] : [];
2987
+ return hydrateArray(children, cursor);
2988
+ }
2989
+ if (isSwitchElement(element)) {
2990
+ return hydrateContent(resolveSwitchContent5(element), cursor);
2991
+ }
2992
+ if (isIndexElement(element)) {
2993
+ const props = element.props;
2994
+ const items = readReactive6(props.each);
2995
+ const children = Array.isArray(items) && typeof props.children === "function" ? items.map((item, index) => props.children(() => item, index)) : props.fallback ? [props.fallback] : [];
2164
2996
  return hydrateArray(children, cursor);
2165
2997
  }
2998
+ if (isKeyElement(element)) {
2999
+ const key = readReactive6(element.props.when);
3000
+ return hydrateContent(resolveKeyChildren5(element, key), cursor);
3001
+ }
3002
+ if (isDynamicElement(element)) {
3003
+ const tag = readReactive6(element.props.component);
3004
+ const dynamic = createDynamicElement5(element, tag);
3005
+ return dynamic ? hydrateElement(dynamic, cursor) : hydrateArray([], cursor);
3006
+ }
2166
3007
  return hydrateArray(element.children, cursor);
2167
3008
  }
2168
3009
  function hydrateContent(content, cursor) {
@@ -2178,9 +3019,68 @@ function resolveShowChildren5(element, value) {
2178
3019
  }
2179
3020
  return children;
2180
3021
  }
2181
- function readReactive5(value) {
3022
+ function resolveSwitchContent5(element) {
3023
+ const props = element.props;
3024
+ const children = normalizeContent5(props.children ?? element.children);
3025
+ for (const child of children) {
3026
+ const match = getMatchElement5(child);
3027
+ if (!match) {
3028
+ continue;
3029
+ }
3030
+ const when = readReactive6(match.props.when);
3031
+ if (when) {
3032
+ return resolveMatchChildren5(match, when);
3033
+ }
3034
+ }
3035
+ return props.fallback;
3036
+ }
3037
+ function resolveMatchChildren5(element, value) {
3038
+ const children = element.props.children ?? element.children;
3039
+ if (typeof children === "function") {
3040
+ return children(value);
3041
+ }
3042
+ return children;
3043
+ }
3044
+ function resolveKeyChildren5(element, value) {
3045
+ const children = element.props.children ?? element.children;
3046
+ if (typeof children === "function") {
3047
+ return children(value);
3048
+ }
3049
+ return children;
3050
+ }
3051
+ function createDynamicElement5(element, tag) {
3052
+ if (typeof tag !== "string" && typeof tag !== "function") {
3053
+ return null;
3054
+ }
3055
+ const { component, ...props } = element.props;
3056
+ const children = normalizeContent5(props.children ?? element.children);
3057
+ return {
3058
+ tag,
3059
+ props,
3060
+ children
3061
+ };
3062
+ }
3063
+ function readReactive6(value) {
2182
3064
  return isSignal(value) || isComputed(value) ? value.value : value;
2183
3065
  }
3066
+ function normalizeContent5(content) {
3067
+ if (content == null || typeof content === "boolean") {
3068
+ return [];
3069
+ }
3070
+ return Array.isArray(content) ? content : [content];
3071
+ }
3072
+ function isElementLike5(value) {
3073
+ return value != null && typeof value === "object" && "tag" in value;
3074
+ }
3075
+ function getMatchElement5(value) {
3076
+ if (!isElementLike5(value)) {
3077
+ return null;
3078
+ }
3079
+ if (isMatchElement(value)) {
3080
+ return value;
3081
+ }
3082
+ return value.tag === Match ? Match(value.props) : null;
3083
+ }
2184
3084
  function applyRef2(el, ref) {
2185
3085
  const value = ref;
2186
3086
  if (!value) {
@@ -2284,5 +3184,5 @@ function hydrate(component, container, props) {
2284
3184
  };
2285
3185
  }
2286
3186
 
2287
- //# debugId=82414CC0A24D81DC64756E2164756E21
3187
+ //# debugId=446E2FDDC310248664756E2164756E21
2288
3188
  //# sourceMappingURL=index.development.js.map