tailwind-to-style 2.9.2 → 2.10.0-beta.1
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 +457 -0
- package/dist/index.browser.js +1274 -376
- package/dist/index.cjs +1274 -376
- package/dist/index.d.ts +118 -2
- package/dist/index.esm.js +1261 -377
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +74 -74
package/README.md
CHANGED
|
@@ -15,6 +15,40 @@ The library exposes two main functions and a CLI tool:
|
|
|
15
15
|
2. **`twsx`**: A more advanced function that allows you to define nested and complex styles similar to SCSS, including support for responsive design, state variants, grouping, and enhanced CSS capabilities.
|
|
16
16
|
3. **`twsx-cli`**: A command-line tool for generating CSS files from `twsx.*.js` files with watch mode support.
|
|
17
17
|
|
|
18
|
+
## ✨ What's New in v2.12.0
|
|
19
|
+
|
|
20
|
+
- 🎬 **Animation Support**: Full support for `animate-spin`, `animate-pulse`, `animate-bounce`, `animate-ping`!
|
|
21
|
+
- 🔄 **Transition Utilities**: Complete transition system with `duration`, `delay`, `ease`, and property control
|
|
22
|
+
- ⏱️ **Keyframes**: Built-in keyframes with support for custom animations via `configure()`
|
|
23
|
+
- 🎨 **Custom Animations**: Create your own animations through theme extension or plugin API
|
|
24
|
+
- 📝 **Examples**: New comprehensive animation examples
|
|
25
|
+
|
|
26
|
+
Now you can create smooth transitions and eye-catching animations like Tailwind CSS!
|
|
27
|
+
|
|
28
|
+
## ✨ What's New in v2.11.0
|
|
29
|
+
|
|
30
|
+
- 🎨 **Theme Customization**: Extend default theme with custom colors, spacing, and more!
|
|
31
|
+
- 🔌 **Plugin API**: Create custom utilities with `createPlugin()` and `createUtilityPlugin()`
|
|
32
|
+
- ⚙️ **Configuration System**: Use `configure()` to set up theme and plugins
|
|
33
|
+
- 📝 **Config Files**: Support for `tailwind-to-style.config.js`
|
|
34
|
+
- 🎯 **Complete TypeScript**: Full type definitions for config and plugins
|
|
35
|
+
- 📚 **Examples**: New examples for theme customization and custom plugins
|
|
36
|
+
|
|
37
|
+
Now you can create brand-specific design systems and custom utilities!
|
|
38
|
+
|
|
39
|
+
## ✨ What's New in v2.10.0
|
|
40
|
+
|
|
41
|
+
- 🔄 **Updated Dependencies**: All dependencies updated to latest 2025 versions (ESLint 9, Jest 30, Rollup 4)
|
|
42
|
+
- 🎯 **LRU Cache**: Replaced naive caching with proper LRU implementation for better memory management
|
|
43
|
+
- 📝 **Logger System**: Configurable logging with production-safe defaults (no more console spam!)
|
|
44
|
+
- ⚠️ **Error Handling**: Event-based error system with `onError()` subscription pattern
|
|
45
|
+
- 🔒 **Singleton Pattern**: Refactored global state to testable singleton
|
|
46
|
+
- 📘 **Complete TypeScript**: Added full type definitions for all exports
|
|
47
|
+
- 🚀 **Node.js Support**: Now supports Node 18.x, 20.x, 22.x LTS (dropped EOL versions)
|
|
48
|
+
- 🔧 **ESLint 9**: Migrated to modern flat config format
|
|
49
|
+
|
|
50
|
+
All changes are **backward compatible** - your existing code continues to work!
|
|
51
|
+
|
|
18
52
|
## ✨ What's New in v2.9.0
|
|
19
53
|
|
|
20
54
|
- 🆕 **Responsive Selector Syntax**: Intuitive `'md:.title': 'text-lg'` format for responsive styling
|
|
@@ -84,6 +118,429 @@ export default App;
|
|
|
84
118
|
|
|
85
119
|
This will apply the Tailwind classes directly as inline styles in the React component.
|
|
86
120
|
|
|
121
|
+
## Advanced Features (v2.10.0+)
|
|
122
|
+
|
|
123
|
+
### Logger Configuration
|
|
124
|
+
|
|
125
|
+
Control logging behavior for production environments:
|
|
126
|
+
|
|
127
|
+
```javascript
|
|
128
|
+
import { logger } from "tailwind-to-style";
|
|
129
|
+
|
|
130
|
+
// Set log level (debug, info, warn, error, silent)
|
|
131
|
+
logger.setLevel('error'); // Only show errors in production
|
|
132
|
+
|
|
133
|
+
// Default is 'warn' in development, 'error' in production
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Error Handling
|
|
137
|
+
|
|
138
|
+
Subscribe to errors for monitoring and debugging:
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
import { onError, TwsError } from "tailwind-to-style";
|
|
142
|
+
|
|
143
|
+
// Subscribe to errors
|
|
144
|
+
const unsubscribe = onError((error) => {
|
|
145
|
+
console.log(error.message);
|
|
146
|
+
console.log(error.context); // Additional context
|
|
147
|
+
console.log(error.timestamp); // When it occurred
|
|
148
|
+
|
|
149
|
+
// Send to error tracking service
|
|
150
|
+
// Sentry.captureException(error);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Unsubscribe when done
|
|
154
|
+
unsubscribe();
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Cache Management
|
|
158
|
+
|
|
159
|
+
For testing or memory management:
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
import { getTailwindCache, resetTailwindCache } from "tailwind-to-style";
|
|
163
|
+
|
|
164
|
+
// Get cache instance
|
|
165
|
+
const cache = getTailwindCache();
|
|
166
|
+
|
|
167
|
+
// Check if initialized
|
|
168
|
+
if (cache.isInitialized()) {
|
|
169
|
+
console.log("Cache is ready");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Reset cache (useful for testing)
|
|
173
|
+
resetTailwindCache();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Custom Logger Instance
|
|
177
|
+
|
|
178
|
+
Create your own logger with custom settings:
|
|
179
|
+
|
|
180
|
+
```javascript
|
|
181
|
+
import { Logger } from "tailwind-to-style";
|
|
182
|
+
|
|
183
|
+
const customLogger = new Logger('debug');
|
|
184
|
+
customLogger.debug('Custom message');
|
|
185
|
+
customLogger.setLevel('silent'); // Disable all logging
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Animations & Transitions (v2.12.0+)
|
|
189
|
+
|
|
190
|
+
Full support for Tailwind CSS animations and transitions!
|
|
191
|
+
|
|
192
|
+
### Built-in Animations
|
|
193
|
+
|
|
194
|
+
```javascript
|
|
195
|
+
import { tws } from "tailwind-to-style";
|
|
196
|
+
|
|
197
|
+
// Spin animation (loading spinners)
|
|
198
|
+
const spinner = tws("animate-spin", 1);
|
|
199
|
+
// { animation: "spin 1s linear infinite" }
|
|
200
|
+
|
|
201
|
+
// Ping animation (notification badges)
|
|
202
|
+
const badge = tws("animate-ping", 1);
|
|
203
|
+
// { animation: "ping 1s cubic-bezier(0, 0, 0.2, 1) infinite" }
|
|
204
|
+
|
|
205
|
+
// Pulse animation (breathing effect)
|
|
206
|
+
const pulse = tws("animate-pulse", 1);
|
|
207
|
+
// { animation: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite" }
|
|
208
|
+
|
|
209
|
+
// Bounce animation
|
|
210
|
+
const bounce = tws("animate-bounce", 1);
|
|
211
|
+
// { animation: "bounce 1s infinite" }
|
|
212
|
+
|
|
213
|
+
// Disable animation
|
|
214
|
+
const none = tws("animate-none", 1);
|
|
215
|
+
// { animation: "none" }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Transition Utilities
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
// Basic transition
|
|
222
|
+
const button = tws("transition duration-300 ease-in-out", 1);
|
|
223
|
+
// {
|
|
224
|
+
// transitionProperty: "color, background-color, border-color, ...",
|
|
225
|
+
// transitionDuration: "300ms",
|
|
226
|
+
// transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)"
|
|
227
|
+
// }
|
|
228
|
+
|
|
229
|
+
// Transition specific properties
|
|
230
|
+
tws("transition-colors", 1); // Only colors
|
|
231
|
+
tws("transition-opacity", 1); // Only opacity
|
|
232
|
+
tws("transition-shadow", 1); // Only box-shadow
|
|
233
|
+
tws("transition-transform", 1); // Only transform
|
|
234
|
+
tws("transition-all", 1); // All properties
|
|
235
|
+
|
|
236
|
+
// Duration
|
|
237
|
+
tws("duration-75", 1); // 75ms
|
|
238
|
+
tws("duration-150", 1); // 150ms
|
|
239
|
+
tws("duration-300", 1); // 300ms
|
|
240
|
+
tws("duration-500", 1); // 500ms
|
|
241
|
+
tws("duration-1000", 1); // 1000ms
|
|
242
|
+
|
|
243
|
+
// Timing functions
|
|
244
|
+
tws("ease-linear", 1); // linear
|
|
245
|
+
tws("ease-in", 1); // cubic-bezier(0.4, 0, 1, 1)
|
|
246
|
+
tws("ease-out", 1); // cubic-bezier(0, 0, 0.2, 1)
|
|
247
|
+
tws("ease-in-out", 1); // cubic-bezier(0.4, 0, 0.2, 1)
|
|
248
|
+
|
|
249
|
+
// Delay
|
|
250
|
+
tws("delay-75", 1); // 75ms
|
|
251
|
+
tws("delay-150", 1); // 150ms
|
|
252
|
+
tws("delay-300", 1); // 300ms
|
|
253
|
+
tws("delay-500", 1); // 500ms
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Custom Animations
|
|
257
|
+
|
|
258
|
+
Create your own animations using `configure()`:
|
|
259
|
+
|
|
260
|
+
```javascript
|
|
261
|
+
import { configure, tws } from "tailwind-to-style";
|
|
262
|
+
|
|
263
|
+
configure({
|
|
264
|
+
theme: {
|
|
265
|
+
extend: {
|
|
266
|
+
animation: {
|
|
267
|
+
'fade-in': 'fadeIn 1s ease-in forwards',
|
|
268
|
+
'slide-up': 'slideUp 0.5s ease-out',
|
|
269
|
+
'wiggle': 'wiggle 1s ease-in-out infinite',
|
|
270
|
+
},
|
|
271
|
+
keyframes: {
|
|
272
|
+
fadeIn: {
|
|
273
|
+
'0%': { opacity: '0' },
|
|
274
|
+
'100%': { opacity: '1' },
|
|
275
|
+
},
|
|
276
|
+
slideUp: {
|
|
277
|
+
'0%': { transform: 'translateY(100%)' },
|
|
278
|
+
'100%': { transform: 'translateY(0)' },
|
|
279
|
+
},
|
|
280
|
+
wiggle: {
|
|
281
|
+
'0%, 100%': { transform: 'rotate(-3deg)' },
|
|
282
|
+
'50%': { transform: 'rotate(3deg)' },
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// Use custom animations
|
|
290
|
+
const modal = tws("animate-fade-in", 1);
|
|
291
|
+
// { animation: "fadeIn 1s ease-in forwards" }
|
|
292
|
+
|
|
293
|
+
const notification = tws("animate-slide-up", 1);
|
|
294
|
+
// { animation: "slideUp 0.5s ease-out" }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Real-World Examples
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
// Button with hover transition
|
|
301
|
+
const button = tws(
|
|
302
|
+
"bg-blue-500 hover:bg-blue-600 transition-colors duration-200",
|
|
303
|
+
1
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
// Loading spinner
|
|
307
|
+
const spinner = tws(
|
|
308
|
+
"animate-spin w-8 h-8 border-2 border-blue-500 rounded-full",
|
|
309
|
+
1
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
// Notification with fade in
|
|
313
|
+
const notification = tws(
|
|
314
|
+
"animate-fade-in bg-green-500 text-white p-4 rounded shadow-lg",
|
|
315
|
+
1
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
// Menu with slide transition
|
|
319
|
+
const menu = tws(
|
|
320
|
+
"transition-transform duration-300 ease-out transform translate-x-0",
|
|
321
|
+
1
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
// Icon with hover wiggle
|
|
325
|
+
const icon = tws("hover:animate-wiggle cursor-pointer", 1);
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
See [examples/animations.js](examples/animations.js) for more examples!
|
|
329
|
+
|
|
330
|
+
## Theme Customization (v2.10.0+)
|
|
331
|
+
|
|
332
|
+
Extend the default Tailwind theme with your own custom values:
|
|
333
|
+
|
|
334
|
+
### Basic Theme Extension
|
|
335
|
+
|
|
336
|
+
```javascript
|
|
337
|
+
import { configure, tws } from "tailwind-to-style";
|
|
338
|
+
|
|
339
|
+
// Configure custom theme
|
|
340
|
+
configure({
|
|
341
|
+
theme: {
|
|
342
|
+
extend: {
|
|
343
|
+
colors: {
|
|
344
|
+
brand: {
|
|
345
|
+
500: '#0ea5e9',
|
|
346
|
+
600: '#0284c7',
|
|
347
|
+
},
|
|
348
|
+
accent: '#ff6b6b',
|
|
349
|
+
},
|
|
350
|
+
spacing: {
|
|
351
|
+
'128': '32rem',
|
|
352
|
+
'144': '36rem',
|
|
353
|
+
},
|
|
354
|
+
borderRadius: {
|
|
355
|
+
'4xl': '2rem',
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
// Now use your custom values
|
|
362
|
+
const button = tws('bg-brand-500 hover:bg-brand-600 p-128 rounded-4xl', 1);
|
|
363
|
+
// Works! Uses your custom colors, spacing, and border radius
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Theme Configuration Options
|
|
367
|
+
|
|
368
|
+
```javascript
|
|
369
|
+
configure({
|
|
370
|
+
theme: {
|
|
371
|
+
extend: {
|
|
372
|
+
colors: { /* custom colors */ },
|
|
373
|
+
spacing: { /* custom spacing */ },
|
|
374
|
+
borderRadius: { /* custom border radius */ },
|
|
375
|
+
fontSize: { /* custom font sizes */ },
|
|
376
|
+
// ... any Tailwind theme property
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
|
|
380
|
+
// Optional: Add prefix to all classes
|
|
381
|
+
prefix: 'tw-',
|
|
382
|
+
|
|
383
|
+
// Optional: Disable specific core plugins
|
|
384
|
+
corePlugins: {
|
|
385
|
+
float: false,
|
|
386
|
+
clear: false,
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Using Config File
|
|
392
|
+
|
|
393
|
+
Create `tailwind-to-style.config.js`:
|
|
394
|
+
|
|
395
|
+
```javascript
|
|
396
|
+
export default {
|
|
397
|
+
theme: {
|
|
398
|
+
extend: {
|
|
399
|
+
colors: {
|
|
400
|
+
brand: {
|
|
401
|
+
500: '#0ea5e9',
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
};
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Then import and use it:
|
|
410
|
+
|
|
411
|
+
```javascript
|
|
412
|
+
import { configure } from "tailwind-to-style";
|
|
413
|
+
import config from "./tailwind-to-style.config.js";
|
|
414
|
+
|
|
415
|
+
configure(config);
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
## Custom Plugins (v2.10.0+)
|
|
419
|
+
|
|
420
|
+
Create custom utility classes with the plugin API:
|
|
421
|
+
|
|
422
|
+
### Simple Utility Plugin
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
import { createPlugin, configure, tws } from "tailwind-to-style";
|
|
426
|
+
|
|
427
|
+
// Create a text gradient plugin
|
|
428
|
+
const textGradientPlugin = createPlugin('text-gradient', {
|
|
429
|
+
utilities: {
|
|
430
|
+
'.text-gradient': {
|
|
431
|
+
'background-clip': 'text',
|
|
432
|
+
'-webkit-background-clip': 'text',
|
|
433
|
+
'-webkit-text-fill-color': 'transparent',
|
|
434
|
+
'background-image': 'linear-gradient(to right, #3b82f6, #8b5cf6)',
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// Register the plugin
|
|
440
|
+
configure({
|
|
441
|
+
plugins: [textGradientPlugin],
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
// Use it!
|
|
445
|
+
const heading = tws('text-gradient text-4xl font-bold', 1);
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Dynamic Utility Plugin
|
|
449
|
+
|
|
450
|
+
```javascript
|
|
451
|
+
import { createUtilityPlugin, configure } from "tailwind-to-style";
|
|
452
|
+
|
|
453
|
+
// Create a text-shadow plugin with multiple values
|
|
454
|
+
const textShadowPlugin = createUtilityPlugin('text-shadow', {
|
|
455
|
+
prefix: 'text-shadow',
|
|
456
|
+
values: {
|
|
457
|
+
sm: '1px 1px 2px rgba(0,0,0,0.1)',
|
|
458
|
+
md: '2px 2px 4px rgba(0,0,0,0.15)',
|
|
459
|
+
lg: '4px 4px 8px rgba(0,0,0,0.2)',
|
|
460
|
+
xl: '6px 6px 12px rgba(0,0,0,0.25)',
|
|
461
|
+
},
|
|
462
|
+
formatter: (value) => ({
|
|
463
|
+
'text-shadow': value,
|
|
464
|
+
}),
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
configure({
|
|
468
|
+
plugins: [textShadowPlugin],
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
// Use with different sizes
|
|
472
|
+
tws('text-shadow-sm'); // Small shadow
|
|
473
|
+
tws('text-shadow-lg'); // Large shadow
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Glassmorphism Plugin Example
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
const glassmorphismPlugin = createPlugin('glassmorphism', {
|
|
480
|
+
utilities: {
|
|
481
|
+
'.glass': {
|
|
482
|
+
'backdrop-filter': 'blur(10px)',
|
|
483
|
+
'-webkit-backdrop-filter': 'blur(10px)',
|
|
484
|
+
'background-color': 'rgba(255, 255, 255, 0.1)',
|
|
485
|
+
'border': '1px solid rgba(255, 255, 255, 0.2)',
|
|
486
|
+
},
|
|
487
|
+
'.glass-dark': {
|
|
488
|
+
'backdrop-filter': 'blur(10px)',
|
|
489
|
+
'-webkit-backdrop-filter': 'blur(10px)',
|
|
490
|
+
'background-color': 'rgba(0, 0, 0, 0.1)',
|
|
491
|
+
'border': '1px solid rgba(255, 255, 255, 0.1)',
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
configure({
|
|
497
|
+
plugins: [glassmorphismPlugin],
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
// Use glassmorphism effects
|
|
501
|
+
const card = tws('glass p-6 rounded-lg', 1);
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### Complete Configuration Example
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
import { configure, createPlugin, createUtilityPlugin } from "tailwind-to-style";
|
|
508
|
+
|
|
509
|
+
const textShadowPlugin = createUtilityPlugin('text-shadow', {
|
|
510
|
+
prefix: 'text-shadow',
|
|
511
|
+
values: {
|
|
512
|
+
sm: '1px 1px 2px rgba(0,0,0,0.1)',
|
|
513
|
+
md: '2px 2px 4px rgba(0,0,0,0.15)',
|
|
514
|
+
lg: '4px 4px 8px rgba(0,0,0,0.2)',
|
|
515
|
+
},
|
|
516
|
+
formatter: (value) => ({ 'text-shadow': value }),
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
const glassmorphismPlugin = createPlugin('glassmorphism', {
|
|
520
|
+
utilities: {
|
|
521
|
+
'.glass': {
|
|
522
|
+
'backdrop-filter': 'blur(10px)',
|
|
523
|
+
'background-color': 'rgba(255, 255, 255, 0.1)',
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
configure({
|
|
529
|
+
theme: {
|
|
530
|
+
extend: {
|
|
531
|
+
colors: {
|
|
532
|
+
brand: {
|
|
533
|
+
500: '#0ea5e9',
|
|
534
|
+
},
|
|
535
|
+
},
|
|
536
|
+
spacing: {
|
|
537
|
+
'128': '32rem',
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
plugins: [textShadowPlugin, glassmorphismPlugin],
|
|
542
|
+
});
|
|
543
|
+
```
|
|
87
544
|
|
|
88
545
|
### 2. `twsx`
|
|
89
546
|
|