tailwind-styled-v4 4.0.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animate.cjs +754 -235
- package/dist/animate.cjs.map +1 -1
- package/dist/animate.d.cts +55 -99
- package/dist/animate.d.ts +55 -99
- package/dist/animate.js +742 -235
- package/dist/animate.js.map +1 -1
- package/dist/chunk-VZEJV27B.js +11 -0
- package/dist/chunk-VZEJV27B.js.map +1 -0
- package/dist/chunk-Y5D3E72P.cjs +13 -0
- package/dist/chunk-Y5D3E72P.cjs.map +1 -0
- package/dist/css.cjs +61 -11
- package/dist/css.cjs.map +1 -1
- package/dist/css.d.cts +3 -18
- package/dist/css.d.ts +3 -18
- package/dist/css.js +61 -11
- package/dist/css.js.map +1 -1
- package/dist/devtools.cjs +200 -88
- package/dist/devtools.cjs.map +1 -1
- package/dist/devtools.js +200 -88
- package/dist/devtools.js.map +1 -1
- package/dist/index.cjs +430 -135
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +74 -3
- package/dist/index.d.ts +74 -3
- package/dist/index.js +415 -132
- package/dist/index.js.map +1 -1
- package/dist/next.cjs +118 -138
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +28 -19
- package/dist/next.d.ts +28 -19
- package/dist/next.js +111 -131
- package/dist/next.js.map +1 -1
- package/dist/preset.cjs +312 -18
- package/dist/preset.cjs.map +1 -1
- package/dist/preset.d.cts +29 -2
- package/dist/preset.d.ts +29 -2
- package/dist/preset.js +311 -19
- package/dist/preset.js.map +1 -1
- package/dist/turbopackLoader.cjs +24 -2676
- package/dist/turbopackLoader.cjs.map +1 -1
- package/dist/turbopackLoader.d.cts +3 -13
- package/dist/turbopackLoader.d.ts +3 -13
- package/dist/turbopackLoader.js +24 -2670
- package/dist/turbopackLoader.js.map +1 -1
- package/dist/vite.cjs +90 -57
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +35 -6
- package/dist/vite.d.ts +35 -6
- package/dist/vite.js +90 -58
- package/dist/vite.js.map +1 -1
- package/dist/webpackLoader.cjs +27 -2646
- package/dist/webpackLoader.cjs.map +1 -1
- package/dist/webpackLoader.d.cts +3 -10
- package/dist/webpackLoader.d.ts +3 -10
- package/dist/webpackLoader.js +27 -2640
- package/dist/webpackLoader.js.map +1 -1
- package/package.json +31 -28
- package/dist/astTransform-ua-eapqs.d.cts +0 -41
- package/dist/astTransform-ua-eapqs.d.ts +0 -41
- package/dist/compiler.cjs +0 -3594
- package/dist/compiler.cjs.map +0 -1
- package/dist/compiler.d.cts +0 -716
- package/dist/compiler.d.ts +0 -716
- package/dist/compiler.js +0 -3535
- package/dist/compiler.js.map +0 -1
- package/dist/plugins.cjs +0 -396
- package/dist/plugins.cjs.map +0 -1
- package/dist/plugins.d.cts +0 -231
- package/dist/plugins.d.ts +0 -231
- package/dist/plugins.js +0 -381
- package/dist/plugins.js.map +0 -1
- package/dist/theme.cjs +0 -154
- package/dist/theme.cjs.map +0 -1
- package/dist/theme.d.cts +0 -181
- package/dist/theme.d.ts +0 -181
- package/dist/theme.js +0 -148
- package/dist/theme.js.map +0 -1
package/dist/compiler.d.cts
DELETED
|
@@ -1,716 +0,0 @@
|
|
|
1
|
-
export { T as TransformOptions, a as TransformResult, t as transformSource } from './astTransform-ua-eapqs.cjs';
|
|
2
|
-
|
|
3
|
-
declare function hasTwUsage(source: string): boolean;
|
|
4
|
-
declare function isDynamic(content: string): boolean;
|
|
5
|
-
declare function isServerComponent(source: string): boolean;
|
|
6
|
-
declare function hasInteractiveFeatures(content: string): boolean;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* tailwind-styled-v4 — Atomic CSS Mode (Optional)
|
|
10
|
-
*
|
|
11
|
-
* Mode opsional yang mengubah Tailwind classes menjadi atomic CSS rules.
|
|
12
|
-
* Mirip konsep StyleX dari Meta — setiap class menghasilkan satu CSS rule.
|
|
13
|
-
*
|
|
14
|
-
* Keuntungan:
|
|
15
|
-
* - CSS global deduplicated (p-4 hanya satu rule di seluruh app)
|
|
16
|
-
* - Bundle CSS lebih kecil untuk app besar
|
|
17
|
-
* - Zero duplicate styles
|
|
18
|
-
*
|
|
19
|
-
* Mode ini TIDAK mengganti Tailwind — tetap pakai Tailwind utilities,
|
|
20
|
-
* hanya menambahkan layer extraction untuk SSR streaming.
|
|
21
|
-
*
|
|
22
|
-
* Usage:
|
|
23
|
-
* withTailwindStyled({ atomic: true })(nextConfig)
|
|
24
|
-
*/
|
|
25
|
-
interface AtomicRule {
|
|
26
|
-
/** Original Tailwind class */
|
|
27
|
-
twClass: string;
|
|
28
|
-
/** Generated atomic class name */
|
|
29
|
-
atomicName: string;
|
|
30
|
-
/** CSS property */
|
|
31
|
-
property: string;
|
|
32
|
-
/** CSS value */
|
|
33
|
-
value: string;
|
|
34
|
-
/** Modifier (hover:, md:, etc.) */
|
|
35
|
-
modifier?: string;
|
|
36
|
-
}
|
|
37
|
-
declare function parseAtomicClass(twClass: string): AtomicRule | null;
|
|
38
|
-
declare function generateAtomicCss(rules: AtomicRule[]): string;
|
|
39
|
-
declare function toAtomicClasses(twClasses: string): {
|
|
40
|
-
atomicClasses: string;
|
|
41
|
-
rules: AtomicRule[];
|
|
42
|
-
unknownClasses: string[];
|
|
43
|
-
};
|
|
44
|
-
declare function getAtomicRegistry(): Map<string, AtomicRule>;
|
|
45
|
-
declare function clearAtomicRegistry(): void;
|
|
46
|
-
|
|
47
|
-
declare function extractAllClasses(source: string): string[];
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* tailwind-styled-v4 — classMerger
|
|
51
|
-
*
|
|
52
|
-
* FIX #05: Ganti custom UTILITY_GROUPS resolver dengan twMerge.
|
|
53
|
-
*
|
|
54
|
-
* WHY: Custom regex resolver memiliki banyak edge case yang salah
|
|
55
|
-
* (ring-, text- grouping, dll). tailwind-merge sudah jadi dependency,
|
|
56
|
-
* lebih akurat, dan di-maintain oleh komunitas Tailwind.
|
|
57
|
-
*
|
|
58
|
-
* RESULT: Output compile-time dan runtime kini identik — tidak ada
|
|
59
|
-
* behavior perbedaan antara dev mode dan production build.
|
|
60
|
-
*/
|
|
61
|
-
/**
|
|
62
|
-
* Merge Tailwind classes statically at compile time.
|
|
63
|
-
* Menggunakan tailwind-merge untuk conflict resolution yang akurat.
|
|
64
|
-
*
|
|
65
|
-
* FIX #05: Sebelumnya pakai custom UTILITY_GROUPS regex yang tidak
|
|
66
|
-
* kompatibel dengan tailwind-merge runtime. Sekarang keduanya identik.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* mergeClassesStatic("p-4 p-2 bg-red-500 bg-blue-500")
|
|
70
|
-
* → "p-2 bg-blue-500"
|
|
71
|
-
*
|
|
72
|
-
* mergeClassesStatic("ring-2 ring-4")
|
|
73
|
-
* → "ring-4" ✓ (custom resolver dulu return "ring-2 ring-4" — salah!)
|
|
74
|
-
*/
|
|
75
|
-
declare function mergeClassesStatic(classes: string): string;
|
|
76
|
-
/**
|
|
77
|
-
* Normalize raw class string — trim, dedupe whitespace, join lines.
|
|
78
|
-
*/
|
|
79
|
-
declare function normalizeClasses(raw: string): string;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* tailwind-styled-v4 — Component Hoister
|
|
83
|
-
*
|
|
84
|
-
* Problem: Component yang didefinisikan di dalam fungsi lain
|
|
85
|
-
* akan direcreate setiap render — sangat buruk untuk performa.
|
|
86
|
-
*
|
|
87
|
-
* BEFORE (buruk):
|
|
88
|
-
* export default function Page() {
|
|
89
|
-
* const Box = tw.div`p-4` ← dibuat ulang tiap render!
|
|
90
|
-
* return <Box/>
|
|
91
|
-
* }
|
|
92
|
-
*
|
|
93
|
-
* AFTER (benar):
|
|
94
|
-
* const Box = tw.div`p-4` ← module scope, dibuat sekali
|
|
95
|
-
* export default function Page() {
|
|
96
|
-
* return <Box/>
|
|
97
|
-
* }
|
|
98
|
-
*
|
|
99
|
-
* Hoister mendeteksi pola ini dan memindahkan deklarasi ke module scope.
|
|
100
|
-
*/
|
|
101
|
-
interface HoistResult {
|
|
102
|
-
code: string;
|
|
103
|
-
hoisted: string[];
|
|
104
|
-
warnings: string[];
|
|
105
|
-
}
|
|
106
|
-
declare function hoistComponents(source: string): HoistResult;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* tailwind-styled-v4 — Dead Style Eliminator
|
|
110
|
-
*
|
|
111
|
-
* Build-time analysis yang scan component usage dan hapus variant + class
|
|
112
|
-
* yang tidak pernah dipakai. Hasilnya: CSS output yang sangat kecil.
|
|
113
|
-
*
|
|
114
|
-
* Pipeline:
|
|
115
|
-
* scan all .tsx/.ts files
|
|
116
|
-
* ↓ extract component usage (JSX props)
|
|
117
|
-
* ↓ compare dengan registered variants
|
|
118
|
-
* ↓ mark unused variants as dead
|
|
119
|
-
* ↓ remove from CSS output
|
|
120
|
-
*
|
|
121
|
-
* @example
|
|
122
|
-
* const Button = tw.button({
|
|
123
|
-
* base: "px-4 py-2",
|
|
124
|
-
* variants: {
|
|
125
|
-
* size: { sm: "text-sm", lg: "text-lg", xl: "text-xl" }, // xl never used!
|
|
126
|
-
* intent: { primary: "bg-blue-500", danger: "bg-red-500" }
|
|
127
|
-
* }
|
|
128
|
-
* })
|
|
129
|
-
*
|
|
130
|
-
* // In codebase: only <Button size="sm"> and <Button size="lg"> appear
|
|
131
|
-
* // Eliminator removes: size.xl → saves CSS
|
|
132
|
-
*
|
|
133
|
-
* Result:
|
|
134
|
-
* Before: 3 size variants in CSS
|
|
135
|
-
* After: 2 size variants in CSS (xl eliminated)
|
|
136
|
-
*/
|
|
137
|
-
interface VariantUsage {
|
|
138
|
-
/** Component name */
|
|
139
|
-
component: string;
|
|
140
|
-
/** Which variant props were used with which values */
|
|
141
|
-
usedValues: Record<string, Set<string>>;
|
|
142
|
-
/** Files where component is used */
|
|
143
|
-
usedInFiles: string[];
|
|
144
|
-
}
|
|
145
|
-
interface EliminationReport {
|
|
146
|
-
/** Total unused variant values found */
|
|
147
|
-
unusedCount: number;
|
|
148
|
-
/** Estimated bytes saved */
|
|
149
|
-
bytesSaved: number;
|
|
150
|
-
/** Details per component */
|
|
151
|
-
components: Record<string, {
|
|
152
|
-
usedVariants: Record<string, string[]>;
|
|
153
|
-
unusedVariants: Record<string, string[]>;
|
|
154
|
-
}>;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Extract all JSX component usages from source.
|
|
158
|
-
* Finds: <ComponentName prop="value" /> patterns.
|
|
159
|
-
*/
|
|
160
|
-
declare function extractComponentUsage(source: string): Record<string, Record<string, Set<string>>>;
|
|
161
|
-
/**
|
|
162
|
-
* Scan entire project for component usage.
|
|
163
|
-
*
|
|
164
|
-
* @param dirs - Directories to scan (e.g. ["src"])
|
|
165
|
-
* @param cwd - Project root
|
|
166
|
-
*/
|
|
167
|
-
declare function scanProjectUsage(dirs: string[], cwd?: string): Record<string, Record<string, Set<string>>>;
|
|
168
|
-
interface RegisteredComponent {
|
|
169
|
-
name: string;
|
|
170
|
-
variants: Record<string, Record<string, string>>;
|
|
171
|
-
}
|
|
172
|
-
interface EliminationOptions {
|
|
173
|
-
dirs?: string[];
|
|
174
|
-
cwd?: string;
|
|
175
|
-
registered?: RegisteredComponent[];
|
|
176
|
-
inputCss: string;
|
|
177
|
-
verbose?: boolean;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Run full dead style elimination pipeline.
|
|
181
|
-
*
|
|
182
|
-
* @example
|
|
183
|
-
* const result = await runElimination({
|
|
184
|
-
* dirs: ["src"],
|
|
185
|
-
* inputCss: fs.readFileSync("dist/styles.css", "utf-8"),
|
|
186
|
-
* registered: [...componentConfigs],
|
|
187
|
-
* })
|
|
188
|
-
* fs.writeFileSync("dist/styles.min.css", result.css)
|
|
189
|
-
* console.log(result.report)
|
|
190
|
-
*/
|
|
191
|
-
declare function runElimination(opts: EliminationOptions): {
|
|
192
|
-
css: string;
|
|
193
|
-
report: EliminationReport;
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* tailwind-styled-v4 — Incremental CSS Compiler
|
|
198
|
-
*
|
|
199
|
-
* Hanya compile ulang file yang berubah, bukan semua file.
|
|
200
|
-
* Hasil: hot-reload styling dalam 5–20ms, bukan 3–10s.
|
|
201
|
-
*
|
|
202
|
-
* Pipeline:
|
|
203
|
-
* file watcher detects change
|
|
204
|
-
* ↓ hash check → skip jika file belum berubah
|
|
205
|
-
* ↓ update dependency graph (hapus rule lama, tambah rule baru)
|
|
206
|
-
* ↓ compute CSS diff (only changed rules)
|
|
207
|
-
* ↓ write diff ke output — bukan rewrite seluruh file
|
|
208
|
-
* ↓ hot reload
|
|
209
|
-
*
|
|
210
|
-
* Integrasi ke webpack/turbopack loader:
|
|
211
|
-
* import { incrementalEngine } from "./incrementalEngine"
|
|
212
|
-
* incrementalEngine.processFile(filepath, source, extractedClasses)
|
|
213
|
-
*
|
|
214
|
-
* Cache disimpan di `.tw-cache/` — persist antar build sessions.
|
|
215
|
-
*/
|
|
216
|
-
/** Satu style node dalam dependency graph */
|
|
217
|
-
interface StyleNode {
|
|
218
|
-
/** Tailwind class, e.g. "p-4" */
|
|
219
|
-
twClass: string;
|
|
220
|
-
/** CSS declaration, e.g. "padding: 1rem" */
|
|
221
|
-
declaration: string;
|
|
222
|
-
/** Modifier (pseudo/media), e.g. ":hover" atau "@media (min-width: 768px)" */
|
|
223
|
-
modifier?: string;
|
|
224
|
-
/** Generated atomic class name, e.g. "tw-a1b2" */
|
|
225
|
-
atomicClass: string;
|
|
226
|
-
}
|
|
227
|
-
/** Graph: filepath → style nodes yang dihasilkan file itu */
|
|
228
|
-
type FileDependencyGraph = Map<string, StyleNode[]>;
|
|
229
|
-
/** Diff antara build sebelum dan setelah */
|
|
230
|
-
interface CssDiff {
|
|
231
|
-
/** Rule yang perlu ditambah ke CSS output */
|
|
232
|
-
added: StyleNode[];
|
|
233
|
-
/** Atomic class names yang perlu dihapus dari CSS output */
|
|
234
|
-
removed: string[];
|
|
235
|
-
/** true jika tidak ada perubahan */
|
|
236
|
-
noChange: boolean;
|
|
237
|
-
}
|
|
238
|
-
/** Summary setelah process satu file */
|
|
239
|
-
interface ProcessResult {
|
|
240
|
-
/** File yang diproses */
|
|
241
|
-
filepath: string;
|
|
242
|
-
/** true jika file berubah dan registry di-update */
|
|
243
|
-
changed: boolean;
|
|
244
|
-
/** CSS diff untuk file ini */
|
|
245
|
-
diff: CssDiff;
|
|
246
|
-
/** Durasi proses dalam ms */
|
|
247
|
-
durationMs: number;
|
|
248
|
-
}
|
|
249
|
-
/** Stats engine */
|
|
250
|
-
interface IncrementalStats {
|
|
251
|
-
totalFiles: number;
|
|
252
|
-
changedFiles: number;
|
|
253
|
-
skippedFiles: number;
|
|
254
|
-
addedRules: number;
|
|
255
|
-
removedRules: number;
|
|
256
|
-
buildTimeMs: number;
|
|
257
|
-
}
|
|
258
|
-
interface IncrementalEngineOptions {
|
|
259
|
-
/** Output path untuk CSS file incremental. Default: ".tw-cache/atomic.css" */
|
|
260
|
-
outputPath?: string;
|
|
261
|
-
/** Apakah persist cache ke disk. Default: true */
|
|
262
|
-
persistCache?: boolean;
|
|
263
|
-
/** Verbose logging. Default: false */
|
|
264
|
-
verbose?: boolean;
|
|
265
|
-
}
|
|
266
|
-
declare class IncrementalEngine {
|
|
267
|
-
private hashCache;
|
|
268
|
-
private depGraph;
|
|
269
|
-
private globalReg;
|
|
270
|
-
private cssWriter;
|
|
271
|
-
private opts;
|
|
272
|
-
private stats;
|
|
273
|
-
private sessionStart;
|
|
274
|
-
constructor(opts?: IncrementalEngineOptions);
|
|
275
|
-
/**
|
|
276
|
-
* Proses satu file. Core method dipanggil oleh webpack/turbopack loader.
|
|
277
|
-
*
|
|
278
|
-
* @param filepath - Absolute path ke file
|
|
279
|
-
* @param source - Source code file (untuk hashing)
|
|
280
|
-
* @param extractedNodes - Style nodes yang di-extract compiler dari file ini
|
|
281
|
-
* @returns ProcessResult dengan diff dan stats
|
|
282
|
-
*/
|
|
283
|
-
processFile(filepath: string, source: string, extractedNodes: StyleNode[]): ProcessResult;
|
|
284
|
-
/**
|
|
285
|
-
* Dipanggil di akhir build. Flush CSS ke disk, persist cache.
|
|
286
|
-
*/
|
|
287
|
-
buildEnd(): Promise<void>;
|
|
288
|
-
/** Sync version untuk webpack buildEnd hook */
|
|
289
|
-
buildEndSync(): void;
|
|
290
|
-
/**
|
|
291
|
-
* Invalidate satu file (untuk hot reload — file dihapus atau renamed).
|
|
292
|
-
*/
|
|
293
|
-
invalidateFile(filepath: string): void;
|
|
294
|
-
/** Get all active style nodes — untuk full CSS generation */
|
|
295
|
-
getAllNodes(): StyleNode[];
|
|
296
|
-
/** Get stats untuk current build session */
|
|
297
|
-
getStats(): Readonly<IncrementalStats>;
|
|
298
|
-
/** Get output CSS path */
|
|
299
|
-
getOutputPath(): string;
|
|
300
|
-
/** Reset stats untuk build session baru */
|
|
301
|
-
resetStats(): void;
|
|
302
|
-
/** Reset semua cache — untuk clean build */
|
|
303
|
-
reset(): void;
|
|
304
|
-
private log;
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Parse daftar Tailwind classes menjadi StyleNodes untuk incremental engine.
|
|
308
|
-
* Supports: responsive variants (md:, lg:), pseudo (hover:, focus:), arbitrary.
|
|
309
|
-
*
|
|
310
|
-
* @example
|
|
311
|
-
* parseClassesToNodes(["p-4", "hover:bg-blue-500", "md:text-lg"])
|
|
312
|
-
*/
|
|
313
|
-
declare function parseClassesToNodes(classes: string[]): StyleNode[];
|
|
314
|
-
declare function getIncrementalEngine(opts?: IncrementalEngineOptions): IncrementalEngine;
|
|
315
|
-
declare function resetIncrementalEngine(): void;
|
|
316
|
-
|
|
317
|
-
/**
|
|
318
|
-
* tailwind-styled-v4 — Tailwind Config Loader
|
|
319
|
-
*
|
|
320
|
-
* Auto-load tailwind config dari project.
|
|
321
|
-
* Jika tidak ada → fallback ke defaultPreset (zero-config mode).
|
|
322
|
-
*
|
|
323
|
-
* Priority:
|
|
324
|
-
* 1. tailwind.config.ts (TypeScript)
|
|
325
|
-
* 2. tailwind.config.js (JavaScript)
|
|
326
|
-
* 3. tailwind.config.mjs (ESM)
|
|
327
|
-
* 4. defaultPreset (fallback — zero-config)
|
|
328
|
-
*/
|
|
329
|
-
type TailwindConfig = Record<string, any>;
|
|
330
|
-
/**
|
|
331
|
-
* Load tailwind config. Cached per process.
|
|
332
|
-
* Returns defaultPreset if no config found (zero-config mode).
|
|
333
|
-
*/
|
|
334
|
-
declare function loadTailwindConfig(cwd?: string): TailwindConfig;
|
|
335
|
-
/**
|
|
336
|
-
* Get content paths dari config (atau default paths)
|
|
337
|
-
*/
|
|
338
|
-
declare function getContentPaths(config: TailwindConfig, cwd?: string): string[];
|
|
339
|
-
/**
|
|
340
|
-
* Invalidate config cache (useful for watch mode)
|
|
341
|
-
*/
|
|
342
|
-
declare function invalidateConfigCache(): void;
|
|
343
|
-
/**
|
|
344
|
-
* Check if project has zero-config setup (no user tailwind config)
|
|
345
|
-
*/
|
|
346
|
-
declare function isZeroConfig(cwd?: string): boolean;
|
|
347
|
-
/**
|
|
348
|
-
* Auto-generate tailwind.config.ts dan globals.css jika tidak ada
|
|
349
|
-
* (dipanggil oleh CLI dan withTailwindStyled pada first run)
|
|
350
|
-
*/
|
|
351
|
-
declare function bootstrapZeroConfig(cwd?: string): {
|
|
352
|
-
generatedConfig: boolean;
|
|
353
|
-
generatedCss: boolean;
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* tailwind-styled-v4 — Route CSS Collector
|
|
358
|
-
*
|
|
359
|
-
* Mengumpulkan Tailwind classes per-route sehingga setiap halaman
|
|
360
|
-
* hanya memuat CSS yang benar-benar dipakai.
|
|
361
|
-
*
|
|
362
|
-
* Tailwind default: ~300kb global CSS
|
|
363
|
-
* Route CSS: ~2–10kb per halaman
|
|
364
|
-
*
|
|
365
|
-
* Cara kerja:
|
|
366
|
-
* 1. Setiap file yang di-transform oleh compiler melaporkan classnya
|
|
367
|
-
* 2. Collector memetakan file → route
|
|
368
|
-
* 3. Di akhir build, CSS di-generate per route
|
|
369
|
-
*
|
|
370
|
-
* File structure output:
|
|
371
|
-
* .next/static/css/
|
|
372
|
-
* _global.css ← base + reset (sekali load)
|
|
373
|
-
* app/page.css ← hanya class yang dipakai di /
|
|
374
|
-
* app/about/page.css ← hanya class untuk /about
|
|
375
|
-
* app/dashboard/...
|
|
376
|
-
*/
|
|
377
|
-
interface RouteClassMap {
|
|
378
|
-
/** filepath → array of tw classes */
|
|
379
|
-
files: Map<string, Set<string>>;
|
|
380
|
-
/** route → Set of files yang dipakai */
|
|
381
|
-
routes: Map<string, Set<string>>;
|
|
382
|
-
/** Global classes (di-load semua route) */
|
|
383
|
-
global: Set<string>;
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Register classes dari sebuah file setelah compiler transform.
|
|
387
|
-
* Dipanggil oleh turbopackLoader/webpackLoader setelah setiap file di-transform.
|
|
388
|
-
*/
|
|
389
|
-
declare function registerFileClasses(filepath: string, classes: string[]): void;
|
|
390
|
-
/**
|
|
391
|
-
* Register global classes (base styles, layout, dsb.)
|
|
392
|
-
* Global classes dimuat di semua route.
|
|
393
|
-
*/
|
|
394
|
-
declare function registerGlobalClasses(classes: string[]): void;
|
|
395
|
-
/**
|
|
396
|
-
* Get all classes for a specific route (termasuk global)
|
|
397
|
-
*/
|
|
398
|
-
declare function getRouteClasses(route: string): Set<string>;
|
|
399
|
-
/**
|
|
400
|
-
* Get all routes yang sudah ter-register
|
|
401
|
-
*/
|
|
402
|
-
declare function getAllRoutes(): string[];
|
|
403
|
-
/**
|
|
404
|
-
* Get complete map (untuk build-time generation)
|
|
405
|
-
*/
|
|
406
|
-
declare function getCollector(): RouteClassMap;
|
|
407
|
-
/**
|
|
408
|
-
* Reset collector (start of each build)
|
|
409
|
-
*/
|
|
410
|
-
declare function resetCollector(): void;
|
|
411
|
-
/**
|
|
412
|
-
* Konversi filepath ke Next.js App Router route.
|
|
413
|
-
*
|
|
414
|
-
* /src/app/page.tsx → /
|
|
415
|
-
* /src/app/about/page.tsx → /about
|
|
416
|
-
* /src/app/dashboard/page.tsx → /dashboard
|
|
417
|
-
* /src/components/Button.tsx → null (shared component, goes to global)
|
|
418
|
-
* /src/app/layout.tsx → __layout (global)
|
|
419
|
-
*/
|
|
420
|
-
declare function fileToRoute(filepath: string): string | null;
|
|
421
|
-
declare function getCollectorSummary(): string;
|
|
422
|
-
|
|
423
|
-
/**
|
|
424
|
-
* tailwind-styled-v4 — RSC Analyzer
|
|
425
|
-
*
|
|
426
|
-
* Inti dari RSC-Aware upgrade.
|
|
427
|
-
* Menganalisis setiap file untuk menentukan:
|
|
428
|
-
* - Server Component atau Client Component
|
|
429
|
-
* - Variant mana yang bisa di-resolve di server
|
|
430
|
-
* - Class mana yang membutuhkan client runtime
|
|
431
|
-
* - Auto client boundary injection
|
|
432
|
-
*
|
|
433
|
-
* Hasilnya:
|
|
434
|
-
* - Server Component → pure static className, zero JS ke client
|
|
435
|
-
* - Client Component → tetap seperti biasa dengan lookup table
|
|
436
|
-
*/
|
|
437
|
-
type ComponentEnv = "server" | "client" | "auto";
|
|
438
|
-
interface RscAnalysis {
|
|
439
|
-
/** File ini adalah server component */
|
|
440
|
-
isServer: boolean;
|
|
441
|
-
/** File ini butuh "use client" directive */
|
|
442
|
-
needsClientDirective: boolean;
|
|
443
|
-
/** Alasan butuh client */
|
|
444
|
-
clientReasons: string[];
|
|
445
|
-
/** Classes yang membutuhkan client interaction */
|
|
446
|
-
interactiveClasses: string[];
|
|
447
|
-
/** Apakah semua variants bisa di-resolve statically di server */
|
|
448
|
-
canStaticResolveVariants: boolean;
|
|
449
|
-
}
|
|
450
|
-
declare function analyzeFile(source: string, _filename?: string): RscAnalysis;
|
|
451
|
-
interface StaticVariantUsage {
|
|
452
|
-
/** Variant prop values yang ditemukan di JSX — bisa di-resolve di server */
|
|
453
|
-
resolved: Record<string, string>;
|
|
454
|
-
/** Variant props yang dinamis — butuh runtime */
|
|
455
|
-
dynamic: string[];
|
|
456
|
-
}
|
|
457
|
-
/**
|
|
458
|
-
* Deteksi penggunaan variant dalam JSX:
|
|
459
|
-
* <Button variant="primary"/> → dapat di-resolve statically
|
|
460
|
-
* <Button variant={userVariant}/> → dinamis, butuh runtime
|
|
461
|
-
*/
|
|
462
|
-
declare function analyzeVariantUsage(source: string, componentName: string, variantKeys: string[]): StaticVariantUsage;
|
|
463
|
-
/**
|
|
464
|
-
* Untuk server component dengan variant usage statically known,
|
|
465
|
-
* resolve langsung ke className string — nol runtime.
|
|
466
|
-
*
|
|
467
|
-
* Input:
|
|
468
|
-
* base = "px-4 py-2"
|
|
469
|
-
* table = { variant: { primary: "px-4 py-2 bg-blue-500" } }
|
|
470
|
-
* resolved = { variant: "primary" }
|
|
471
|
-
*
|
|
472
|
-
* Output:
|
|
473
|
-
* "px-4 py-2 bg-blue-500" ← langsung inline di server
|
|
474
|
-
*/
|
|
475
|
-
declare function resolveServerVariant(base: string, table: Record<string, Record<string, string>>, defaults: Record<string, string>, resolved: Record<string, string>): string;
|
|
476
|
-
declare function injectClientDirective(code: string): string;
|
|
477
|
-
declare function injectServerOnlyComment(code: string): string;
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* tailwind-styled-v4 — safelistGenerator
|
|
481
|
-
*
|
|
482
|
-
* Scan semua source files dan extract Tailwind classes untuk safelist.
|
|
483
|
-
* Output: .tailwind-styled-safelist.json
|
|
484
|
-
*
|
|
485
|
-
* Developer tidak perlu manual safelist.
|
|
486
|
-
*/
|
|
487
|
-
declare function generateSafelist(scanDirs: string[], outputPath?: string, cwd?: string): string[];
|
|
488
|
-
declare function loadSafelist(safelistPath: string): string[];
|
|
489
|
-
/**
|
|
490
|
-
* Tailwind v4 variant — output CSS dengan @source inline() bukan JSON.
|
|
491
|
-
* Tailwind v4 tidak punya 'safelist' di config — pakai @source inline() di CSS.
|
|
492
|
-
*/
|
|
493
|
-
declare function generateSafelistCss(scanDirs: string[], outputPath?: string, cwd?: string): string[];
|
|
494
|
-
|
|
495
|
-
/**
|
|
496
|
-
* tailwind-styled-v4 — Style Bucket System
|
|
497
|
-
*
|
|
498
|
-
* Setiap CSS rule masuk ke "bucket" berdasarkan tipe property-nya.
|
|
499
|
-
* Bucket di-emit dalam urutan yang selalu sama → CSS order stabil
|
|
500
|
-
* meskipun rule di-generate dari banyak file secara incremental.
|
|
501
|
-
*
|
|
502
|
-
* Tanpa bucket system:
|
|
503
|
-
* .tw-color { color: blue } ← dari file A
|
|
504
|
-
* .tw-flex { display: flex } ← dari file B
|
|
505
|
-
* .tw-color2 { color: red } ← dari file C
|
|
506
|
-
* → urutan output bergantung urutan file di-process = TIDAK STABIL
|
|
507
|
-
*
|
|
508
|
-
* Dengan bucket system:
|
|
509
|
-
* /* reset *\/
|
|
510
|
-
* /* layout *\/ → display, position, flex, grid, overflow
|
|
511
|
-
* /* spacing *\/ → margin, padding, gap, inset
|
|
512
|
-
* /* sizing *\/ → width, height, max/min-width/height
|
|
513
|
-
* /* typography *\/ → font-size, font-weight, line-height, text-*
|
|
514
|
-
* /* visual *\/ → color, background, border, shadow, opacity
|
|
515
|
-
* /* interaction *\/ → cursor, pointer-events, user-select, transition
|
|
516
|
-
* /* responsive *\/ → @media queries (selalu di akhir)
|
|
517
|
-
* → SELALU urutan ini, terlepas dari urutan file
|
|
518
|
-
*
|
|
519
|
-
* Keuntungan utama:
|
|
520
|
-
* 1. CSS output deterministic antar build (reproducible builds)
|
|
521
|
-
* 2. Specificity conflict sangat kecil — base selalu lebih awal dari responsive
|
|
522
|
-
* 3. Debug lebih mudah — tahu section mana rule berada
|
|
523
|
-
*
|
|
524
|
-
* Integrasi:
|
|
525
|
-
* import { BucketEngine, bucketSort } from "./styleBucketSystem"
|
|
526
|
-
*
|
|
527
|
-
* const engine = new BucketEngine()
|
|
528
|
-
* engine.add(styleNode)
|
|
529
|
-
* const css = engine.emit()
|
|
530
|
-
*/
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* 8 bucket utama + 1 bucket "unknown" untuk fallback.
|
|
534
|
-
* Urutan angka = urutan emit di CSS output.
|
|
535
|
-
*/
|
|
536
|
-
type StyleBucket = "reset" | "layout" | "spacing" | "sizing" | "typography" | "visual" | "interaction" | "responsive" | "unknown";
|
|
537
|
-
/**
|
|
538
|
-
* Classify satu StyleNode ke bucket yang tepat.
|
|
539
|
-
*
|
|
540
|
-
* Priority:
|
|
541
|
-
* 1. Jika ada modifier @media → "responsive" (selalu paling akhir)
|
|
542
|
-
* 2. Cek declaration property → lookup PROPERTY_BUCKET_MAP
|
|
543
|
-
* 3. Fallback ke "unknown"
|
|
544
|
-
*/
|
|
545
|
-
declare function classifyNode(node: StyleNode): StyleBucket;
|
|
546
|
-
interface BucketStats {
|
|
547
|
-
totalNodes: number;
|
|
548
|
-
perBucket: Record<StyleBucket, number>;
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* BucketEngine — menyimpan dan emit CSS dalam urutan bucket yang stabil.
|
|
552
|
-
*
|
|
553
|
-
* @example
|
|
554
|
-
* const engine = new BucketEngine()
|
|
555
|
-
* for (const node of styleNodes) engine.add(node)
|
|
556
|
-
* const css = engine.emit()
|
|
557
|
-
*/
|
|
558
|
-
declare class BucketEngine {
|
|
559
|
-
private buckets;
|
|
560
|
-
constructor();
|
|
561
|
-
/**
|
|
562
|
-
* Tambah StyleNode ke bucket yang tepat.
|
|
563
|
-
* Idempotent — atomic class yang sama tidak akan duplikat.
|
|
564
|
-
*/
|
|
565
|
-
add(node: StyleNode): void;
|
|
566
|
-
/**
|
|
567
|
-
* Hapus node dari bucket (untuk incremental update).
|
|
568
|
-
*/
|
|
569
|
-
remove(atomicClass: string): void;
|
|
570
|
-
/**
|
|
571
|
-
* Apply CssDiff dari incremental engine.
|
|
572
|
-
*/
|
|
573
|
-
applyDiff(diff: {
|
|
574
|
-
added: StyleNode[];
|
|
575
|
-
removed: string[];
|
|
576
|
-
}): void;
|
|
577
|
-
/**
|
|
578
|
-
* Emit seluruh CSS dalam urutan bucket yang deterministic.
|
|
579
|
-
*
|
|
580
|
-
* @param comments - Tambahkan komentar section per bucket. Default: true
|
|
581
|
-
* @returns CSS string yang siap di-write ke file
|
|
582
|
-
*/
|
|
583
|
-
emit(comments?: boolean): string;
|
|
584
|
-
/**
|
|
585
|
-
* Emit dengan @layer CSS untuk native browser layering.
|
|
586
|
-
* Lebih powerful — browser respects layer order untuk specificity.
|
|
587
|
-
*
|
|
588
|
-
* @example output:
|
|
589
|
-
* @layer tw-layout, tw-spacing, tw-visual, tw-responsive;
|
|
590
|
-
* @layer tw-layout { .tw-a1 { display: flex } }
|
|
591
|
-
*/
|
|
592
|
-
emitLayered(): string;
|
|
593
|
-
/** Semua nodes dari semua bucket (untuk full registry access) */
|
|
594
|
-
allNodes(): StyleNode[];
|
|
595
|
-
/** Stats per bucket */
|
|
596
|
-
stats(): BucketStats;
|
|
597
|
-
/** Clear semua bucket */
|
|
598
|
-
clear(): void;
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Sort array StyleNodes dalam urutan bucket.
|
|
602
|
-
* Berguna untuk one-off sorting tanpa perlu BucketEngine instance.
|
|
603
|
-
*
|
|
604
|
-
* @example
|
|
605
|
-
* const sorted = bucketSort(allNodes)
|
|
606
|
-
* const css = sorted.map(nodeToCSS).join("\n")
|
|
607
|
-
*/
|
|
608
|
-
declare function bucketSort(nodes: StyleNode[]): StyleNode[];
|
|
609
|
-
interface ConflictWarning {
|
|
610
|
-
property: string;
|
|
611
|
-
classes: string[];
|
|
612
|
-
bucket: StyleBucket;
|
|
613
|
-
message: string;
|
|
614
|
-
}
|
|
615
|
-
/**
|
|
616
|
-
* Detect potential CSS conflicts dalam satu set StyleNodes.
|
|
617
|
-
* Hanya untuk dev mode — tidak perlu run di production.
|
|
618
|
-
*
|
|
619
|
-
* Conflict = dua node dengan property yang sama tapi value berbeda
|
|
620
|
-
* di bucket yang sama (bukan responsive override).
|
|
621
|
-
*
|
|
622
|
-
* @example
|
|
623
|
-
* const warnings = detectConflicts(nodes)
|
|
624
|
-
* if (warnings.length) console.warn(warnings)
|
|
625
|
-
*/
|
|
626
|
-
declare function detectConflicts(nodes: StyleNode[]): ConflictWarning[];
|
|
627
|
-
declare function getBucketEngine(): BucketEngine;
|
|
628
|
-
declare function resetBucketEngine(): void;
|
|
629
|
-
|
|
630
|
-
/**
|
|
631
|
-
* tailwind-styled-v4 — Embedded Tailwind Engine
|
|
632
|
-
*
|
|
633
|
-
* Compiler menjalankan Tailwind internally — tidak perlu tailwind CLI,
|
|
634
|
-
* tidak perlu postcss config manual.
|
|
635
|
-
*
|
|
636
|
-
* Cara kerja:
|
|
637
|
-
* 1. Compiler extract semua class dari source (via classExtractor)
|
|
638
|
-
* 2. Engine generate CSS hanya untuk class tersebut
|
|
639
|
-
* 3. CSS di-output per route (route-level CSS bundling)
|
|
640
|
-
*
|
|
641
|
-
* Ini membuat CSS output jauh lebih kecil:
|
|
642
|
-
* Tailwind normal: ~300kb global
|
|
643
|
-
* Route CSS: ~2–10kb per route
|
|
644
|
-
*
|
|
645
|
-
* Mode operasi:
|
|
646
|
-
* "jit" → generate CSS saat file berubah (dev mode)
|
|
647
|
-
* "build" → generate semua CSS di akhir build (production)
|
|
648
|
-
* "manual" → tidak generate, hanya extract (default untuk kompatibilitas)
|
|
649
|
-
*/
|
|
650
|
-
type TailwindEngineMode = "jit" | "build" | "manual";
|
|
651
|
-
interface TailwindEngineOptions {
|
|
652
|
-
mode?: TailwindEngineMode;
|
|
653
|
-
cwd?: string;
|
|
654
|
-
outputDir?: string;
|
|
655
|
-
config?: Record<string, any>;
|
|
656
|
-
minify?: boolean;
|
|
657
|
-
}
|
|
658
|
-
interface CssGenerateResult {
|
|
659
|
-
route: string;
|
|
660
|
-
css: string;
|
|
661
|
-
classes: string[];
|
|
662
|
-
sizeBytes: number;
|
|
663
|
-
}
|
|
664
|
-
/**
|
|
665
|
-
* Try to use Tailwind's internal API for CSS generation.
|
|
666
|
-
* Fallback ke manual CSS generation jika Tailwind API tidak tersedia.
|
|
667
|
-
*
|
|
668
|
-
* NOTE: Tailwind v4 mengubah API internal — kita support keduanya.
|
|
669
|
-
*/
|
|
670
|
-
declare function generateCssForClasses(classes: string[], config?: Record<string, any>, cwd?: string): Promise<string>;
|
|
671
|
-
declare function generateAllRouteCss(opts?: TailwindEngineOptions): Promise<CssGenerateResult[]>;
|
|
672
|
-
|
|
673
|
-
/**
|
|
674
|
-
* tailwind-styled-v4 — variantCompiler
|
|
675
|
-
*
|
|
676
|
-
* FIXES:
|
|
677
|
-
* #01 — Don't pre-merge base into variant table values (double-merge bug)
|
|
678
|
-
* #06 — Use proper AST parser instead of fragile regex
|
|
679
|
-
*
|
|
680
|
-
* BEFORE (double-merge):
|
|
681
|
-
* compileVariants: table["size"]["sm"] = "px-4 py-2 text-sm" ← base included
|
|
682
|
-
* astTransform: [base, table["size"][...]] ← base AGAIN → DUPE
|
|
683
|
-
*
|
|
684
|
-
* AFTER (correct):
|
|
685
|
-
* compileVariants: table["size"]["sm"] = "text-sm" ← variant only
|
|
686
|
-
* astTransform: [base, table["size"][...], className] ← base once, correct
|
|
687
|
-
*
|
|
688
|
-
* Input:
|
|
689
|
-
* { base: "px-4 py-2", variants: { size: { sm: "text-sm" } } }
|
|
690
|
-
*
|
|
691
|
-
* Output code:
|
|
692
|
-
* const __vt_abc123 = { size: { sm: "text-sm" } }
|
|
693
|
-
* // className = [base, table[variant]] → no duplication
|
|
694
|
-
*/
|
|
695
|
-
interface CompiledVariants {
|
|
696
|
-
base: string;
|
|
697
|
-
table: Record<string, Record<string, string>>;
|
|
698
|
-
compounds: Array<{
|
|
699
|
-
class: string;
|
|
700
|
-
[key: string]: any;
|
|
701
|
-
}>;
|
|
702
|
-
defaults: Record<string, string>;
|
|
703
|
-
}
|
|
704
|
-
/**
|
|
705
|
-
* Compile variant config into lookup table.
|
|
706
|
-
*
|
|
707
|
-
* FIX #01: Do NOT pre-merge base into table values.
|
|
708
|
-
* Table contains variant-specific classes only.
|
|
709
|
-
* Base is always injected separately in the component className array.
|
|
710
|
-
*/
|
|
711
|
-
declare function compileVariants(base: string, variants: Record<string, Record<string, string>>, compounds?: Array<{
|
|
712
|
-
class: string;
|
|
713
|
-
[key: string]: any;
|
|
714
|
-
}>, defaults?: Record<string, string>): CompiledVariants;
|
|
715
|
-
|
|
716
|
-
export { type AtomicRule, BucketEngine, type BucketStats, type ComponentEnv, type ConflictWarning, type CssDiff, type CssGenerateResult, type EliminationReport, type FileDependencyGraph, type HoistResult, IncrementalEngine, type IncrementalEngineOptions, type IncrementalStats, type ProcessResult, type RouteClassMap, type RscAnalysis, type StaticVariantUsage, type StyleBucket, type StyleNode, type TailwindEngineOptions, type VariantUsage, analyzeFile, analyzeVariantUsage, bootstrapZeroConfig, bucketSort, classifyNode, clearAtomicRegistry, compileVariants, detectConflicts, extractAllClasses, extractComponentUsage, fileToRoute, generateAllRouteCss, generateAtomicCss, generateCssForClasses, generateSafelist, generateSafelistCss, getAllRoutes, getAtomicRegistry, getBucketEngine, getCollector, getCollectorSummary, getContentPaths, getIncrementalEngine, getRouteClasses, hasInteractiveFeatures, hasTwUsage, hoistComponents, injectClientDirective, injectServerOnlyComment, invalidateConfigCache, isDynamic, isServerComponent, isZeroConfig, loadSafelist, loadTailwindConfig, mergeClassesStatic, normalizeClasses, parseAtomicClass, parseClassesToNodes, registerFileClasses, registerGlobalClasses, resetBucketEngine, resetCollector, resetIncrementalEngine, resolveServerVariant, runElimination, scanProjectUsage, hasTwUsage as shouldProcess, toAtomicClasses };
|