@acusti/styling 2.1.0 → 2.1.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 +629 -15
- package/dist/index.js +41 -23
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -5,26 +5,640 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@acusti/styling)
|
|
6
6
|
[](https://bundlejs.com/?q=%40acusti%2Fstyling)
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
`@acusti/styling` provides React 19+ optimized styling utilities, including
|
|
9
|
+
the `Style` component that leverages React’s new `<style>` element special
|
|
10
|
+
rendering behavior and a collection of CSS utilities. It’s designed for
|
|
11
|
+
modern React applications that need efficient, SSR-friendly styling with
|
|
12
|
+
automatic optimization.
|
|
13
|
+
|
|
14
|
+
## Key Features
|
|
15
|
+
|
|
16
|
+
- **React 19+ optimized** - Uses React’s new `<style>` element special
|
|
17
|
+
rendering behavior
|
|
18
|
+
- **Automatic minification** - CSS is minified and cached for optimal
|
|
19
|
+
performance
|
|
20
|
+
- **SSR-friendly** - No hydration errors with server-side rendering
|
|
21
|
+
- **Style deduplication** - Identical styles are automatically deduplicated
|
|
22
|
+
- **Suspense integration** - Assets in CSS suspend properly during loading
|
|
23
|
+
- **Global cache** - Minified styles are cached to avoid re-computation
|
|
24
|
+
- **CSS utilities** - Includes useful CSS constants like system fonts
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @acusti/styling
|
|
30
|
+
# or
|
|
31
|
+
yarn add @acusti/styling
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import { Style } from '@acusti/styling';
|
|
38
|
+
|
|
39
|
+
function MyComponent() {
|
|
40
|
+
return (
|
|
41
|
+
<>
|
|
42
|
+
<Style>
|
|
43
|
+
{`
|
|
44
|
+
.my-button {
|
|
45
|
+
background: #007bff;
|
|
46
|
+
color: white;
|
|
47
|
+
border: none;
|
|
48
|
+
padding: 8px 16px;
|
|
49
|
+
border-radius: 4px;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
}
|
|
52
|
+
.my-button:hover {
|
|
53
|
+
background: #0056b3;
|
|
54
|
+
}
|
|
55
|
+
`}
|
|
56
|
+
</Style>
|
|
57
|
+
|
|
58
|
+
<button className="my-button">Click me</button>
|
|
59
|
+
</>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## React 19+ `<style>` Special Behavior
|
|
65
|
+
|
|
66
|
+
This package leverages React 19’s new `<style>` element
|
|
11
67
|
[special rendering behavior](https://react.dev/reference/react-dom/components/style#special-rendering-behavior):
|
|
12
68
|
|
|
13
69
|
> React will move `<style>` components to the document’s `<head>`,
|
|
14
70
|
> de-duplicate identical stylesheets, and suspend while the stylesheet is
|
|
15
71
|
> loading.
|
|
16
72
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
73
|
+
**Benefits:**
|
|
74
|
+
|
|
75
|
+
- **SSR-friendly** - No hydration errors between server and client
|
|
76
|
+
- **Automatic deduplication** - Identical styles are merged automatically
|
|
77
|
+
- **Suspense integration** - CSS assets (fonts, images) suspend properly
|
|
78
|
+
during loading
|
|
79
|
+
- **Performance optimized** - Styles are hoisted to `<head>` for optimal
|
|
80
|
+
loading
|
|
81
|
+
|
|
82
|
+
## API Reference
|
|
83
|
+
|
|
84
|
+
### `Style` Component
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
type Props = {
|
|
88
|
+
children: string;
|
|
89
|
+
href?: string;
|
|
90
|
+
precedence?: string;
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Props:**
|
|
95
|
+
|
|
96
|
+
- **`children`** (string, required): The CSS string to render
|
|
97
|
+
- **`href`** (string, optional): Custom identifier for the stylesheet.
|
|
98
|
+
Defaults to minified CSS content
|
|
99
|
+
- **`precedence`** (string, optional): Controls loading priority. Defaults
|
|
100
|
+
to `'medium'`
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { Style } from '@acusti/styling';
|
|
104
|
+
|
|
105
|
+
function MyComponent() {
|
|
106
|
+
return (
|
|
107
|
+
<Style precedence="high" href="critical-styles">
|
|
108
|
+
{`.critical { display: block !important; }`}
|
|
109
|
+
</Style>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### CSS Minification Function
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import { minifyStyles } from '@acusti/styling';
|
|
118
|
+
|
|
119
|
+
const minified = minifyStyles(`
|
|
120
|
+
.button {
|
|
121
|
+
background-color: #ffffff;
|
|
122
|
+
padding: 10px 20px;
|
|
123
|
+
border: 1px solid #cccccc;
|
|
124
|
+
}
|
|
125
|
+
`);
|
|
126
|
+
// Result: ".button{background-color:#fff;padding:10px 20px;border:1px solid #ccc}"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### CSS Constants
|
|
130
|
+
|
|
131
|
+
- **`SYSTEM_UI_FONT`**: Cross-platform system UI font stack
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
import { Style, SYSTEM_UI_FONT } from '@acusti/styling';
|
|
135
|
+
|
|
136
|
+
function SystemStyles() {
|
|
137
|
+
return <Style>{':root { font-family: ${SYSTEM_UI_FONT}; }'}</Style>;
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Usage Examples
|
|
142
|
+
|
|
143
|
+
### Component-Scoped Styles
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
import { Style } from '@acusti/styling';
|
|
147
|
+
|
|
148
|
+
function Card({ title, children }) {
|
|
149
|
+
return (
|
|
150
|
+
<>
|
|
151
|
+
<Style>
|
|
152
|
+
{`
|
|
153
|
+
.card {
|
|
154
|
+
border: 1px solid #e0e0e0;
|
|
155
|
+
border-radius: 8px;
|
|
156
|
+
padding: 16px;
|
|
157
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
158
|
+
background: white;
|
|
159
|
+
}
|
|
160
|
+
.card-title {
|
|
161
|
+
margin: 0 0 12px 0;
|
|
162
|
+
font-size: 18px;
|
|
163
|
+
font-weight: 600;
|
|
164
|
+
color: #333;
|
|
165
|
+
}
|
|
166
|
+
.card-content {
|
|
167
|
+
color: #666;
|
|
168
|
+
line-height: 1.5;
|
|
169
|
+
}
|
|
170
|
+
`}
|
|
171
|
+
</Style>
|
|
172
|
+
|
|
173
|
+
<div className="card">
|
|
174
|
+
<h3 className="card-title">{title}</h3>
|
|
175
|
+
<div className="card-content">{children}</div>
|
|
176
|
+
</div>
|
|
177
|
+
</>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Global Styles with System Fonts
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { Style, SYSTEM_UI_FONT } from '@acusti/styling';
|
|
186
|
+
|
|
187
|
+
function GlobalStyles() {
|
|
188
|
+
return (
|
|
189
|
+
<Style precedence="low" href="global-styles">
|
|
190
|
+
{`
|
|
191
|
+
* {
|
|
192
|
+
box-sizing: border-box;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
body {
|
|
196
|
+
margin: 0;
|
|
197
|
+
font-family: ${SYSTEM_UI_FONT};
|
|
198
|
+
line-height: 1.5;
|
|
199
|
+
color: #333;
|
|
200
|
+
background: #fff;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
button {
|
|
204
|
+
font-family: inherit;
|
|
205
|
+
cursor: pointer;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
input, textarea {
|
|
209
|
+
font-family: inherit;
|
|
210
|
+
}
|
|
211
|
+
`}
|
|
212
|
+
</Style>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Theme-Based Styling
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
import { Style } from '@acusti/styling';
|
|
221
|
+
|
|
222
|
+
function ThemedButton({ theme = 'primary', children }) {
|
|
223
|
+
const themes = {
|
|
224
|
+
primary: {
|
|
225
|
+
bg: '#007bff',
|
|
226
|
+
hoverBg: '#0056b3',
|
|
227
|
+
color: 'white',
|
|
228
|
+
},
|
|
229
|
+
secondary: {
|
|
230
|
+
bg: '#6c757d',
|
|
231
|
+
hoverBg: '#545b62',
|
|
232
|
+
color: 'white',
|
|
233
|
+
},
|
|
234
|
+
success: {
|
|
235
|
+
bg: '#28a745',
|
|
236
|
+
hoverBg: '#1e7e34',
|
|
237
|
+
color: 'white',
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const currentTheme = themes[theme] || themes.primary;
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<>
|
|
245
|
+
<Style href={`button-${theme}`}>
|
|
246
|
+
{`
|
|
247
|
+
.btn-${theme} {
|
|
248
|
+
background: ${currentTheme.bg};
|
|
249
|
+
color: ${currentTheme.color};
|
|
250
|
+
border: none;
|
|
251
|
+
padding: 8px 16px;
|
|
252
|
+
border-radius: 4px;
|
|
253
|
+
font-size: 14px;
|
|
254
|
+
font-weight: 500;
|
|
255
|
+
cursor: pointer;
|
|
256
|
+
transition: background-color 0.2s;
|
|
257
|
+
}
|
|
258
|
+
.btn-${theme}:hover {
|
|
259
|
+
background: ${currentTheme.hoverBg};
|
|
260
|
+
}
|
|
261
|
+
.btn-${theme}:focus {
|
|
262
|
+
outline: 2px solid ${currentTheme.bg};
|
|
263
|
+
outline-offset: 2px;
|
|
264
|
+
}
|
|
265
|
+
`}
|
|
266
|
+
</Style>
|
|
267
|
+
|
|
268
|
+
<button className={`btn-${theme}`}>{children}</button>
|
|
269
|
+
</>
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Dynamic Styles
|
|
275
|
+
|
|
276
|
+
```tsx
|
|
277
|
+
import { Style } from '@acusti/styling';
|
|
278
|
+
import { useState } from 'react';
|
|
279
|
+
|
|
280
|
+
function DynamicCard() {
|
|
281
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
282
|
+
const [accentColor, setAccentColor] = useState('#007bff');
|
|
283
|
+
|
|
284
|
+
return (
|
|
285
|
+
<>
|
|
286
|
+
<Style href={`dynamic-card-${accentColor}`}>
|
|
287
|
+
{`
|
|
288
|
+
.dynamic-card {
|
|
289
|
+
border: 2px solid ${accentColor};
|
|
290
|
+
border-radius: 8px;
|
|
291
|
+
padding: 16px;
|
|
292
|
+
transition: all 0.3s ease;
|
|
293
|
+
cursor: pointer;
|
|
294
|
+
background: white;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.dynamic-card:hover {
|
|
298
|
+
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
|
299
|
+
transform: translateY(-2px);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.dynamic-card.expanded {
|
|
303
|
+
background: ${accentColor}10;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.card-header {
|
|
307
|
+
color: ${accentColor};
|
|
308
|
+
font-weight: 600;
|
|
309
|
+
margin-bottom: 8px;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.card-controls {
|
|
313
|
+
margin-top: 16px;
|
|
314
|
+
display: flex;
|
|
315
|
+
gap: 8px;
|
|
316
|
+
align-items: center;
|
|
317
|
+
}
|
|
318
|
+
`}
|
|
319
|
+
</Style>
|
|
320
|
+
|
|
321
|
+
<div
|
|
322
|
+
className={`dynamic-card ${isExpanded ? 'expanded' : ''}`}
|
|
323
|
+
onClick={() => setIsExpanded(!isExpanded)}
|
|
324
|
+
>
|
|
325
|
+
<div className="card-header">
|
|
326
|
+
Dynamic Card{' '}
|
|
327
|
+
{isExpanded ? '(Expanded)' : '(Collapsed)'}
|
|
328
|
+
</div>
|
|
329
|
+
|
|
330
|
+
<p>Click to toggle expansion state</p>
|
|
331
|
+
|
|
332
|
+
{isExpanded && (
|
|
333
|
+
<div className="card-controls">
|
|
334
|
+
<label>Accent Color:</label>
|
|
335
|
+
<input
|
|
336
|
+
type="color"
|
|
337
|
+
value={accentColor}
|
|
338
|
+
onChange={(e) =>
|
|
339
|
+
setAccentColor(e.target.value)
|
|
340
|
+
}
|
|
341
|
+
onClick={(e) => e.stopPropagation()}
|
|
342
|
+
/>
|
|
343
|
+
</div>
|
|
344
|
+
)}
|
|
345
|
+
</div>
|
|
346
|
+
</>
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Critical CSS with High Precedence
|
|
352
|
+
|
|
353
|
+
```tsx
|
|
354
|
+
import { Style } from '@acusti/styling';
|
|
355
|
+
|
|
356
|
+
function CriticalStyles() {
|
|
357
|
+
return (
|
|
358
|
+
<Style precedence="high" href="critical">
|
|
359
|
+
{`
|
|
360
|
+
/* Critical above-the-fold styles */
|
|
361
|
+
.hero {
|
|
362
|
+
height: 100vh;
|
|
363
|
+
display: flex;
|
|
364
|
+
align-items: center;
|
|
365
|
+
justify-content: center;
|
|
366
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
367
|
+
color: white;
|
|
368
|
+
text-align: center;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.hero h1 {
|
|
372
|
+
font-size: clamp(2rem, 5vw, 4rem);
|
|
373
|
+
margin: 0;
|
|
374
|
+
font-weight: 700;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.hero p {
|
|
378
|
+
font-size: clamp(1rem, 3vw, 1.5rem);
|
|
379
|
+
margin: 1rem 0 2rem 0;
|
|
380
|
+
opacity: 0.9;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.cta-button {
|
|
384
|
+
background: rgba(255,255,255,0.2);
|
|
385
|
+
border: 2px solid rgba(255,255,255,0.3);
|
|
386
|
+
color: white;
|
|
387
|
+
padding: 12px 24px;
|
|
388
|
+
border-radius: 8px;
|
|
389
|
+
font-size: 16px;
|
|
390
|
+
font-weight: 600;
|
|
391
|
+
cursor: pointer;
|
|
392
|
+
transition: all 0.3s;
|
|
393
|
+
backdrop-filter: blur(10px);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.cta-button:hover {
|
|
397
|
+
background: rgba(255,255,255,0.3);
|
|
398
|
+
border-color: rgba(255,255,255,0.5);
|
|
399
|
+
transform: translateY(-2px);
|
|
400
|
+
}
|
|
401
|
+
`}
|
|
402
|
+
</Style>
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Animation Styles
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
import { Style } from '@acusti/styling';
|
|
411
|
+
|
|
412
|
+
function AnimatedModal({ isOpen, onClose, children }) {
|
|
413
|
+
return (
|
|
414
|
+
<>
|
|
415
|
+
<Style href="modal-animations">
|
|
416
|
+
{`
|
|
417
|
+
@keyframes fadeIn {
|
|
418
|
+
from { opacity: 0; }
|
|
419
|
+
to { opacity: 1; }
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
@keyframes slideUp {
|
|
423
|
+
from {
|
|
424
|
+
opacity: 0;
|
|
425
|
+
transform: translateY(20px);
|
|
426
|
+
}
|
|
427
|
+
to {
|
|
428
|
+
opacity: 1;
|
|
429
|
+
transform: translateY(0);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
.modal-overlay {
|
|
434
|
+
position: fixed;
|
|
435
|
+
top: 0;
|
|
436
|
+
left: 0;
|
|
437
|
+
right: 0;
|
|
438
|
+
bottom: 0;
|
|
439
|
+
background: rgba(0,0,0,0.5);
|
|
440
|
+
display: flex;
|
|
441
|
+
align-items: center;
|
|
442
|
+
justify-content: center;
|
|
443
|
+
animation: fadeIn 0.2s ease-out;
|
|
444
|
+
z-index: 1000;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.modal-content {
|
|
448
|
+
background: white;
|
|
449
|
+
border-radius: 8px;
|
|
450
|
+
padding: 24px;
|
|
451
|
+
max-width: 500px;
|
|
452
|
+
width: 90%;
|
|
453
|
+
max-height: 80vh;
|
|
454
|
+
overflow: auto;
|
|
455
|
+
animation: slideUp 0.3s ease-out;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.modal-close {
|
|
459
|
+
position: absolute;
|
|
460
|
+
top: 16px;
|
|
461
|
+
right: 16px;
|
|
462
|
+
background: none;
|
|
463
|
+
border: none;
|
|
464
|
+
font-size: 24px;
|
|
465
|
+
cursor: pointer;
|
|
466
|
+
color: #666;
|
|
467
|
+
}
|
|
468
|
+
`}
|
|
469
|
+
</Style>
|
|
470
|
+
|
|
471
|
+
{isOpen && (
|
|
472
|
+
<div className="modal-overlay" onClick={onClose}>
|
|
473
|
+
<div
|
|
474
|
+
className="modal-content"
|
|
475
|
+
onClick={(e) => e.stopPropagation()}
|
|
476
|
+
>
|
|
477
|
+
<button className="modal-close" onClick={onClose}>
|
|
478
|
+
×
|
|
479
|
+
</button>
|
|
480
|
+
{children}
|
|
481
|
+
</div>
|
|
482
|
+
</div>
|
|
483
|
+
)}
|
|
484
|
+
</>
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Performance Considerations
|
|
490
|
+
|
|
491
|
+
### Style Caching
|
|
492
|
+
|
|
493
|
+
The component automatically caches minified styles to avoid recomputation:
|
|
494
|
+
|
|
495
|
+
```tsx
|
|
496
|
+
// These will use the same cached minified styles
|
|
497
|
+
function Button1() {
|
|
498
|
+
return <Style>{buttonStyles}</Style>;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
function Button2() {
|
|
502
|
+
return <Style>{buttonStyles}</Style>; // Reuses cache
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Custom href for Better Caching
|
|
507
|
+
|
|
508
|
+
Use custom `href` values for better caching control:
|
|
509
|
+
|
|
510
|
+
```tsx
|
|
511
|
+
// Good: Uses custom href for consistent caching
|
|
512
|
+
<Style href="button-primary">
|
|
513
|
+
{generateButtonStyles('primary')}
|
|
514
|
+
</Style>
|
|
515
|
+
|
|
516
|
+
// Less optimal: href changes with dynamic content
|
|
517
|
+
<Style>
|
|
518
|
+
{generateButtonStyles(dynamicTheme)}
|
|
519
|
+
</Style>
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Precedence for DOM Order
|
|
523
|
+
|
|
524
|
+
Control CSS parsing priority with precedence:
|
|
525
|
+
|
|
526
|
+
```tsx
|
|
527
|
+
// Critical styles load first
|
|
528
|
+
<Style precedence="high" href="critical">
|
|
529
|
+
{criticalStyles}
|
|
530
|
+
</Style>
|
|
531
|
+
|
|
532
|
+
// Component styles load normally
|
|
533
|
+
<Style precedence="medium" href="components">
|
|
534
|
+
{componentStyles}
|
|
535
|
+
</Style>
|
|
536
|
+
|
|
537
|
+
// Non-critical styles load last
|
|
538
|
+
<Style precedence="low" href="animations">
|
|
539
|
+
{animationStyles}
|
|
540
|
+
</Style>
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
## CSS Minification
|
|
544
|
+
|
|
545
|
+
The package includes a powerful CSS minifier that:
|
|
546
|
+
|
|
547
|
+
- Removes comments (except `/*!` important comments)
|
|
548
|
+
- Normalizes whitespace
|
|
549
|
+
- Removes unnecessary semicolons
|
|
550
|
+
- Optimizes values (e.g., `0px` → `0`, `#ffffff` → `#fff`)
|
|
551
|
+
- Preserves `calc()` expressions
|
|
552
|
+
- Handles string literals safely
|
|
553
|
+
|
|
554
|
+
```tsx
|
|
555
|
+
import { minifyStyles } from '@acusti/styling';
|
|
556
|
+
|
|
557
|
+
const original = `
|
|
558
|
+
/* Comment */
|
|
559
|
+
.button {
|
|
560
|
+
background-color: #ffffff;
|
|
561
|
+
padding: 10px 20px;
|
|
562
|
+
border: 1px solid #cccccc;
|
|
563
|
+
margin: 0px 0px 0px 0px;
|
|
564
|
+
}
|
|
565
|
+
`;
|
|
566
|
+
|
|
567
|
+
const minified = minifyStyles(original);
|
|
568
|
+
// ".button{background-color:#fff;padding:10px 20px;border:1px solid #ccc;margin:0}"
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Best Practices
|
|
572
|
+
|
|
573
|
+
### Component-Level Styles
|
|
574
|
+
|
|
575
|
+
Keep styles close to their components:
|
|
576
|
+
|
|
577
|
+
```tsx
|
|
578
|
+
// ✅ Good: Styles are colocated with component
|
|
579
|
+
function Newsletter() {
|
|
580
|
+
return (
|
|
581
|
+
<>
|
|
582
|
+
<Style href="newsletter">{newsletterStyles}</Style>
|
|
583
|
+
<div className="newsletter">...</div>
|
|
584
|
+
</>
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### Global vs Component Styles
|
|
590
|
+
|
|
591
|
+
Use precedence to control loading order:
|
|
592
|
+
|
|
593
|
+
```tsx
|
|
594
|
+
// ✅ Global styles with low precedence
|
|
595
|
+
function GlobalStyles() {
|
|
596
|
+
return (
|
|
597
|
+
<Style precedence="low" href="global">
|
|
598
|
+
{globalStyles}
|
|
599
|
+
</Style>
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// ✅ Critical component styles with high precedence
|
|
604
|
+
function Hero() {
|
|
605
|
+
return (
|
|
606
|
+
<Style precedence="high" href="hero">
|
|
607
|
+
{heroStyles}
|
|
608
|
+
</Style>
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### Custom Properties for Theming
|
|
614
|
+
|
|
615
|
+
Use CSS custom properties for dynamic theming:
|
|
616
|
+
|
|
617
|
+
```tsx
|
|
618
|
+
<Style href="theme">
|
|
619
|
+
{`
|
|
620
|
+
:root {
|
|
621
|
+
--primary-color: ${theme.primary};
|
|
622
|
+
--secondary-color: ${theme.secondary};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.button {
|
|
626
|
+
background: var(--primary-color);
|
|
627
|
+
}
|
|
628
|
+
`}
|
|
629
|
+
</Style>
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
## Common Use Cases
|
|
22
633
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
634
|
+
- **Component libraries** - Style components without external CSS files
|
|
635
|
+
- **Dynamic themes** - Generate styles based on user preferences
|
|
636
|
+
- **SSR applications** - Avoid hydration issues with server-rendered styles
|
|
637
|
+
- **Critical CSS** - Inline above-the-fold styles for faster rendering
|
|
638
|
+
- **CSS-in-JS alternative** - Use regular CSS with React 19+ benefits
|
|
639
|
+
- **Animation libraries** - Define keyframes and animations inline
|
|
640
|
+
- **Responsive components** - Include media queries with components
|
|
27
641
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
642
|
+
This package provides a modern, efficient way to handle CSS in React 19+
|
|
643
|
+
applications while maintaining the familiarity and power of traditional
|
|
644
|
+
CSS.
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { c } from "react/compiler-runtime";
|
|
3
|
-
import { useState, useEffect } from "react";
|
|
3
|
+
import { useState, useEffectEvent, useEffect } from "react";
|
|
4
4
|
function minifyStyles(css) {
|
|
5
5
|
const preservedTokens = [];
|
|
6
6
|
const comments = [];
|
|
@@ -78,7 +78,7 @@ const EMPTY_STYLES_ITEM = {
|
|
|
78
78
|
styles: ""
|
|
79
79
|
};
|
|
80
80
|
function useStyles(styles, initialHref) {
|
|
81
|
-
const $ = c(
|
|
81
|
+
const $ = c(13);
|
|
82
82
|
let t0;
|
|
83
83
|
if ($[0] !== initialHref || $[1] !== styles) {
|
|
84
84
|
t0 = () => {
|
|
@@ -108,23 +108,34 @@ function useStyles(styles, initialHref) {
|
|
|
108
108
|
}
|
|
109
109
|
const [stylesItem, setStylesItem] = useState(t0);
|
|
110
110
|
let t1;
|
|
111
|
-
let t2;
|
|
112
111
|
if ($[3] !== initialHref || $[4] !== styles) {
|
|
113
|
-
t1 = () => {
|
|
114
|
-
if (
|
|
112
|
+
t1 = (key_0) => {
|
|
113
|
+
if (styleCache.get(key_0)) {
|
|
115
114
|
return;
|
|
116
115
|
}
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
116
|
+
const minified_0 = minifyStyles(styles);
|
|
117
|
+
const item_0 = {
|
|
118
|
+
href: sanitizeHref(initialHref ?? minified_0),
|
|
119
|
+
referenceCount: 1,
|
|
120
|
+
styles: minified_0
|
|
121
|
+
};
|
|
122
|
+
styleCache.set(key_0, item_0);
|
|
123
|
+
setStylesItem(item_0);
|
|
124
|
+
};
|
|
125
|
+
$[3] = initialHref;
|
|
126
|
+
$[4] = styles;
|
|
127
|
+
$[5] = t1;
|
|
128
|
+
} else {
|
|
129
|
+
t1 = $[5];
|
|
130
|
+
}
|
|
131
|
+
const handleKeyUpdate = useEffectEvent(t1);
|
|
132
|
+
let t2;
|
|
133
|
+
if ($[6] !== handleKeyUpdate || $[7] !== initialHref || $[8] !== styles) {
|
|
134
|
+
t2 = () => {
|
|
135
|
+
if (!styles) {
|
|
136
|
+
return;
|
|
127
137
|
}
|
|
138
|
+
handleKeyUpdate(initialHref ?? styles);
|
|
128
139
|
return () => {
|
|
129
140
|
const existingItem = styleCache.get(styles);
|
|
130
141
|
if (existingItem) {
|
|
@@ -135,16 +146,23 @@ function useStyles(styles, initialHref) {
|
|
|
135
146
|
}
|
|
136
147
|
};
|
|
137
148
|
};
|
|
138
|
-
|
|
139
|
-
$[
|
|
140
|
-
$[
|
|
141
|
-
$[
|
|
142
|
-
$[6] = t2;
|
|
149
|
+
$[6] = handleKeyUpdate;
|
|
150
|
+
$[7] = initialHref;
|
|
151
|
+
$[8] = styles;
|
|
152
|
+
$[9] = t2;
|
|
143
153
|
} else {
|
|
144
|
-
|
|
145
|
-
|
|
154
|
+
t2 = $[9];
|
|
155
|
+
}
|
|
156
|
+
let t3;
|
|
157
|
+
if ($[10] !== initialHref || $[11] !== styles) {
|
|
158
|
+
t3 = [initialHref, styles];
|
|
159
|
+
$[10] = initialHref;
|
|
160
|
+
$[11] = styles;
|
|
161
|
+
$[12] = t3;
|
|
162
|
+
} else {
|
|
163
|
+
t3 = $[12];
|
|
146
164
|
}
|
|
147
|
-
useEffect(
|
|
165
|
+
useEffect(t2, t3);
|
|
148
166
|
return stylesItem;
|
|
149
167
|
}
|
|
150
168
|
function sanitizeHref(text) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/minifyStyles.ts","../src/useStyles.ts","../src/Style.tsx","../src/index.ts"],"sourcesContent":["/**\n * Adapted from:\n * https://github.com/jbleuzen/node-cssmin/blob/master/cssmin.js\n * node-cssmin\n * A simple module for Node.js that minify CSS\n * Author : Johan Bleuzen\n */\n\n/**\n * cssmin.js\n * Author: Stoyan Stefanov - http://phpied.com/\n * This is a JavaScript port of the CSS minification tool\n * distributed with YUICompressor, itself a port\n * of the cssmin utility by Isaac Schlueter - http://foohack.com/\n * Permission is hereby granted to use the JavaScript version under the same\n * conditions as the YUICompressor (original YUICompressor note below).\n */\n\n/*\n * YUI Compressor\n * http://developer.yahoo.com/yui/compressor/\n * Author: Julien Lecomte - http://www.julienlecomte.net/\n * Copyright (c) 2011 Yahoo! Inc. All rights reserved.\n * The copyrights embodied in the content of this file are licensed\n * by Yahoo! Inc. under the BSD (revised) open source license.\n */\n\nexport function minifyStyles(css: string) {\n const preservedTokens: Array<string> = [];\n const comments: Array<string> = [];\n const totalLength = css.length;\n let endIndex = 0,\n placeholder = '',\n startIndex = 0,\n token = '';\n\n // collect all comment blocks...\n while ((startIndex = css.indexOf('/*', startIndex)) >= 0) {\n endIndex = css.indexOf('*/', startIndex + 2);\n if (endIndex < 0) {\n endIndex = totalLength;\n }\n token = css.slice(startIndex + 2, endIndex);\n comments.push(token);\n css =\n css.slice(0, startIndex + 2) +\n '___PRESERVE_CANDIDATE_COMMENT_' +\n (comments.length - 1) +\n '___' +\n css.slice(endIndex);\n startIndex += 2;\n }\n\n // preserve strings so their content doesn't get accidentally minified\n css = css.replace(/(\"([^\\\\\"]|\\\\.|\\\\)*\")|('([^\\\\']|\\\\.|\\\\)*')/g, function (match) {\n const quote = match.substring(0, 1);\n\n match = match.slice(1, -1);\n\n // maybe the string contains a comment-like substring?\n // one, maybe more? put'em back then\n if (match.indexOf('___PRESERVE_CANDIDATE_COMMENT_') >= 0) {\n for (let i = 0, max = comments.length; i < max; i++) {\n match = match.replace(\n '___PRESERVE_CANDIDATE_COMMENT_' + i + '___',\n comments[i],\n );\n }\n }\n\n preservedTokens.push(match);\n return (\n quote + '___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___' + quote\n );\n });\n\n // strings are safe, now wrestle the comments\n for (let i = 0, max = comments.length; i < max; i = i + 1) {\n token = comments[i];\n placeholder = '___PRESERVE_CANDIDATE_COMMENT_' + i + '___';\n\n // ! in the first position of the comment means preserve\n // so push to the preserved tokens keeping the !\n if (token.charAt(0) === '!') {\n preservedTokens.push(token);\n css = css.replace(\n placeholder,\n '___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___',\n );\n continue;\n }\n\n // otherwise, kill the comment\n css = css.replace('/*' + placeholder + '*/', '');\n }\n\n // Normalize all whitespace strings to single spaces. Easier to work with that way.\n css = css.replace(/\\s+/g, ' ');\n\n // Remove the spaces before the things that should not have spaces before them.\n // But, be careful not to turn \"p :link {...}\" into \"p:link{...}\"\n // Swap out any pseudo-class colons with the token, and then swap back.\n css = css.replace(/(^|\\})(([^{:])+:)+([^{]*\\{)/g, function (m) {\n return m.replace(/:/g, '___PSEUDOCLASSCOLON___');\n });\n\n // Preserve spaces in calc expressions\n css = css.replace(/calc\\s*\\(\\s*(.*?)\\s*\\)/g, function (m, c: string) {\n return m.replace(c, c.replace(/\\s+/g, '___SPACE_IN_CALC___'));\n });\n\n css = css.replace(/\\s+([!{};:>+()\\],])/g, '$1');\n css = css.replace(/___PSEUDOCLASSCOLON___/g, ':');\n\n // no space after the end of a preserved comment\n css = css.replace(/\\*\\/ /g, '*/');\n\n // If there is a @charset, then only allow one, and push to the top of the file.\n css = css.replace(/^(.*)(@charset \"[^\"]*\";)/gi, '$2$1');\n css = css.replace(/^(\\s*@charset [^;]+;\\s*)+/gi, '$1');\n\n // Put the space back in some cases, to support stuff like\n // @media screen and (-webkit-min-device-pixel-ratio:0){\n css = css.replace(/\\band\\(/gi, 'and (');\n\n // Remove the spaces after the things that should not have spaces after them.\n css = css.replace(/([!{}:;>+([,])\\s+/g, '$1');\n\n // Restore preserved spaces in calc expressions\n css = css.replace(/___SPACE_IN_CALC___/g, ' ');\n\n // remove unnecessary semicolons\n css = css.replace(/;+\\}/g, '}');\n\n // Replace 0(px,em,%) with 0.\n css = css.replace(/([\\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, '$1$2');\n\n // Replace 0 0 0 0; with 0.\n css = css.replace(/:0 0 0 0(;|\\})/g, ':0$1');\n css = css.replace(/:0 0 0(;|\\})/g, ':0$1');\n css = css.replace(/:0 0(;|\\})/g, ':0$1');\n\n // Replace background-position:0; with background-position:0 0;\n // same for transform-origin\n css = css.replace(\n /(background-position|transform-origin):0(;|\\})/gi,\n function (_all, prop: string, tail: string) {\n return prop.toLowerCase() + ':0 0' + tail;\n },\n );\n\n // Replace 0.6 to .6, but only when preceded by : or a white-space\n css = css.replace(/(:|\\s)0+\\.(\\d+)/g, '$1.$2');\n\n // border: none -> border:0\n css = css.replace(\n /(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\\})/gi,\n function (_all, prop: string, tail: string) {\n return prop.toLowerCase() + ':0' + tail;\n },\n );\n\n // Remove empty rules.\n css = css.replace(/[^};{/]+\\{\\}/g, '');\n\n // Replace multiple semi-colons in a row by a single one\n // See SF bug #1980989\n css = css.replace(/;;+/g, ';');\n\n // restore preserved comments and strings\n for (let i = 0, max = preservedTokens.length; i < max; i = i + 1) {\n css = css.replace('___PRESERVED_TOKEN_' + i + '___', preservedTokens[i]);\n }\n\n return css.trim();\n}\n","import { useEffect, useState } from 'react';\n\nimport { minifyStyles } from './minifyStyles.js';\n\ntype StyleCache = Map<string, { href: string; referenceCount: number; styles: string }>;\n\nconst styleCache: StyleCache = new Map();\n\nconst EMPTY_STYLES_ITEM = { href: '', referenceCount: 0, styles: '' };\n\nexport function useStyles(styles: string, initialHref?: string) {\n const [stylesItem, setStylesItem] = useState(() => {\n if (!styles) return EMPTY_STYLES_ITEM;\n\n const key = initialHref ?? styles;\n let item = styleCache.get(key);\n\n if (item) {\n item.referenceCount++;\n } else {\n const minified = minifyStyles(styles);\n item = {\n href: sanitizeHref(initialHref ?? minified),\n referenceCount: 1,\n styles: minified,\n };\n styleCache.set(key, item);\n }\n\n return item;\n });\n\n useEffect(() => {\n if (!styles) return;\n\n const key = initialHref ?? styles;\n\n if (!styleCache.get(key)) {\n const minified = minifyStyles(styles);\n const item = {\n href: sanitizeHref(initialHref ?? minified),\n referenceCount: 1,\n styles: minified,\n };\n styleCache.set(key, item);\n setStylesItem(item);\n }\n\n return () => {\n const existingItem = styleCache.get(styles);\n if (existingItem) {\n existingItem.referenceCount--;\n if (!existingItem.referenceCount) {\n // TODO try scheduling this via setTimeout\n // and add another referenceCount check\n // to deal with instance where existing <Style>\n // component is moved in the tree or re-keyed\n styleCache.delete(styles);\n }\n }\n };\n }, [initialHref, styles]);\n\n return stylesItem;\n}\n\nexport default useStyles;\n\n// Dashes in selectors in href prop create happy-dom / jsdom test errors:\n// Invalid regular expression (“Range out of order in character class”)\n// Spaces create react errors: React expected the `href` prop for a <style> tag\n// opting into hoisting semantics using the `precedence` prop to not have any\n// spaces but ecountered spaces instead. using spaces in this prop will cause\n// hydration of this style to fail on the client.\nfunction sanitizeHref(text: string) {\n return text.replace(/[- ]/g, '');\n}\n\n// The following export is for test usage only\nexport const getStyleCache = () => styleCache;\n","import { useStyles } from './useStyles.js';\n\ntype Props = {\n children: string;\n href?: string;\n precedence?: string;\n};\n\nconst Style = ({ children, href: _href, precedence = 'medium' }: Props) => {\n // Minify CSS styles to prevent unnecessary cache misses\n const { href, styles } = useStyles(children, _href);\n\n return (\n <style href={href} precedence={precedence}>\n {styles}\n </style>\n );\n};\n\nexport default Style;\n","export { minifyStyles } from './minifyStyles.js';\nexport { default as Style } from './Style.js';\n\nexport const SYSTEM_UI_FONT =\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif';\n"],"names":["minifyStyles","css","preservedTokens","comments","totalLength","length","endIndex","placeholder","startIndex","token","indexOf","slice","push","replace","match","quote","substring","i","max","charAt","m","c","_all","prop","tail","toLowerCase","trim","styleCache","Map","EMPTY_STYLES_ITEM","href","referenceCount","styles","useStyles","initialHref","$","_c","t0","key","item","get","minified","set","stylesItem","setStylesItem","useState","t1","t2","key_0","minified_0","item_0","sanitizeHref","existingItem","delete","useEffect","text","Style","children","_href","precedence","undefined","SYSTEM_UI_FONT"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/minifyStyles.ts","../src/useStyles.ts","../src/Style.tsx","../src/index.ts"],"sourcesContent":["/**\n * Adapted from:\n * https://github.com/jbleuzen/node-cssmin/blob/master/cssmin.js\n * node-cssmin\n * A simple module for Node.js that minify CSS\n * Author : Johan Bleuzen\n */\n\n/**\n * cssmin.js\n * Author: Stoyan Stefanov - http://phpied.com/\n * This is a JavaScript port of the CSS minification tool\n * distributed with YUICompressor, itself a port\n * of the cssmin utility by Isaac Schlueter - http://foohack.com/\n * Permission is hereby granted to use the JavaScript version under the same\n * conditions as the YUICompressor (original YUICompressor note below).\n */\n\n/*\n * YUI Compressor\n * http://developer.yahoo.com/yui/compressor/\n * Author: Julien Lecomte - http://www.julienlecomte.net/\n * Copyright (c) 2011 Yahoo! Inc. All rights reserved.\n * The copyrights embodied in the content of this file are licensed\n * by Yahoo! Inc. under the BSD (revised) open source license.\n */\n\nexport function minifyStyles(css: string) {\n const preservedTokens: Array<string> = [];\n const comments: Array<string> = [];\n const totalLength = css.length;\n let endIndex = 0,\n placeholder = '',\n startIndex = 0,\n token = '';\n\n // collect all comment blocks...\n while ((startIndex = css.indexOf('/*', startIndex)) >= 0) {\n endIndex = css.indexOf('*/', startIndex + 2);\n if (endIndex < 0) {\n endIndex = totalLength;\n }\n token = css.slice(startIndex + 2, endIndex);\n comments.push(token);\n css =\n css.slice(0, startIndex + 2) +\n '___PRESERVE_CANDIDATE_COMMENT_' +\n (comments.length - 1) +\n '___' +\n css.slice(endIndex);\n startIndex += 2;\n }\n\n // preserve strings so their content doesn't get accidentally minified\n css = css.replace(/(\"([^\\\\\"]|\\\\.|\\\\)*\")|('([^\\\\']|\\\\.|\\\\)*')/g, function (match) {\n const quote = match.substring(0, 1);\n\n match = match.slice(1, -1);\n\n // maybe the string contains a comment-like substring?\n // one, maybe more? put'em back then\n if (match.indexOf('___PRESERVE_CANDIDATE_COMMENT_') >= 0) {\n for (let i = 0, max = comments.length; i < max; i++) {\n match = match.replace(\n '___PRESERVE_CANDIDATE_COMMENT_' + i + '___',\n comments[i],\n );\n }\n }\n\n preservedTokens.push(match);\n return (\n quote + '___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___' + quote\n );\n });\n\n // strings are safe, now wrestle the comments\n for (let i = 0, max = comments.length; i < max; i = i + 1) {\n token = comments[i];\n placeholder = '___PRESERVE_CANDIDATE_COMMENT_' + i + '___';\n\n // ! in the first position of the comment means preserve\n // so push to the preserved tokens keeping the !\n if (token.charAt(0) === '!') {\n preservedTokens.push(token);\n css = css.replace(\n placeholder,\n '___PRESERVED_TOKEN_' + (preservedTokens.length - 1) + '___',\n );\n continue;\n }\n\n // otherwise, kill the comment\n css = css.replace('/*' + placeholder + '*/', '');\n }\n\n // Normalize all whitespace strings to single spaces. Easier to work with that way.\n css = css.replace(/\\s+/g, ' ');\n\n // Remove the spaces before the things that should not have spaces before them.\n // But, be careful not to turn \"p :link {...}\" into \"p:link{...}\"\n // Swap out any pseudo-class colons with the token, and then swap back.\n css = css.replace(/(^|\\})(([^{:])+:)+([^{]*\\{)/g, function (m) {\n return m.replace(/:/g, '___PSEUDOCLASSCOLON___');\n });\n\n // Preserve spaces in calc expressions\n css = css.replace(/calc\\s*\\(\\s*(.*?)\\s*\\)/g, function (m, c: string) {\n return m.replace(c, c.replace(/\\s+/g, '___SPACE_IN_CALC___'));\n });\n\n css = css.replace(/\\s+([!{};:>+()\\],])/g, '$1');\n css = css.replace(/___PSEUDOCLASSCOLON___/g, ':');\n\n // no space after the end of a preserved comment\n css = css.replace(/\\*\\/ /g, '*/');\n\n // If there is a @charset, then only allow one, and push to the top of the file.\n css = css.replace(/^(.*)(@charset \"[^\"]*\";)/gi, '$2$1');\n css = css.replace(/^(\\s*@charset [^;]+;\\s*)+/gi, '$1');\n\n // Put the space back in some cases, to support stuff like\n // @media screen and (-webkit-min-device-pixel-ratio:0){\n css = css.replace(/\\band\\(/gi, 'and (');\n\n // Remove the spaces after the things that should not have spaces after them.\n css = css.replace(/([!{}:;>+([,])\\s+/g, '$1');\n\n // Restore preserved spaces in calc expressions\n css = css.replace(/___SPACE_IN_CALC___/g, ' ');\n\n // remove unnecessary semicolons\n css = css.replace(/;+\\}/g, '}');\n\n // Replace 0(px,em,%) with 0.\n css = css.replace(/([\\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, '$1$2');\n\n // Replace 0 0 0 0; with 0.\n css = css.replace(/:0 0 0 0(;|\\})/g, ':0$1');\n css = css.replace(/:0 0 0(;|\\})/g, ':0$1');\n css = css.replace(/:0 0(;|\\})/g, ':0$1');\n\n // Replace background-position:0; with background-position:0 0;\n // same for transform-origin\n css = css.replace(\n /(background-position|transform-origin):0(;|\\})/gi,\n function (_all, prop: string, tail: string) {\n return prop.toLowerCase() + ':0 0' + tail;\n },\n );\n\n // Replace 0.6 to .6, but only when preceded by : or a white-space\n css = css.replace(/(:|\\s)0+\\.(\\d+)/g, '$1.$2');\n\n // border: none -> border:0\n css = css.replace(\n /(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\\})/gi,\n function (_all, prop: string, tail: string) {\n return prop.toLowerCase() + ':0' + tail;\n },\n );\n\n // Remove empty rules.\n css = css.replace(/[^};{/]+\\{\\}/g, '');\n\n // Replace multiple semi-colons in a row by a single one\n // See SF bug #1980989\n css = css.replace(/;;+/g, ';');\n\n // restore preserved comments and strings\n for (let i = 0, max = preservedTokens.length; i < max; i = i + 1) {\n css = css.replace('___PRESERVED_TOKEN_' + i + '___', preservedTokens[i]);\n }\n\n return css.trim();\n}\n","import { useEffect, useEffectEvent, useState } from 'react';\n\nimport { minifyStyles } from './minifyStyles.js';\n\ntype StyleCache = Map<string, { href: string; referenceCount: number; styles: string }>;\n\nconst styleCache: StyleCache = new Map();\n\nconst EMPTY_STYLES_ITEM = { href: '', referenceCount: 0, styles: '' };\n\nexport function useStyles(styles: string, initialHref?: string) {\n const [stylesItem, setStylesItem] = useState(() => {\n if (!styles) return EMPTY_STYLES_ITEM;\n\n const key = initialHref ?? styles;\n let item = styleCache.get(key);\n\n if (item) {\n item.referenceCount++;\n } else {\n const minified = minifyStyles(styles);\n item = {\n href: sanitizeHref(initialHref ?? minified),\n referenceCount: 1,\n styles: minified,\n };\n styleCache.set(key, item);\n }\n\n return item;\n });\n\n const handleKeyUpdate = useEffectEvent((key: string) => {\n if (styleCache.get(key)) return;\n const minified = minifyStyles(styles);\n const item = {\n href: sanitizeHref(initialHref ?? minified),\n referenceCount: 1,\n styles: minified,\n };\n styleCache.set(key, item);\n setStylesItem(item);\n });\n\n useEffect(() => {\n if (!styles) return;\n\n handleKeyUpdate(initialHref ?? styles);\n return () => {\n const existingItem = styleCache.get(styles);\n if (existingItem) {\n existingItem.referenceCount--;\n if (!existingItem.referenceCount) {\n // TODO try scheduling this via setTimeout\n // and add another referenceCount check\n // to deal with instance where existing <Style>\n // component is moved in the tree or re-keyed\n styleCache.delete(styles);\n }\n }\n };\n }, [initialHref, styles]);\n\n return stylesItem;\n}\n\nexport default useStyles;\n\n// Dashes in selectors in href prop create happy-dom / jsdom test errors:\n// Invalid regular expression (“Range out of order in character class”)\n// Spaces create react errors: React expected the `href` prop for a <style> tag\n// opting into hoisting semantics using the `precedence` prop to not have any\n// spaces but ecountered spaces instead. using spaces in this prop will cause\n// hydration of this style to fail on the client.\nfunction sanitizeHref(text: string) {\n return text.replace(/[- ]/g, '');\n}\n\n// The following export is for test usage only\nexport const getStyleCache = () => styleCache;\n","import { useStyles } from './useStyles.js';\n\ntype Props = {\n children: string;\n href?: string;\n precedence?: string;\n};\n\nconst Style = ({ children, href: _href, precedence = 'medium' }: Props) => {\n // Minify CSS styles to prevent unnecessary cache misses\n const { href, styles } = useStyles(children, _href);\n\n return (\n <style href={href} precedence={precedence}>\n {styles}\n </style>\n );\n};\n\nexport default Style;\n","export { minifyStyles } from './minifyStyles.js';\nexport { default as Style } from './Style.js';\n\nexport const SYSTEM_UI_FONT =\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen-Sans, Ubuntu, Cantarell, \"Helvetica Neue\", sans-serif';\n"],"names":["minifyStyles","css","preservedTokens","comments","totalLength","length","endIndex","placeholder","startIndex","token","indexOf","slice","push","replace","match","quote","substring","i","max","charAt","m","c","_all","prop","tail","toLowerCase","trim","styleCache","Map","EMPTY_STYLES_ITEM","href","referenceCount","styles","useStyles","initialHref","$","_c","t0","key","item","get","minified","sanitizeHref","set","stylesItem","setStylesItem","useState","t1","key_0","minified_0","item_0","handleKeyUpdate","useEffectEvent","t2","existingItem","delete","t3","useEffect","text","Style","children","_href","precedence","undefined","SYSTEM_UI_FONT"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acusti/styling",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"exports": "./dist/index.js",
|
|
@@ -36,19 +36,19 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://github.com/acusti/uikit/tree/main/packages/styling#readme",
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@testing-library/dom": "^10.4.
|
|
40
|
-
"@testing-library/react": "^16.3.
|
|
39
|
+
"@testing-library/dom": "^10.4.1",
|
|
40
|
+
"@testing-library/react": "^16.3.2",
|
|
41
41
|
"@testing-library/user-event": "^14.6.1",
|
|
42
|
-
"@types/react": "^19.
|
|
43
|
-
"@vitejs/plugin-react": "^
|
|
44
|
-
"babel-plugin-react-compiler": "
|
|
45
|
-
"happy-dom": "^
|
|
42
|
+
"@types/react": "^19.2.10",
|
|
43
|
+
"@vitejs/plugin-react": "^5.0.4",
|
|
44
|
+
"babel-plugin-react-compiler": "^1",
|
|
45
|
+
"happy-dom": "^20.4.0",
|
|
46
46
|
"react": "^19",
|
|
47
47
|
"react-dom": "^19",
|
|
48
|
-
"typescript": "5.
|
|
49
|
-
"unplugin-dts": "^1.0.0-beta.
|
|
50
|
-
"vite": "^
|
|
51
|
-
"vitest": "^3.
|
|
48
|
+
"typescript": "5.9.2",
|
|
49
|
+
"unplugin-dts": "^1.0.0-beta.6",
|
|
50
|
+
"vite": "^7.1.10",
|
|
51
|
+
"vitest": "^3.2.4"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"react": "^19 || ~0.0.0-experimental < 0.0.0-f",
|