@bookklik/senangstart-css 0.2.7 → 0.2.9
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/dist/senangstart-css.js +9052 -2142
- package/dist/senangstart-css.min.js +1207 -119
- package/dist/senangstart-tw.js +170 -73
- package/dist/senangstart-tw.min.js +1 -1
- package/docs/guide/configuration.md +2 -2
- package/docs/guide/states.md +60 -0
- package/docs/ms/guide/configuration.md +2 -2
- package/docs/ms/guide/states.md +60 -0
- package/docs/ms/reference/colors.md +2 -2
- package/docs/ms/reference/space/height.md +10 -10
- package/docs/ms/reference/space/width.md +12 -12
- package/docs/public/assets/senangstart-css.min.js +1207 -119
- package/docs/public/llms.txt +28 -0
- package/docs/reference/colors.md +2 -2
- package/docs/reference/space/height.md +10 -10
- package/docs/reference/space/width.md +12 -12
- package/package.json +1 -1
- package/public/senangstart.css +1196 -0
- package/scripts/convert-tailwind.js +191 -68
- package/scripts/generate-llms-txt.js +28 -0
- package/src/cdn/senangstart-engine.js +36 -2268
- package/src/cdn/tw-conversion-engine.js +203 -74
- package/src/compiler/generators/css.js +309 -249
- package/src/compiler/parser.js +14 -4
- package/src/compiler/tokenizer.js +0 -1
- package/src/config/defaults.js +1 -1
- package/src/core/constants.js +5 -3
- package/src/core/tokenizer-core.js +3 -58
- package/src/definitions/index.js +3 -2
- package/src/definitions/layout.js +6 -2
- package/src/definitions/space.js +45 -19
- package/src/index.js +47 -0
- package/src/utils/common.js +27 -0
- package/templates/senangstart.config.js +1 -1
- package/tests/helpers/test-utils.js +1 -1
- package/tests/integration/compiler.test.js +12 -1
- package/tests/unit/compiler/generators/css.coverage.test.js +833 -0
- package/tests/unit/compiler/generators/css.test.js +1418 -1
- package/tests/unit/compiler/generators/preflight.test.js +31 -0
- package/tests/unit/compiler/parser.test.js +26 -0
- package/tests/unit/config/defaults.test.js +2 -2
- package/tests/unit/convert-tailwind.cli.test.js +95 -0
- package/tests/unit/convert-tailwind.coverage.test.js +225 -0
- package/tests/unit/convert-tailwind.test.js +49 -20
- package/tests/unit/core/tokenizer-core.test.js +102 -0
- package/tests/unit/definitions/index.test.js +108 -0
- package/tests/unit/definitions/layout_definitions.test.js +40 -0
- package/tests/unit/utils/common.test.js +26 -0
- package/scripts/bundle-jit.js +0 -45
|
@@ -4,22 +4,36 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { generatePreflight } from './preflight.js';
|
|
7
|
+
import { sanitizeValue } from '../../utils/common.js';
|
|
8
|
+
import { buildAllMaps } from '../../definitions/index.js';
|
|
9
|
+
|
|
10
|
+
// Initialize maps from definitions - Single Source of Truth
|
|
11
|
+
const { layoutMap, typographyKeywords } = buildAllMaps();
|
|
12
|
+
|
|
13
|
+
// Helper to sanitize arbitrary values using common utility
|
|
14
|
+
function sanitizeArbitraryValue(value) {
|
|
15
|
+
return sanitizeValue(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// CSS color keywords that should be passed through directly without var() wrapping
|
|
19
|
+
const CSS_COLOR_KEYWORDS = ['transparent', 'currentColor', 'inherit', 'initial', 'unset'];
|
|
7
20
|
|
|
8
21
|
/**
|
|
9
|
-
*
|
|
10
|
-
* @param {string} value -
|
|
11
|
-
* @
|
|
22
|
+
* Resolve a color value to CSS
|
|
23
|
+
* @param {string} value - The color value
|
|
24
|
+
* @param {boolean} isArbitrary - Whether the value is arbitrary (wrapped in [])
|
|
25
|
+
* @returns {string} - The resolved CSS color value
|
|
12
26
|
*/
|
|
13
|
-
function
|
|
14
|
-
if (
|
|
15
|
-
return
|
|
27
|
+
function resolveColorValue(value, isArbitrary) {
|
|
28
|
+
if (isArbitrary) {
|
|
29
|
+
return value;
|
|
16
30
|
}
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return value.replace(dangerousChars, '_');
|
|
31
|
+
// Check if it's a CSS keyword that should pass through directly
|
|
32
|
+
if (CSS_COLOR_KEYWORDS.includes(value)) {
|
|
33
|
+
return value;
|
|
21
34
|
}
|
|
22
|
-
|
|
35
|
+
// Otherwise wrap in CSS variable
|
|
36
|
+
return `var(--c-${value})`;
|
|
23
37
|
}
|
|
24
38
|
|
|
25
39
|
/**
|
|
@@ -88,8 +102,9 @@ export function generateCSSVariables(config) {
|
|
|
88
102
|
'60': '15rem', '64': '16rem', '72': '18rem', '80': '20rem', '96': '24rem'
|
|
89
103
|
};
|
|
90
104
|
for (const [key, value] of Object.entries(twSpacing)) {
|
|
91
|
-
css += ` --tw-${key}: ${value};\n`;
|
|
105
|
+
css += ` --tw-${key.replace(/\./g, '\\\\.')}: ${value};\n`;
|
|
92
106
|
}
|
|
107
|
+
|
|
93
108
|
|
|
94
109
|
// Tailwind Border Radius Scale
|
|
95
110
|
const twRadius = {
|
|
@@ -97,7 +112,7 @@ export function generateCSSVariables(config) {
|
|
|
97
112
|
'lg': '0.5rem', 'xl': '0.75rem', '2xl': '1rem', '3xl': '1.5rem', 'full': '9999px'
|
|
98
113
|
};
|
|
99
114
|
for (const [key, value] of Object.entries(twRadius)) {
|
|
100
|
-
css += ` --tw
|
|
115
|
+
css += ` --r-tw-${key}: ${value};\n`;
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
// Tailwind Shadow Scale
|
|
@@ -112,7 +127,7 @@ export function generateCSSVariables(config) {
|
|
|
112
127
|
'none': '0 0 #0000'
|
|
113
128
|
};
|
|
114
129
|
for (const [key, value] of Object.entries(twShadow)) {
|
|
115
|
-
css += ` --tw
|
|
130
|
+
css += ` --shadow-tw-${key}: ${value};\n`;
|
|
116
131
|
}
|
|
117
132
|
|
|
118
133
|
// Tailwind Font Size Scale
|
|
@@ -161,95 +176,8 @@ export function generateCSSVariables(config) {
|
|
|
161
176
|
function generateLayoutRule(token, config) {
|
|
162
177
|
const { property, value, isArbitrary } = token;
|
|
163
178
|
|
|
164
|
-
const layoutMap = {
|
|
165
|
-
// Display
|
|
166
|
-
'flex': 'display: flex;',
|
|
167
|
-
'grid': 'display: grid;',
|
|
168
|
-
'inline-flex': 'display: inline-flex;',
|
|
169
|
-
'inline-grid': 'display: inline-grid;',
|
|
170
|
-
'block': 'display: block;',
|
|
171
|
-
'inline': 'display: inline-block;',
|
|
172
|
-
'hidden': 'display: none;',
|
|
173
|
-
|
|
174
|
-
// Flex Direction
|
|
175
|
-
'row': 'flex-direction: row;',
|
|
176
|
-
'col': 'flex-direction: column;',
|
|
177
|
-
'row-reverse': 'flex-direction: row-reverse;',
|
|
178
|
-
'col-reverse': 'flex-direction: column-reverse;',
|
|
179
|
-
|
|
180
|
-
// Flex Wrap
|
|
181
|
-
'wrap': 'flex-wrap: wrap;',
|
|
182
|
-
'nowrap': 'flex-wrap: nowrap;',
|
|
183
|
-
'wrap-reverse': 'flex-wrap: wrap-reverse;',
|
|
184
|
-
|
|
185
|
-
// Flex Item
|
|
186
|
-
'grow': 'flex-grow: 1;',
|
|
187
|
-
'grow-0': 'flex-grow: 0;',
|
|
188
|
-
'shrink': 'flex-shrink: 1;',
|
|
189
|
-
'shrink-0': 'flex-shrink: 0;',
|
|
190
|
-
|
|
191
|
-
// Grid Auto Flow
|
|
192
|
-
'grid-flow-row': 'grid-auto-flow: row;',
|
|
193
|
-
'grid-flow-col': 'grid-auto-flow: column;',
|
|
194
|
-
'grid-flow-dense': 'grid-auto-flow: dense;',
|
|
195
|
-
'grid-flow-row-dense': 'grid-auto-flow: row dense;',
|
|
196
|
-
'grid-flow-col-dense': 'grid-auto-flow: column dense;',
|
|
197
|
-
|
|
198
|
-
// Shorthand Alignment (backwards compat - simple keywords)
|
|
199
|
-
'center': 'justify-content: center; align-items: center;',
|
|
200
|
-
'start': 'justify-content: flex-start; align-items: flex-start;',
|
|
201
|
-
'end': 'justify-content: flex-end; align-items: flex-end;',
|
|
202
|
-
'between': 'justify-content: space-between;',
|
|
203
|
-
'around': 'justify-content: space-around;',
|
|
204
|
-
'evenly': 'justify-content: space-evenly;',
|
|
205
|
-
|
|
206
|
-
// Position
|
|
207
|
-
'absolute': 'position: absolute;',
|
|
208
|
-
'relative': 'position: relative;',
|
|
209
|
-
'fixed': 'position: fixed;',
|
|
210
|
-
'sticky': 'position: sticky;',
|
|
211
|
-
'static': 'position: static;',
|
|
212
|
-
|
|
213
|
-
// Visibility
|
|
214
|
-
'visible': 'visibility: visible;',
|
|
215
|
-
'invisible': 'visibility: hidden;',
|
|
216
|
-
|
|
217
|
-
// Isolation
|
|
218
|
-
'isolate': 'isolation: isolate;',
|
|
219
|
-
'isolate-auto': 'isolation: auto;',
|
|
220
|
-
|
|
221
|
-
// Box Sizing
|
|
222
|
-
'box-border': 'box-sizing: border-box;',
|
|
223
|
-
'box-content': 'box-sizing: content-box;',
|
|
224
|
-
|
|
225
|
-
// Float
|
|
226
|
-
'float-left': 'float: left;',
|
|
227
|
-
'float-right': 'float: right;',
|
|
228
|
-
'float-none': 'float: none;',
|
|
229
|
-
|
|
230
|
-
// Clear
|
|
231
|
-
'clear-left': 'clear: left;',
|
|
232
|
-
'clear-right': 'clear: right;',
|
|
233
|
-
'clear-both': 'clear: both;',
|
|
234
|
-
'clear-none': 'clear: none;',
|
|
235
|
-
|
|
236
|
-
// Table - Border Collapse
|
|
237
|
-
'border-collapse': 'border-collapse: collapse;',
|
|
238
|
-
'border-separate': 'border-collapse: separate;',
|
|
239
|
-
|
|
240
|
-
// Table - Table Layout
|
|
241
|
-
'table-auto': 'table-layout: auto;',
|
|
242
|
-
'table-fixed': 'table-layout: fixed;',
|
|
243
|
-
|
|
244
|
-
// Table - Caption Side
|
|
245
|
-
'caption-top': 'caption-side: top;',
|
|
246
|
-
'caption-bottom': 'caption-side: bottom;',
|
|
247
|
-
|
|
248
|
-
// Container
|
|
249
|
-
'container': 'width: 100%; margin-left: auto; margin-right: auto;'
|
|
250
|
-
};
|
|
251
|
-
|
|
252
179
|
// Check for simple layout keywords first (property === value means it's a keyword like 'flex', 'grid', etc.)
|
|
180
|
+
// layoutMap is now imported from definitions
|
|
253
181
|
if (property === value && layoutMap[property]) {
|
|
254
182
|
return layoutMap[property];
|
|
255
183
|
}
|
|
@@ -381,27 +309,64 @@ function generateLayoutRule(token, config) {
|
|
|
381
309
|
return `object-position: ${cssValue};`;
|
|
382
310
|
}
|
|
383
311
|
|
|
312
|
+
// Percentage adjectives for positioning utilities
|
|
313
|
+
const positioningPercentages = {
|
|
314
|
+
'full': '100%',
|
|
315
|
+
'half': '50%',
|
|
316
|
+
'third': '33.333333%',
|
|
317
|
+
'third-2x': '66.666667%',
|
|
318
|
+
'quarter': '25%',
|
|
319
|
+
'quarter-2x': '50%',
|
|
320
|
+
'quarter-3x': '75%',
|
|
321
|
+
// Keep fractional values for backwards compatibility
|
|
322
|
+
'1/1': '100%',
|
|
323
|
+
'1/2': '50%',
|
|
324
|
+
'1/3': '33.333333%',
|
|
325
|
+
'2/3': '66.666667%',
|
|
326
|
+
'1/4': '25%',
|
|
327
|
+
'2/4': '50%',
|
|
328
|
+
'3/4': '75%'
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
// Helper function to resolve positioning value
|
|
332
|
+
const resolvePositioningValue = (val, arb) => {
|
|
333
|
+
if (arb) return val;
|
|
334
|
+
if (val === '0') return '0';
|
|
335
|
+
// Check for negative percentage adjective
|
|
336
|
+
if (val.startsWith('-')) {
|
|
337
|
+
const positiveVal = val.substring(1);
|
|
338
|
+
if (positioningPercentages[positiveVal]) {
|
|
339
|
+
return `-${positioningPercentages[positiveVal]}`;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// Check for percentage adjective
|
|
343
|
+
if (positioningPercentages[val]) {
|
|
344
|
+
return positioningPercentages[val];
|
|
345
|
+
}
|
|
346
|
+
return `var(--s-${val})`;
|
|
347
|
+
};
|
|
348
|
+
|
|
384
349
|
// Inset (all sides)
|
|
385
350
|
if (property === 'inset') {
|
|
386
|
-
const cssValue =
|
|
351
|
+
const cssValue = resolvePositioningValue(value, isArbitrary);
|
|
387
352
|
return `inset: ${cssValue};`;
|
|
388
353
|
}
|
|
389
354
|
|
|
390
355
|
// Individual positioning: top, right, bottom, left
|
|
391
356
|
if (['top', 'right', 'bottom', 'left'].includes(property)) {
|
|
392
|
-
const cssValue =
|
|
357
|
+
const cssValue = resolvePositioningValue(value, isArbitrary);
|
|
393
358
|
return `${property}: ${cssValue};`;
|
|
394
359
|
}
|
|
395
360
|
|
|
396
361
|
// Inset X (left + right)
|
|
397
362
|
if (property === 'inset-x') {
|
|
398
|
-
const cssValue =
|
|
363
|
+
const cssValue = resolvePositioningValue(value, isArbitrary);
|
|
399
364
|
return `left: ${cssValue}; right: ${cssValue};`;
|
|
400
365
|
}
|
|
401
366
|
|
|
402
367
|
// Inset Y (top + bottom)
|
|
403
368
|
if (property === 'inset-y') {
|
|
404
|
-
const cssValue =
|
|
369
|
+
const cssValue = resolvePositioningValue(value, isArbitrary);
|
|
405
370
|
return `top: ${cssValue}; bottom: ${cssValue};`;
|
|
406
371
|
}
|
|
407
372
|
|
|
@@ -586,6 +551,39 @@ function generateSpaceRule(token, config) {
|
|
|
586
551
|
return propMap[property] || '';
|
|
587
552
|
}
|
|
588
553
|
|
|
554
|
+
// Percentage adjectives for sizing utilities (human-readable alternatives to fractions)
|
|
555
|
+
const percentageAdjectives = {
|
|
556
|
+
'full': '100%',
|
|
557
|
+
'half': '50%',
|
|
558
|
+
'third': '33.333333%',
|
|
559
|
+
'third-2x': '66.666667%',
|
|
560
|
+
'quarter': '25%',
|
|
561
|
+
'quarter-2x': '50%',
|
|
562
|
+
'quarter-3x': '75%',
|
|
563
|
+
// Keep fractional values for backwards compatibility
|
|
564
|
+
'1/1': '100%',
|
|
565
|
+
'1/2': '50%',
|
|
566
|
+
'1/3': '33.333333%',
|
|
567
|
+
'2/3': '66.666667%',
|
|
568
|
+
'1/4': '25%',
|
|
569
|
+
'2/4': '50%',
|
|
570
|
+
'3/4': '75%'
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
// Check if this is a sizing utility with a percentage adjective
|
|
574
|
+
if (sizingProps.includes(property) && percentageAdjectives[value]) {
|
|
575
|
+
const cssVal = percentageAdjectives[value];
|
|
576
|
+
const propMap = {
|
|
577
|
+
'w': `width: ${cssVal};`,
|
|
578
|
+
'h': `height: ${cssVal};`,
|
|
579
|
+
'min-w': `min-width: ${cssVal};`,
|
|
580
|
+
'max-w': `max-width: ${cssVal};`,
|
|
581
|
+
'min-h': `min-height: ${cssVal};`,
|
|
582
|
+
'max-h': `max-height: ${cssVal};`
|
|
583
|
+
};
|
|
584
|
+
return propMap[property] || '';
|
|
585
|
+
}
|
|
586
|
+
|
|
589
587
|
// Determine the CSS value
|
|
590
588
|
let cssValue;
|
|
591
589
|
if (isArbitrary) {
|
|
@@ -598,7 +596,7 @@ function generateSpaceRule(token, config) {
|
|
|
598
596
|
let baseValue;
|
|
599
597
|
if (cleanValue.startsWith('tw-')) {
|
|
600
598
|
const twValue = cleanValue.slice(3); // Remove 'tw-' prefix
|
|
601
|
-
baseValue = `var(--tw-${twValue})`;
|
|
599
|
+
baseValue = `var(--tw-${twValue.replace(/\./g, '\\\\.')})`;
|
|
602
600
|
} else {
|
|
603
601
|
baseValue = `var(--s-${cleanValue})`;
|
|
604
602
|
}
|
|
@@ -667,100 +665,7 @@ function generateVisualRule(token, config) {
|
|
|
667
665
|
const { property, value, isArbitrary } = token;
|
|
668
666
|
|
|
669
667
|
// Static typography keywords
|
|
670
|
-
|
|
671
|
-
// Font Style
|
|
672
|
-
'italic': 'font-style: italic;',
|
|
673
|
-
'not-italic': 'font-style: normal;',
|
|
674
|
-
|
|
675
|
-
// Font Stretch
|
|
676
|
-
'font-stretch-condensed': 'font-stretch: condensed;',
|
|
677
|
-
'font-stretch-expanded': 'font-stretch: expanded;',
|
|
678
|
-
'font-stretch-normal': 'font-stretch: normal;',
|
|
679
|
-
|
|
680
|
-
// Font Smoothing
|
|
681
|
-
'antialiased': '-webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;',
|
|
682
|
-
'subpixel-antialiased': '-webkit-font-smoothing: auto; -moz-osx-font-smoothing: auto;',
|
|
683
|
-
|
|
684
|
-
// Font Variant Numeric
|
|
685
|
-
'normal-nums': 'font-variant-numeric: normal;',
|
|
686
|
-
'ordinal': 'font-variant-numeric: ordinal;',
|
|
687
|
-
'slashed-zero': 'font-variant-numeric: slashed-zero;',
|
|
688
|
-
'lining-nums': 'font-variant-numeric: lining-nums;',
|
|
689
|
-
'oldstyle-nums': 'font-variant-numeric: oldstyle-nums;',
|
|
690
|
-
'proportional-nums': 'font-variant-numeric: proportional-nums;',
|
|
691
|
-
'tabular-nums': 'font-variant-numeric: tabular-nums;',
|
|
692
|
-
|
|
693
|
-
// Text Transform
|
|
694
|
-
'uppercase': 'text-transform: uppercase;',
|
|
695
|
-
'lowercase': 'text-transform: lowercase;',
|
|
696
|
-
'capitalize': 'text-transform: capitalize;',
|
|
697
|
-
'normal-case': 'text-transform: none;',
|
|
698
|
-
|
|
699
|
-
// Text Decoration Line
|
|
700
|
-
'underline': 'text-decoration-line: underline;',
|
|
701
|
-
'overline': 'text-decoration-line: overline;',
|
|
702
|
-
'line-through': 'text-decoration-line: line-through;',
|
|
703
|
-
'no-underline': 'text-decoration-line: none;',
|
|
704
|
-
|
|
705
|
-
// Text Decoration Style
|
|
706
|
-
'decoration-solid': 'text-decoration-style: solid;',
|
|
707
|
-
'decoration-double': 'text-decoration-style: double;',
|
|
708
|
-
'decoration-dotted': 'text-decoration-style: dotted;',
|
|
709
|
-
'decoration-dashed': 'text-decoration-style: dashed;',
|
|
710
|
-
'decoration-wavy': 'text-decoration-style: wavy;',
|
|
711
|
-
|
|
712
|
-
// Text Overflow
|
|
713
|
-
'truncate': 'overflow: hidden; text-overflow: ellipsis; white-space: nowrap;',
|
|
714
|
-
'text-ellipsis': 'text-overflow: ellipsis;',
|
|
715
|
-
'text-clip': 'text-overflow: clip;',
|
|
716
|
-
|
|
717
|
-
// Text Wrap
|
|
718
|
-
'text-wrap': 'text-wrap: wrap;',
|
|
719
|
-
'text-nowrap': 'text-wrap: nowrap;',
|
|
720
|
-
'text-balance': 'text-wrap: balance;',
|
|
721
|
-
'text-pretty': 'text-wrap: pretty;',
|
|
722
|
-
|
|
723
|
-
// Whitespace
|
|
724
|
-
'whitespace-normal': 'white-space: normal;',
|
|
725
|
-
'whitespace-nowrap': 'white-space: nowrap;',
|
|
726
|
-
'whitespace-pre': 'white-space: pre;',
|
|
727
|
-
'whitespace-pre-line': 'white-space: pre-line;',
|
|
728
|
-
'whitespace-pre-wrap': 'white-space: pre-wrap;',
|
|
729
|
-
'whitespace-break-spaces': 'white-space: break-spaces;',
|
|
730
|
-
|
|
731
|
-
// Word Break
|
|
732
|
-
'break-normal': 'overflow-wrap: normal; word-break: normal;',
|
|
733
|
-
'break-words': 'overflow-wrap: break-word;',
|
|
734
|
-
'break-all': 'word-break: break-all;',
|
|
735
|
-
'break-keep': 'word-break: keep-all;',
|
|
736
|
-
|
|
737
|
-
// Hyphens
|
|
738
|
-
'hyphens-none': 'hyphens: none;',
|
|
739
|
-
'hyphens-manual': 'hyphens: manual;',
|
|
740
|
-
'hyphens-auto': 'hyphens: auto;',
|
|
741
|
-
|
|
742
|
-
// Vertical Align
|
|
743
|
-
'align-baseline': 'vertical-align: baseline;',
|
|
744
|
-
'align-top': 'vertical-align: top;',
|
|
745
|
-
'align-middle': 'vertical-align: middle;',
|
|
746
|
-
'align-bottom': 'vertical-align: bottom;',
|
|
747
|
-
'align-text-top': 'vertical-align: text-top;',
|
|
748
|
-
'align-text-bottom': 'vertical-align: text-bottom;',
|
|
749
|
-
'align-sub': 'vertical-align: sub;',
|
|
750
|
-
'align-super': 'vertical-align: super;',
|
|
751
|
-
|
|
752
|
-
// List Style Type
|
|
753
|
-
'list-none': 'list-style-type: none;',
|
|
754
|
-
'list-disc': 'list-style-type: disc;',
|
|
755
|
-
'list-decimal': 'list-style-type: decimal;',
|
|
756
|
-
'list-square': 'list-style-type: square;',
|
|
757
|
-
|
|
758
|
-
// List Style Position
|
|
759
|
-
'list-inside': 'list-style-position: inside;',
|
|
760
|
-
'list-outside': 'list-style-position: outside;'
|
|
761
|
-
};
|
|
762
|
-
|
|
763
|
-
// Check static keywords first
|
|
668
|
+
// Check static keywords first (imported from definitions)
|
|
764
669
|
if (typographyKeywords[property]) {
|
|
765
670
|
return typographyKeywords[property];
|
|
766
671
|
}
|
|
@@ -768,12 +673,34 @@ function generateVisualRule(token, config) {
|
|
|
768
673
|
const rules = {
|
|
769
674
|
// Background Color
|
|
770
675
|
'bg': () => {
|
|
771
|
-
const cssValue =
|
|
676
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
772
677
|
return `background-color: ${cssValue};`;
|
|
773
678
|
},
|
|
774
679
|
|
|
775
680
|
// Background Image
|
|
776
681
|
'bg-image': () => {
|
|
682
|
+
if (value === 'none') return 'background-image: none;';
|
|
683
|
+
|
|
684
|
+
// Handle gradient definitions
|
|
685
|
+
if (value.startsWith('gradient-to-')) {
|
|
686
|
+
const directionMap = {
|
|
687
|
+
't': 'to top',
|
|
688
|
+
'tr': 'to top right',
|
|
689
|
+
'r': 'to right',
|
|
690
|
+
'br': 'to bottom right',
|
|
691
|
+
'b': 'to bottom',
|
|
692
|
+
'bl': 'to bottom left',
|
|
693
|
+
'l': 'to left',
|
|
694
|
+
'tl': 'to top left'
|
|
695
|
+
};
|
|
696
|
+
const directionCode = value.replace('gradient-to-', '');
|
|
697
|
+
const direction = directionMap[directionCode];
|
|
698
|
+
|
|
699
|
+
if (direction) {
|
|
700
|
+
return `background-image: linear-gradient(${direction}, var(--ss-gradient-stops, transparent));`;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
777
704
|
const cssValue = isArbitrary ? sanitizeArbitraryValue(`url(${value})`) : `url(${value})`;
|
|
778
705
|
return `background-image: ${cssValue};`;
|
|
779
706
|
},
|
|
@@ -852,13 +779,29 @@ function generateVisualRule(token, config) {
|
|
|
852
779
|
'bg-blend': () => {
|
|
853
780
|
return `background-blend-mode: ${value};`;
|
|
854
781
|
},
|
|
782
|
+
|
|
783
|
+
// Gradient Color Stops
|
|
784
|
+
'from': () => {
|
|
785
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
786
|
+
return `--ss-gradient-from: ${cssValue}; --ss-gradient-to: rgb(255 255 255 / 0); --ss-gradient-stops: var(--ss-gradient-from), var(--ss-gradient-to);`;
|
|
787
|
+
},
|
|
788
|
+
|
|
789
|
+
'via': () => {
|
|
790
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
791
|
+
return `--ss-gradient-to: rgb(255 255 255 / 0); --ss-gradient-stops: var(--ss-gradient-from), ${cssValue}, var(--ss-gradient-to);`;
|
|
792
|
+
},
|
|
793
|
+
|
|
794
|
+
'to': () => {
|
|
795
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
796
|
+
return `--ss-gradient-to: ${cssValue};`;
|
|
797
|
+
},
|
|
855
798
|
|
|
856
799
|
// Text color
|
|
857
800
|
'text': () => {
|
|
858
801
|
if (['left', 'center', 'right', 'justify'].includes(value)) {
|
|
859
802
|
return `text-align: ${value};`;
|
|
860
803
|
}
|
|
861
|
-
const cssValue =
|
|
804
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
862
805
|
return `color: ${cssValue};`;
|
|
863
806
|
},
|
|
864
807
|
|
|
@@ -951,7 +894,7 @@ function generateVisualRule(token, config) {
|
|
|
951
894
|
|
|
952
895
|
// Text decoration color
|
|
953
896
|
'decoration': () => {
|
|
954
|
-
const cssValue =
|
|
897
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
955
898
|
return `text-decoration-color: ${cssValue};`;
|
|
956
899
|
},
|
|
957
900
|
|
|
@@ -975,33 +918,33 @@ function generateVisualRule(token, config) {
|
|
|
975
918
|
|
|
976
919
|
// Border color
|
|
977
920
|
'border': () => {
|
|
978
|
-
const cssValue =
|
|
921
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
979
922
|
return `border-color: ${cssValue}; border-style: solid;`;
|
|
980
923
|
},
|
|
981
924
|
|
|
982
925
|
// Border color - directional
|
|
983
926
|
'border-t': () => {
|
|
984
|
-
const cssValue =
|
|
927
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
985
928
|
return `border-top-color: ${cssValue}; border-top-style: solid;`;
|
|
986
929
|
},
|
|
987
930
|
'border-b': () => {
|
|
988
|
-
const cssValue =
|
|
931
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
989
932
|
return `border-bottom-color: ${cssValue}; border-bottom-style: solid;`;
|
|
990
933
|
},
|
|
991
934
|
'border-l': () => {
|
|
992
|
-
const cssValue =
|
|
935
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
993
936
|
return `border-left-color: ${cssValue}; border-left-style: solid;`;
|
|
994
937
|
},
|
|
995
938
|
'border-r': () => {
|
|
996
|
-
const cssValue =
|
|
939
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
997
940
|
return `border-right-color: ${cssValue}; border-right-style: solid;`;
|
|
998
941
|
},
|
|
999
942
|
'border-x': () => {
|
|
1000
|
-
const cssValue =
|
|
943
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1001
944
|
return `border-left-color: ${cssValue}; border-right-color: ${cssValue}; border-left-style: solid; border-right-style: solid;`;
|
|
1002
945
|
},
|
|
1003
946
|
'border-y': () => {
|
|
1004
|
-
const cssValue =
|
|
947
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1005
948
|
return `border-top-color: ${cssValue}; border-bottom-color: ${cssValue}; border-top-style: solid; border-bottom-style: solid;`;
|
|
1006
949
|
},
|
|
1007
950
|
|
|
@@ -1053,7 +996,7 @@ function generateVisualRule(token, config) {
|
|
|
1053
996
|
|
|
1054
997
|
// Divide color - all sides
|
|
1055
998
|
'divide': () => {
|
|
1056
|
-
const cssValue =
|
|
999
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1057
1000
|
return `border-color: ${cssValue}; border-style: solid;`;
|
|
1058
1001
|
},
|
|
1059
1002
|
|
|
@@ -1063,7 +1006,7 @@ function generateVisualRule(token, config) {
|
|
|
1063
1006
|
if (value === 'reverse') {
|
|
1064
1007
|
return '--ss-divide-x-reverse: 1;';
|
|
1065
1008
|
}
|
|
1066
|
-
const cssValue =
|
|
1009
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1067
1010
|
return `border-left-color: ${cssValue}; border-right-color: ${cssValue}; border-left-style: solid; border-right-style: solid;`;
|
|
1068
1011
|
},
|
|
1069
1012
|
'divide-y': () => {
|
|
@@ -1071,7 +1014,7 @@ function generateVisualRule(token, config) {
|
|
|
1071
1014
|
if (value === 'reverse') {
|
|
1072
1015
|
return '--ss-divide-y-reverse: 1;';
|
|
1073
1016
|
}
|
|
1074
|
-
const cssValue =
|
|
1017
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1075
1018
|
return `border-top-color: ${cssValue}; border-bottom-color: ${cssValue}; border-top-style: solid; border-bottom-style: solid;`;
|
|
1076
1019
|
},
|
|
1077
1020
|
|
|
@@ -1104,7 +1047,7 @@ function generateVisualRule(token, config) {
|
|
|
1104
1047
|
|
|
1105
1048
|
// Outline Color
|
|
1106
1049
|
'outline': () => {
|
|
1107
|
-
const cssValue =
|
|
1050
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1108
1051
|
return `outline-color: ${cssValue};`;
|
|
1109
1052
|
},
|
|
1110
1053
|
|
|
@@ -1119,6 +1062,51 @@ function generateVisualRule(token, config) {
|
|
|
1119
1062
|
return `outline-offset: ${cssValue};`;
|
|
1120
1063
|
},
|
|
1121
1064
|
|
|
1065
|
+
// Ring Width
|
|
1066
|
+
'ring-w': () => {
|
|
1067
|
+
const cssValue = isArbitrary ? value : `var(--s-${value})`;
|
|
1068
|
+
return `--ss-ring-width: ${cssValue};`;
|
|
1069
|
+
},
|
|
1070
|
+
|
|
1071
|
+
// Ring Color
|
|
1072
|
+
'ring-color': () => {
|
|
1073
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1074
|
+
return `--ss-ring-color: ${cssValue};`;
|
|
1075
|
+
},
|
|
1076
|
+
|
|
1077
|
+
// Ring Offset Width
|
|
1078
|
+
'ring-offset': () => {
|
|
1079
|
+
const cssValue = isArbitrary ? value : `var(--s-${value})`;
|
|
1080
|
+
return `--ss-ring-offset-width: ${cssValue};`;
|
|
1081
|
+
},
|
|
1082
|
+
|
|
1083
|
+
// Ring Offset Color
|
|
1084
|
+
'ring-offset-color': () => {
|
|
1085
|
+
const cssValue = resolveColorValue(value, isArbitrary);
|
|
1086
|
+
return `--ss-ring-offset-color: ${cssValue};`;
|
|
1087
|
+
},
|
|
1088
|
+
|
|
1089
|
+
// Ring (Main utility)
|
|
1090
|
+
'ring': () => {
|
|
1091
|
+
if (value === 'none') {
|
|
1092
|
+
return 'box-shadow: 0 0 #0000;';
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
const ringPresets = {
|
|
1096
|
+
'thin': '1px',
|
|
1097
|
+
'regular': '2px',
|
|
1098
|
+
'small': '4px',
|
|
1099
|
+
'medium': '6px',
|
|
1100
|
+
'big': '8px'
|
|
1101
|
+
};
|
|
1102
|
+
|
|
1103
|
+
const width = isArbitrary ? value : (ringPresets[value] || (parseInt(value) ? `${value}px` : `var(--s-${value})`));
|
|
1104
|
+
|
|
1105
|
+
// We set both the variable and the box-shadow that uses it
|
|
1106
|
+
// This allows ring:[size] to work on its own or with ring-color:[color]
|
|
1107
|
+
return `--ss-ring-width: ${width}; box-shadow: var(--ss-ring-inset) 0 0 0 calc(var(--ss-ring-width) + var(--ss-ring-offset-width, 0px)) var(--ss-ring-color, currentColor);`;
|
|
1108
|
+
},
|
|
1109
|
+
|
|
1122
1110
|
// Box shadow
|
|
1123
1111
|
'shadow': () => {
|
|
1124
1112
|
return `box-shadow: var(--shadow-${value});`;
|
|
@@ -1596,11 +1584,31 @@ function generateVisualRule(token, config) {
|
|
|
1596
1584
|
'translate-x': () => {
|
|
1597
1585
|
const translatePresets = {
|
|
1598
1586
|
'full': '100%',
|
|
1587
|
+
'half': '50%',
|
|
1588
|
+
'third': '33.333333%',
|
|
1589
|
+
'third-2x': '66.666667%',
|
|
1590
|
+
'quarter': '25%',
|
|
1591
|
+
'quarter-2x': '50%',
|
|
1592
|
+
'quarter-3x': '75%',
|
|
1593
|
+
// Legacy fraction format (for backward compatibility)
|
|
1599
1594
|
'1/2': '50%',
|
|
1600
1595
|
'1/3': '33.333333%',
|
|
1601
1596
|
'2/3': '66.666667%',
|
|
1602
1597
|
'1/4': '25%',
|
|
1603
|
-
'3/4': '75%'
|
|
1598
|
+
'3/4': '75%',
|
|
1599
|
+
// Negatives (prefixed with -)
|
|
1600
|
+
'-full': '-100%',
|
|
1601
|
+
'-half': '-50%',
|
|
1602
|
+
'-third': '-33.333333%',
|
|
1603
|
+
'-third-2x': '-66.666667%',
|
|
1604
|
+
'-quarter': '-25%',
|
|
1605
|
+
'-quarter-2x': '-50%',
|
|
1606
|
+
'-quarter-3x': '-75%',
|
|
1607
|
+
'-1/2': '-50%',
|
|
1608
|
+
'-1/3': '-33.333333%',
|
|
1609
|
+
'-2/3': '-66.666667%',
|
|
1610
|
+
'-1/4': '-25%',
|
|
1611
|
+
'-3/4': '-75%'
|
|
1604
1612
|
};
|
|
1605
1613
|
const cssValue = isArbitrary ? value : (translatePresets[value] || `var(--s-${value})`);
|
|
1606
1614
|
return `transform: translateX(${cssValue});`;
|
|
@@ -1609,42 +1617,36 @@ function generateVisualRule(token, config) {
|
|
|
1609
1617
|
'translate-y': () => {
|
|
1610
1618
|
const translatePresets = {
|
|
1611
1619
|
'full': '100%',
|
|
1620
|
+
'half': '50%',
|
|
1621
|
+
'third': '33.333333%',
|
|
1622
|
+
'third-2x': '66.666667%',
|
|
1623
|
+
'quarter': '25%',
|
|
1624
|
+
'quarter-2x': '50%',
|
|
1625
|
+
'quarter-3x': '75%',
|
|
1626
|
+
// Legacy fraction format (for backward compatibility)
|
|
1612
1627
|
'1/2': '50%',
|
|
1613
1628
|
'1/3': '33.333333%',
|
|
1614
1629
|
'2/3': '66.666667%',
|
|
1615
1630
|
'1/4': '25%',
|
|
1616
|
-
'3/4': '75%'
|
|
1631
|
+
'3/4': '75%',
|
|
1632
|
+
// Negatives (prefixed with -)
|
|
1633
|
+
'-full': '-100%',
|
|
1634
|
+
'-half': '-50%',
|
|
1635
|
+
'-third': '-33.333333%',
|
|
1636
|
+
'-third-2x': '-66.666667%',
|
|
1637
|
+
'-quarter': '-25%',
|
|
1638
|
+
'-quarter-2x': '-50%',
|
|
1639
|
+
'-quarter-3x': '-75%',
|
|
1640
|
+
'-1/2': '-50%',
|
|
1641
|
+
'-1/3': '-33.333333%',
|
|
1642
|
+
'-2/3': '-66.666667%',
|
|
1643
|
+
'-1/4': '-25%',
|
|
1644
|
+
'-3/4': '-75%'
|
|
1617
1645
|
};
|
|
1618
1646
|
const cssValue = isArbitrary ? value : (translatePresets[value] || `var(--s-${value})`);
|
|
1619
1647
|
return `transform: translateY(${cssValue});`;
|
|
1620
1648
|
},
|
|
1621
1649
|
|
|
1622
|
-
'-translate-x': () => {
|
|
1623
|
-
const translatePresets = {
|
|
1624
|
-
'full': '-100%',
|
|
1625
|
-
'1/2': '-50%',
|
|
1626
|
-
'1/3': '-33.333333%',
|
|
1627
|
-
'2/3': '-66.666667%',
|
|
1628
|
-
'1/4': '-25%',
|
|
1629
|
-
'3/4': '-75%'
|
|
1630
|
-
};
|
|
1631
|
-
const cssValue = isArbitrary ? `-${value}` : (translatePresets[value] || `calc(var(--s-${value}) * -1)`);
|
|
1632
|
-
return `transform: translateX(${cssValue});`;
|
|
1633
|
-
},
|
|
1634
|
-
|
|
1635
|
-
'-translate-y': () => {
|
|
1636
|
-
const translatePresets = {
|
|
1637
|
-
'full': '-100%',
|
|
1638
|
-
'1/2': '-50%',
|
|
1639
|
-
'1/3': '-33.333333%',
|
|
1640
|
-
'2/3': '-66.666667%',
|
|
1641
|
-
'1/4': '-25%',
|
|
1642
|
-
'3/4': '-75%'
|
|
1643
|
-
};
|
|
1644
|
-
const cssValue = isArbitrary ? `-${value}` : (translatePresets[value] || `calc(var(--s-${value}) * -1)`);
|
|
1645
|
-
return `transform: translateY(${cssValue});`;
|
|
1646
|
-
},
|
|
1647
|
-
|
|
1648
1650
|
// Skew
|
|
1649
1651
|
'skew-x': () => {
|
|
1650
1652
|
const cssValue = isArbitrary ? value : `${value}deg`;
|
|
@@ -1984,7 +1986,7 @@ function generateVisualRule(token, config) {
|
|
|
1984
1986
|
* @param {Object} config - Configuration object
|
|
1985
1987
|
* @param {boolean} skipDarkWrapper - If true, don't add dark mode wrapper (used when generating inside dark block)
|
|
1986
1988
|
*/
|
|
1987
|
-
export function generateRule(token, config, skipDarkWrapper = false) {
|
|
1989
|
+
export function generateRule(token, config, skipDarkWrapper = false, interactIds = new Set()) {
|
|
1988
1990
|
const { raw, attrType, breakpoint, state } = token;
|
|
1989
1991
|
|
|
1990
1992
|
let cssDeclaration = '';
|
|
@@ -2020,9 +2022,59 @@ export function generateRule(token, config, skipDarkWrapper = false) {
|
|
|
2020
2022
|
if (state && state !== 'dark') {
|
|
2021
2023
|
if (isDivide) {
|
|
2022
2024
|
// For divide utilities, add state to the element after tilde
|
|
2025
|
+
// Divide utilities don't support group/peer states yet to avoid complexity
|
|
2023
2026
|
selector = `[${attrType}~="${raw}"] > :not([hidden]) ~ :not([hidden]):${state}`;
|
|
2024
2027
|
} else {
|
|
2025
|
-
|
|
2028
|
+
// Helper to map state to CSS selector
|
|
2029
|
+
const getStateSelector = (s) => {
|
|
2030
|
+
const map = {
|
|
2031
|
+
'expanded': '[aria-expanded="true"]',
|
|
2032
|
+
'selected': '[aria-selected="true"]',
|
|
2033
|
+
'disabled': ':disabled'
|
|
2034
|
+
};
|
|
2035
|
+
return map[s] || `:${s}`;
|
|
2036
|
+
};
|
|
2037
|
+
|
|
2038
|
+
const selectors = [];
|
|
2039
|
+
|
|
2040
|
+
// 1. Standard State Selector
|
|
2041
|
+
selectors.push(`${selector}${getStateSelector(state)}`);
|
|
2042
|
+
|
|
2043
|
+
// 2. Group & Peer State Selectors
|
|
2044
|
+
// Only for supported triggers
|
|
2045
|
+
const groupTriggers = {
|
|
2046
|
+
'hover': 'hoverable',
|
|
2047
|
+
'focus': 'focusable',
|
|
2048
|
+
'focus-visible': 'focusable',
|
|
2049
|
+
'active': 'pressable',
|
|
2050
|
+
'expanded': 'expandable',
|
|
2051
|
+
'selected': 'selectable'
|
|
2052
|
+
};
|
|
2053
|
+
|
|
2054
|
+
if (groupTriggers[state]) {
|
|
2055
|
+
const parentAttr = groupTriggers[state];
|
|
2056
|
+
// For focus, we trigger on focus-within of the container
|
|
2057
|
+
let triggerState = state;
|
|
2058
|
+
if (state === 'focus' || state === 'focus-visible') triggerState = 'focus-within';
|
|
2059
|
+
|
|
2060
|
+
const triggerSelector = getStateSelector(triggerState);
|
|
2061
|
+
|
|
2062
|
+
// Group Selector
|
|
2063
|
+
// [layout~="hoverable"]:not([layout~="disabled"]):hover [visual~="..."]
|
|
2064
|
+
const groupSelector = `[layout~="${parentAttr}"]:not([layout~="disabled"])${triggerSelector} ${selector}`;
|
|
2065
|
+
selectors.push(groupSelector);
|
|
2066
|
+
|
|
2067
|
+
// Peer Selectors
|
|
2068
|
+
// [interact~="id"]:not([layout~="disabled"]):hover ~ [listens~="id"][visual~="..."]
|
|
2069
|
+
if (interactIds && interactIds.size > 0) {
|
|
2070
|
+
for (const id of interactIds) {
|
|
2071
|
+
const peerSelector = `[interact~="${id}"]:not([layout~="disabled"])${triggerSelector} ~ [listens~="${id}"]${selector}`;
|
|
2072
|
+
selectors.push(peerSelector);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
|
|
2077
|
+
selector = selectors.join(',\n');
|
|
2026
2078
|
}
|
|
2027
2079
|
}
|
|
2028
2080
|
|
|
@@ -2110,6 +2162,14 @@ export function generateCSS(tokens, config) {
|
|
|
2110
2162
|
}
|
|
2111
2163
|
}
|
|
2112
2164
|
|
|
2165
|
+
// Collect interact IDs for Peer selector generation
|
|
2166
|
+
const interactIds = new Set();
|
|
2167
|
+
for (const token of tokens) {
|
|
2168
|
+
if (token.attrType === 'interact') {
|
|
2169
|
+
interactIds.add(token.raw);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2113
2173
|
// Track display properties to handle conflicts like Tailwind
|
|
2114
2174
|
// When responsive display property conflicts with base display property on the same element,
|
|
2115
2175
|
// we need to add reset rules in the responsive media query
|
|
@@ -2131,7 +2191,7 @@ export function generateCSS(tokens, config) {
|
|
|
2131
2191
|
|
|
2132
2192
|
// Generate base rules
|
|
2133
2193
|
for (const token of baseTokens) {
|
|
2134
|
-
css += generateRule(token, config);
|
|
2194
|
+
css += generateRule(token, config, false, interactIds);
|
|
2135
2195
|
}
|
|
2136
2196
|
|
|
2137
2197
|
// Generate responsive rules
|
|
@@ -2169,7 +2229,7 @@ export function generateCSS(tokens, config) {
|
|
|
2169
2229
|
|
|
2170
2230
|
// Generate responsive token rules
|
|
2171
2231
|
for (const token of bpTokens) {
|
|
2172
|
-
css += ' ' + generateRule(token, config);
|
|
2232
|
+
css += ' ' + generateRule(token, config, false, interactIds);
|
|
2173
2233
|
}
|
|
2174
2234
|
css += '}\n';
|
|
2175
2235
|
}
|
|
@@ -2185,14 +2245,14 @@ export function generateCSS(tokens, config) {
|
|
|
2185
2245
|
css += `\n/* Dark Mode (prefers-color-scheme) */\n`;
|
|
2186
2246
|
css += `@media (prefers-color-scheme: dark) {\n`;
|
|
2187
2247
|
for (const token of darkTokens) {
|
|
2188
|
-
css += ' ' + generateRule(token, config, true);
|
|
2248
|
+
css += ' ' + generateRule(token, config, true, interactIds);
|
|
2189
2249
|
}
|
|
2190
2250
|
css += '}\n';
|
|
2191
2251
|
} else {
|
|
2192
2252
|
// Selector strategy (.dark class or custom selector)
|
|
2193
2253
|
css += `\n/* Dark Mode (${darkSelector}) */\n`;
|
|
2194
2254
|
for (const token of darkTokens) {
|
|
2195
|
-
const baseRule = generateRule(token, config, true);
|
|
2255
|
+
const baseRule = generateRule(token, config, true, interactIds);
|
|
2196
2256
|
// Wrap selector with dark parent
|
|
2197
2257
|
const wrappedRule = baseRule.replace(/^(\[[^\]]+\])/, `${darkSelector} $1`);
|
|
2198
2258
|
css += wrappedRule;
|