tailwind-to-style 2.7.8 → 2.8.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 +249 -157
- package/dist/index.browser.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.esm.js +1 -1
- package/lib/build-twsx.js +41 -0
- package/package.json +5 -2
- package/plugins/vite-twsx.js +59 -0
- package/plugins/webpack-twsx.js +61 -0
- package/twsx.css +0 -0
- package/dist/generated-styles.css +0 -336
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
|
-
|
|
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-
|
|
98
|
-
".title": "text-lg font-bold",
|
|
99
|
-
".desc": "text-sm text-gray-
|
|
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
|
-
|
|
110
|
+
**Output**:
|
|
108
111
|
|
|
109
112
|
```css
|
|
110
113
|
.card {
|
|
111
|
-
background-color:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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:
|
|
151
|
-
color:
|
|
152
|
-
padding: 0.5rem;
|
|
153
|
-
border-radius: 0.
|
|
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:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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);
|
|
182
|
-
}
|
|
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;
|
|
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);
|
|
203
169
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
You can group related utilities for better readability:
|
|
209
|
-
|
|
210
|
-
```javascript
|
|
211
|
-
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;
|
|
170
|
+
.button:focus {
|
|
171
|
+
box-shadow: var(--ring-offset-shadow), var(--ring-shadow);
|
|
172
|
+
outline: none;
|
|
224
173
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
padding-right: 1.5rem;
|
|
229
|
-
padding-top: 0.75rem;
|
|
230
|
-
padding-bottom: 0.75rem;
|
|
231
|
-
}
|
|
174
|
+
.button:active {
|
|
175
|
+
background-color: rgba(29, 78, 216, var(--bg-opacity));
|
|
176
|
+
transform: scale(0.95);
|
|
232
177
|
}
|
|
233
178
|
```
|
|
234
179
|
|
|
235
|
-
#### Responsive Variants
|
|
180
|
+
#### Responsive Variants
|
|
236
181
|
|
|
237
|
-
Responsive variants work
|
|
182
|
+
Responsive variants work seamlessly with both standard syntax and grouping syntax:
|
|
238
183
|
|
|
239
184
|
```javascript
|
|
240
185
|
const styles = twsx({
|
|
241
|
-
".
|
|
242
|
-
|
|
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
|
-
|
|
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
|
-
.
|
|
205
|
+
.hero {
|
|
206
|
+
font-size: 1.5rem;
|
|
254
207
|
width: 100%;
|
|
255
208
|
padding: 1rem;
|
|
256
|
-
|
|
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
|
-
.
|
|
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
|
-
.
|
|
224
|
+
.hero {
|
|
225
|
+
font-size: 3rem;
|
|
265
226
|
width: 33.333333%;
|
|
227
|
+
padding: 6rem 2rem;
|
|
266
228
|
}
|
|
267
229
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
|
|
245
|
+
### Performance Utilities
|
|
246
|
+
|
|
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
|
+
```
|
|
292
278
|
|
|
293
|
-
|
|
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:
|
|
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
|
-
|
|
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,108 @@ 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
|
+
### Automated Modular CSS Generation
|
|
492
|
+
|
|
493
|
+
1. Save your modular styles in the `src/twsx/` folder as JS files (e.g., `card.js`, `button.js`).
|
|
494
|
+
2. Use the Vite/Webpack plugin from the `plugins/` folder to automatically generate CSS on every build/rebuild.
|
|
495
|
+
3. All generated CSS files will be merged into a single `twsx.css` file inside `node_modules/tailwind-to-style/`.
|
|
496
|
+
4. In React, simply import this file in your entry point: `import 'tailwind-to-style/twsx.css'`.
|
|
497
|
+
|
|
498
|
+
#### Vite Plugin Usage Example
|
|
499
|
+
|
|
500
|
+
Add the plugin to your `vite.config.js`:
|
|
501
|
+
```js
|
|
502
|
+
import twsxPlugin from './plugins/vite-twsx';
|
|
503
|
+
|
|
504
|
+
export default {
|
|
505
|
+
plugins: [
|
|
506
|
+
twsxPlugin({
|
|
507
|
+
twsxDir: 'src/twsx',
|
|
508
|
+
outDir: 'dist'
|
|
509
|
+
})
|
|
510
|
+
]
|
|
511
|
+
};
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
After build, the merged CSS file will be automatically created at `node_modules/tailwind-to-style/twsx.css`.
|
|
515
|
+
Import in React:
|
|
516
|
+
```js
|
|
517
|
+
// src/index.js
|
|
518
|
+
import 'tailwind-to-style/twsx.css';
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
#### Webpack Plugin Usage Example
|
|
522
|
+
|
|
523
|
+
Add the plugin to your `webpack.config.js`:
|
|
524
|
+
```js
|
|
525
|
+
import TwsxPlugin from './plugins/webpack-twsx';
|
|
526
|
+
|
|
527
|
+
module.exports = {
|
|
528
|
+
plugins: [
|
|
529
|
+
new TwsxPlugin({
|
|
530
|
+
twsxDir: 'src/twsx',
|
|
531
|
+
outDir: 'dist'
|
|
532
|
+
})
|
|
533
|
+
]
|
|
534
|
+
};
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
After build, the merged CSS file will be automatically created at `node_modules/tailwind-to-style/twsx.css`.
|
|
538
|
+
Import in React:
|
|
539
|
+
```js
|
|
540
|
+
// src/index.js
|
|
541
|
+
import 'tailwind-to-style/twsx.css';
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
## Build-Time CSS Generation via Script
|
|
545
|
+
|
|
546
|
+
In addition to using the Vite/Webpack plugin, you can also use a Node.js script to generate a CSS file from the `src/twsx` folder manually or as part of your build workflow.
|
|
547
|
+
|
|
548
|
+
### Script: lib/build-twsx.js
|
|
549
|
+
|
|
550
|
+
This script will read all JS files in `src/twsx`, generate CSS using the `twsx` function, and write the result to `node_modules/tailwind-to-style/twsx.css`.
|
|
551
|
+
|
|
552
|
+
#### How to Use
|
|
553
|
+
|
|
554
|
+
1. Make sure your JS files containing style objects are in `src/twsx`.
|
|
555
|
+
2. Run the script with the following command:
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
node lib/build-twsx.js
|
|
559
|
+
```
|
|
560
|
+
3. After running, the combined CSS file will be available at:
|
|
561
|
+
|
|
562
|
+
```
|
|
563
|
+
node_modules/tailwind-to-style/twsx.css
|
|
564
|
+
```
|
|
565
|
+
4. Import this CSS file in your React entry point:
|
|
566
|
+
|
|
567
|
+
```js
|
|
568
|
+
import 'tailwind-to-style/twsx.css';
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
#### Automatic Integration
|
|
572
|
+
|
|
573
|
+
You can add this script to the build section in your `package.json`:
|
|
574
|
+
|
|
575
|
+
```json
|
|
576
|
+
{
|
|
577
|
+
"scripts": {
|
|
578
|
+
"build-css": "node lib/build-twsx.js"
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
Then run:
|
|
584
|
+
|
|
585
|
+
```bash
|
|
586
|
+
npm run build-css
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
This script is suitable for CI/CD workflows, pre-build steps, or manually generating CSS without a bundler plugin.
|
|
590
|
+
|
|
499
591
|
## License
|
|
500
592
|
|
|
501
593
|
## Contributing
|
package/dist/index.browser.js
CHANGED
package/dist/index.cjs
CHANGED
package/dist/index.esm.js
CHANGED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { pathToFileURL } from "url";
|
|
4
|
+
import { twsx } from "tailwind-to-style";
|
|
5
|
+
|
|
6
|
+
const twsxDir = path.resolve(process.cwd(), "src/twsx");
|
|
7
|
+
const cssFile = path.resolve(process.cwd(), "node_modules/tailwind-to-style/twsx.css");
|
|
8
|
+
|
|
9
|
+
async function buildTwsx() {
|
|
10
|
+
let allCss = "";
|
|
11
|
+
try {
|
|
12
|
+
const files = fs.readdirSync(twsxDir);
|
|
13
|
+
for (const file of files) {
|
|
14
|
+
if (file.endsWith(".js")) {
|
|
15
|
+
try {
|
|
16
|
+
const styleModule = await import(
|
|
17
|
+
pathToFileURL(path.join(twsxDir, file)).href
|
|
18
|
+
);
|
|
19
|
+
const styleObj = styleModule.default || styleModule;
|
|
20
|
+
const css = twsx(styleObj, { inject: false });
|
|
21
|
+
allCss += css + "\n";
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.error(`[build-twsx] Error importing or processing ${file}:`, err);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch (err) {
|
|
28
|
+
console.error('[build-twsx] Error reading twsxDir:', err);
|
|
29
|
+
}
|
|
30
|
+
return allCss;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
(async () => {
|
|
34
|
+
try {
|
|
35
|
+
const allCss = await buildTwsx();
|
|
36
|
+
fs.writeFileSync(cssFile, allCss);
|
|
37
|
+
console.log(`[build-twsx] CSS written to ${cssFile}`);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
console.error('[build-twsx] Error writing CSS:', err);
|
|
40
|
+
}
|
|
41
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwind-to-style",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.1",
|
|
4
4
|
"description": "Convert tailwind classes to inline style",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
"dist",
|
|
11
11
|
"preflight.css",
|
|
12
12
|
"README.md",
|
|
13
|
-
"LICENSE"
|
|
13
|
+
"LICENSE",
|
|
14
|
+
"plugins",
|
|
15
|
+
"lib",
|
|
16
|
+
"twsx.css"
|
|
14
17
|
],
|
|
15
18
|
"scripts": {
|
|
16
19
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --passWithNoTests",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { pathToFileURL } from "url";
|
|
5
|
+
import { twsx } from "tailwind-to-style";
|
|
6
|
+
|
|
7
|
+
async function buildTwsx(twsxDir) {
|
|
8
|
+
let allCss = "";
|
|
9
|
+
try {
|
|
10
|
+
const files = fs.readdirSync(twsxDir);
|
|
11
|
+
for (const file of files) {
|
|
12
|
+
if (file.endsWith(".js")) {
|
|
13
|
+
try {
|
|
14
|
+
const styleModule = await import(
|
|
15
|
+
pathToFileURL(path.join(twsxDir, file)).href
|
|
16
|
+
);
|
|
17
|
+
const styleObj = styleModule.default || styleModule;
|
|
18
|
+
const css = twsx(styleObj, { inject: false });
|
|
19
|
+
allCss += css + "\n";
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.error(`[vite-twsx] Error importing or processing ${file}:`, err);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
} catch (err) {
|
|
26
|
+
console.error('[vite-twsx] Error reading twsxDir:', err);
|
|
27
|
+
}
|
|
28
|
+
return allCss;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default function twsxPlugin(options = {}) {
|
|
32
|
+
const twsxDir = options.twsxDir || path.resolve(process.cwd(), "src/twsx");
|
|
33
|
+
const cssFile = path.resolve(
|
|
34
|
+
process.cwd(),
|
|
35
|
+
"node_modules/tailwind-to-style/twsx.css"
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
name: "vite-twsx",
|
|
40
|
+
async buildStart() {
|
|
41
|
+
try {
|
|
42
|
+
const allCss = await buildTwsx(twsxDir);
|
|
43
|
+
fs.writeFileSync(cssFile, allCss);
|
|
44
|
+
console.log(`[vite-twsx] CSS written to ${cssFile}`);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error('[vite-twsx] Error writing CSS:', err);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
async handleHotUpdate() {
|
|
50
|
+
try {
|
|
51
|
+
const allCss = await buildTwsx(twsxDir);
|
|
52
|
+
fs.writeFileSync(cssFile, allCss);
|
|
53
|
+
console.log(`[vite-twsx] CSS written to ${cssFile}`);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
console.error('[vite-twsx] Error writing CSS:', err);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { pathToFileURL } from "url";
|
|
4
|
+
import { twsx } from "tailwind-to-style";
|
|
5
|
+
|
|
6
|
+
class TwsxPlugin {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
this.twsxDir = options.twsxDir || path.resolve(process.cwd(), "src/twsx");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async buildTwsx() {
|
|
12
|
+
let allCss = "";
|
|
13
|
+
try {
|
|
14
|
+
const files = fs.readdirSync(this.twsxDir);
|
|
15
|
+
for (const file of files) {
|
|
16
|
+
if (file.endsWith(".js")) {
|
|
17
|
+
try {
|
|
18
|
+
const styleModule = await import(
|
|
19
|
+
pathToFileURL(path.join(this.twsxDir, file)).href
|
|
20
|
+
);
|
|
21
|
+
const styleObj = styleModule.default || styleModule;
|
|
22
|
+
const css = twsx(styleObj, { inject: false });
|
|
23
|
+
allCss += css + "\n";
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error(`[webpack-twsx] Error importing or processing ${file}:`, err);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
} catch (err) {
|
|
30
|
+
console.error('[webpack-twsx] Error reading twsxDir:', err);
|
|
31
|
+
}
|
|
32
|
+
return allCss;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
apply(compiler) {
|
|
36
|
+
const cssFile = path.resolve(
|
|
37
|
+
process.cwd(),
|
|
38
|
+
"node_modules/tailwind-to-style/twsx.css"
|
|
39
|
+
);
|
|
40
|
+
compiler.hooks.beforeCompile.tapPromise("TwsxPlugin", async () => {
|
|
41
|
+
try {
|
|
42
|
+
const allCss = await this.buildTwsx();
|
|
43
|
+
fs.writeFileSync(cssFile, allCss);
|
|
44
|
+
console.log(`[webpack-twsx] CSS written to ${cssFile}`);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
console.error('[webpack-twsx] Error writing CSS:', err);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
compiler.hooks.watchRun.tapPromise("TwsxPlugin", async () => {
|
|
50
|
+
try {
|
|
51
|
+
const allCss = await this.buildTwsx();
|
|
52
|
+
fs.writeFileSync(cssFile, allCss);
|
|
53
|
+
console.log(`[webpack-twsx] CSS written to ${cssFile}`);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
console.error('[webpack-twsx] Error writing CSS:', err);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default TwsxPlugin;
|
package/twsx.css
ADDED
|
File without changes
|
|
@@ -1,336 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/* Component Styles */
|
|
3
|
-
/* btn Component */
|
|
4
|
-
.btn {
|
|
5
|
-
display: inline-block;
|
|
6
|
-
padding: 0.5rem 1rem;
|
|
7
|
-
border-radius: 0.25rem;
|
|
8
|
-
font-weight: 500;
|
|
9
|
-
text-align: center;
|
|
10
|
-
text-decoration: none;
|
|
11
|
-
cursor: pointer;
|
|
12
|
-
transition: all 0.2s ease-in-out;
|
|
13
|
-
}
|
|
14
|
-
.btn--primary {
|
|
15
|
-
background-color: #3b82f6;
|
|
16
|
-
color: #ffffff;
|
|
17
|
-
}
|
|
18
|
-
.btn--secondary {
|
|
19
|
-
background-color: #6b7280;
|
|
20
|
-
color: #ffffff;
|
|
21
|
-
}
|
|
22
|
-
.btn--success {
|
|
23
|
-
background-color: #10b981;
|
|
24
|
-
color: #ffffff;
|
|
25
|
-
}
|
|
26
|
-
.btn--danger {
|
|
27
|
-
background-color: #ef4444;
|
|
28
|
-
color: #ffffff;
|
|
29
|
-
}
|
|
30
|
-
.btn:hover {
|
|
31
|
-
opacity: 0.9;
|
|
32
|
-
transform: translateY(-1px);
|
|
33
|
-
}
|
|
34
|
-
.btn:focus {
|
|
35
|
-
outline: 2px solid #3b82f6;
|
|
36
|
-
outline-offset: 2px;
|
|
37
|
-
}
|
|
38
|
-
.btn:active {
|
|
39
|
-
transform: translateY(0);
|
|
40
|
-
}
|
|
41
|
-
/* card Component */
|
|
42
|
-
.card {
|
|
43
|
-
background-color: #ffffff;
|
|
44
|
-
border-radius: 0.5rem;
|
|
45
|
-
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
|
46
|
-
padding: 1.5rem;
|
|
47
|
-
}
|
|
48
|
-
.card--elevated {
|
|
49
|
-
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
|
50
|
-
}
|
|
51
|
-
.card--bordered {
|
|
52
|
-
border: 1px solid #e5e7eb;
|
|
53
|
-
box-shadow: none;
|
|
54
|
-
}
|
|
55
|
-
/* input Component */
|
|
56
|
-
.input {
|
|
57
|
-
display: block;
|
|
58
|
-
width: 100%;
|
|
59
|
-
padding: 0.5rem 0.75rem;
|
|
60
|
-
border: 1px solid #d1d5db;
|
|
61
|
-
border-radius: 0.375rem;
|
|
62
|
-
font-size: 1rem;
|
|
63
|
-
line-height: 1.5;
|
|
64
|
-
}
|
|
65
|
-
.input:focus {
|
|
66
|
-
outline: none;
|
|
67
|
-
border-color: #3b82f6;
|
|
68
|
-
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
69
|
-
}
|
|
70
|
-
.input:disabled {
|
|
71
|
-
background-color: #f3f4f6;
|
|
72
|
-
opacity: 0.6;
|
|
73
|
-
cursor: not-allowed;
|
|
74
|
-
}
|
|
75
|
-
/* Utility Styles */
|
|
76
|
-
/* Background Color utilities */
|
|
77
|
-
.bg-primary { background-color: #3b82f6; }
|
|
78
|
-
.bg-secondary { background-color: #6b7280; }
|
|
79
|
-
.bg-success { background-color: #10b981; }
|
|
80
|
-
.bg-warning { background-color: #f59e0b; }
|
|
81
|
-
.bg-error { background-color: #ef4444; }
|
|
82
|
-
.bg-white { background-color: #ffffff; }
|
|
83
|
-
.bg-black { background-color: #000000; }
|
|
84
|
-
.bg-gray-100 { background-color: #f3f4f6; }
|
|
85
|
-
.bg-gray-200 { background-color: #e5e7eb; }
|
|
86
|
-
.bg-gray-300 { background-color: #d1d5db; }
|
|
87
|
-
.bg-gray-400 { background-color: #9ca3af; }
|
|
88
|
-
.bg-gray-500 { background-color: #6b7280; }
|
|
89
|
-
.bg-gray-600 { background-color: #4b5563; }
|
|
90
|
-
.bg-gray-700 { background-color: #374151; }
|
|
91
|
-
.bg-gray-800 { background-color: #1f2937; }
|
|
92
|
-
.bg-gray-900 { background-color: #111827; }
|
|
93
|
-
/* Text Color utilities */
|
|
94
|
-
.text-primary { color: #3b82f6; }
|
|
95
|
-
.text-secondary { color: #6b7280; }
|
|
96
|
-
.text-success { color: #10b981; }
|
|
97
|
-
.text-warning { color: #f59e0b; }
|
|
98
|
-
.text-error { color: #ef4444; }
|
|
99
|
-
.text-white { color: #ffffff; }
|
|
100
|
-
.text-black { color: #000000; }
|
|
101
|
-
.text-gray-100 { color: #f3f4f6; }
|
|
102
|
-
.text-gray-200 { color: #e5e7eb; }
|
|
103
|
-
.text-gray-300 { color: #d1d5db; }
|
|
104
|
-
.text-gray-400 { color: #9ca3af; }
|
|
105
|
-
.text-gray-500 { color: #6b7280; }
|
|
106
|
-
.text-gray-600 { color: #4b5563; }
|
|
107
|
-
.text-gray-700 { color: #374151; }
|
|
108
|
-
.text-gray-800 { color: #1f2937; }
|
|
109
|
-
.text-gray-900 { color: #111827; }
|
|
110
|
-
/* Padding utilities */
|
|
111
|
-
.p-0 { padding: 0; }
|
|
112
|
-
.px-0 { padding-left: 0; padding-right: 0; }
|
|
113
|
-
.py-0 { padding-top: 0; padding-bottom: 0; }
|
|
114
|
-
.pt-0 { padding-top: 0; }
|
|
115
|
-
.pr-0 { padding-right: 0; }
|
|
116
|
-
.pb-0 { padding-bottom: 0; }
|
|
117
|
-
.pl-0 { padding-left: 0; }
|
|
118
|
-
.p-1 { padding: 0.25rem; }
|
|
119
|
-
.px-1 { padding-left: 0.25rem; padding-right: 0.25rem; }
|
|
120
|
-
.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }
|
|
121
|
-
.pt-1 { padding-top: 0.25rem; }
|
|
122
|
-
.pr-1 { padding-right: 0.25rem; }
|
|
123
|
-
.pb-1 { padding-bottom: 0.25rem; }
|
|
124
|
-
.pl-1 { padding-left: 0.25rem; }
|
|
125
|
-
.p-2 { padding: 0.5rem; }
|
|
126
|
-
.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }
|
|
127
|
-
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
|
|
128
|
-
.pt-2 { padding-top: 0.5rem; }
|
|
129
|
-
.pr-2 { padding-right: 0.5rem; }
|
|
130
|
-
.pb-2 { padding-bottom: 0.5rem; }
|
|
131
|
-
.pl-2 { padding-left: 0.5rem; }
|
|
132
|
-
.p-3 { padding: 0.75rem; }
|
|
133
|
-
.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
|
|
134
|
-
.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
|
|
135
|
-
.pt-3 { padding-top: 0.75rem; }
|
|
136
|
-
.pr-3 { padding-right: 0.75rem; }
|
|
137
|
-
.pb-3 { padding-bottom: 0.75rem; }
|
|
138
|
-
.pl-3 { padding-left: 0.75rem; }
|
|
139
|
-
.p-4 { padding: 1rem; }
|
|
140
|
-
.px-4 { padding-left: 1rem; padding-right: 1rem; }
|
|
141
|
-
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
|
|
142
|
-
.pt-4 { padding-top: 1rem; }
|
|
143
|
-
.pr-4 { padding-right: 1rem; }
|
|
144
|
-
.pb-4 { padding-bottom: 1rem; }
|
|
145
|
-
.pl-4 { padding-left: 1rem; }
|
|
146
|
-
.p-5 { padding: 1.25rem; }
|
|
147
|
-
.px-5 { padding-left: 1.25rem; padding-right: 1.25rem; }
|
|
148
|
-
.py-5 { padding-top: 1.25rem; padding-bottom: 1.25rem; }
|
|
149
|
-
.pt-5 { padding-top: 1.25rem; }
|
|
150
|
-
.pr-5 { padding-right: 1.25rem; }
|
|
151
|
-
.pb-5 { padding-bottom: 1.25rem; }
|
|
152
|
-
.pl-5 { padding-left: 1.25rem; }
|
|
153
|
-
.p-6 { padding: 1.5rem; }
|
|
154
|
-
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
|
|
155
|
-
.py-6 { padding-top: 1.5rem; padding-bottom: 1.5rem; }
|
|
156
|
-
.pt-6 { padding-top: 1.5rem; }
|
|
157
|
-
.pr-6 { padding-right: 1.5rem; }
|
|
158
|
-
.pb-6 { padding-bottom: 1.5rem; }
|
|
159
|
-
.pl-6 { padding-left: 1.5rem; }
|
|
160
|
-
.p-8 { padding: 2rem; }
|
|
161
|
-
.px-8 { padding-left: 2rem; padding-right: 2rem; }
|
|
162
|
-
.py-8 { padding-top: 2rem; padding-bottom: 2rem; }
|
|
163
|
-
.pt-8 { padding-top: 2rem; }
|
|
164
|
-
.pr-8 { padding-right: 2rem; }
|
|
165
|
-
.pb-8 { padding-bottom: 2rem; }
|
|
166
|
-
.pl-8 { padding-left: 2rem; }
|
|
167
|
-
.p-10 { padding: 2.5rem; }
|
|
168
|
-
.px-10 { padding-left: 2.5rem; padding-right: 2.5rem; }
|
|
169
|
-
.py-10 { padding-top: 2.5rem; padding-bottom: 2.5rem; }
|
|
170
|
-
.pt-10 { padding-top: 2.5rem; }
|
|
171
|
-
.pr-10 { padding-right: 2.5rem; }
|
|
172
|
-
.pb-10 { padding-bottom: 2.5rem; }
|
|
173
|
-
.pl-10 { padding-left: 2.5rem; }
|
|
174
|
-
.p-12 { padding: 3rem; }
|
|
175
|
-
.px-12 { padding-left: 3rem; padding-right: 3rem; }
|
|
176
|
-
.py-12 { padding-top: 3rem; padding-bottom: 3rem; }
|
|
177
|
-
.pt-12 { padding-top: 3rem; }
|
|
178
|
-
.pr-12 { padding-right: 3rem; }
|
|
179
|
-
.pb-12 { padding-bottom: 3rem; }
|
|
180
|
-
.pl-12 { padding-left: 3rem; }
|
|
181
|
-
.p-16 { padding: 4rem; }
|
|
182
|
-
.px-16 { padding-left: 4rem; padding-right: 4rem; }
|
|
183
|
-
.py-16 { padding-top: 4rem; padding-bottom: 4rem; }
|
|
184
|
-
.pt-16 { padding-top: 4rem; }
|
|
185
|
-
.pr-16 { padding-right: 4rem; }
|
|
186
|
-
.pb-16 { padding-bottom: 4rem; }
|
|
187
|
-
.pl-16 { padding-left: 4rem; }
|
|
188
|
-
.p-20 { padding: 5rem; }
|
|
189
|
-
.px-20 { padding-left: 5rem; padding-right: 5rem; }
|
|
190
|
-
.py-20 { padding-top: 5rem; padding-bottom: 5rem; }
|
|
191
|
-
.pt-20 { padding-top: 5rem; }
|
|
192
|
-
.pr-20 { padding-right: 5rem; }
|
|
193
|
-
.pb-20 { padding-bottom: 5rem; }
|
|
194
|
-
.pl-20 { padding-left: 5rem; }
|
|
195
|
-
.p-24 { padding: 6rem; }
|
|
196
|
-
.px-24 { padding-left: 6rem; padding-right: 6rem; }
|
|
197
|
-
.py-24 { padding-top: 6rem; padding-bottom: 6rem; }
|
|
198
|
-
.pt-24 { padding-top: 6rem; }
|
|
199
|
-
.pr-24 { padding-right: 6rem; }
|
|
200
|
-
.pb-24 { padding-bottom: 6rem; }
|
|
201
|
-
.pl-24 { padding-left: 6rem; }
|
|
202
|
-
.p-32 { padding: 8rem; }
|
|
203
|
-
.px-32 { padding-left: 8rem; padding-right: 8rem; }
|
|
204
|
-
.py-32 { padding-top: 8rem; padding-bottom: 8rem; }
|
|
205
|
-
.pt-32 { padding-top: 8rem; }
|
|
206
|
-
.pr-32 { padding-right: 8rem; }
|
|
207
|
-
.pb-32 { padding-bottom: 8rem; }
|
|
208
|
-
.pl-32 { padding-left: 8rem; }
|
|
209
|
-
/* Margin utilities */
|
|
210
|
-
.m-0 { margin: 0; }
|
|
211
|
-
.mx-0 { margin-left: 0; margin-right: 0; }
|
|
212
|
-
.my-0 { margin-top: 0; margin-bottom: 0; }
|
|
213
|
-
.mt-0 { margin-top: 0; }
|
|
214
|
-
.mr-0 { margin-right: 0; }
|
|
215
|
-
.mb-0 { margin-bottom: 0; }
|
|
216
|
-
.ml-0 { margin-left: 0; }
|
|
217
|
-
.m-1 { margin: 0.25rem; }
|
|
218
|
-
.mx-1 { margin-left: 0.25rem; margin-right: 0.25rem; }
|
|
219
|
-
.my-1 { margin-top: 0.25rem; margin-bottom: 0.25rem; }
|
|
220
|
-
.mt-1 { margin-top: 0.25rem; }
|
|
221
|
-
.mr-1 { margin-right: 0.25rem; }
|
|
222
|
-
.mb-1 { margin-bottom: 0.25rem; }
|
|
223
|
-
.ml-1 { margin-left: 0.25rem; }
|
|
224
|
-
.m-2 { margin: 0.5rem; }
|
|
225
|
-
.mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; }
|
|
226
|
-
.my-2 { margin-top: 0.5rem; margin-bottom: 0.5rem; }
|
|
227
|
-
.mt-2 { margin-top: 0.5rem; }
|
|
228
|
-
.mr-2 { margin-right: 0.5rem; }
|
|
229
|
-
.mb-2 { margin-bottom: 0.5rem; }
|
|
230
|
-
.ml-2 { margin-left: 0.5rem; }
|
|
231
|
-
.m-3 { margin: 0.75rem; }
|
|
232
|
-
.mx-3 { margin-left: 0.75rem; margin-right: 0.75rem; }
|
|
233
|
-
.my-3 { margin-top: 0.75rem; margin-bottom: 0.75rem; }
|
|
234
|
-
.mt-3 { margin-top: 0.75rem; }
|
|
235
|
-
.mr-3 { margin-right: 0.75rem; }
|
|
236
|
-
.mb-3 { margin-bottom: 0.75rem; }
|
|
237
|
-
.ml-3 { margin-left: 0.75rem; }
|
|
238
|
-
.m-4 { margin: 1rem; }
|
|
239
|
-
.mx-4 { margin-left: 1rem; margin-right: 1rem; }
|
|
240
|
-
.my-4 { margin-top: 1rem; margin-bottom: 1rem; }
|
|
241
|
-
.mt-4 { margin-top: 1rem; }
|
|
242
|
-
.mr-4 { margin-right: 1rem; }
|
|
243
|
-
.mb-4 { margin-bottom: 1rem; }
|
|
244
|
-
.ml-4 { margin-left: 1rem; }
|
|
245
|
-
.m-5 { margin: 1.25rem; }
|
|
246
|
-
.mx-5 { margin-left: 1.25rem; margin-right: 1.25rem; }
|
|
247
|
-
.my-5 { margin-top: 1.25rem; margin-bottom: 1.25rem; }
|
|
248
|
-
.mt-5 { margin-top: 1.25rem; }
|
|
249
|
-
.mr-5 { margin-right: 1.25rem; }
|
|
250
|
-
.mb-5 { margin-bottom: 1.25rem; }
|
|
251
|
-
.ml-5 { margin-left: 1.25rem; }
|
|
252
|
-
.m-6 { margin: 1.5rem; }
|
|
253
|
-
.mx-6 { margin-left: 1.5rem; margin-right: 1.5rem; }
|
|
254
|
-
.my-6 { margin-top: 1.5rem; margin-bottom: 1.5rem; }
|
|
255
|
-
.mt-6 { margin-top: 1.5rem; }
|
|
256
|
-
.mr-6 { margin-right: 1.5rem; }
|
|
257
|
-
.mb-6 { margin-bottom: 1.5rem; }
|
|
258
|
-
.ml-6 { margin-left: 1.5rem; }
|
|
259
|
-
.m-8 { margin: 2rem; }
|
|
260
|
-
.mx-8 { margin-left: 2rem; margin-right: 2rem; }
|
|
261
|
-
.my-8 { margin-top: 2rem; margin-bottom: 2rem; }
|
|
262
|
-
.mt-8 { margin-top: 2rem; }
|
|
263
|
-
.mr-8 { margin-right: 2rem; }
|
|
264
|
-
.mb-8 { margin-bottom: 2rem; }
|
|
265
|
-
.ml-8 { margin-left: 2rem; }
|
|
266
|
-
.m-10 { margin: 2.5rem; }
|
|
267
|
-
.mx-10 { margin-left: 2.5rem; margin-right: 2.5rem; }
|
|
268
|
-
.my-10 { margin-top: 2.5rem; margin-bottom: 2.5rem; }
|
|
269
|
-
.mt-10 { margin-top: 2.5rem; }
|
|
270
|
-
.mr-10 { margin-right: 2.5rem; }
|
|
271
|
-
.mb-10 { margin-bottom: 2.5rem; }
|
|
272
|
-
.ml-10 { margin-left: 2.5rem; }
|
|
273
|
-
.m-12 { margin: 3rem; }
|
|
274
|
-
.mx-12 { margin-left: 3rem; margin-right: 3rem; }
|
|
275
|
-
.my-12 { margin-top: 3rem; margin-bottom: 3rem; }
|
|
276
|
-
.mt-12 { margin-top: 3rem; }
|
|
277
|
-
.mr-12 { margin-right: 3rem; }
|
|
278
|
-
.mb-12 { margin-bottom: 3rem; }
|
|
279
|
-
.ml-12 { margin-left: 3rem; }
|
|
280
|
-
.m-16 { margin: 4rem; }
|
|
281
|
-
.mx-16 { margin-left: 4rem; margin-right: 4rem; }
|
|
282
|
-
.my-16 { margin-top: 4rem; margin-bottom: 4rem; }
|
|
283
|
-
.mt-16 { margin-top: 4rem; }
|
|
284
|
-
.mr-16 { margin-right: 4rem; }
|
|
285
|
-
.mb-16 { margin-bottom: 4rem; }
|
|
286
|
-
.ml-16 { margin-left: 4rem; }
|
|
287
|
-
.m-20 { margin: 5rem; }
|
|
288
|
-
.mx-20 { margin-left: 5rem; margin-right: 5rem; }
|
|
289
|
-
.my-20 { margin-top: 5rem; margin-bottom: 5rem; }
|
|
290
|
-
.mt-20 { margin-top: 5rem; }
|
|
291
|
-
.mr-20 { margin-right: 5rem; }
|
|
292
|
-
.mb-20 { margin-bottom: 5rem; }
|
|
293
|
-
.ml-20 { margin-left: 5rem; }
|
|
294
|
-
.m-24 { margin: 6rem; }
|
|
295
|
-
.mx-24 { margin-left: 6rem; margin-right: 6rem; }
|
|
296
|
-
.my-24 { margin-top: 6rem; margin-bottom: 6rem; }
|
|
297
|
-
.mt-24 { margin-top: 6rem; }
|
|
298
|
-
.mr-24 { margin-right: 6rem; }
|
|
299
|
-
.mb-24 { margin-bottom: 6rem; }
|
|
300
|
-
.ml-24 { margin-left: 6rem; }
|
|
301
|
-
.m-32 { margin: 8rem; }
|
|
302
|
-
.mx-32 { margin-left: 8rem; margin-right: 8rem; }
|
|
303
|
-
.my-32 { margin-top: 8rem; margin-bottom: 8rem; }
|
|
304
|
-
.mt-32 { margin-top: 8rem; }
|
|
305
|
-
.mr-32 { margin-right: 8rem; }
|
|
306
|
-
.mb-32 { margin-bottom: 8rem; }
|
|
307
|
-
.ml-32 { margin-left: 8rem; }
|
|
308
|
-
/* Font Size utilities */
|
|
309
|
-
.text-xs { font-size: 0.75rem; }
|
|
310
|
-
.text-sm { font-size: 0.875rem; }
|
|
311
|
-
.text-base { font-size: 1rem; }
|
|
312
|
-
.text-lg { font-size: 1.125rem; }
|
|
313
|
-
.text-xl { font-size: 1.25rem; }
|
|
314
|
-
.text-2xl { font-size: 1.5rem; }
|
|
315
|
-
.text-3xl { font-size: 1.875rem; }
|
|
316
|
-
.text-4xl { font-size: 2.25rem; }
|
|
317
|
-
/* Border Radius utilities */
|
|
318
|
-
.rounded-none { border-radius: 0; }
|
|
319
|
-
.rounded-sm { border-radius: 0.125rem; }
|
|
320
|
-
.rounded { border-radius: 0.25rem; }
|
|
321
|
-
.rounded-md { border-radius: 0.375rem; }
|
|
322
|
-
.rounded-lg { border-radius: 0.5rem; }
|
|
323
|
-
.rounded-xl { border-radius: 0.75rem; }
|
|
324
|
-
.rounded-2xl { border-radius: 1rem; }
|
|
325
|
-
.rounded-full { border-radius: 9999px; }
|
|
326
|
-
/* Custom Styles */
|
|
327
|
-
.container {
|
|
328
|
-
max-width: 1200px;
|
|
329
|
-
margin: 0 auto;
|
|
330
|
-
padding: 0 1rem;
|
|
331
|
-
}
|
|
332
|
-
.flex-center {
|
|
333
|
-
display: flex;
|
|
334
|
-
align-items: center;
|
|
335
|
-
justify-content: center;
|
|
336
|
-
}
|