tailwind-to-style 2.10.1 → 2.10.3
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 +229 -15
- package/dist/index.browser.js +95 -8
- package/dist/index.cjs +95 -8
- package/dist/index.esm.js +95 -8
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/react.cjs.js +681 -182
- package/dist/react.esm.js +681 -182
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,15 +15,14 @@ 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.
|
|
18
|
+
## ✨ What's New in v2.10.2
|
|
19
19
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
Now you can create smooth transitions and eye-catching animations like Tailwind CSS!
|
|
20
|
+
- **⚛️ React Integration**: Built-in React hooks and provider for seamless integration
|
|
21
|
+
- **🎬 Enhanced Animations**: Complete animation system with custom keyframes support
|
|
22
|
+
- **🔄 Improved Transitions**: Full transition utilities with duration, delay, and easing
|
|
23
|
+
- **🎨 Advanced Theming**: More flexible theme customization and plugin system
|
|
24
|
+
- **⚡ Performance Boost**: Better caching and optimized CSS generation
|
|
25
|
+
- **📱 Responsive Selector Syntax**: New intuitive `'md:.title': 'text-lg'` format
|
|
27
26
|
|
|
28
27
|
## ✨ What's New in v2.11.0
|
|
29
28
|
|
|
@@ -58,18 +57,233 @@ All changes are **backward compatible** - your existing code continues to work!
|
|
|
58
57
|
|
|
59
58
|
## Installation
|
|
60
59
|
|
|
61
|
-
To use `tailwind-to-style`, install the library using either npm or yarn:
|
|
62
|
-
|
|
63
|
-
### Using npm
|
|
64
|
-
|
|
65
60
|
```bash
|
|
66
61
|
npm install tailwind-to-style
|
|
67
62
|
```
|
|
68
63
|
|
|
69
|
-
|
|
64
|
+
## React Integration
|
|
70
65
|
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
### Quick Start with React
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { useTwsx, TwsxProvider } from 'tailwind-to-style'
|
|
70
|
+
|
|
71
|
+
// Theme configuration
|
|
72
|
+
const config = {
|
|
73
|
+
theme: {
|
|
74
|
+
extend: {
|
|
75
|
+
colors: {
|
|
76
|
+
brand: { 500: '#3b82f6', 600: '#2563eb' }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function App() {
|
|
83
|
+
return (
|
|
84
|
+
<TwsxProvider config={config}>
|
|
85
|
+
<MyComponent />
|
|
86
|
+
</TwsxProvider>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function MyComponent() {
|
|
91
|
+
// Auto-inject CSS into document head
|
|
92
|
+
useTwsx({
|
|
93
|
+
'.card': [
|
|
94
|
+
'bg-brand-500 text-white p-6 rounded-lg',
|
|
95
|
+
{
|
|
96
|
+
'&:hover': 'bg-brand-600 transform scale-105',
|
|
97
|
+
'.title': 'text-xl font-bold mb-2'
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<div className="card">
|
|
104
|
+
<h2 className="title">Interactive Card</h2>
|
|
105
|
+
<p>Hover me to see the effect!</p>
|
|
106
|
+
</div>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Import Options
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
// Import from main package (recommended)
|
|
115
|
+
import { useTwsx, TwsxProvider } from 'tailwind-to-style'
|
|
116
|
+
|
|
117
|
+
// Or from React subpath
|
|
118
|
+
import { useTwsx, TwsxProvider } from 'tailwind-to-style/react'
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `useTwsx()` Hook
|
|
122
|
+
|
|
123
|
+
The main React hook for component styling:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
import { useTwsx } from 'tailwind-to-style'
|
|
127
|
+
|
|
128
|
+
function MyComponent() {
|
|
129
|
+
// Auto-inject CSS (default behavior)
|
|
130
|
+
useTwsx({
|
|
131
|
+
'.button': [
|
|
132
|
+
'bg-blue-500 text-white px-6 py-3 rounded-lg font-medium',
|
|
133
|
+
{
|
|
134
|
+
'&:hover': 'bg-blue-600 transform scale-105',
|
|
135
|
+
'&:active': 'bg-blue-700 scale-95',
|
|
136
|
+
'&:disabled': 'bg-gray-400 cursor-not-allowed'
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
// Get CSS without injection
|
|
142
|
+
const css = useTwsx({
|
|
143
|
+
'.card': 'bg-white p-6 rounded-lg shadow-md'
|
|
144
|
+
}, { inject: false })
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<>
|
|
148
|
+
<style>{css}</style>
|
|
149
|
+
<div className="card">
|
|
150
|
+
<button className="button">Click me</button>
|
|
151
|
+
</div>
|
|
152
|
+
</>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### `TwsxProvider` - Theme Configuration
|
|
158
|
+
|
|
159
|
+
Provide global theme configuration and custom colors:
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
import { TwsxProvider, useTwsx } from 'tailwind-to-style'
|
|
163
|
+
|
|
164
|
+
const themeConfig = {
|
|
165
|
+
theme: {
|
|
166
|
+
extend: {
|
|
167
|
+
colors: {
|
|
168
|
+
brand: {
|
|
169
|
+
50: '#eff6ff',
|
|
170
|
+
500: '#3b82f6',
|
|
171
|
+
600: '#2563eb',
|
|
172
|
+
900: '#1e3a8a'
|
|
173
|
+
},
|
|
174
|
+
accent: '#f59e0b'
|
|
175
|
+
},
|
|
176
|
+
spacing: {
|
|
177
|
+
'128': '32rem',
|
|
178
|
+
'144': '36rem'
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function App() {
|
|
185
|
+
return (
|
|
186
|
+
<TwsxProvider config={themeConfig}>
|
|
187
|
+
<Header />
|
|
188
|
+
<Main />
|
|
189
|
+
<Footer />
|
|
190
|
+
</TwsxProvider>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function Header() {
|
|
195
|
+
useTwsx({
|
|
196
|
+
'.header': [
|
|
197
|
+
'bg-brand-500 text-white p-128', // Uses custom spacing
|
|
198
|
+
{
|
|
199
|
+
'.logo': 'text-accent font-bold text-2xl', // Uses custom color
|
|
200
|
+
'&:hover': 'bg-brand-600'
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<header className="header">
|
|
207
|
+
<div className="logo">My Brand</div>
|
|
208
|
+
</header>
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Dynamic Styling with State
|
|
214
|
+
|
|
215
|
+
Create dynamic styles that respond to component state:
|
|
216
|
+
|
|
217
|
+
```javascript
|
|
218
|
+
import { useTwsx } from 'tailwind-to-style'
|
|
219
|
+
import { useState } from 'react'
|
|
220
|
+
|
|
221
|
+
function ThemeToggle() {
|
|
222
|
+
const [theme, setTheme] = useState('light')
|
|
223
|
+
|
|
224
|
+
useTwsx({
|
|
225
|
+
'.theme-container': [
|
|
226
|
+
`bg-${theme === 'dark' ? 'gray-900' : 'white'} p-6 rounded-lg transition-all duration-300`,
|
|
227
|
+
{
|
|
228
|
+
[`&.${theme}`]: theme === 'dark'
|
|
229
|
+
? 'text-white border-gray-700'
|
|
230
|
+
: 'text-gray-900 border-gray-200',
|
|
231
|
+
'.theme-title': 'text-2xl font-bold mb-4',
|
|
232
|
+
'.theme-button': [
|
|
233
|
+
'px-4 py-2 rounded-lg font-medium transition-colors',
|
|
234
|
+
theme === 'dark'
|
|
235
|
+
? 'bg-yellow-500 text-gray-900 hover:bg-yellow-400'
|
|
236
|
+
: 'bg-gray-800 text-white hover:bg-gray-700'
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
<div className={`theme-container ${theme}`}>
|
|
244
|
+
<h2 className="theme-title">🌓 Dynamic Theme</h2>
|
|
245
|
+
<button
|
|
246
|
+
className="theme-button"
|
|
247
|
+
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
|
|
248
|
+
>
|
|
249
|
+
Switch to {theme === 'light' ? 'Dark' : 'Light'} Mode
|
|
250
|
+
</button>
|
|
251
|
+
</div>
|
|
252
|
+
)
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Available React Hooks
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
import {
|
|
260
|
+
useTwsx, // Main hook for styling
|
|
261
|
+
TwsxProvider, // Context provider
|
|
262
|
+
useTwsxContext, // Access provider context
|
|
263
|
+
useTwsxConfig, // Get current config
|
|
264
|
+
useUpdateTwsxConfig // Update config
|
|
265
|
+
} from 'tailwind-to-style'
|
|
266
|
+
|
|
267
|
+
// Example usage
|
|
268
|
+
function ConfigAwareComponent() {
|
|
269
|
+
const { config, isConfigured } = useTwsxConfig()
|
|
270
|
+
const updateConfig = useUpdateTwsxConfig()
|
|
271
|
+
|
|
272
|
+
if (!isConfigured) {
|
|
273
|
+
return <div>Loading theme...</div>
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<div>
|
|
278
|
+
<p>Current theme: {config.theme?.extend?.colors?.brand ? 'Custom' : 'Default'}</p>
|
|
279
|
+
<button onClick={() => updateConfig({
|
|
280
|
+
theme: { extend: { colors: { brand: { 500: '#ef4444' } } } }
|
|
281
|
+
})}>
|
|
282
|
+
Change Brand Color
|
|
283
|
+
</button>
|
|
284
|
+
</div>
|
|
285
|
+
)
|
|
286
|
+
}
|
|
73
287
|
```
|
|
74
288
|
|
|
75
289
|
## Core Functions
|
package/dist/index.browser.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tailwind-to-style v2.10.
|
|
2
|
+
* tailwind-to-style v2.10.3
|
|
3
3
|
* Convert tailwind classes to inline style
|
|
4
4
|
*
|
|
5
5
|
* @author Bigetion
|
|
@@ -25,6 +25,8 @@ var tailwindToStyle = (function (exports) {
|
|
|
25
25
|
ping: "ping 1s cubic-bezier(0, 0, 0.2, 1) infinite",
|
|
26
26
|
pulse: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
|
|
27
27
|
bounce: "bounce 1s infinite",
|
|
28
|
+
"fade-in": "fadeIn 2s ease-in-out infinite",
|
|
29
|
+
"slide-up": "slideUp 2s ease-in-out infinite",
|
|
28
30
|
custom: "custom_value"
|
|
29
31
|
},
|
|
30
32
|
aspectRatio: {
|
|
@@ -1541,6 +1543,31 @@ var tailwindToStyle = (function (exports) {
|
|
|
1541
1543
|
transform: "none",
|
|
1542
1544
|
animationTimingFunction: "cubic-bezier(0,0,0.2,1)"
|
|
1543
1545
|
}
|
|
1546
|
+
},
|
|
1547
|
+
fadeIn: {
|
|
1548
|
+
"0%": {
|
|
1549
|
+
opacity: "0"
|
|
1550
|
+
},
|
|
1551
|
+
"50%": {
|
|
1552
|
+
opacity: "1"
|
|
1553
|
+
},
|
|
1554
|
+
"100%": {
|
|
1555
|
+
opacity: "0"
|
|
1556
|
+
}
|
|
1557
|
+
},
|
|
1558
|
+
slideUp: {
|
|
1559
|
+
"0%": {
|
|
1560
|
+
transform: "translateY(20px)",
|
|
1561
|
+
opacity: "0"
|
|
1562
|
+
},
|
|
1563
|
+
"50%": {
|
|
1564
|
+
transform: "translateY(0)",
|
|
1565
|
+
opacity: "1"
|
|
1566
|
+
},
|
|
1567
|
+
"100%": {
|
|
1568
|
+
transform: "translateY(-20px)",
|
|
1569
|
+
opacity: "0"
|
|
1570
|
+
}
|
|
1544
1571
|
}
|
|
1545
1572
|
},
|
|
1546
1573
|
transitionProperty: {
|
|
@@ -2446,18 +2473,39 @@ var tailwindToStyle = (function (exports) {
|
|
|
2446
2473
|
} = configOptions;
|
|
2447
2474
|
const prefix = `${globalPrefix}animate`;
|
|
2448
2475
|
const {
|
|
2449
|
-
animation = {}
|
|
2476
|
+
animation = {},
|
|
2477
|
+
keyframes = {}
|
|
2450
2478
|
} = theme;
|
|
2451
2479
|
const responsiveCssString = generateCssString$1(_ref => {
|
|
2452
2480
|
let {
|
|
2453
2481
|
getCssByOptions
|
|
2454
2482
|
} = _ref;
|
|
2455
|
-
//
|
|
2483
|
+
// Generate keyframes first
|
|
2484
|
+
let keyframesCSS = "";
|
|
2485
|
+
for (const [name, keyframe] of Object.entries(keyframes)) {
|
|
2486
|
+
keyframesCSS += `@keyframes ${name} {\n`;
|
|
2487
|
+
for (const [percentage, styles] of Object.entries(keyframe)) {
|
|
2488
|
+
keyframesCSS += ` ${percentage} {\n`;
|
|
2489
|
+
for (const [prop, value] of Object.entries(styles)) {
|
|
2490
|
+
const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
2491
|
+
keyframesCSS += ` ${cssProp}: ${value};\n`;
|
|
2492
|
+
}
|
|
2493
|
+
keyframesCSS += " }\n";
|
|
2494
|
+
}
|
|
2495
|
+
keyframesCSS += "}\n";
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
// Merge theme animations with inline animations (but skip inline if keyframes exist)
|
|
2456
2499
|
const allAnimations = {
|
|
2457
2500
|
...animation,
|
|
2458
|
-
// Add inline animations to the mix
|
|
2501
|
+
// Add inline animations to the mix, but skip if keyframes version exists
|
|
2459
2502
|
...Object.keys(INLINE_ANIMATIONS).reduce((acc, key) => {
|
|
2460
|
-
|
|
2503
|
+
// Check if keyframes version exists (both camelCase and kebab-case)
|
|
2504
|
+
const camelCaseKey = key.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
|
|
2505
|
+
const hasKeyframes = keyframes[key] || keyframes[camelCaseKey];
|
|
2506
|
+
if (!hasKeyframes) {
|
|
2507
|
+
acc[key] = `inline-${key}`; // Special marker for inline animations
|
|
2508
|
+
}
|
|
2461
2509
|
return acc;
|
|
2462
2510
|
}, {})
|
|
2463
2511
|
};
|
|
@@ -2503,7 +2551,9 @@ var tailwindToStyle = (function (exports) {
|
|
|
2503
2551
|
}
|
|
2504
2552
|
`;
|
|
2505
2553
|
});
|
|
2506
|
-
|
|
2554
|
+
|
|
2555
|
+
// Combine keyframes and animation classes
|
|
2556
|
+
return keyframesCSS + cssString;
|
|
2507
2557
|
}, configOptions);
|
|
2508
2558
|
return responsiveCssString;
|
|
2509
2559
|
}
|
|
@@ -9145,6 +9195,7 @@ var tailwindToStyle = (function (exports) {
|
|
|
9145
9195
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
9146
9196
|
const totalMarker = performanceMonitor.start("twsx:total");
|
|
9147
9197
|
try {
|
|
9198
|
+
var _options$theme2, _userConfigData$theme2;
|
|
9148
9199
|
if (!obj || typeof obj !== "object") {
|
|
9149
9200
|
logger.warn("twsx: Expected an object but received:", obj);
|
|
9150
9201
|
return "";
|
|
@@ -9221,12 +9272,48 @@ var tailwindToStyle = (function (exports) {
|
|
|
9221
9272
|
// Generate CSS string
|
|
9222
9273
|
const cssString = performanceMonitor.measure(() => generateCssString(styles), "twsx:generate");
|
|
9223
9274
|
|
|
9275
|
+
// Generate keyframes CSS separately
|
|
9276
|
+
const keyframesMarker = performanceMonitor.start("twsx:keyframes");
|
|
9277
|
+
const userConfigData = getConfig();
|
|
9278
|
+
const mergedOptions = {
|
|
9279
|
+
...options,
|
|
9280
|
+
theme: {
|
|
9281
|
+
...options.theme,
|
|
9282
|
+
...userConfigData.theme,
|
|
9283
|
+
extend: {
|
|
9284
|
+
...((_options$theme2 = options.theme) === null || _options$theme2 === void 0 ? void 0 : _options$theme2.extend),
|
|
9285
|
+
...((_userConfigData$theme2 = userConfigData.theme) === null || _userConfigData$theme2 === void 0 ? void 0 : _userConfigData$theme2.extend)
|
|
9286
|
+
}
|
|
9287
|
+
}
|
|
9288
|
+
};
|
|
9289
|
+
const configOptions = getConfigOptions(mergedOptions, Object.keys(plugins));
|
|
9290
|
+
const {
|
|
9291
|
+
keyframes = {}
|
|
9292
|
+
} = configOptions.theme || {};
|
|
9293
|
+
let keyframesCSS = "";
|
|
9294
|
+
for (const [name, keyframe] of Object.entries(keyframes)) {
|
|
9295
|
+
keyframesCSS += `@keyframes ${name} {\n`;
|
|
9296
|
+
for (const [percentage, styles] of Object.entries(keyframe)) {
|
|
9297
|
+
keyframesCSS += ` ${percentage} {\n`;
|
|
9298
|
+
for (const [prop, value] of Object.entries(styles)) {
|
|
9299
|
+
const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
9300
|
+
keyframesCSS += ` ${cssProp}: ${value};\n`;
|
|
9301
|
+
}
|
|
9302
|
+
keyframesCSS += ` }\n`;
|
|
9303
|
+
}
|
|
9304
|
+
keyframesCSS += `}\n`;
|
|
9305
|
+
}
|
|
9306
|
+
performanceMonitor.end(keyframesMarker);
|
|
9307
|
+
|
|
9308
|
+
// Combine keyframes and regular CSS
|
|
9309
|
+
const finalCSS = keyframesCSS + cssString;
|
|
9310
|
+
|
|
9224
9311
|
// Auto-inject if needed
|
|
9225
9312
|
if (inject && typeof window !== "undefined" && typeof document !== "undefined") {
|
|
9226
|
-
performanceMonitor.measure(() => autoInjectCss(
|
|
9313
|
+
performanceMonitor.measure(() => autoInjectCss(finalCSS), "twsx:inject");
|
|
9227
9314
|
}
|
|
9228
9315
|
performanceMonitor.end(totalMarker);
|
|
9229
|
-
return
|
|
9316
|
+
return finalCSS;
|
|
9230
9317
|
} catch (error) {
|
|
9231
9318
|
performanceMonitor.end(totalMarker);
|
|
9232
9319
|
handleError(error, {
|
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* tailwind-to-style v2.10.
|
|
2
|
+
* tailwind-to-style v2.10.3
|
|
3
3
|
* Convert tailwind classes to inline style
|
|
4
4
|
*
|
|
5
5
|
* @author Bigetion
|
|
@@ -26,6 +26,8 @@ const theme = {
|
|
|
26
26
|
ping: "ping 1s cubic-bezier(0, 0, 0.2, 1) infinite",
|
|
27
27
|
pulse: "pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite",
|
|
28
28
|
bounce: "bounce 1s infinite",
|
|
29
|
+
"fade-in": "fadeIn 2s ease-in-out infinite",
|
|
30
|
+
"slide-up": "slideUp 2s ease-in-out infinite",
|
|
29
31
|
custom: "custom_value"
|
|
30
32
|
},
|
|
31
33
|
aspectRatio: {
|
|
@@ -1542,6 +1544,31 @@ const theme = {
|
|
|
1542
1544
|
transform: "none",
|
|
1543
1545
|
animationTimingFunction: "cubic-bezier(0,0,0.2,1)"
|
|
1544
1546
|
}
|
|
1547
|
+
},
|
|
1548
|
+
fadeIn: {
|
|
1549
|
+
"0%": {
|
|
1550
|
+
opacity: "0"
|
|
1551
|
+
},
|
|
1552
|
+
"50%": {
|
|
1553
|
+
opacity: "1"
|
|
1554
|
+
},
|
|
1555
|
+
"100%": {
|
|
1556
|
+
opacity: "0"
|
|
1557
|
+
}
|
|
1558
|
+
},
|
|
1559
|
+
slideUp: {
|
|
1560
|
+
"0%": {
|
|
1561
|
+
transform: "translateY(20px)",
|
|
1562
|
+
opacity: "0"
|
|
1563
|
+
},
|
|
1564
|
+
"50%": {
|
|
1565
|
+
transform: "translateY(0)",
|
|
1566
|
+
opacity: "1"
|
|
1567
|
+
},
|
|
1568
|
+
"100%": {
|
|
1569
|
+
transform: "translateY(-20px)",
|
|
1570
|
+
opacity: "0"
|
|
1571
|
+
}
|
|
1545
1572
|
}
|
|
1546
1573
|
},
|
|
1547
1574
|
transitionProperty: {
|
|
@@ -2447,18 +2474,39 @@ function generator$2H() {
|
|
|
2447
2474
|
} = configOptions;
|
|
2448
2475
|
const prefix = `${globalPrefix}animate`;
|
|
2449
2476
|
const {
|
|
2450
|
-
animation = {}
|
|
2477
|
+
animation = {},
|
|
2478
|
+
keyframes = {}
|
|
2451
2479
|
} = theme;
|
|
2452
2480
|
const responsiveCssString = generateCssString$1(_ref => {
|
|
2453
2481
|
let {
|
|
2454
2482
|
getCssByOptions
|
|
2455
2483
|
} = _ref;
|
|
2456
|
-
//
|
|
2484
|
+
// Generate keyframes first
|
|
2485
|
+
let keyframesCSS = "";
|
|
2486
|
+
for (const [name, keyframe] of Object.entries(keyframes)) {
|
|
2487
|
+
keyframesCSS += `@keyframes ${name} {\n`;
|
|
2488
|
+
for (const [percentage, styles] of Object.entries(keyframe)) {
|
|
2489
|
+
keyframesCSS += ` ${percentage} {\n`;
|
|
2490
|
+
for (const [prop, value] of Object.entries(styles)) {
|
|
2491
|
+
const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
2492
|
+
keyframesCSS += ` ${cssProp}: ${value};\n`;
|
|
2493
|
+
}
|
|
2494
|
+
keyframesCSS += " }\n";
|
|
2495
|
+
}
|
|
2496
|
+
keyframesCSS += "}\n";
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
// Merge theme animations with inline animations (but skip inline if keyframes exist)
|
|
2457
2500
|
const allAnimations = {
|
|
2458
2501
|
...animation,
|
|
2459
|
-
// Add inline animations to the mix
|
|
2502
|
+
// Add inline animations to the mix, but skip if keyframes version exists
|
|
2460
2503
|
...Object.keys(INLINE_ANIMATIONS).reduce((acc, key) => {
|
|
2461
|
-
|
|
2504
|
+
// Check if keyframes version exists (both camelCase and kebab-case)
|
|
2505
|
+
const camelCaseKey = key.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
|
|
2506
|
+
const hasKeyframes = keyframes[key] || keyframes[camelCaseKey];
|
|
2507
|
+
if (!hasKeyframes) {
|
|
2508
|
+
acc[key] = `inline-${key}`; // Special marker for inline animations
|
|
2509
|
+
}
|
|
2462
2510
|
return acc;
|
|
2463
2511
|
}, {})
|
|
2464
2512
|
};
|
|
@@ -2504,7 +2552,9 @@ function generator$2H() {
|
|
|
2504
2552
|
}
|
|
2505
2553
|
`;
|
|
2506
2554
|
});
|
|
2507
|
-
|
|
2555
|
+
|
|
2556
|
+
// Combine keyframes and animation classes
|
|
2557
|
+
return keyframesCSS + cssString;
|
|
2508
2558
|
}, configOptions);
|
|
2509
2559
|
return responsiveCssString;
|
|
2510
2560
|
}
|
|
@@ -9146,6 +9196,7 @@ function twsx(obj) {
|
|
|
9146
9196
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
9147
9197
|
const totalMarker = performanceMonitor.start("twsx:total");
|
|
9148
9198
|
try {
|
|
9199
|
+
var _options$theme2, _userConfigData$theme2;
|
|
9149
9200
|
if (!obj || typeof obj !== "object") {
|
|
9150
9201
|
logger.warn("twsx: Expected an object but received:", obj);
|
|
9151
9202
|
return "";
|
|
@@ -9222,12 +9273,48 @@ function twsx(obj) {
|
|
|
9222
9273
|
// Generate CSS string
|
|
9223
9274
|
const cssString = performanceMonitor.measure(() => generateCssString(styles), "twsx:generate");
|
|
9224
9275
|
|
|
9276
|
+
// Generate keyframes CSS separately
|
|
9277
|
+
const keyframesMarker = performanceMonitor.start("twsx:keyframes");
|
|
9278
|
+
const userConfigData = getConfig();
|
|
9279
|
+
const mergedOptions = {
|
|
9280
|
+
...options,
|
|
9281
|
+
theme: {
|
|
9282
|
+
...options.theme,
|
|
9283
|
+
...userConfigData.theme,
|
|
9284
|
+
extend: {
|
|
9285
|
+
...((_options$theme2 = options.theme) === null || _options$theme2 === void 0 ? void 0 : _options$theme2.extend),
|
|
9286
|
+
...((_userConfigData$theme2 = userConfigData.theme) === null || _userConfigData$theme2 === void 0 ? void 0 : _userConfigData$theme2.extend)
|
|
9287
|
+
}
|
|
9288
|
+
}
|
|
9289
|
+
};
|
|
9290
|
+
const configOptions = getConfigOptions(mergedOptions, Object.keys(plugins));
|
|
9291
|
+
const {
|
|
9292
|
+
keyframes = {}
|
|
9293
|
+
} = configOptions.theme || {};
|
|
9294
|
+
let keyframesCSS = "";
|
|
9295
|
+
for (const [name, keyframe] of Object.entries(keyframes)) {
|
|
9296
|
+
keyframesCSS += `@keyframes ${name} {\n`;
|
|
9297
|
+
for (const [percentage, styles] of Object.entries(keyframe)) {
|
|
9298
|
+
keyframesCSS += ` ${percentage} {\n`;
|
|
9299
|
+
for (const [prop, value] of Object.entries(styles)) {
|
|
9300
|
+
const cssProp = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
|
|
9301
|
+
keyframesCSS += ` ${cssProp}: ${value};\n`;
|
|
9302
|
+
}
|
|
9303
|
+
keyframesCSS += ` }\n`;
|
|
9304
|
+
}
|
|
9305
|
+
keyframesCSS += `}\n`;
|
|
9306
|
+
}
|
|
9307
|
+
performanceMonitor.end(keyframesMarker);
|
|
9308
|
+
|
|
9309
|
+
// Combine keyframes and regular CSS
|
|
9310
|
+
const finalCSS = keyframesCSS + cssString;
|
|
9311
|
+
|
|
9225
9312
|
// Auto-inject if needed
|
|
9226
9313
|
if (inject && typeof window !== "undefined" && typeof document !== "undefined") {
|
|
9227
|
-
performanceMonitor.measure(() => autoInjectCss(
|
|
9314
|
+
performanceMonitor.measure(() => autoInjectCss(finalCSS), "twsx:inject");
|
|
9228
9315
|
}
|
|
9229
9316
|
performanceMonitor.end(totalMarker);
|
|
9230
|
-
return
|
|
9317
|
+
return finalCSS;
|
|
9231
9318
|
} catch (error) {
|
|
9232
9319
|
performanceMonitor.end(totalMarker);
|
|
9233
9320
|
handleError(error, {
|