tailwind-styled-v4 5.0.10 → 5.0.11

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/README.md +245 -373
  2. package/dist/analyzer.js +75 -22
  3. package/dist/analyzer.js.map +1 -1
  4. package/dist/analyzer.mjs +74 -21
  5. package/dist/analyzer.mjs.map +1 -1
  6. package/dist/animate.js +4 -2
  7. package/dist/animate.js.map +1 -1
  8. package/dist/animate.mjs +4 -2
  9. package/dist/animate.mjs.map +1 -1
  10. package/dist/atomic.js +20 -5
  11. package/dist/atomic.js.map +1 -1
  12. package/dist/atomic.mjs +20 -5
  13. package/dist/atomic.mjs.map +1 -1
  14. package/dist/cli.js +174 -67
  15. package/dist/cli.js.map +1 -1
  16. package/dist/cli.mjs +171 -64
  17. package/dist/cli.mjs.map +1 -1
  18. package/dist/compiler.d.mts +7 -1
  19. package/dist/compiler.d.ts +7 -1
  20. package/dist/compiler.js +53 -27
  21. package/dist/compiler.js.map +1 -1
  22. package/dist/compiler.mjs +53 -27
  23. package/dist/compiler.mjs.map +1 -1
  24. package/dist/devtools.js.map +1 -1
  25. package/dist/devtools.mjs.map +1 -1
  26. package/dist/engine.js +159 -61
  27. package/dist/engine.js.map +1 -1
  28. package/dist/engine.mjs +159 -61
  29. package/dist/engine.mjs.map +1 -1
  30. package/dist/index.browser.mjs +1512 -0
  31. package/dist/index.browser.mjs.map +1 -0
  32. package/dist/index.d.mts +94 -12
  33. package/dist/index.d.ts +94 -12
  34. package/dist/index.js +436 -106
  35. package/dist/index.js.map +1 -1
  36. package/dist/index.mjs +436 -106
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/next.js +1946 -47
  39. package/dist/next.js.map +1 -1
  40. package/dist/next.mjs +1929 -44
  41. package/dist/next.mjs.map +1 -1
  42. package/dist/plugin-api.js.map +1 -1
  43. package/dist/plugin-api.mjs.map +1 -1
  44. package/dist/plugin-registry.js +23 -10
  45. package/dist/plugin-registry.js.map +1 -1
  46. package/dist/plugin-registry.mjs +23 -11
  47. package/dist/plugin-registry.mjs.map +1 -1
  48. package/dist/plugin.js.map +1 -1
  49. package/dist/plugin.mjs.map +1 -1
  50. package/dist/rspack.js.map +1 -1
  51. package/dist/rspack.mjs.map +1 -1
  52. package/dist/scanner.js +72 -19
  53. package/dist/scanner.js.map +1 -1
  54. package/dist/scanner.mjs +71 -18
  55. package/dist/scanner.mjs.map +1 -1
  56. package/dist/shared.js +32 -15
  57. package/dist/shared.js.map +1 -1
  58. package/dist/shared.mjs +32 -15
  59. package/dist/shared.mjs.map +1 -1
  60. package/dist/svelte.js +38 -12
  61. package/dist/svelte.js.map +1 -1
  62. package/dist/svelte.mjs +38 -12
  63. package/dist/svelte.mjs.map +1 -1
  64. package/dist/syntax.js +17 -5
  65. package/dist/syntax.js.map +1 -1
  66. package/dist/syntax.mjs +17 -5
  67. package/dist/syntax.mjs.map +1 -1
  68. package/dist/theme.js +4 -2
  69. package/dist/theme.js.map +1 -1
  70. package/dist/theme.mjs +4 -2
  71. package/dist/theme.mjs.map +1 -1
  72. package/dist/turbopackLoader.js +87 -33
  73. package/dist/turbopackLoader.js.map +1 -1
  74. package/dist/turbopackLoader.mjs +87 -33
  75. package/dist/turbopackLoader.mjs.map +1 -1
  76. package/dist/tw.js +174 -67
  77. package/dist/tw.js.map +1 -1
  78. package/dist/tw.mjs +171 -64
  79. package/dist/tw.mjs.map +1 -1
  80. package/dist/vite.js +145 -63
  81. package/dist/vite.js.map +1 -1
  82. package/dist/vite.mjs +145 -63
  83. package/dist/vite.mjs.map +1 -1
  84. package/dist/vue.js +38 -12
  85. package/dist/vue.js.map +1 -1
  86. package/dist/vue.mjs +38 -12
  87. package/dist/vue.mjs.map +1 -1
  88. package/dist/webpackLoader.js +20 -5
  89. package/dist/webpackLoader.js.map +1 -1
  90. package/dist/webpackLoader.mjs +20 -5
  91. package/dist/webpackLoader.mjs.map +1 -1
  92. package/native/tailwind-styled-native.node +0 -0
  93. package/package.json +29 -24
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
+ import { createRequire } from 'module';
1
2
  import * as path from 'path';
2
3
  import { dirname } from 'path';
3
4
  import { fileURLToPath } from 'url';
4
5
  import 'crypto';
5
6
  import * as fs from 'fs';
6
- import { createRequire } from 'module';
7
7
  import React3 from 'react';
8
8
 
9
9
  /* tailwind-styled-v4 v5.0.4 | MIT | https://github.com/dictionar32/tailwind-styled-v4 */
@@ -16,12 +16,12 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
16
16
  var isBrowser = typeof window !== "undefined" || typeof document !== "undefined";
17
17
  var _require = typeof __require !== "undefined" ? __require : createRequire(import.meta.url);
18
18
  var PLATFORM_MAP = {
19
- "linux-x64": ["@tailwind-styled/native-linux-x64"],
20
- "linux-arm64": ["@tailwind-styled/native-linux-arm64"],
19
+ "linux-x64": ["@tailwind-styled/native-linux-x64-gnu", "@tailwind-styled/native-linux-x64"],
20
+ "linux-arm64": ["@tailwind-styled/native-linux-arm64-gnu", "@tailwind-styled/native-linux-arm64"],
21
21
  "darwin-x64": ["@tailwind-styled/native-darwin-x64"],
22
22
  "darwin-arm64": ["@tailwind-styled/native-darwin-arm64"],
23
- "win32-x64": ["@tailwind-styled/native-win32-x64"],
24
- "win32-arm64": ["@tailwind-styled/native-win32-arm64"]
23
+ "win32-x64": ["@tailwind-styled/native-win32-x64-msvc", "@tailwind-styled/native-win32-x64"],
24
+ "win32-arm64": ["@tailwind-styled/native-win32-arm64-msvc", "@tailwind-styled/native-win32-arm64"]
25
25
  };
26
26
  function platformKey() {
27
27
  if (isBrowser) return "browser";
@@ -55,9 +55,24 @@ function resolveNativeBinary(runtimeDir) {
55
55
  tried.push(`prebuilt:${pkg} (not installed)`);
56
56
  }
57
57
  }
58
+ const napiPlatform = platform === "linux-x64" ? "linux-x64-gnu" : platform === "linux-arm64" ? "linux-arm64-gnu" : platform;
59
+ const BINARY_NAMES_SELF = ["tailwind-styled-native", "tailwind_styled_parser"];
60
+ if (runtimeDir) {
61
+ for (const depth of ["..", path.join("..", ".."), path.join("..", "..", "..")]) {
62
+ const pkgRoot = path.resolve(runtimeDir, depth);
63
+ for (const bin of BINARY_NAMES_SELF) {
64
+ for (const suffix of ["", `.${platform}`, `.${napiPlatform}`]) {
65
+ const candidate = path.resolve(pkgRoot, "native", `${bin}${suffix}.node`);
66
+ tried.push(`self-bundled:${candidate}`);
67
+ if (fs.existsSync(candidate)) {
68
+ return { path: candidate, source: "prebuilt", platform, tried };
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
58
74
  const cwd = process.cwd();
59
75
  const base = runtimeDir ?? cwd;
60
- const napiPlatform = platform === "linux-x64" ? "linux-x64-gnu" : platform === "linux-arm64" ? "linux-arm64-gnu" : platform;
61
76
  const BINARY_NAMES = ["tailwind-styled-native", "tailwind_styled_parser"];
62
77
  const localCandidates = [];
63
78
  for (const bin of BINARY_NAMES) {
@@ -96,7 +111,8 @@ createRequire(import.meta.url);
96
111
  // packages/domain/core/src/native.ts
97
112
  var isBrowser2 = typeof window !== "undefined" || typeof document !== "undefined";
98
113
  var NATIVE_UNAVAILABLE_MESSAGE = "[tailwind-styled/core] Native binding is required but not available.\nPlease ensure you have run: npm run build:rust";
99
- var _loadNative = (path3) => __require(path3);
114
+ var _nodeRequire = createRequire(import.meta.url);
115
+ var _loadNative = (path3) => _nodeRequire(path3);
100
116
  var nativeBinding = null;
101
117
  var bindingLoadAttempted = false;
102
118
  var getBinding = () => {
@@ -140,10 +156,25 @@ var containerRegistry = /* @__PURE__ */ new Map();
140
156
  if (typeof window !== "undefined") {
141
157
  window.__TW_CONTAINER_REGISTRY__ = containerRegistry;
142
158
  }
159
+ var _hashContainerCache = /* @__PURE__ */ new Map();
143
160
  function hashContainer(tag, container, name) {
144
- const key = tag + (name ?? "") + JSON.stringify(Object.entries(container).sort());
145
- const hash = key.split("").reduce((h, char) => (h << 5) + h ^ char.charCodeAt(0), 5381);
146
- return `tw-cq-${Math.abs(hash).toString(36).slice(0, 6)}`;
161
+ const sortedKey = tag + (name ?? "") + JSON.stringify(Object.entries(container).sort());
162
+ const cached = _hashContainerCache.get(sortedKey);
163
+ if (cached) return cached;
164
+ let id;
165
+ try {
166
+ const native = getNativeBinding();
167
+ if (native?.hashContent) {
168
+ id = `tw-cq-${native.hashContent(sortedKey, "fnv", 6)}`;
169
+ } else {
170
+ throw new Error("no hashContent");
171
+ }
172
+ } catch {
173
+ const hash = sortedKey.split("").reduce((h, char) => (h << 5) + h ^ char.charCodeAt(0), 5381);
174
+ id = `tw-cq-${Math.abs(hash).toString(36).slice(0, 6)}`;
175
+ }
176
+ _hashContainerCache.set(sortedKey, id);
177
+ return id;
147
178
  }
148
179
  var LAYOUT_MAP = {
149
180
  "flex-col": "flex-direction:column",
@@ -228,17 +259,21 @@ function buildContainerRules(id, container, containerName) {
228
259
  }).filter(Boolean);
229
260
  return rules.join("\n");
230
261
  }
262
+ var _cqBatchedInjectFn = null;
263
+ try {
264
+ const mod = __require("@tailwind-styled/runtime-css/batched");
265
+ if (typeof mod?.batchedInject === "function") _cqBatchedInjectFn = mod.batchedInject;
266
+ } catch {
267
+ }
231
268
  function injectContainerStyles(id, container, containerName) {
232
269
  if (typeof document === "undefined") return;
233
270
  const styleId = `tw-cq-${id}`;
234
271
  if (document.getElementById(styleId)) return;
235
272
  const css = buildContainerRules(id, container, containerName);
236
273
  if (!css) return;
237
- try {
238
- const { batchedInject } = __require("@tailwind-styled/runtime-css/batched");
239
- for (const rule of css.split("\n").filter(Boolean)) batchedInject(rule);
274
+ if (_cqBatchedInjectFn) {
275
+ for (const rule of css.split("\n").filter(Boolean)) _cqBatchedInjectFn(rule);
240
276
  return;
241
- } catch {
242
277
  }
243
278
  const style = document.createElement("style");
244
279
  style.id = styleId;
@@ -286,17 +321,27 @@ function getContainerRegistry() {
286
321
 
287
322
  // packages/domain/core/src/merge.ts
288
323
  function normalizeClassInput(classLists) {
289
- return classLists.filter(Boolean).map((v) => String(v).trim()).filter((v) => v.length > 0);
324
+ const result = [];
325
+ for (let i = 0; i < classLists.length; i++) {
326
+ const v = classLists[i];
327
+ if (!v) continue;
328
+ const s = String(v).trim();
329
+ if (s.length > 0) result.push(s);
330
+ }
331
+ return result;
290
332
  }
291
333
  function createTwMerge(_options = {}) {
292
334
  return function twMerge2(...classLists) {
293
335
  const clean = normalizeClassInput(classLists);
294
336
  if (clean.length === 0) return "";
295
- const native = getNativeBinding();
296
- if (!native?.twMergeMany) {
297
- throw new Error("FATAL: Native binding 'twMergeMany' is required but not available.");
337
+ try {
338
+ const native = getNativeBinding();
339
+ if (native?.twMergeMany) {
340
+ return native.twMergeMany(clean);
341
+ }
342
+ } catch {
298
343
  }
299
- return native.twMergeMany(clean);
344
+ return clean.join(" ");
300
345
  };
301
346
  }
302
347
  var twMerge = createTwMerge();
@@ -314,17 +359,44 @@ var stateRegistry = /* @__PURE__ */ new Map();
314
359
  if (typeof window !== "undefined") {
315
360
  window.__TW_STATE_REGISTRY__ = stateRegistry;
316
361
  }
362
+ var _hashStateCache = /* @__PURE__ */ new Map();
317
363
  function hashState(tag, state) {
318
- const key = tag + JSON.stringify(Object.entries(state).sort());
319
- const hash = key.split("").reduce((h, char) => (h << 5) + h ^ char.charCodeAt(0), 5381);
320
- return `tw-s-${Math.abs(hash).toString(36).slice(0, 6)}`;
364
+ const sortedKey = tag + JSON.stringify(Object.entries(state).sort());
365
+ const cached = _hashStateCache.get(sortedKey);
366
+ if (cached) return cached;
367
+ let id;
368
+ try {
369
+ const native = getNativeBinding();
370
+ if (native?.hashContent) {
371
+ const raw = native.hashContent(sortedKey, "fnv", 6);
372
+ id = `tw-s-${raw}`;
373
+ } else {
374
+ throw new Error("no hashContent");
375
+ }
376
+ } catch {
377
+ const hash = sortedKey.split("").reduce((h, char) => (h << 5) + h ^ char.charCodeAt(0), 5381);
378
+ id = `tw-s-${Math.abs(hash).toString(36).slice(0, 6)}`;
379
+ }
380
+ _hashStateCache.set(sortedKey, id);
381
+ return id;
321
382
  }
383
+ var _twClassesToCssCache = /* @__PURE__ */ new Map();
322
384
  function twClassesToCss(classes) {
385
+ const cached = _twClassesToCssCache.get(classes);
386
+ if (cached !== void 0) return cached;
323
387
  const native = getNativeBinding();
324
388
  if (!native?.twClassesToCss) {
325
389
  throw new Error("FATAL: Native binding 'twClassesToCss' is required but not available.");
326
390
  }
327
- return native.twClassesToCss(classes);
391
+ const result = native.twClassesToCss(classes);
392
+ _twClassesToCssCache.set(classes, result);
393
+ return result;
394
+ }
395
+ var _batchedInjectFn = null;
396
+ try {
397
+ const mod = __require("@tailwind-styled/runtime-css/batched");
398
+ if (typeof mod?.batchedInject === "function") _batchedInjectFn = mod.batchedInject;
399
+ } catch {
328
400
  }
329
401
  function injectStateStyles(id, state) {
330
402
  if (typeof document === "undefined") return;
@@ -335,11 +407,9 @@ function injectStateStyles(id, state) {
335
407
  return css ? `.${id}[data-${stateName}="true"]{${css}}` : null;
336
408
  }).filter(Boolean);
337
409
  if (rules.length === 0) return;
338
- try {
339
- const { batchedInject } = __require("@tailwind-styled/runtime-css/batched");
340
- for (const rule of rules) batchedInject(rule);
410
+ if (_batchedInjectFn) {
411
+ for (const rule of rules) _batchedInjectFn(rule);
341
412
  return;
342
- } catch {
343
413
  }
344
414
  const style = document.createElement("style");
345
415
  style.id = styleId;
@@ -377,35 +447,120 @@ function getStateRegistry() {
377
447
 
378
448
  // packages/domain/core/src/createComponent.ts
379
449
  var ALWAYS_BLOCKED = /* @__PURE__ */ new Set(["base", "_ref", "state", "container", "containerName"]);
380
- function parseSubComponentBlocks(template) {
381
- const native = getNativeBinding();
382
- if (!native?.parseSubcomponentBlocksNapi) {
383
- throw new Error("FATAL: Native binding 'parseSubcomponentBlocksNapi' is required but not available.");
384
- }
385
- const result = native.parseSubcomponentBlocksNapi(template, "tw");
386
- const raw = JSON.parse(result.subMapJson);
387
- return new Map(Object.entries(raw));
388
- }
389
- function extractBaseClasses(template) {
450
+ var _templateParseCache = /* @__PURE__ */ new Map();
451
+ var _statesLookupCache = /* @__PURE__ */ new Map();
452
+ function _getParsedTemplate(template) {
453
+ const cached = _templateParseCache.get(template);
454
+ if (cached) return cached;
455
+ let result;
390
456
  try {
391
457
  const native = getNativeBinding();
392
458
  if (native?.parseSubcomponentBlocksNapi) {
393
- const result = native.parseSubcomponentBlocksNapi(template, "tw");
394
- return result.baseClasses;
459
+ const r = native.parseSubcomponentBlocksNapi(template, "tw");
460
+ const raw = JSON.parse(r.subMapJson);
461
+ result = {
462
+ baseClasses: r.baseClasses.trim().replace(/\s+/g, " "),
463
+ subMap: new Map(Object.entries(raw))
464
+ };
465
+ _templateParseCache.set(template, result);
466
+ return result;
395
467
  }
396
468
  } catch {
397
469
  }
398
- return template.replace(/(?:\[[a-zA-Z][a-zA-Z0-9_-]*\]|[a-zA-Z][a-zA-Z0-9_-]*)\s*\{[^}]*\}/g, "").replace(/\s+/g, " ").trim();
470
+ const subMap = /* @__PURE__ */ new Map();
471
+ const regex = /((?:\[[a-zA-Z][a-zA-Z0-9_-]*\]|[a-zA-Z][a-zA-Z0-9_-]*))\s*\{([^}]*)\}/g;
472
+ let match;
473
+ while ((match = regex.exec(template)) !== null) {
474
+ const rawName = match[1];
475
+ const name = rawName.startsWith("[") ? rawName.slice(1, -1) : rawName;
476
+ const classes = match[2].trim().replace(/\s+/g, " ");
477
+ if (classes) subMap.set(name, classes);
478
+ }
479
+ const baseClasses = template.replace(/(?:\[[a-zA-Z][a-zA-Z0-9_-]*\]|[a-zA-Z][a-zA-Z0-9_-]*)\s*\{[^}]*\}/g, "").replace(/\s+/g, " ").trim();
480
+ result = { baseClasses, subMap };
481
+ _templateParseCache.set(template, result);
482
+ return result;
483
+ }
484
+ function parseSubComponentBlocks(template) {
485
+ return _getParsedTemplate(template).subMap;
486
+ }
487
+ function extractBaseClasses(template) {
488
+ return _getParsedTemplate(template).baseClasses;
399
489
  }
400
- function createSubComponentAccessor(parentDisplayName, name, classes) {
490
+ var SEMANTIC_HTML_TAGS = /* @__PURE__ */ new Set([
491
+ "article",
492
+ "aside",
493
+ "details",
494
+ "figcaption",
495
+ "figure",
496
+ "footer",
497
+ "header",
498
+ "main",
499
+ "mark",
500
+ "nav",
501
+ "section",
502
+ "summary",
503
+ "time",
504
+ "h1",
505
+ "h2",
506
+ "h3",
507
+ "h4",
508
+ "h5",
509
+ "h6",
510
+ "p",
511
+ "ul",
512
+ "ol",
513
+ "li",
514
+ "dl",
515
+ "dt",
516
+ "dd",
517
+ "table",
518
+ "thead",
519
+ "tbody",
520
+ "tfoot",
521
+ "tr",
522
+ "th",
523
+ "td",
524
+ "form",
525
+ "fieldset",
526
+ "legend",
527
+ "label",
528
+ "a",
529
+ "button",
530
+ "img",
531
+ "span",
532
+ "div",
533
+ "blockquote",
534
+ "pre",
535
+ "code",
536
+ "em",
537
+ "strong",
538
+ "small"
539
+ ]);
540
+ function parseSubKey(key) {
541
+ const colonIdx = key.indexOf(":");
542
+ if (colonIdx !== -1) {
543
+ const tag = key.slice(0, colonIdx).trim();
544
+ const componentName = key.slice(colonIdx + 1).trim();
545
+ return { tag: tag || "span", componentName: componentName || tag };
546
+ }
547
+ const isSemanticTag = SEMANTIC_HTML_TAGS.has(key);
548
+ return { tag: isSemanticTag ? key : "span", componentName: key };
549
+ }
550
+ function createSubComponentAccessor(parentDisplayName, name, classes, tag = "span", asChild = false) {
401
551
  const SubComponent = ({
402
552
  children,
403
553
  className
404
- }) => React3.createElement(
405
- "span",
406
- { className: className ? `${classes} ${className}` : classes },
407
- children
408
- );
554
+ }) => {
555
+ const mergedClass = className ? `${classes} ${className}` : classes;
556
+ if (asChild && React3.isValidElement(children)) {
557
+ const child = React3.Children.only(children);
558
+ return React3.cloneElement(child, {
559
+ className: child.props.className ? `${mergedClass} ${child.props.className}` : mergedClass
560
+ });
561
+ }
562
+ return React3.createElement(tag, { className: mergedClass }, children);
563
+ };
409
564
  SubComponent.displayName = `${parentDisplayName}[${name}]`;
410
565
  return SubComponent;
411
566
  }
@@ -413,8 +568,26 @@ function registerSubComponents(component, template, configSub) {
413
568
  const displayName = component.displayName ?? "tw";
414
569
  const map = component;
415
570
  if (configSub) {
416
- for (const [name, classes] of Object.entries(configSub)) {
417
- map[name] = createSubComponentAccessor(displayName, name, classes.trim().replace(/\s+/g, " "));
571
+ for (const [key, value] of Object.entries(configSub)) {
572
+ if (typeof value === "string") {
573
+ const { tag, componentName } = parseSubKey(key);
574
+ map[componentName] = createSubComponentAccessor(
575
+ displayName,
576
+ componentName,
577
+ value.trim().replace(/\s+/g, " "),
578
+ tag
579
+ );
580
+ } else {
581
+ const tag = key;
582
+ for (const [componentName, classes] of Object.entries(value)) {
583
+ map[componentName] = createSubComponentAccessor(
584
+ displayName,
585
+ componentName,
586
+ classes.trim().replace(/\s+/g, " "),
587
+ tag
588
+ );
589
+ }
590
+ }
418
591
  }
419
592
  }
420
593
  const blocks = parseSubComponentBlocks(template);
@@ -427,11 +600,12 @@ function registerSubComponents(component, template, configSub) {
427
600
  function normalizeClassName(value) {
428
601
  return typeof value === "string" ? value : void 0;
429
602
  }
430
- function makeFilterProps(variantKeys) {
603
+ function makeFilterProps(variantKeys, stateKeys = /* @__PURE__ */ new Set()) {
431
604
  return function filterProps(props) {
432
605
  const out = {};
433
606
  for (const key in props) {
434
607
  if (variantKeys.has(key)) continue;
608
+ if (stateKeys.has(key)) continue;
435
609
  if (key.startsWith("$")) continue;
436
610
  if (ALWAYS_BLOCKED.has(key)) continue;
437
611
  out[key] = props[key];
@@ -440,15 +614,42 @@ function makeFilterProps(variantKeys) {
440
614
  };
441
615
  }
442
616
  function resolveVariants(variants, props, defaults) {
443
- const binding = getNativeBinding();
444
- if (!binding?.resolveSimpleVariants) {
445
- throw new Error("FATAL: Native binding 'resolveSimpleVariants' is required but not available.");
446
- }
617
+ const variantKeys = Object.keys(variants);
447
618
  const cleanProps = {};
448
- for (const [k, v] of Object.entries(props)) {
619
+ for (const k of variantKeys) {
620
+ const v = props[k];
449
621
  if (v !== void 0 && v !== null) cleanProps[k] = String(v);
450
622
  }
451
- return binding.resolveSimpleVariants(null, variants, defaults, cleanProps);
623
+ try {
624
+ const binding = getNativeBinding();
625
+ if (binding?.resolveSimpleVariants) {
626
+ const result = binding.resolveSimpleVariants(null, variants, defaults, cleanProps);
627
+ return result.trim().replace(/\s+/g, " ");
628
+ }
629
+ } catch {
630
+ }
631
+ const resolved = { ...defaults, ...cleanProps };
632
+ const classes = [];
633
+ const sortedVariantEntries = Object.entries(variants).sort(([a], [b]) => a.localeCompare(b));
634
+ for (const [variantKey, variantMap] of sortedVariantEntries) {
635
+ const selected = resolved[variantKey];
636
+ if (selected !== void 0 && variantMap[selected] !== void 0) {
637
+ const normalized = variantMap[selected].trim().replace(/\s+/g, " ");
638
+ classes.push(normalized);
639
+ }
640
+ }
641
+ return classes.filter(Boolean).join(" ");
642
+ }
643
+ function resolveStates(statesConfig, stateKeys, statesLookup, props) {
644
+ if (statesLookup && stateKeys.length > 0) {
645
+ let mask = 0;
646
+ for (let i = 0; i < stateKeys.length; i++) {
647
+ if (props[stateKeys[i]]) mask |= 1 << i;
648
+ }
649
+ return statesLookup[mask] ?? "";
650
+ }
651
+ const activeClasses = stateKeys.filter((k) => props[k]).map((k) => statesConfig[k]).filter(Boolean);
652
+ return activeClasses.join(" ");
452
653
  }
453
654
  function resolveCompound(compounds, props) {
454
655
  const classes = [];
@@ -545,19 +746,46 @@ function createComponent(tag, config) {
545
746
  const containerConfig = typeof config === "string" ? void 0 : config.container;
546
747
  const containerName = typeof config === "string" ? void 0 : config.containerName;
547
748
  const configSub = typeof config === "string" ? void 0 : config.sub;
749
+ const statesConfig = typeof config === "string" ? void 0 : config.states;
750
+ let statesLookup = null;
751
+ let stateKeys = [];
752
+ if (statesConfig && Object.keys(statesConfig).length > 0) {
753
+ stateKeys = Object.keys(statesConfig);
754
+ const statesCacheKey = JSON.stringify(statesConfig, Object.keys(statesConfig).sort());
755
+ const cachedStates = _statesLookupCache.get(statesCacheKey);
756
+ if (cachedStates) {
757
+ statesLookup = cachedStates.lookup;
758
+ stateKeys = cachedStates.keys;
759
+ } else {
760
+ try {
761
+ const native = getNativeBinding();
762
+ if (native?.pregenerateStatesNapi) {
763
+ const result2 = native.pregenerateStatesNapi(statesConfig);
764
+ statesLookup = JSON.parse(result2.lookupJson);
765
+ stateKeys = result2.stateKeys;
766
+ _statesLookupCache.set(statesCacheKey, { lookup: statesLookup, keys: stateKeys });
767
+ }
768
+ } catch (e) {
769
+ console.warn("[tailwind-styled-v4] states pre-generation failed, falling back to runtime cx()", e);
770
+ }
771
+ }
772
+ }
548
773
  const stateResult = stateConfig ? processState(typeof tag === "string" ? tag : "component", stateConfig) : null;
549
774
  const containerResult = containerConfig ? processContainer(typeof tag === "string" ? tag : "component", containerConfig, containerName) : null;
550
775
  const engineClasses = [stateResult?.stateClass, containerResult?.containerClass].filter(Boolean).join(" ");
551
- const filterProps = makeFilterProps(new Set(Object.keys(variants)));
776
+ const filterProps = makeFilterProps(new Set(Object.keys(variants)), new Set(stateKeys));
552
777
  const tagLabel = typeof tag === "string" ? tag : tag.displayName ?? "Component";
553
778
  if (isStatic || Object.keys(variants).length === 0) {
554
779
  const baseComponent2 = React3.forwardRef((props, ref) => {
555
780
  const { className, ...rest } = props;
556
781
  const runtimeClassName = normalizeClassName(className);
782
+ const statesClasses = statesConfig ? resolveStates(statesConfig, stateKeys, statesLookup, props) : "";
783
+ const mergedBase = twMerge(extractBaseClasses(base), engineClasses, runtimeClassName);
784
+ const className2 = statesClasses ? `${mergedBase} ${statesClasses}`.trim() : mergedBase;
557
785
  return React3.createElement(tag, {
558
786
  ref,
559
787
  ...filterProps(rest),
560
- className: twMerge(extractBaseClasses(base), engineClasses, runtimeClassName)
788
+ className: className2
561
789
  });
562
790
  });
563
791
  const component2 = baseComponent2;
@@ -571,10 +799,13 @@ function createComponent(tag, config) {
571
799
  const runtimeClassName = normalizeClassName(className);
572
800
  const variantClasses = resolveVariants(variants, props, defaultVariants);
573
801
  const compoundClasses = resolveCompound(compoundVariants, props);
802
+ const statesClasses = statesConfig ? resolveStates(statesConfig, stateKeys, statesLookup, props) : "";
803
+ const mergedBase = twMerge(extractBaseClasses(base), variantClasses, compoundClasses, engineClasses, runtimeClassName);
804
+ const className2 = statesClasses ? `${mergedBase} ${statesClasses}`.trim() : mergedBase;
574
805
  return React3.createElement(tag, {
575
806
  ref,
576
807
  ...filterProps(rest),
577
- className: twMerge(extractBaseClasses(base), variantClasses, compoundClasses, engineClasses, runtimeClassName)
808
+ className: className2
578
809
  });
579
810
  });
580
811
  const component = baseComponent;
@@ -614,47 +845,114 @@ function wrapWithSubProxy(component, tagLabel) {
614
845
 
615
846
  // packages/domain/core/src/cv.ts
616
847
  var __generatedRegistry = {};
617
- function lookupGenerated(componentId, props, defaultVariants) {
848
+ var _sortedVariantKeysCache = /* @__PURE__ */ new Map();
849
+ function lookupGenerated(componentId, props, defaultVariants, variantKeys) {
618
850
  const table = __generatedRegistry[componentId];
619
851
  if (!table) return void 0;
620
852
  const merged = { ...defaultVariants, ...props };
621
- const key = Object.keys(merged).sort().filter((k) => k !== "className").map((k) => `${k}:${String(merged[k])}`).join("|");
853
+ let sortedKeys = _sortedVariantKeysCache.get(componentId);
854
+ if (!sortedKeys) {
855
+ const keysToUse = variantKeys ? variantKeys : Object.keys(merged).filter((k) => k !== "className");
856
+ sortedKeys = [...keysToUse].sort();
857
+ _sortedVariantKeysCache.set(componentId, sortedKeys);
858
+ }
859
+ let key = "";
860
+ for (let i = 0; i < sortedKeys.length; i++) {
861
+ if (i > 0) key += "|";
862
+ key += sortedKeys[i] + ":" + String(merged[sortedKeys[i]]);
863
+ }
622
864
  return table[key];
623
865
  }
866
+ var _configJsonCache = /* @__PURE__ */ new WeakMap();
867
+ function _getConfigJson(config) {
868
+ let json = _configJsonCache.get(config);
869
+ if (!json) {
870
+ json = JSON.stringify(config);
871
+ _configJsonCache.set(config, json);
872
+ }
873
+ return json;
874
+ }
624
875
  function resolveVariantsNative(config, props) {
625
876
  const { base = "", variants = {}, compoundVariants = [], defaultVariants = {} } = config;
626
- const binding = getNativeBinding();
627
- if (binding?.resolveSimpleVariants) {
628
- const mergedProps = {};
629
- for (const [k, v] of Object.entries(defaultVariants)) {
630
- if (v !== void 0 && v !== null) mergedProps[k] = String(v);
631
- }
632
- for (const [k, v] of Object.entries(props)) {
633
- if (v !== void 0 && v !== null && k !== "className") {
634
- mergedProps[k] = String(v);
877
+ const variantKeys = Object.keys(variants);
878
+ try {
879
+ const binding = getNativeBinding();
880
+ if (binding?.resolveVariants) {
881
+ const configJson = _getConfigJson(config);
882
+ const cleanProps = {};
883
+ for (const k of variantKeys) {
884
+ const dv = defaultVariants[k];
885
+ if (dv !== void 0 && dv !== null) cleanProps[k] = String(dv);
886
+ }
887
+ for (const k of variantKeys) {
888
+ const v = props[k];
889
+ if (v !== void 0 && v !== null) cleanProps[k] = String(v);
635
890
  }
891
+ const propsJson = JSON.stringify(cleanProps);
892
+ const result = binding.resolveVariants(configJson, propsJson);
893
+ return result.classes;
636
894
  }
637
- let result = binding.resolveSimpleVariants(
638
- base || null,
639
- variants,
640
- {},
641
- // already merged into mergedProps
642
- mergedProps
643
- );
644
- const resolved = { ...defaultVariants, ...props };
645
- const extra = [];
646
- for (const compound of compoundVariants) {
647
- const { class: compoundClass, className: compoundClassName, ...conditions } = compound;
648
- const matches = Object.entries(conditions).every(([key, val]) => resolved[key] === val);
649
- if (matches) {
650
- if (compoundClass) extra.push(String(compoundClass));
651
- if (compoundClassName) extra.push(String(compoundClassName));
895
+ if (binding?.resolveSimpleVariants) {
896
+ const mergedProps = {};
897
+ for (const k of variantKeys) {
898
+ const dv = defaultVariants[k];
899
+ if (dv !== void 0 && dv !== null) mergedProps[k] = String(dv);
900
+ }
901
+ for (const k of variantKeys) {
902
+ const v = props[k];
903
+ if (v !== void 0 && v !== null) mergedProps[k] = String(v);
904
+ }
905
+ let result = binding.resolveSimpleVariants(
906
+ base || null,
907
+ variants,
908
+ {},
909
+ mergedProps
910
+ );
911
+ if (compoundVariants.length > 0) {
912
+ const resolved2 = { ...defaultVariants, ...props };
913
+ const extra = [];
914
+ for (const compound of compoundVariants) {
915
+ const { class: compoundClass, className: compoundClassName, ...conditions } = compound;
916
+ const matches = Object.entries(conditions).every(([key, val]) => resolved2[key] === val);
917
+ if (matches) {
918
+ if (compoundClass) extra.push(String(compoundClass));
919
+ if (compoundClassName) extra.push(String(compoundClassName));
920
+ }
921
+ }
922
+ if (extra.length > 0) result = `${result} ${extra.join(" ")}`.trim();
652
923
  }
924
+ return result;
925
+ }
926
+ } catch {
927
+ }
928
+ const resolved = {};
929
+ for (const k of variantKeys) {
930
+ const dv = defaultVariants[k];
931
+ if (dv !== void 0) resolved[k] = dv;
932
+ }
933
+ for (const k of variantKeys) {
934
+ const v = props[k];
935
+ if (v !== void 0 && v !== null) resolved[k] = String(v);
936
+ }
937
+ const classes = [];
938
+ if (base) classes.push(base);
939
+ for (const k of variantKeys) {
940
+ const variantMap = variants[k];
941
+ const selected = resolved[k];
942
+ if (selected !== void 0 && variantMap?.[selected] !== void 0) {
943
+ classes.push(variantMap[selected]);
944
+ }
945
+ }
946
+ const resolvedFull = { ...defaultVariants, ...props };
947
+ for (const compound of compoundVariants) {
948
+ const { class: compoundClass, className: compoundClassName, ...conditions } = compound;
949
+ const matches = Object.entries(conditions).every(([key, val]) => resolvedFull[key] === val);
950
+ if (matches) {
951
+ if (compoundClass) classes.push(String(compoundClass));
952
+ if (compoundClassName) classes.push(String(compoundClassName));
653
953
  }
654
- if (extra.length > 0) result = `${result} ${extra.join(" ")}`.trim();
655
- return result;
656
954
  }
657
- throw new Error("FATAL: Native binding 'resolveSimpleVariants' is required but not available.");
955
+ return classes.filter(Boolean).join(" ");
658
956
  }
659
957
  function cv(config, componentId) {
660
958
  if (process.env.NODE_ENV !== "production") {
@@ -667,11 +965,13 @@ function cv(config, componentId) {
667
965
  }
668
966
  return (props = {}) => {
669
967
  let result;
968
+ const variantKeys = Object.keys(config.variants ?? {});
670
969
  if (componentId) {
671
970
  const generated = lookupGenerated(
672
971
  componentId,
673
972
  props,
674
- config.defaultVariants
973
+ config.defaultVariants,
974
+ variantKeys
675
975
  );
676
976
  result = generated ?? resolveVariantsNative(config, props);
677
977
  } else {
@@ -683,24 +983,34 @@ function cv(config, componentId) {
683
983
 
684
984
  // packages/domain/core/src/cx.ts
685
985
  function cn(...inputs) {
686
- const native = getNativeBinding();
687
- if (!native?.resolveClassNames) {
688
- throw new Error("FATAL: Native binding 'resolveClassNames' is required but not available.");
986
+ const strings = [];
987
+ for (const item of inputs) {
988
+ if (Array.isArray(item)) {
989
+ for (const v of item) {
990
+ if (v) strings.push(String(v));
991
+ }
992
+ } else if (item) {
993
+ strings.push(String(item));
994
+ }
995
+ }
996
+ if (strings.length === 0) return "";
997
+ try {
998
+ const native = getNativeBinding();
999
+ if (native?.resolveClassNames) return native.resolveClassNames(strings);
1000
+ } catch {
689
1001
  }
690
- const strings = inputs.flat().filter(Boolean);
691
- return native.resolveClassNames(strings);
1002
+ return strings.join(" ");
692
1003
  }
693
1004
  function cx(...inputs) {
694
1005
  const filtered = inputs.flat().filter(Boolean);
695
1006
  if (filtered.length === 0) return "";
696
- const native = getNativeBinding();
697
- if (!native?.twMergeMany && !native?.twMerge) {
698
- throw new Error("FATAL: Native binding 'twMerge' or 'twMergeMany' is required but not available.");
699
- }
700
- if (native.twMergeMany) {
701
- return native.twMergeMany(filtered);
1007
+ try {
1008
+ const native = getNativeBinding();
1009
+ if (native?.twMergeMany) return native.twMergeMany(filtered);
1010
+ if (native?.twMerge) return native.twMerge(filtered.join(" "));
1011
+ } catch {
702
1012
  }
703
- return native.twMerge(filtered.join(" "));
1013
+ return filtered.join(" ");
704
1014
  }
705
1015
  var cxm = cx;
706
1016
  var TOKEN_ENGINE_KEY = "__TW_TOKEN_ENGINE__";
@@ -1149,29 +1459,49 @@ function parseTemplateFallback(strings, exprs) {
1149
1459
  SUB_RE.lastIndex = 0;
1150
1460
  while ((match = SUB_RE.exec(raw)) !== null) {
1151
1461
  const name = match[1] ?? match[2];
1152
- const inner = match[3].replace(COMMENT_RE, "").split("\n").map((l) => l.trim()).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
1462
+ const rawInner = match[3].replace(COMMENT_RE, "");
1463
+ let inner = "";
1464
+ for (const line of rawInner.split("\n")) {
1465
+ const t2 = line.trim();
1466
+ if (t2) inner += (inner ? " " : "") + t2;
1467
+ }
1468
+ inner = inner.replace(/\s+/g, " ").trim();
1153
1469
  subs[name] = inner;
1154
1470
  base = base.replace(match[0], "");
1155
1471
  }
1156
- const cleanBase = base.replace(COMMENT_RE, "").split("\n").map((l) => l.trim()).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
1472
+ const rawBase = base.replace(COMMENT_RE, "");
1473
+ let cleanBase = "";
1474
+ for (const line of rawBase.split("\n")) {
1475
+ const t2 = line.trim();
1476
+ if (t2) cleanBase += (cleanBase ? " " : "") + t2;
1477
+ }
1478
+ cleanBase = cleanBase.replace(/\s+/g, " ").trim();
1157
1479
  return { base: cleanBase, subs, hasSubs: Object.keys(subs).length > 0 };
1158
1480
  }
1481
+ var _parsedTemplateCache = /* @__PURE__ */ new Map();
1159
1482
  function parseTemplate(strings, exprs) {
1160
1483
  const raw = strings.raw.reduce((acc, str, i) => {
1161
1484
  const expr = exprs[i];
1162
1485
  const exprStr = typeof expr === "function" ? "" : expr ?? "";
1163
1486
  return acc + str + String(exprStr);
1164
1487
  }, "");
1488
+ const cached = _parsedTemplateCache.get(raw);
1489
+ if (cached) return cached;
1490
+ let result;
1165
1491
  try {
1166
1492
  const binding = getNativeBinding();
1167
1493
  if (binding?.parseTemplate) {
1168
- const result = binding.parseTemplate(raw);
1169
- const subs = result.hasSubs ? JSON.parse(result.subsJson) : {};
1170
- return { base: result.base, subs, hasSubs: result.hasSubs };
1494
+ const r = binding.parseTemplate(raw);
1495
+ const subs = r.hasSubs ? JSON.parse(r.subsJson) : {};
1496
+ result = { base: r.base, subs, hasSubs: r.hasSubs };
1497
+ _parsedTemplateCache.set(raw, result);
1498
+ return result;
1171
1499
  }
1172
1500
  } catch {
1173
1501
  }
1174
- return parseTemplateFallback(strings, exprs);
1502
+ result = parseTemplateFallback(strings, exprs);
1503
+ _parsedTemplateCache.set(raw, result);
1504
+ return result;
1175
1505
  }
1176
1506
  function makeTag(tag) {
1177
1507
  return ((stringsOrConfig, ...exprs) => {