tailwind-styled-v4 5.0.0 → 5.0.2

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 (180) hide show
  1. package/CHANGELOG.md +398 -0
  2. package/LICENSE +21 -0
  3. package/README.md +532 -0
  4. package/dist/analyzer.d.mts +114 -0
  5. package/dist/analyzer.d.ts +114 -0
  6. package/dist/analyzer.js +6808 -0
  7. package/dist/analyzer.js.map +1 -0
  8. package/dist/analyzer.mjs +6798 -0
  9. package/dist/analyzer.mjs.map +1 -0
  10. package/dist/{animate.d.cts → animate.d.mts} +3 -30
  11. package/dist/animate.d.ts +3 -30
  12. package/dist/animate.js +7096 -352
  13. package/dist/animate.js.map +1 -1
  14. package/dist/animate.mjs +7482 -0
  15. package/dist/animate.mjs.map +1 -0
  16. package/dist/atomic.d.mts +18 -0
  17. package/dist/atomic.d.ts +18 -0
  18. package/dist/atomic.js +191 -0
  19. package/dist/atomic.js.map +1 -0
  20. package/dist/atomic.mjs +185 -0
  21. package/dist/atomic.mjs.map +1 -0
  22. package/dist/cli.d.mts +1 -0
  23. package/dist/cli.d.ts +1 -0
  24. package/dist/cli.js +45008 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/cli.mjs +44980 -0
  27. package/dist/cli.mjs.map +1 -0
  28. package/dist/compiler.d.mts +1009 -0
  29. package/dist/compiler.d.ts +1009 -0
  30. package/dist/compiler.js +4937 -0
  31. package/dist/compiler.js.map +1 -0
  32. package/dist/compiler.mjs +4862 -0
  33. package/dist/compiler.mjs.map +1 -0
  34. package/dist/dashboard.d.mts +272 -0
  35. package/dist/dashboard.d.ts +272 -0
  36. package/dist/dashboard.js +249 -0
  37. package/dist/dashboard.js.map +1 -0
  38. package/dist/dashboard.mjs +239 -0
  39. package/dist/dashboard.mjs.map +1 -0
  40. package/dist/devtools.js +171 -158
  41. package/dist/devtools.js.map +1 -1
  42. package/dist/{devtools.cjs → devtools.mjs} +166 -167
  43. package/dist/devtools.mjs.map +1 -0
  44. package/dist/engine.d.mts +398 -0
  45. package/dist/engine.d.ts +398 -0
  46. package/dist/engine.js +19264 -0
  47. package/dist/engine.js.map +1 -0
  48. package/dist/engine.mjs +19227 -0
  49. package/dist/engine.mjs.map +1 -0
  50. package/dist/{index.d.cts → index.d.mts} +12 -5
  51. package/dist/index.d.ts +12 -5
  52. package/dist/index.js +7178 -27
  53. package/dist/index.js.map +1 -1
  54. package/dist/index.mjs +8408 -0
  55. package/dist/index.mjs.map +1 -0
  56. package/dist/liveTokenEngine-DYN3Zale.d.mts +34 -0
  57. package/dist/liveTokenEngine-DYN3Zale.d.ts +34 -0
  58. package/dist/{next.d.cts → next.d.mts} +2 -1
  59. package/dist/next.d.ts +2 -1
  60. package/dist/next.js +24027 -28
  61. package/dist/next.js.map +1 -1
  62. package/dist/next.mjs +24232 -0
  63. package/dist/next.mjs.map +1 -0
  64. package/dist/plugin.d.mts +90 -0
  65. package/dist/plugin.d.ts +90 -0
  66. package/dist/plugin.js +185 -0
  67. package/dist/plugin.js.map +1 -0
  68. package/dist/plugin.mjs +174 -0
  69. package/dist/plugin.mjs.map +1 -0
  70. package/dist/pluginRegistry.d.mts +83 -0
  71. package/dist/pluginRegistry.d.ts +83 -0
  72. package/dist/pluginRegistry.js +303 -0
  73. package/dist/pluginRegistry.js.map +1 -0
  74. package/dist/pluginRegistry.mjs +298 -0
  75. package/dist/pluginRegistry.mjs.map +1 -0
  76. package/dist/preset.js +9 -4
  77. package/dist/preset.js.map +1 -1
  78. package/dist/{preset.cjs → preset.mjs} +5 -14
  79. package/dist/preset.mjs.map +1 -0
  80. package/dist/rspack.d.mts +33 -0
  81. package/dist/rspack.d.ts +33 -0
  82. package/dist/rspack.js +66 -0
  83. package/dist/rspack.js.map +1 -0
  84. package/dist/rspack.mjs +55 -0
  85. package/dist/rspack.mjs.map +1 -0
  86. package/dist/runtime.d.mts +62 -0
  87. package/dist/runtime.d.ts +62 -0
  88. package/dist/runtime.js +455 -0
  89. package/dist/runtime.js.map +1 -0
  90. package/dist/runtime.mjs +436 -0
  91. package/dist/runtime.mjs.map +1 -0
  92. package/dist/runtimeCss.d.mts +65 -0
  93. package/dist/runtimeCss.d.ts +65 -0
  94. package/dist/{css.cjs → runtimeCss.js} +71 -4
  95. package/dist/runtimeCss.js.map +1 -0
  96. package/dist/{css.js → runtimeCss.mjs} +66 -5
  97. package/dist/runtimeCss.mjs.map +1 -0
  98. package/dist/scanner.d.mts +25 -0
  99. package/dist/scanner.d.ts +25 -0
  100. package/dist/scanner.js +5774 -0
  101. package/dist/scanner.js.map +1 -0
  102. package/dist/scanner.mjs +5760 -0
  103. package/dist/scanner.mjs.map +1 -0
  104. package/dist/shared.d.mts +85 -0
  105. package/dist/shared.d.ts +85 -0
  106. package/dist/shared.js +255 -0
  107. package/dist/shared.js.map +1 -0
  108. package/dist/shared.mjs +233 -0
  109. package/dist/shared.mjs.map +1 -0
  110. package/dist/storybookAddon.d.mts +108 -0
  111. package/dist/storybookAddon.d.ts +108 -0
  112. package/dist/storybookAddon.js +95 -0
  113. package/dist/storybookAddon.js.map +1 -0
  114. package/dist/storybookAddon.mjs +88 -0
  115. package/dist/storybookAddon.mjs.map +1 -0
  116. package/dist/svelte.d.mts +114 -0
  117. package/dist/svelte.d.ts +114 -0
  118. package/dist/svelte.js +67 -0
  119. package/dist/svelte.js.map +1 -0
  120. package/dist/svelte.mjs +59 -0
  121. package/dist/svelte.mjs.map +1 -0
  122. package/dist/testing.d.mts +185 -0
  123. package/dist/testing.d.ts +185 -0
  124. package/dist/testing.js +173 -0
  125. package/dist/testing.js.map +1 -0
  126. package/dist/testing.mjs +158 -0
  127. package/dist/testing.mjs.map +1 -0
  128. package/dist/theme.d.mts +188 -0
  129. package/dist/theme.d.ts +188 -0
  130. package/dist/theme.js +334 -0
  131. package/dist/theme.js.map +1 -0
  132. package/dist/theme.mjs +311 -0
  133. package/dist/theme.mjs.map +1 -0
  134. package/dist/tsconfig.tsbuildinfo +1 -0
  135. package/dist/types-DXr2PmGP.d.mts +31 -0
  136. package/dist/types-DXr2PmGP.d.ts +31 -0
  137. package/dist/vite.js +29611 -17
  138. package/dist/vite.js.map +1 -1
  139. package/dist/vite.mjs +29712 -0
  140. package/dist/vite.mjs.map +1 -0
  141. package/dist/vue.d.mts +89 -0
  142. package/dist/vue.d.ts +89 -0
  143. package/dist/vue.js +104 -0
  144. package/dist/vue.js.map +1 -0
  145. package/dist/vue.mjs +96 -0
  146. package/dist/vue.mjs.map +1 -0
  147. package/package.json +170 -64
  148. package/dist/animate.cjs +0 -771
  149. package/dist/animate.cjs.map +0 -1
  150. package/dist/chunk-VZEJV27B.js +0 -11
  151. package/dist/chunk-VZEJV27B.js.map +0 -1
  152. package/dist/chunk-Y5D3E72P.cjs +0 -13
  153. package/dist/chunk-Y5D3E72P.cjs.map +0 -1
  154. package/dist/css.cjs.map +0 -1
  155. package/dist/css.d.cts +0 -30
  156. package/dist/css.d.ts +0 -30
  157. package/dist/css.js.map +0 -1
  158. package/dist/devtools.cjs.map +0 -1
  159. package/dist/index.cjs +0 -1353
  160. package/dist/index.cjs.map +0 -1
  161. package/dist/next.cjs +0 -248
  162. package/dist/next.cjs.map +0 -1
  163. package/dist/preset.cjs.map +0 -1
  164. package/dist/turbopackLoader.cjs +0 -37
  165. package/dist/turbopackLoader.cjs.map +0 -1
  166. package/dist/turbopackLoader.d.cts +0 -12
  167. package/dist/turbopackLoader.d.ts +0 -12
  168. package/dist/turbopackLoader.js +0 -35
  169. package/dist/turbopackLoader.js.map +0 -1
  170. package/dist/vite.cjs +0 -138
  171. package/dist/vite.cjs.map +0 -1
  172. package/dist/webpackLoader.cjs +0 -51
  173. package/dist/webpackLoader.cjs.map +0 -1
  174. package/dist/webpackLoader.d.cts +0 -17
  175. package/dist/webpackLoader.d.ts +0 -17
  176. package/dist/webpackLoader.js +0 -49
  177. package/dist/webpackLoader.js.map +0 -1
  178. /package/dist/{devtools.d.cts → devtools.d.mts} +0 -0
  179. /package/dist/{preset.d.cts → preset.d.mts} +0 -0
  180. /package/dist/{vite.d.cts → vite.d.mts} +0 -0
@@ -0,0 +1,233 @@
1
+ import fs from 'fs';
2
+ import { createRequire } from 'module';
3
+ import os from 'os';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { createHash } from 'crypto';
7
+
8
+ /* tailwind-styled-v4 v5.0.1 | MIT | https://github.com/dictionar32/tailwind-styled-v4 */
9
+
10
+ // packages/shared/src/cache.ts
11
+ var LRUCache = class {
12
+ constructor(max = 256, ttlMs = null) {
13
+ this.map = /* @__PURE__ */ new Map();
14
+ this.max = max;
15
+ this.ttlMs = ttlMs;
16
+ }
17
+ get(key) {
18
+ const entry = this.map.get(key);
19
+ if (!entry) return void 0;
20
+ if (this.ttlMs !== null && Date.now() - entry.ts > this.ttlMs) {
21
+ this.map.delete(key);
22
+ return void 0;
23
+ }
24
+ this.map.delete(key);
25
+ this.map.set(key, entry);
26
+ return entry.value;
27
+ }
28
+ set(key, value) {
29
+ if (this.map.has(key)) this.map.delete(key);
30
+ else if (this.map.size >= this.max) {
31
+ this.map.delete(this.map.keys().next().value);
32
+ }
33
+ this.map.set(key, { value, ts: Date.now() });
34
+ }
35
+ has(key) {
36
+ return this.get(key) !== void 0;
37
+ }
38
+ delete(key) {
39
+ this.map.delete(key);
40
+ }
41
+ clear() {
42
+ this.map.clear();
43
+ }
44
+ get size() {
45
+ return this.map.size;
46
+ }
47
+ keys() {
48
+ return this.map.keys();
49
+ }
50
+ *values() {
51
+ for (const entry of this.map.values()) {
52
+ yield entry.value;
53
+ }
54
+ }
55
+ *entries() {
56
+ for (const [key, entry] of this.map.entries()) {
57
+ yield [key, entry.value];
58
+ }
59
+ }
60
+ };
61
+ function getPlatformExtension() {
62
+ const platform = os.platform();
63
+ switch (platform) {
64
+ case "win32":
65
+ return ".node";
66
+ case "darwin":
67
+ return ".dylib";
68
+ case "linux":
69
+ return ".so";
70
+ default:
71
+ return ".node";
72
+ }
73
+ }
74
+ function formatErrorMessage(error) {
75
+ return error instanceof Error ? error.message : String(error);
76
+ }
77
+ function resolveRuntimeDir(dirnameValue, moduleImportUrl) {
78
+ if (typeof dirnameValue === "string" && dirnameValue.length > 0) return dirnameValue;
79
+ return path.dirname(fileURLToPath(moduleImportUrl));
80
+ }
81
+ function resolveNativeBindingCandidates(options) {
82
+ const out = [];
83
+ const envVarNames = options.envVarNames ?? ["TWS_NATIVE_PATH"];
84
+ for (const envVarName of envVarNames) {
85
+ const raw = process.env[envVarName]?.trim();
86
+ if (!raw) continue;
87
+ const resolved = path.resolve(raw);
88
+ if (options.enforceNodeExtensionForEnvPath) {
89
+ if (path.extname(resolved).toLowerCase() !== ".node") {
90
+ throw new Error(
91
+ `Invalid native binding path from ${envVarName}="${raw}". Expected a .node file.`
92
+ );
93
+ }
94
+ }
95
+ out.push(resolved);
96
+ }
97
+ if (options.includeDefaultCandidates !== false) {
98
+ const ext = options.platformExtension ?? getPlatformExtension();
99
+ const defaultBindingName = `tailwind_styled_parser${ext}`;
100
+ out.push(path.resolve(process.cwd(), "native", defaultBindingName));
101
+ out.push(path.resolve(options.runtimeDir, "..", "..", "..", "native", defaultBindingName));
102
+ }
103
+ return Array.from(new Set(out));
104
+ }
105
+ function parseDebugToken(namespace, token) {
106
+ if (token === "*" || token === namespace || token === "tailwind-styled:*") return true;
107
+ return token.endsWith("*") && namespace.startsWith(token.slice(0, -1));
108
+ }
109
+ function isDebugNamespaceEnabled(namespace) {
110
+ if (process.env.TWS_DEBUG === "1" || process.env.TAILWIND_STYLED_DEBUG === "1") return true;
111
+ const raw = process.env.DEBUG;
112
+ if (!raw) return false;
113
+ return raw.split(",").map((token) => token.trim()).some((token) => parseDebugToken(namespace, token));
114
+ }
115
+ function createDebugLogger(namespace, label = namespace) {
116
+ const debugEnabled = isDebugNamespaceEnabled(namespace);
117
+ return (message) => {
118
+ if (!debugEnabled) return;
119
+ console.debug(`[${label}] ${message}`);
120
+ };
121
+ }
122
+ function loadNativeBinding(options) {
123
+ const req = createRequire(path.join(options.runtimeDir, "noop.cjs"));
124
+ const loadErrors = [];
125
+ for (const candidate of options.candidates) {
126
+ if (!fs.existsSync(candidate)) continue;
127
+ try {
128
+ const mod = req(candidate);
129
+ if (options.isValid(mod)) {
130
+ return {
131
+ binding: mod,
132
+ loadedPath: candidate,
133
+ loadErrors
134
+ };
135
+ }
136
+ loadErrors.push({
137
+ path: candidate,
138
+ message: options.invalidExportMessage
139
+ });
140
+ } catch (error) {
141
+ loadErrors.push({
142
+ path: candidate,
143
+ message: formatErrorMessage(error)
144
+ });
145
+ }
146
+ }
147
+ return {
148
+ binding: null,
149
+ loadedPath: null,
150
+ loadErrors
151
+ };
152
+ }
153
+
154
+ // packages/shared/src/logger.ts
155
+ var LEVELS = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
156
+ function getEnvLevel() {
157
+ const env = process.env.TWS_LOG_LEVEL?.toLowerCase();
158
+ if (env && env in LEVELS) return env;
159
+ return process.env.TWS_DEBUG_SCANNER === "1" ? "debug" : "info";
160
+ }
161
+ function createLogger(prefix, level) {
162
+ let currentLevel = level ?? getEnvLevel();
163
+ const log = (msgLevel, stream, args) => {
164
+ if (LEVELS[msgLevel] > LEVELS[currentLevel]) return;
165
+ const line = `[${prefix}] ${args.map(String).join(" ")}
166
+ `;
167
+ process[stream].write(line);
168
+ };
169
+ return {
170
+ error: (...a) => log("error", "stderr", a),
171
+ warn: (...a) => log("warn", "stderr", a),
172
+ info: (...a) => log("info", "stdout", a),
173
+ debug: (...a) => log("debug", "stderr", a),
174
+ setLevel: (l) => {
175
+ currentLevel = l;
176
+ }
177
+ };
178
+ }
179
+ var logger = createLogger("tailwind-styled");
180
+ function hashContent(content, algorithm = "md5", length = 8) {
181
+ return createHash(algorithm).update(content).digest("hex").slice(0, length);
182
+ }
183
+ function hashFile(filePath, algorithm = "md5", length = 8) {
184
+ try {
185
+ const content = fs.readFileSync(filePath, "utf8");
186
+ return hashContent(content, algorithm, length);
187
+ } catch {
188
+ return "00000000";
189
+ }
190
+ }
191
+
192
+ // packages/shared/src/timing.ts
193
+ function debounce(fn, ms) {
194
+ let timer = null;
195
+ return ((...args) => {
196
+ if (timer) clearTimeout(timer);
197
+ timer = setTimeout(() => {
198
+ timer = null;
199
+ fn(...args);
200
+ }, ms);
201
+ });
202
+ }
203
+ function throttle(fn, ms) {
204
+ let last = 0;
205
+ return ((...args) => {
206
+ const now = Date.now();
207
+ if (now - last >= ms) {
208
+ last = now;
209
+ fn(...args);
210
+ }
211
+ });
212
+ }
213
+
214
+ // packages/shared/src/version.ts
215
+ function parseVersion(v) {
216
+ const parts = v.replace(/^v/, "").split(".").map((p) => {
217
+ const n = Number(p);
218
+ return Number.isNaN(n) ? 0 : n;
219
+ });
220
+ const [major = 0, minor = 0, patch = 0] = parts;
221
+ return { major, minor, patch };
222
+ }
223
+ function satisfiesMinVersion(version, minVersion) {
224
+ const v = parseVersion(version);
225
+ const min = parseVersion(minVersion);
226
+ if (v.major !== min.major) return v.major > min.major;
227
+ if (v.minor !== min.minor) return v.minor > min.minor;
228
+ return v.patch >= min.patch;
229
+ }
230
+
231
+ export { LRUCache, createDebugLogger, createLogger, debounce, formatErrorMessage, hashContent, hashFile, isDebugNamespaceEnabled, loadNativeBinding, logger, parseVersion, resolveNativeBindingCandidates, resolveRuntimeDir, satisfiesMinVersion, throttle };
232
+ //# sourceMappingURL=shared.mjs.map
233
+ //# sourceMappingURL=shared.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/shared/src/cache.ts","../packages/shared/src/nativeBinding.ts","../packages/shared/src/logger.ts","../packages/shared/src/hash.ts","../packages/shared/src/timing.ts","../packages/shared/src/version.ts"],"names":["fs"],"mappings":"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","file":"shared.mjs","sourcesContent":["/**\n * LRUCache — Least Recently Used cache with optional TTL\n * Centralized from packages/compiler/src/incrementalEngine.ts\n */\nexport class LRUCache<K, V> {\n private readonly max: number\n private readonly ttlMs: number | null\n private readonly map = new Map<K, { value: V; ts: number }>()\n\n constructor(max = 256, ttlMs: number | null = null) {\n this.max = max\n this.ttlMs = ttlMs\n }\n\n get(key: K): V | undefined {\n const entry = this.map.get(key)\n if (!entry) return undefined\n if (this.ttlMs !== null && Date.now() - entry.ts > this.ttlMs) {\n this.map.delete(key)\n return undefined\n }\n // Move to end (most recently used)\n this.map.delete(key)\n this.map.set(key, entry)\n return entry.value\n }\n\n set(key: K, value: V): void {\n if (this.map.has(key)) this.map.delete(key)\n else if (this.map.size >= this.max) {\n // Evict least recently used (first entry)\n this.map.delete(this.map.keys().next().value!)\n }\n this.map.set(key, { value, ts: Date.now() })\n }\n\n has(key: K): boolean {\n return this.get(key) !== undefined\n }\n\n delete(key: K): void {\n this.map.delete(key)\n }\n\n clear(): void {\n this.map.clear()\n }\n\n get size(): number {\n return this.map.size\n }\n\n keys(): IterableIterator<K> {\n return this.map.keys()\n }\n\n *values(): IterableIterator<V> {\n for (const entry of this.map.values()) {\n yield entry.value\n }\n }\n\n *entries(): IterableIterator<[K, V]> {\n for (const [key, entry] of this.map.entries()) {\n yield [key, entry.value]\n }\n }\n}\n","import fs from \"node:fs\"\nimport { createRequire } from \"node:module\"\nimport os from \"node:os\"\nimport path from \"node:path\"\nimport { fileURLToPath } from \"node:url\"\n\nexport type PlatformExtension = \".node\" | \".dll\" | \".dylib\" | \".so\"\n\nexport function getPlatformExtension(): PlatformExtension {\n const platform = os.platform()\n switch (platform) {\n case \"win32\":\n return \".node\"\n case \"darwin\":\n return \".dylib\"\n case \"linux\":\n return \".so\"\n default:\n return \".node\"\n }\n}\n\nexport function checkNativeDisabled(): { disabled: boolean; reason: string | null } {\n if (process.env.TWS_NO_NATIVE === \"1\" || process.env.TWS_NO_NATIVE === \"true\") {\n return {\n disabled: true,\n reason: \"Native bindings disabled via TWS_NO_NATIVE=1\",\n }\n }\n if (process.env.TWS_NO_RUST === \"1\" || process.env.TWS_NO_RUST === \"true\") {\n return {\n disabled: true,\n reason: \"Native bindings disabled via TWS_NO_RUST=1\",\n }\n }\n return { disabled: false, reason: null }\n}\n\nexport interface NativeBindingLoadError {\n path: string\n message: string\n}\n\nexport interface ResolveNativeBindingCandidatesOptions {\n runtimeDir: string\n envVarNames?: string[]\n enforceNodeExtensionForEnvPath?: boolean\n includeDefaultCandidates?: boolean\n platformExtension?: PlatformExtension\n}\n\nexport interface LoadNativeBindingOptions<T> {\n runtimeDir: string\n candidates: string[]\n isValid: (module: unknown) => module is T\n invalidExportMessage: string\n}\n\nexport interface LoadNativeBindingResult<T> {\n binding: T | null\n loadedPath: string | null\n loadErrors: NativeBindingLoadError[]\n}\n\nexport function formatErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nexport function resolveRuntimeDir(\n dirnameValue: string | undefined,\n moduleImportUrl: string\n): string {\n if (typeof dirnameValue === \"string\" && dirnameValue.length > 0) return dirnameValue\n return path.dirname(fileURLToPath(moduleImportUrl))\n}\n\nexport function resolveNativeBindingCandidates(\n options: ResolveNativeBindingCandidatesOptions\n): string[] {\n const out: string[] = []\n const envVarNames = options.envVarNames ?? [\"TWS_NATIVE_PATH\"]\n\n for (const envVarName of envVarNames) {\n const raw = process.env[envVarName]?.trim()\n if (!raw) continue\n const resolved = path.resolve(raw)\n\n if (options.enforceNodeExtensionForEnvPath) {\n if (path.extname(resolved).toLowerCase() !== \".node\") {\n throw new Error(\n `Invalid native binding path from ${envVarName}=\"${raw}\". Expected a .node file.`\n )\n }\n }\n\n out.push(resolved)\n }\n\n if (options.includeDefaultCandidates !== false) {\n const ext = options.platformExtension ?? getPlatformExtension()\n const defaultBindingName = `tailwind_styled_parser${ext}`\n\n out.push(path.resolve(process.cwd(), \"native\", defaultBindingName))\n out.push(path.resolve(options.runtimeDir, \"..\", \"..\", \"..\", \"native\", defaultBindingName))\n }\n\n return Array.from(new Set(out))\n}\n\nfunction parseDebugToken(namespace: string, token: string): boolean {\n if (token === \"*\" || token === namespace || token === \"tailwind-styled:*\") return true\n return token.endsWith(\"*\") && namespace.startsWith(token.slice(0, -1))\n}\n\nexport function isDebugNamespaceEnabled(namespace: string): boolean {\n if (process.env.TWS_DEBUG === \"1\" || process.env.TAILWIND_STYLED_DEBUG === \"1\") return true\n const raw = process.env.DEBUG\n if (!raw) return false\n\n return raw\n .split(\",\")\n .map((token) => token.trim())\n .some((token) => parseDebugToken(namespace, token))\n}\n\nexport function createDebugLogger(namespace: string, label = namespace): (message: string) => void {\n const debugEnabled = isDebugNamespaceEnabled(namespace)\n return (message: string) => {\n if (!debugEnabled) return\n console.debug(`[${label}] ${message}`)\n }\n}\n\nexport function loadNativeBinding<T>(\n options: LoadNativeBindingOptions<T>\n): LoadNativeBindingResult<T> {\n const req = createRequire(path.join(options.runtimeDir, \"noop.cjs\"))\n const loadErrors: NativeBindingLoadError[] = []\n\n for (const candidate of options.candidates) {\n if (!fs.existsSync(candidate)) continue\n try {\n const mod = req(candidate)\n if (options.isValid(mod)) {\n return {\n binding: mod,\n loadedPath: candidate,\n loadErrors,\n }\n }\n loadErrors.push({\n path: candidate,\n message: options.invalidExportMessage,\n })\n } catch (error) {\n loadErrors.push({\n path: candidate,\n message: formatErrorMessage(error),\n })\n }\n }\n\n return {\n binding: null,\n loadedPath: null,\n loadErrors,\n }\n}\n\nexport function loadNativeBindingOrThrow<T>(\n options: LoadNativeBindingOptions<T> & { bindingName: string }\n): T {\n const disabledCheck = checkNativeDisabled()\n if (disabledCheck.disabled) {\n throw new Error(\n `Native binding '${options.bindingName}' cannot be loaded.\\n${disabledCheck.reason}`\n )\n }\n\n const { bindingName, ...loadOptions } = options\n const { binding, loadErrors } = loadNativeBinding<T>(loadOptions)\n\n if (binding) {\n return binding\n }\n\n const lines = [\n `FATAL: Native binding '${bindingName}' not found.`,\n \"\",\n \"This package requires native Rust bindings.\",\n \"The binding was not found in any of these paths:\",\n ...loadOptions.candidates.map((p) => ` - ${p}`),\n \"\",\n ]\n\n if (loadErrors.length > 0) {\n lines.push(\"Load errors:\")\n for (const error of loadErrors) {\n lines.push(` - ${error.path}: ${error.message}`)\n }\n lines.push(\"\")\n }\n\n lines.push(\n \"Resolution steps:\",\n \"\",\n \"1. Build the native Rust module:\",\n \" npm run build:rust\",\n \"\",\n \"2. Or install pre-built binaries:\",\n \" npm install\",\n \"\",\n \"3. Override with environment variable:\",\n \" TWS_NATIVE_PATH=/path/to/tailwind_styled_parser.node\",\n \"\",\n \"4. Disable native bindings (use JS fallback):\",\n \" TWS_NO_NATIVE=1\",\n \"\",\n \"For CI/CD environments, ensure Rust toolchain is installed and\",\n \"'npm run build:rust' is executed before running tests or building.\"\n )\n\n throw new Error(lines.join(\"\\n\"))\n}\n","/**\n * Centralized logger — replaces scattered console.log/warn/error calls\n * across packages.\n */\nexport type LogLevel = \"silent\" | \"error\" | \"warn\" | \"info\" | \"debug\"\n\nconst LEVELS: Record<LogLevel, number> = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 }\n\nfunction getEnvLevel(): LogLevel {\n const env = process.env.TWS_LOG_LEVEL?.toLowerCase()\n if (env && env in LEVELS) return env as LogLevel\n return process.env.TWS_DEBUG_SCANNER === \"1\" ? \"debug\" : \"info\"\n}\n\nexport interface Logger {\n error(...args: unknown[]): void\n warn(...args: unknown[]): void\n info(...args: unknown[]): void\n debug(...args: unknown[]): void\n setLevel(level: LogLevel): void\n}\n\nexport function createLogger(prefix: string, level?: LogLevel): Logger {\n let currentLevel = level ?? getEnvLevel()\n\n const log = (msgLevel: LogLevel, stream: \"stdout\" | \"stderr\", args: unknown[]) => {\n if (LEVELS[msgLevel] > LEVELS[currentLevel]) return\n const line = `[${prefix}] ${args.map(String).join(\" \")}\\n`\n process[stream].write(line)\n }\n\n return {\n error: (...a) => log(\"error\", \"stderr\", a),\n warn: (...a) => log(\"warn\", \"stderr\", a),\n info: (...a) => log(\"info\", \"stdout\", a),\n debug: (...a) => log(\"debug\", \"stderr\", a),\n setLevel: (l) => {\n currentLevel = l\n },\n }\n}\n\nexport const logger = createLogger(\"tailwind-styled\")\n","/**\n * Centralized hash utilities\n * Replaces duplicated crypto.createHash() calls across packages\n */\nimport { createHash } from \"node:crypto\"\nimport fs from \"node:fs\"\n\n/** Hash a string content → short hex string */\nexport function hashContent(content: string, algorithm = \"md5\", length = 8): string {\n return createHash(algorithm).update(content).digest(\"hex\").slice(0, length)\n}\n\n/** Hash a file's content → short hex string */\nexport function hashFile(filePath: string, algorithm = \"md5\", length = 8): string {\n try {\n const content = fs.readFileSync(filePath, \"utf8\")\n return hashContent(content, algorithm, length)\n } catch {\n return \"00000000\"\n }\n}\n","/** Debounce: delay fn execution until after `ms` ms of inactivity */\nexport function debounce<T extends (...args: any[]) => void>(fn: T, ms: number): T {\n let timer: ReturnType<typeof setTimeout> | null = null\n return ((...args: any[]) => {\n if (timer) clearTimeout(timer)\n timer = setTimeout(() => {\n timer = null\n fn(...args)\n }, ms)\n }) as T\n}\n\n/** Throttle: execute fn at most once per `ms` ms */\nexport function throttle<T extends (...args: any[]) => void>(fn: T, ms: number): T {\n let last = 0\n return ((...args: any[]) => {\n const now = Date.now()\n if (now - last >= ms) {\n last = now\n fn(...args)\n }\n }) as T\n}\n","/** Parse semver string → { major, minor, patch } */\nexport function parseVersion(v: string): { major: number; minor: number; patch: number } {\n const parts = v\n .replace(/^v/, \"\")\n .split(\".\")\n .map((p) => {\n const n = Number(p)\n return Number.isNaN(n) ? 0 : n\n })\n const [major = 0, minor = 0, patch = 0] = parts\n return { major, minor, patch }\n}\n\n/** Check if version satisfies minimum (major.minor) */\nexport function satisfiesMinVersion(version: string, minVersion: string): boolean {\n const v = parseVersion(version)\n const min = parseVersion(minVersion)\n if (v.major !== min.major) return v.major > min.major\n if (v.minor !== min.minor) return v.minor > min.minor\n return v.patch >= min.patch\n}\n"]}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * tailwind-styled-v4 — Storybook Addon
3
+ *
4
+ * Integrasi Storybook untuk komponen tw().
5
+ * Fitur:
6
+ * - withTailwindStyled decorator: inject className ke story
7
+ * - generateArgTypes: auto-generate controls dari ComponentConfig
8
+ * - enumerateVariantProps: buat semua kombinasi variant untuk testing
9
+ *
10
+ * @example
11
+ * // .storybook/preview.ts
12
+ * import { withTailwindStyled } from '@tailwind-styled/storybook-addon'
13
+ * export const decorators = [withTailwindStyled]
14
+ *
15
+ * // Button.stories.ts
16
+ * import { generateArgTypes } from '@tailwind-styled/storybook-addon'
17
+ * import { buttonConfig } from './Button'
18
+ *
19
+ * export default {
20
+ * title: 'Components/Button',
21
+ * component: Button,
22
+ * argTypes: generateArgTypes(buttonConfig),
23
+ * }
24
+ */
25
+ type VariantMatrix = Record<string, Array<string | number | boolean>>;
26
+ interface ComponentConfig {
27
+ base?: string;
28
+ variants?: Record<string, Record<string, string>>;
29
+ defaultVariants?: Record<string, string>;
30
+ compoundVariants?: Array<{
31
+ class: string;
32
+ [key: string]: any;
33
+ }>;
34
+ }
35
+ /**
36
+ * Enumerate semua kombinasi variant dari matrix.
37
+ *
38
+ * @example
39
+ * enumerateVariantProps({ size: ['sm','lg'], intent: ['primary','danger'] })
40
+ * // → [{ size:'sm', intent:'primary' }, { size:'sm', intent:'danger' }, ...]
41
+ */
42
+ declare function enumerateVariantProps(matrix: VariantMatrix): Array<Record<string, string | number | boolean>>;
43
+ /**
44
+ * Generate Storybook argTypes dari ComponentConfig.
45
+ * Otomatis membuat kontrol dropdown untuk setiap variant.
46
+ *
47
+ * @example
48
+ * export default {
49
+ * title: 'Components/Button',
50
+ * argTypes: generateArgTypes({
51
+ * variants: {
52
+ * intent: { primary: '...', danger: '...' },
53
+ * size: { sm: '...', md: '...', lg: '...' },
54
+ * },
55
+ * defaultVariants: { intent: 'primary', size: 'md' },
56
+ * })
57
+ * }
58
+ */
59
+ declare function generateArgTypes(config: ComponentConfig): Record<string, unknown>;
60
+ /**
61
+ * Generate default args dari ComponentConfig.
62
+ *
63
+ * @example
64
+ * export default {
65
+ * args: generateDefaultArgs(buttonConfig),
66
+ * }
67
+ */
68
+ declare function generateDefaultArgs(config: ComponentConfig): Record<string, string>;
69
+ /**
70
+ * Storybook decorator yang inject className dari args ke story.
71
+ * Compatible dengan Storybook 7+ (CSF3).
72
+ *
73
+ * @example
74
+ * // .storybook/preview.ts
75
+ * import { withTailwindStyled } from '@tailwind-styled/storybook-addon'
76
+ * export const decorators = [withTailwindStyled]
77
+ */
78
+ declare function withTailwindStyled(StoryFn: () => unknown, context: {
79
+ args?: Record<string, unknown>;
80
+ parameters?: {
81
+ tailwindStyled?: {
82
+ wrapperClass?: string;
83
+ padding?: string;
84
+ };
85
+ };
86
+ }): unknown;
87
+ /**
88
+ * Buat "All Variants" story yang menampilkan semua kombinasi variant.
89
+ * Berguna untuk visual regression testing.
90
+ *
91
+ * @example
92
+ * export const AllVariants = createAllVariantsStory(Button, buttonConfig)
93
+ */
94
+ declare function createVariantStoryArgs(config: ComponentConfig): {
95
+ combinations: Array<Record<string, string | number | boolean>>;
96
+ matrix: VariantMatrix;
97
+ };
98
+ /**
99
+ * Extract class string untuk variant props dari config.
100
+ * Berguna untuk manual class lookup di stories.
101
+ *
102
+ * @example
103
+ * const cls = getVariantClass(buttonConfig, { intent: 'primary', size: 'lg' })
104
+ * // → 'bg-blue-500 text-white h-12 text-lg'
105
+ */
106
+ declare function getVariantClass(config: ComponentConfig, props: Record<string, string>): string;
107
+
108
+ export { type ComponentConfig, type VariantMatrix, createVariantStoryArgs, enumerateVariantProps, generateArgTypes, generateDefaultArgs, getVariantClass, withTailwindStyled };
@@ -0,0 +1,108 @@
1
+ /**
2
+ * tailwind-styled-v4 — Storybook Addon
3
+ *
4
+ * Integrasi Storybook untuk komponen tw().
5
+ * Fitur:
6
+ * - withTailwindStyled decorator: inject className ke story
7
+ * - generateArgTypes: auto-generate controls dari ComponentConfig
8
+ * - enumerateVariantProps: buat semua kombinasi variant untuk testing
9
+ *
10
+ * @example
11
+ * // .storybook/preview.ts
12
+ * import { withTailwindStyled } from '@tailwind-styled/storybook-addon'
13
+ * export const decorators = [withTailwindStyled]
14
+ *
15
+ * // Button.stories.ts
16
+ * import { generateArgTypes } from '@tailwind-styled/storybook-addon'
17
+ * import { buttonConfig } from './Button'
18
+ *
19
+ * export default {
20
+ * title: 'Components/Button',
21
+ * component: Button,
22
+ * argTypes: generateArgTypes(buttonConfig),
23
+ * }
24
+ */
25
+ type VariantMatrix = Record<string, Array<string | number | boolean>>;
26
+ interface ComponentConfig {
27
+ base?: string;
28
+ variants?: Record<string, Record<string, string>>;
29
+ defaultVariants?: Record<string, string>;
30
+ compoundVariants?: Array<{
31
+ class: string;
32
+ [key: string]: any;
33
+ }>;
34
+ }
35
+ /**
36
+ * Enumerate semua kombinasi variant dari matrix.
37
+ *
38
+ * @example
39
+ * enumerateVariantProps({ size: ['sm','lg'], intent: ['primary','danger'] })
40
+ * // → [{ size:'sm', intent:'primary' }, { size:'sm', intent:'danger' }, ...]
41
+ */
42
+ declare function enumerateVariantProps(matrix: VariantMatrix): Array<Record<string, string | number | boolean>>;
43
+ /**
44
+ * Generate Storybook argTypes dari ComponentConfig.
45
+ * Otomatis membuat kontrol dropdown untuk setiap variant.
46
+ *
47
+ * @example
48
+ * export default {
49
+ * title: 'Components/Button',
50
+ * argTypes: generateArgTypes({
51
+ * variants: {
52
+ * intent: { primary: '...', danger: '...' },
53
+ * size: { sm: '...', md: '...', lg: '...' },
54
+ * },
55
+ * defaultVariants: { intent: 'primary', size: 'md' },
56
+ * })
57
+ * }
58
+ */
59
+ declare function generateArgTypes(config: ComponentConfig): Record<string, unknown>;
60
+ /**
61
+ * Generate default args dari ComponentConfig.
62
+ *
63
+ * @example
64
+ * export default {
65
+ * args: generateDefaultArgs(buttonConfig),
66
+ * }
67
+ */
68
+ declare function generateDefaultArgs(config: ComponentConfig): Record<string, string>;
69
+ /**
70
+ * Storybook decorator yang inject className dari args ke story.
71
+ * Compatible dengan Storybook 7+ (CSF3).
72
+ *
73
+ * @example
74
+ * // .storybook/preview.ts
75
+ * import { withTailwindStyled } from '@tailwind-styled/storybook-addon'
76
+ * export const decorators = [withTailwindStyled]
77
+ */
78
+ declare function withTailwindStyled(StoryFn: () => unknown, context: {
79
+ args?: Record<string, unknown>;
80
+ parameters?: {
81
+ tailwindStyled?: {
82
+ wrapperClass?: string;
83
+ padding?: string;
84
+ };
85
+ };
86
+ }): unknown;
87
+ /**
88
+ * Buat "All Variants" story yang menampilkan semua kombinasi variant.
89
+ * Berguna untuk visual regression testing.
90
+ *
91
+ * @example
92
+ * export const AllVariants = createAllVariantsStory(Button, buttonConfig)
93
+ */
94
+ declare function createVariantStoryArgs(config: ComponentConfig): {
95
+ combinations: Array<Record<string, string | number | boolean>>;
96
+ matrix: VariantMatrix;
97
+ };
98
+ /**
99
+ * Extract class string untuk variant props dari config.
100
+ * Berguna untuk manual class lookup di stories.
101
+ *
102
+ * @example
103
+ * const cls = getVariantClass(buttonConfig, { intent: 'primary', size: 'lg' })
104
+ * // → 'bg-blue-500 text-white h-12 text-lg'
105
+ */
106
+ declare function getVariantClass(config: ComponentConfig, props: Record<string, string>): string;
107
+
108
+ export { type ComponentConfig, type VariantMatrix, createVariantStoryArgs, enumerateVariantProps, generateArgTypes, generateDefaultArgs, getVariantClass, withTailwindStyled };
@@ -0,0 +1,95 @@
1
+ 'use strict';
2
+
3
+ /* tailwind-styled-v4 v5.0.1 | MIT | https://github.com/dictionar32/tailwind-styled-v4 */
4
+
5
+ // packages/storybook-addon/src/index.ts
6
+ function enumerateVariantProps(matrix) {
7
+ const keys = Object.keys(matrix);
8
+ if (keys.length === 0) return [{}];
9
+ const result = [];
10
+ function walk(index, current) {
11
+ if (index >= keys.length) {
12
+ result.push({ ...current });
13
+ return;
14
+ }
15
+ const key = keys[index];
16
+ for (const value of matrix[key] ?? []) {
17
+ current[key] = value;
18
+ walk(index + 1, current);
19
+ }
20
+ }
21
+ walk(0, {});
22
+ return result;
23
+ }
24
+ function generateArgTypes(config) {
25
+ if (!config.variants) return {};
26
+ const argTypes = {};
27
+ for (const [variantKey, variantValues] of Object.entries(config.variants)) {
28
+ const options = Object.keys(variantValues);
29
+ const defaultValue = config.defaultVariants?.[variantKey];
30
+ argTypes[variantKey] = {
31
+ control: { type: "select" },
32
+ options,
33
+ defaultValue,
34
+ description: `Variant: **${variantKey}**`,
35
+ table: {
36
+ type: { summary: options.join(" | ") },
37
+ defaultValue: defaultValue ? { summary: defaultValue } : void 0,
38
+ category: "Variants"
39
+ }
40
+ };
41
+ }
42
+ return argTypes;
43
+ }
44
+ function generateDefaultArgs(config) {
45
+ return { ...config.defaultVariants ?? void 0 };
46
+ }
47
+ function withTailwindStyled(StoryFn, context) {
48
+ const wrapperClass = context.parameters?.tailwindStyled?.wrapperClass ?? "";
49
+ const padding = context.parameters?.tailwindStyled?.padding ?? "p-8";
50
+ if (typeof document !== "undefined") {
51
+ const wrapper = document.createElement("div");
52
+ wrapper.className = [padding, wrapperClass].filter(Boolean).join(" ");
53
+ return wrapper;
54
+ }
55
+ return StoryFn();
56
+ }
57
+ function createVariantStoryArgs(config) {
58
+ if (!config.variants) return { combinations: [{}], matrix: {} };
59
+ const matrix = {};
60
+ for (const [key, values] of Object.entries(config.variants)) {
61
+ matrix[key] = Object.keys(values);
62
+ }
63
+ return {
64
+ combinations: enumerateVariantProps(matrix),
65
+ matrix
66
+ };
67
+ }
68
+ function getVariantClass(config, props) {
69
+ const classes = [];
70
+ if (config.base) classes.push(config.base);
71
+ if (config.variants) {
72
+ for (const [key, values] of Object.entries(config.variants)) {
73
+ const val = props[key] ?? config.defaultVariants?.[key];
74
+ if (val && values[val]) classes.push(values[val]);
75
+ }
76
+ }
77
+ if (config.compoundVariants) {
78
+ for (const compound of config.compoundVariants) {
79
+ const { class: cls, ...conditions } = compound;
80
+ if (Object.entries(conditions).every(([k, v]) => props[k] === v)) {
81
+ classes.push(cls);
82
+ }
83
+ }
84
+ }
85
+ return classes.join(" ");
86
+ }
87
+
88
+ exports.createVariantStoryArgs = createVariantStoryArgs;
89
+ exports.enumerateVariantProps = enumerateVariantProps;
90
+ exports.generateArgTypes = generateArgTypes;
91
+ exports.generateDefaultArgs = generateDefaultArgs;
92
+ exports.getVariantClass = getVariantClass;
93
+ exports.withTailwindStyled = withTailwindStyled;
94
+ //# sourceMappingURL=storybookAddon.js.map
95
+ //# sourceMappingURL=storybookAddon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../packages/storybook-addon/src/index.ts"],"names":[],"mappings":"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","file":"storybookAddon.js","sourcesContent":["/**\n * tailwind-styled-v4 — Storybook Addon\n *\n * Integrasi Storybook untuk komponen tw().\n * Fitur:\n * - withTailwindStyled decorator: inject className ke story\n * - generateArgTypes: auto-generate controls dari ComponentConfig\n * - enumerateVariantProps: buat semua kombinasi variant untuk testing\n *\n * @example\n * // .storybook/preview.ts\n * import { withTailwindStyled } from '@tailwind-styled/storybook-addon'\n * export const decorators = [withTailwindStyled]\n *\n * // Button.stories.ts\n * import { generateArgTypes } from '@tailwind-styled/storybook-addon'\n * import { buttonConfig } from './Button'\n *\n * export default {\n * title: 'Components/Button',\n * component: Button,\n * argTypes: generateArgTypes(buttonConfig),\n * }\n */\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type VariantMatrix = Record<string, Array<string | number | boolean>>\n\nexport interface ComponentConfig {\n base?: string\n variants?: Record<string, Record<string, string>>\n defaultVariants?: Record<string, string>\n compoundVariants?: Array<{ class: string; [key: string]: any }>\n}\n\n// ─── Variant enumeration (core utility) ──────────────────────────────────────\n\n/**\n * Enumerate semua kombinasi variant dari matrix.\n *\n * @example\n * enumerateVariantProps({ size: ['sm','lg'], intent: ['primary','danger'] })\n * // → [{ size:'sm', intent:'primary' }, { size:'sm', intent:'danger' }, ...]\n */\nexport function enumerateVariantProps(\n matrix: VariantMatrix\n): Array<Record<string, string | number | boolean>> {\n const keys = Object.keys(matrix)\n if (keys.length === 0) return [{}]\n\n const result: Array<Record<string, string | number | boolean>> = []\n\n function walk(index: number, current: Record<string, string | number | boolean>) {\n if (index >= keys.length) {\n result.push({ ...current })\n return\n }\n const key = keys[index]!\n for (const value of matrix[key] ?? []) {\n current[key] = value\n walk(index + 1, current)\n }\n }\n\n walk(0, {})\n return result\n}\n\n// ─── Storybook argTypes generator ─────────────────────────────────────────────\n\n/**\n * Generate Storybook argTypes dari ComponentConfig.\n * Otomatis membuat kontrol dropdown untuk setiap variant.\n *\n * @example\n * export default {\n * title: 'Components/Button',\n * argTypes: generateArgTypes({\n * variants: {\n * intent: { primary: '...', danger: '...' },\n * size: { sm: '...', md: '...', lg: '...' },\n * },\n * defaultVariants: { intent: 'primary', size: 'md' },\n * })\n * }\n */\nexport function generateArgTypes(config: ComponentConfig): Record<string, unknown> {\n if (!config.variants) return {}\n\n const argTypes: Record<string, unknown> = {}\n\n for (const [variantKey, variantValues] of Object.entries(config.variants)) {\n const options = Object.keys(variantValues)\n const defaultValue = config.defaultVariants?.[variantKey]\n\n argTypes[variantKey] = {\n control: { type: \"select\" },\n options,\n defaultValue,\n description: `Variant: **${variantKey}**`,\n table: {\n type: { summary: options.join(\" | \") },\n defaultValue: defaultValue ? { summary: defaultValue } : undefined,\n category: \"Variants\",\n },\n }\n }\n\n return argTypes\n}\n\n/**\n * Generate default args dari ComponentConfig.\n *\n * @example\n * export default {\n * args: generateDefaultArgs(buttonConfig),\n * }\n */\nexport function generateDefaultArgs(config: ComponentConfig): Record<string, string> {\n return { ...(config.defaultVariants ?? undefined) }\n}\n\n// ─── Storybook decorator ───────────────────────────────────────────────────────\n\n/**\n * Storybook decorator yang inject className dari args ke story.\n * Compatible dengan Storybook 7+ (CSF3).\n *\n * @example\n * // .storybook/preview.ts\n * import { withTailwindStyled } from '@tailwind-styled/storybook-addon'\n * export const decorators = [withTailwindStyled]\n */\nexport function withTailwindStyled(\n StoryFn: () => unknown,\n context: {\n args?: Record<string, unknown>\n parameters?: { tailwindStyled?: { wrapperClass?: string; padding?: string } }\n }\n): unknown {\n const wrapperClass = context.parameters?.tailwindStyled?.wrapperClass ?? \"\"\n const padding = context.parameters?.tailwindStyled?.padding ?? \"p-8\"\n\n // Wrap story dalam div dengan class dari parameters\n // Ini memungkinkan dark mode testing, custom backgrounds, dll\n if (typeof document !== \"undefined\") {\n const wrapper = document.createElement(\"div\")\n wrapper.className = [padding, wrapperClass].filter(Boolean).join(\" \")\n return wrapper\n }\n\n return StoryFn()\n}\n\n// ─── Story template helpers ────────────────────────────────────────────────────\n\n/**\n * Buat \"All Variants\" story yang menampilkan semua kombinasi variant.\n * Berguna untuk visual regression testing.\n *\n * @example\n * export const AllVariants = createAllVariantsStory(Button, buttonConfig)\n */\nexport function createVariantStoryArgs(config: ComponentConfig): {\n combinations: Array<Record<string, string | number | boolean>>\n matrix: VariantMatrix\n} {\n if (!config.variants) return { combinations: [{}], matrix: {} }\n\n const matrix: VariantMatrix = {}\n for (const [key, values] of Object.entries(config.variants)) {\n matrix[key] = Object.keys(values)\n }\n\n return {\n combinations: enumerateVariantProps(matrix),\n matrix,\n }\n}\n\n/**\n * Extract class string untuk variant props dari config.\n * Berguna untuk manual class lookup di stories.\n *\n * @example\n * const cls = getVariantClass(buttonConfig, { intent: 'primary', size: 'lg' })\n * // → 'bg-blue-500 text-white h-12 text-lg'\n */\nexport function getVariantClass(config: ComponentConfig, props: Record<string, string>): string {\n const classes: string[] = []\n\n if (config.base) classes.push(config.base)\n\n if (config.variants) {\n for (const [key, values] of Object.entries(config.variants)) {\n const val = props[key] ?? config.defaultVariants?.[key]\n if (val && values[val]) classes.push(values[val])\n }\n }\n\n if (config.compoundVariants) {\n for (const compound of config.compoundVariants) {\n const { class: cls, ...conditions } = compound\n if (Object.entries(conditions).every(([k, v]) => props[k] === v)) {\n classes.push(cls)\n }\n }\n }\n\n return classes.join(\" \")\n}\n"]}