@animus-ui/vite-plugin 0.1.0-next.10 → 0.1.0-next.16

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.
package/dist/index.d.ts CHANGED
@@ -1,48 +1,12 @@
1
1
  import type { Plugin } from 'vite';
2
2
  export interface AnimusExtractOptions {
3
- /**
4
- * Theme data for the extraction pipeline.
5
- *
6
- * Two forms are accepted:
7
- * - `string` — pre-serialized flat JSON (legacy; no CSS variable emission)
8
- * - `{ scales: string; variables: string }` — pre-evaluated scales JSON
9
- * plus fully-formed CSS variable declarations to prepend to the virtual
10
- * stylesheet. The caller is responsible for evaluating the theme module
11
- * (e.g. via `evaluateTheme` or a Bun subprocess) before passing it here.
12
- *
13
- * When omitted, the plugin auto-detects `src/theme.ts`, `src/theme.js`,
14
- * `theme.ts`, or `theme.js` relative to the project root.
15
- */
16
- theme?: string | {
17
- scales: string;
18
- variables: string;
19
- };
20
- /**
21
- * Explicit path to the theme module (relative to project root or absolute).
22
- * Takes precedence over auto-detection, but lower priority than `theme`.
23
- */
24
- themePath?: string;
25
3
  /**
26
4
  * Path to a module exporting a SystemInstance from `@animus-ui/system`.
27
5
  * The module is loaded via a single bun subprocess at build start.
28
- * Replaces configPath + themePath when using the system package.
29
- */
30
- system?: string;
31
- /**
32
- * Path to a module exporting `getExtractConfig()`. The module is loaded via
33
- * bun subprocess at build start. Use this for custom Animus instances created
34
- * with `createAnimus().addGroup(...).build()`.
35
- *
36
- * When omitted, automatically imported from `@animus-ui/core`.
37
- */
38
- configPath?: string;
39
- /**
40
- * Pre-serialized prop config JSON. When omitted, automatically imported from
41
- * `@animus-ui/core` via `getExtractConfig()`.
6
+ * It provides prop config, group registry, theme tokens, transforms,
7
+ * and global styles — everything the extraction pipeline needs.
42
8
  */
43
- config?: string;
44
- /** Pre-serialized group registry JSON. Maps group names to prop name arrays. */
45
- groupRegistry?: string;
9
+ system: string;
46
10
  /** Glob patterns to include. Defaults to .ts/.tsx/.js/.jsx files. */
47
11
  include?: string[];
48
12
  /** Glob patterns to exclude. */
@@ -53,8 +17,38 @@ export interface AnimusExtractOptions {
53
17
  strict?: boolean;
54
18
  /** Enable verbose logging. Also activatable via ANIMUS_DEBUG=1 env var. */
55
19
  verbose?: boolean;
20
+ /**
21
+ * Browser targets for CSS autoprefixing and syntax lowering.
22
+ * Accepts a browserslist query string or array of queries.
23
+ * Falls back to project's browserslist config, then to `defaults`.
24
+ */
25
+ targets?: string | string[];
26
+ /**
27
+ * Control CSS minification.
28
+ * - `true`: always minify (dev + prod)
29
+ * - `false`: never minify (autoprefixing still applies)
30
+ * - `undefined` (default): minify in prod only
31
+ */
32
+ minify?: boolean;
33
+ /**
34
+ * Namespace prefix for CSS variables and class names.
35
+ * When set, all generated CSS variables become `--{prefix}-{name}`
36
+ * and class names become `{prefix}-{Component}-{hash}`.
37
+ * Defaults to no prefix.
38
+ */
39
+ prefix?: string;
40
+ /**
41
+ * Full `@layer` declaration order. Must include all 7 Animus layers
42
+ * (global, base, variants, states, system, custom) as a subsequence
43
+ * in their required order. Consumer layers may be interleaved around them.
44
+ *
45
+ * Example: `['reset', 'global', 'base', 'variants', 'states', 'system', 'custom', 'overrides']`
46
+ *
47
+ * When omitted, defaults to the 7 Animus layers.
48
+ */
49
+ layers?: string[];
56
50
  }
57
- export declare function animusExtract(options?: AnimusExtractOptions): Plugin;
51
+ export declare function animusExtract(options: AnimusExtractOptions): Plugin;
58
52
  export { evaluateTheme, evaluateThemeObject } from './theme-evaluator';
59
53
  export default animusExtract;
60
54
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAM3C,MAAM,WAAW,oBAAoB;IACnC;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,qGAAqG;IACrG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA6RD,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,CA+gCxE;AAED,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACvE,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAU,MAAM,EAAE,MAAM,MAAM,CAAC;AAM3C,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,8FAA8F;IAC9F,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,qGAAqG;IACrG,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAwUD,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CA45BnE;AAED,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACvE,eAAe,aAAa,CAAC"}
package/dist/index.mjs CHANGED
@@ -5,6 +5,8 @@ import { existsSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileS
5
5
  import { tmpdir } from "os";
6
6
  import { dirname, extname, join, relative, resolve } from "path";
7
7
  import { fileURLToPath } from "url";
8
+ import browserslist from "browserslist";
9
+ import { browserslistToTargets, transform } from "lightningcss";
8
10
  //#region \0rolldown/runtime.js
9
11
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
10
12
  //#endregion
@@ -12,10 +14,24 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
12
14
  /**
13
15
  * Evaluate a theme object that has already been loaded/imported.
14
16
  *
15
- * This is the pure logic: takes a theme object, flattens scales, builds variable CSS.
16
- * Use this when you have already loaded the module yourself.
17
+ * If the theme has a `.manifest` property (from ThemeBuilder.build()),
18
+ * reads structured data directly no re-flattening or var() pattern-matching.
19
+ * Falls back to legacy path for themes without manifests.
17
20
  */
18
21
  function evaluateThemeObject(theme) {
22
+ if (theme.manifest && typeof theme.manifest === "object") {
23
+ const manifest = theme.manifest;
24
+ return {
25
+ scalesJson: JSON.stringify(manifest.tokenMap),
26
+ variableMapJson: JSON.stringify(manifest.variableMap),
27
+ variableCss: manifest.variableCss
28
+ };
29
+ }
30
+ console.warn("[animus] Theme has no .manifest property — using legacy evaluation. Update to @animus-ui/system >=0.2.0 for structured manifest support.");
31
+ return evaluateThemeObjectLegacy(theme);
32
+ }
33
+ /** Legacy theme evaluation — flattens theme and pattern-matches var() strings. */
34
+ function evaluateThemeObjectLegacy(theme) {
19
35
  const flat = {};
20
36
  for (const [scaleName, scaleValue] of Object.entries(theme)) {
21
37
  if (scaleName.startsWith("_")) continue;
@@ -152,24 +168,6 @@ function discoverFiles(dir, rootDir, excludePatterns) {
152
168
  return results;
153
169
  }
154
170
  /**
155
- * Apply transform placeholders emitted by the Rust pipeline.
156
- *
157
- * Rust emits `__TRANSFORM__name__rawValue__` for props with transforms.
158
- * This function resolves each placeholder using the actual JS transform
159
- * functions from the config.
160
- */
161
- function applyTransformPlaceholders(css, transformRegistry) {
162
- return css.replace(/__TRANSFORM__(\w+)__(.+?)__/g, (_match, name, rawValue) => {
163
- const fn = transformRegistry.get(name);
164
- if (!fn) {
165
- console.warn(`[animus-extract] Unknown transform: "${name}" — using raw value`);
166
- return rawValue;
167
- }
168
- const result = fn(rawValue !== "" && !isNaN(Number(rawValue)) ? Number(rawValue) : rawValue);
169
- return typeof result === "object" ? JSON.stringify(result) : String(result);
170
- });
171
- }
172
- /**
173
171
  * CSS properties that accept unitless numeric values.
174
172
  * Matches @emotion/unitless and React DOM's style handling.
175
173
  * Bare numerics on properties NOT in this set receive `px`.
@@ -256,6 +254,38 @@ function applyUnitFallback(css) {
256
254
  return fixed !== value ? `${prop}:${fixed};` : match;
257
255
  });
258
256
  }
257
+ /**
258
+ * Resolve browser targets for Lightning CSS.
259
+ * Priority: explicit config → project browserslist → 'defaults' fallback.
260
+ */
261
+ function resolveLightningTargets(explicitTargets, rootDir) {
262
+ let queries;
263
+ if (explicitTargets) queries = Array.isArray(explicitTargets) ? explicitTargets : [explicitTargets];
264
+ else {
265
+ const detected = browserslist(void 0, { path: rootDir });
266
+ queries = detected.length > 0 ? detected : browserslist("defaults");
267
+ }
268
+ return browserslistToTargets(Array.isArray(queries) && typeof queries[0] === "string" && queries[0].includes(" ") ? browserslist(queries) : queries);
269
+ }
270
+ /**
271
+ * Post-process CSS with Lightning CSS: autoprefixing + optional minification.
272
+ * On failure, returns the original CSS and logs a warning.
273
+ */
274
+ function postProcessCss(css, opts) {
275
+ if (!css) return css;
276
+ try {
277
+ return transform({
278
+ filename: "animus-extracted.css",
279
+ code: Buffer.from(css),
280
+ minify: opts.minify,
281
+ targets: opts.targets
282
+ }).code.toString();
283
+ } catch (e) {
284
+ const msg = e instanceof Error ? e.message : String(e);
285
+ (opts.warnFn ?? console.warn)(`[animus] Lightning CSS post-processing failed: ${msg}`);
286
+ return css;
287
+ }
288
+ }
259
289
  /** Compute MD5 content hash for a string. */
260
290
  function contentHash(source) {
261
291
  return createHash("md5").update(source).digest("hex");
@@ -276,39 +306,61 @@ function buildFileEntriesFromCache(cache, changedPath) {
276
306
  return entries;
277
307
  }
278
308
  /**
279
- * Resolve transform placeholders in CSS via bun subprocess.
280
- * Falls back to in-process resolution if the subprocess fails.
309
+ * Apply namespace prefix to a variable map and CSS variable declarations.
310
+ *
311
+ * Variable map: `{ "colors.ember": "--color-ember" }` → `{ "colors.ember": "--prefix-color-ember" }`
312
+ * Variable CSS: `--color-ember: #FF2800` → `--prefix-color-ember: #FF2800`
313
+ * `var(--color-ember)` → `var(--prefix-color-ember)`
281
314
  */
282
- function resolveTransformPlaceholders(css, rootDir, configPath, transformRegistry) {
283
- if (!css.includes("__TRANSFORM__")) return css;
284
- try {
285
- const ts = Date.now();
286
- const tmpCss = join(tmpdir(), `animus-transforms-${ts}.css`);
287
- const tmpOut = join(tmpdir(), `animus-transforms-${ts}.out.css`);
288
- writeFileSync(tmpCss, css);
289
- const candidates = [join(__pluginDir, "resolve-transforms.ts"), join(__pluginDir, "..", "src", "resolve-transforms.ts")];
290
- try {
291
- const pkgDir = dirname(__require.resolve("@animus-ui/vite-plugin/package.json", { paths: [rootDir] }));
292
- candidates.push(join(pkgDir, "src", "resolve-transforms.ts"));
293
- } catch {}
294
- const scriptPath = candidates.find((p) => existsSync(p));
295
- if (!scriptPath) throw new Error(`resolve-transforms.ts not found in: ${candidates.join(", ")}`);
296
- execSync(`bun run "${scriptPath}" "${tmpCss}" "${tmpOut}" ${configPath ? `"${resolve(rootDir, configPath)}"` : ""}`, {
297
- cwd: rootDir,
298
- encoding: "utf-8"
299
- });
300
- const resolved = readFileSync(tmpOut, "utf-8");
301
- try {
302
- unlinkSync(tmpCss);
303
- unlinkSync(tmpOut);
304
- } catch {}
305
- return resolved;
306
- } catch (e) {
307
- console.error("[animus-extract] Transform resolution failed:", e?.message || e);
308
- return applyTransformPlaceholders(css, transformRegistry);
315
+ function applyPrefix(prefix, variableMapJson, variableCss) {
316
+ if (!prefix) return {
317
+ variableMapJson,
318
+ variableCss
319
+ };
320
+ const map = JSON.parse(variableMapJson);
321
+ const prefixed = {};
322
+ for (const [key, varName] of Object.entries(map)) prefixed[key] = varName.startsWith("--") ? `--${prefix}-${varName.slice(2)}` : varName;
323
+ let css = variableCss;
324
+ css = css.replace(/--([a-zA-Z][\w-]*)\s*:/g, `--${prefix}-$1:`);
325
+ css = css.replace(/var\(--([a-zA-Z][\w-]*)\)/g, `var(--${prefix}-$1)`);
326
+ return {
327
+ variableMapJson: JSON.stringify(prefixed),
328
+ variableCss: css
329
+ };
330
+ }
331
+ /**
332
+ * The 7 Animus cascade layers in required order.
333
+ * Consumer-provided `layers` must contain these as a subsequence.
334
+ */
335
+ const ANIMUS_LAYERS = [
336
+ "global",
337
+ "base",
338
+ "variants",
339
+ "compounds",
340
+ "states",
341
+ "system",
342
+ "custom"
343
+ ];
344
+ /**
345
+ * Validate that a consumer `layers` array contains all 7 Animus layers
346
+ * in the correct relative order. Consumer layers may be interleaved.
347
+ *
348
+ * @throws Error with descriptive message on violation
349
+ */
350
+ function validateLayerOrder(layers) {
351
+ let cursor = 0;
352
+ for (const layer of layers) if (cursor < ANIMUS_LAYERS.length && layer === ANIMUS_LAYERS[cursor]) cursor++;
353
+ if (cursor < ANIMUS_LAYERS.length) {
354
+ const missing = ANIMUS_LAYERS.slice(cursor);
355
+ const found = ANIMUS_LAYERS.slice(0, cursor);
356
+ if (!ANIMUS_LAYERS.every((l) => layers.includes(l))) {
357
+ const absent = ANIMUS_LAYERS.filter((l) => !layers.includes(l));
358
+ throw new Error(`[animus] Invalid layers config: missing required layers: ${absent.join(", ")}. All 7 Animus layers must be present: ${ANIMUS_LAYERS.join(", ")}`);
359
+ }
360
+ throw new Error(`[animus] Invalid layers config: Animus layers must appear in order (${ANIMUS_LAYERS.join(" < ")}). Found ${found.join(", ")} in order, but ${missing.join(", ")} appeared out of sequence. Received: [${layers.join(", ")}]`);
309
361
  }
310
362
  }
311
- function animusExtract(options = {}) {
363
+ function animusExtract(options) {
312
364
  let themeJson = "{}";
313
365
  let variableMapJson = "{}";
314
366
  let configJson = "{}";
@@ -323,9 +375,9 @@ function animusExtract(options = {}) {
323
375
  function warn(msg) {
324
376
  (logger ?? console).warn(`[animus] ${msg}`);
325
377
  }
378
+ let lcssTargets = {};
326
379
  let variableCss = "";
327
380
  let globalCss = "";
328
- let transformRegistry = /* @__PURE__ */ new Map();
329
381
  let storedManifest = null;
330
382
  let storedManifestJson = "";
331
383
  let resolvedComponentCss = "";
@@ -333,93 +385,17 @@ function animusExtract(options = {}) {
333
385
  let storedSystemPropMapJson = "{}";
334
386
  let storedDynamicPropsJson = "{}";
335
387
  let storedTransformsSource = "";
388
+ let layerDeclaration = "";
336
389
  const fileCache = /* @__PURE__ */ new Map();
337
390
  let packageMap = {};
338
391
  let bridgeInjected = false;
339
- let resolvedConfigPath = null;
340
- let resolvedThemePath = null;
341
392
  let resolvedSystemPath = null;
342
- /** Resolve config via bun subprocess. Updates configJson + groupRegistryJson. */
343
- function loadConfig() {
344
- if (options.config) {
345
- configJson = options.config;
346
- groupRegistryJson = options.groupRegistry ?? groupRegistryJson;
347
- return;
348
- }
349
- const configSource = options.configPath ? resolve(rootDir, options.configPath) : "@animus-ui/core";
350
- const requireExpr = options.configPath ? `require('${configSource.replace(/\\/g, "/")}')` : `require('@animus-ui/core')`;
351
- if (options.configPath) resolvedConfigPath = resolve(rootDir, options.configPath);
352
- try {
353
- const result = execSync(`bun -e "const m = ${requireExpr}; const r = m.getExtractConfig(); process.stdout.write(JSON.stringify(r))"`, {
354
- cwd: rootDir,
355
- encoding: "utf-8"
356
- });
357
- const { propConfig, groupRegistry } = JSON.parse(result);
358
- configJson = propConfig;
359
- groupRegistryJson = groupRegistry;
360
- } catch (e) {
361
- if (options.strict) throw new Error(`[animus-extract] Failed to auto-import config from ${configSource}: ${e}`);
362
- console.warn(`[animus-extract] Failed to auto-import config from ${configSource}:`, e);
363
- }
364
- }
365
- /** Resolve theme via bun subprocess. Updates themeJson + variableCss. */
366
- function loadTheme() {
367
- if (options.theme) {
368
- if (typeof options.theme === "string") {
369
- themeJson = options.theme;
370
- variableCss = "";
371
- } else {
372
- themeJson = options.theme.scales;
373
- variableCss = options.theme.variables;
374
- }
375
- return;
376
- }
377
- resolvedThemePath = null;
378
- if (options.themePath) {
379
- const p = resolve(rootDir, options.themePath);
380
- if (existsSync(p)) resolvedThemePath = p;
381
- else if (options.strict) throw new Error(`[animus-extract] Theme file not found: ${p}`);
382
- else console.warn(`[animus-extract] Theme file not found: ${p}`);
383
- } else {
384
- const candidates = [
385
- join(rootDir, "src", "theme.ts"),
386
- join(rootDir, "src", "theme.js"),
387
- join(rootDir, "theme.ts"),
388
- join(rootDir, "theme.js")
389
- ];
390
- for (const candidate of candidates) if (existsSync(candidate)) {
391
- resolvedThemePath = candidate;
392
- break;
393
- }
394
- }
395
- if (resolvedThemePath) try {
396
- const themeJson_ = execSync(`bun -e "${[
397
- `const m = require(${JSON.stringify(resolvedThemePath)});`,
398
- `const theme = m.theme || m.default;`,
399
- `process.stdout.write(JSON.stringify(theme || {}));`
400
- ].join(" ").replace(/"/g, "\\\"")}"`, {
401
- cwd: rootDir,
402
- encoding: "utf-8"
403
- });
404
- const theme = JSON.parse(themeJson_);
405
- if (theme && Object.keys(theme).length > 0) {
406
- const result = evaluateThemeObject(theme);
407
- themeJson = result.scalesJson;
408
- variableMapJson = result.variableMapJson;
409
- variableCss = result.variableCss;
410
- }
411
- } catch (e) {
412
- if (options.strict) throw new Error(`[animus-extract] Failed to load theme from ${resolvedThemePath}: ${e}`);
413
- console.warn(`[animus-extract] Failed to load theme from ${resolvedThemePath}:`, e);
414
- }
415
- }
416
393
  /**
417
394
  * Load a SystemInstance via single bun subprocess.
418
- * Replaces loadConfig() + loadTheme() when `system` option is provided.
419
- * The subprocess imports the module and calls .serialize().
395
+ * The subprocess imports the module and calls .serialize() to provide
396
+ * prop config, group registry, tokens, transforms, and global styles.
420
397
  */
421
398
  function loadSystem() {
422
- if (!options.system) return;
423
399
  resolvedSystemPath = resolve(rootDir, options.system);
424
400
  try {
425
401
  const ts = Date.now();
@@ -443,6 +419,11 @@ function animusExtract(options = {}) {
443
419
  themeJson = result.scalesJson;
444
420
  variableMapJson = result.variableMapJson;
445
421
  variableCss = result.variableCss;
422
+ if (options.prefix) {
423
+ const prefixed = applyPrefix(options.prefix, variableMapJson, variableCss);
424
+ variableMapJson = prefixed.variableMapJson;
425
+ variableCss = prefixed.variableCss;
426
+ }
446
427
  } else if (logger) logger.warn("[animus] No tokens export found in system module — CSS variables will not be generated. Export your theme as `tokens` or `theme`.");
447
428
  if (parsed.globalStyles) {
448
429
  const hasReset = parsed.globalStyles.reset && Object.keys(parsed.globalStyles.reset).length > 0;
@@ -492,7 +473,7 @@ function animusExtract(options = {}) {
492
473
  function runAnalysis(fileEntries) {
493
474
  try {
494
475
  const { analyzeProject } = __require("@animus-ui/extract");
495
- const manifestJson = analyzeProject(JSON.stringify(fileEntries), themeJson, variableMapJson, configJson, groupRegistryJson, JSON.stringify(packageMap), !isProd);
476
+ const manifestJson = analyzeProject(JSON.stringify(fileEntries), themeJson, variableMapJson, configJson, groupRegistryJson, JSON.stringify(packageMap), !isProd, options.prefix || null);
496
477
  storedManifest = JSON.parse(manifestJson);
497
478
  storedManifestJson = manifestJson;
498
479
  storedSystemPropMapJson = JSON.stringify(storedManifest?.system_prop_map ?? {});
@@ -508,24 +489,13 @@ function animusExtract(options = {}) {
508
489
  for (const match of matches) usedTransformNames.add(match[1]);
509
490
  }
510
491
  }
511
- if (usedTransformNames.size > 0 && transformRegistry.size > 0) {
512
- const transformParts = [];
513
- for (const name of usedTransformNames) {
514
- const fn = transformRegistry.get(name);
515
- if (fn) try {
516
- transformParts.push(`${JSON.stringify(name)}: ${fn.toString()}`);
517
- } catch {
518
- console.warn(`[animus-extract] Could not serialize transform "${name}" — dynamic props using it will fall back to raw values`);
519
- }
520
- }
521
- storedTransformsSource = transformParts.length > 0 ? `{ ${transformParts.join(", ")} }` : "{}";
522
- } else storedTransformsSource = "{}";
492
+ storedTransformsSource = "{}";
523
493
  }
524
494
  bridgeInjected = false;
525
495
  storedSheets = storedManifest?.sheets ?? null;
526
496
  const rawCss = storedManifest?.css || "";
527
497
  const systemResolveScript = globalThis.__animus_system_resolve_script;
528
- if (systemResolveScript && rawCss.includes("__TRANSFORM__") && isProd) try {
498
+ if (systemResolveScript && rawCss.includes("__TRANSFORM__")) try {
529
499
  const tsTmp = Date.now();
530
500
  const tmpIn = join(tmpdir(), `animus-css-${tsTmp}.css`);
531
501
  const tmpOut = join(tmpdir(), `animus-css-${tsTmp}.out.css`);
@@ -540,10 +510,10 @@ function animusExtract(options = {}) {
540
510
  unlinkSync(tmpOut);
541
511
  } catch {}
542
512
  } catch (e) {
543
- console.warn("[animus-extract] System transform resolution failed:", e?.message);
544
- resolvedComponentCss = resolveTransformPlaceholders(rawCss, rootDir, options.configPath, transformRegistry);
513
+ console.warn("[animus-extract] Transform resolution failed:", e?.message);
514
+ resolvedComponentCss = rawCss;
545
515
  }
546
- else resolvedComponentCss = resolveTransformPlaceholders(rawCss, rootDir, options.configPath, transformRegistry);
516
+ else resolvedComponentCss = rawCss;
547
517
  resolvedComponentCss = applyUnitFallback(resolvedComponentCss);
548
518
  } catch (e) {
549
519
  if (options.strict) throw new Error(`[animus-extract] analyzeProject failed: ${e}`);
@@ -557,14 +527,17 @@ function animusExtract(options = {}) {
557
527
  isProd = config.command === "build";
558
528
  rootDir = config.root;
559
529
  logger = config.logger;
530
+ lcssTargets = resolveLightningTargets(options.targets, rootDir);
531
+ log(`Lightning CSS targets resolved (${Object.keys(lcssTargets).length} browsers)`);
532
+ if (options.layers) {
533
+ validateLayerOrder(options.layers);
534
+ log(`Custom layers: [${options.layers.join(", ")}]`);
535
+ }
536
+ if (options.prefix) log(`Namespace prefix: "${options.prefix}"`);
560
537
  },
561
538
  async buildStart() {
562
539
  let t0 = performance.now();
563
- if (options.system) loadSystem();
564
- else {
565
- loadConfig();
566
- loadTheme();
567
- }
540
+ loadSystem();
568
541
  if (verbose) {
569
542
  const propCount = Object.keys(JSON.parse(configJson)).length;
570
543
  const groupCount = Object.keys(JSON.parse(groupRegistryJson)).length;
@@ -659,8 +632,11 @@ function animusExtract(options = {}) {
659
632
  for (const d of diagnostics) if (d.kind === "bail") warn(`⚠ ${d.component} not extracted: ${d.message}`);
660
633
  else if (d.kind === "skip") warn(`⚠ ${d.component}: skipped ${d.message}`);
661
634
  log(`CSS: ${resolvedComponentCss.length} bytes (${Object.keys(storedManifest.components || {}).length} components)`);
635
+ if (options.layers) layerDeclaration = `@layer ${options.layers.join(", ")};\n`;
636
+ else if (storedSheets) layerDeclaration = storedSheets.declaration;
637
+ else layerDeclaration = `@layer ${ANIMUS_LAYERS.join(", ")};\n`;
662
638
  if (!isProd && storedSheets) {
663
- const staticSize = (storedSheets.declaration + variableCss + globalCss).length;
639
+ const staticSize = (layerDeclaration + variableCss + globalCss).length;
664
640
  const componentSize = resolvedComponentCss.length;
665
641
  log(`Delivery: split mode — static ${staticSize} bytes, components ${componentSize} bytes (adopted stylesheet)`);
666
642
  } else log("Delivery: single file mode (production)");
@@ -674,19 +650,31 @@ function animusExtract(options = {}) {
674
650
  return null;
675
651
  },
676
652
  load(id) {
653
+ const lcssOpts = {
654
+ minify: options.minify ?? isProd,
655
+ targets: lcssTargets,
656
+ warnFn: warn
657
+ };
677
658
  if (id === RESOLVED_CSS_ID) {
678
- if (!isProd && storedSheets) return [
679
- storedSheets.declaration,
659
+ if (!isProd && storedSheets) return postProcessCss([
660
+ layerDeclaration,
680
661
  variableCss,
681
662
  globalCss
682
- ].filter(Boolean).join("\n");
683
- return [
663
+ ].filter(Boolean).join("\n"), {
664
+ ...lcssOpts,
665
+ minify: false
666
+ });
667
+ return postProcessCss([
668
+ layerDeclaration,
684
669
  variableCss,
685
670
  globalCss,
686
671
  resolvedComponentCss
687
- ].filter(Boolean).join("\n");
672
+ ].filter(Boolean).join("\n"), lcssOpts);
688
673
  }
689
- if (id === RESOLVED_COMPONENTS_ID) return `export default \`${(resolvedComponentCss || "").replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`;`;
674
+ if (id === RESOLVED_COMPONENTS_ID) return `export default \`${postProcessCss(resolvedComponentCss || "", {
675
+ ...lcssOpts,
676
+ minify: false
677
+ }).replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$")}\`;`;
690
678
  if (id === RESOLVED_BRIDGE_ID) return `
691
679
  import css from '${VIRTUAL_COMPONENTS_ID}';
692
680
 
@@ -774,17 +762,10 @@ if (import.meta.hot) {
774
762
  if ((options.exclude ?? DEFAULT_EXCLUDE).some((pattern) => file.includes(pattern) || relative(rootDir, file).includes(pattern))) return;
775
763
  const absFile = resolve(file);
776
764
  const relPath = relative(rootDir, absFile);
777
- const isConfigChange = resolvedConfigPath && absFile === resolve(resolvedConfigPath);
778
- const isThemeChange = resolvedThemePath && absFile === resolve(resolvedThemePath);
779
- const isSystemChange = resolvedSystemPath && absFile === resolve(resolvedSystemPath);
780
- if (isConfigChange || isThemeChange || isSystemChange) {
765
+ if (resolvedSystemPath && absFile === resolve(resolvedSystemPath)) {
781
766
  const resetStart = performance.now();
782
767
  log(`HMR geological reset: ${relPath}`);
783
- if (isSystemChange) loadSystem();
784
- else {
785
- if (isConfigChange) loadConfig();
786
- if (isThemeChange) loadTheme();
787
- }
768
+ loadSystem();
788
769
  try {
789
770
  const { clearAnalysisCache } = __require("@animus-ui/extract");
790
771
  clearAnalysisCache();
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Evaluate a theme object that has already been loaded/imported.
3
3
  *
4
- * This is the pure logic: takes a theme object, flattens scales, builds variable CSS.
5
- * Use this when you have already loaded the module yourself.
4
+ * If the theme has a `.manifest` property (from ThemeBuilder.build()),
5
+ * reads structured data directly no re-flattening or var() pattern-matching.
6
+ * Falls back to legacy path for themes without manifests.
6
7
  */
7
8
  export declare function evaluateThemeObject(theme: Record<string, any>): {
8
9
  scalesJson: string;
@@ -1 +1 @@
1
- {"version":3,"file":"theme-evaluator.d.ts","sourceRoot":"","sources":["../src/theme-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAuCA;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAC5D,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAWD;AAuKD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EACjD,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC,GAC1C,MAAM,CAiCR"}
1
+ {"version":3,"file":"theme-evaluator.d.ts","sourceRoot":"","sources":["../src/theme-evaluator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAiBA;AA0CD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EAC5D,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IACT,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC,CAWD;AAuKD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,EACjD,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG,CAAC,GAC1C,MAAM,CAiCR"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@animus-ui/vite-plugin",
3
- "version": "0.1.0-next.10",
3
+ "version": "0.1.0-next.16",
4
4
  "description": "Animus static CSS extraction Vite plugin",
5
5
  "author": "codecaaron <airrobb@gmail.com>",
6
6
  "license": "MIT",
@@ -25,7 +25,8 @@
25
25
  "vite": ">=5.0.0"
26
26
  },
27
27
  "dependencies": {
28
- "@animus-ui/core": "0.1.0-next.10",
29
- "@animus-ui/extract": "0.1.0-next.10"
28
+ "@animus-ui/extract": "0.1.0-next.16",
29
+ "browserslist": "^4.24.0",
30
+ "lightningcss": "^1.29.0"
30
31
  }
31
32
  }
@@ -1,25 +0,0 @@
1
- /**
2
- * Serialize the prop config from @animus-ui/core for the Rust extraction pipeline.
3
- *
4
- * Maps JS transform functions to string identifiers that the Rust crate
5
- * can dispatch to its native implementations.
6
- */
7
- interface PropConfig {
8
- property: string;
9
- properties?: string[];
10
- scale?: string | Record<string, any> | any[];
11
- transform?: Function;
12
- }
13
- /**
14
- * Serialize all prop groups from the animus config into a JSON map.
15
- * Prop config entries with inline scales (object/array) are skipped
16
- * since the Rust crate only handles named theme scales.
17
- */
18
- export declare function serializeConfig(propRegistry: Record<string, PropConfig>): string;
19
- /**
20
- * Serialize the group registry from the Animus config.
21
- * Maps each group name to its array of constituent prop names.
22
- */
23
- export declare function serializeGroupRegistry(groupRegistry: Record<string, string[]>): string;
24
- export {};
25
- //# sourceMappingURL=config-serializer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config-serializer.d.ts","sourceRoot":"","sources":["../src/config-serializer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC;IAC7C,SAAS,CAAC,EAAE,QAAQ,CAAC;CACtB;AASD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GACvC,MAAM,CA8BR;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACtC,MAAM,CAER"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Standalone script executed via `bun run` to apply transform placeholders.
3
- *
4
- * Usage: bun run resolve-transforms.ts <input-file> <output-file> [config-path]
5
- *
6
- * Reads CSS from input file containing __TRANSFORM__name__rawValue__ placeholders,
7
- * loads transform functions from @animus-ui/core (and optionally a custom config),
8
- * applies them, and writes the resolved CSS to the output file.
9
- *
10
- * When config-path is provided, transforms from that module are loaded IN ADDITION
11
- * to core transforms. Custom transforms take precedence on name collisions.
12
- */
13
- export {};
14
- //# sourceMappingURL=resolve-transforms.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolve-transforms.d.ts","sourceRoot":"","sources":["../src/resolve-transforms.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}