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
@@ -163,6 +163,37 @@ function isSafeHtml(value) {
163
163
  return value instanceof HtmlEscapedString;
164
164
  }
165
165
 
166
+ // src/server/attribute-utils.ts
167
+ var PROP_ALIASES = {
168
+ className: "class",
169
+ htmlFor: "for",
170
+ tabIndex: "tabindex",
171
+ crossOrigin: "crossorigin"
172
+ };
173
+ function renderServerAttribute(key, value) {
174
+ const attrName = PROP_ALIASES[key] ?? key;
175
+ if (value == null || value === false) {
176
+ return "";
177
+ }
178
+ if (value === true) {
179
+ return ` ${attrName}`;
180
+ }
181
+ const attrValue = attrName === "class" && typeof value === "object" ? stringifyClass(value) : attrName === "style" && typeof value === "object" ? stringifyStyle(value) : String(value);
182
+ return ` ${attrName}="${escapeHtml(attrValue)}"`;
183
+ }
184
+ function stringifyClass(value) {
185
+ if (Array.isArray(value)) {
186
+ return value.filter(Boolean).join(" ");
187
+ }
188
+ return Object.entries(value).filter(([, enabled]) => Boolean(enabled)).map(([name]) => name).join(" ");
189
+ }
190
+ function stringifyStyle(value) {
191
+ return Object.entries(value).filter(([, val]) => val != null && val !== false).map(([prop, val]) => `${toKebabCase(prop)}:${String(val)}`).join(";");
192
+ }
193
+ function toKebabCase(value) {
194
+ return value.includes("-") ? value : value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
195
+ }
196
+
166
197
  // src/reactivity/scheduler.ts
167
198
  var pendingEffects = new Set;
168
199
  var flushScheduled = false;
@@ -493,10 +524,41 @@ function bindEvents(el, props) {
493
524
  }
494
525
  return cleanups;
495
526
  }
496
-
527
+ // src/reactivity/batch.ts
528
+ var batchDepth = 0;
529
+ function batch(fn) {
530
+ batchDepth++;
531
+ try {
532
+ fn();
533
+ } finally {
534
+ batchDepth--;
535
+ if (batchDepth === 0) {
536
+ flushSync();
537
+ }
538
+ }
539
+ }
540
+ // src/reactivity/normalization.ts
541
+ function isReactive(value) {
542
+ return isSignal(value) || isComputed(value) || typeof value === "function";
543
+ }
544
+ function resolve(value) {
545
+ if (isSignal(value) || isComputed(value)) {
546
+ return value.value;
547
+ }
548
+ if (typeof value === "function") {
549
+ return value();
550
+ }
551
+ return value;
552
+ }
497
553
  // src/component/control-flow.ts
498
554
  var SHOW_TYPE = Symbol.for("Sinwan.Show");
499
555
  var FOR_TYPE = Symbol.for("Sinwan.For");
556
+ var SWITCH_TYPE = Symbol.for("Sinwan.Switch");
557
+ var MATCH_TYPE = Symbol.for("Sinwan.Match");
558
+ var INDEX_TYPE = Symbol.for("Sinwan.Index");
559
+ var KEY_TYPE = Symbol.for("Sinwan.Key");
560
+ var DYNAMIC_TYPE = Symbol.for("Sinwan.Dynamic");
561
+ var PORTAL_TYPE = Symbol.for("Sinwan.Portal");
500
562
  function Show(props) {
501
563
  return {
502
564
  tag: SHOW_TYPE,
@@ -511,12 +573,114 @@ function For(props) {
511
573
  children: []
512
574
  };
513
575
  }
576
+ function Switch(props) {
577
+ return {
578
+ tag: SWITCH_TYPE,
579
+ props,
580
+ children: []
581
+ };
582
+ }
583
+ function Match(props) {
584
+ return {
585
+ tag: MATCH_TYPE,
586
+ props,
587
+ children: []
588
+ };
589
+ }
590
+ function Index(props) {
591
+ return {
592
+ tag: INDEX_TYPE,
593
+ props,
594
+ children: []
595
+ };
596
+ }
597
+ function Key(props) {
598
+ return {
599
+ tag: KEY_TYPE,
600
+ props,
601
+ children: []
602
+ };
603
+ }
604
+ function Dynamic(props) {
605
+ return {
606
+ tag: DYNAMIC_TYPE,
607
+ props,
608
+ children: []
609
+ };
610
+ }
611
+ function Visible(props) {
612
+ const {
613
+ when,
614
+ as = "span",
615
+ style,
616
+ children,
617
+ ...rest
618
+ } = props;
619
+ const visibleStyle = computed(() => {
620
+ const base = readReactive(style);
621
+ const visible = Boolean(readReactive(when));
622
+ if (typeof base === "string") {
623
+ return visible ? base : appendHiddenDisplay(base);
624
+ }
625
+ const styleObject = base && typeof base === "object" ? { ...base } : {};
626
+ styleObject.display = visible ? styleObject.display : "none";
627
+ return styleObject;
628
+ });
629
+ return {
630
+ tag: as,
631
+ props: {
632
+ ...rest,
633
+ style: visibleStyle,
634
+ children
635
+ },
636
+ children: normalizeChildren2(children)
637
+ };
638
+ }
639
+ function Portal(props) {
640
+ return {
641
+ tag: PORTAL_TYPE,
642
+ props,
643
+ children: []
644
+ };
645
+ }
514
646
  function isShowElement(element) {
515
647
  return element.tag === SHOW_TYPE;
516
648
  }
517
649
  function isForElement(element) {
518
650
  return element.tag === FOR_TYPE;
519
651
  }
652
+ function isSwitchElement(element) {
653
+ return element.tag === SWITCH_TYPE;
654
+ }
655
+ function isMatchElement(element) {
656
+ return element.tag === MATCH_TYPE;
657
+ }
658
+ function isIndexElement(element) {
659
+ return element.tag === INDEX_TYPE;
660
+ }
661
+ function isKeyElement(element) {
662
+ return element.tag === KEY_TYPE;
663
+ }
664
+ function isDynamicElement(element) {
665
+ return element.tag === DYNAMIC_TYPE;
666
+ }
667
+ function isPortalElement(element) {
668
+ return element.tag === PORTAL_TYPE;
669
+ }
670
+ function normalizeChildren2(children) {
671
+ if (children == null || typeof children === "boolean") {
672
+ return [];
673
+ }
674
+ return Array.isArray(children) ? children : [children];
675
+ }
676
+ function readReactive(value) {
677
+ return resolve(value);
678
+ }
679
+ function appendHiddenDisplay(style) {
680
+ const trimmed = style.trim();
681
+ const separator = trimmed.length > 0 && !trimmed.endsWith(";") ? ";" : "";
682
+ return `${trimmed}${separator}display:none`;
683
+ }
520
684
 
521
685
  // src/server/renderer.ts
522
686
  var componentCache = new WeakMap;
@@ -565,13 +729,41 @@ async function renderToString(node) {
565
729
  }
566
730
  async function renderElement(element) {
567
731
  const { tag, props, children } = element;
732
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
733
+ return renderElement(tag(props));
734
+ }
735
+ if (tag === Visible) {
736
+ return renderElement(tag(props));
737
+ }
568
738
  if (isShowElement(element)) {
569
- const when = readReactive(props.when);
739
+ const when = readReactive2(props.when);
570
740
  return renderToString(when ? resolveShowChildren(element, when) : props.fallback);
571
741
  }
572
742
  if (isForElement(element)) {
573
743
  return renderForElement(element);
574
744
  }
745
+ if (isSwitchElement(element)) {
746
+ return renderToString(resolveSwitchContent(element));
747
+ }
748
+ if (isMatchElement(element)) {
749
+ const when = readReactive2(props.when);
750
+ return renderToString(when ? resolveMatchChildren(element, when) : null);
751
+ }
752
+ if (isIndexElement(element)) {
753
+ return renderIndexElement(element);
754
+ }
755
+ if (isKeyElement(element)) {
756
+ const key = readReactive2(props.when);
757
+ return renderToString(resolveKeyChildren(element, key));
758
+ }
759
+ if (isDynamicElement(element)) {
760
+ const tag2 = readReactive2(props.component);
761
+ const dynamic = createDynamicElement(element, tag2);
762
+ return dynamic ? renderElement(dynamic) : "";
763
+ }
764
+ if (isPortalElement(element)) {
765
+ return "";
766
+ }
575
767
  if (typeof tag === "function") {
576
768
  const result = await tag(props);
577
769
  return renderToString(result);
@@ -611,17 +803,10 @@ function renderAttributes(props) {
611
803
  if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
612
804
  continue;
613
805
  }
614
- const resolvedValue = readReactive(value);
806
+ const resolvedValue = readReactive2(value);
615
807
  if (resolvedValue == null || resolvedValue === false)
616
808
  continue;
617
- const attrName = key === "className" ? "class" : key;
618
- const finalName = attrName === "htmlFor" ? "for" : attrName;
619
- if (resolvedValue === true) {
620
- attrs += ` ${finalName}`;
621
- continue;
622
- }
623
- const attrValue = escapeHtml(String(resolvedValue));
624
- attrs += ` ${finalName}="${attrValue}"`;
809
+ attrs += renderServerAttribute(key, resolvedValue);
625
810
  }
626
811
  return attrs;
627
812
  }
@@ -637,13 +822,69 @@ function isSlots(children) {
637
822
  }
638
823
  async function renderForElement(element) {
639
824
  const props = element.props;
640
- const each = readReactive(props.each);
825
+ const each = readReactive2(props.each);
641
826
  if (!Array.isArray(each) || typeof props.children !== "function") {
642
- return "";
827
+ return props.fallback ? renderToString(props.fallback) : "";
828
+ }
829
+ if (each.length === 0) {
830
+ return props.fallback ? renderToString(props.fallback) : "";
643
831
  }
644
832
  const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(item, () => index))));
645
833
  return rendered.join("");
646
834
  }
835
+ async function renderIndexElement(element) {
836
+ const props = element.props;
837
+ const each = readReactive2(props.each);
838
+ if (!Array.isArray(each) || typeof props.children !== "function") {
839
+ return props.fallback ? renderToString(props.fallback) : "";
840
+ }
841
+ if (each.length === 0) {
842
+ return props.fallback ? renderToString(props.fallback) : "";
843
+ }
844
+ const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(() => item, index))));
845
+ return rendered.join("");
846
+ }
847
+ function resolveSwitchContent(element) {
848
+ const props = element.props;
849
+ const children = normalizeContent(props.children ?? element.children);
850
+ for (const child of children) {
851
+ const match = getMatchElement(child);
852
+ if (!match) {
853
+ continue;
854
+ }
855
+ const when = readReactive2(match.props.when);
856
+ if (when) {
857
+ return resolveMatchChildren(match, when);
858
+ }
859
+ }
860
+ return props.fallback;
861
+ }
862
+ function resolveMatchChildren(element, value) {
863
+ const children = element.props.children ?? element.children;
864
+ if (typeof children === "function") {
865
+ return children(value);
866
+ }
867
+ return children;
868
+ }
869
+ function resolveKeyChildren(element, value) {
870
+ const children = element.props.children ?? element.children;
871
+ if (typeof children === "function") {
872
+ return children(value);
873
+ }
874
+ return children;
875
+ }
876
+ function createDynamicElement(element, tag) {
877
+ if (typeof tag !== "string" && typeof tag !== "function") {
878
+ return null;
879
+ }
880
+ const { component, ...props } = element.props;
881
+ const children = normalizeContent(props.children ?? element.children);
882
+ return {
883
+ tag,
884
+ props,
885
+ children
886
+ };
887
+ }
647
888
  function resolveShowChildren(element, value) {
648
889
  const children = element.props.children ?? element.children;
649
890
  if (typeof children === "function") {
@@ -651,9 +892,27 @@ function resolveShowChildren(element, value) {
651
892
  }
652
893
  return children;
653
894
  }
654
- function readReactive(value) {
895
+ function readReactive2(value) {
655
896
  return isSignal(value) || isComputed(value) ? value.value : value;
656
897
  }
898
+ function normalizeContent(content) {
899
+ if (content == null || typeof content === "boolean") {
900
+ return [];
901
+ }
902
+ return Array.isArray(content) ? content : [content];
903
+ }
904
+ function isElementLike(value) {
905
+ return value != null && typeof value === "object" && "tag" in value;
906
+ }
907
+ function getMatchElement(value) {
908
+ if (!isElementLike(value)) {
909
+ return null;
910
+ }
911
+ if (isMatchElement(value)) {
912
+ return value;
913
+ }
914
+ return value.tag === Match ? Match(value.props) : null;
915
+ }
657
916
  // src/component/instance.ts
658
917
  var uidCounter = 0;
659
918
  function createComponentInstance(component, props, parent) {
@@ -877,8 +1136,16 @@ async function streamNode(node, controller, encoder) {
877
1136
  }
878
1137
  async function streamElement(element, controller, encoder) {
879
1138
  const { tag, props, children } = element;
1139
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1140
+ await streamElement(tag(props), controller, encoder);
1141
+ return;
1142
+ }
1143
+ if (tag === Visible) {
1144
+ await streamElement(tag(props), controller, encoder);
1145
+ return;
1146
+ }
880
1147
  if (isShowElement(element)) {
881
- const when = readReactive2(props.when);
1148
+ const when = readReactive3(props.when);
882
1149
  await streamNode(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder);
883
1150
  return;
884
1151
  }
@@ -886,6 +1153,35 @@ async function streamElement(element, controller, encoder) {
886
1153
  await streamForElement(element, controller, encoder);
887
1154
  return;
888
1155
  }
1156
+ if (isSwitchElement(element)) {
1157
+ await streamNode(resolveSwitchContent2(element), controller, encoder);
1158
+ return;
1159
+ }
1160
+ if (isMatchElement(element)) {
1161
+ const when = readReactive3(props.when);
1162
+ await streamNode(when ? resolveMatchChildren2(element, when) : null, controller, encoder);
1163
+ return;
1164
+ }
1165
+ if (isIndexElement(element)) {
1166
+ await streamIndexElement(element, controller, encoder);
1167
+ return;
1168
+ }
1169
+ if (isKeyElement(element)) {
1170
+ const key = readReactive3(props.when);
1171
+ await streamNode(resolveKeyChildren2(element, key), controller, encoder);
1172
+ return;
1173
+ }
1174
+ if (isDynamicElement(element)) {
1175
+ const dynamicTag = readReactive3(props.component);
1176
+ const dynamic = createDynamicElement2(element, dynamicTag);
1177
+ if (dynamic) {
1178
+ await streamElement(dynamic, controller, encoder);
1179
+ }
1180
+ return;
1181
+ }
1182
+ if (isPortalElement(element)) {
1183
+ return;
1184
+ }
889
1185
  if (typeof tag === "function") {
890
1186
  const result = await tag(props);
891
1187
  await streamNode(result, controller, encoder);
@@ -920,16 +1216,10 @@ function renderAttributes2(props) {
920
1216
  if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
921
1217
  continue;
922
1218
  }
923
- const resolvedValue = readReactive2(value);
1219
+ const resolvedValue = readReactive3(value);
924
1220
  if (resolvedValue == null || resolvedValue === false)
925
1221
  continue;
926
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
927
- if (resolvedValue === true) {
928
- attrs += ` ${attrName}`;
929
- continue;
930
- }
931
- const attrValue = escapeHtml(String(resolvedValue));
932
- attrs += ` ${attrName}="${attrValue}"`;
1222
+ attrs += renderServerAttribute(key, resolvedValue);
933
1223
  }
934
1224
  return attrs;
935
1225
  }
@@ -974,12 +1264,16 @@ async function streamHydratableElement(element, controller, encoder, ctx, isComp
974
1264
  }
975
1265
  return;
976
1266
  }
977
- if (tag === Show || tag === For) {
1267
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1268
+ await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
1269
+ return;
1270
+ }
1271
+ if (tag === Visible) {
978
1272
  await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
979
1273
  return;
980
1274
  }
981
1275
  if (isShowElement(element)) {
982
- const when = readReactive2(props.when);
1276
+ const when = readReactive3(props.when);
983
1277
  await streamHydratableNodeToController(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder, ctx, isComponentRoot);
984
1278
  return;
985
1279
  }
@@ -987,6 +1281,35 @@ async function streamHydratableElement(element, controller, encoder, ctx, isComp
987
1281
  await streamHydratableForElement(element, controller, encoder, ctx);
988
1282
  return;
989
1283
  }
1284
+ if (isSwitchElement(element)) {
1285
+ await streamHydratableNodeToController(resolveSwitchContent2(element), controller, encoder, ctx, isComponentRoot);
1286
+ return;
1287
+ }
1288
+ if (isMatchElement(element)) {
1289
+ const when = readReactive3(props.when);
1290
+ await streamHydratableNodeToController(when ? resolveMatchChildren2(element, when) : null, controller, encoder, ctx, isComponentRoot);
1291
+ return;
1292
+ }
1293
+ if (isIndexElement(element)) {
1294
+ await streamHydratableIndexElement(element, controller, encoder, ctx);
1295
+ return;
1296
+ }
1297
+ if (isKeyElement(element)) {
1298
+ const key = readReactive3(props.when);
1299
+ await streamHydratableNodeToController(resolveKeyChildren2(element, key), controller, encoder, ctx, isComponentRoot);
1300
+ return;
1301
+ }
1302
+ if (isDynamicElement(element)) {
1303
+ const dynamicTag = readReactive3(props.component);
1304
+ const dynamic = createDynamicElement2(element, dynamicTag);
1305
+ if (dynamic) {
1306
+ await streamHydratableElement(dynamic, controller, encoder, ctx, isComponentRoot);
1307
+ }
1308
+ return;
1309
+ }
1310
+ if (isPortalElement(element)) {
1311
+ return;
1312
+ }
990
1313
  if (typeof tag === "function") {
991
1314
  await streamHydratableComponent(tag, props, controller, encoder, ctx, true);
992
1315
  return;
@@ -1029,14 +1352,42 @@ async function streamHydratableIntrinsic(tag, props, children, controller, encod
1029
1352
  }
1030
1353
  async function streamHydratableForElement(element, controller, encoder, ctx) {
1031
1354
  const props = element.props;
1032
- const each = readReactive2(props.each);
1355
+ const each = readReactive3(props.each);
1033
1356
  if (!Array.isArray(each) || typeof props.children !== "function") {
1357
+ if (props.fallback) {
1358
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1359
+ }
1360
+ return;
1361
+ }
1362
+ if (each.length === 0) {
1363
+ if (props.fallback) {
1364
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1365
+ }
1034
1366
  return;
1035
1367
  }
1036
1368
  for (let index = 0;index < each.length; index++) {
1037
1369
  await streamHydratableNodeToController(props.children(each[index], () => index), controller, encoder, ctx);
1038
1370
  }
1039
1371
  }
1372
+ async function streamHydratableIndexElement(element, controller, encoder, ctx) {
1373
+ const props = element.props;
1374
+ const each = readReactive3(props.each);
1375
+ if (!Array.isArray(each) || typeof props.children !== "function") {
1376
+ if (props.fallback) {
1377
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1378
+ }
1379
+ return;
1380
+ }
1381
+ if (each.length === 0) {
1382
+ if (props.fallback) {
1383
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1384
+ }
1385
+ return;
1386
+ }
1387
+ for (let index = 0;index < each.length; index++) {
1388
+ await streamHydratableNodeToController(props.children(() => each[index], index), controller, encoder, ctx);
1389
+ }
1390
+ }
1040
1391
  function renderHydratableAttributes(props, ctx, isComponentRoot) {
1041
1392
  let attrs = "";
1042
1393
  if (isComponentRoot) {
@@ -1051,15 +1402,10 @@ function renderHydratableAttributes(props, ctx, isComponentRoot) {
1051
1402
  eventParts.push(`${toEventName(key)}:${ctx.eventIndex++}`);
1052
1403
  continue;
1053
1404
  }
1054
- const resolvedValue = readReactive2(value);
1405
+ const resolvedValue = readReactive3(value);
1055
1406
  if (resolvedValue == null || resolvedValue === false)
1056
1407
  continue;
1057
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1058
- if (resolvedValue === true) {
1059
- attrs += ` ${attrName}`;
1060
- continue;
1061
- }
1062
- attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
1408
+ attrs += renderServerAttribute(key, resolvedValue);
1063
1409
  }
1064
1410
  if (eventParts.length > 0) {
1065
1411
  attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
@@ -1071,14 +1417,42 @@ function enqueue(controller, encoder, html) {
1071
1417
  }
1072
1418
  async function streamForElement(element, controller, encoder) {
1073
1419
  const props = element.props;
1074
- const each = readReactive2(props.each);
1420
+ const each = readReactive3(props.each);
1075
1421
  if (!Array.isArray(each) || typeof props.children !== "function") {
1422
+ if (props.fallback) {
1423
+ await streamNode(props.fallback, controller, encoder);
1424
+ }
1425
+ return;
1426
+ }
1427
+ if (each.length === 0) {
1428
+ if (props.fallback) {
1429
+ await streamNode(props.fallback, controller, encoder);
1430
+ }
1076
1431
  return;
1077
1432
  }
1078
1433
  for (let index = 0;index < each.length; index++) {
1079
1434
  await streamNode(props.children(each[index], () => index), controller, encoder);
1080
1435
  }
1081
1436
  }
1437
+ async function streamIndexElement(element, controller, encoder) {
1438
+ const props = element.props;
1439
+ const each = readReactive3(props.each);
1440
+ if (!Array.isArray(each) || typeof props.children !== "function") {
1441
+ if (props.fallback) {
1442
+ await streamNode(props.fallback, controller, encoder);
1443
+ }
1444
+ return;
1445
+ }
1446
+ if (each.length === 0) {
1447
+ if (props.fallback) {
1448
+ await streamNode(props.fallback, controller, encoder);
1449
+ }
1450
+ return;
1451
+ }
1452
+ for (let index = 0;index < each.length; index++) {
1453
+ await streamNode(props.children(() => each[index], index), controller, encoder);
1454
+ }
1455
+ }
1082
1456
  function resolveShowChildren2(element, value) {
1083
1457
  const children = element.props.children ?? element.children;
1084
1458
  if (typeof children === "function") {
@@ -1086,9 +1460,68 @@ function resolveShowChildren2(element, value) {
1086
1460
  }
1087
1461
  return children;
1088
1462
  }
1089
- function readReactive2(value) {
1463
+ function resolveSwitchContent2(element) {
1464
+ const props = element.props;
1465
+ const children = normalizeContent2(props.children ?? element.children);
1466
+ for (const child of children) {
1467
+ const match = getMatchElement2(child);
1468
+ if (!match) {
1469
+ continue;
1470
+ }
1471
+ const when = readReactive3(match.props.when);
1472
+ if (when) {
1473
+ return resolveMatchChildren2(match, when);
1474
+ }
1475
+ }
1476
+ return props.fallback;
1477
+ }
1478
+ function resolveMatchChildren2(element, value) {
1479
+ const children = element.props.children ?? element.children;
1480
+ if (typeof children === "function") {
1481
+ return children(value);
1482
+ }
1483
+ return children;
1484
+ }
1485
+ function resolveKeyChildren2(element, value) {
1486
+ const children = element.props.children ?? element.children;
1487
+ if (typeof children === "function") {
1488
+ return children(value);
1489
+ }
1490
+ return children;
1491
+ }
1492
+ function createDynamicElement2(element, tag) {
1493
+ if (typeof tag !== "string" && typeof tag !== "function") {
1494
+ return null;
1495
+ }
1496
+ const { component, ...props } = element.props;
1497
+ const children = normalizeContent2(props.children ?? element.children);
1498
+ return {
1499
+ tag,
1500
+ props,
1501
+ children
1502
+ };
1503
+ }
1504
+ function readReactive3(value) {
1090
1505
  return isSignal(value) || isComputed(value) ? value.value : value;
1091
1506
  }
1507
+ function normalizeContent2(content) {
1508
+ if (content == null || typeof content === "boolean") {
1509
+ return [];
1510
+ }
1511
+ return Array.isArray(content) ? content : [content];
1512
+ }
1513
+ function isElementLike2(value) {
1514
+ return value != null && typeof value === "object" && "tag" in value;
1515
+ }
1516
+ function getMatchElement2(value) {
1517
+ if (!isElementLike2(value)) {
1518
+ return null;
1519
+ }
1520
+ if (isMatchElement(value)) {
1521
+ return value;
1522
+ }
1523
+ return value.tag === Match ? Match(value.props) : null;
1524
+ }
1092
1525
  // src/server/hydration-markers.ts
1093
1526
  function createHydrationContext() {
1094
1527
  return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
@@ -1158,17 +1591,42 @@ function renderElementH(element, ctx, isComponentRoot) {
1158
1591
  if (tag === "") {
1159
1592
  return children.map((child) => renderNodeH(child, ctx)).join("");
1160
1593
  }
1161
- if (tag === Show || tag === For) {
1594
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1595
+ return renderElementH(tag(props), ctx, isComponentRoot);
1596
+ }
1597
+ if (tag === Visible) {
1162
1598
  return renderElementH(tag(props), ctx, isComponentRoot);
1163
1599
  }
1164
1600
  if (isShowElement(element)) {
1165
- const when = readReactive3(props.when);
1601
+ const when = readReactive4(props.when);
1166
1602
  const content = when ? resolveShowChildren3(element, when) : props.fallback;
1167
1603
  return renderNodeMaybeRoot(content, ctx, isComponentRoot);
1168
1604
  }
1169
1605
  if (isForElement(element)) {
1170
1606
  return renderForElementH(element, ctx);
1171
1607
  }
1608
+ if (isSwitchElement(element)) {
1609
+ return renderNodeMaybeRoot(resolveSwitchContent3(element), ctx, isComponentRoot);
1610
+ }
1611
+ if (isMatchElement(element)) {
1612
+ const when = readReactive4(props.when);
1613
+ return renderNodeMaybeRoot(when ? resolveMatchChildren3(element, when) : null, ctx, isComponentRoot);
1614
+ }
1615
+ if (isIndexElement(element)) {
1616
+ return renderIndexElementH(element, ctx);
1617
+ }
1618
+ if (isKeyElement(element)) {
1619
+ const key = readReactive4(props.when);
1620
+ return renderNodeMaybeRoot(resolveKeyChildren3(element, key), ctx, isComponentRoot);
1621
+ }
1622
+ if (isDynamicElement(element)) {
1623
+ const dynamicTag = readReactive4(props.component);
1624
+ const dynamic = createDynamicElement3(element, dynamicTag);
1625
+ return dynamic ? renderElementH(dynamic, ctx, isComponentRoot) : "";
1626
+ }
1627
+ if (isPortalElement(element)) {
1628
+ return "";
1629
+ }
1172
1630
  if (typeof tag === "function") {
1173
1631
  return renderComponentH(tag, props, ctx);
1174
1632
  }
@@ -1215,13 +1673,7 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
1215
1673
  if (isSignal(value) || isComputed(value)) {
1216
1674
  resolvedValue = value.value;
1217
1675
  }
1218
- if (resolvedValue === true) {
1219
- const attrName2 = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1220
- attrs += ` ${attrName2}`;
1221
- continue;
1222
- }
1223
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1224
- attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
1676
+ attrs += renderServerAttribute(key, resolvedValue);
1225
1677
  }
1226
1678
  if (eventParts.length > 0) {
1227
1679
  attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
@@ -1244,12 +1696,26 @@ function renderNodeMaybeRoot(node, ctx, isComponentRoot) {
1244
1696
  }
1245
1697
  function renderForElementH(element, ctx) {
1246
1698
  const props = element.props;
1247
- const each = readReactive3(props.each);
1699
+ const each = readReactive4(props.each);
1248
1700
  if (!Array.isArray(each) || typeof props.children !== "function") {
1249
- return "";
1701
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1702
+ }
1703
+ if (each.length === 0) {
1704
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1250
1705
  }
1251
1706
  return each.map((item, index) => renderNodeH(props.children(item, () => index), ctx)).join("");
1252
1707
  }
1708
+ function renderIndexElementH(element, ctx) {
1709
+ const props = element.props;
1710
+ const each = readReactive4(props.each);
1711
+ if (!Array.isArray(each) || typeof props.children !== "function") {
1712
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1713
+ }
1714
+ if (each.length === 0) {
1715
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1716
+ }
1717
+ return each.map((item, index) => renderNodeH(props.children(() => item, index), ctx)).join("");
1718
+ }
1253
1719
  function resolveShowChildren3(element, value) {
1254
1720
  const children = element.props.children ?? element.children;
1255
1721
  if (typeof children === "function") {
@@ -1257,9 +1723,68 @@ function resolveShowChildren3(element, value) {
1257
1723
  }
1258
1724
  return children;
1259
1725
  }
1260
- function readReactive3(value) {
1726
+ function resolveSwitchContent3(element) {
1727
+ const props = element.props;
1728
+ const children = normalizeContent3(props.children ?? element.children);
1729
+ for (const child of children) {
1730
+ const match = getMatchElement3(child);
1731
+ if (!match) {
1732
+ continue;
1733
+ }
1734
+ const when = readReactive4(match.props.when);
1735
+ if (when) {
1736
+ return resolveMatchChildren3(match, when);
1737
+ }
1738
+ }
1739
+ return props.fallback;
1740
+ }
1741
+ function resolveMatchChildren3(element, value) {
1742
+ const children = element.props.children ?? element.children;
1743
+ if (typeof children === "function") {
1744
+ return children(value);
1745
+ }
1746
+ return children;
1747
+ }
1748
+ function resolveKeyChildren3(element, value) {
1749
+ const children = element.props.children ?? element.children;
1750
+ if (typeof children === "function") {
1751
+ return children(value);
1752
+ }
1753
+ return children;
1754
+ }
1755
+ function createDynamicElement3(element, tag) {
1756
+ if (typeof tag !== "string" && typeof tag !== "function") {
1757
+ return null;
1758
+ }
1759
+ const { component, ...props } = element.props;
1760
+ const children = normalizeContent3(props.children ?? element.children);
1761
+ return {
1762
+ tag,
1763
+ props,
1764
+ children
1765
+ };
1766
+ }
1767
+ function readReactive4(value) {
1261
1768
  return isSignal(value) || isComputed(value) ? value.value : value;
1262
1769
  }
1770
+ function normalizeContent3(content) {
1771
+ if (content == null || typeof content === "boolean") {
1772
+ return [];
1773
+ }
1774
+ return Array.isArray(content) ? content : [content];
1775
+ }
1776
+ function isElementLike3(value) {
1777
+ return value != null && typeof value === "object" && "tag" in value;
1778
+ }
1779
+ function getMatchElement3(value) {
1780
+ if (!isElementLike3(value)) {
1781
+ return null;
1782
+ }
1783
+ if (isMatchElement(value)) {
1784
+ return value;
1785
+ }
1786
+ return value.tag === Match ? Match(value.props) : null;
1787
+ }
1263
1788
 
1264
- //# debugId=107ADB344D9D30F764756E2164756E21
1789
+ //# debugId=F3CADBAD7CA6F96364756E2164756E21
1265
1790
  //# sourceMappingURL=index.development.js.map