@decantr/css 1.0.0

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 ADDED
@@ -0,0 +1,134 @@
1
+ # @decantr/css
2
+
3
+ Framework-agnostic CSS atoms runtime for Decantr projects.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @decantr/css
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```js
14
+ import { css } from '@decantr/css';
15
+
16
+ // In your components
17
+ <div className={css('_flex _col _gap4 _p4')}>
18
+ <h1 className={css('_heading1')}>Title</h1>
19
+ <p className={css('_textsm _fgmuted')}>Description</p>
20
+ </div>
21
+ ```
22
+
23
+ ## How It Works
24
+
25
+ The `css()` function:
26
+ 1. Parses atom strings (e.g., `'_flex _col _gap4'`)
27
+ 2. Resolves each atom to CSS (e.g., `_flex` -> `display:flex`)
28
+ 3. Injects the CSS into the DOM via `<style>` tags
29
+ 4. Returns the class names for use in your markup
30
+
31
+ CSS is injected into `@layer d.atoms` for proper cascade control.
32
+
33
+ ## API
34
+
35
+ ### css(...classes)
36
+
37
+ Process atom strings and inject CSS. Returns space-separated class names.
38
+
39
+ ```js
40
+ css('_flex _col') // Returns: '_flex _col', injects CSS
41
+ css('_flex', '_col', condition && '_gap4') // Handles multiple args, falsy values
42
+ ```
43
+
44
+ ### define(name, declaration)
45
+
46
+ Register a custom atom.
47
+
48
+ ```js
49
+ define('_brand', 'color:var(--brand);font-weight:700');
50
+ css('_brand') // Now works
51
+ ```
52
+
53
+ ### extractCSS()
54
+
55
+ Get all injected CSS as a string (for SSR).
56
+
57
+ ```js
58
+ const cssString = extractCSS();
59
+ // Returns: '@layer d.atoms{._flex{display:flex}...}'
60
+ ```
61
+
62
+ ### reset()
63
+
64
+ Clear all injected styles (for testing).
65
+
66
+ ```js
67
+ reset();
68
+ ```
69
+
70
+ ## Atom Reference
71
+
72
+ ### Display
73
+ `_flex`, `_grid`, `_block`, `_inline`, `_none`, `_contents`
74
+
75
+ ### Flexbox
76
+ `_col`, `_row`, `_wrap`, `_nowrap`, `_flex1`, `_grow`, `_shrink0`
77
+
78
+ ### Alignment
79
+ `_aic` (align-items:center), `_jcc` (justify-content:center), `_jcsb` (space-between)
80
+
81
+ ### Spacing
82
+ `_gap{n}`, `_p{n}`, `_m{n}`, `_pt{n}`, `_px{n}`, `_my{n}` where n = 0-96
83
+
84
+ ### Sizing
85
+ `_wfull`, `_hfull`, `_w{n}`, `_h{n}`, `_minw0`, `_maxwfull`
86
+
87
+ ### Typography
88
+ `_textsm`, `_textlg`, `_text2xl`, `_heading1`-`_heading6`, `_fontbold`
89
+
90
+ ### Colors (use CSS variables)
91
+ `_bgprimary`, `_bgsurface`, `_fgmuted`, `_bcborder`
92
+
93
+ ### Responsive Prefixes
94
+ Mobile-first breakpoints: `_sm:` (640px), `_md:` (768px), `_lg:` (1024px), `_xl:` (1280px)
95
+
96
+ ```jsx
97
+ <div className={css('_gc1 _sm:gc2 _lg:gc4')}>
98
+ {/* 1 col -> 2 cols at 640px -> 4 cols at 1024px */}
99
+ </div>
100
+ ```
101
+
102
+ ### Pseudo-class Prefixes
103
+ `_h:` (hover), `_f:` (focus), `_fv:` (focus-visible), `_a:` (active)
104
+
105
+ ```jsx
106
+ <button className={css('_bgprimary _h:bgprimary/80')}>
107
+ Hover me
108
+ </button>
109
+ ```
110
+
111
+ ### Opacity Modifiers
112
+ `_bgprimary/50` -> 50% opacity via `color-mix()`
113
+
114
+ ### Arbitrary Values
115
+ `_w[512px]`, `_p[clamp(1rem,3vw,2rem)]`, `_bg[#1a1a2e]`
116
+
117
+ ## Integration with Decantr
118
+
119
+ When you scaffold a project with `@decantr/cli`, it generates:
120
+
121
+ - `src/styles/tokens.css` - Theme tokens (colors, spacing, radii)
122
+ - `src/styles/decorators.css` - Recipe decorator classes
123
+
124
+ Import these alongside @decantr/css:
125
+
126
+ ```js
127
+ import { css } from '@decantr/css';
128
+ import './styles/tokens.css';
129
+ import './styles/decorators.css';
130
+ ```
131
+
132
+ ## License
133
+
134
+ MIT
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Decantr CSS - Main css() function.
3
+ * Ported from decantr-framework/src/css/index.js
4
+ */
5
+ /**
6
+ * Process atom strings and inject CSS.
7
+ * @param classes - One or more class strings
8
+ * @returns Space-separated class names
9
+ */
10
+ declare function css(...classes: (string | undefined | null | false)[]): string;
11
+ /**
12
+ * Define a custom atom.
13
+ * @param name - Atom name (e.g., '_myatom')
14
+ * @param declaration - CSS declaration(s)
15
+ */
16
+ declare function define(name: string, declaration: string): void;
17
+
18
+ /**
19
+ * Decantr CSS Runtime - CSS injection and extraction.
20
+ * Ported from decantr-framework/src/css/runtime.js
21
+ */
22
+ /** Responsive breakpoints (mobile-first, min-width) */
23
+ declare const BREAKPOINTS: {
24
+ readonly sm: 640;
25
+ readonly md: 768;
26
+ readonly lg: 1024;
27
+ readonly xl: 1280;
28
+ };
29
+ /** Container query breakpoints */
30
+ declare const CQ_WIDTHS: readonly [320, 480, 640, 768, 1024];
31
+ /**
32
+ * Inject a CSS rule for a class.
33
+ * @param className - The class name (e.g., '_flex')
34
+ * @param declaration - CSS declaration(s) (e.g., 'display:flex')
35
+ * @param escapedName - Pre-escaped class name for special chars
36
+ */
37
+ declare function inject(className: string, declaration: string, escapedName?: string): void;
38
+ /**
39
+ * Inject a responsive (breakpoint-wrapped) atom.
40
+ * @param className - e.g., '_sm:gc3'
41
+ * @param declaration - CSS declaration(s)
42
+ * @param bp - breakpoint key (sm|md|lg|xl)
43
+ */
44
+ declare function injectResponsive(className: string, declaration: string, bp: string): void;
45
+ /**
46
+ * Inject a pseudo-class atom.
47
+ * @param className - e.g., '_h:bgprimary'
48
+ * @param declaration - CSS declaration(s)
49
+ * @param prefix - 'h'|'f'|'fv'|'a'|'fw'
50
+ */
51
+ declare function injectPseudo(className: string, declaration: string, prefix: string): void;
52
+ /**
53
+ * Inject a container query-wrapped atom.
54
+ * @param className - e.g., '_cq640:gc3'
55
+ * @param declaration - CSS declaration(s)
56
+ * @param width - container min-width in px
57
+ */
58
+ declare function injectContainer(className: string, declaration: string, width: number): void;
59
+ /**
60
+ * Inject a group/peer state atom.
61
+ * @param className - e.g., '_gh:fgprimary'
62
+ * @param declaration - CSS declaration(s)
63
+ * @param prefix - 'gh'|'gf'|'ga'|'ph'|'pf'|'pa'
64
+ */
65
+ declare function injectGroupPeer(className: string, declaration: string, prefix: string): void;
66
+ /**
67
+ * Inject a media query-wrapped atom.
68
+ * @param className - e.g., '_motionSafe:trans'
69
+ * @param declaration - CSS declaration(s)
70
+ * @param query - media query string
71
+ */
72
+ declare function injectMediaQuery(className: string, declaration: string, query: string): void;
73
+ /**
74
+ * Extract all injected CSS as a string (for SSR).
75
+ */
76
+ declare function extractCSS(): string;
77
+ /**
78
+ * Get set of injected class names.
79
+ */
80
+ declare function getInjectedClasses(): Set<string>;
81
+ /**
82
+ * Reset all injected styles (for testing).
83
+ */
84
+ declare function reset(): void;
85
+
86
+ /**
87
+ * Decantr CSS Atoms - Direct atom definitions and algorithmic resolution.
88
+ * Ported from decantr-framework/src/css/atoms.js
89
+ */
90
+ /**
91
+ * Resolve an atom name to its CSS declaration.
92
+ * @param atom - Atom name (e.g., '_flex', '_gap4', '_p2')
93
+ * @returns CSS declaration or null if not recognized
94
+ */
95
+ declare function resolveAtomDecl(atom: string): string | null;
96
+
97
+ export { BREAKPOINTS, CQ_WIDTHS, css, define, extractCSS, getInjectedClasses, inject, injectContainer, injectGroupPeer, injectMediaQuery, injectPseudo, injectResponsive, reset, resolveAtomDecl };
package/dist/index.js ADDED
@@ -0,0 +1,1014 @@
1
+ // src/atoms.ts
2
+ var DIRECT = {
3
+ // Display
4
+ block: "display:block",
5
+ inline: "display:inline",
6
+ flex: "display:flex",
7
+ inlineflex: "display:inline-flex",
8
+ grid: "display:grid",
9
+ inlinegrid: "display:inline-grid",
10
+ none: "display:none",
11
+ contents: "display:contents",
12
+ // Flexbox direction
13
+ col: "flex-direction:column",
14
+ row: "flex-direction:row",
15
+ colrev: "flex-direction:column-reverse",
16
+ rowrev: "flex-direction:row-reverse",
17
+ // Flex wrap
18
+ wrap: "flex-wrap:wrap",
19
+ nowrap: "flex-wrap:nowrap",
20
+ wraprev: "flex-wrap:wrap-reverse",
21
+ // Flex grow/shrink
22
+ flex1: "flex:1",
23
+ flex0: "flex:none",
24
+ flexauto: "flex:auto",
25
+ grow: "flex-grow:1",
26
+ grow0: "flex-grow:0",
27
+ shrink: "flex-shrink:1",
28
+ shrink0: "flex-shrink:0",
29
+ // Align items
30
+ aic: "align-items:center",
31
+ aifs: "align-items:flex-start",
32
+ aife: "align-items:flex-end",
33
+ aist: "align-items:stretch",
34
+ aibl: "align-items:baseline",
35
+ // Justify content
36
+ jcc: "justify-content:center",
37
+ jcfs: "justify-content:flex-start",
38
+ jcfe: "justify-content:flex-end",
39
+ jcsb: "justify-content:space-between",
40
+ jcsa: "justify-content:space-around",
41
+ jcse: "justify-content:space-evenly",
42
+ // Align self
43
+ asc: "align-self:center",
44
+ asfs: "align-self:flex-start",
45
+ asfe: "align-self:flex-end",
46
+ asst: "align-self:stretch",
47
+ // Justify self
48
+ jsc: "justify-self:center",
49
+ jsfs: "justify-self:start",
50
+ jsfe: "justify-self:end",
51
+ jsst: "justify-self:stretch",
52
+ // Place items/content
53
+ pic: "place-items:center",
54
+ pcc: "place-content:center",
55
+ // Position
56
+ rel: "position:relative",
57
+ abs: "position:absolute",
58
+ fixed: "position:fixed",
59
+ sticky: "position:sticky",
60
+ static: "position:static",
61
+ // Sizing
62
+ wfull: "width:100%",
63
+ hfull: "height:100%",
64
+ w100: "width:100%",
65
+ h100: "height:100%",
66
+ wscreen: "width:100vw",
67
+ hscreen: "height:100vh",
68
+ wfit: "width:fit-content",
69
+ hfit: "height:fit-content",
70
+ wmin: "width:min-content",
71
+ hmin: "height:min-content",
72
+ wmax: "width:max-content",
73
+ hmax: "height:max-content",
74
+ wauto: "width:auto",
75
+ hauto: "height:auto",
76
+ minw0: "min-width:0",
77
+ minh0: "min-height:0",
78
+ maxwfull: "max-width:100%",
79
+ maxhfull: "max-height:100%",
80
+ // Overflow
81
+ overhidden: "overflow:hidden",
82
+ overauto: "overflow:auto",
83
+ overscroll: "overflow:scroll",
84
+ overvis: "overflow:visible",
85
+ overclip: "overflow:clip",
86
+ overxhidden: "overflow-x:hidden",
87
+ overyhidden: "overflow-y:hidden",
88
+ overxauto: "overflow-x:auto",
89
+ overyauto: "overflow-y:auto",
90
+ // Text alignment
91
+ textl: "text-align:left",
92
+ textc: "text-align:center",
93
+ textr: "text-align:right",
94
+ textj: "text-align:justify",
95
+ // Vertical alignment
96
+ vam: "vertical-align:middle",
97
+ vat: "vertical-align:top",
98
+ vab: "vertical-align:bottom",
99
+ vabl: "vertical-align:baseline",
100
+ // Font weight
101
+ fontlight: "font-weight:300",
102
+ fontnormal: "font-weight:400",
103
+ fontmedium: "font-weight:500",
104
+ fontsemi: "font-weight:600",
105
+ fontbold: "font-weight:700",
106
+ fontextrabold: "font-weight:800",
107
+ // Font style
108
+ italic: "font-style:italic",
109
+ notitalic: "font-style:normal",
110
+ // Text decoration
111
+ underline: "text-decoration:underline",
112
+ linethrough: "text-decoration:line-through",
113
+ nounderline: "text-decoration:none",
114
+ // Text transform
115
+ uppercase: "text-transform:uppercase",
116
+ lowercase: "text-transform:lowercase",
117
+ capitalize: "text-transform:capitalize",
118
+ normalcase: "text-transform:none",
119
+ // Whitespace
120
+ nowraptext: "white-space:nowrap",
121
+ pre: "white-space:pre",
122
+ prewrap: "white-space:pre-wrap",
123
+ preline: "white-space:pre-line",
124
+ breakspaces: "white-space:break-spaces",
125
+ // Word/text breaking
126
+ breakword: "overflow-wrap:break-word",
127
+ breakall: "word-break:break-all",
128
+ breakkeep: "word-break:keep-all",
129
+ truncate: "overflow:hidden;text-overflow:ellipsis;white-space:nowrap",
130
+ // Cursor
131
+ pointer: "cursor:pointer",
132
+ cursordefault: "cursor:default",
133
+ wait: "cursor:wait",
134
+ cursortext: "cursor:text",
135
+ move: "cursor:move",
136
+ notallowed: "cursor:not-allowed",
137
+ grab: "cursor:grab",
138
+ grabbing: "cursor:grabbing",
139
+ // Pointer events
140
+ ptrall: "pointer-events:all",
141
+ ptrnone: "pointer-events:none",
142
+ ptrauto: "pointer-events:auto",
143
+ // User select
144
+ selectnone: "user-select:none",
145
+ selecttext: "user-select:text",
146
+ selectall: "user-select:all",
147
+ selectauto: "user-select:auto",
148
+ // Visibility
149
+ visible: "visibility:visible",
150
+ invisible: "visibility:hidden",
151
+ // Opacity
152
+ op0: "opacity:0",
153
+ op25: "opacity:0.25",
154
+ op50: "opacity:0.5",
155
+ op75: "opacity:0.75",
156
+ op100: "opacity:1",
157
+ // Border style
158
+ bordernone: "border:none",
159
+ bordersolid: "border-style:solid",
160
+ borderdashed: "border-style:dashed",
161
+ borderdotted: "border-style:dotted",
162
+ // Border radius
163
+ rounded: "border-radius:var(--d-radius,0.5rem)",
164
+ roundedfull: "border-radius:9999px",
165
+ roundednone: "border-radius:0",
166
+ roundedsm: "border-radius:0.25rem",
167
+ roundedlg: "border-radius:0.75rem",
168
+ roundedxl: "border-radius:1rem",
169
+ rounded2xl: "border-radius:1.5rem",
170
+ // Shadows
171
+ shadow: "box-shadow:var(--d-shadow,0 1px 3px rgba(0,0,0,0.1))",
172
+ shadowsm: "box-shadow:0 1px 2px rgba(0,0,0,0.05)",
173
+ shadowmd: "box-shadow:0 4px 6px rgba(0,0,0,0.1)",
174
+ shadowlg: "box-shadow:0 10px 15px rgba(0,0,0,0.1)",
175
+ shadowxl: "box-shadow:0 20px 25px rgba(0,0,0,0.1)",
176
+ shadownone: "box-shadow:none",
177
+ // Transitions
178
+ trans: "transition:all 0.15s ease",
179
+ transnone: "transition:none",
180
+ transcolors: "transition:color,background-color,border-color 0.15s ease",
181
+ transopacity: "transition:opacity 0.15s ease",
182
+ transtransform: "transition:transform 0.15s ease",
183
+ // Object fit
184
+ objcover: "object-fit:cover",
185
+ objcontain: "object-fit:contain",
186
+ objfill: "object-fit:fill",
187
+ objnone: "object-fit:none",
188
+ objscale: "object-fit:scale-down",
189
+ // Object position
190
+ objcenter: "object-position:center",
191
+ objtop: "object-position:top",
192
+ objbottom: "object-position:bottom",
193
+ objleft: "object-position:left",
194
+ objright: "object-position:right",
195
+ // List style
196
+ listnone: "list-style:none",
197
+ listdisc: "list-style-type:disc",
198
+ listdecimal: "list-style-type:decimal",
199
+ // Table
200
+ bordercollapse: "border-collapse:collapse",
201
+ borderseparate: "border-collapse:separate",
202
+ tablelayout: "table-layout:fixed",
203
+ // Aspect ratio
204
+ aspect11: "aspect-ratio:1/1",
205
+ aspect169: "aspect-ratio:16/9",
206
+ aspect43: "aspect-ratio:4/3",
207
+ aspectvideo: "aspect-ratio:16/9",
208
+ aspectsquare: "aspect-ratio:1/1",
209
+ // Z-index
210
+ z0: "z-index:0",
211
+ z10: "z-index:10",
212
+ z20: "z-index:20",
213
+ z30: "z-index:30",
214
+ z40: "z-index:40",
215
+ z50: "z-index:50",
216
+ zauto: "z-index:auto",
217
+ zneg: "z-index:-1",
218
+ // Isolation
219
+ isolate: "isolation:isolate",
220
+ isolateauto: "isolation:auto",
221
+ // Inset
222
+ inset0: "inset:0",
223
+ insetauto: "inset:auto",
224
+ top0: "top:0",
225
+ right0: "right:0",
226
+ bottom0: "bottom:0",
227
+ left0: "left:0",
228
+ // Appearance
229
+ appearancenone: "appearance:none",
230
+ // Outline
231
+ outlinenone: "outline:none",
232
+ ring: "outline:2px solid var(--d-primary,#6366f1);outline-offset:2px",
233
+ ring1: "outline:1px solid var(--d-primary,#6366f1);outline-offset:1px",
234
+ ring2: "outline:2px solid var(--d-primary,#6366f1);outline-offset:2px",
235
+ // Container
236
+ container: "container-type:inline-size",
237
+ // Background
238
+ bgcover: "background-size:cover",
239
+ bgcontain: "background-size:contain",
240
+ bgcenter: "background-position:center",
241
+ bgnorepeat: "background-repeat:no-repeat",
242
+ bgrepeat: "background-repeat:repeat",
243
+ bgfixed: "background-attachment:fixed",
244
+ // Will-change
245
+ willchange: "will-change:transform",
246
+ willchangeauto: "will-change:auto",
247
+ // Backface
248
+ backfacehidden: "backface-visibility:hidden",
249
+ backfacevisible: "backface-visibility:visible",
250
+ // Resize
251
+ resizenone: "resize:none",
252
+ resizex: "resize:horizontal",
253
+ resizey: "resize:vertical",
254
+ resize: "resize:both",
255
+ // Touch action
256
+ touchnone: "touch-action:none",
257
+ touchpan: "touch-action:pan-x pan-y",
258
+ touchmanip: "touch-action:manipulation",
259
+ // Scroll behavior
260
+ scrollsmooth: "scroll-behavior:smooth",
261
+ scrollauto: "scroll-behavior:auto",
262
+ // Snap
263
+ snapx: "scroll-snap-type:x mandatory",
264
+ snapy: "scroll-snap-type:y mandatory",
265
+ snapstart: "scroll-snap-align:start",
266
+ snapcenter: "scroll-snap-align:center",
267
+ snapend: "scroll-snap-align:end",
268
+ // SR only
269
+ sronly: "position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0",
270
+ notsr: "position:static;width:auto;height:auto;padding:0;margin:0;overflow:visible;clip:auto;white-space:normal"
271
+ };
272
+ var SPACING_SCALE = {
273
+ 0: "0",
274
+ 0.5: "0.125rem",
275
+ 1: "0.25rem",
276
+ 1.5: "0.375rem",
277
+ 2: "0.5rem",
278
+ 2.5: "0.625rem",
279
+ 3: "0.75rem",
280
+ 3.5: "0.875rem",
281
+ 4: "1rem",
282
+ 5: "1.25rem",
283
+ 6: "1.5rem",
284
+ 7: "1.75rem",
285
+ 8: "2rem",
286
+ 9: "2.25rem",
287
+ 10: "2.5rem",
288
+ 11: "2.75rem",
289
+ 12: "3rem",
290
+ 14: "3.5rem",
291
+ 16: "4rem",
292
+ 20: "5rem",
293
+ 24: "6rem",
294
+ 28: "7rem",
295
+ 32: "8rem",
296
+ 36: "9rem",
297
+ 40: "10rem",
298
+ 44: "11rem",
299
+ 48: "12rem",
300
+ 52: "13rem",
301
+ 56: "14rem",
302
+ 60: "15rem",
303
+ 64: "16rem",
304
+ 72: "18rem",
305
+ 80: "20rem",
306
+ 96: "24rem"
307
+ };
308
+ var TEXT_SCALE = {
309
+ xs: "font-size:0.75rem;line-height:1rem",
310
+ sm: "font-size:0.875rem;line-height:1.25rem",
311
+ base: "font-size:1rem;line-height:1.5rem",
312
+ lg: "font-size:1.125rem;line-height:1.75rem",
313
+ xl: "font-size:1.25rem;line-height:1.75rem",
314
+ "2xl": "font-size:1.5rem;line-height:2rem",
315
+ "3xl": "font-size:1.875rem;line-height:2.25rem",
316
+ "4xl": "font-size:2.25rem;line-height:2.5rem",
317
+ "5xl": "font-size:3rem;line-height:1",
318
+ "6xl": "font-size:3.75rem;line-height:1"
319
+ };
320
+ var HEADING_SCALE = {
321
+ "1": "font-size:2.25rem;line-height:2.5rem;font-weight:700",
322
+ "2": "font-size:1.875rem;line-height:2.25rem;font-weight:700",
323
+ "3": "font-size:1.5rem;line-height:2rem;font-weight:600",
324
+ "4": "font-size:1.25rem;line-height:1.75rem;font-weight:600",
325
+ "5": "font-size:1.125rem;line-height:1.75rem;font-weight:600",
326
+ "6": "font-size:1rem;line-height:1.5rem;font-weight:600"
327
+ };
328
+ var COLOR_ATOMS = {
329
+ // Background colors
330
+ bgprimary: "background:var(--d-primary)",
331
+ bgsecondary: "background:var(--d-secondary)",
332
+ bgaccent: "background:var(--d-accent)",
333
+ bgsurface: "background:var(--d-surface)",
334
+ bgsurface0: "background:var(--d-surface-0,var(--d-bg))",
335
+ bgsurface1: "background:var(--d-surface-1,var(--d-surface))",
336
+ bgsurface2: "background:var(--d-surface-2,var(--d-surface-raised))",
337
+ bgmuted: "background:var(--d-muted,var(--d-surface))",
338
+ bgbg: "background:var(--d-bg)",
339
+ bgtransparent: "background:transparent",
340
+ bgwhite: "background:#fff",
341
+ bgblack: "background:#000",
342
+ bgsuccess: "background:var(--d-success,#22c55e)",
343
+ bgerror: "background:var(--d-error,#ef4444)",
344
+ bgwarning: "background:var(--d-warning,#f59e0b)",
345
+ bginfo: "background:var(--d-info,#3b82f6)",
346
+ // Foreground/text colors
347
+ fgprimary: "color:var(--d-primary)",
348
+ fgsecondary: "color:var(--d-secondary)",
349
+ fgaccent: "color:var(--d-accent)",
350
+ fgmuted: "color:var(--d-text-muted,var(--d-muted))",
351
+ fgtext: "color:var(--d-text)",
352
+ fgwhite: "color:#fff",
353
+ fgblack: "color:#000",
354
+ fginherit: "color:inherit",
355
+ fgsuccess: "color:var(--d-success,#22c55e)",
356
+ fgerror: "color:var(--d-error,#ef4444)",
357
+ fgwarning: "color:var(--d-warning,#f59e0b)",
358
+ fginfo: "color:var(--d-info,#3b82f6)",
359
+ // Border colors
360
+ bcprimary: "border-color:var(--d-primary)",
361
+ bcsecondary: "border-color:var(--d-secondary)",
362
+ bcaccent: "border-color:var(--d-accent)",
363
+ bcborder: "border-color:var(--d-border)",
364
+ bcmuted: "border-color:var(--d-muted,var(--d-border))",
365
+ bctransparent: "border-color:transparent"
366
+ };
367
+ var GRID_COLS = {
368
+ gc1: "grid-template-columns:repeat(1,minmax(0,1fr))",
369
+ gc2: "grid-template-columns:repeat(2,minmax(0,1fr))",
370
+ gc3: "grid-template-columns:repeat(3,minmax(0,1fr))",
371
+ gc4: "grid-template-columns:repeat(4,minmax(0,1fr))",
372
+ gc5: "grid-template-columns:repeat(5,minmax(0,1fr))",
373
+ gc6: "grid-template-columns:repeat(6,minmax(0,1fr))",
374
+ gc7: "grid-template-columns:repeat(7,minmax(0,1fr))",
375
+ gc8: "grid-template-columns:repeat(8,minmax(0,1fr))",
376
+ gc9: "grid-template-columns:repeat(9,minmax(0,1fr))",
377
+ gc10: "grid-template-columns:repeat(10,minmax(0,1fr))",
378
+ gc11: "grid-template-columns:repeat(11,minmax(0,1fr))",
379
+ gc12: "grid-template-columns:repeat(12,minmax(0,1fr))"
380
+ };
381
+ var GRID_ROWS = {
382
+ gr1: "grid-template-rows:repeat(1,minmax(0,1fr))",
383
+ gr2: "grid-template-rows:repeat(2,minmax(0,1fr))",
384
+ gr3: "grid-template-rows:repeat(3,minmax(0,1fr))",
385
+ gr4: "grid-template-rows:repeat(4,minmax(0,1fr))",
386
+ gr5: "grid-template-rows:repeat(5,minmax(0,1fr))",
387
+ gr6: "grid-template-rows:repeat(6,minmax(0,1fr))"
388
+ };
389
+ var GRID_SPAN = {
390
+ span1: "grid-column:span 1/span 1",
391
+ span2: "grid-column:span 2/span 2",
392
+ span3: "grid-column:span 3/span 3",
393
+ span4: "grid-column:span 4/span 4",
394
+ span5: "grid-column:span 5/span 5",
395
+ span6: "grid-column:span 6/span 6",
396
+ span7: "grid-column:span 7/span 7",
397
+ span8: "grid-column:span 8/span 8",
398
+ span9: "grid-column:span 9/span 9",
399
+ span10: "grid-column:span 10/span 10",
400
+ span11: "grid-column:span 11/span 11",
401
+ span12: "grid-column:span 12/span 12",
402
+ spanfull: "grid-column:1/-1",
403
+ rowspan1: "grid-row:span 1/span 1",
404
+ rowspan2: "grid-row:span 2/span 2",
405
+ rowspan3: "grid-row:span 3/span 3",
406
+ rowspan4: "grid-row:span 4/span 4",
407
+ rowspan5: "grid-row:span 5/span 5",
408
+ rowspan6: "grid-row:span 6/span 6",
409
+ rowspanfull: "grid-row:1/-1"
410
+ };
411
+ function resolveAtomDecl(atom) {
412
+ const name = atom.startsWith("_") ? atom.slice(1) : atom;
413
+ if (DIRECT[name]) return DIRECT[name];
414
+ if (COLOR_ATOMS[name]) return COLOR_ATOMS[name];
415
+ if (GRID_COLS[name]) return GRID_COLS[name];
416
+ if (GRID_ROWS[name]) return GRID_ROWS[name];
417
+ if (GRID_SPAN[name]) return GRID_SPAN[name];
418
+ if (name.startsWith("text")) {
419
+ const size = name.slice(4);
420
+ if (TEXT_SCALE[size]) return TEXT_SCALE[size];
421
+ }
422
+ if (name.startsWith("heading")) {
423
+ const level = name.slice(7);
424
+ if (HEADING_SCALE[level]) return HEADING_SCALE[level];
425
+ }
426
+ const gapMatch = name.match(/^gap(\d+(?:\.\d+)?)$/);
427
+ if (gapMatch) {
428
+ const n = parseFloat(gapMatch[1]);
429
+ const value = SPACING_SCALE[n];
430
+ if (value) return `gap:${value}`;
431
+ }
432
+ const gxMatch = name.match(/^gx(\d+(?:\.\d+)?)$/);
433
+ if (gxMatch) {
434
+ const n = parseFloat(gxMatch[1]);
435
+ const value = SPACING_SCALE[n];
436
+ if (value) return `column-gap:${value}`;
437
+ }
438
+ const gyMatch = name.match(/^gy(\d+(?:\.\d+)?)$/);
439
+ if (gyMatch) {
440
+ const n = parseFloat(gyMatch[1]);
441
+ const value = SPACING_SCALE[n];
442
+ if (value) return `row-gap:${value}`;
443
+ }
444
+ const paddingMatch = name.match(/^p([trblxy]?)(\d+(?:\.\d+)?)$/);
445
+ if (paddingMatch) {
446
+ const [, dir, num] = paddingMatch;
447
+ const n = parseFloat(num);
448
+ const value = SPACING_SCALE[n];
449
+ if (value) {
450
+ if (!dir || dir === "") return `padding:${value}`;
451
+ if (dir === "t") return `padding-top:${value}`;
452
+ if (dir === "r") return `padding-right:${value}`;
453
+ if (dir === "b") return `padding-bottom:${value}`;
454
+ if (dir === "l") return `padding-left:${value}`;
455
+ if (dir === "x") return `padding-inline:${value}`;
456
+ if (dir === "y") return `padding-block:${value}`;
457
+ }
458
+ }
459
+ const marginMatch = name.match(/^m([trblxy]?)(\d+(?:\.\d+)?)$/);
460
+ if (marginMatch) {
461
+ const [, dir, num] = marginMatch;
462
+ const n = parseFloat(num);
463
+ const value = SPACING_SCALE[n];
464
+ if (value) {
465
+ if (!dir || dir === "") return `margin:${value}`;
466
+ if (dir === "t") return `margin-top:${value}`;
467
+ if (dir === "r") return `margin-right:${value}`;
468
+ if (dir === "b") return `margin-bottom:${value}`;
469
+ if (dir === "l") return `margin-left:${value}`;
470
+ if (dir === "x") return `margin-inline:${value}`;
471
+ if (dir === "y") return `margin-block:${value}`;
472
+ }
473
+ }
474
+ const negMarginMatch = name.match(/^-m([trblxy]?)(\d+(?:\.\d+)?)$/);
475
+ if (negMarginMatch) {
476
+ const [, dir, num] = negMarginMatch;
477
+ const n = parseFloat(num);
478
+ const value = SPACING_SCALE[n];
479
+ if (value) {
480
+ const negValue = `-${value}`;
481
+ if (!dir || dir === "") return `margin:${negValue}`;
482
+ if (dir === "t") return `margin-top:${negValue}`;
483
+ if (dir === "r") return `margin-right:${negValue}`;
484
+ if (dir === "b") return `margin-bottom:${negValue}`;
485
+ if (dir === "l") return `margin-left:${negValue}`;
486
+ if (dir === "x") return `margin-inline:${negValue}`;
487
+ if (dir === "y") return `margin-block:${negValue}`;
488
+ }
489
+ }
490
+ const widthMatch = name.match(/^w(\d+(?:\.\d+)?)$/);
491
+ if (widthMatch) {
492
+ const n = parseFloat(widthMatch[1]);
493
+ const value = SPACING_SCALE[n];
494
+ if (value) return `width:${value}`;
495
+ }
496
+ const heightMatch = name.match(/^h(\d+(?:\.\d+)?)$/);
497
+ if (heightMatch) {
498
+ const n = parseFloat(heightMatch[1]);
499
+ const value = SPACING_SCALE[n];
500
+ if (value) return `height:${value}`;
501
+ }
502
+ const minwMatch = name.match(/^minw(\d+(?:\.\d+)?)$/);
503
+ if (minwMatch) {
504
+ const n = parseFloat(minwMatch[1]);
505
+ const value = SPACING_SCALE[n];
506
+ if (value) return `min-width:${value}`;
507
+ }
508
+ const maxwMatch = name.match(/^maxw(\d+(?:\.\d+)?)$/);
509
+ if (maxwMatch) {
510
+ const n = parseFloat(maxwMatch[1]);
511
+ const value = SPACING_SCALE[n];
512
+ if (value) return `max-width:${value}`;
513
+ }
514
+ const minhMatch = name.match(/^minh(\d+(?:\.\d+)?)$/);
515
+ if (minhMatch) {
516
+ const n = parseFloat(minhMatch[1]);
517
+ const value = SPACING_SCALE[n];
518
+ if (value) return `min-height:${value}`;
519
+ }
520
+ const maxhMatch = name.match(/^maxh(\d+(?:\.\d+)?)$/);
521
+ if (maxhMatch) {
522
+ const n = parseFloat(maxhMatch[1]);
523
+ const value = SPACING_SCALE[n];
524
+ if (value) return `max-height:${value}`;
525
+ }
526
+ const bwMatch = name.match(/^bw(\d+)$/);
527
+ if (bwMatch) {
528
+ const n = parseInt(bwMatch[1], 10);
529
+ return `border-width:${n}px`;
530
+ }
531
+ const radiusMatch = name.match(/^r(\d+)$/);
532
+ if (radiusMatch) {
533
+ const n = parseInt(radiusMatch[1], 10);
534
+ return `border-radius:${n}px`;
535
+ }
536
+ const lhMatch = name.match(/^lh(\d+(?:\.\d+)?)$/);
537
+ if (lhMatch) {
538
+ return `line-height:${lhMatch[1]}`;
539
+ }
540
+ const lsMatch = name.match(/^ls(\d+)$/);
541
+ if (lsMatch) {
542
+ const n = parseInt(lsMatch[1], 10);
543
+ return `letter-spacing:${n * 0.025}em`;
544
+ }
545
+ const scaleMatch = name.match(/^scale(\d+)$/);
546
+ if (scaleMatch) {
547
+ const n = parseInt(scaleMatch[1], 10);
548
+ return `transform:scale(${n / 100})`;
549
+ }
550
+ const rotateMatch = name.match(/^rotate(-?\d+)$/);
551
+ if (rotateMatch) {
552
+ return `transform:rotate(${rotateMatch[1]}deg)`;
553
+ }
554
+ const translateXMatch = name.match(/^translatex(-?\d+)$/);
555
+ if (translateXMatch) {
556
+ const n = parseInt(translateXMatch[1], 10);
557
+ const value = SPACING_SCALE[Math.abs(n)] || `${n}px`;
558
+ return `transform:translateX(${n < 0 ? "-" : ""}${value})`;
559
+ }
560
+ const translateYMatch = name.match(/^translatey(-?\d+)$/);
561
+ if (translateYMatch) {
562
+ const n = parseInt(translateYMatch[1], 10);
563
+ const value = SPACING_SCALE[Math.abs(n)] || `${n}px`;
564
+ return `transform:translateY(${n < 0 ? "-" : ""}${value})`;
565
+ }
566
+ const insetMatch = name.match(/^(top|right|bottom|left|inset)(\d+(?:\.\d+)?)$/);
567
+ if (insetMatch) {
568
+ const [, prop, num] = insetMatch;
569
+ const n = parseFloat(num);
570
+ const value = SPACING_SCALE[n];
571
+ if (value) return `${prop}:${value}`;
572
+ }
573
+ return null;
574
+ }
575
+
576
+ // src/runtime.ts
577
+ var injected = /* @__PURE__ */ new Set();
578
+ var BREAKPOINTS = { sm: 640, md: 768, lg: 1024, xl: 1280 };
579
+ var BP_ORDER = ["sm", "md", "lg", "xl"];
580
+ var CQ_WIDTHS = [320, 480, 640, 768, 1024];
581
+ var LAYER_ORDER = "@layer d.base,d.theme,d.atoms,d.user;";
582
+ var atomBuffer = [];
583
+ var bpBuffers = {};
584
+ var cqBuffer = [];
585
+ var flushScheduled = false;
586
+ var styleEl = null;
587
+ var layerEl = null;
588
+ var bpEls = null;
589
+ var cqEl = null;
590
+ function scheduleFlush() {
591
+ if (flushScheduled) return;
592
+ flushScheduled = true;
593
+ if (typeof queueMicrotask === "function") {
594
+ queueMicrotask(flushBuffers);
595
+ } else {
596
+ Promise.resolve().then(flushBuffers);
597
+ }
598
+ }
599
+ function flushBuffers() {
600
+ flushScheduled = false;
601
+ if (atomBuffer.length) {
602
+ const el = getStyleElement();
603
+ if (el) el.textContent = (el.textContent || "") + atomBuffer.join("");
604
+ atomBuffer = [];
605
+ }
606
+ if (Object.keys(bpBuffers).length) {
607
+ const els = ensureBpElements();
608
+ if (els) {
609
+ for (const bp of BP_ORDER) {
610
+ if (bpBuffers[bp]?.length) {
611
+ els[bp].textContent = (els[bp].textContent || "") + bpBuffers[bp].join("");
612
+ bpBuffers[bp] = [];
613
+ }
614
+ }
615
+ }
616
+ bpBuffers = {};
617
+ }
618
+ if (cqBuffer.length) {
619
+ const el = ensureCqElement();
620
+ if (el) el.textContent = (el.textContent || "") + cqBuffer.join("");
621
+ cqBuffer = [];
622
+ }
623
+ }
624
+ function ensureLayerOrder() {
625
+ if (layerEl) return;
626
+ if (typeof document === "undefined") return;
627
+ layerEl = document.createElement("style");
628
+ layerEl.setAttribute("data-decantr-layers", "");
629
+ layerEl.textContent = LAYER_ORDER;
630
+ document.head.prepend(layerEl);
631
+ }
632
+ function getStyleElement() {
633
+ if (!styleEl) {
634
+ if (typeof document === "undefined") return null;
635
+ ensureLayerOrder();
636
+ styleEl = document.createElement("style");
637
+ styleEl.setAttribute("data-decantr", "");
638
+ document.head.appendChild(styleEl);
639
+ }
640
+ return styleEl;
641
+ }
642
+ function ensureBpElements() {
643
+ if (bpEls) return bpEls;
644
+ if (typeof document === "undefined") return null;
645
+ bpEls = {};
646
+ getStyleElement();
647
+ for (const bp of BP_ORDER) {
648
+ const el = document.createElement("style");
649
+ el.setAttribute(`data-decantr-${bp}`, "");
650
+ document.head.appendChild(el);
651
+ bpEls[bp] = el;
652
+ }
653
+ return bpEls;
654
+ }
655
+ function ensureCqElement() {
656
+ if (cqEl) return cqEl;
657
+ if (typeof document === "undefined") return null;
658
+ getStyleElement();
659
+ cqEl = document.createElement("style");
660
+ cqEl.setAttribute("data-decantr-cq", "");
661
+ document.head.appendChild(cqEl);
662
+ return cqEl;
663
+ }
664
+ function inject(className, declaration, escapedName) {
665
+ if (injected.has(className)) return;
666
+ injected.add(className);
667
+ if (typeof document === "undefined") return;
668
+ const sel = escapedName || className;
669
+ atomBuffer.push(`@layer d.atoms{.${sel}{${declaration}}}`);
670
+ scheduleFlush();
671
+ }
672
+ function injectResponsive(className, declaration, bp) {
673
+ if (injected.has(className)) return;
674
+ injected.add(className);
675
+ if (typeof document === "undefined") return;
676
+ const escaped = className.replace(/:/g, "\\:");
677
+ if (!bpBuffers[bp]) bpBuffers[bp] = [];
678
+ bpBuffers[bp].push(`@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}{${declaration}}}}`);
679
+ scheduleFlush();
680
+ }
681
+ function injectPseudo(className, declaration, prefix) {
682
+ if (injected.has(className)) return;
683
+ injected.add(className);
684
+ if (typeof document === "undefined") return;
685
+ const escaped = escapeSelector(className);
686
+ const PSEUDO_MAP = {
687
+ h: "hover",
688
+ f: "focus",
689
+ fv: "focus-visible",
690
+ a: "active",
691
+ fw: "focus-within"
692
+ };
693
+ const pseudo = PSEUDO_MAP[prefix];
694
+ atomBuffer.push(`@layer d.atoms{.${escaped}:${pseudo}{${declaration}}}`);
695
+ scheduleFlush();
696
+ }
697
+ function injectResponsivePseudo(className, declaration, bp, pseudo) {
698
+ if (injected.has(className)) return;
699
+ injected.add(className);
700
+ if (typeof document === "undefined") return;
701
+ const escaped = escapeSelector(className);
702
+ if (!bpBuffers[bp]) bpBuffers[bp] = [];
703
+ bpBuffers[bp].push(`@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}:${pseudo}{${declaration}}}}`);
704
+ scheduleFlush();
705
+ }
706
+ function injectContainer(className, declaration, width) {
707
+ if (injected.has(className)) return;
708
+ injected.add(className);
709
+ if (typeof document === "undefined") return;
710
+ const escaped = className.replace(/:/g, "\\:");
711
+ cqBuffer.push(`@layer d.atoms{@container(min-width:${width}px){.${escaped}{${declaration}}}}`);
712
+ scheduleFlush();
713
+ }
714
+ function injectGroupPeer(className, declaration, prefix) {
715
+ if (injected.has(className)) return;
716
+ injected.add(className);
717
+ if (typeof document === "undefined") return;
718
+ const escaped = escapeSelector(className);
719
+ const GP_STATE = {
720
+ gh: ["group", "hover"],
721
+ gf: ["group", "focus-within"],
722
+ ga: ["group", "active"],
723
+ ph: ["peer", "hover"],
724
+ pf: ["peer", "focus"],
725
+ pa: ["peer", "active"]
726
+ };
727
+ const [kind, state] = GP_STATE[prefix];
728
+ const combinator = kind === "group" ? " " : " ~ ";
729
+ atomBuffer.push(`@layer d.atoms{.d-${kind}:${state}${combinator}.${escaped}{${declaration}}}`);
730
+ scheduleFlush();
731
+ }
732
+ function injectMediaQuery(className, declaration, query) {
733
+ if (injected.has(className)) return;
734
+ injected.add(className);
735
+ if (typeof document === "undefined") return;
736
+ const escaped = className.replace(/:/g, "\\:");
737
+ atomBuffer.push(`@layer d.atoms{@media${query}{.${escaped}{${declaration}}}}`);
738
+ scheduleFlush();
739
+ }
740
+ function escapeSelector(className) {
741
+ return className.replace(/:/g, "\\:").replace(/\//g, "\\/").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/#/g, "\\#").replace(/%/g, "\\%").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/,/g, "\\,").replace(/\+/g, "\\+");
742
+ }
743
+ function extractCSS() {
744
+ flushBuffers();
745
+ let css2 = layerEl ? layerEl.textContent || "" : "";
746
+ css2 += styleEl ? styleEl.textContent || "" : "";
747
+ if (bpEls) {
748
+ for (const bp of BP_ORDER) {
749
+ if (bpEls[bp]) css2 += bpEls[bp].textContent || "";
750
+ }
751
+ }
752
+ if (cqEl) css2 += cqEl.textContent || "";
753
+ return css2;
754
+ }
755
+ function getInjectedClasses() {
756
+ return new Set(injected);
757
+ }
758
+ function reset() {
759
+ injected.clear();
760
+ atomBuffer = [];
761
+ bpBuffers = {};
762
+ cqBuffer = [];
763
+ flushScheduled = false;
764
+ if (layerEl) layerEl.textContent = LAYER_ORDER;
765
+ if (styleEl) styleEl.textContent = "";
766
+ if (bpEls) {
767
+ for (const bp of BP_ORDER) {
768
+ if (bpEls[bp]) bpEls[bp].textContent = "";
769
+ }
770
+ }
771
+ if (cqEl) cqEl.textContent = "";
772
+ }
773
+
774
+ // src/css.ts
775
+ var customAtoms = /* @__PURE__ */ new Map();
776
+ var BP_RE = /^_(sm|md|lg|xl):(.+)$/;
777
+ var CQ_RE = /^_cq(\d+):(.+)$/;
778
+ var GP_RE = /^_(gh|gf|ga|ph|pf|pa):(.+)$/;
779
+ var PSEUDO_RE = /^_(h|f|fv|a|fw):(.+)$/;
780
+ var MOTION_RE = /^_(motionSafe|motionReduce):(.+)$/;
781
+ var ALPHA_RE = /^(_[a-zA-Z0-9]+)\/(\d+)$/;
782
+ var ARB_RE = /^_([a-zA-Z]+)\[([^\]]+)\]$/;
783
+ var MOTION_QUERIES = {
784
+ motionSafe: "(prefers-reduced-motion: no-preference)",
785
+ motionReduce: "(prefers-reduced-motion: reduce)"
786
+ };
787
+ var PSEUDO_NAMES = {
788
+ h: "hover",
789
+ f: "focus",
790
+ fv: "focus-visible",
791
+ a: "active",
792
+ fw: "focus-within"
793
+ };
794
+ var CQ_SET = new Set(CQ_WIDTHS);
795
+ var ARB_PROPS = {
796
+ w: "width",
797
+ h: "height",
798
+ mw: "max-width",
799
+ mh: "max-height",
800
+ minw: "min-width",
801
+ minh: "min-height",
802
+ p: "padding",
803
+ pt: "padding-top",
804
+ pr: "padding-right",
805
+ pb: "padding-bottom",
806
+ pl: "padding-left",
807
+ px: "padding-inline",
808
+ py: "padding-block",
809
+ m: "margin",
810
+ mt: "margin-top",
811
+ mr: "margin-right",
812
+ mb: "margin-bottom",
813
+ ml: "margin-left",
814
+ mx: "margin-inline",
815
+ my: "margin-block",
816
+ gap: "gap",
817
+ gx: "column-gap",
818
+ gy: "row-gap",
819
+ t: "font-size",
820
+ fs: "font-size",
821
+ lh: "line-height",
822
+ fw: "font-weight",
823
+ ls: "letter-spacing",
824
+ r: "border-radius",
825
+ bg: "background",
826
+ fg: "color",
827
+ bc: "border-color",
828
+ bw: "border-width",
829
+ bt: "border-top",
830
+ bb: "border-bottom",
831
+ br: "border-right",
832
+ bl: "border-left",
833
+ z: "z-index",
834
+ op: "opacity",
835
+ top: "top",
836
+ right: "right",
837
+ bottom: "bottom",
838
+ left: "left",
839
+ inset: "inset",
840
+ shadow: "box-shadow",
841
+ bf: "backdrop-filter",
842
+ outline: "outline",
843
+ trans: "transition",
844
+ object: "object-fit",
845
+ gc: "grid-template-columns",
846
+ gr: "grid-template-rows"
847
+ };
848
+ function sanitizeArbValue(val) {
849
+ let safe = val.replace(/[{}<>;]/g, "");
850
+ safe = safe.replace(/url\s*\(/gi, "");
851
+ return safe;
852
+ }
853
+ function resolveAtom(atomPart) {
854
+ const custom = customAtoms.get(atomPart);
855
+ if (custom) return { className: atomPart, decl: custom };
856
+ const decl = resolveAtomDecl(atomPart);
857
+ if (decl) return { className: atomPart, decl };
858
+ const alphaMatch = atomPart.match(ALPHA_RE);
859
+ if (alphaMatch) {
860
+ const [, base, alphaStr] = alphaMatch;
861
+ const baseDecl = customAtoms.get(base) || resolveAtomDecl(base);
862
+ if (baseDecl) {
863
+ const alpha = Number(alphaStr);
864
+ if (alpha >= 0 && alpha <= 100) {
865
+ const colorMatch = baseDecl.match(/^(background|color|border-color):(var\(--[^)]+\))$/);
866
+ if (colorMatch) {
867
+ const [, prop, varRef] = colorMatch;
868
+ return {
869
+ className: atomPart,
870
+ decl: `${prop}:color-mix(in srgb,${varRef} ${alpha}%,transparent)`
871
+ };
872
+ }
873
+ }
874
+ }
875
+ return null;
876
+ }
877
+ const arbMatch = atomPart.match(ARB_RE);
878
+ if (arbMatch) {
879
+ const [, propPrefix, rawValue] = arbMatch;
880
+ const cssProp = ARB_PROPS[propPrefix] || ARB_PROPS[propPrefix.toLowerCase()];
881
+ if (cssProp) {
882
+ const value = sanitizeArbValue(rawValue.replace(/_/g, " "));
883
+ if (!value) return null;
884
+ return { className: atomPart, decl: `${cssProp}:${value}` };
885
+ }
886
+ return null;
887
+ }
888
+ return null;
889
+ }
890
+ function escapeClass(cls) {
891
+ return cls.replace(/:/g, "\\:").replace(/\//g, "\\/").replace(/\[/g, "\\[").replace(/\]/g, "\\]").replace(/#/g, "\\#").replace(/%/g, "\\%").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/,/g, "\\,").replace(/\+/g, "\\+");
892
+ }
893
+ function css(...classes) {
894
+ const result = [];
895
+ for (let i = 0; i < classes.length; i++) {
896
+ const cls = classes[i];
897
+ if (!cls) continue;
898
+ const parts = cls.split(/\s+/);
899
+ for (const part of parts) {
900
+ if (!part) continue;
901
+ if (part === "_group") {
902
+ result.push("d-group");
903
+ continue;
904
+ }
905
+ if (part === "_peer") {
906
+ result.push("d-peer");
907
+ continue;
908
+ }
909
+ if (part === "_prose") {
910
+ result.push("d-prose");
911
+ continue;
912
+ }
913
+ if (part === "_divideY") {
914
+ result.push("d-divide-y");
915
+ continue;
916
+ }
917
+ if (part === "_divideX") {
918
+ result.push("d-divide-x");
919
+ continue;
920
+ }
921
+ const motionMatch = part.match(MOTION_RE);
922
+ if (motionMatch) {
923
+ const [, motionPrefix, innerAtom] = motionMatch;
924
+ const resolved2 = resolveAtom(`_${innerAtom}`);
925
+ if (resolved2) {
926
+ injectMediaQuery(part, resolved2.decl, MOTION_QUERIES[motionPrefix]);
927
+ }
928
+ result.push(part);
929
+ continue;
930
+ }
931
+ const bpMatch = part.match(BP_RE);
932
+ if (bpMatch) {
933
+ const [, bp, innerAtom] = bpMatch;
934
+ const pseudoInner = innerAtom.match(/^(h|f|fv|a|fw):(.+)$/);
935
+ if (pseudoInner) {
936
+ const [, pseudoPrefix, atomName] = pseudoInner;
937
+ const resolved3 = resolveAtom(`_${atomName}`);
938
+ if (resolved3) {
939
+ injectResponsivePseudo(part, resolved3.decl, bp, PSEUDO_NAMES[pseudoPrefix]);
940
+ }
941
+ result.push(part);
942
+ continue;
943
+ }
944
+ const resolved2 = resolveAtom(`_${innerAtom}`);
945
+ if (resolved2) {
946
+ injectResponsive(part, resolved2.decl, bp);
947
+ }
948
+ result.push(part);
949
+ continue;
950
+ }
951
+ const cqMatch = part.match(CQ_RE);
952
+ if (cqMatch) {
953
+ const width = Number(cqMatch[1]);
954
+ const innerAtom = cqMatch[2];
955
+ if (CQ_SET.has(width)) {
956
+ const resolved2 = resolveAtom(`_${innerAtom}`);
957
+ if (resolved2) {
958
+ injectContainer(part, resolved2.decl, width);
959
+ }
960
+ }
961
+ result.push(part);
962
+ continue;
963
+ }
964
+ const gpMatch = part.match(GP_RE);
965
+ if (gpMatch) {
966
+ const [, prefix, atomName] = gpMatch;
967
+ const resolved2 = resolveAtom(`_${atomName}`);
968
+ if (resolved2) {
969
+ injectGroupPeer(part, resolved2.decl, prefix);
970
+ }
971
+ result.push(part);
972
+ continue;
973
+ }
974
+ const pseudoMatch = part.match(PSEUDO_RE);
975
+ if (pseudoMatch) {
976
+ const [, prefix, innerAtom] = pseudoMatch;
977
+ const resolved2 = resolveAtom(`_${innerAtom}`);
978
+ if (resolved2) {
979
+ injectPseudo(part, resolved2.decl, prefix);
980
+ }
981
+ result.push(part);
982
+ continue;
983
+ }
984
+ const resolved = resolveAtom(part);
985
+ if (resolved) {
986
+ const needsEscape = /[/\[\]#%(),+]/.test(resolved.className);
987
+ inject(resolved.className, resolved.decl, needsEscape ? escapeClass(resolved.className) : void 0);
988
+ result.push(part);
989
+ } else {
990
+ result.push(part);
991
+ }
992
+ }
993
+ }
994
+ return result.join(" ");
995
+ }
996
+ function define(name, declaration) {
997
+ customAtoms.set(name, declaration);
998
+ }
999
+ export {
1000
+ BREAKPOINTS,
1001
+ CQ_WIDTHS,
1002
+ css,
1003
+ define,
1004
+ extractCSS,
1005
+ getInjectedClasses,
1006
+ inject,
1007
+ injectContainer,
1008
+ injectGroupPeer,
1009
+ injectMediaQuery,
1010
+ injectPseudo,
1011
+ injectResponsive,
1012
+ reset,
1013
+ resolveAtomDecl
1014
+ };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@decantr/css",
3
+ "version": "1.0.0",
4
+ "description": "Framework-agnostic CSS atoms runtime for Decantr projects",
5
+ "author": "Decantr",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/decantr/decantr-monorepo",
9
+ "directory": "packages/css"
10
+ },
11
+ "homepage": "https://github.com/decantr/decantr-monorepo/tree/main/packages/css",
12
+ "type": "module",
13
+ "main": "./dist/index.js",
14
+ "types": "./dist/index.d.ts",
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/index.js",
18
+ "types": "./dist/index.d.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsup src/index.ts --format esm --dts",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest",
28
+ "lint": "tsc --noEmit"
29
+ },
30
+ "keywords": [
31
+ "decantr",
32
+ "css",
33
+ "atoms",
34
+ "utility-css"
35
+ ],
36
+ "license": "MIT",
37
+ "devDependencies": {
38
+ "jsdom": "^26.0.0",
39
+ "tsup": "^8.0.0",
40
+ "typescript": "^5.0.0",
41
+ "vitest": "^3.0.0"
42
+ }
43
+ }