tailwind-styled-v4 5.0.27 → 5.0.29

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 (88) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +575 -575
  3. package/dist/analyzer.js.map +1 -1
  4. package/dist/analyzer.mjs.map +1 -1
  5. package/dist/animate.js.map +1 -1
  6. package/dist/animate.mjs.map +1 -1
  7. package/dist/atomic.js.map +1 -1
  8. package/dist/atomic.mjs.map +1 -1
  9. package/dist/cli.js.map +1 -1
  10. package/dist/cli.mjs.map +1 -1
  11. package/dist/compiler.js +2 -1
  12. package/dist/compiler.js.map +1 -1
  13. package/dist/compiler.mjs +2 -1
  14. package/dist/compiler.mjs.map +1 -1
  15. package/dist/dashboard.d.mts +69 -69
  16. package/dist/dashboard.d.ts +69 -69
  17. package/dist/dashboard.js.map +1 -1
  18. package/dist/dashboard.mjs.map +1 -1
  19. package/dist/devtools.js.map +1 -1
  20. package/dist/devtools.mjs.map +1 -1
  21. package/dist/engine.js +2 -1
  22. package/dist/engine.js.map +1 -1
  23. package/dist/engine.mjs +2 -1
  24. package/dist/engine.mjs.map +1 -1
  25. package/dist/index.browser.mjs +16 -16
  26. package/dist/index.browser.mjs.map +1 -1
  27. package/dist/index.d.mts +4 -4
  28. package/dist/index.d.ts +4 -4
  29. package/dist/index.js +27 -24
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +27 -24
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/next.js +2 -1
  34. package/dist/next.js.map +1 -1
  35. package/dist/next.mjs +2 -1
  36. package/dist/next.mjs.map +1 -1
  37. package/dist/plugin-api.js.map +1 -1
  38. package/dist/plugin-api.mjs.map +1 -1
  39. package/dist/plugin-registry.js.map +1 -1
  40. package/dist/plugin-registry.mjs.map +1 -1
  41. package/dist/plugin.js.map +1 -1
  42. package/dist/plugin.mjs.map +1 -1
  43. package/dist/preset.js.map +1 -1
  44. package/dist/preset.mjs.map +1 -1
  45. package/dist/rspack.js.map +1 -1
  46. package/dist/rspack.mjs.map +1 -1
  47. package/dist/runtime-css.js.map +1 -1
  48. package/dist/runtime-css.mjs.map +1 -1
  49. package/dist/runtime.js.map +1 -1
  50. package/dist/runtime.mjs.map +1 -1
  51. package/dist/scanner.js.map +1 -1
  52. package/dist/scanner.mjs.map +1 -1
  53. package/dist/shared.js +2 -1
  54. package/dist/shared.js.map +1 -1
  55. package/dist/shared.mjs +2 -1
  56. package/dist/shared.mjs.map +1 -1
  57. package/dist/storybook-addon.js.map +1 -1
  58. package/dist/storybook-addon.mjs.map +1 -1
  59. package/dist/svelte.js.map +1 -1
  60. package/dist/svelte.mjs.map +1 -1
  61. package/dist/syntax.js.map +1 -1
  62. package/dist/syntax.mjs.map +1 -1
  63. package/dist/testing.js.map +1 -1
  64. package/dist/testing.mjs.map +1 -1
  65. package/dist/theme.js.map +1 -1
  66. package/dist/theme.mjs.map +1 -1
  67. package/dist/turbopackLoader.js +2 -1
  68. package/dist/turbopackLoader.js.map +1 -1
  69. package/dist/turbopackLoader.mjs +2 -1
  70. package/dist/turbopackLoader.mjs.map +1 -1
  71. package/dist/tw.js +0 -0
  72. package/dist/tw.js.map +1 -1
  73. package/dist/tw.mjs +0 -0
  74. package/dist/tw.mjs.map +1 -1
  75. package/dist/vite.js +2 -1
  76. package/dist/vite.js.map +1 -1
  77. package/dist/vite.mjs +2 -1
  78. package/dist/vite.mjs.map +1 -1
  79. package/dist/vue.js.map +1 -1
  80. package/dist/vue.mjs.map +1 -1
  81. package/dist/webpackLoader.js +2 -1
  82. package/dist/webpackLoader.js.map +1 -1
  83. package/dist/webpackLoader.mjs +2 -1
  84. package/dist/webpackLoader.mjs.map +1 -1
  85. package/native/tailwind-styled-native.linux-x64-gnu.node +0 -0
  86. package/native/tailwind-styled-native.node +0 -0
  87. package/package.json +296 -289
  88. package/native/tailwind-styled-native.win32-x64-msvc.node +0 -0
package/README.md CHANGED
@@ -1,576 +1,576 @@
1
- <div align="center">
2
-
3
- # tailwind-styled-v4
4
-
5
- ### ⚡ Rust-powered Tailwind CSS v4 untuk React
6
- **Build-time compiler · Zero runtime overhead · RSC-aware · Next.js / Vite / Rspack**
7
-
8
- [![npm](https://img.shields.io/npm/v/tailwind-styled-v4?color=blue)](https://npmjs.com/package/tailwind-styled-v4)
9
- [![license](https://img.shields.io/npm/l/tailwind-styled-v4)](LICENSE)
10
- [![Rust](https://img.shields.io/badge/Rust-1.75+-orange?logo=rust)](https://rust-lang.org)
11
- [![Node](https://img.shields.io/badge/Node.js-20+-green?logo=node.js)](https://nodejs.org)
12
- [![test](https://img.shields.io/badge/tests-84%2F86%20passing-brightgreen)](#)
13
- [![bundle](https://img.shields.io/badge/runtime-~4.5kb-green)](https://bundlephobia.com/package/tailwind-styled-v4)
14
-
15
- </div>
16
-
17
- ---
18
-
19
- ## Apa ini?
20
-
21
- `tailwind-styled-v4` adalah library styling untuk React yang menggabungkan **DX styled-components** dengan **performa Tailwind CSS v4** dan **engine berbasis Rust**. Tulis komponen dengan `tw.button` atau `tw.div({ variants })` — compiler extract dan optimasi CSS di build time, bukan runtime.
22
-
23
- **Perbandingan singkat:**
24
-
25
- | | tailwind-styled-v4 | styled-components | Tailwind CSS biasa |
26
- |---|---|---|---|
27
- | Build-time CSS | ✅ | ❌ (runtime inject) | ✅ |
28
- | Runtime overhead | ~0 | ~15KB | ~0 |
29
- | Variants API | ✅ type-safe | terbatas | ❌ |
30
- | SSR/RSC support | ✅ zero config | ⚠️ butuh ServerStyleSheet | ✅ manual |
31
- | Hydration mismatch | ✅ tidak ada | ⚠️ hash bisa beda | ✅ tidak ada |
32
- | DevTools readable | ✅ class name jelas | ❌ hash (`sc-abc123`) | ✅ |
33
- | Engine | 🦀 Rust | JS | JS |
34
- | Dark mode | ✅ `dark:` prefix | manual | ✅ |
35
- | TypeScript | ✅ full inference | partial | ✅ |
36
-
37
- ---
38
-
39
- ## Instalasi
40
-
41
- ```bash
42
- npm install tailwind-styled-v4
43
-
44
- # Setup otomatis
45
- npx tw setup
46
- ```
47
-
48
- `npx tw setup` akan otomatis:
49
- - Mendeteksi bundler (Next.js / Vite / Rspack)
50
- - Meng-inject plugin ke `next.config.ts` / `vite.config.ts`
51
- - Membuat `tailwind-styled.config.json` dengan CSS entry yang terdeteksi otomatis
52
- - Menambahkan `@import "tailwindcss"` ke CSS entry
53
- - Pre-warming scanner cache supaya dev pertama tidak cache miss
54
-
55
- ---
56
-
57
- ## Quick Start
58
-
59
- ### 1. Template Literal
60
-
61
- ```tsx
62
- import { tw } from "tailwind-styled-v4"
63
-
64
- const Button = tw.button`
65
- inline-flex items-center rounded-lg px-4 py-2
66
- bg-blue-600 text-white font-medium
67
- hover:bg-blue-700 transition
68
- `
69
-
70
- <Button onClick={handleClick}>Klik saya</Button>
71
- ```
72
-
73
- ### 2. Object Config + Variants
74
-
75
- ```tsx
76
- const Button = tw.button({
77
- base: "inline-flex items-center rounded-full px-5 py-2 font-medium transition-all",
78
- variants: {
79
- intent: {
80
- primary: "bg-foreground text-background hover:bg-[#383838]",
81
- secondary: "bg-white text-gray-900 border border-gray-300 hover:bg-gray-50",
82
- outline: "bg-transparent border-2 border-foreground text-foreground hover:bg-foreground hover:text-background",
83
- ghost: "bg-transparent text-foreground hover:bg-gray-100",
84
- },
85
- size: {
86
- sm: "h-10 px-4 text-sm rounded-lg",
87
- md: "h-12 px-5 text-base rounded-full",
88
- lg: "h-14 px-6 text-lg rounded-full",
89
- },
90
- },
91
- defaultVariants: { intent: "primary", size: "md" },
92
- states: {
93
- loading: "opacity-60 cursor-wait pointer-events-none",
94
- disabled: "opacity-50 cursor-not-allowed",
95
- fullWidth: "w-full",
96
- },
97
- })
98
-
99
- // TypeScript tahu variant apa yang valid — autocomplete ✅
100
- <Button intent="primary" size="lg">Submit</Button>
101
- <Button intent="ghost">Batal</Button>
102
- <Button intent="outline" size="sm">Edit</Button>
103
- <Button loading>Memproses...</Button>
104
- ```
105
-
106
- ### 3. Sub-components
107
-
108
- ```tsx
109
- const Card = tw.div({
110
- base: "rounded-xl bg-white shadow-md overflow-hidden",
111
- sub: {
112
- header: "px-6 py-4 border-b font-semibold",
113
- main: "px-6 py-4",
114
- footer: "px-6 py-4 border-t text-sm text-gray-400",
115
- "div:action": "px-6 py-4 flex gap-3", // render <div>, akses Card.action
116
- },
117
- states: {
118
- selected: "ring-2 ring-blue-500",
119
- disabled: "opacity-50 pointer-events-none",
120
- },
121
- })
122
-
123
- // Penggunaan
124
- <Card selected>
125
- <Card.header>Judul Card</Card.header>
126
- <Card.main>Konten card di sini.</Card.main>
127
- <Card.action>
128
- <Button>Lihat Detail</Button>
129
- <Button intent="ghost">Batal</Button>
130
- </Card.action>
131
- <Card.footer>Updated 2 hours ago</Card.footer>
132
- </Card>
133
- ```
134
-
135
- Format `"tag:name"` untuk sub-components — misalnya `"div:action"` render sebagai `<div>` dengan akses via `Card.action`. TypeScript otomatis strip prefix tag dari type inference.
136
-
137
- ### 4. `.extend()` — Inheritance
138
-
139
- ```tsx
140
- const PrimaryButton = Button.extend`text-lg px-8`
141
- const DangerButton = Button.extend({
142
- classes: "bg-red-600 hover:bg-red-700",
143
- defaultVariants: { intent: "primary" }
144
- })
145
- ```
146
-
147
- ### 5. States — Boolean Props
148
-
149
- ```tsx
150
- // states di-resolve via Rust bitmask lookup — O(1), tidak ada runtime overhead
151
- const Badge = tw.span({
152
- base: "inline-flex px-2 py-1 rounded text-sm font-medium",
153
- states: {
154
- active: "bg-green-100 text-green-800",
155
- warning: "bg-yellow-100 text-yellow-800",
156
- error: "bg-red-100 text-red-800",
157
- },
158
- })
159
-
160
- <Badge active>Online</Badge>
161
- <Badge error>Error</Badge>
162
- ```
163
-
164
- ### 6. Dark Mode
165
-
166
- Dark mode bekerja otomatis via `prefers-color-scheme` — tidak perlu konfigurasi tambahan:
167
-
168
- ```tsx
169
- const Card = tw.div({
170
- base: "bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100",
171
- sub: {
172
- header: "border-b border-gray-200 dark:border-gray-700",
173
- },
174
- })
175
- ```
176
-
177
- ### 7. Compound Variants
178
-
179
- ```tsx
180
- const Button = tw.button({
181
- base: "...",
182
- variants: {
183
- intent: { primary: "...", outline: "..." },
184
- size: { sm: "...", lg: "..." },
185
- },
186
- compoundVariants: [
187
- // Kalau intent=primary AND size=lg → tambah class ini
188
- { intent: "primary", size: "lg", class: "shadow-lg" },
189
- ],
190
- })
191
- ```
192
-
193
- ### 8. .withSub — Strict TypeScript untuk Template Literals
194
-
195
- ```tsx
196
- const Button = tw.button`
197
- flex h-12 px-5 rounded-full
198
- icon { flex h-4 w-4 }
199
- badge { absolute -top-1 -right-1 }
200
- `.withSub<"icon" | "badge">()
201
-
202
- Button.icon // ✅ autocomplete
203
- Button.badge // ✅ autocomplete
204
- Button.xyz // ❌ TypeScript error
205
- ```
206
-
207
- ---
208
-
209
- ## Bagaimana CSS Di-generate?
210
-
211
- Pipeline baru di v5 — tidak lagi pakai empty rules:
212
-
213
- ```
214
- 1. withTailwindStyled (Next.js startup)
215
- └─> scanWorkspace() via Rust scanner
216
- └─> ast_extract_classes() per file
217
- └─> extract semua classes dari variants, states, sub, base
218
-
219
- 2. generateCssForClasses(classes, globals.css)
220
- └─> Tailwind JS compile(globals.css, { loadStylesheet })
221
- └─> Tailwind baca @theme inline user (custom colors, fonts, dll)
222
- └─> Generate real CSS untuk semua classes
223
- └─> LightningCSS post-process (production only)
224
- └─> tulis .next/tw-classes/_initial-scan.css
225
-
226
- 3. globals.css: @source "../.next/tw-classes/**"
227
- └─> Tailwind scan class names dari _initial-scan.css
228
- └─> Generate CSS di bundle akhir
229
- ```
230
-
231
- Hasilnya `_initial-scan.css` berisi real CSS (bukan empty rules):
232
-
233
- ```css
234
- /* tw-classes: initial scan — auto-generated by withTailwindStyled */
235
- @layer utilities {
236
- .bg-foreground {
237
- background-color: var(--foreground);
238
- }
239
- .text-foreground {
240
- color: var(--foreground);
241
- }
242
- .hover\:bg-foreground {
243
- &:hover {
244
- background-color: var(--foreground);
245
- }
246
- }
247
- /* ... */
248
- }
249
- ```
250
-
251
- Custom colors dari `@theme inline` di `globals.css` otomatis ter-generate — tidak perlu konfigurasi tambahan.
252
-
253
- ---
254
-
255
- ## Setup Next.js
256
-
257
- ### next.config.ts
258
-
259
- ```ts
260
- import { withTailwindStyled } from "tailwind-styled-v4/next"
261
- import type { NextConfig } from "next"
262
-
263
- const nextConfig: NextConfig = {}
264
-
265
- export default withTailwindStyled({ verbose: true })(nextConfig)
266
- ```
267
-
268
- ### globals.css
269
-
270
- ```css
271
- @import "tailwindcss";
272
- @source "../.next/tw-classes/**";
273
-
274
- :root {
275
- --background: #ffffff;
276
- --foreground: #171717;
277
- }
278
-
279
- @theme inline {
280
- --color-background: var(--background);
281
- --color-foreground: var(--foreground);
282
- --font-sans: var(--font-geist-sans);
283
- --font-mono: var(--font-geist-mono);
284
- }
285
-
286
- @media (prefers-color-scheme: dark) {
287
- :root {
288
- --background: #0a0a0a;
289
- --foreground: #ededed;
290
- }
291
- }
292
- ```
293
-
294
- ---
295
-
296
- ## Bundler Integration
297
-
298
- ### Vite
299
-
300
- ```ts
301
- import { defineConfig } from "vite"
302
- import react from "@vitejs/plugin-react"
303
- import { tailwindStyled } from "tailwind-styled-v4/vite"
304
-
305
- export default defineConfig({
306
- plugins: [react(), tailwindStyled()],
307
- })
308
- ```
309
-
310
- ### Rspack
311
-
312
- ```js
313
- import { defineConfig } from "@rspack/cli"
314
- import { tailwindStyled } from "tailwind-styled-v4/rspack"
315
-
316
- export default defineConfig({
317
- entry: "./src/index.ts",
318
- plugins: [tailwindStyled()],
319
- })
320
- ```
321
-
322
- ---
323
-
324
- ## CLI
325
-
326
- ```bash
327
- # Setup otomatis (detect bundler, patch config, pre-warm cache)
328
- npx tw setup
329
-
330
- # Verifikasi setup
331
- npx tw preflight
332
-
333
- # Analisis workspace
334
- npx tw audit
335
-
336
- # Benchmark performa
337
- npx tw benchmark
338
- ```
339
-
340
- ---
341
-
342
- ## Kenapa Bukan styled-components?
343
-
344
- styled-components inject `<style>` tag ke DOM saat runtime — setiap component punya hash class (`sc-abc123 dEfGhI`) yang di-generate di browser. Masalahnya:
345
-
346
- - **Runtime overhead** — ~15KB JS untuk generate + inject CSS
347
- - **SSR mismatch** — hash bisa berbeda antara server dan client → hydration warning
348
- - **DevTools susah dibaca** — `sc-abc123` tidak informatif
349
- - **Butuh setup khusus** — `ServerStyleSheet`, `StyledEngineProvider`, dll untuk Next.js App Router
350
-
351
- `tailwind-styled-v4` tidak punya masalah ini karena CSS sudah di-bundle sebelum browser buka halaman. Class name readable, SSR dan CSR identik, tidak ada runtime overhead.
352
-
353
- ---
354
-
355
- ## Benchmark
356
-
357
- Diukur di Node.js 22, Rust 1.75.
358
-
359
- | Operasi | tailwind-styled-v4 | Tailwind CSS (JS) | Speedup |
360
- |---|---|---|---|
361
- | Scan 1000 file | **0.8 ms** | ~340 ms | **~425×** |
362
- | Compile 500 class | **0.02 ms** | ~1.2 ms | **~60×** |
363
- | Parse class string | **0.010 ms** | ~0.8 ms | **~80×** |
364
- | Cache read/write | **0.009 ms** | ~0.5 ms | **~55×** |
365
- | Watch mode rebuild | **< 5 ms** | ~85 ms | **~17×** |
366
-
367
- ---
368
-
369
- ## Arsitektur
370
-
371
- ```
372
- tailwind-styled-v4/
373
- ├── native/ # Rust engine (NAPI-RS)
374
- │ ├── src/application/
375
- │ │ ├── ast_extract.rs # Extract Tailwind classes dari source files
376
- │ │ ├── variant_resolver.rs # Variant resolution with precedence
377
- │ │ ├── variant_system.rs # Variant composition system
378
- │ │ └── theme_resolver_pool.rs # Multi-tier caching
379
- │ ├── src/domain/
380
- │ │ ├── variants.rs # Variant resolution (props override defaults)
381
- │ │ ├── variant_precedence.rs # Precedence calculation
382
- │ │ └── transform.rs # Transform object config → JS component
383
- │ └── src/infrastructure/
384
- │ ├── napi_bridge_*.rs # Modularized NAPI bridges
385
- │ └── cache_*.rs # Multi-tier cache backends
386
-
387
- ├── packages/
388
- │ ├── domain/
389
- │ │ ├── core/ # tw, cx, cv, cn — core API + createComponent
390
- │ │ ├── compiler/ # Tailwind JS + LightningCSS pipeline
391
- │ │ └── scanner/ # File scanner (Rust-backed)
392
- │ ├── presentation/
393
- │ │ ├── next/ # Next.js plugin (withTailwindStyled)
394
- │ │ ├── vite/ # Vite plugin
395
- │ │ └── rspack/ # Rspack plugin
396
- │ └── infrastructure/
397
- │ └── cli/ # CLI (tw setup, tw audit, dll)
398
-
399
- ├── config/ # Configuration files (centralized)
400
- │ ├── biome.json
401
- │ ├── tsconfig.base.json
402
- │ ├── turbo.json
403
- │ └── ...
404
-
405
- ├── docs/
406
- │ ├── archive/ # Phase docs, session summaries, reference
407
- │ ├── phase-4/, phase-5/, phase-6/ # Phase-specific documentation
408
- │ └── api/ # API reference
409
- ```
410
-
411
- **New Structure (Phase 7):**
412
- - Configuration files centralized in `config/` directory
413
- - Documentation archived in `docs/archive/` for cleaner root
414
- - Modularized NAPI bridges (`napi_bridge_*.rs`) for better maintainability
415
- - Phase-specific docs in dedicated directories
416
-
417
- ---
418
-
419
- ## TypeScript
420
-
421
- Library ini fully typed — tidak ada `any` di public API:
422
-
423
- ```tsx
424
- // Type inference otomatis dari config
425
- const Button = tw.button({
426
- variants: {
427
- intent: { primary: "...", ghost: "...", outline: "..." },
428
- size: { sm: "...", md: "...", lg: "..." },
429
- },
430
- defaultVariants: { intent: "primary", size: "md" },
431
- })
432
-
433
- // TypeScript tahu props yang valid
434
- <Button intent="invalid" /> // ❌ Type error
435
- <Button intent="primary" /> // ✅
436
-
437
- // Sub-components — ExtractSubName type inference
438
- const Card = tw.div({
439
- sub: {
440
- header: "font-bold",
441
- "div:action": "flex gap-3", // → Card.action (tag prefix di-strip otomatis)
442
- },
443
- })
444
-
445
- Card.action // ✅ autocomplete
446
- Card.xyz // ❌ TypeScript error
447
- ```
448
-
449
- ---
450
-
451
- ## Environment Variables
452
-
453
- | Variable | Default | Deskripsi |
454
- |---|---|---|
455
- | `TWS_LOG_LEVEL` | `info` | `debug\|info\|warn\|error\|silent` |
456
- | `TWS_DEBUG_SCANNER` | `0` | `1` = aktifkan scanner debug logs |
457
- | `STUDIO_PORT` | `3030` | Port studio server |
458
-
459
- ---
460
-
461
- ## Architecture Updates (Phase 7)
462
-
463
- ### R1-R6: Parser Consolidation through Resolver Caching ✅ Completed 2026-06-12
464
-
465
- Recent Phase 7 updates span multiple refactoring rounds:
466
-
467
- **R1: Parser Consolidation** ✅
468
- - Single unified production parser (v2-based)
469
- - ~5% binary size reduction
470
- - 100% backward compatible, all 545+ tests passing
471
-
472
- **R2-R3: Infrastructure Modularization** ✅
473
- - NAPI bridge modularized into specialized modules
474
- - Comprehensive integration tests covering all layers
475
- - Cache backend infrastructure refactored
476
-
477
- **R4: Property Testing Framework** ✅
478
- - 6 core properties verified across 53 test cases
479
- - Parser determinism property testing
480
- - Round-trip parsing validation
481
- - Cache consistency & eviction properties
482
-
483
- **R5: Variant Precedence System** ✅
484
- - Native variant resolution with precedence handling
485
- - Compound variant support
486
- - Theme-aware variant composition
487
-
488
- **R6: Resolver Caching** ✅
489
- - Multi-tier caching for theme resolver
490
- - Performance optimization verified
491
-
492
- For architecture details and improvements roadmap, see:
493
- - [Phase 7 Architecture Design](.kiro/specs/phase-7-architecture/design.md)
494
- - [R4 Property Tests Design](.kiro/specs/phase-7-architecture/R4_PROPERTY_TESTS_DESIGN.md)
495
- - [R5 Variant Precedence Design](.kiro/specs/phase-7-architecture/R5_VARIANT_PRECEDENCE_DESIGN.md)
496
- - [Full spec directory](.kiro/specs/phase-7-architecture/)
497
-
498
- ---
499
-
500
- ## Recent Changes (82 commits, not yet pushed)
501
-
502
- ### Infrastructure & Organization 🏗️
503
- - **Config centralization** — moved 6 root config files to `config/` directory
504
- - **Docs reorganization** — 42 summary/reference files moved to `docs/archive/`
505
- - **Benchmarking suite** — added comprehensive performance benchmarking (`native/benches/`)
506
-
507
- ### Rust Engine Enhancements 🦀
508
- - **Modularized NAPI bridges** — split monolithic bridge into specialized modules:
509
- - `napi_bridge_cache.rs` — caching layer
510
- - `napi_bridge_redis.rs` — distributed cache
511
- - `napi_bridge_theme.rs` — theme resolution
512
- - `napi_bridge_variants.rs` — variant composition
513
- - And 5 more specialized modules
514
- - **Theme resolver pool** — multi-tier caching with adaptive strategies
515
- - **Variant system improvements** — precedence calculation, compound variant support
516
-
517
- ### Testing & Validation ✅
518
- - **Property testing** — 6 core properties across 53 test cases
519
- - **Integration tests** — comprehensive NAPI module tests (1000+ tests added)
520
- - **Variant precedence tests** — 493+ test cases for variant resolution
521
- - **Performance benchmarks** — week8, week9 scale testing suites
522
-
523
- ### TypeScript/JS Improvements
524
- - **Native bridge refactor** — simplified async/sync patterns, improved error handling
525
- - **Cache integration** — unified cache interface across Redis, LRU, and file-based backends
526
- - **Stream support** — added streaming CSS compilation
527
-
528
- ### Documentation 📚
529
- - **Phase 7 specs** — comprehensive design docs in `.kiro/specs/phase-7-architecture/`
530
- - **NAPI module guide** — `MIGRATION_GUIDE_PHASE_7_3.md`
531
- - **Architecture docs** — modular bridge patterns and integration guide
532
-
533
- ---
534
-
535
- ```bash
536
- git clone https://github.com/Dictionar32/tailwind-styled-v4.git
537
- cd tailwind-styled-v4
538
-
539
- npm install
540
-
541
- # Build Rust binary + semua packages
542
- npm run build
543
-
544
- # Build Rust only
545
- npm run build:rust
546
-
547
- # Test
548
- npm run test
549
-
550
- # Dev mode
551
- npm run dev
552
-
553
- # Benchmark
554
- npm run bench
555
- ```
556
-
557
- **Requirements:**
558
- - Node.js 20+
559
- - Rust 1.75+ (untuk build dari source)
560
-
561
- ---
562
-
563
- ## Contributing
564
-
565
- PR dan issue sangat welcome!
566
-
567
- Prioritas saat ini:
568
- - [ ] macOS & Windows pre-built binary
569
- - [ ] Docs website (VitePress)
570
- - [ ] More bundler adapters
571
-
572
- ---
573
-
574
- ## License
575
-
1
+ <div align="center">
2
+
3
+ # tailwind-styled-v4
4
+
5
+ ### ⚡ Rust-powered Tailwind CSS v4 untuk React
6
+ **Build-time compiler · Zero runtime overhead · RSC-aware · Next.js / Vite / Rspack**
7
+
8
+ [![npm](https://img.shields.io/npm/v/tailwind-styled-v4?color=blue)](https://npmjs.com/package/tailwind-styled-v4)
9
+ [![license](https://img.shields.io/npm/l/tailwind-styled-v4)](LICENSE)
10
+ [![Rust](https://img.shields.io/badge/Rust-1.75+-orange?logo=rust)](https://rust-lang.org)
11
+ [![Node](https://img.shields.io/badge/Node.js-20+-green?logo=node.js)](https://nodejs.org)
12
+ [![test](https://img.shields.io/badge/tests-84%2F86%20passing-brightgreen)](#)
13
+ [![bundle](https://img.shields.io/badge/runtime-~4.5kb-green)](https://bundlephobia.com/package/tailwind-styled-v4)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## Apa ini?
20
+
21
+ `tailwind-styled-v4` adalah library styling untuk React yang menggabungkan **DX styled-components** dengan **performa Tailwind CSS v4** dan **engine berbasis Rust**. Tulis komponen dengan `tw.button` atau `tw.div({ variants })` — compiler extract dan optimasi CSS di build time, bukan runtime.
22
+
23
+ **Perbandingan singkat:**
24
+
25
+ | | tailwind-styled-v4 | styled-components | Tailwind CSS biasa |
26
+ |---|---|---|---|
27
+ | Build-time CSS | ✅ | ❌ (runtime inject) | ✅ |
28
+ | Runtime overhead | ~0 | ~15KB | ~0 |
29
+ | Variants API | ✅ type-safe | terbatas | ❌ |
30
+ | SSR/RSC support | ✅ zero config | ⚠️ butuh ServerStyleSheet | ✅ manual |
31
+ | Hydration mismatch | ✅ tidak ada | ⚠️ hash bisa beda | ✅ tidak ada |
32
+ | DevTools readable | ✅ class name jelas | ❌ hash (`sc-abc123`) | ✅ |
33
+ | Engine | 🦀 Rust | JS | JS |
34
+ | Dark mode | ✅ `dark:` prefix | manual | ✅ |
35
+ | TypeScript | ✅ full inference | partial | ✅ |
36
+
37
+ ---
38
+
39
+ ## Instalasi
40
+
41
+ ```bash
42
+ npm install tailwind-styled-v4
43
+
44
+ # Setup otomatis
45
+ npx tw setup
46
+ ```
47
+
48
+ `npx tw setup` akan otomatis:
49
+ - Mendeteksi bundler (Next.js / Vite / Rspack)
50
+ - Meng-inject plugin ke `next.config.ts` / `vite.config.ts`
51
+ - Membuat `tailwind-styled.config.json` dengan CSS entry yang terdeteksi otomatis
52
+ - Menambahkan `@import "tailwindcss"` ke CSS entry
53
+ - Pre-warming scanner cache supaya dev pertama tidak cache miss
54
+
55
+ ---
56
+
57
+ ## Quick Start
58
+
59
+ ### 1. Template Literal
60
+
61
+ ```tsx
62
+ import { tw } from "tailwind-styled-v4"
63
+
64
+ const Button = tw.button`
65
+ inline-flex items-center rounded-lg px-4 py-2
66
+ bg-blue-600 text-white font-medium
67
+ hover:bg-blue-700 transition
68
+ `
69
+
70
+ <Button onClick={handleClick}>Klik saya</Button>
71
+ ```
72
+
73
+ ### 2. Object Config + Variants
74
+
75
+ ```tsx
76
+ const Button = tw.button({
77
+ base: "inline-flex items-center rounded-full px-5 py-2 font-medium transition-all",
78
+ variants: {
79
+ intent: {
80
+ primary: "bg-foreground text-background hover:bg-[#383838]",
81
+ secondary: "bg-white text-gray-900 border border-gray-300 hover:bg-gray-50",
82
+ outline: "bg-transparent border-2 border-foreground text-foreground hover:bg-foreground hover:text-background",
83
+ ghost: "bg-transparent text-foreground hover:bg-gray-100",
84
+ },
85
+ size: {
86
+ sm: "h-10 px-4 text-sm rounded-lg",
87
+ md: "h-12 px-5 text-base rounded-full",
88
+ lg: "h-14 px-6 text-lg rounded-full",
89
+ },
90
+ },
91
+ defaultVariants: { intent: "primary", size: "md" },
92
+ states: {
93
+ loading: "opacity-60 cursor-wait pointer-events-none",
94
+ disabled: "opacity-50 cursor-not-allowed",
95
+ fullWidth: "w-full",
96
+ },
97
+ })
98
+
99
+ // TypeScript tahu variant apa yang valid — autocomplete ✅
100
+ <Button intent="primary" size="lg">Submit</Button>
101
+ <Button intent="ghost">Batal</Button>
102
+ <Button intent="outline" size="sm">Edit</Button>
103
+ <Button loading>Memproses...</Button>
104
+ ```
105
+
106
+ ### 3. Sub-components
107
+
108
+ ```tsx
109
+ const Card = tw.div({
110
+ base: "rounded-xl bg-white shadow-md overflow-hidden",
111
+ sub: {
112
+ header: "px-6 py-4 border-b font-semibold",
113
+ main: "px-6 py-4",
114
+ footer: "px-6 py-4 border-t text-sm text-gray-400",
115
+ "div:action": "px-6 py-4 flex gap-3", // render <div>, akses Card.action
116
+ },
117
+ states: {
118
+ selected: "ring-2 ring-blue-500",
119
+ disabled: "opacity-50 pointer-events-none",
120
+ },
121
+ })
122
+
123
+ // Penggunaan
124
+ <Card selected>
125
+ <Card.header>Judul Card</Card.header>
126
+ <Card.main>Konten card di sini.</Card.main>
127
+ <Card.action>
128
+ <Button>Lihat Detail</Button>
129
+ <Button intent="ghost">Batal</Button>
130
+ </Card.action>
131
+ <Card.footer>Updated 2 hours ago</Card.footer>
132
+ </Card>
133
+ ```
134
+
135
+ Format `"tag:name"` untuk sub-components — misalnya `"div:action"` render sebagai `<div>` dengan akses via `Card.action`. TypeScript otomatis strip prefix tag dari type inference.
136
+
137
+ ### 4. `.extend()` — Inheritance
138
+
139
+ ```tsx
140
+ const PrimaryButton = Button.extend`text-lg px-8`
141
+ const DangerButton = Button.extend({
142
+ classes: "bg-red-600 hover:bg-red-700",
143
+ defaultVariants: { intent: "primary" }
144
+ })
145
+ ```
146
+
147
+ ### 5. States — Boolean Props
148
+
149
+ ```tsx
150
+ // states di-resolve via Rust bitmask lookup — O(1), tidak ada runtime overhead
151
+ const Badge = tw.span({
152
+ base: "inline-flex px-2 py-1 rounded text-sm font-medium",
153
+ states: {
154
+ active: "bg-green-100 text-green-800",
155
+ warning: "bg-yellow-100 text-yellow-800",
156
+ error: "bg-red-100 text-red-800",
157
+ },
158
+ })
159
+
160
+ <Badge active>Online</Badge>
161
+ <Badge error>Error</Badge>
162
+ ```
163
+
164
+ ### 6. Dark Mode
165
+
166
+ Dark mode bekerja otomatis via `prefers-color-scheme` — tidak perlu konfigurasi tambahan:
167
+
168
+ ```tsx
169
+ const Card = tw.div({
170
+ base: "bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100",
171
+ sub: {
172
+ header: "border-b border-gray-200 dark:border-gray-700",
173
+ },
174
+ })
175
+ ```
176
+
177
+ ### 7. Compound Variants
178
+
179
+ ```tsx
180
+ const Button = tw.button({
181
+ base: "...",
182
+ variants: {
183
+ intent: { primary: "...", outline: "..." },
184
+ size: { sm: "...", lg: "..." },
185
+ },
186
+ compoundVariants: [
187
+ // Kalau intent=primary AND size=lg → tambah class ini
188
+ { intent: "primary", size: "lg", class: "shadow-lg" },
189
+ ],
190
+ })
191
+ ```
192
+
193
+ ### 8. .withSub — Strict TypeScript untuk Template Literals
194
+
195
+ ```tsx
196
+ const Button = tw.button`
197
+ flex h-12 px-5 rounded-full
198
+ icon { flex h-4 w-4 }
199
+ badge { absolute -top-1 -right-1 }
200
+ `.withSub<"icon" | "badge">()
201
+
202
+ Button.icon // ✅ autocomplete
203
+ Button.badge // ✅ autocomplete
204
+ Button.xyz // ❌ TypeScript error
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Bagaimana CSS Di-generate?
210
+
211
+ Pipeline baru di v5 — tidak lagi pakai empty rules:
212
+
213
+ ```
214
+ 1. withTailwindStyled (Next.js startup)
215
+ └─> scanWorkspace() via Rust scanner
216
+ └─> ast_extract_classes() per file
217
+ └─> extract semua classes dari variants, states, sub, base
218
+
219
+ 2. generateCssForClasses(classes, globals.css)
220
+ └─> Tailwind JS compile(globals.css, { loadStylesheet })
221
+ └─> Tailwind baca @theme inline user (custom colors, fonts, dll)
222
+ └─> Generate real CSS untuk semua classes
223
+ └─> LightningCSS post-process (production only)
224
+ └─> tulis .next/tw-classes/_initial-scan.css
225
+
226
+ 3. globals.css: @source "../.next/tw-classes/**"
227
+ └─> Tailwind scan class names dari _initial-scan.css
228
+ └─> Generate CSS di bundle akhir
229
+ ```
230
+
231
+ Hasilnya `_initial-scan.css` berisi real CSS (bukan empty rules):
232
+
233
+ ```css
234
+ /* tw-classes: initial scan — auto-generated by withTailwindStyled */
235
+ @layer utilities {
236
+ .bg-foreground {
237
+ background-color: var(--foreground);
238
+ }
239
+ .text-foreground {
240
+ color: var(--foreground);
241
+ }
242
+ .hover\:bg-foreground {
243
+ &:hover {
244
+ background-color: var(--foreground);
245
+ }
246
+ }
247
+ /* ... */
248
+ }
249
+ ```
250
+
251
+ Custom colors dari `@theme inline` di `globals.css` otomatis ter-generate — tidak perlu konfigurasi tambahan.
252
+
253
+ ---
254
+
255
+ ## Setup Next.js
256
+
257
+ ### next.config.ts
258
+
259
+ ```ts
260
+ import { withTailwindStyled } from "tailwind-styled-v4/next"
261
+ import type { NextConfig } from "next"
262
+
263
+ const nextConfig: NextConfig = {}
264
+
265
+ export default withTailwindStyled({ verbose: true })(nextConfig)
266
+ ```
267
+
268
+ ### globals.css
269
+
270
+ ```css
271
+ @import "tailwindcss";
272
+ @source "../.next/tw-classes/**";
273
+
274
+ :root {
275
+ --background: #ffffff;
276
+ --foreground: #171717;
277
+ }
278
+
279
+ @theme inline {
280
+ --color-background: var(--background);
281
+ --color-foreground: var(--foreground);
282
+ --font-sans: var(--font-geist-sans);
283
+ --font-mono: var(--font-geist-mono);
284
+ }
285
+
286
+ @media (prefers-color-scheme: dark) {
287
+ :root {
288
+ --background: #0a0a0a;
289
+ --foreground: #ededed;
290
+ }
291
+ }
292
+ ```
293
+
294
+ ---
295
+
296
+ ## Bundler Integration
297
+
298
+ ### Vite
299
+
300
+ ```ts
301
+ import { defineConfig } from "vite"
302
+ import react from "@vitejs/plugin-react"
303
+ import { tailwindStyled } from "tailwind-styled-v4/vite"
304
+
305
+ export default defineConfig({
306
+ plugins: [react(), tailwindStyled()],
307
+ })
308
+ ```
309
+
310
+ ### Rspack
311
+
312
+ ```js
313
+ import { defineConfig } from "@rspack/cli"
314
+ import { tailwindStyled } from "tailwind-styled-v4/rspack"
315
+
316
+ export default defineConfig({
317
+ entry: "./src/index.ts",
318
+ plugins: [tailwindStyled()],
319
+ })
320
+ ```
321
+
322
+ ---
323
+
324
+ ## CLI
325
+
326
+ ```bash
327
+ # Setup otomatis (detect bundler, patch config, pre-warm cache)
328
+ npx tw setup
329
+
330
+ # Verifikasi setup
331
+ npx tw preflight
332
+
333
+ # Analisis workspace
334
+ npx tw audit
335
+
336
+ # Benchmark performa
337
+ npx tw benchmark
338
+ ```
339
+
340
+ ---
341
+
342
+ ## Kenapa Bukan styled-components?
343
+
344
+ styled-components inject `<style>` tag ke DOM saat runtime — setiap component punya hash class (`sc-abc123 dEfGhI`) yang di-generate di browser. Masalahnya:
345
+
346
+ - **Runtime overhead** — ~15KB JS untuk generate + inject CSS
347
+ - **SSR mismatch** — hash bisa berbeda antara server dan client → hydration warning
348
+ - **DevTools susah dibaca** — `sc-abc123` tidak informatif
349
+ - **Butuh setup khusus** — `ServerStyleSheet`, `StyledEngineProvider`, dll untuk Next.js App Router
350
+
351
+ `tailwind-styled-v4` tidak punya masalah ini karena CSS sudah di-bundle sebelum browser buka halaman. Class name readable, SSR dan CSR identik, tidak ada runtime overhead.
352
+
353
+ ---
354
+
355
+ ## Benchmark
356
+
357
+ Diukur di Node.js 22, Rust 1.75.
358
+
359
+ | Operasi | tailwind-styled-v4 | Tailwind CSS (JS) | Speedup |
360
+ |---|---|---|---|
361
+ | Scan 1000 file | **0.8 ms** | ~340 ms | **~425×** |
362
+ | Compile 500 class | **0.02 ms** | ~1.2 ms | **~60×** |
363
+ | Parse class string | **0.010 ms** | ~0.8 ms | **~80×** |
364
+ | Cache read/write | **0.009 ms** | ~0.5 ms | **~55×** |
365
+ | Watch mode rebuild | **< 5 ms** | ~85 ms | **~17×** |
366
+
367
+ ---
368
+
369
+ ## Arsitektur
370
+
371
+ ```
372
+ tailwind-styled-v4/
373
+ ├── native/ # Rust engine (NAPI-RS)
374
+ │ ├── src/application/
375
+ │ │ ├── ast_extract.rs # Extract Tailwind classes dari source files
376
+ │ │ ├── variant_resolver.rs # Variant resolution with precedence
377
+ │ │ ├── variant_system.rs # Variant composition system
378
+ │ │ └── theme_resolver_pool.rs # Multi-tier caching
379
+ │ ├── src/domain/
380
+ │ │ ├── variants.rs # Variant resolution (props override defaults)
381
+ │ │ ├── variant_precedence.rs # Precedence calculation
382
+ │ │ └── transform.rs # Transform object config → JS component
383
+ │ └── src/infrastructure/
384
+ │ ├── napi_bridge_*.rs # Modularized NAPI bridges
385
+ │ └── cache_*.rs # Multi-tier cache backends
386
+
387
+ ├── packages/
388
+ │ ├── domain/
389
+ │ │ ├── core/ # tw, cx, cv, cn — core API + createComponent
390
+ │ │ ├── compiler/ # Tailwind JS + LightningCSS pipeline
391
+ │ │ └── scanner/ # File scanner (Rust-backed)
392
+ │ ├── presentation/
393
+ │ │ ├── next/ # Next.js plugin (withTailwindStyled)
394
+ │ │ ├── vite/ # Vite plugin
395
+ │ │ └── rspack/ # Rspack plugin
396
+ │ └── infrastructure/
397
+ │ └── cli/ # CLI (tw setup, tw audit, dll)
398
+
399
+ ├── config/ # Configuration files (centralized)
400
+ │ ├── biome.json
401
+ │ ├── tsconfig.base.json
402
+ │ ├── turbo.json
403
+ │ └── ...
404
+
405
+ ├── docs/
406
+ │ ├── archive/ # Phase docs, session summaries, reference
407
+ │ ├── phase-4/, phase-5/, phase-6/ # Phase-specific documentation
408
+ │ └── api/ # API reference
409
+ ```
410
+
411
+ **New Structure (Phase 7):**
412
+ - Configuration files centralized in `config/` directory
413
+ - Documentation archived in `docs/archive/` for cleaner root
414
+ - Modularized NAPI bridges (`napi_bridge_*.rs`) for better maintainability
415
+ - Phase-specific docs in dedicated directories
416
+
417
+ ---
418
+
419
+ ## TypeScript
420
+
421
+ Library ini fully typed — tidak ada `any` di public API:
422
+
423
+ ```tsx
424
+ // Type inference otomatis dari config
425
+ const Button = tw.button({
426
+ variants: {
427
+ intent: { primary: "...", ghost: "...", outline: "..." },
428
+ size: { sm: "...", md: "...", lg: "..." },
429
+ },
430
+ defaultVariants: { intent: "primary", size: "md" },
431
+ })
432
+
433
+ // TypeScript tahu props yang valid
434
+ <Button intent="invalid" /> // ❌ Type error
435
+ <Button intent="primary" /> // ✅
436
+
437
+ // Sub-components — ExtractSubName type inference
438
+ const Card = tw.div({
439
+ sub: {
440
+ header: "font-bold",
441
+ "div:action": "flex gap-3", // → Card.action (tag prefix di-strip otomatis)
442
+ },
443
+ })
444
+
445
+ Card.action // ✅ autocomplete
446
+ Card.xyz // ❌ TypeScript error
447
+ ```
448
+
449
+ ---
450
+
451
+ ## Environment Variables
452
+
453
+ | Variable | Default | Deskripsi |
454
+ |---|---|---|
455
+ | `TWS_LOG_LEVEL` | `info` | `debug\|info\|warn\|error\|silent` |
456
+ | `TWS_DEBUG_SCANNER` | `0` | `1` = aktifkan scanner debug logs |
457
+ | `STUDIO_PORT` | `3030` | Port studio server |
458
+
459
+ ---
460
+
461
+ ## Architecture Updates (Phase 7)
462
+
463
+ ### R1-R6: Parser Consolidation through Resolver Caching ✅ Completed 2026-06-12
464
+
465
+ Recent Phase 7 updates span multiple refactoring rounds:
466
+
467
+ **R1: Parser Consolidation** ✅
468
+ - Single unified production parser (v2-based)
469
+ - ~5% binary size reduction
470
+ - 100% backward compatible, all 545+ tests passing
471
+
472
+ **R2-R3: Infrastructure Modularization** ✅
473
+ - NAPI bridge modularized into specialized modules
474
+ - Comprehensive integration tests covering all layers
475
+ - Cache backend infrastructure refactored
476
+
477
+ **R4: Property Testing Framework** ✅
478
+ - 6 core properties verified across 53 test cases
479
+ - Parser determinism property testing
480
+ - Round-trip parsing validation
481
+ - Cache consistency & eviction properties
482
+
483
+ **R5: Variant Precedence System** ✅
484
+ - Native variant resolution with precedence handling
485
+ - Compound variant support
486
+ - Theme-aware variant composition
487
+
488
+ **R6: Resolver Caching** ✅
489
+ - Multi-tier caching for theme resolver
490
+ - Performance optimization verified
491
+
492
+ For architecture details and improvements roadmap, see:
493
+ - [Phase 7 Architecture Design](.kiro/specs/phase-7-architecture/design.md)
494
+ - [R4 Property Tests Design](.kiro/specs/phase-7-architecture/R4_PROPERTY_TESTS_DESIGN.md)
495
+ - [R5 Variant Precedence Design](.kiro/specs/phase-7-architecture/R5_VARIANT_PRECEDENCE_DESIGN.md)
496
+ - [Full spec directory](.kiro/specs/phase-7-architecture/)
497
+
498
+ ---
499
+
500
+ ## Recent Changes (82 commits, not yet pushed)
501
+
502
+ ### Infrastructure & Organization 🏗️
503
+ - **Config centralization** — moved 6 root config files to `config/` directory
504
+ - **Docs reorganization** — 42 summary/reference files moved to `docs/archive/`
505
+ - **Benchmarking suite** — added comprehensive performance benchmarking (`native/benches/`)
506
+
507
+ ### Rust Engine Enhancements 🦀
508
+ - **Modularized NAPI bridges** — split monolithic bridge into specialized modules:
509
+ - `napi_bridge_cache.rs` — caching layer
510
+ - `napi_bridge_redis.rs` — distributed cache
511
+ - `napi_bridge_theme.rs` — theme resolution
512
+ - `napi_bridge_variants.rs` — variant composition
513
+ - And 5 more specialized modules
514
+ - **Theme resolver pool** — multi-tier caching with adaptive strategies
515
+ - **Variant system improvements** — precedence calculation, compound variant support
516
+
517
+ ### Testing & Validation ✅
518
+ - **Property testing** — 6 core properties across 53 test cases
519
+ - **Integration tests** — comprehensive NAPI module tests (1000+ tests added)
520
+ - **Variant precedence tests** — 493+ test cases for variant resolution
521
+ - **Performance benchmarks** — week8, week9 scale testing suites
522
+
523
+ ### TypeScript/JS Improvements
524
+ - **Native bridge refactor** — simplified async/sync patterns, improved error handling
525
+ - **Cache integration** — unified cache interface across Redis, LRU, and file-based backends
526
+ - **Stream support** — added streaming CSS compilation
527
+
528
+ ### Documentation 📚
529
+ - **Phase 7 specs** — comprehensive design docs in `.kiro/specs/phase-7-architecture/`
530
+ - **NAPI module guide** — `MIGRATION_GUIDE_PHASE_7_3.md`
531
+ - **Architecture docs** — modular bridge patterns and integration guide
532
+
533
+ ---
534
+
535
+ ```bash
536
+ git clone https://github.com/Dictionar32/tailwind-styled-v4.git
537
+ cd tailwind-styled-v4
538
+
539
+ npm install
540
+
541
+ # Build Rust binary + semua packages
542
+ npm run build
543
+
544
+ # Build Rust only
545
+ npm run build:rust
546
+
547
+ # Test
548
+ npm run test
549
+
550
+ # Dev mode
551
+ npm run dev
552
+
553
+ # Benchmark
554
+ npm run bench
555
+ ```
556
+
557
+ **Requirements:**
558
+ - Node.js 20+
559
+ - Rust 1.75+ (untuk build dari source)
560
+
561
+ ---
562
+
563
+ ## Contributing
564
+
565
+ PR dan issue sangat welcome!
566
+
567
+ Prioritas saat ini:
568
+ - [ ] macOS & Windows pre-built binary
569
+ - [ ] Docs website (VitePress)
570
+ - [ ] More bundler adapters
571
+
572
+ ---
573
+
574
+ ## License
575
+
576
576
  [MIT](LICENSE) © Dictionar32