@fluixi/compiler 1.0.0-alpha.93 → 1.0.0-alpha.95

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 (93) hide show
  1. package/LICENSE +1 -1
  2. package/dist/analyze/intrinsics.cjs +13 -1
  3. package/dist/analyze/intrinsics.d.cts +14 -0
  4. package/dist/analyze/intrinsics.d.ts +14 -0
  5. package/dist/analyze/intrinsics.d.ts.map +1 -1
  6. package/dist/analyze/intrinsics.js +17 -0
  7. package/dist/analyze/intrinsics.mjs +13 -1
  8. package/dist/analyze/static-graph.cjs +1 -1
  9. package/dist/analyze/static-graph.mjs +1 -1
  10. package/dist/{babel-RJHJQVEM.mjs → babel-V33QLJBF.mjs} +4 -4
  11. package/dist/{chunk-56QSOVVL.mjs → chunk-62F2LLBM.mjs} +1 -1
  12. package/dist/{chunk-R7PPFBCL.mjs → chunk-7GNSGUHK.mjs} +4 -83
  13. package/dist/{chunk-U7HCFLZ2.mjs → chunk-B64LVPTU.mjs} +356 -24
  14. package/dist/{chunk-OD53TMER.mjs → chunk-C3AK5PBV.mjs} +13 -1
  15. package/dist/{chunk-TJIH7TLX.mjs → chunk-GLFUPZ27.mjs} +1 -1
  16. package/dist/chunk-HUABRVWB.mjs +92 -0
  17. package/dist/chunk-XCWP7WJG.mjs +584 -0
  18. package/dist/codegen/backends/imperative.cjs +1 -1
  19. package/dist/codegen/backends/imperative.d.ts.map +1 -1
  20. package/dist/codegen/backends/imperative.js +2 -1
  21. package/dist/codegen/backends/imperative.mjs +1 -1
  22. package/dist/frontend/babel/build-ir-lit.cjs +352 -22
  23. package/dist/frontend/babel/build-ir-lit.mjs +352 -22
  24. package/dist/frontend/babel/build-ir.cjs +352 -22
  25. package/dist/frontend/babel/build-ir.mjs +352 -22
  26. package/dist/frontend/babel/index.cjs +353 -23
  27. package/dist/frontend/babel/index.mjs +353 -23
  28. package/dist/frontend/babel/lower-template.cjs +352 -22
  29. package/dist/frontend/babel/lower-template.mjs +352 -22
  30. package/dist/frontend/babel/plugin.cjs +352 -22
  31. package/dist/frontend/babel/plugin.mjs +352 -22
  32. package/dist/index.cjs +321 -22
  33. package/dist/index.mjs +333 -22
  34. package/dist/integrations.cjs +1240 -56
  35. package/dist/integrations.d.ts.map +1 -1
  36. package/dist/integrations.js +62 -9
  37. package/dist/integrations.mjs +257 -26
  38. package/dist/lower/compile-template.cjs +315 -21
  39. package/dist/lower/compile-template.d.cts +13 -0
  40. package/dist/lower/compile-template.d.ts +13 -0
  41. package/dist/lower/compile-template.d.ts.map +1 -1
  42. package/dist/lower/compile-template.js +3 -0
  43. package/dist/lower/compile-template.mjs +327 -21
  44. package/dist/lower/entities.cjs +288 -0
  45. package/dist/lower/entities.d.cts +1 -0
  46. package/dist/lower/entities.d.ts +2 -0
  47. package/dist/lower/entities.d.ts.map +1 -0
  48. package/dist/lower/entities.js +54 -0
  49. package/dist/lower/entities.mjs +267 -0
  50. package/dist/lower/jsx.cjs +104 -47
  51. package/dist/lower/jsx.d.cts +8 -0
  52. package/dist/lower/jsx.d.ts +8 -0
  53. package/dist/lower/jsx.d.ts.map +1 -1
  54. package/dist/lower/jsx.js +92 -2
  55. package/dist/lower/jsx.mjs +104 -47
  56. package/dist/lower/template.cjs +293 -20
  57. package/dist/lower/template.d.ts.map +1 -1
  58. package/dist/lower/template.js +35 -19
  59. package/dist/lower/template.mjs +293 -20
  60. package/dist/resolve/builtins.cjs +1 -1
  61. package/dist/resolve/builtins.mjs +1 -1
  62. package/dist/resolve/component-globals.cjs +6 -1
  63. package/dist/resolve/component-globals.js +2 -2
  64. package/dist/resolve/component-globals.mjs +6 -1
  65. package/dist/resolve/write-globals.cjs +6 -1
  66. package/dist/resolve/write-globals.mjs +6 -1
  67. package/dist/{server-fns-ZFRDIQ2X.mjs → server-fns-N3SDJXA7.mjs} +5 -4
  68. package/dist/{server-functions-CTDXX67X.mjs → server-functions-LVS66Q4R.mjs} +3 -3
  69. package/dist/transform/index.cjs +973 -33
  70. package/dist/transform/index.mjs +991 -47
  71. package/dist/transform/props.mjs +19 -14
  72. package/dist/transform/server-fns.mjs +19 -14
  73. package/dist/transform/styles.cjs +606 -0
  74. package/dist/transform/styles.d.cts +237 -0
  75. package/dist/transform/styles.d.ts +238 -0
  76. package/dist/transform/styles.d.ts.map +1 -0
  77. package/dist/transform/styles.js +743 -0
  78. package/dist/transform/styles.mjs +671 -0
  79. package/dist/transform/templates.cjs +972 -32
  80. package/dist/transform/templates.d.cts +13 -0
  81. package/dist/transform/templates.d.ts +13 -0
  82. package/dist/transform/templates.d.ts.map +1 -1
  83. package/dist/transform/templates.js +49 -12
  84. package/dist/transform/templates.mjs +990 -46
  85. package/dist/{transform-QWWQDCXE.mjs → transform-P4AETYV4.mjs} +49 -16
  86. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  87. package/dist/vite-styles.cjs +223 -0
  88. package/dist/vite-styles.d.cts +68 -0
  89. package/dist/vite-styles.d.ts +69 -0
  90. package/dist/vite-styles.d.ts.map +1 -0
  91. package/dist/vite-styles.js +241 -0
  92. package/dist/vite-styles.mjs +214 -0
  93. package/package.json +5 -4
@@ -1 +1 @@
1
- {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../src/integrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAEhC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAE5C;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,eAAoB;;;;;;;;;;;;;;;;;GAwCpE;AAMD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,eAAoB,aAIpD,GAAG,MAAM,YAAY,GAAG,SAkB5C;AAqCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAE,eAAoB,GAAG,CAAC,CAsHpE;AAoID;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,eAAoB,IACxC,MAAM,GAAG,EAAE,QAAQ,MAAM,mBAUjD;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,eAAoB;;oBAItC,MAAM,MAAM,MAAM;;;;;;;;;;;;EAK3C;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,eAAoB;;iBAIhD,GAAG;EAwBnB;AAWD,YAAY,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAoD7E;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,CAAC,CAqCvF;;;;;;;;;AAED,wBAOE"}
1
+ {"version":3,"file":"integrations.d.ts","sourceRoot":"","sources":["../src/integrations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACzB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAEhC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAE5C;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAMD;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,eAAoB;;;;;;;;;;;;;;;;;GAwCpE;AAMD;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,eAAoB,aAIpD,GAAG,MAAM,YAAY,GAAG,SAkB5C;AAqCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAE,eAAoB,GAAG,CAAC,CAqKpE;AAsID;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,eAAoB,IACxC,MAAM,GAAG,EAAE,QAAQ,MAAM,mBAUjD;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,eAAoB;;oBAItC,MAAM,MAAM,MAAM;;;;;;;;;;;;EAK3C;AAMD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,eAAoB;;iBAIhD,GAAG;EAwBnB;AAWD,YAAY,EAAE,wBAAwB,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAqD7E;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,GAAG,GAAG,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,CAAC,CAqCvF;;;;;;;;;AAED,wBAOE"}
@@ -120,28 +120,73 @@ const RETIRED_SUBPATHS = {
120
120
  * Create a Vite plugin for JSX transformation
121
121
  */
122
122
  export function createVitePlugin(options = {}) {
123
+ // Component `<style>` blocks, when @fluixi-css/vite is in the build to process them.
124
+ let transformTemplates;
125
+ let projectRoot = process.cwd();
126
+ const componentStyles = createComponentStyles((code, id, styles) => {
127
+ // Scope ids hash the path from the project root, marks or not: the same on every machine
128
+ // and for every id a module is reached by.
129
+ // Reported by `transform`, from the module's last pass: a first pass, or a compile of
130
+ // another module whose values this one uses, would report what the next pass resolves.
131
+ return transformTemplates(code, id, { ...transformOptions(options, id), sourceRoot: projectRoot, styles });
132
+ });
123
133
  return {
124
134
  name: 'vite-fluixi-jsx',
125
135
  enforce: 'pre',
126
- config() {
127
- return {
128
- esbuild: {
129
- jsx: 'automatic',
130
- jsxImportSource: options.importSource || '@fluixi/jsx',
131
- },
132
- };
136
+ // JSX the compiler leaves alone goes to Vite's own transform: Oxc in Vite 8 (Rolldown),
137
+ // esbuild before, which Vite 8 warns about.
138
+ // In dev, CSS maps are on unless the app says otherwise, so devtools show the line a
139
+ // component's rule was written on. Vite leaves them off by default; a build never has them.
140
+ config(user) {
141
+ const importSource = options.importSource || '@fluixi/jsx';
142
+ const jsx = this && this.meta?.rolldownVersion
143
+ ? { oxc: { jsx: { runtime: 'automatic', importSource } } }
144
+ : { esbuild: { jsx: 'automatic', jsxImportSource: importSource } };
145
+ return user?.css?.devSourcemap === undefined ? { ...jsx, css: { devSourcemap: true } } : jsx;
133
146
  },
134
147
  // Written once per build, and on dev-server start, rather than per transform: the
135
148
  // set of resolvable names comes from config, so nothing a file does can change it.
136
- configResolved(config) {
149
+ async configResolved(config) {
137
150
  const outcome = writeComponentGlobals(options, config?.root ?? process.cwd());
138
151
  if (outcome.warning)
139
152
  console.warn(outcome.warning);
153
+ if (options.babel)
154
+ return;
155
+ projectRoot = config?.root ?? projectRoot;
156
+ componentStyles.connect(config?.plugins, config?.root);
157
+ const entry = config?.command === 'build' && config.build?.lib ? config.build.lib.entry : undefined;
158
+ const first = typeof entry === 'string' ? entry : Array.isArray(entry) ? entry[0] : entry && typeof entry === 'object' ? Object.values(entry)[0] : undefined;
159
+ if (typeof first === 'string')
160
+ componentStyles.setLibrary(dirname(resolvePath(config.root ?? process.cwd(), first)));
161
+ if (componentStyles.active)
162
+ ({ transformTemplates } = await import('./transform/index.js'));
163
+ },
164
+ generateBundle() {
165
+ for (const [fileName, source] of componentStyles.libraryFiles())
166
+ this.emitFile({ type: 'asset', fileName, source });
167
+ },
168
+ // An edited component's style modules go out with its update: their ids end in `.css`, so
169
+ // Vite does not connect them to the file.
170
+ handleHotUpdate(ctx) {
171
+ if (!componentStyles.active)
172
+ return undefined;
173
+ const styles = componentStyles.hotModules(ctx.file, ctx.server.moduleGraph);
174
+ return styles.length ? [...ctx.modules, ...styles] : undefined;
175
+ },
176
+ configureServer(server) {
177
+ componentStyles.setServer(server);
178
+ },
179
+ load(id) {
180
+ return componentStyles.isStyle(id) ? componentStyles.load(id, this) : null;
140
181
  },
141
182
  // A subpath we retired resolves to nothing, and the bundler reports that as
142
183
  // `Missing "./x" specifier`, which names neither the replacement nor the file
143
184
  // that asked. Answer it here, where the rename is known.
144
185
  resolveId(id, importer) {
186
+ if (componentStyles.isStyle(id))
187
+ return componentStyles.resolveId(id, importer, this);
188
+ if (componentStyles.isLibraryImport(id, importer))
189
+ return { id, external: true };
145
190
  const moved = RETIRED_SUBPATHS[id];
146
191
  if (!moved)
147
192
  return null;
@@ -152,6 +197,11 @@ export function createVitePlugin(options = {}) {
152
197
  if (!/\.(jsx|tsx|ts)$/i.test(id)) {
153
198
  return null;
154
199
  }
200
+ if (!options.babel && componentStyles.active) {
201
+ const result = await componentStyles.compile(code, id, this);
202
+ reportDiagnostics(result, id);
203
+ return result;
204
+ }
155
205
  if (!options.babel)
156
206
  return compileModule(code, id, options);
157
207
  const babelPlugin = await createBabelPlugin(options);
@@ -306,6 +356,8 @@ function reportDiagnostics(result, id) {
306
356
  say(d.message);
307
357
  for (const d of r?.intrinsicDiagnostics ?? [])
308
358
  say(d.message);
359
+ for (const d of r?.styleDiagnostics ?? [])
360
+ say(`${d.line}:${d.column + 1} ${d.message}`);
309
361
  for (const d of r?.propsDiagnostics ?? []) {
310
362
  say(`\`${d.name}\` was left destructured: ${d.message}. It reads once instead of tracking.`);
311
363
  }
@@ -403,8 +455,9 @@ export function createESBuildPlugin(options = {}) {
403
455
  };
404
456
  }
405
457
  import { writeComponentGlobals } from './resolve/write-globals.js';
458
+ import { createComponentStyles } from './vite-styles.js';
406
459
  import { readdirSync, readFileSync } from 'node:fs';
407
- import { join as _join } from 'node:path';
460
+ import { dirname, join as _join, resolve as resolvePath } from 'node:path';
408
461
  const SERVER_FNS_VMOD = 'virtual:fluixi-server-fns';
409
462
  /** Recursively find source files containing the `"use server"` directive under `dir`. */
410
463
  /**
@@ -1,12 +1,17 @@
1
- /*! @fluixi/compiler v1.0.0-alpha.93 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
1
+ /*! @fluixi/compiler v1.0.0-alpha.95 | (c) 2026 Ibrahima Touré and Fluixi contributors | MIT */
2
+ import {
3
+ styleIds
4
+ } from "./chunk-XCWP7WJG.mjs";
2
5
  import {
3
6
  INTRINSICS,
7
+ TAG_INTRINSICS,
4
8
  builtinComponentMap,
5
9
  createComponentResolver
6
- } from "./chunk-OD53TMER.mjs";
10
+ } from "./chunk-C3AK5PBV.mjs";
11
+ import "./chunk-HUABRVWB.mjs";
7
12
  import {
8
13
  __require
9
- } from "./chunk-TJIH7TLX.mjs";
14
+ } from "./chunk-GLFUPZ27.mjs";
10
15
 
11
16
  // src/resolve/write-globals.ts
12
17
  import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
@@ -75,7 +80,7 @@ function componentGlobals(rules, options = {}) {
75
80
  resolved.set(name, target);
76
81
  }
77
82
  }
78
- const usableIntrinsics = intrinsics ? Object.entries(INTRINSICS).filter(([, i]) => {
83
+ const usableIntrinsics = intrinsics ? Object.entries({ ...INTRINSICS, ...TAG_INTRINSICS }).filter(([, i]) => {
79
84
  const pkg = packageOf(i.module);
80
85
  return !available || !pkg || available.has(pkg);
81
86
  }) : [];
@@ -138,11 +143,11 @@ function coveredByInclude(root, target) {
138
143
  }
139
144
  if (config.extends !== void 0) return void 0;
140
145
  if (!Array.isArray(config.include)) return true;
141
- const relative2 = relativePosix(root, target);
146
+ const relative3 = relativePosix(root, target);
142
147
  return config.include.some((entry) => {
143
148
  if (typeof entry !== "string") return false;
144
149
  const pattern = entry.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*\//g, "(?:.*/)?").replace(/\*/g, "[^/]*");
145
- return new RegExp(`^${pattern}(?:/.*)?$`).test(relative2);
150
+ return new RegExp(`^${pattern}(?:/.*)?$`).test(relative3);
146
151
  });
147
152
  }
148
153
  function relativePosix(from, to) {
@@ -228,17 +233,206 @@ function writeComponentGlobals(options, root) {
228
233
  }
229
234
  function warnIfUnreachable(root, target) {
230
235
  if (coveredByInclude(root, target) !== false) return void 0;
231
- const relative2 = relativePosix(root, target);
232
- return `[fluixi] ${relative2} is not covered by "include" in tsconfig.json, so TypeScript will ignore it and every resolved component stays "Cannot find name". Add "${relative2}" to "include".`;
236
+ const relative3 = relativePosix(root, target);
237
+ return `[fluixi] ${relative3} is not covered by "include" in tsconfig.json, so TypeScript will ignore it and every resolved component stays "Cannot find name". Add "${relative3}" to "include".`;
238
+ }
239
+
240
+ // src/vite-styles.ts
241
+ import { existsSync, readFileSync as readFileSync2 } from "node:fs";
242
+ import { basename as basename2, dirname as dirname2, extname, join, relative as relative2 } from "node:path";
243
+ var STYLE_ID = /\.fx-(\d+)\.css(?:\?inline)?$/;
244
+ var LITERAL_ID = /\.fx-literal-([\w$]+)\.css\?inline$/;
245
+ var SUFFIX = /\.fx-(?:\d+|literal-[\w$]+)\.css(?:\?inline)?$/;
246
+ var styleId = styleIds.block;
247
+ function firstLoc(nodes) {
248
+ for (const node of nodes) {
249
+ if (node.loc) return node.loc.source;
250
+ if ((node.kind === "rule" || node.kind === "at-rule") && node.nodes.length) {
251
+ const inner = firstLoc(node.nodes);
252
+ if (inner) return inner;
253
+ }
254
+ }
255
+ return void 0;
256
+ }
257
+ var ownerOf = (id) => id.slice(0, id.search(SUFFIX));
258
+ var loader = (name) => `const href = new URL(${JSON.stringify(`./${name}`)}, import.meta.url).href;
259
+ if (typeof document !== 'undefined' && !document.querySelector(\`link[data-fx-css="\${href}"]\`)) {
260
+ const link = document.createElement('link');
261
+ link.rel = 'stylesheet';
262
+ link.href = href;
263
+ link.dataset.fxCss = href;
264
+ document.head.appendChild(link);
265
+ }
266
+ `;
267
+ function createComponentStyles(compile) {
268
+ let api;
269
+ let server;
270
+ let root = process.cwd();
271
+ let library;
272
+ const emitted = /* @__PURE__ */ new Map();
273
+ const fileOf = (id) => existsSync(id) ? id : join(root, id);
274
+ const cache = /* @__PURE__ */ new Map();
275
+ const resolveReference = async (ref, importer, ctx, seen, modules) => {
276
+ const resolved = await ctx.resolve?.(ref.source, importer);
277
+ if (!resolved) return null;
278
+ const file = resolved.id.split("?")[0];
279
+ if (seen.has(file)) return null;
280
+ let code;
281
+ try {
282
+ code = readFileSync2(fileOf(file), "utf8");
283
+ } catch {
284
+ return null;
285
+ }
286
+ const styles = api.styles(file);
287
+ let result = compile(code, file, styles);
288
+ if (result?.styleReferences?.length) {
289
+ const imported = await resolveAll(result.styleReferences, file, ctx, /* @__PURE__ */ new Set([...seen, file]), modules);
290
+ result = compile(code, file, { ...styles, imported, importedModules: modules });
291
+ }
292
+ const literal = result?.styleLiterals?.find((l) => l.name === ref.name);
293
+ if (!literal) return null;
294
+ const nodes = literal.nodes ?? styles.process(literal.css, file);
295
+ const named = firstLoc(nodes);
296
+ if (named) modules.set(named, { id: file, code });
297
+ return nodes;
298
+ };
299
+ const resolveAll = async (refs, importer, ctx, seen, modules) => {
300
+ const imported = /* @__PURE__ */ new Map();
301
+ for (const ref of refs) {
302
+ const nodes = await resolveReference(ref, importer, ctx, seen, modules);
303
+ if (nodes) imported.set(`${ref.source}#${ref.name}`, nodes);
304
+ }
305
+ return imported;
306
+ };
307
+ const run = async (code, id, ctx) => {
308
+ const file = fileOf(id);
309
+ const styles = api.styles(file);
310
+ let result = compile(code, file, styles);
311
+ if (result?.styleReferences?.length) {
312
+ const modules = /* @__PURE__ */ new Map();
313
+ const imported = await resolveAll(result.styleReferences, id, ctx, /* @__PURE__ */ new Set([file]), modules);
314
+ result = compile(code, file, { ...styles, imported, importedModules: modules });
315
+ }
316
+ const css = (result?.styles ?? []).map((s) => s.css);
317
+ const maps = (result?.styles ?? []).map((s) => s.map ?? null);
318
+ const literals = new Map((result?.styleLiterals ?? []).map((l) => [l.name, l.css]));
319
+ const before = cache.get(file);
320
+ cache.set(file, { source: code, css, maps, literals });
321
+ if (server && before) {
322
+ for (let i = 0; i < css.length; i++) {
323
+ if (before.css[i] === css[i]) continue;
324
+ const mod = server.moduleGraph.getModuleById(styleId(file, i));
325
+ if (mod) void server.reloadModule(mod);
326
+ }
327
+ }
328
+ const page = (result?.styles ?? []).flatMap((s, i) => s.shadow ? [] : [i]);
329
+ if (!result || page.length === 0) return result;
330
+ if (library) {
331
+ const name = `${basename2(file, extname(file))}.css`;
332
+ if (existsSync(join(dirname2(file), name))) {
333
+ throw new Error(`[fluixi] ${file} has <style> blocks, and ${name} next to it would be overwritten by their CSS. Rename one of them.`);
334
+ }
335
+ const out = join(relative2(library, dirname2(file)), name);
336
+ emitted.set(out, page.map((i) => css[i]).join("\n"));
337
+ emitted.set(`${out}.js`, loader(name));
338
+ return { ...result, code: `${result.code}
339
+ import ${JSON.stringify(`./${name}`)};` };
340
+ }
341
+ const imports = page.map((i) => `
342
+ import ${JSON.stringify(styleId(file, i))};`).join("");
343
+ return { ...result, code: result.code + imports };
344
+ };
345
+ return {
346
+ /** Looks for @fluixi-css/vite among the plugins; without it component styles stay off. */
347
+ connect(plugins, projectRoot) {
348
+ if (projectRoot) root = projectRoot;
349
+ api = (plugins ?? []).map((p) => p?.api?.fluixiCss).find((a) => Boolean(a));
350
+ api?.useComponentStyles();
351
+ },
352
+ /** Turns on library output, from the directory of a `build.lib` entry. */
353
+ setLibrary(entryDir) {
354
+ library = entryDir;
355
+ },
356
+ /** A library build's style import: left for the package's consumer to bundle. */
357
+ isLibraryImport(id, importer) {
358
+ if (library === void 0 || !importer || !id.startsWith("./") || !id.endsWith(".css")) return false;
359
+ return emitted.has(join(relative2(library, dirname2(fileOf(importer))), id));
360
+ },
361
+ /** The style files a library build writes, by path under the output directory. */
362
+ libraryFiles() {
363
+ return emitted;
364
+ },
365
+ get active() {
366
+ return api !== void 0;
367
+ },
368
+ setServer(dev) {
369
+ server = dev;
370
+ },
371
+ isStyle(id) {
372
+ return STYLE_ID.test(id) || LITERAL_ID.test(id);
373
+ },
374
+ /**
375
+ * A style request as the module id Vite keeps: its owner's absolute path, then the suffix.
376
+ * One id per block however it was asked for (`/src/card.tsx.fx-0.css` from a page, the
377
+ * absolute path from the component), or the reload after an edit misses the copy in use.
378
+ * A css`` value imported from another module names that module relatively, as written.
379
+ */
380
+ async resolveId(id, importer, ctx) {
381
+ const at = id.search(SUFFIX);
382
+ const owner = id.slice(0, at);
383
+ if (!owner.startsWith(".")) return fileOf(owner) + id.slice(at);
384
+ const resolved = importer ? await ctx.resolve?.(owner, importer) : null;
385
+ return resolved ? resolved.id.split("?")[0] + id.slice(at) : null;
386
+ },
387
+ /**
388
+ * The style modules of a changed file, for the update Vite sends. Their ids do not name the
389
+ * file (they end in `.css`), so Vite would not find them itself.
390
+ */
391
+ hotModules(file, graph) {
392
+ const entry = cache.get(file);
393
+ if (!entry) return [];
394
+ const paths = [
395
+ ...entry.css.map((_, i) => styleId(file, i)),
396
+ ...[...entry.literals.keys()].map((name) => styleIds.literal(file, name).replace(/\?inline$/, ""))
397
+ ];
398
+ return paths.flatMap((path) => [...graph.getModulesByFile(path) ?? []]);
399
+ },
400
+ compile: run,
401
+ /**
402
+ * A block's CSS and its map back to the module, compiling the module again when the cache
403
+ * does not match the file.
404
+ */
405
+ async load(id, ctx) {
406
+ const match = STYLE_ID.exec(id);
407
+ const literal = LITERAL_ID.exec(id);
408
+ if (!match && !literal || !api) return null;
409
+ const file = ownerOf(id);
410
+ let source;
411
+ try {
412
+ source = readFileSync2(fileOf(file), "utf8");
413
+ } catch {
414
+ return null;
415
+ }
416
+ if (cache.get(fileOf(file))?.source !== source) await run(source, file, ctx);
417
+ const entry = cache.get(fileOf(file));
418
+ if (literal) {
419
+ const css = entry?.literals.get(literal[1]);
420
+ if (css === void 0) throw new Error(`[fluixi] ${literal[1]} in ${file} is not a css\`\` value, so it cannot be a shadow root's styles.`);
421
+ return { code: css, map: null, moduleType: "css" };
422
+ }
423
+ const index = Number(match[1]);
424
+ return { code: entry?.css[index] ?? "", map: entry?.maps[index] ?? null, moduleType: "css" };
425
+ }
426
+ };
233
427
  }
234
428
 
235
429
  // src/integrations.ts
236
- import { readdirSync as readdirSync2, readFileSync as readFileSync2 } from "node:fs";
237
- import { join as _join } from "node:path";
430
+ import { readdirSync as readdirSync2, readFileSync as readFileSync3 } from "node:fs";
431
+ import { dirname as dirname3, join as _join, resolve as resolvePath2 } from "node:path";
238
432
  async function createBabelPlugin(options = {}) {
239
433
  let pluginModule = null;
240
434
  try {
241
- pluginModule = await import("./babel-RJHJQVEM.mjs");
435
+ pluginModule = await import("./babel-V33QLJBF.mjs");
242
436
  } catch (e) {
243
437
  console.warn("Could not load the babel front-end:", e);
244
438
  }
@@ -299,27 +493,58 @@ var RETIRED_SUBPATHS = {
299
493
  "@fluixi/core/rx": "is gone — import signals and effects from @fluixi/reactive, or the server primitives it resolved to under node from @fluixi/core/server"
300
494
  };
301
495
  function createVitePlugin(options = {}) {
496
+ let transformTemplates;
497
+ let projectRoot = process.cwd();
498
+ const componentStyles = createComponentStyles((code, id, styles) => {
499
+ return transformTemplates(code, id, { ...transformOptions(options, id), sourceRoot: projectRoot, styles });
500
+ });
302
501
  return {
303
502
  name: "vite-fluixi-jsx",
304
503
  enforce: "pre",
305
- config() {
306
- return {
307
- esbuild: {
308
- jsx: "automatic",
309
- jsxImportSource: options.importSource || "@fluixi/jsx"
310
- }
311
- };
504
+ // JSX the compiler leaves alone goes to Vite's own transform: Oxc in Vite 8 (Rolldown),
505
+ // esbuild before, which Vite 8 warns about.
506
+ // In dev, CSS maps are on unless the app says otherwise, so devtools show the line a
507
+ // component's rule was written on. Vite leaves them off by default; a build never has them.
508
+ config(user) {
509
+ const importSource = options.importSource || "@fluixi/jsx";
510
+ const jsx = this && this.meta?.rolldownVersion ? { oxc: { jsx: { runtime: "automatic", importSource } } } : { esbuild: { jsx: "automatic", jsxImportSource: importSource } };
511
+ return user?.css?.devSourcemap === void 0 ? { ...jsx, css: { devSourcemap: true } } : jsx;
312
512
  },
313
513
  // Written once per build, and on dev-server start, rather than per transform: the
314
514
  // set of resolvable names comes from config, so nothing a file does can change it.
315
- configResolved(config) {
515
+ async configResolved(config) {
316
516
  const outcome = writeComponentGlobals(options, config?.root ?? process.cwd());
317
517
  if (outcome.warning) console.warn(outcome.warning);
518
+ if (options.babel) return;
519
+ projectRoot = config?.root ?? projectRoot;
520
+ componentStyles.connect(config?.plugins, config?.root);
521
+ const entry = config?.command === "build" && config.build?.lib ? config.build.lib.entry : void 0;
522
+ const first = typeof entry === "string" ? entry : Array.isArray(entry) ? entry[0] : entry && typeof entry === "object" ? Object.values(entry)[0] : void 0;
523
+ if (typeof first === "string") componentStyles.setLibrary(dirname3(resolvePath2(config.root ?? process.cwd(), first)));
524
+ if (componentStyles.active) ({ transformTemplates } = await import("./transform-P4AETYV4.mjs"));
525
+ },
526
+ generateBundle() {
527
+ for (const [fileName, source] of componentStyles.libraryFiles()) this.emitFile({ type: "asset", fileName, source });
528
+ },
529
+ // An edited component's style modules go out with its update: their ids end in `.css`, so
530
+ // Vite does not connect them to the file.
531
+ handleHotUpdate(ctx) {
532
+ if (!componentStyles.active) return void 0;
533
+ const styles = componentStyles.hotModules(ctx.file, ctx.server.moduleGraph);
534
+ return styles.length ? [...ctx.modules, ...styles] : void 0;
535
+ },
536
+ configureServer(server) {
537
+ componentStyles.setServer(server);
538
+ },
539
+ load(id) {
540
+ return componentStyles.isStyle(id) ? componentStyles.load(id, this) : null;
318
541
  },
319
542
  // A subpath we retired resolves to nothing, and the bundler reports that as
320
543
  // `Missing "./x" specifier`, which names neither the replacement nor the file
321
544
  // that asked. Answer it here, where the rename is known.
322
545
  resolveId(id, importer) {
546
+ if (componentStyles.isStyle(id)) return componentStyles.resolveId(id, importer, this);
547
+ if (componentStyles.isLibraryImport(id, importer)) return { id, external: true };
323
548
  const moved = RETIRED_SUBPATHS[id];
324
549
  if (!moved) return null;
325
550
  throw new Error(
@@ -331,6 +556,11 @@ function createVitePlugin(options = {}) {
331
556
  if (!/\.(jsx|tsx|ts)$/i.test(id)) {
332
557
  return null;
333
558
  }
559
+ if (!options.babel && componentStyles.active) {
560
+ const result = await componentStyles.compile(code, id, this);
561
+ reportDiagnostics(result, id);
562
+ return result;
563
+ }
334
564
  if (!options.babel) return compileModule(code, id, options);
335
565
  const babelPlugin = await createBabelPlugin(options);
336
566
  try {
@@ -409,7 +639,7 @@ function transformOptions(options, id) {
409
639
  }
410
640
  async function rewriteProps(code, id, options) {
411
641
  if (options.propsDestructure === false) return code;
412
- const { transformProps } = await import("./transform-QWWQDCXE.mjs");
642
+ const { transformProps } = await import("./transform-P4AETYV4.mjs");
413
643
  const result = transformProps(code, id);
414
644
  reportDiagnostics({ propsDiagnostics: result.diagnostics }, id);
415
645
  return result.rewritten > 0 ? result.code : code;
@@ -426,13 +656,14 @@ function reportDiagnostics(result, id) {
426
656
  for (const d of r?.unresolvedDiagnostics ?? []) say(d.message);
427
657
  for (const d of r?.loadDiagnostics ?? []) say(d.message);
428
658
  for (const d of r?.intrinsicDiagnostics ?? []) say(d.message);
659
+ for (const d of r?.styleDiagnostics ?? []) say(`${d.line}:${d.column + 1} ${d.message}`);
429
660
  for (const d of r?.propsDiagnostics ?? []) {
430
661
  say(`\`${d.name}\` was left destructured: ${d.message}. It reads once instead of tracking.`);
431
662
  }
432
663
  }
433
664
  async function compileModule(code, id, options) {
434
665
  if (!options.babel) {
435
- const { transformTemplates } = await import("./transform-QWWQDCXE.mjs");
666
+ const { transformTemplates } = await import("./transform-P4AETYV4.mjs");
436
667
  const result2 = transformTemplates(code, id, transformOptions(options, id));
437
668
  reportDiagnostics(result2, id);
438
669
  return result2;
@@ -478,8 +709,8 @@ function createESBuildPlugin(options = {}) {
478
709
  name: "esbuild-fluixi-jsx",
479
710
  setup(build) {
480
711
  build.onLoad({ filter: /\.[jt]sx?$/ }, async (args) => {
481
- const { readFileSync: readFileSync3 } = await import("node:fs");
482
- const source = readFileSync3(args.path, "utf8");
712
+ const { readFileSync: readFileSync4 } = await import("node:fs");
713
+ const source = readFileSync4(args.path, "utf8");
483
714
  try {
484
715
  const result = await compileModule(source, args.path, options);
485
716
  return {
@@ -517,7 +748,7 @@ function findServerFnModules(dir, out = []) {
517
748
  if (e.isDirectory()) findServerFnModules(full, out);
518
749
  else if (/\.[jt]sx?$/.test(e.name)) {
519
750
  try {
520
- if (hasServerDirective(readFileSync2(full, "utf8"))) out.push(full);
751
+ if (hasServerDirective(readFileSync3(full, "utf8"))) out.push(full);
521
752
  } catch {
522
753
  }
523
754
  }
@@ -551,10 +782,10 @@ export { isServerFnRequest, handleServerFn } from '@fluixi/start/server-fn';
551
782
  if (!code.includes("use server")) return null;
552
783
  const args = { ssr: !!opts?.ssr, filename: id, root };
553
784
  if (options.babel) {
554
- const { transformServerFunctions } = await import("./server-functions-CTDXX67X.mjs");
785
+ const { transformServerFunctions } = await import("./server-functions-LVS66Q4R.mjs");
555
786
  return transformServerFunctions(code, args);
556
787
  }
557
- const { transformServerFns } = await import("./server-fns-ZFRDIQ2X.mjs");
788
+ const { transformServerFns } = await import("./server-fns-N3SDJXA7.mjs");
558
789
  return transformServerFns(code, args);
559
790
  }
560
791
  };