tailwind-to-style 2.8.10 → 2.9.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 +162 -2
- package/dist/index.browser.js +78 -13
- package/dist/index.cjs +78 -13
- package/dist/index.esm.js +78 -13
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -10,9 +10,16 @@
|
|
|
10
10
|
The library exposes two main functions and a CLI tool:
|
|
11
11
|
|
|
12
12
|
1. **`tws`**: Converts Tailwind CSS classes into inline CSS styles or JavaScript objects (JSON).
|
|
13
|
-
2. **`twsx`**: A more advanced function that allows you to define nested and complex styles similar to SCSS, including support for responsive, state variants, and
|
|
13
|
+
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.
|
|
14
14
|
3. **`twsx-cli`**: A command-line tool for generating CSS files from `twsx.*.js` files with watch mode support.
|
|
15
15
|
|
|
16
|
+
## ✨ What's New in v2.9.0
|
|
17
|
+
|
|
18
|
+
- 🆕 **Responsive Selector Syntax**: Intuitive `'md:.title': 'text-lg'` format for responsive styling
|
|
19
|
+
- 🐛 **Critical @css Bug Fix**: Perfect preservation of CSS variables, functions, and complex expressions
|
|
20
|
+
- ⚡ **Enhanced Performance**: Improved processing for large datasets and concurrent operations
|
|
21
|
+
- 🔧 **Better Error Handling**: 100% error recovery rate for malformed inputs
|
|
22
|
+
|
|
16
23
|
## Installation
|
|
17
24
|
|
|
18
25
|
To use `tailwind-to-style`, install the library using either npm or yarn:
|
|
@@ -84,10 +91,11 @@ This will apply the Tailwind classes directly as inline styles in the React comp
|
|
|
84
91
|
- ✅ **Nested styles** similar to SCSS, enabling more complex CSS structures
|
|
85
92
|
- ✅ **Grouping**: Supports grouping utilities inside parentheses `hover:(bg-blue-600 scale-105)`
|
|
86
93
|
- ✅ **Responsive variants** (`sm`, `md`, `lg`, `xl`, `2xl`) in standard and grouping syntax
|
|
94
|
+
- ✅ **🆕 Responsive selector syntax** (v2.9.0+): `'md:.title': 'text-lg'` format for intuitive responsive styling
|
|
87
95
|
- ✅ **State variants** like `hover`, `focus`, `active`, `disabled`, etc.
|
|
88
96
|
- ✅ **Dynamic utilities** such as `w-[300px]`, `bg-[rgba(0,0,0,0.5)]`, `text-[14px]`
|
|
89
97
|
- ✅ **!important support** with `!text-red-500`, `!bg-blue-500`
|
|
90
|
-
- ✅
|
|
98
|
+
- ✅ **🆕 Enhanced @css directive** (v2.9.0+): Perfect CSS variables, functions, and complex expressions support
|
|
91
99
|
|
|
92
100
|
#### Basic Usage
|
|
93
101
|
|
|
@@ -243,6 +251,53 @@ const styles = twsx({
|
|
|
243
251
|
}
|
|
244
252
|
```
|
|
245
253
|
|
|
254
|
+
#### 🆕 Responsive Selector Syntax (v2.9.0+)
|
|
255
|
+
|
|
256
|
+
**New feature**: You can now use responsive breakpoints directly in selectors for more intuitive responsive styling:
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
const styles = twsx({
|
|
260
|
+
// New responsive selector syntax
|
|
261
|
+
"md:.title": "text-lg font-bold",
|
|
262
|
+
"lg:.title": "text-xl",
|
|
263
|
+
"xl:.title": "text-2xl",
|
|
264
|
+
|
|
265
|
+
// Equivalent to the traditional syntax:
|
|
266
|
+
".title": "md:text-lg md:font-bold lg:text-xl xl:text-2xl"
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
This new syntax automatically converts responsive selectors to traditional Tailwind responsive classes and generates proper media queries:
|
|
271
|
+
|
|
272
|
+
```css
|
|
273
|
+
.title {
|
|
274
|
+
/* Base styles if any */
|
|
275
|
+
}
|
|
276
|
+
@media (min-width: 768px) {
|
|
277
|
+
.title {
|
|
278
|
+
font-size: 1.125rem;
|
|
279
|
+
font-weight: 700;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
@media (min-width: 1024px) {
|
|
283
|
+
.title {
|
|
284
|
+
font-size: 1.25rem;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
@media (min-width: 1280px) {
|
|
288
|
+
.title {
|
|
289
|
+
font-size: 1.5rem;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Benefits of Responsive Selector Syntax:**
|
|
295
|
+
- ✅ More intuitive and organized responsive code
|
|
296
|
+
- ✅ Better separation of breakpoint-specific styles
|
|
297
|
+
- ✅ Easier to maintain complex responsive designs
|
|
298
|
+
- ✅ Backward compatible with existing syntax
|
|
299
|
+
- ✅ Works with all breakpoints: `sm`, `md`, `lg`, `xl`, `2xl`
|
|
300
|
+
|
|
246
301
|
### Performance Utilities
|
|
247
302
|
|
|
248
303
|
The library includes performance optimization features:
|
|
@@ -279,6 +334,33 @@ console.log(`Generation time: ${end - start}ms`);
|
|
|
279
334
|
|
|
280
335
|
## Advanced `@css` Directive
|
|
281
336
|
|
|
337
|
+
The `@css` directive allows you to write custom CSS properties that aren't available as Tailwind utilities. **Starting from v2.9.0**, the `@css` directive has been significantly enhanced with improved CSS syntax preservation.
|
|
338
|
+
|
|
339
|
+
### 🆕 Enhanced CSS Support (v2.9.0+)
|
|
340
|
+
|
|
341
|
+
**Major improvements in CSS handling:**
|
|
342
|
+
- ✅ **Perfect CSS Variables**: `var(--custom-property)` syntax fully preserved
|
|
343
|
+
- ✅ **CSS Functions**: `calc()`, `rgba()`, `linear-gradient()`, `clamp()` etc. work flawlessly
|
|
344
|
+
- ✅ **Complex Expressions**: Multi-function CSS expressions preserved accurately
|
|
345
|
+
- ✅ **Zero Corruption**: Fixed critical bug where CSS values were being corrupted
|
|
346
|
+
|
|
347
|
+
**Before v2.9.0** (corrupted):
|
|
348
|
+
```css
|
|
349
|
+
/* This would be corrupted */
|
|
350
|
+
background: -var--primary; /* ❌ WRONG */
|
|
351
|
+
color: rgba-255,0,0,0.5; /* ❌ WRONG */
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**v2.9.0+** (perfect preservation):
|
|
355
|
+
```css
|
|
356
|
+
/* Now works perfectly */
|
|
357
|
+
background: var(--primary); /* ✅ CORRECT */
|
|
358
|
+
color: rgba(255,0,0,0.5); /* ✅ CORRECT */
|
|
359
|
+
transform: calc(100% - 20px); /* ✅ CORRECT */
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Usage Examples
|
|
363
|
+
|
|
282
364
|
There are several ways to use the `@css` feature:
|
|
283
365
|
|
|
284
366
|
1. **As a nested object inside selectors**:
|
|
@@ -373,6 +455,66 @@ const styles = twsx({
|
|
|
373
455
|
}
|
|
374
456
|
```
|
|
375
457
|
|
|
458
|
+
#### 🆕 CSS Variables & Functions Examples (v2.9.0+)
|
|
459
|
+
|
|
460
|
+
With the enhanced `@css` directive, you can now use complex CSS features:
|
|
461
|
+
|
|
462
|
+
```javascript
|
|
463
|
+
const styles = twsx({
|
|
464
|
+
".theme-component": {
|
|
465
|
+
"@css": {
|
|
466
|
+
// CSS Variables - now work perfectly!
|
|
467
|
+
"--primary-color": "#3b82f6",
|
|
468
|
+
"--secondary-color": "#8b5cf6",
|
|
469
|
+
"--border-radius": "0.5rem",
|
|
470
|
+
|
|
471
|
+
// CSS Functions - fully preserved!
|
|
472
|
+
"background": "linear-gradient(135deg, var(--primary-color), var(--secondary-color))",
|
|
473
|
+
"border-radius": "var(--border-radius)",
|
|
474
|
+
"box-shadow": "0 4px 20px rgba(0, 0, 0, 0.15)",
|
|
475
|
+
"transform": "translateY(calc(-1 * var(--spacing, 10px)))",
|
|
476
|
+
|
|
477
|
+
// Complex CSS expressions
|
|
478
|
+
"width": "clamp(200px, 50vw, 800px)",
|
|
479
|
+
"padding": "calc(1rem + 2vw)",
|
|
480
|
+
"color": "hsl(220, 100%, 50%)"
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
".dynamic-grid": {
|
|
485
|
+
"@css": {
|
|
486
|
+
"display": "grid",
|
|
487
|
+
"grid-template-columns": "repeat(auto-fit, minmax(250px, 1fr))",
|
|
488
|
+
"gap": "clamp(1rem, 5vw, 3rem)",
|
|
489
|
+
"grid-auto-rows": "minmax(200px, auto)"
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**Output** (perfectly preserved CSS):
|
|
496
|
+
|
|
497
|
+
```css
|
|
498
|
+
.theme-component {
|
|
499
|
+
--primary-color: #3b82f6;
|
|
500
|
+
--secondary-color: #8b5cf6;
|
|
501
|
+
--border-radius: 0.5rem;
|
|
502
|
+
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
|
|
503
|
+
border-radius: var(--border-radius);
|
|
504
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
505
|
+
transform: translateY(calc(-1 * var(--spacing, 10px)));
|
|
506
|
+
width: clamp(200px, 50vw, 800px);
|
|
507
|
+
padding: calc(1rem + 2vw);
|
|
508
|
+
color: hsl(220, 100%, 50%);
|
|
509
|
+
}
|
|
510
|
+
.dynamic-grid {
|
|
511
|
+
display: grid;
|
|
512
|
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
513
|
+
gap: clamp(1rem, 5vw, 3rem);
|
|
514
|
+
grid-auto-rows: minmax(200px, auto);
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
376
518
|
For responsive styles, you can use standard Tailwind responsive utilities within your classes:
|
|
377
519
|
|
|
378
520
|
```javascript
|
|
@@ -709,6 +851,24 @@ This script is suitable for CI/CD workflows, pre-build steps, or manually genera
|
|
|
709
851
|
|
|
710
852
|
## License
|
|
711
853
|
|
|
854
|
+
## Support
|
|
855
|
+
|
|
856
|
+
If you find this library helpful and want to support its development, consider buying me a coffee:
|
|
857
|
+
|
|
858
|
+
[](https://buymeacoffee.com/bigetion)
|
|
859
|
+
|
|
860
|
+
Your support helps maintain and improve this library! ❤️
|
|
861
|
+
|
|
862
|
+
### Why Support?
|
|
863
|
+
|
|
864
|
+
- 🔧 **Active Maintenance**: Regular updates and bug fixes
|
|
865
|
+
- ⚡ **New Features**: Continuous improvement based on community feedback
|
|
866
|
+
- 📚 **Documentation**: Better examples and tutorials
|
|
867
|
+
- 🚀 **Performance**: Optimization and new capabilities
|
|
868
|
+
- 💬 **Support**: Responsive community support
|
|
869
|
+
|
|
870
|
+
Every contribution, no matter how small, is greatly appreciated and helps keep this project alive and growing!
|
|
871
|
+
|
|
712
872
|
## Contributing
|
|
713
873
|
|
|
714
874
|
Contributions are welcome! Please see our [Contributing Guide](CONTRIBUTING.md) for more details.
|
package/dist/index.browser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tailwind-to-style v2.
|
|
2
|
+
* tailwind-to-style v2.9.1
|
|
3
3
|
* Convert tailwind classes to inline style
|
|
4
4
|
*
|
|
5
5
|
* @author Bigetion
|
|
@@ -6488,7 +6488,8 @@ var tailwindToStyle = (function (exports) {
|
|
|
6488
6488
|
const pseudoVariants = new Set(["hover", "focus", "focus-within", "active", "visited", "disabled", "first", "last", "checked", "invalid", "required"]);
|
|
6489
6489
|
const specialVariants = {
|
|
6490
6490
|
group: (state, sel) => `.group:${state} ${sel}`,
|
|
6491
|
-
peer: (state, sel) => `.peer:${state} ~ ${sel}
|
|
6491
|
+
peer: (state, sel) => `.peer:${state} ~ ${sel}`,
|
|
6492
|
+
dark: (state, sel) => `.dark ${sel}`
|
|
6492
6493
|
};
|
|
6493
6494
|
const selectorVariants = {
|
|
6494
6495
|
first: () => `> :first-child`,
|
|
@@ -6538,6 +6539,9 @@ var tailwindToStyle = (function (exports) {
|
|
|
6538
6539
|
media = breakpoints[v];
|
|
6539
6540
|
} else if (pseudoVariants.has(v)) {
|
|
6540
6541
|
finalSelector += `:${v}`;
|
|
6542
|
+
} else if (v === 'dark') {
|
|
6543
|
+
// Special handling for dark variant
|
|
6544
|
+
finalSelector = `.dark ${finalSelector}`;
|
|
6541
6545
|
} else {
|
|
6542
6546
|
for (const key in specialVariants) {
|
|
6543
6547
|
if (v.startsWith(`${key}-`)) {
|
|
@@ -6877,6 +6881,10 @@ var tailwindToStyle = (function (exports) {
|
|
|
6877
6881
|
// Utility functions for class expansion
|
|
6878
6882
|
function expandDirectiveGroups(str) {
|
|
6879
6883
|
return str.replace(/(\w+)\(([^()]+)\)/g, (_, directive, content) => {
|
|
6884
|
+
// Special handling for dark mode syntax: dark:(classes)
|
|
6885
|
+
if (directive === 'dark') {
|
|
6886
|
+
return content.trim().split(/\s+/).map(cls => `dark:${cls}`).join(" ");
|
|
6887
|
+
}
|
|
6880
6888
|
return content.trim().split(/\s+/).map(val => {
|
|
6881
6889
|
if (val.includes(":")) {
|
|
6882
6890
|
const [variant, v] = val.split(":");
|
|
@@ -7012,9 +7020,12 @@ var tailwindToStyle = (function (exports) {
|
|
|
7012
7020
|
for (const nestedSel in nested) {
|
|
7013
7021
|
const nestedVal = nested[nestedSel];
|
|
7014
7022
|
if (nestedSel === "@css" && typeof nestedVal === "object") {
|
|
7023
|
+
// For @css directive, use raw CSS values without any processing
|
|
7015
7024
|
const cssDeclarations = Object.entries(nestedVal).map(_ref3 => {
|
|
7016
7025
|
let [key, value] = _ref3;
|
|
7017
|
-
|
|
7026
|
+
// Ensure CSS values are properly formatted and not processed through Tailwind conversion
|
|
7027
|
+
const cleanValue = typeof value === 'string' ? value.trim() : String(value);
|
|
7028
|
+
return `${key}: ${cleanValue};`;
|
|
7018
7029
|
}).join(" ");
|
|
7019
7030
|
if (selector in styles) {
|
|
7020
7031
|
styles[selector] += cssDeclarations + "\n";
|
|
@@ -7071,14 +7082,33 @@ var tailwindToStyle = (function (exports) {
|
|
|
7071
7082
|
styles[baseSelector] += `${cssProperty}: ${cssValue};\n`;
|
|
7072
7083
|
return;
|
|
7073
7084
|
}
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7085
|
+
|
|
7086
|
+
// Check if this is a @css object within the current object
|
|
7087
|
+
if (val['@css'] && typeof val['@css'] === 'object') {
|
|
7088
|
+
// Handle object with @css directive - process the @css part specially
|
|
7089
|
+
const cssDeclarations = Object.entries(val['@css']).map(_ref4 => {
|
|
7090
|
+
let [key, value] = _ref4;
|
|
7091
|
+
// Keep CSS values intact without any processing
|
|
7092
|
+
const cleanValue = typeof value === 'string' ? value.trim() : String(value);
|
|
7093
|
+
return `${key}: ${cleanValue};`;
|
|
7094
|
+
}).join(" ");
|
|
7095
|
+
if (selector in styles) {
|
|
7096
|
+
styles[selector] += cssDeclarations + "\n";
|
|
7097
|
+
} else {
|
|
7098
|
+
styles[selector] = cssDeclarations + "\n";
|
|
7099
|
+
}
|
|
7100
|
+
|
|
7101
|
+
// Process other properties in the object (non-@css)
|
|
7102
|
+
const otherProps = {
|
|
7103
|
+
...val
|
|
7104
|
+
};
|
|
7105
|
+
delete otherProps['@css'];
|
|
7106
|
+
if (Object.keys(otherProps).length > 0) {
|
|
7107
|
+
processNestedSelectors(otherProps, selector, styles, walk);
|
|
7108
|
+
}
|
|
7080
7109
|
} else {
|
|
7081
|
-
|
|
7110
|
+
// Regular object processing - use processNestedSelectors to handle properly
|
|
7111
|
+
processNestedSelectors(val, selector, styles, walk);
|
|
7082
7112
|
}
|
|
7083
7113
|
}
|
|
7084
7114
|
}
|
|
@@ -7188,8 +7218,36 @@ var tailwindToStyle = (function (exports) {
|
|
|
7188
7218
|
walkStyleTree(selector, val, styles, walk);
|
|
7189
7219
|
}
|
|
7190
7220
|
|
|
7191
|
-
//
|
|
7192
|
-
const
|
|
7221
|
+
// Enhanced selector processing to handle responsive breakpoints
|
|
7222
|
+
const enhancedObj = {};
|
|
7223
|
+
for (const selector in obj) {
|
|
7224
|
+
const val = obj[selector];
|
|
7225
|
+
|
|
7226
|
+
// Check if selector starts with breakpoint (e.g., 'md:.title')
|
|
7227
|
+
const breakpointMatch = selector.match(/^(sm|md|lg|xl|2xl):(.+)$/);
|
|
7228
|
+
if (breakpointMatch) {
|
|
7229
|
+
const [, breakpoint, baseSelector] = breakpointMatch;
|
|
7230
|
+
if (typeof val === "string") {
|
|
7231
|
+
// Convert 'md:.title': 'text-lg' to '.title': 'md:text-lg'
|
|
7232
|
+
if (!enhancedObj[baseSelector]) {
|
|
7233
|
+
enhancedObj[baseSelector] = "";
|
|
7234
|
+
}
|
|
7235
|
+
|
|
7236
|
+
// Add responsive classes to the base selector
|
|
7237
|
+
const responsiveClasses = val.split(" ").map(cls => `${breakpoint}:${cls}`).join(" ");
|
|
7238
|
+
enhancedObj[baseSelector] += (enhancedObj[baseSelector] ? " " : "") + responsiveClasses;
|
|
7239
|
+
} else {
|
|
7240
|
+
// For non-string values (objects, arrays), keep original structure
|
|
7241
|
+
enhancedObj[selector] = val;
|
|
7242
|
+
}
|
|
7243
|
+
} else {
|
|
7244
|
+
// Regular selector - keep as is
|
|
7245
|
+
enhancedObj[selector] = val;
|
|
7246
|
+
}
|
|
7247
|
+
}
|
|
7248
|
+
|
|
7249
|
+
// Flatten the enhanced input object
|
|
7250
|
+
const flattered = performanceMonitor.measure(() => flattenStyleObject(enhancedObj), "twsx:flatten");
|
|
7193
7251
|
|
|
7194
7252
|
// Process each selector
|
|
7195
7253
|
const processMarker = performanceMonitor.start("twsx:process");
|
|
@@ -7198,7 +7256,14 @@ var tailwindToStyle = (function (exports) {
|
|
|
7198
7256
|
let baseClass = "";
|
|
7199
7257
|
let nested = {};
|
|
7200
7258
|
if (typeof val === "string") {
|
|
7201
|
-
|
|
7259
|
+
// Check if this is a @css property value - if so, don't process through expandGroupedClass
|
|
7260
|
+
if (selector.includes(" @css ")) {
|
|
7261
|
+
// This is a CSS property value from @css flattening - keep as-is
|
|
7262
|
+
baseClass = val;
|
|
7263
|
+
} else {
|
|
7264
|
+
// Regular Tailwind class - process normally
|
|
7265
|
+
baseClass = expandGroupedClass(val);
|
|
7266
|
+
}
|
|
7202
7267
|
} else if (Array.isArray(val)) {
|
|
7203
7268
|
for (const item of val) {
|
|
7204
7269
|
if (typeof item === "string") {
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tailwind-to-style v2.
|
|
2
|
+
* tailwind-to-style v2.9.1
|
|
3
3
|
* Convert tailwind classes to inline style
|
|
4
4
|
*
|
|
5
5
|
* @author Bigetion
|
|
@@ -6489,7 +6489,8 @@ const breakpoints = {
|
|
|
6489
6489
|
const pseudoVariants = new Set(["hover", "focus", "focus-within", "active", "visited", "disabled", "first", "last", "checked", "invalid", "required"]);
|
|
6490
6490
|
const specialVariants = {
|
|
6491
6491
|
group: (state, sel) => `.group:${state} ${sel}`,
|
|
6492
|
-
peer: (state, sel) => `.peer:${state} ~ ${sel}
|
|
6492
|
+
peer: (state, sel) => `.peer:${state} ~ ${sel}`,
|
|
6493
|
+
dark: (state, sel) => `.dark ${sel}`
|
|
6493
6494
|
};
|
|
6494
6495
|
const selectorVariants = {
|
|
6495
6496
|
first: () => `> :first-child`,
|
|
@@ -6539,6 +6540,9 @@ function resolveVariants(selector, variants) {
|
|
|
6539
6540
|
media = breakpoints[v];
|
|
6540
6541
|
} else if (pseudoVariants.has(v)) {
|
|
6541
6542
|
finalSelector += `:${v}`;
|
|
6543
|
+
} else if (v === 'dark') {
|
|
6544
|
+
// Special handling for dark variant
|
|
6545
|
+
finalSelector = `.dark ${finalSelector}`;
|
|
6542
6546
|
} else {
|
|
6543
6547
|
for (const key in specialVariants) {
|
|
6544
6548
|
if (v.startsWith(`${key}-`)) {
|
|
@@ -6878,6 +6882,10 @@ const performanceMonitor = {
|
|
|
6878
6882
|
// Utility functions for class expansion
|
|
6879
6883
|
function expandDirectiveGroups(str) {
|
|
6880
6884
|
return str.replace(/(\w+)\(([^()]+)\)/g, (_, directive, content) => {
|
|
6885
|
+
// Special handling for dark mode syntax: dark:(classes)
|
|
6886
|
+
if (directive === 'dark') {
|
|
6887
|
+
return content.trim().split(/\s+/).map(cls => `dark:${cls}`).join(" ");
|
|
6888
|
+
}
|
|
6881
6889
|
return content.trim().split(/\s+/).map(val => {
|
|
6882
6890
|
if (val.includes(":")) {
|
|
6883
6891
|
const [variant, v] = val.split(":");
|
|
@@ -7013,9 +7021,12 @@ function processNestedSelectors(nested, selector, styles, walk) {
|
|
|
7013
7021
|
for (const nestedSel in nested) {
|
|
7014
7022
|
const nestedVal = nested[nestedSel];
|
|
7015
7023
|
if (nestedSel === "@css" && typeof nestedVal === "object") {
|
|
7024
|
+
// For @css directive, use raw CSS values without any processing
|
|
7016
7025
|
const cssDeclarations = Object.entries(nestedVal).map(_ref3 => {
|
|
7017
7026
|
let [key, value] = _ref3;
|
|
7018
|
-
|
|
7027
|
+
// Ensure CSS values are properly formatted and not processed through Tailwind conversion
|
|
7028
|
+
const cleanValue = typeof value === 'string' ? value.trim() : String(value);
|
|
7029
|
+
return `${key}: ${cleanValue};`;
|
|
7019
7030
|
}).join(" ");
|
|
7020
7031
|
if (selector in styles) {
|
|
7021
7032
|
styles[selector] += cssDeclarations + "\n";
|
|
@@ -7072,14 +7083,33 @@ function walkStyleTree(selector, val, styles, walk) {
|
|
|
7072
7083
|
styles[baseSelector] += `${cssProperty}: ${cssValue};\n`;
|
|
7073
7084
|
return;
|
|
7074
7085
|
}
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
|
|
7086
|
+
|
|
7087
|
+
// Check if this is a @css object within the current object
|
|
7088
|
+
if (val['@css'] && typeof val['@css'] === 'object') {
|
|
7089
|
+
// Handle object with @css directive - process the @css part specially
|
|
7090
|
+
const cssDeclarations = Object.entries(val['@css']).map(_ref4 => {
|
|
7091
|
+
let [key, value] = _ref4;
|
|
7092
|
+
// Keep CSS values intact without any processing
|
|
7093
|
+
const cleanValue = typeof value === 'string' ? value.trim() : String(value);
|
|
7094
|
+
return `${key}: ${cleanValue};`;
|
|
7095
|
+
}).join(" ");
|
|
7096
|
+
if (selector in styles) {
|
|
7097
|
+
styles[selector] += cssDeclarations + "\n";
|
|
7098
|
+
} else {
|
|
7099
|
+
styles[selector] = cssDeclarations + "\n";
|
|
7100
|
+
}
|
|
7101
|
+
|
|
7102
|
+
// Process other properties in the object (non-@css)
|
|
7103
|
+
const otherProps = {
|
|
7104
|
+
...val
|
|
7105
|
+
};
|
|
7106
|
+
delete otherProps['@css'];
|
|
7107
|
+
if (Object.keys(otherProps).length > 0) {
|
|
7108
|
+
processNestedSelectors(otherProps, selector, styles, walk);
|
|
7109
|
+
}
|
|
7081
7110
|
} else {
|
|
7082
|
-
|
|
7111
|
+
// Regular object processing - use processNestedSelectors to handle properly
|
|
7112
|
+
processNestedSelectors(val, selector, styles, walk);
|
|
7083
7113
|
}
|
|
7084
7114
|
}
|
|
7085
7115
|
}
|
|
@@ -7189,8 +7219,36 @@ function twsx(obj) {
|
|
|
7189
7219
|
walkStyleTree(selector, val, styles, walk);
|
|
7190
7220
|
}
|
|
7191
7221
|
|
|
7192
|
-
//
|
|
7193
|
-
const
|
|
7222
|
+
// Enhanced selector processing to handle responsive breakpoints
|
|
7223
|
+
const enhancedObj = {};
|
|
7224
|
+
for (const selector in obj) {
|
|
7225
|
+
const val = obj[selector];
|
|
7226
|
+
|
|
7227
|
+
// Check if selector starts with breakpoint (e.g., 'md:.title')
|
|
7228
|
+
const breakpointMatch = selector.match(/^(sm|md|lg|xl|2xl):(.+)$/);
|
|
7229
|
+
if (breakpointMatch) {
|
|
7230
|
+
const [, breakpoint, baseSelector] = breakpointMatch;
|
|
7231
|
+
if (typeof val === "string") {
|
|
7232
|
+
// Convert 'md:.title': 'text-lg' to '.title': 'md:text-lg'
|
|
7233
|
+
if (!enhancedObj[baseSelector]) {
|
|
7234
|
+
enhancedObj[baseSelector] = "";
|
|
7235
|
+
}
|
|
7236
|
+
|
|
7237
|
+
// Add responsive classes to the base selector
|
|
7238
|
+
const responsiveClasses = val.split(" ").map(cls => `${breakpoint}:${cls}`).join(" ");
|
|
7239
|
+
enhancedObj[baseSelector] += (enhancedObj[baseSelector] ? " " : "") + responsiveClasses;
|
|
7240
|
+
} else {
|
|
7241
|
+
// For non-string values (objects, arrays), keep original structure
|
|
7242
|
+
enhancedObj[selector] = val;
|
|
7243
|
+
}
|
|
7244
|
+
} else {
|
|
7245
|
+
// Regular selector - keep as is
|
|
7246
|
+
enhancedObj[selector] = val;
|
|
7247
|
+
}
|
|
7248
|
+
}
|
|
7249
|
+
|
|
7250
|
+
// Flatten the enhanced input object
|
|
7251
|
+
const flattered = performanceMonitor.measure(() => flattenStyleObject(enhancedObj), "twsx:flatten");
|
|
7194
7252
|
|
|
7195
7253
|
// Process each selector
|
|
7196
7254
|
const processMarker = performanceMonitor.start("twsx:process");
|
|
@@ -7199,7 +7257,14 @@ function twsx(obj) {
|
|
|
7199
7257
|
let baseClass = "";
|
|
7200
7258
|
let nested = {};
|
|
7201
7259
|
if (typeof val === "string") {
|
|
7202
|
-
|
|
7260
|
+
// Check if this is a @css property value - if so, don't process through expandGroupedClass
|
|
7261
|
+
if (selector.includes(" @css ")) {
|
|
7262
|
+
// This is a CSS property value from @css flattening - keep as-is
|
|
7263
|
+
baseClass = val;
|
|
7264
|
+
} else {
|
|
7265
|
+
// Regular Tailwind class - process normally
|
|
7266
|
+
baseClass = expandGroupedClass(val);
|
|
7267
|
+
}
|
|
7203
7268
|
} else if (Array.isArray(val)) {
|
|
7204
7269
|
for (const item of val) {
|
|
7205
7270
|
if (typeof item === "string") {
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tailwind-to-style v2.
|
|
2
|
+
* tailwind-to-style v2.9.1
|
|
3
3
|
* Convert tailwind classes to inline style
|
|
4
4
|
*
|
|
5
5
|
* @author Bigetion
|
|
@@ -6485,7 +6485,8 @@ const breakpoints = {
|
|
|
6485
6485
|
const pseudoVariants = new Set(["hover", "focus", "focus-within", "active", "visited", "disabled", "first", "last", "checked", "invalid", "required"]);
|
|
6486
6486
|
const specialVariants = {
|
|
6487
6487
|
group: (state, sel) => `.group:${state} ${sel}`,
|
|
6488
|
-
peer: (state, sel) => `.peer:${state} ~ ${sel}
|
|
6488
|
+
peer: (state, sel) => `.peer:${state} ~ ${sel}`,
|
|
6489
|
+
dark: (state, sel) => `.dark ${sel}`
|
|
6489
6490
|
};
|
|
6490
6491
|
const selectorVariants = {
|
|
6491
6492
|
first: () => `> :first-child`,
|
|
@@ -6535,6 +6536,9 @@ function resolveVariants(selector, variants) {
|
|
|
6535
6536
|
media = breakpoints[v];
|
|
6536
6537
|
} else if (pseudoVariants.has(v)) {
|
|
6537
6538
|
finalSelector += `:${v}`;
|
|
6539
|
+
} else if (v === 'dark') {
|
|
6540
|
+
// Special handling for dark variant
|
|
6541
|
+
finalSelector = `.dark ${finalSelector}`;
|
|
6538
6542
|
} else {
|
|
6539
6543
|
for (const key in specialVariants) {
|
|
6540
6544
|
if (v.startsWith(`${key}-`)) {
|
|
@@ -6874,6 +6878,10 @@ const performanceMonitor = {
|
|
|
6874
6878
|
// Utility functions for class expansion
|
|
6875
6879
|
function expandDirectiveGroups(str) {
|
|
6876
6880
|
return str.replace(/(\w+)\(([^()]+)\)/g, (_, directive, content) => {
|
|
6881
|
+
// Special handling for dark mode syntax: dark:(classes)
|
|
6882
|
+
if (directive === 'dark') {
|
|
6883
|
+
return content.trim().split(/\s+/).map(cls => `dark:${cls}`).join(" ");
|
|
6884
|
+
}
|
|
6877
6885
|
return content.trim().split(/\s+/).map(val => {
|
|
6878
6886
|
if (val.includes(":")) {
|
|
6879
6887
|
const [variant, v] = val.split(":");
|
|
@@ -7009,9 +7017,12 @@ function processNestedSelectors(nested, selector, styles, walk) {
|
|
|
7009
7017
|
for (const nestedSel in nested) {
|
|
7010
7018
|
const nestedVal = nested[nestedSel];
|
|
7011
7019
|
if (nestedSel === "@css" && typeof nestedVal === "object") {
|
|
7020
|
+
// For @css directive, use raw CSS values without any processing
|
|
7012
7021
|
const cssDeclarations = Object.entries(nestedVal).map(_ref3 => {
|
|
7013
7022
|
let [key, value] = _ref3;
|
|
7014
|
-
|
|
7023
|
+
// Ensure CSS values are properly formatted and not processed through Tailwind conversion
|
|
7024
|
+
const cleanValue = typeof value === 'string' ? value.trim() : String(value);
|
|
7025
|
+
return `${key}: ${cleanValue};`;
|
|
7015
7026
|
}).join(" ");
|
|
7016
7027
|
if (selector in styles) {
|
|
7017
7028
|
styles[selector] += cssDeclarations + "\n";
|
|
@@ -7068,14 +7079,33 @@ function walkStyleTree(selector, val, styles, walk) {
|
|
|
7068
7079
|
styles[baseSelector] += `${cssProperty}: ${cssValue};\n`;
|
|
7069
7080
|
return;
|
|
7070
7081
|
}
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7082
|
+
|
|
7083
|
+
// Check if this is a @css object within the current object
|
|
7084
|
+
if (val['@css'] && typeof val['@css'] === 'object') {
|
|
7085
|
+
// Handle object with @css directive - process the @css part specially
|
|
7086
|
+
const cssDeclarations = Object.entries(val['@css']).map(_ref4 => {
|
|
7087
|
+
let [key, value] = _ref4;
|
|
7088
|
+
// Keep CSS values intact without any processing
|
|
7089
|
+
const cleanValue = typeof value === 'string' ? value.trim() : String(value);
|
|
7090
|
+
return `${key}: ${cleanValue};`;
|
|
7091
|
+
}).join(" ");
|
|
7092
|
+
if (selector in styles) {
|
|
7093
|
+
styles[selector] += cssDeclarations + "\n";
|
|
7094
|
+
} else {
|
|
7095
|
+
styles[selector] = cssDeclarations + "\n";
|
|
7096
|
+
}
|
|
7097
|
+
|
|
7098
|
+
// Process other properties in the object (non-@css)
|
|
7099
|
+
const otherProps = {
|
|
7100
|
+
...val
|
|
7101
|
+
};
|
|
7102
|
+
delete otherProps['@css'];
|
|
7103
|
+
if (Object.keys(otherProps).length > 0) {
|
|
7104
|
+
processNestedSelectors(otherProps, selector, styles, walk);
|
|
7105
|
+
}
|
|
7077
7106
|
} else {
|
|
7078
|
-
|
|
7107
|
+
// Regular object processing - use processNestedSelectors to handle properly
|
|
7108
|
+
processNestedSelectors(val, selector, styles, walk);
|
|
7079
7109
|
}
|
|
7080
7110
|
}
|
|
7081
7111
|
}
|
|
@@ -7185,8 +7215,36 @@ function twsx(obj) {
|
|
|
7185
7215
|
walkStyleTree(selector, val, styles, walk);
|
|
7186
7216
|
}
|
|
7187
7217
|
|
|
7188
|
-
//
|
|
7189
|
-
const
|
|
7218
|
+
// Enhanced selector processing to handle responsive breakpoints
|
|
7219
|
+
const enhancedObj = {};
|
|
7220
|
+
for (const selector in obj) {
|
|
7221
|
+
const val = obj[selector];
|
|
7222
|
+
|
|
7223
|
+
// Check if selector starts with breakpoint (e.g., 'md:.title')
|
|
7224
|
+
const breakpointMatch = selector.match(/^(sm|md|lg|xl|2xl):(.+)$/);
|
|
7225
|
+
if (breakpointMatch) {
|
|
7226
|
+
const [, breakpoint, baseSelector] = breakpointMatch;
|
|
7227
|
+
if (typeof val === "string") {
|
|
7228
|
+
// Convert 'md:.title': 'text-lg' to '.title': 'md:text-lg'
|
|
7229
|
+
if (!enhancedObj[baseSelector]) {
|
|
7230
|
+
enhancedObj[baseSelector] = "";
|
|
7231
|
+
}
|
|
7232
|
+
|
|
7233
|
+
// Add responsive classes to the base selector
|
|
7234
|
+
const responsiveClasses = val.split(" ").map(cls => `${breakpoint}:${cls}`).join(" ");
|
|
7235
|
+
enhancedObj[baseSelector] += (enhancedObj[baseSelector] ? " " : "") + responsiveClasses;
|
|
7236
|
+
} else {
|
|
7237
|
+
// For non-string values (objects, arrays), keep original structure
|
|
7238
|
+
enhancedObj[selector] = val;
|
|
7239
|
+
}
|
|
7240
|
+
} else {
|
|
7241
|
+
// Regular selector - keep as is
|
|
7242
|
+
enhancedObj[selector] = val;
|
|
7243
|
+
}
|
|
7244
|
+
}
|
|
7245
|
+
|
|
7246
|
+
// Flatten the enhanced input object
|
|
7247
|
+
const flattered = performanceMonitor.measure(() => flattenStyleObject(enhancedObj), "twsx:flatten");
|
|
7190
7248
|
|
|
7191
7249
|
// Process each selector
|
|
7192
7250
|
const processMarker = performanceMonitor.start("twsx:process");
|
|
@@ -7195,7 +7253,14 @@ function twsx(obj) {
|
|
|
7195
7253
|
let baseClass = "";
|
|
7196
7254
|
let nested = {};
|
|
7197
7255
|
if (typeof val === "string") {
|
|
7198
|
-
|
|
7256
|
+
// Check if this is a @css property value - if so, don't process through expandGroupedClass
|
|
7257
|
+
if (selector.includes(" @css ")) {
|
|
7258
|
+
// This is a CSS property value from @css flattening - keep as-is
|
|
7259
|
+
baseClass = val;
|
|
7260
|
+
} else {
|
|
7261
|
+
// Regular Tailwind class - process normally
|
|
7262
|
+
baseClass = expandGroupedClass(val);
|
|
7263
|
+
}
|
|
7199
7264
|
} else if (Array.isArray(val)) {
|
|
7200
7265
|
for (const item of val) {
|
|
7201
7266
|
if (typeof item === "string") {
|