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 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