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
@@ -99,6 +99,37 @@ function isSafeHtml(value) {
99
99
  return value instanceof HtmlEscapedString;
100
100
  }
101
101
 
102
+ // src/server/attribute-utils.ts
103
+ var PROP_ALIASES = {
104
+ className: "class",
105
+ htmlFor: "for",
106
+ tabIndex: "tabindex",
107
+ crossOrigin: "crossorigin"
108
+ };
109
+ function renderServerAttribute(key, value) {
110
+ const attrName = PROP_ALIASES[key] ?? key;
111
+ if (value == null || value === false) {
112
+ return "";
113
+ }
114
+ if (value === true) {
115
+ return ` ${attrName}`;
116
+ }
117
+ const attrValue = attrName === "class" && typeof value === "object" ? stringifyClass(value) : attrName === "style" && typeof value === "object" ? stringifyStyle(value) : String(value);
118
+ return ` ${attrName}="${escapeHtml(attrValue)}"`;
119
+ }
120
+ function stringifyClass(value) {
121
+ if (Array.isArray(value)) {
122
+ return value.filter(Boolean).join(" ");
123
+ }
124
+ return Object.entries(value).filter(([, enabled]) => Boolean(enabled)).map(([name]) => name).join(" ");
125
+ }
126
+ function stringifyStyle(value) {
127
+ return Object.entries(value).filter(([, val]) => val != null && val !== false).map(([prop, val]) => `${toKebabCase(prop)}:${String(val)}`).join(";");
128
+ }
129
+ function toKebabCase(value) {
130
+ return value.includes("-") ? value : value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
131
+ }
132
+
102
133
  // src/reactivity/scheduler.ts
103
134
  var pendingEffects = new Set;
104
135
  var flushScheduled = false;
@@ -429,10 +460,41 @@ function bindEvents(el, props) {
429
460
  }
430
461
  return cleanups;
431
462
  }
432
-
463
+ // src/reactivity/batch.ts
464
+ var batchDepth = 0;
465
+ function batch(fn) {
466
+ batchDepth++;
467
+ try {
468
+ fn();
469
+ } finally {
470
+ batchDepth--;
471
+ if (batchDepth === 0) {
472
+ flushSync();
473
+ }
474
+ }
475
+ }
476
+ // src/reactivity/normalization.ts
477
+ function isReactive(value) {
478
+ return isSignal(value) || isComputed(value) || typeof value === "function";
479
+ }
480
+ function resolve(value) {
481
+ if (isSignal(value) || isComputed(value)) {
482
+ return value.value;
483
+ }
484
+ if (typeof value === "function") {
485
+ return value();
486
+ }
487
+ return value;
488
+ }
433
489
  // src/component/control-flow.ts
434
490
  var SHOW_TYPE = Symbol.for("Sinwan.Show");
435
491
  var FOR_TYPE = Symbol.for("Sinwan.For");
492
+ var SWITCH_TYPE = Symbol.for("Sinwan.Switch");
493
+ var MATCH_TYPE = Symbol.for("Sinwan.Match");
494
+ var INDEX_TYPE = Symbol.for("Sinwan.Index");
495
+ var KEY_TYPE = Symbol.for("Sinwan.Key");
496
+ var DYNAMIC_TYPE = Symbol.for("Sinwan.Dynamic");
497
+ var PORTAL_TYPE = Symbol.for("Sinwan.Portal");
436
498
  function Show(props) {
437
499
  return {
438
500
  tag: SHOW_TYPE,
@@ -447,12 +509,114 @@ function For(props) {
447
509
  children: []
448
510
  };
449
511
  }
512
+ function Switch(props) {
513
+ return {
514
+ tag: SWITCH_TYPE,
515
+ props,
516
+ children: []
517
+ };
518
+ }
519
+ function Match(props) {
520
+ return {
521
+ tag: MATCH_TYPE,
522
+ props,
523
+ children: []
524
+ };
525
+ }
526
+ function Index(props) {
527
+ return {
528
+ tag: INDEX_TYPE,
529
+ props,
530
+ children: []
531
+ };
532
+ }
533
+ function Key(props) {
534
+ return {
535
+ tag: KEY_TYPE,
536
+ props,
537
+ children: []
538
+ };
539
+ }
540
+ function Dynamic(props) {
541
+ return {
542
+ tag: DYNAMIC_TYPE,
543
+ props,
544
+ children: []
545
+ };
546
+ }
547
+ function Visible(props) {
548
+ const {
549
+ when,
550
+ as = "span",
551
+ style,
552
+ children,
553
+ ...rest
554
+ } = props;
555
+ const visibleStyle = computed(() => {
556
+ const base = readReactive(style);
557
+ const visible = Boolean(readReactive(when));
558
+ if (typeof base === "string") {
559
+ return visible ? base : appendHiddenDisplay(base);
560
+ }
561
+ const styleObject = base && typeof base === "object" ? { ...base } : {};
562
+ styleObject.display = visible ? styleObject.display : "none";
563
+ return styleObject;
564
+ });
565
+ return {
566
+ tag: as,
567
+ props: {
568
+ ...rest,
569
+ style: visibleStyle,
570
+ children
571
+ },
572
+ children: normalizeChildren2(children)
573
+ };
574
+ }
575
+ function Portal(props) {
576
+ return {
577
+ tag: PORTAL_TYPE,
578
+ props,
579
+ children: []
580
+ };
581
+ }
450
582
  function isShowElement(element) {
451
583
  return element.tag === SHOW_TYPE;
452
584
  }
453
585
  function isForElement(element) {
454
586
  return element.tag === FOR_TYPE;
455
587
  }
588
+ function isSwitchElement(element) {
589
+ return element.tag === SWITCH_TYPE;
590
+ }
591
+ function isMatchElement(element) {
592
+ return element.tag === MATCH_TYPE;
593
+ }
594
+ function isIndexElement(element) {
595
+ return element.tag === INDEX_TYPE;
596
+ }
597
+ function isKeyElement(element) {
598
+ return element.tag === KEY_TYPE;
599
+ }
600
+ function isDynamicElement(element) {
601
+ return element.tag === DYNAMIC_TYPE;
602
+ }
603
+ function isPortalElement(element) {
604
+ return element.tag === PORTAL_TYPE;
605
+ }
606
+ function normalizeChildren2(children) {
607
+ if (children == null || typeof children === "boolean") {
608
+ return [];
609
+ }
610
+ return Array.isArray(children) ? children : [children];
611
+ }
612
+ function readReactive(value) {
613
+ return resolve(value);
614
+ }
615
+ function appendHiddenDisplay(style) {
616
+ const trimmed = style.trim();
617
+ const separator = trimmed.length > 0 && !trimmed.endsWith(";") ? ";" : "";
618
+ return `${trimmed}${separator}display:none`;
619
+ }
456
620
 
457
621
  // src/server/renderer.ts
458
622
  var componentCache = new WeakMap;
@@ -501,13 +665,41 @@ async function renderToString(node) {
501
665
  }
502
666
  async function renderElement(element) {
503
667
  const { tag, props, children } = element;
668
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
669
+ return renderElement(tag(props));
670
+ }
671
+ if (tag === Visible) {
672
+ return renderElement(tag(props));
673
+ }
504
674
  if (isShowElement(element)) {
505
- const when = readReactive(props.when);
675
+ const when = readReactive2(props.when);
506
676
  return renderToString(when ? resolveShowChildren(element, when) : props.fallback);
507
677
  }
508
678
  if (isForElement(element)) {
509
679
  return renderForElement(element);
510
680
  }
681
+ if (isSwitchElement(element)) {
682
+ return renderToString(resolveSwitchContent(element));
683
+ }
684
+ if (isMatchElement(element)) {
685
+ const when = readReactive2(props.when);
686
+ return renderToString(when ? resolveMatchChildren(element, when) : null);
687
+ }
688
+ if (isIndexElement(element)) {
689
+ return renderIndexElement(element);
690
+ }
691
+ if (isKeyElement(element)) {
692
+ const key = readReactive2(props.when);
693
+ return renderToString(resolveKeyChildren(element, key));
694
+ }
695
+ if (isDynamicElement(element)) {
696
+ const tag2 = readReactive2(props.component);
697
+ const dynamic = createDynamicElement(element, tag2);
698
+ return dynamic ? renderElement(dynamic) : "";
699
+ }
700
+ if (isPortalElement(element)) {
701
+ return "";
702
+ }
511
703
  if (typeof tag === "function") {
512
704
  const result = await tag(props);
513
705
  return renderToString(result);
@@ -547,17 +739,10 @@ function renderAttributes(props) {
547
739
  if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
548
740
  continue;
549
741
  }
550
- const resolvedValue = readReactive(value);
742
+ const resolvedValue = readReactive2(value);
551
743
  if (resolvedValue == null || resolvedValue === false)
552
744
  continue;
553
- const attrName = key === "className" ? "class" : key;
554
- const finalName = attrName === "htmlFor" ? "for" : attrName;
555
- if (resolvedValue === true) {
556
- attrs += ` ${finalName}`;
557
- continue;
558
- }
559
- const attrValue = escapeHtml(String(resolvedValue));
560
- attrs += ` ${finalName}="${attrValue}"`;
745
+ attrs += renderServerAttribute(key, resolvedValue);
561
746
  }
562
747
  return attrs;
563
748
  }
@@ -573,13 +758,69 @@ function isSlots(children) {
573
758
  }
574
759
  async function renderForElement(element) {
575
760
  const props = element.props;
576
- const each = readReactive(props.each);
761
+ const each = readReactive2(props.each);
577
762
  if (!Array.isArray(each) || typeof props.children !== "function") {
578
- return "";
763
+ return props.fallback ? renderToString(props.fallback) : "";
764
+ }
765
+ if (each.length === 0) {
766
+ return props.fallback ? renderToString(props.fallback) : "";
579
767
  }
580
768
  const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(item, () => index))));
581
769
  return rendered.join("");
582
770
  }
771
+ async function renderIndexElement(element) {
772
+ const props = element.props;
773
+ const each = readReactive2(props.each);
774
+ if (!Array.isArray(each) || typeof props.children !== "function") {
775
+ return props.fallback ? renderToString(props.fallback) : "";
776
+ }
777
+ if (each.length === 0) {
778
+ return props.fallback ? renderToString(props.fallback) : "";
779
+ }
780
+ const rendered = await Promise.all(each.map((item, index) => renderToString(props.children(() => item, index))));
781
+ return rendered.join("");
782
+ }
783
+ function resolveSwitchContent(element) {
784
+ const props = element.props;
785
+ const children = normalizeContent(props.children ?? element.children);
786
+ for (const child of children) {
787
+ const match = getMatchElement(child);
788
+ if (!match) {
789
+ continue;
790
+ }
791
+ const when = readReactive2(match.props.when);
792
+ if (when) {
793
+ return resolveMatchChildren(match, when);
794
+ }
795
+ }
796
+ return props.fallback;
797
+ }
798
+ function resolveMatchChildren(element, value) {
799
+ const children = element.props.children ?? element.children;
800
+ if (typeof children === "function") {
801
+ return children(value);
802
+ }
803
+ return children;
804
+ }
805
+ function resolveKeyChildren(element, value) {
806
+ const children = element.props.children ?? element.children;
807
+ if (typeof children === "function") {
808
+ return children(value);
809
+ }
810
+ return children;
811
+ }
812
+ function createDynamicElement(element, tag) {
813
+ if (typeof tag !== "string" && typeof tag !== "function") {
814
+ return null;
815
+ }
816
+ const { component, ...props } = element.props;
817
+ const children = normalizeContent(props.children ?? element.children);
818
+ return {
819
+ tag,
820
+ props,
821
+ children
822
+ };
823
+ }
583
824
  function resolveShowChildren(element, value) {
584
825
  const children = element.props.children ?? element.children;
585
826
  if (typeof children === "function") {
@@ -587,9 +828,27 @@ function resolveShowChildren(element, value) {
587
828
  }
588
829
  return children;
589
830
  }
590
- function readReactive(value) {
831
+ function readReactive2(value) {
591
832
  return isSignal(value) || isComputed(value) ? value.value : value;
592
833
  }
834
+ function normalizeContent(content) {
835
+ if (content == null || typeof content === "boolean") {
836
+ return [];
837
+ }
838
+ return Array.isArray(content) ? content : [content];
839
+ }
840
+ function isElementLike(value) {
841
+ return value != null && typeof value === "object" && "tag" in value;
842
+ }
843
+ function getMatchElement(value) {
844
+ if (!isElementLike(value)) {
845
+ return null;
846
+ }
847
+ if (isMatchElement(value)) {
848
+ return value;
849
+ }
850
+ return value.tag === Match ? Match(value.props) : null;
851
+ }
593
852
  // src/component/instance.ts
594
853
  var uidCounter = 0;
595
854
  function createComponentInstance(component, props, parent) {
@@ -813,8 +1072,16 @@ async function streamNode(node, controller, encoder) {
813
1072
  }
814
1073
  async function streamElement(element, controller, encoder) {
815
1074
  const { tag, props, children } = element;
1075
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1076
+ await streamElement(tag(props), controller, encoder);
1077
+ return;
1078
+ }
1079
+ if (tag === Visible) {
1080
+ await streamElement(tag(props), controller, encoder);
1081
+ return;
1082
+ }
816
1083
  if (isShowElement(element)) {
817
- const when = readReactive2(props.when);
1084
+ const when = readReactive3(props.when);
818
1085
  await streamNode(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder);
819
1086
  return;
820
1087
  }
@@ -822,6 +1089,35 @@ async function streamElement(element, controller, encoder) {
822
1089
  await streamForElement(element, controller, encoder);
823
1090
  return;
824
1091
  }
1092
+ if (isSwitchElement(element)) {
1093
+ await streamNode(resolveSwitchContent2(element), controller, encoder);
1094
+ return;
1095
+ }
1096
+ if (isMatchElement(element)) {
1097
+ const when = readReactive3(props.when);
1098
+ await streamNode(when ? resolveMatchChildren2(element, when) : null, controller, encoder);
1099
+ return;
1100
+ }
1101
+ if (isIndexElement(element)) {
1102
+ await streamIndexElement(element, controller, encoder);
1103
+ return;
1104
+ }
1105
+ if (isKeyElement(element)) {
1106
+ const key = readReactive3(props.when);
1107
+ await streamNode(resolveKeyChildren2(element, key), controller, encoder);
1108
+ return;
1109
+ }
1110
+ if (isDynamicElement(element)) {
1111
+ const dynamicTag = readReactive3(props.component);
1112
+ const dynamic = createDynamicElement2(element, dynamicTag);
1113
+ if (dynamic) {
1114
+ await streamElement(dynamic, controller, encoder);
1115
+ }
1116
+ return;
1117
+ }
1118
+ if (isPortalElement(element)) {
1119
+ return;
1120
+ }
825
1121
  if (typeof tag === "function") {
826
1122
  const result = await tag(props);
827
1123
  await streamNode(result, controller, encoder);
@@ -856,16 +1152,10 @@ function renderAttributes2(props) {
856
1152
  if (key === "children" || key === "key" || key === "ref" || key === "dangerouslySetInnerHTML" || isEventProp(key)) {
857
1153
  continue;
858
1154
  }
859
- const resolvedValue = readReactive2(value);
1155
+ const resolvedValue = readReactive3(value);
860
1156
  if (resolvedValue == null || resolvedValue === false)
861
1157
  continue;
862
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
863
- if (resolvedValue === true) {
864
- attrs += ` ${attrName}`;
865
- continue;
866
- }
867
- const attrValue = escapeHtml(String(resolvedValue));
868
- attrs += ` ${attrName}="${attrValue}"`;
1158
+ attrs += renderServerAttribute(key, resolvedValue);
869
1159
  }
870
1160
  return attrs;
871
1161
  }
@@ -910,12 +1200,16 @@ async function streamHydratableElement(element, controller, encoder, ctx, isComp
910
1200
  }
911
1201
  return;
912
1202
  }
913
- if (tag === Show || tag === For) {
1203
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1204
+ await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
1205
+ return;
1206
+ }
1207
+ if (tag === Visible) {
914
1208
  await streamHydratableElement(tag(props), controller, encoder, ctx, isComponentRoot);
915
1209
  return;
916
1210
  }
917
1211
  if (isShowElement(element)) {
918
- const when = readReactive2(props.when);
1212
+ const when = readReactive3(props.when);
919
1213
  await streamHydratableNodeToController(when ? resolveShowChildren2(element, when) : props.fallback, controller, encoder, ctx, isComponentRoot);
920
1214
  return;
921
1215
  }
@@ -923,6 +1217,35 @@ async function streamHydratableElement(element, controller, encoder, ctx, isComp
923
1217
  await streamHydratableForElement(element, controller, encoder, ctx);
924
1218
  return;
925
1219
  }
1220
+ if (isSwitchElement(element)) {
1221
+ await streamHydratableNodeToController(resolveSwitchContent2(element), controller, encoder, ctx, isComponentRoot);
1222
+ return;
1223
+ }
1224
+ if (isMatchElement(element)) {
1225
+ const when = readReactive3(props.when);
1226
+ await streamHydratableNodeToController(when ? resolveMatchChildren2(element, when) : null, controller, encoder, ctx, isComponentRoot);
1227
+ return;
1228
+ }
1229
+ if (isIndexElement(element)) {
1230
+ await streamHydratableIndexElement(element, controller, encoder, ctx);
1231
+ return;
1232
+ }
1233
+ if (isKeyElement(element)) {
1234
+ const key = readReactive3(props.when);
1235
+ await streamHydratableNodeToController(resolveKeyChildren2(element, key), controller, encoder, ctx, isComponentRoot);
1236
+ return;
1237
+ }
1238
+ if (isDynamicElement(element)) {
1239
+ const dynamicTag = readReactive3(props.component);
1240
+ const dynamic = createDynamicElement2(element, dynamicTag);
1241
+ if (dynamic) {
1242
+ await streamHydratableElement(dynamic, controller, encoder, ctx, isComponentRoot);
1243
+ }
1244
+ return;
1245
+ }
1246
+ if (isPortalElement(element)) {
1247
+ return;
1248
+ }
926
1249
  if (typeof tag === "function") {
927
1250
  await streamHydratableComponent(tag, props, controller, encoder, ctx, true);
928
1251
  return;
@@ -965,14 +1288,42 @@ async function streamHydratableIntrinsic(tag, props, children, controller, encod
965
1288
  }
966
1289
  async function streamHydratableForElement(element, controller, encoder, ctx) {
967
1290
  const props = element.props;
968
- const each = readReactive2(props.each);
1291
+ const each = readReactive3(props.each);
969
1292
  if (!Array.isArray(each) || typeof props.children !== "function") {
1293
+ if (props.fallback) {
1294
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1295
+ }
1296
+ return;
1297
+ }
1298
+ if (each.length === 0) {
1299
+ if (props.fallback) {
1300
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1301
+ }
970
1302
  return;
971
1303
  }
972
1304
  for (let index = 0;index < each.length; index++) {
973
1305
  await streamHydratableNodeToController(props.children(each[index], () => index), controller, encoder, ctx);
974
1306
  }
975
1307
  }
1308
+ async function streamHydratableIndexElement(element, controller, encoder, ctx) {
1309
+ const props = element.props;
1310
+ const each = readReactive3(props.each);
1311
+ if (!Array.isArray(each) || typeof props.children !== "function") {
1312
+ if (props.fallback) {
1313
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1314
+ }
1315
+ return;
1316
+ }
1317
+ if (each.length === 0) {
1318
+ if (props.fallback) {
1319
+ await streamHydratableNodeToController(props.fallback, controller, encoder, ctx);
1320
+ }
1321
+ return;
1322
+ }
1323
+ for (let index = 0;index < each.length; index++) {
1324
+ await streamHydratableNodeToController(props.children(() => each[index], index), controller, encoder, ctx);
1325
+ }
1326
+ }
976
1327
  function renderHydratableAttributes(props, ctx, isComponentRoot) {
977
1328
  let attrs = "";
978
1329
  if (isComponentRoot) {
@@ -987,15 +1338,10 @@ function renderHydratableAttributes(props, ctx, isComponentRoot) {
987
1338
  eventParts.push(`${toEventName(key)}:${ctx.eventIndex++}`);
988
1339
  continue;
989
1340
  }
990
- const resolvedValue = readReactive2(value);
1341
+ const resolvedValue = readReactive3(value);
991
1342
  if (resolvedValue == null || resolvedValue === false)
992
1343
  continue;
993
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
994
- if (resolvedValue === true) {
995
- attrs += ` ${attrName}`;
996
- continue;
997
- }
998
- attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
1344
+ attrs += renderServerAttribute(key, resolvedValue);
999
1345
  }
1000
1346
  if (eventParts.length > 0) {
1001
1347
  attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
@@ -1007,14 +1353,42 @@ function enqueue(controller, encoder, html) {
1007
1353
  }
1008
1354
  async function streamForElement(element, controller, encoder) {
1009
1355
  const props = element.props;
1010
- const each = readReactive2(props.each);
1356
+ const each = readReactive3(props.each);
1011
1357
  if (!Array.isArray(each) || typeof props.children !== "function") {
1358
+ if (props.fallback) {
1359
+ await streamNode(props.fallback, controller, encoder);
1360
+ }
1361
+ return;
1362
+ }
1363
+ if (each.length === 0) {
1364
+ if (props.fallback) {
1365
+ await streamNode(props.fallback, controller, encoder);
1366
+ }
1012
1367
  return;
1013
1368
  }
1014
1369
  for (let index = 0;index < each.length; index++) {
1015
1370
  await streamNode(props.children(each[index], () => index), controller, encoder);
1016
1371
  }
1017
1372
  }
1373
+ async function streamIndexElement(element, controller, encoder) {
1374
+ const props = element.props;
1375
+ const each = readReactive3(props.each);
1376
+ if (!Array.isArray(each) || typeof props.children !== "function") {
1377
+ if (props.fallback) {
1378
+ await streamNode(props.fallback, controller, encoder);
1379
+ }
1380
+ return;
1381
+ }
1382
+ if (each.length === 0) {
1383
+ if (props.fallback) {
1384
+ await streamNode(props.fallback, controller, encoder);
1385
+ }
1386
+ return;
1387
+ }
1388
+ for (let index = 0;index < each.length; index++) {
1389
+ await streamNode(props.children(() => each[index], index), controller, encoder);
1390
+ }
1391
+ }
1018
1392
  function resolveShowChildren2(element, value) {
1019
1393
  const children = element.props.children ?? element.children;
1020
1394
  if (typeof children === "function") {
@@ -1022,9 +1396,68 @@ function resolveShowChildren2(element, value) {
1022
1396
  }
1023
1397
  return children;
1024
1398
  }
1025
- function readReactive2(value) {
1399
+ function resolveSwitchContent2(element) {
1400
+ const props = element.props;
1401
+ const children = normalizeContent2(props.children ?? element.children);
1402
+ for (const child of children) {
1403
+ const match = getMatchElement2(child);
1404
+ if (!match) {
1405
+ continue;
1406
+ }
1407
+ const when = readReactive3(match.props.when);
1408
+ if (when) {
1409
+ return resolveMatchChildren2(match, when);
1410
+ }
1411
+ }
1412
+ return props.fallback;
1413
+ }
1414
+ function resolveMatchChildren2(element, value) {
1415
+ const children = element.props.children ?? element.children;
1416
+ if (typeof children === "function") {
1417
+ return children(value);
1418
+ }
1419
+ return children;
1420
+ }
1421
+ function resolveKeyChildren2(element, value) {
1422
+ const children = element.props.children ?? element.children;
1423
+ if (typeof children === "function") {
1424
+ return children(value);
1425
+ }
1426
+ return children;
1427
+ }
1428
+ function createDynamicElement2(element, tag) {
1429
+ if (typeof tag !== "string" && typeof tag !== "function") {
1430
+ return null;
1431
+ }
1432
+ const { component, ...props } = element.props;
1433
+ const children = normalizeContent2(props.children ?? element.children);
1434
+ return {
1435
+ tag,
1436
+ props,
1437
+ children
1438
+ };
1439
+ }
1440
+ function readReactive3(value) {
1026
1441
  return isSignal(value) || isComputed(value) ? value.value : value;
1027
1442
  }
1443
+ function normalizeContent2(content) {
1444
+ if (content == null || typeof content === "boolean") {
1445
+ return [];
1446
+ }
1447
+ return Array.isArray(content) ? content : [content];
1448
+ }
1449
+ function isElementLike2(value) {
1450
+ return value != null && typeof value === "object" && "tag" in value;
1451
+ }
1452
+ function getMatchElement2(value) {
1453
+ if (!isElementLike2(value)) {
1454
+ return null;
1455
+ }
1456
+ if (isMatchElement(value)) {
1457
+ return value;
1458
+ }
1459
+ return value.tag === Match ? Match(value.props) : null;
1460
+ }
1028
1461
  // src/server/hydration-markers.ts
1029
1462
  function createHydrationContext() {
1030
1463
  return { componentIndex: 0, textIndex: 0, eventIndex: 0 };
@@ -1094,17 +1527,42 @@ function renderElementH(element, ctx, isComponentRoot) {
1094
1527
  if (tag === "") {
1095
1528
  return children.map((child) => renderNodeH(child, ctx)).join("");
1096
1529
  }
1097
- if (tag === Show || tag === For) {
1530
+ if (tag === Show || tag === For || tag === Switch || tag === Index || tag === Key || tag === Dynamic || tag === Portal) {
1531
+ return renderElementH(tag(props), ctx, isComponentRoot);
1532
+ }
1533
+ if (tag === Visible) {
1098
1534
  return renderElementH(tag(props), ctx, isComponentRoot);
1099
1535
  }
1100
1536
  if (isShowElement(element)) {
1101
- const when = readReactive3(props.when);
1537
+ const when = readReactive4(props.when);
1102
1538
  const content = when ? resolveShowChildren3(element, when) : props.fallback;
1103
1539
  return renderNodeMaybeRoot(content, ctx, isComponentRoot);
1104
1540
  }
1105
1541
  if (isForElement(element)) {
1106
1542
  return renderForElementH(element, ctx);
1107
1543
  }
1544
+ if (isSwitchElement(element)) {
1545
+ return renderNodeMaybeRoot(resolveSwitchContent3(element), ctx, isComponentRoot);
1546
+ }
1547
+ if (isMatchElement(element)) {
1548
+ const when = readReactive4(props.when);
1549
+ return renderNodeMaybeRoot(when ? resolveMatchChildren3(element, when) : null, ctx, isComponentRoot);
1550
+ }
1551
+ if (isIndexElement(element)) {
1552
+ return renderIndexElementH(element, ctx);
1553
+ }
1554
+ if (isKeyElement(element)) {
1555
+ const key = readReactive4(props.when);
1556
+ return renderNodeMaybeRoot(resolveKeyChildren3(element, key), ctx, isComponentRoot);
1557
+ }
1558
+ if (isDynamicElement(element)) {
1559
+ const dynamicTag = readReactive4(props.component);
1560
+ const dynamic = createDynamicElement3(element, dynamicTag);
1561
+ return dynamic ? renderElementH(dynamic, ctx, isComponentRoot) : "";
1562
+ }
1563
+ if (isPortalElement(element)) {
1564
+ return "";
1565
+ }
1108
1566
  if (typeof tag === "function") {
1109
1567
  return renderComponentH(tag, props, ctx);
1110
1568
  }
@@ -1151,13 +1609,7 @@ function renderIntrinsicH(tag, props, children, ctx, isComponentRoot) {
1151
1609
  if (isSignal(value) || isComputed(value)) {
1152
1610
  resolvedValue = value.value;
1153
1611
  }
1154
- if (resolvedValue === true) {
1155
- const attrName2 = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1156
- attrs += ` ${attrName2}`;
1157
- continue;
1158
- }
1159
- const attrName = key === "className" ? "class" : key === "htmlFor" ? "for" : key;
1160
- attrs += ` ${attrName}="${escapeHtml(String(resolvedValue))}"`;
1612
+ attrs += renderServerAttribute(key, resolvedValue);
1161
1613
  }
1162
1614
  if (eventParts.length > 0) {
1163
1615
  attrs += ` ${EVENT_ATTR}="${eventParts.join(",")}"`;
@@ -1180,12 +1632,26 @@ function renderNodeMaybeRoot(node, ctx, isComponentRoot) {
1180
1632
  }
1181
1633
  function renderForElementH(element, ctx) {
1182
1634
  const props = element.props;
1183
- const each = readReactive3(props.each);
1635
+ const each = readReactive4(props.each);
1184
1636
  if (!Array.isArray(each) || typeof props.children !== "function") {
1185
- return "";
1637
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1638
+ }
1639
+ if (each.length === 0) {
1640
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1186
1641
  }
1187
1642
  return each.map((item, index) => renderNodeH(props.children(item, () => index), ctx)).join("");
1188
1643
  }
1644
+ function renderIndexElementH(element, ctx) {
1645
+ const props = element.props;
1646
+ const each = readReactive4(props.each);
1647
+ if (!Array.isArray(each) || typeof props.children !== "function") {
1648
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1649
+ }
1650
+ if (each.length === 0) {
1651
+ return props.fallback ? renderNodeH(props.fallback, ctx) : "";
1652
+ }
1653
+ return each.map((item, index) => renderNodeH(props.children(() => item, index), ctx)).join("");
1654
+ }
1189
1655
  function resolveShowChildren3(element, value) {
1190
1656
  const children = element.props.children ?? element.children;
1191
1657
  if (typeof children === "function") {
@@ -1193,9 +1659,68 @@ function resolveShowChildren3(element, value) {
1193
1659
  }
1194
1660
  return children;
1195
1661
  }
1196
- function readReactive3(value) {
1662
+ function resolveSwitchContent3(element) {
1663
+ const props = element.props;
1664
+ const children = normalizeContent3(props.children ?? element.children);
1665
+ for (const child of children) {
1666
+ const match = getMatchElement3(child);
1667
+ if (!match) {
1668
+ continue;
1669
+ }
1670
+ const when = readReactive4(match.props.when);
1671
+ if (when) {
1672
+ return resolveMatchChildren3(match, when);
1673
+ }
1674
+ }
1675
+ return props.fallback;
1676
+ }
1677
+ function resolveMatchChildren3(element, value) {
1678
+ const children = element.props.children ?? element.children;
1679
+ if (typeof children === "function") {
1680
+ return children(value);
1681
+ }
1682
+ return children;
1683
+ }
1684
+ function resolveKeyChildren3(element, value) {
1685
+ const children = element.props.children ?? element.children;
1686
+ if (typeof children === "function") {
1687
+ return children(value);
1688
+ }
1689
+ return children;
1690
+ }
1691
+ function createDynamicElement3(element, tag) {
1692
+ if (typeof tag !== "string" && typeof tag !== "function") {
1693
+ return null;
1694
+ }
1695
+ const { component, ...props } = element.props;
1696
+ const children = normalizeContent3(props.children ?? element.children);
1697
+ return {
1698
+ tag,
1699
+ props,
1700
+ children
1701
+ };
1702
+ }
1703
+ function readReactive4(value) {
1197
1704
  return isSignal(value) || isComputed(value) ? value.value : value;
1198
1705
  }
1706
+ function normalizeContent3(content) {
1707
+ if (content == null || typeof content === "boolean") {
1708
+ return [];
1709
+ }
1710
+ return Array.isArray(content) ? content : [content];
1711
+ }
1712
+ function isElementLike3(value) {
1713
+ return value != null && typeof value === "object" && "tag" in value;
1714
+ }
1715
+ function getMatchElement3(value) {
1716
+ if (!isElementLike3(value)) {
1717
+ return null;
1718
+ }
1719
+ if (isMatchElement(value)) {
1720
+ return value;
1721
+ }
1722
+ return value.tag === Match ? Match(value.props) : null;
1723
+ }
1199
1724
  export {
1200
1725
  streamPage,
1201
1726
  streamHydratablePage,
@@ -1210,5 +1735,5 @@ export {
1210
1735
  getPage
1211
1736
  };
1212
1737
 
1213
- //# debugId=E47F9E2EB5705D1864756E2164756E21
1738
+ //# debugId=F305883ADDC8E25564756E2164756E21
1214
1739
  //# sourceMappingURL=index.development.js.map