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.d.ts CHANGED
@@ -12,11 +12,57 @@ export { a as LiveTokenSet, T as TokenSubscriber, b as applyTokenSet, t as conta
12
12
  */
13
13
 
14
14
  type VariantLiterals = string | number | boolean;
15
+ /** Sizes sugar syntax — shorthand untuk variants.size */
16
+ type SizesConfig = Record<string, string>;
15
17
  type InferVariantProps<T extends ComponentConfig> = {
16
18
  [K in keyof T["variants"]]?: keyof T["variants"][K];
17
19
  };
20
+ type InferSizeProps<T extends ComponentConfig> = T["sizes"] extends Record<string, string> ? {
21
+ size?: keyof T["sizes"];
22
+ } : Record<never, never>;
23
+ /**
24
+ * Infer boolean props dari states config.
25
+ * Setiap key di states → optional boolean prop di component.
26
+ *
27
+ * @example
28
+ * // states: { loading: "...", fullWidth: "..." }
29
+ * // → { loading?: boolean, fullWidth?: boolean }
30
+ */
31
+ type InferStatesProps<T extends ComponentConfig> = {
32
+ [K in keyof T["states"]]?: boolean;
33
+ };
34
+ /**
35
+ * Sub config bisa berupa:
36
+ * - string: "font-bold text-lg" → render <span>
37
+ * - Record<name, string>: nested object per HTML tag
38
+ *
39
+ * @example
40
+ * sub: {
41
+ * icon: "w-4 h-4", // → <span class="w-4 h-4"> dipanggil Card.icon
42
+ * header: { topBar: "bg-gray-900" }, // → <header> dipanggil Card.topBar
43
+ * h2: { title: "text-xl font-bold" }, // → <h2> dipanggil Card.title
44
+ * section: { content: "px-6 py-4" }, // → <section> dipanggil Card.content
45
+ * }
46
+ */
47
+ type SubValue = string | Record<string, string>;
48
+ /**
49
+ * Boolean props yang di-resolve via bitmask lookup table (pre-generated di build time).
50
+ * Berbeda dari `state` (CSS data-attribute driven) — ini adalah React props boolean.
51
+ *
52
+ * @example
53
+ * states: {
54
+ * loading: "opacity-60 cursor-wait pointer-events-none",
55
+ * fullWidth: "w-full",
56
+ * disabled: "opacity-50 cursor-not-allowed",
57
+ * }
58
+ *
59
+ * // JSX — boolean prop langsung:
60
+ * <Button loading fullWidth>Submit</Button>
61
+ */
62
+ type StatesConfig = Record<string, string>;
18
63
  interface ComponentConfig {
19
64
  base?: string;
65
+ /** Variants — nested: { intent: { primary: "..." }, size: { sm: "..." } } */
20
66
  variants?: Record<string, Record<string, string>>;
21
67
  defaultVariants?: Record<string, string>;
22
68
  compoundVariants?: Array<{
@@ -26,12 +72,35 @@ interface ComponentConfig {
26
72
  state?: Record<string, Record<string, string>>;
27
73
  container?: Record<string, string>;
28
74
  containerName?: string;
29
- /** Sub-component definitionskeys di-infer otomatis oleh TypeScript */
30
- sub?: Record<string, string>;
75
+ /** Sugar syntax untuk variants.size { sm: "...", md: "...", lg: "..." } */
76
+ sizes?: SizesConfig;
77
+ /** defaultSize — default ke key pertama kalau tidak diset */
78
+ defaultSize?: string;
79
+ /**
80
+ * Boolean props — di-resolve via Rust bitmask lookup table di build time.
81
+ * Maksimal 16 states per komponen (2^16 kombinasi).
82
+ */
83
+ states?: StatesConfig;
84
+ /** Sub-component definitions — string atau nested { tag: { name: classes } } */
85
+ sub?: Record<string, SubValue>;
31
86
  }
87
+ /**
88
+ * Strip tag prefix dari "tag:name" format sub key.
89
+ * "div:action" → "action"
90
+ * "header" → "header" (tidak berubah)
91
+ */
92
+ type ExtractSubName<K extends string> = K extends `${string}:${infer Name}` ? Name : K;
93
+ /**
94
+ * Infer semua sub-component names dari config.sub:
95
+ * - string value plain → key langsung: { icon: "..." } → "icon"
96
+ * - string value tag:name → strip tag: { "div:action": "..." } → "action"
97
+ * - nested object → nested keys: { h2: { title: "..." } } → "title"
98
+ */
32
99
  type InferSubFromConfig<C extends ComponentConfig> = C extends {
33
- sub: Record<infer K extends string, string>;
34
- } ? K : never;
100
+ sub: infer S extends Record<string, SubValue>;
101
+ } ? {
102
+ [K in keyof S]: S[K] extends string ? K extends string ? ExtractSubName<K> : never : S[K] extends Record<infer N extends string, string> ? N : never;
103
+ }[keyof S] : never;
35
104
  interface ContainerConfig {
36
105
  base?: string;
37
106
  queries?: Record<string, string>;
@@ -73,7 +142,7 @@ type SubComponentKeys<S extends string> = string extends S ? {
73
142
  [K in S]: TwSubComponentAccessor;
74
143
  };
75
144
  type TwStyledComponent<Config extends ComponentConfig = ComponentConfig, S extends string = string> = {
76
- (props: StyledComponentProps & InferVariantProps<Config>): React.ReactElement | null;
145
+ (props: StyledComponentProps & InferVariantProps<Config> & InferSizeProps<Config> & InferStatesProps<Config>): React.ReactElement | null;
77
146
  displayName?: string;
78
147
  extend: {
79
148
  (strings: TemplateStringsArray, ...exprs: unknown[]): TwStyledComponent<Config, S>;
@@ -182,7 +251,7 @@ declare function processContainer(tag: string, container: ContainerConfig, conta
182
251
  declare function generateContainerCss(tag: string, container: ContainerConfig, containerName?: string): string;
183
252
  declare function getContainerRegistry(): Map<string, ContainerEntry>;
184
253
 
185
- declare function createComponent<P extends object = Record<string, unknown>>(tag: React.ElementType, config: string | ComponentConfig): TwStyledComponent<P>;
254
+ declare function createComponent<TConfig extends ComponentConfig>(tag: React.ElementType, config: TConfig | string): TwStyledComponent<TConfig, InferSubFromConfig<TConfig>>;
186
255
 
187
256
  /**
188
257
  * tailwind-styled-v4 — cv()
@@ -203,22 +272,27 @@ declare function cv<C extends ComponentConfig>(config: C, componentId?: string):
203
272
  *
204
273
  * Native-first:
205
274
  * cn() → simple join (no conflict resolution) — delegates ke Rust `resolve_class_names`
206
- * cx() → conflict-aware merge — delegates ke Rust `tw_merge` (required)
275
+ * cx() → conflict-aware merge — delegates ke Rust `tw_merge` (preferred)
207
276
  * cxm() → alias cx() untuk backward compat
277
+ *
278
+ * Browser fallback: simple join when native binding unavailable.
279
+ * In browser/client context, classes were already resolved on server during SSR.
208
280
  */
209
281
  type ClassValue = string | undefined | null | false | 0;
210
282
  /**
211
283
  * cn — simple class name joiner (no conflict resolution).
212
284
  * Native-first: delegates ke Rust `resolve_class_names` yang filter+join
213
285
  * dalam satu pass tanpa intermediate allocations.
286
+ * Browser fallback: flat+filter+join.
214
287
  *
215
288
  * @example cn("p-4", isActive && "opacity-100") → "p-4 opacity-100"
216
289
  */
217
290
  declare function cn(...inputs: (ClassValue | ClassValue[])[]): string;
218
291
  /**
219
292
  * cx — conflict-aware class merger.
220
- * Native-first: delegates ke Rust `tw_merge` (required).
293
+ * Native-first: delegates ke Rust `tw_merge` (preferred).
221
294
  * Mendukung array inputs — flatten sebelum di-pass ke native.
295
+ * Browser fallback: simple join without conflict resolution.
222
296
  *
223
297
  * @example cx("p-4 p-8") → "p-8"
224
298
  * @example cx("bg-red-500", "bg-blue-500") → "bg-blue-500"
@@ -243,8 +317,9 @@ interface ThemeConfig$1 {
243
317
  /**
244
318
  * tailwind-styled-v4 — createTwMerge()
245
319
  *
246
- * Native-only: uses Rust `tw_merge_many`; requires native binding.
247
- * No JS fallback tailwind-merge removed from bundle.
320
+ * Native-first: uses Rust `tw_merge_many` when available.
321
+ * Browser fallback: simple join (no conflict resolution).
322
+ * In browser/client context, classes were already resolved on the server during SSR.
248
323
  */
249
324
 
250
325
  interface MergeOptions {
@@ -254,7 +329,14 @@ interface MergeOptions {
254
329
  }
255
330
  /**
256
331
  * createTwMerge — returns a conflict-aware merge function.
257
- * Native-only: uses Rust `tw_merge_many`; throws if native binding unavailable.
332
+ * Native-first: uses Rust `tw_merge_many` when available.
333
+ * Browser fallback: simple join without conflict resolution.
334
+ *
335
+ * IMPORTANT: The browser fallback must produce output identical to the server
336
+ * (Rust) path to avoid React hydration mismatches. For static base classes this
337
+ * is fine because they are pre-resolved at build time. For runtime className
338
+ * overrides passed by the consumer, the join order must be stable and
339
+ * deterministic on both sides.
258
340
  *
259
341
  * Note: `prefix` and `separator` options are not supported in native mode
260
342
  * (Tailwind v3/v4 defaults are used).
@@ -430,7 +512,7 @@ interface StyledSystemConfig<T extends SystemTokenMap = SystemTokenMap, C extend
430
512
  /** If true, auto-inject token CSS vars into :root on init. Default: true */
431
513
  injectTokens?: boolean;
432
514
  }
433
- type SystemComponentFactory<C extends SystemComponentConfig> = (overrides?: Partial<C>) => TwStyledComponent<Record<string, unknown>>;
515
+ type SystemComponentFactory<C extends SystemComponentConfig> = (overrides?: Partial<C>) => TwStyledComponent<ComponentConfig, string>;
434
516
  type StyledSystemInstance<T extends SystemTokenMap, C extends Record<string, SystemComponentConfig>> = {
435
517
  [K in keyof C]: SystemComponentFactory<C[K]>;
436
518
  } & {