@fluixi/compiler 1.0.0-alpha.92 → 1.0.0-alpha.94

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 (102) hide show
  1. package/dist/analyze/intrinsics.cjs +31 -1
  2. package/dist/analyze/intrinsics.d.cts +14 -0
  3. package/dist/analyze/intrinsics.d.ts +14 -0
  4. package/dist/analyze/intrinsics.d.ts.map +1 -1
  5. package/dist/analyze/intrinsics.js +35 -0
  6. package/dist/analyze/intrinsics.mjs +31 -1
  7. package/dist/analyze/reactive-bindings.cjs +18 -0
  8. package/dist/analyze/reactive-bindings.mjs +18 -0
  9. package/dist/analyze/static-graph.cjs +22 -4
  10. package/dist/analyze/static-graph.d.ts.map +1 -1
  11. package/dist/analyze/static-graph.js +6 -4
  12. package/dist/analyze/static-graph.mjs +22 -4
  13. package/dist/{babel-GI375YZ2.mjs → babel-RJFQVFJW.mjs} +4 -4
  14. package/dist/{chunk-QZ4CJPYP.mjs → chunk-DP2QDWWH.mjs} +1 -1
  15. package/dist/{chunk-DWNWN5RH.mjs → chunk-E2RWTIYE.mjs} +21 -15
  16. package/dist/{chunk-XJ5H2MXY.mjs → chunk-HCCBEJEZ.mjs} +31 -1
  17. package/dist/{chunk-VOUI6XPV.mjs → chunk-HIZU7WI2.mjs} +1 -1
  18. package/dist/{chunk-VC6X44FS.mjs → chunk-ZR2QHTEX.mjs} +505 -68
  19. package/dist/codegen/backends/imperative.cjs +24 -6
  20. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  21. package/dist/codegen/backends/imperative.js +20 -4
  22. package/dist/codegen/backends/imperative.mjs +24 -6
  23. package/dist/frontend/babel/build-ir-lit.cjs +470 -63
  24. package/dist/frontend/babel/build-ir-lit.mjs +470 -63
  25. package/dist/frontend/babel/build-ir.cjs +470 -63
  26. package/dist/frontend/babel/build-ir.mjs +470 -63
  27. package/dist/frontend/babel/index.cjs +471 -64
  28. package/dist/frontend/babel/index.mjs +471 -64
  29. package/dist/frontend/babel/lower-template.cjs +470 -63
  30. package/dist/frontend/babel/lower-template.mjs +470 -63
  31. package/dist/frontend/babel/plugin.cjs +470 -63
  32. package/dist/frontend/babel/plugin.mjs +470 -63
  33. package/dist/index.cjs +360 -58
  34. package/dist/index.mjs +372 -58
  35. package/dist/integrations.cjs +1347 -98
  36. package/dist/integrations.d.ts.map +1 -1
  37. package/dist/integrations.js +44 -2
  38. package/dist/integrations.mjs +205 -19
  39. package/dist/lower/compile-template.cjs +354 -57
  40. package/dist/lower/compile-template.d.cts +13 -0
  41. package/dist/lower/compile-template.d.ts +13 -0
  42. package/dist/lower/compile-template.d.ts.map +1 -1
  43. package/dist/lower/compile-template.js +3 -0
  44. package/dist/lower/compile-template.mjs +366 -57
  45. package/dist/lower/entities.cjs +288 -0
  46. package/dist/lower/entities.d.cts +1 -0
  47. package/dist/lower/entities.d.ts +2 -0
  48. package/dist/lower/entities.d.ts.map +1 -0
  49. package/dist/lower/entities.js +54 -0
  50. package/dist/lower/entities.mjs +267 -0
  51. package/dist/lower/jsx.cjs +567 -7
  52. package/dist/lower/jsx.d.cts +8 -0
  53. package/dist/lower/jsx.d.ts +8 -0
  54. package/dist/lower/jsx.d.ts.map +1 -1
  55. package/dist/lower/jsx.js +205 -7
  56. package/dist/lower/jsx.mjs +567 -7
  57. package/dist/lower/template.cjs +332 -56
  58. package/dist/lower/template.d.ts.map +1 -1
  59. package/dist/lower/template.js +57 -49
  60. package/dist/lower/template.mjs +332 -56
  61. package/dist/resolve/builtins.cjs +1 -1
  62. package/dist/resolve/builtins.mjs +1 -1
  63. package/dist/resolve/component-globals.cjs +20 -1
  64. package/dist/resolve/component-globals.js +2 -2
  65. package/dist/resolve/component-globals.mjs +20 -1
  66. package/dist/resolve/write-globals.cjs +20 -1
  67. package/dist/resolve/write-globals.mjs +20 -1
  68. package/dist/{server-fns-BBZRZUPP.mjs → server-fns-JLSTKWPS.mjs} +4 -4
  69. package/dist/{server-functions-VEGLIFCE.mjs → server-functions-BGY3RD4R.mjs} +3 -3
  70. package/dist/transform/index.cjs +1123 -77
  71. package/dist/transform/index.mjs +1141 -91
  72. package/dist/transform/intrinsics.cjs +18 -0
  73. package/dist/transform/intrinsics.mjs +18 -0
  74. package/dist/transform/props.mjs +19 -14
  75. package/dist/transform/server-fns.mjs +19 -14
  76. package/dist/transform/source-locations.cjs +64 -3
  77. package/dist/transform/source-locations.d.cts +7 -2
  78. package/dist/transform/source-locations.d.ts +7 -2
  79. package/dist/transform/source-locations.d.ts.map +1 -1
  80. package/dist/transform/source-locations.js +68 -3
  81. package/dist/transform/source-locations.mjs +64 -3
  82. package/dist/transform/styles.cjs +588 -0
  83. package/dist/transform/styles.d.cts +211 -0
  84. package/dist/transform/styles.d.ts +212 -0
  85. package/dist/transform/styles.d.ts.map +1 -0
  86. package/dist/transform/styles.js +714 -0
  87. package/dist/transform/styles.mjs +653 -0
  88. package/dist/transform/templates.cjs +1122 -76
  89. package/dist/transform/templates.d.cts +13 -0
  90. package/dist/transform/templates.d.ts +13 -0
  91. package/dist/transform/templates.d.ts.map +1 -1
  92. package/dist/transform/templates.js +51 -14
  93. package/dist/transform/templates.mjs +1140 -90
  94. package/dist/{transform-UWZ7ZGJ2.mjs → transform-GBP6Y4UI.mjs} +603 -19
  95. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  96. package/dist/vite-styles.cjs +180 -0
  97. package/dist/vite-styles.d.cts +59 -0
  98. package/dist/vite-styles.d.ts +60 -0
  99. package/dist/vite-styles.d.ts.map +1 -0
  100. package/dist/vite-styles.js +198 -0
  101. package/dist/vite-styles.mjs +159 -0
  102. package/package.json +10 -3
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! @fluixi/compiler v1.0.0-alpha.92 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/compiler v1.0.0-alpha.94 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -328,6 +328,7 @@ var INTRINSICS = {
328
328
  $effect: { export: "effect", module: REACTIVE_MODULE, returns: "effect" },
329
329
  $store: { export: "store", module: "@fluixi/reactive/store", returns: "store-handle" },
330
330
  $resource: { export: "resource", module: REACTIVE_MODULE, returns: "resource-handle" },
331
+ $cachedResource: { export: "cachedResource", module: "@fluixi/reactive/cached-resource", returns: "resource-handle" },
331
332
  // No short runtime form for these yet, so the intrinsic stands for the `create*`
332
333
  // name. Still worth having: no import to write, and when a shorter form is
333
334
  // designed, the change is this line rather than a compiler pass.
@@ -338,9 +339,27 @@ var INTRINSICS = {
338
339
  // dependency analysis must not guess at.
339
340
  $untrack: { export: "untrack", module: REACTIVE_MODULE, returns: "plain" },
340
341
  $untrackStore: { export: "untrackStore", module: "@fluixi/reactive/store", returns: "plain" },
342
+ // Scopes, scheduling and lifecycle: no value to classify, but the same authoring promise,
343
+ // no import to write. `$cleanup` registers a callback on the current owner (`onCleanup`).
344
+ $batch: { export: "batch", module: REACTIVE_MODULE, returns: "plain" },
345
+ $cleanup: { export: "onCleanup", module: REACTIVE_MODULE, returns: "plain" },
346
+ $root: { export: "root", module: REACTIVE_MODULE, returns: "plain" },
347
+ $context: { export: "context", module: REACTIVE_MODULE, returns: "plain" },
348
+ $renderEffect: { export: "renderEffect", module: REACTIVE_MODULE, returns: "effect" },
349
+ $computed: { export: "computed", module: REACTIVE_MODULE, returns: "effect" },
350
+ // Storage for where the code runs, and a signal kept in it. `$persisted` is a signal
351
+ // handle as far as reads go: the same accessor with `set` on it.
352
+ $storage: { export: "useStorage", module: "@fluixi/core/storage", returns: "plain" },
353
+ $asyncStorage: { export: "useAsyncStorage", module: "@fluixi/core/storage", returns: "plain" },
354
+ $persisted: { export: "persisted", module: "@fluixi/core/storage", returns: "signal-handle" },
341
355
  // An environment variable, public or server-only; the browser build refuses a secret.
342
356
  $env: { export: "env", module: "@fluixi/start/env", returns: "plain" }
343
357
  };
358
+ var TAG_INTRINSICS = {
359
+ $html: { export: "html", module: "@fluixi/core" },
360
+ $svg: { export: "svg", module: "@fluixi/core" },
361
+ $css: { export: "css", module: "@fluixi/core" }
362
+ };
344
363
  var INTRINSIC_CALL = new RegExp(`\\$(?:${Object.keys(INTRINSICS).map((n) => n.slice(1)).join("|")})\\s*\\(`);
345
364
 
346
365
  // src/transform/source-locations.ts
@@ -515,13 +534,16 @@ function emitComponent(name, props, children, used, templates, at) {
515
534
  used.add("createComponent");
516
535
  const spreads = props.filter((p) => p.kind === "spread");
517
536
  const normal = props.filter((p) => p.kind !== "spread");
518
- const entries = normal.map(
519
- (p) => `get ${propKey(p.name)}() { return ${componentPropValue(p)}; }`
520
- );
537
+ const bodies = normal.map((p) => [p.name, componentPropValue(p)]);
521
538
  if (children.length > 0) {
522
- entries.push(`get children() { return ${emitChildren(children, used, templates)}; }`);
539
+ bodies.push(["children", emitChildren(children, used, templates)]);
540
+ }
541
+ let obj = `{ ${bodies.map(([name2, body]) => `get ${propKey(name2)}() { return ${body}; }`).join(", ")} }`;
542
+ if (bodies.some(([, body]) => /\bthis\b/.test(body))) {
543
+ const thunks = bodies.map(([name2, body]) => `${JSON.stringify(name2)}: () => (${body})`);
544
+ const getters = bodies.map(([name2]) => `get ${propKey(name2)}() { return _$t[${JSON.stringify(name2)}](); }`);
545
+ obj = `((_$t) => ({ ${getters.join(", ")} }))({ ${thunks.join(", ")} })`;
523
546
  }
524
- let obj = `{ ${entries.join(", ")} }`;
525
547
  if (spreads.length > 0) {
526
548
  used.add("mergeProps");
527
549
  obj = `mergeProps(${spreads.map((s) => s.expr).join(", ")}, ${obj})`;
@@ -603,7 +625,8 @@ function emitNode(node, used, templates) {
603
625
  } else {
604
626
  used.add("spread");
605
627
  const svgFlag = node.svg ? ", isSVG: true" : "";
606
- const customFlag = node.tag.includes("-") ? ", isCustomElement: true" : "";
628
+ const accessors = node.props.filter((p) => p.kind !== "spread" && p.expr !== void 0 && p.reactive && p.name !== "ref").map((p) => p.name);
629
+ const customFlag = node.tag.includes("-") ? `, isCustomElement: true, accessors: ${JSON.stringify(accessors)}` : "";
607
630
  parts.push(
608
631
  `spread({ element: ${el}, props: ${emitProps(node.props, null, used)}${svgFlag}${customFlag} });`
609
632
  );
@@ -656,6 +679,271 @@ function cleanTemplateText(value) {
656
679
  return out;
657
680
  }
658
681
 
682
+ // src/lower/entities.ts
683
+ var NAMED = {
684
+ quot: 34,
685
+ amp: 38,
686
+ apos: 39,
687
+ lt: 60,
688
+ gt: 62,
689
+ nbsp: 160,
690
+ iexcl: 161,
691
+ cent: 162,
692
+ pound: 163,
693
+ curren: 164,
694
+ yen: 165,
695
+ brvbar: 166,
696
+ sect: 167,
697
+ uml: 168,
698
+ copy: 169,
699
+ ordf: 170,
700
+ laquo: 171,
701
+ not: 172,
702
+ shy: 173,
703
+ reg: 174,
704
+ macr: 175,
705
+ deg: 176,
706
+ plusmn: 177,
707
+ sup2: 178,
708
+ sup3: 179,
709
+ acute: 180,
710
+ micro: 181,
711
+ para: 182,
712
+ middot: 183,
713
+ cedil: 184,
714
+ sup1: 185,
715
+ ordm: 186,
716
+ raquo: 187,
717
+ frac14: 188,
718
+ frac12: 189,
719
+ frac34: 190,
720
+ iquest: 191,
721
+ Agrave: 192,
722
+ Aacute: 193,
723
+ Acirc: 194,
724
+ Atilde: 195,
725
+ Auml: 196,
726
+ Aring: 197,
727
+ AElig: 198,
728
+ Ccedil: 199,
729
+ Egrave: 200,
730
+ Eacute: 201,
731
+ Ecirc: 202,
732
+ Euml: 203,
733
+ Igrave: 204,
734
+ Iacute: 205,
735
+ Icirc: 206,
736
+ Iuml: 207,
737
+ ETH: 208,
738
+ Ntilde: 209,
739
+ Ograve: 210,
740
+ Oacute: 211,
741
+ Ocirc: 212,
742
+ Otilde: 213,
743
+ Ouml: 214,
744
+ times: 215,
745
+ Oslash: 216,
746
+ Ugrave: 217,
747
+ Uacute: 218,
748
+ Ucirc: 219,
749
+ Uuml: 220,
750
+ Yacute: 221,
751
+ THORN: 222,
752
+ szlig: 223,
753
+ agrave: 224,
754
+ aacute: 225,
755
+ acirc: 226,
756
+ atilde: 227,
757
+ auml: 228,
758
+ aring: 229,
759
+ aelig: 230,
760
+ ccedil: 231,
761
+ egrave: 232,
762
+ eacute: 233,
763
+ ecirc: 234,
764
+ euml: 235,
765
+ igrave: 236,
766
+ iacute: 237,
767
+ icirc: 238,
768
+ iuml: 239,
769
+ eth: 240,
770
+ ntilde: 241,
771
+ ograve: 242,
772
+ oacute: 243,
773
+ ocirc: 244,
774
+ otilde: 245,
775
+ ouml: 246,
776
+ divide: 247,
777
+ oslash: 248,
778
+ ugrave: 249,
779
+ uacute: 250,
780
+ ucirc: 251,
781
+ uuml: 252,
782
+ yacute: 253,
783
+ thorn: 254,
784
+ yuml: 255,
785
+ OElig: 338,
786
+ oelig: 339,
787
+ Scaron: 352,
788
+ scaron: 353,
789
+ Yuml: 376,
790
+ fnof: 402,
791
+ circ: 710,
792
+ tilde: 732,
793
+ Alpha: 913,
794
+ Beta: 914,
795
+ Gamma: 915,
796
+ Delta: 916,
797
+ Epsilon: 917,
798
+ Zeta: 918,
799
+ Eta: 919,
800
+ Theta: 920,
801
+ Iota: 921,
802
+ Kappa: 922,
803
+ Lambda: 923,
804
+ Mu: 924,
805
+ Nu: 925,
806
+ Xi: 926,
807
+ Omicron: 927,
808
+ Pi: 928,
809
+ Rho: 929,
810
+ Sigma: 931,
811
+ Tau: 932,
812
+ Upsilon: 933,
813
+ Phi: 934,
814
+ Chi: 935,
815
+ Psi: 936,
816
+ Omega: 937,
817
+ alpha: 945,
818
+ beta: 946,
819
+ gamma: 947,
820
+ delta: 948,
821
+ epsilon: 949,
822
+ zeta: 950,
823
+ eta: 951,
824
+ theta: 952,
825
+ iota: 953,
826
+ kappa: 954,
827
+ lambda: 955,
828
+ mu: 956,
829
+ nu: 957,
830
+ xi: 958,
831
+ omicron: 959,
832
+ pi: 960,
833
+ rho: 961,
834
+ sigmaf: 962,
835
+ sigma: 963,
836
+ tau: 964,
837
+ upsilon: 965,
838
+ phi: 966,
839
+ chi: 967,
840
+ psi: 968,
841
+ omega: 969,
842
+ thetasym: 977,
843
+ upsih: 978,
844
+ piv: 982,
845
+ ensp: 8194,
846
+ emsp: 8195,
847
+ thinsp: 8201,
848
+ zwnj: 8204,
849
+ zwj: 8205,
850
+ lrm: 8206,
851
+ rlm: 8207,
852
+ ndash: 8211,
853
+ mdash: 8212,
854
+ lsquo: 8216,
855
+ rsquo: 8217,
856
+ sbquo: 8218,
857
+ ldquo: 8220,
858
+ rdquo: 8221,
859
+ bdquo: 8222,
860
+ dagger: 8224,
861
+ Dagger: 8225,
862
+ bull: 8226,
863
+ hellip: 8230,
864
+ permil: 8240,
865
+ prime: 8242,
866
+ Prime: 8243,
867
+ lsaquo: 8249,
868
+ rsaquo: 8250,
869
+ oline: 8254,
870
+ frasl: 8260,
871
+ euro: 8364,
872
+ image: 8465,
873
+ weierp: 8472,
874
+ real: 8476,
875
+ trade: 8482,
876
+ alefsym: 8501,
877
+ larr: 8592,
878
+ uarr: 8593,
879
+ rarr: 8594,
880
+ darr: 8595,
881
+ harr: 8596,
882
+ crarr: 8629,
883
+ lArr: 8656,
884
+ uArr: 8657,
885
+ rArr: 8658,
886
+ dArr: 8659,
887
+ hArr: 8660,
888
+ forall: 8704,
889
+ part: 8706,
890
+ exist: 8707,
891
+ empty: 8709,
892
+ nabla: 8711,
893
+ isin: 8712,
894
+ notin: 8713,
895
+ ni: 8715,
896
+ prod: 8719,
897
+ sum: 8721,
898
+ minus: 8722,
899
+ lowast: 8727,
900
+ radic: 8730,
901
+ prop: 8733,
902
+ infin: 8734,
903
+ ang: 8736,
904
+ and: 8743,
905
+ or: 8744,
906
+ cap: 8745,
907
+ cup: 8746,
908
+ int: 8747,
909
+ there4: 8756,
910
+ sim: 8764,
911
+ cong: 8773,
912
+ asymp: 8776,
913
+ ne: 8800,
914
+ equiv: 8801,
915
+ le: 8804,
916
+ ge: 8805,
917
+ sub: 8834,
918
+ sup: 8835,
919
+ nsub: 8836,
920
+ sube: 8838,
921
+ supe: 8839,
922
+ oplus: 8853,
923
+ otimes: 8855,
924
+ perp: 8869,
925
+ sdot: 8901,
926
+ lceil: 8968,
927
+ rceil: 8969,
928
+ lfloor: 8970,
929
+ rfloor: 8971,
930
+ lang: 9001,
931
+ rang: 9002,
932
+ loz: 9674,
933
+ spades: 9824,
934
+ clubs: 9827,
935
+ hearts: 9829,
936
+ diams: 9830
937
+ };
938
+ var REFERENCE = /&(?:#[xX]([0-9a-fA-F]{1,6})|#([0-9]{1,7})|([a-zA-Z][a-zA-Z0-9]{1,31}));/g;
939
+ function decodeEntities(value) {
940
+ if (!value.includes("&")) return value;
941
+ return value.replace(REFERENCE, (match, hex, dec, name) => {
942
+ const code = hex ? parseInt(hex, 16) : dec ? parseInt(dec, 10) : Object.prototype.hasOwnProperty.call(NAMED, name) ? NAMED[name] : void 0;
943
+ return code !== void 0 && code <= 1114111 ? String.fromCodePoint(code) : match;
944
+ });
945
+ }
946
+
659
947
  // src/lower/template.ts
660
948
  var DELEGATED = /* @__PURE__ */ new Set([
661
949
  "click",
@@ -674,6 +962,7 @@ var DELEGATED = /* @__PURE__ */ new Set([
674
962
  function escapeTemplate(s) {
675
963
  return s.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
676
964
  }
965
+ var CONTAINER = "container";
677
966
  function capitalize(s) {
678
967
  return s.charAt(0).toUpperCase() + s.slice(1);
679
968
  }
@@ -728,10 +1017,6 @@ var Lowerer = class {
728
1017
  if (hasElse) i = elseIdx;
729
1018
  continue;
730
1019
  }
731
- if (child.attributes.some((a) => a.kind === "EachDirective")) {
732
- out.push(this.lowerEach(child));
733
- continue;
734
- }
735
1020
  }
736
1021
  const node = this.lowerNode(child);
737
1022
  if (node) out.push(node);
@@ -745,7 +1030,7 @@ var Lowerer = class {
745
1030
  switch (node.kind) {
746
1031
  case "Text": {
747
1032
  if (node.raw) return { kind: "text", value: node.value };
748
- const cleaned = cleanTemplateText(node.value);
1033
+ const cleaned = decodeEntities(cleanTemplateText(node.value));
749
1034
  return cleaned ? { kind: "text", value: cleaned } : null;
750
1035
  }
751
1036
  case "Comment":
@@ -773,13 +1058,16 @@ var Lowerer = class {
773
1058
  node.props.unshift({ name: "component", kind: "attr", expr: `() => ${paren(this.hole(isAttr.value.hole).code, "arrowBody")}` });
774
1059
  return node;
775
1060
  }
1061
+ const each = this.lowerEach(el);
1062
+ const children = each ? [each] : this.lowerChildren(el.children);
1063
+ if (el.tag === CONTAINER) return children.length === 1 ? children[0] : { kind: "fragment", children };
776
1064
  const at = this.tagAt(el);
777
1065
  return {
778
1066
  kind: "element",
779
1067
  tag: el.tag,
780
1068
  svg: el.namespace === "svg",
781
- props: this.lowerAttributes(el.attributes),
782
- children: this.lowerChildren(el.children),
1069
+ props: this.lowerAttributes(el.attributes, true),
1070
+ children,
783
1071
  static: false,
784
1072
  ...at ? { at } : {}
785
1073
  };
@@ -851,10 +1139,14 @@ var Lowerer = class {
851
1139
  const at = this.tagAt(el);
852
1140
  return { kind: "component", name: "Show", props, children: [child], ...at ? { at } : {}, ...cond.at ? { bindAt: cond.at } : {} };
853
1141
  }
854
- /** `<el each=${items} key?>${item => …}</el>` → `<For each>{item => <el>…</el>}</For>`. */
1142
+ /**
1143
+ * `<el each=${items} key?>${item => …}</el>` → `<el><For each>{item => …}</For></el>`: the
1144
+ * content is repeated per item. Content that is not a `${item => …}` arrow is repeated as
1145
+ * it is. Null when the element has no `each`.
1146
+ */
855
1147
  lowerEach(el) {
856
1148
  const eachDir = el.attributes.find((a) => a.kind === "EachDirective");
857
- if (!eachDir || eachDir.kind !== "EachDirective") return this.lowerNode(el);
1149
+ if (!eachDir || eachDir.kind !== "EachDirective") return null;
858
1150
  const each = this.hole(eachDir.hole);
859
1151
  const props = [{ name: "each", kind: "attr", expr: each.code, reactive: each.reactive, ...each.at ? { at: each.at } : {} }];
860
1152
  if (eachDir.key) {
@@ -864,12 +1156,12 @@ var Lowerer = class {
864
1156
  const arrow = this.itemArrow(el);
865
1157
  let childrenCode;
866
1158
  if (arrow) {
867
- const bodyIR = { kind: "expr", code: arrow.body, reactive: arrow.bodyReactive };
868
- const repeated = this.rebuildWithChildren(el, [bodyIR]);
869
- childrenCode = `(${arrow.params.join(", ")}) => ${paren(this.emit(repeated), "arrowBody")}`;
1159
+ const body = arrow.bodyReactive ? `() => ${paren(arrow.body, "arrowBody")}` : paren(arrow.body, "arrowBody");
1160
+ childrenCode = `(${arrow.params.join(", ")}) => ${body}`;
870
1161
  } else {
871
- const repeated = this.stripAndLower(el, (a) => a.kind === "EachDirective");
872
- childrenCode = `() => ${paren(this.emit(repeated), "arrowBody")}`;
1162
+ const content = this.lowerChildren(el.children);
1163
+ const ir = content.length === 1 ? content[0] : { kind: "fragment", children: content };
1164
+ childrenCode = `() => ${paren(this.emit(ir), "arrowBody")}`;
873
1165
  }
874
1166
  const children = [{ kind: "expr", code: childrenCode, reactive: false }];
875
1167
  const at = this.tagAt(el);
@@ -886,33 +1178,23 @@ var Lowerer = class {
886
1178
  const clone = { ...el, attributes: el.attributes.filter((a) => !drop(a)) };
887
1179
  return clone.kind === "Element" ? this.lowerElement(clone) : this.lowerComponent(clone);
888
1180
  }
889
- /** Same element (minus each/key) but with explicit IR children. */
890
- rebuildWithChildren(el, children) {
891
- const props = this.lowerAttributes(
892
- el.attributes.filter((a) => a.kind !== "EachDirective")
893
- );
894
- if (el.kind === "Element") {
895
- const at = this.tagAt(el);
896
- return {
897
- kind: "element",
898
- tag: el.tag,
899
- svg: el.namespace === "svg",
900
- props,
901
- children,
902
- static: false,
903
- ...at ? { at } : {}
904
- };
905
- }
906
- return { kind: "component", name: el.tag, props, children };
907
- }
908
1181
  // --- attributes ---------------------------------------------------------
909
- lowerAttributes(attrs) {
1182
+ /**
1183
+ * `element`: a DOM element, where each class:/style: value that moves is its own accessor.
1184
+ * A component gets the object as before, rebuilt whole when any value moves.
1185
+ */
1186
+ lowerAttributes(attrs, element = false) {
1187
+ let anyReactive = false;
1188
+ const entry = (name, h) => {
1189
+ anyReactive ||= h.reactive;
1190
+ if (!element || !h.reactive) return `${JSON.stringify(name)}: ${h.code}`;
1191
+ const accessor = `() => ${paren(h.code, "arrowBody")}`;
1192
+ return `${JSON.stringify(name)}: ${h.at ? markHole(accessor, h.at.line, h.at.column) : accessor}`;
1193
+ };
910
1194
  const props = [];
911
1195
  const classEntries = [];
912
- let classReactive = false;
913
1196
  let classAt;
914
1197
  const styleEntries = [];
915
- let styleReactive = false;
916
1198
  let styleAt;
917
1199
  const usePairs = [];
918
1200
  for (const a of attrs) {
@@ -952,15 +1234,13 @@ var Lowerer = class {
952
1234
  break;
953
1235
  case "ClassDirective": {
954
1236
  const h = this.hole(a.hole);
955
- classEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
956
- classReactive = classReactive || h.reactive;
1237
+ classEntries.push(entry(a.name, h));
957
1238
  classAt ??= h.at;
958
1239
  break;
959
1240
  }
960
1241
  case "StyleDirective": {
961
1242
  const h = this.hole(a.hole);
962
- styleEntries.push(`${JSON.stringify(a.name)}: ${h.code}`);
963
- styleReactive = styleReactive || h.reactive;
1243
+ styleEntries.push(entry(a.name, h));
964
1244
  styleAt ??= h.at;
965
1245
  break;
966
1246
  }
@@ -980,18 +1260,19 @@ var Lowerer = class {
980
1260
  name: "classList",
981
1261
  kind: "attr",
982
1262
  expr: `{ ${classEntries.join(", ")} }`,
983
- reactive: classReactive,
1263
+ reactive: !element && anyReactive,
984
1264
  ...classAt ? { at: classAt } : {}
985
1265
  });
986
1266
  }
987
1267
  if (styleEntries.length > 0) {
988
- props.push({
989
- name: "style",
990
- kind: "attr",
991
- expr: `{ ${styleEntries.join(", ")} }`,
992
- reactive: styleReactive,
993
- ...styleAt ? { at: styleAt } : {}
994
- });
1268
+ const entries = `{ ${styleEntries.join(", ")} }`;
1269
+ const base = props.findIndex((p) => p.name === "style");
1270
+ if (base === -1) props.push({ name: "style", kind: "attr", expr: entries, reactive: !element && anyReactive, ...styleAt ? { at: styleAt } : {} });
1271
+ else {
1272
+ const prop = props[base];
1273
+ const value = prop.expr === void 0 ? JSON.stringify(prop.literal) : prop.reactive ? `() => ${paren(prop.expr, "arrowBody")}` : prop.expr;
1274
+ props[base] = { name: "style", kind: "attr", expr: `[${value}, ${entries}]`, reactive: false, ...prop.at ? { at: prop.at } : {} };
1275
+ }
995
1276
  }
996
1277
  if (usePairs.length > 0) {
997
1278
  props.push({ name: "use", kind: "attr", expr: `[${usePairs.join(", ")}]` });
@@ -1080,7 +1361,7 @@ var Lowerer = class {
1080
1361
  return base;
1081
1362
  }
1082
1363
  if (v.kind === "static") {
1083
- base.literal = v.value;
1364
+ base.literal = decodeEntities(v.value);
1084
1365
  return base;
1085
1366
  }
1086
1367
  if (v.kind === "hole") {
@@ -1093,7 +1374,7 @@ var Lowerer = class {
1093
1374
  let reactive = false;
1094
1375
  let at;
1095
1376
  const body = v.parts.map((p) => {
1096
- if ("text" in p) return escapeTemplate(p.text);
1377
+ if ("text" in p) return escapeTemplate(decodeEntities(p.text));
1097
1378
  const h = this.hole(p.hole);
1098
1379
  reactive = reactive || h.reactive;
1099
1380
  at ??= h.at;
@@ -1110,6 +1391,26 @@ function lowerTemplate(pieces, holes, used, opts = {}) {
1110
1391
  return new Lowerer(holes, used, opts.sourceFile, opts.positionAt).lowerRoot(root.children);
1111
1392
  }
1112
1393
 
1394
+ // src/transform/styles.ts
1395
+ var import_sourcemap_codec = require("@jridgewell/sourcemap-codec");
1396
+ var SCOPE_ATTR = "data-fx-s";
1397
+ function applyTemplateStyles(ir, t) {
1398
+ const walk2 = (node) => {
1399
+ const children = node.children;
1400
+ if (children) {
1401
+ for (let i = children.length - 1; i >= 0; i--) {
1402
+ const child = children[i];
1403
+ if (child.kind === "element" && child.tag === "style" && t.owner) children.splice(i, 1);
1404
+ else walk2(child);
1405
+ }
1406
+ }
1407
+ if (t.scope && node.kind === "element" && node.tag !== "style" && node.props && !node.props.some((p) => p.name === SCOPE_ATTR)) {
1408
+ node.props.unshift({ name: SCOPE_ATTR, kind: "attr", literal: t.scope });
1409
+ }
1410
+ };
1411
+ walk2(ir);
1412
+ }
1413
+
1113
1414
  // src/optimize/analyze-static.ts
1114
1415
  function propReason(prop) {
1115
1416
  switch (prop.kind) {
@@ -1385,6 +1686,7 @@ function compilePieces(pieces, holes, options = {}) {
1385
1686
  ...options.sourceFile ? { sourceFile: options.sourceFile } : {},
1386
1687
  ...options.positionAt ? { positionAt: options.positionAt } : {}
1387
1688
  });
1689
+ if (options.templateStyles) applyTemplateStyles(ir, options.templateStyles);
1388
1690
  analyzeStatic(ir);
1389
1691
  resolveComponentSources(ir, {
1390
1692
  resolver: createComponentResolver(options.resolve ?? []),
@@ -1468,7 +1770,7 @@ function componentGlobals(rules, options = {}) {
1468
1770
  resolved.set(name, target);
1469
1771
  }
1470
1772
  }
1471
- const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
1773
+ const usableIntrinsics = intrinsics ? Object.entries({ ...INTRINSICS, ...TAG_INTRINSICS }).filter(([, i]) => {
1472
1774
  const pkg = packageOf(i.module);
1473
1775
  return !available || !pkg || available.has(pkg);
1474
1776
  }) : [];