tailwind-to-style 2.7.7 → 2.8.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/README.md CHANGED
@@ -35,6 +35,7 @@ yarn add tailwind-to-style
35
35
  The `tws` function is designed to convert Tailwind CSS utility classes into either **inline CSS** or **JSON style objects**. This makes it particularly useful for applying styles dynamically in React or similar frameworks where inline styles or style objects are often needed.
36
36
 
37
37
  #### Features of `tws`:
38
+
38
39
  - Converts Tailwind utility classes into **inline CSS** or **JSON style objects**.
39
40
 
40
41
  #### Usage
@@ -78,219 +79,204 @@ This will apply the Tailwind classes directly as inline styles in the React comp
78
79
  `twsx` is an advanced function that builds on `tws` by allowing you to define **nested styles** and more complex CSS structures. It supports **grouping**, **responsive variants**, **state variants**, **dynamic utilities**, and **direct CSS properties** via the `@css` directive, making it ideal for more advanced styling needs.
79
80
 
80
81
  #### Features of `twsx`:
81
- - Allows **nested styles** similar to SCSS, enabling more complex CSS structures.
82
- - **Grouping**: Supports grouping utilities inside parentheses, including responsive variants.
83
- - Supports **responsive variants** (`sm`, `md`, `lg`, etc.) when used within Tailwind utility classes or in grouping syntax.
84
- - Handles **state variants** like `hover`, `focus`, and more.
85
- - Supports **dynamic utilities** such as `w-[300px]`, `bg-[rgba(0,0,0,0.5)]`.
86
- - **@css directive**: Apply custom CSS properties directly for more complex styles like transitions and animations.
87
82
 
88
- #### Usage
83
+ - ✅ **Nested styles** similar to SCSS, enabling more complex CSS structures
84
+ - ✅ **Grouping**: Supports grouping utilities inside parentheses `hover:(bg-blue-600 scale-105)`
85
+ - ✅ **Responsive variants** (`sm`, `md`, `lg`, `xl`, `2xl`) in standard and grouping syntax
86
+ - ✅ **State variants** like `hover`, `focus`, `active`, `disabled`, etc.
87
+ - ✅ **Dynamic utilities** such as `w-[300px]`, `bg-[rgba(0,0,0,0.5)]`, `text-[14px]`
88
+ - ✅ **!important support** with `!text-red-500`, `!bg-blue-500`
89
+ - ✅ **@css directive**: Apply custom CSS properties for animations, transitions, and modern effects
90
+
91
+ #### Basic Usage
89
92
 
90
93
  ```javascript
91
94
  import { twsx } from "tailwind-to-style";
92
95
 
93
96
  const styles = twsx({
94
97
  ".card": [
95
- "bg-white p-4 rounded-lg",
98
+ "bg-white p-4 rounded-lg shadow-md",
96
99
  {
97
- "&:hover": "shadow-lg",
98
- ".title": "text-lg font-bold",
99
- ".desc": "text-sm text-gray-500"
100
- }
101
- ]
100
+ "&:hover": "shadow-xl scale-105",
101
+ ".title": "text-lg font-bold text-gray-900",
102
+ ".desc": "text-sm text-gray-600 mt-2",
103
+ },
104
+ ],
102
105
  });
103
106
 
104
107
  console.log(styles);
105
108
  ```
106
109
 
107
- This will generate CSS like:
110
+ **Output**:
108
111
 
109
112
  ```css
110
113
  .card {
111
- background-color: white;
114
+ background-color: rgba(255, 255, 255, var(--bg-opacity));
112
115
  padding: 1rem;
113
116
  border-radius: 0.5rem;
117
+ box-shadow:
118
+ 0 4px 6px -1px rgb(0 0 0 / 0.1),
119
+ 0 2px 4px -2px rgb(0 0 0 / 0.1);
114
120
  }
115
121
  .card:hover {
116
- box-shadow: 0 10px 15px rgba(0,0,0,0.1);
122
+ box-shadow:
123
+ 0 20px 25px -5px rgb(0 0 0 / 0.1),
124
+ 0 8px 10px -6px rgb(0 0 0 / 0.1);
125
+ transform: scale(1.05);
117
126
  }
118
127
  .card .title {
119
128
  font-size: 1.125rem;
120
- font-weight: bold;
129
+ font-weight: 700;
130
+ color: rgba(17, 24, 39, var(--text-opacity));
121
131
  }
122
132
  .card .desc {
123
133
  font-size: 0.875rem;
124
- color: #6b7280;
134
+ color: rgba(75, 85, 99, var(--text-opacity));
135
+ margin-top: 0.5rem;
125
136
  }
126
137
  ```
127
138
 
128
- #### Grouping Support:
139
+ #### Grouping Support
129
140
 
130
- With `twsx`, you can group related utilities together inside parentheses, making the CSS more modular and easier to manage. This is especially useful for responsive and state variants.
141
+ Group related utilities together inside parentheses for better readability and organization:
131
142
 
132
143
  ```javascript
133
144
  const styles = twsx({
134
145
  ".button": [
135
- "bg-blue-500 text-white p-2 rounded-md",
136
- {
137
- "&:hover": "bg-blue-600",
138
- ".icon": "text-lg"
139
- }
140
- ]
146
+ "bg-blue-500 text-white px-6 py-3 rounded-lg",
147
+ "hover:(bg-blue-600 scale-105 shadow-lg)",
148
+ "focus:(ring-2 ring-blue-300 outline-none)",
149
+ "active:(bg-blue-700 scale-95)",
150
+ ],
141
151
  });
142
-
143
- console.log(styles);
144
152
  ```
145
153
 
146
154
  **Output**:
147
155
 
148
156
  ```css
149
157
  .button {
150
- background-color: #3b82f6;
151
- color: white;
152
- padding: 0.5rem;
153
- border-radius: 0.375rem;
158
+ background-color: rgba(59, 130, 246, var(--bg-opacity));
159
+ color: rgba(255, 255, 255, var(--text-opacity));
160
+ padding: 0.75rem 1.5rem;
161
+ border-radius: 0.5rem;
154
162
  }
155
163
  .button:hover {
156
- background-color: #2563eb;
157
- }
158
- .button .icon {
159
- font-size: 1.125rem;
164
+ background-color: rgba(37, 99, 235, var(--bg-opacity));
165
+ transform: scale(1.05);
166
+ box-shadow:
167
+ 0 10px 15px -3px rgb(0 0 0 / 0.1),
168
+ 0 4px 6px -4px rgb(0 0 0 / 0.1);
160
169
  }
161
- ```
162
-
163
- #### Dynamic Utilities:
164
-
165
- `twsx` supports dynamic values in utilities like `w-[300px]` and `bg-[rgba(0,0,0,0.5)]`.
166
-
167
- ```javascript
168
- const styles = twsx({
169
- ".box": "w-[300px] h-[50vh] bg-[rgba(0,0,0,0.5)]"
170
- });
171
-
172
- console.log(styles);
173
- ```
174
-
175
- **Output**:
176
-
177
- ```css
178
- .box {
179
- width: 300px;
180
- height: 50vh;
181
- background-color: rgba(0,0,0,0.5);
170
+ .button:focus {
171
+ box-shadow: var(--ring-offset-shadow), var(--ring-shadow);
172
+ outline: none;
182
173
  }
183
- ```
184
-
185
- #### `!important` Support
186
-
187
- You can prepend an exclamation mark (`!`) directly to the class name to make it `!important`. This feature is useful for easily overriding default styles.
188
-
189
- ```javascript
190
- const styles = twsx({
191
- ".alert": "!text-red-500 !bg-yellow-100 !p-4"
192
- });
193
-
194
- console.log(styles);
195
- ```
196
-
197
- **Output**:
198
- ```css
199
- .alert {
200
- color: #ef4444 !important;
201
- background-color: #fef3c7 !important;
202
- padding: 1rem !important;
174
+ .button:active {
175
+ background-color: rgba(29, 78, 216, var(--bg-opacity));
176
+ transform: scale(0.95);
203
177
  }
204
178
  ```
205
179
 
206
- #### Grouping Example:
180
+ #### Responsive Variants
207
181
 
208
- You can group related utilities for better readability:
182
+ Responsive variants work seamlessly with both standard syntax and grouping syntax:
209
183
 
210
184
  ```javascript
211
185
  const styles = twsx({
212
- ".alert": "hover:(bg-yellow-500 text-black) md:(px-6 py-3)"
213
- });
214
-
215
- console.log(styles);
216
- ```
217
-
218
- **Output**:
219
-
220
- ```css
221
- .alert:hover {
222
- background-color: #f59e0b;
223
- color: #000;
224
- }
225
- @media (min-width: 768px) {
226
- .alert {
227
- padding-left: 1.5rem;
228
- padding-right: 1.5rem;
229
- padding-top: 0.75rem;
230
- padding-bottom: 0.75rem;
231
- }
232
- }
233
- ```
234
-
235
- #### Responsive Variants:
236
-
237
- Responsive variants work within Tailwind utility classes and in grouping syntax:
238
-
239
- ```javascript
240
- const styles = twsx({
241
- ".responsive-card": [
242
- "w-full md:w-1/2 lg:w-1/3 p-4 bg-white",
186
+ ".hero": [
187
+ // Standard responsive syntax
188
+ "text-2xl sm:text-3xl md:text-4xl lg:text-5xl xl:text-6xl",
189
+ "w-full md:w-1/2 lg:w-1/3 p-4",
190
+ // Grouped responsive syntax
191
+ "sm:(py-16 px-4)",
192
+ "md:(py-20 px-6)",
193
+ "lg:(py-24 px-8)",
243
194
  {
244
- "&:hover": "shadow-lg transform:scale-105"
245
- }
195
+ h1: "font-bold text-gray-900",
196
+ p: "text-gray-600 mt-4",
197
+ },
246
198
  ],
247
- ".grouped-responsive": "text-sm md:(text-lg px-6) lg:(text-xl px-8)"
248
199
  });
249
200
  ```
250
201
 
251
202
  **Output**:
203
+
252
204
  ```css
253
- .responsive-card {
205
+ .hero {
206
+ font-size: 1.5rem;
254
207
  width: 100%;
255
208
  padding: 1rem;
256
- background-color: white;
209
+ }
210
+ @media (min-width: 640px) {
211
+ .hero {
212
+ font-size: 1.875rem;
213
+ padding: 4rem 1rem;
214
+ }
257
215
  }
258
216
  @media (min-width: 768px) {
259
- .responsive-card {
217
+ .hero {
218
+ font-size: 2.25rem;
260
219
  width: 50%;
220
+ padding: 5rem 1.5rem;
261
221
  }
262
222
  }
263
223
  @media (min-width: 1024px) {
264
- .responsive-card {
224
+ .hero {
225
+ font-size: 3rem;
265
226
  width: 33.333333%;
227
+ padding: 6rem 2rem;
266
228
  }
267
229
  }
268
- .responsive-card:hover {
269
- box-shadow: 0 10px 15px rgba(0,0,0,0.1);
270
- transform: scale(1.05);
271
- }
272
- .grouped-responsive {
273
- font-size: 0.875rem;
274
- }
275
- @media (min-width: 768px) {
276
- .grouped-responsive {
277
- font-size: 1.125rem;
278
- padding-left: 1.5rem;
279
- padding-right: 1.5rem;
230
+ @media (min-width: 1280px) {
231
+ .hero {
232
+ font-size: 3.75rem;
280
233
  }
281
234
  }
282
- @media (min-width: 1024px) {
283
- .grouped-responsive {
284
- font-size: 1.25rem;
285
- padding-left: 2rem;
286
- padding-right: 2rem;
287
- }
235
+ .hero h1 {
236
+ font-weight: 700;
237
+ color: rgba(17, 24, 39, var(--text-opacity));
238
+ }
239
+ .hero p {
240
+ color: rgba(75, 85, 99, var(--text-opacity));
241
+ margin-top: 1rem;
288
242
  }
289
243
  ```
290
244
 
291
- #### `@css` Direct CSS Properties:
245
+ ### Performance Utilities
292
246
 
293
- With the `@css` feature, you can directly add CSS properties that aren't available as Tailwind utilities or when you need more complex CSS values like transitions, animations, or custom properties.
247
+ The library includes performance optimization features:
248
+
249
+ #### Inject Option
250
+
251
+ Control CSS output location with the `inject` option:
252
+
253
+ ```javascript
254
+ import { tws, twsx } from "tailwind-to-style";
255
+
256
+ // Auto-inject into document head (default)
257
+ const styles1 = tws("bg-blue-500 text-white p-4");
258
+
259
+ // Skip injection - returns CSS only
260
+ const styles2 = tws("bg-red-500 text-black p-2", { inject: false });
261
+
262
+ // Custom injection target
263
+ const targetElement = document.getElementById("custom-styles");
264
+ const styles3 = tws("bg-green-500 text-yellow p-3", { inject: targetElement });
265
+ ```
266
+
267
+ #### Performance Monitoring
268
+
269
+ ```javascript
270
+ import { tws } from "tailwind-to-style";
271
+
272
+ // Enable performance logging
273
+ const start = performance.now();
274
+ const styles = tws("complex-classes here...");
275
+ const end = performance.now();
276
+ console.log(`Generation time: ${end - start}ms`);
277
+ ```
278
+
279
+ ## Advanced `@css` Directive
294
280
 
295
281
  There are several ways to use the `@css` feature:
296
282
 
@@ -303,15 +289,16 @@ const styles = twsx({
303
289
  {
304
290
  "@css": {
305
291
  transition: "all 0.3s ease-in-out",
306
- "will-change": "transform, opacity"
292
+ "will-change": "transform, opacity",
307
293
  },
308
- "&:hover": "bg-blue-600"
309
- }
310
- ]
294
+ "&:hover": "bg-blue-600",
295
+ },
296
+ ],
311
297
  });
312
298
  ```
313
299
 
314
300
  **Output**:
301
+
315
302
  ```css
316
303
  .button {
317
304
  background-color: #3b82f6;
@@ -331,7 +318,7 @@ const styles = twsx({
331
318
  const styles = twsx({
332
319
  ".button @css transition": "all 0.3s ease-in-out",
333
320
  ".button": "bg-blue-500 text-white rounded-md",
334
- ".button:hover": "bg-blue-600"
321
+ ".button:hover": "bg-blue-600",
335
322
  });
336
323
  ```
337
324
 
@@ -351,27 +338,30 @@ const styles = twsx({
351
338
  "@css": {
352
339
  transform: "translateX(0px)",
353
340
  transition: "all 0.3s ease-out",
354
- "will-change": "transform, opacity"
341
+ "will-change": "transform, opacity",
355
342
  },
356
343
  "&.hidden": [
357
344
  "opacity-0",
358
345
  {
359
346
  "@css": {
360
- transform: "translateX(-100px)"
361
- }
362
- }
363
- ]
364
- }
365
- ]
347
+ transform: "translateX(-100px)",
348
+ },
349
+ },
350
+ ],
351
+ },
352
+ ],
366
353
  });
367
354
  ```
368
355
 
369
356
  **Output**:
357
+
370
358
  ```css
371
359
  .modal {
372
360
  background-color: white;
373
361
  border-radius: 0.5rem;
374
- box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
362
+ box-shadow:
363
+ 0 20px 25px -5px rgba(0, 0, 0, 0.1),
364
+ 0 10px 10px -5px rgba(0, 0, 0, 0.04);
375
365
  transform: translateX(0px);
376
366
  transition: all 0.3s ease-out;
377
367
  will-change: transform, opacity;
@@ -386,7 +376,7 @@ For responsive styles, you can use standard Tailwind responsive utilities within
386
376
 
387
377
  ```javascript
388
378
  const styles = twsx({
389
- ".responsive-box": "w-full md:w-1/2 lg:w-1/3 p-4 bg-blue-500"
379
+ ".responsive-box": "w-full md:w-1/2 lg:w-1/3 p-4 bg-blue-500",
390
380
  });
391
381
  ```
392
382
 
@@ -449,7 +439,7 @@ performanceUtils.clearCaches();
449
439
  The library automatically tracks performance for key operations:
450
440
 
451
441
  - **tws:total** - Total execution time for `tws()`
452
- - **tws:parse** - Time spent parsing classes
442
+ - **tws:parse** - Time spent parsing classes
453
443
  - **tws:process** - Time spent processing classes
454
444
  - **twsx:total** - Total execution time for `twsx()`
455
445
  - **twsx:flatten** - Time spent flattening objects
@@ -482,12 +472,12 @@ const complexStyles = twsx({
482
472
  ".hero": [
483
473
  "bg-gradient-to-br from-indigo-900 to-purple-900 min-h-screen",
484
474
  {
485
- "h1": "text-6xl font-bold text-white md:text-4xl",
475
+ h1: "text-6xl font-bold text-white md:text-4xl",
486
476
  "@css": {
487
- transition: "font-size 0.3s ease-in-out"
488
- }
489
- }
490
- ]
477
+ transition: "font-size 0.3s ease-in-out",
478
+ },
479
+ },
480
+ ],
491
481
  });
492
482
 
493
483
  // Check performance stats
@@ -496,6 +486,63 @@ console.log(performanceUtils.getStats());
496
486
 
497
487
  This will automatically log warnings for operations taking longer than 5ms and provide insights into cache usage and performance bottlenecks.
498
488
 
489
+ # Build-Time Plugins: Vite & Webpack
490
+
491
+ ### Otomatisasi Generate CSS Modular
492
+
493
+ ### Automated Modular CSS Generation
494
+
495
+ 1. Save your modular styles in the `src/twsx/` folder as JSON files (e.g., `card.json`, `button.json`).
496
+ 2. Use the Vite/Webpack plugin from the `plugins/` folder to automatically generate CSS on every build/rebuild.
497
+ 3. All generated CSS files will be merged into a single `twsx.css` file inside `node_modules/tailwind-to-style/`.
498
+ 4. In React, simply import this file in your entry point: `import 'tailwind-to-style/twsx.css'`.
499
+
500
+ #### Contoh Penggunaan Plugin Vite
501
+
502
+ Add the plugin to your `vite.config.js`:
503
+ ```js
504
+ import twsxPlugin from './plugins/vite-twsx';
505
+
506
+ export default {
507
+ plugins: [
508
+ twsxPlugin({
509
+ twsxDir: 'src/twsx',
510
+ outDir: 'dist'
511
+ })
512
+ ]
513
+ };
514
+ ```
515
+
516
+ After build, the merged CSS file will be automatically created at `node_modules/tailwind-to-style/twsx.css`.
517
+ Import in React:
518
+ ```js
519
+ // src/index.js
520
+ import 'tailwind-to-style/twsx.css';
521
+ ```
522
+
523
+ #### Contoh Penggunaan Plugin Webpack
524
+
525
+ Add the plugin to your `webpack.config.js`:
526
+ ```js
527
+ import TwsxPlugin from './plugins/webpack-twsx';
528
+
529
+ module.exports = {
530
+ plugins: [
531
+ new TwsxPlugin({
532
+ twsxDir: 'src/twsx',
533
+ outDir: 'dist'
534
+ })
535
+ ]
536
+ };
537
+ ```
538
+
539
+ After build, the merged CSS file will be automatically created at `node_modules/tailwind-to-style/twsx.css`.
540
+ Import in React:
541
+ ```js
542
+ // src/index.js
543
+ import 'tailwind-to-style/twsx.css';
544
+ ```
545
+
499
546
  ## License
500
547
 
501
548
  ## Contributing