@kbach/react 0.6.25 → 0.6.28

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.
@@ -40,3259 +40,26 @@ __export(jsx_runtime_exports, {
40
40
  module.exports = __toCommonJS(jsx_runtime_exports);
41
41
  var import_jsx_runtime = require("react/jsx-runtime");
42
42
  var import_react4 = require("react");
43
-
44
- // src/core/theme.ts
45
- var defaultColors = {
46
- transparent: "transparent",
47
- current: "currentColor",
48
- black: "#000000",
49
- white: "#ffffff",
50
- slate: {
51
- 1: "#f8fafc",
52
- 2: "#f1f5f9",
53
- 3: "#e2e8f0",
54
- 4: "#cbd5e1",
55
- 5: "#94a3b8",
56
- 6: "#64748b",
57
- 7: "#475569",
58
- 8: "#334155",
59
- 9: "#1e293b",
60
- 10: "#0f172a",
61
- 11: "#020617",
62
- 12: "#01020a"
63
- },
64
- gray: {
65
- 1: "#f9fafb",
66
- 2: "#f3f4f6",
67
- 3: "#e5e7eb",
68
- 4: "#d1d5db",
69
- 5: "#9ca3af",
70
- 6: "#6b7280",
71
- 7: "#4b5563",
72
- 8: "#374151",
73
- 9: "#1f2937",
74
- 10: "#111827",
75
- 11: "#030712",
76
- 12: "#020409"
77
- },
78
- zinc: {
79
- 1: "#fafafa",
80
- 2: "#f4f4f5",
81
- 3: "#e4e4e7",
82
- 4: "#d4d4d8",
83
- 5: "#a1a1aa",
84
- 6: "#71717a",
85
- 7: "#52525b",
86
- 8: "#3f3f46",
87
- 9: "#27272a",
88
- 10: "#18181b",
89
- 11: "#09090b",
90
- 12: "#050506"
91
- },
92
- neutral: {
93
- 1: "#fafafa",
94
- 2: "#f5f5f5",
95
- 3: "#e5e5e5",
96
- 4: "#d4d4d4",
97
- 5: "#a3a3a3",
98
- 6: "#737373",
99
- 7: "#525252",
100
- 8: "#404040",
101
- 9: "#262626",
102
- 10: "#171717",
103
- 11: "#0a0a0a",
104
- 12: "#050505"
105
- },
106
- stone: {
107
- 1: "#fafaf9",
108
- 2: "#f5f5f4",
109
- 3: "#e7e5e4",
110
- 4: "#d6d3d1",
111
- 5: "#a8a29e",
112
- 6: "#78716c",
113
- 7: "#57534e",
114
- 8: "#44403c",
115
- 9: "#292524",
116
- 10: "#1c1917",
117
- 11: "#0c0a09",
118
- 12: "#070605"
119
- },
120
- red: {
121
- 1: "#fef2f2",
122
- 2: "#fee2e2",
123
- 3: "#fecaca",
124
- 4: "#fca5a5",
125
- 5: "#f87171",
126
- 6: "#ef4444",
127
- 7: "#dc2626",
128
- 8: "#b91c1c",
129
- 9: "#991b1b",
130
- 10: "#7f1d1d",
131
- 11: "#450a0a",
132
- 12: "#280606"
133
- },
134
- orange: {
135
- 1: "#fff7ed",
136
- 2: "#ffedd5",
137
- 3: "#fed7aa",
138
- 4: "#fdba74",
139
- 5: "#fb923c",
140
- 6: "#f97316",
141
- 7: "#ea580c",
142
- 8: "#c2410c",
143
- 9: "#9a3412",
144
- 10: "#7c2d12",
145
- 11: "#431407",
146
- 12: "#270c04"
147
- },
148
- amber: {
149
- 1: "#fffbeb",
150
- 2: "#fef3c7",
151
- 3: "#fde68a",
152
- 4: "#fcd34d",
153
- 5: "#fbbf24",
154
- 6: "#f59e0b",
155
- 7: "#d97706",
156
- 8: "#b45309",
157
- 9: "#92400e",
158
- 10: "#78350f",
159
- 11: "#451a03",
160
- 12: "#291002"
161
- },
162
- yellow: {
163
- 1: "#fefce8",
164
- 2: "#fef9c3",
165
- 3: "#fef08a",
166
- 4: "#fde047",
167
- 5: "#facc15",
168
- 6: "#eab308",
169
- 7: "#ca8a04",
170
- 8: "#a16207",
171
- 9: "#854d0e",
172
- 10: "#713f12",
173
- 11: "#422006",
174
- 12: "#271304"
175
- },
176
- lime: {
177
- 1: "#f7fee7",
178
- 2: "#ecfccb",
179
- 3: "#d9f99d",
180
- 4: "#bef264",
181
- 5: "#a3e635",
182
- 6: "#84cc16",
183
- 7: "#65a30d",
184
- 8: "#4d7c0f",
185
- 9: "#3f6212",
186
- 10: "#365314",
187
- 11: "#1a2e05",
188
- 12: "#0f1b03"
189
- },
190
- green: {
191
- 1: "#f0fdf4",
192
- 2: "#dcfce7",
193
- 3: "#bbf7d0",
194
- 4: "#86efac",
195
- 5: "#4ade80",
196
- 6: "#22c55e",
197
- 7: "#16a34a",
198
- 8: "#15803d",
199
- 9: "#166534",
200
- 10: "#14532d",
201
- 11: "#052e16",
202
- 12: "#031b0d"
203
- },
204
- emerald: {
205
- 1: "#ecfdf5",
206
- 2: "#d1fae5",
207
- 3: "#a7f3d0",
208
- 4: "#6ee7b7",
209
- 5: "#34d399",
210
- 6: "#10b981",
211
- 7: "#059669",
212
- 8: "#047857",
213
- 9: "#065f46",
214
- 10: "#064e3b",
215
- 11: "#022c22",
216
- 12: "#011a14"
217
- },
218
- teal: {
219
- 1: "#f0fdfa",
220
- 2: "#ccfbf1",
221
- 3: "#99f6e4",
222
- 4: "#5eead4",
223
- 5: "#2dd4bf",
224
- 6: "#14b8a6",
225
- 7: "#0d9488",
226
- 8: "#0f766e",
227
- 9: "#115e59",
228
- 10: "#134e4a",
229
- 11: "#042f2e",
230
- 12: "#021c1b"
231
- },
232
- cyan: {
233
- 1: "#ecfeff",
234
- 2: "#cffafe",
235
- 3: "#a5f3fc",
236
- 4: "#67e8f9",
237
- 5: "#22d3ee",
238
- 6: "#06b6d4",
239
- 7: "#0891b2",
240
- 8: "#0e7490",
241
- 9: "#155e75",
242
- 10: "#164e63",
243
- 11: "#083344",
244
- 12: "#041e28"
245
- },
246
- sky: {
247
- 1: "#f0f9ff",
248
- 2: "#e0f2fe",
249
- 3: "#bae6fd",
250
- 4: "#7dd3fc",
251
- 5: "#38bdf8",
252
- 6: "#0ea5e9",
253
- 7: "#0284c7",
254
- 8: "#0369a1",
255
- 9: "#075985",
256
- 10: "#0c4a6e",
257
- 11: "#082f49",
258
- 12: "#041b2b"
259
- },
260
- blue: {
261
- 1: "#eff6ff",
262
- 2: "#dbeafe",
263
- 3: "#bfdbfe",
264
- 4: "#93c5fd",
265
- 5: "#60a5fa",
266
- 6: "#3b82f6",
267
- 7: "#2563eb",
268
- 8: "#1d4ed8",
269
- 9: "#1e40af",
270
- 10: "#1e3a8a",
271
- 11: "#172554",
272
- 12: "#0d1633"
273
- },
274
- indigo: {
275
- 1: "#eef2ff",
276
- 2: "#e0e7ff",
277
- 3: "#c7d2fe",
278
- 4: "#a5b4fc",
279
- 5: "#818cf8",
280
- 6: "#6366f1",
281
- 7: "#4f46e5",
282
- 8: "#4338ca",
283
- 9: "#3730a3",
284
- 10: "#312e81",
285
- 11: "#1e1b4b",
286
- 12: "#12102d"
287
- },
288
- violet: {
289
- 1: "#f5f3ff",
290
- 2: "#ede9fe",
291
- 3: "#ddd6fe",
292
- 4: "#c4b5fd",
293
- 5: "#a78bfa",
294
- 6: "#8b5cf6",
295
- 7: "#7c3aed",
296
- 8: "#6d28d9",
297
- 9: "#5b21b6",
298
- 10: "#4c1d95",
299
- 11: "#2e1065",
300
- 12: "#1c0a3d"
301
- },
302
- purple: {
303
- 1: "#faf5ff",
304
- 2: "#f3e8ff",
305
- 3: "#e9d5ff",
306
- 4: "#d8b4fe",
307
- 5: "#c084fc",
308
- 6: "#a855f7",
309
- 7: "#9333ea",
310
- 8: "#7e22ce",
311
- 9: "#6b21a8",
312
- 10: "#581c87",
313
- 11: "#3b0764",
314
- 12: "#23043c"
315
- },
316
- fuchsia: {
317
- 1: "#fdf4ff",
318
- 2: "#fae8ff",
319
- 3: "#f5d0fe",
320
- 4: "#f0abfc",
321
- 5: "#e879f9",
322
- 6: "#d946ef",
323
- 7: "#c026d3",
324
- 8: "#a21caf",
325
- 9: "#86198f",
326
- 10: "#701a75",
327
- 11: "#4a044e",
328
- 12: "#2d022f"
329
- },
330
- pink: {
331
- 1: "#fdf2f8",
332
- 2: "#fce7f3",
333
- 3: "#fbcfe8",
334
- 4: "#f9a8d4",
335
- 5: "#f472b6",
336
- 6: "#ec4899",
337
- 7: "#db2777",
338
- 8: "#be185d",
339
- 9: "#9d174d",
340
- 10: "#831843",
341
- 11: "#500724",
342
- 12: "#300415"
343
- },
344
- rose: {
345
- 1: "#fff1f2",
346
- 2: "#ffe4e6",
347
- 3: "#fecdd3",
348
- 4: "#fda4af",
349
- 5: "#fb7185",
350
- 6: "#f43f5e",
351
- 7: "#e11d48",
352
- 8: "#be123c",
353
- 9: "#9f1239",
354
- 10: "#881337",
355
- 11: "#4c0519",
356
- 12: "#2d030e"
357
- }
358
- };
359
- var defaultTheme = {
360
- colors: defaultColors,
361
- // 1 unit = 4px
362
- spacing: {
363
- px: 1,
364
- 0: 0,
365
- "0.5": 2,
366
- 1: 4,
367
- "1.5": 6,
368
- 2: 8,
369
- "2.5": 10,
370
- 3: 12,
371
- "3.5": 14,
372
- 4: 16,
373
- 5: 20,
374
- 6: 24,
375
- 7: 28,
376
- 8: 32,
377
- 9: 36,
378
- 10: 40,
379
- 11: 44,
380
- 12: 48,
381
- 14: 56,
382
- 16: 64,
383
- 20: 80,
384
- 24: 96,
385
- 28: 112,
386
- 32: 128,
387
- 36: 144,
388
- 40: 160,
389
- 44: 176,
390
- 48: 192,
391
- 52: 208,
392
- 56: 224,
393
- 60: 240,
394
- 64: 256,
395
- 72: 288,
396
- 80: 320,
397
- 96: 384,
398
- auto: "auto",
399
- full: "100%",
400
- "1/2": "50%",
401
- "1/3": "33.333333%",
402
- "2/3": "66.666667%",
403
- "1/4": "25%",
404
- "3/4": "75%",
405
- // Dynamic viewport unit — see the comment on the 'screen' standalone utilities
406
- // in utilities.ts for why dvh beats vh on mobile. Used by h-screen (w-screen
407
- // has its own standalone entry so it never reaches this spacing lookup).
408
- screen: "100dvh",
409
- min: "min-content",
410
- max: "max-content",
411
- fit: "fit-content"
412
- },
413
- fontSize: {
414
- xs: 12,
415
- sm: 14,
416
- base: 16,
417
- lg: 18,
418
- xl: 20,
419
- "2xl": 24,
420
- "3xl": 30,
421
- "4xl": 36,
422
- "5xl": 48,
423
- "6xl": 60,
424
- "7xl": 72,
425
- "8xl": 96,
426
- "9xl": 128
427
- },
428
- fontFamily: {
429
- sans: "System",
430
- mono: "Courier New",
431
- serif: "Georgia"
432
- },
433
- fontWeight: {
434
- thin: "100",
435
- extralight: "200",
436
- light: "300",
437
- normal: "400",
438
- medium: "500",
439
- semibold: "600",
440
- bold: "700",
441
- extrabold: "800",
442
- black: "900"
443
- },
444
- borderRadius: {
445
- none: 0,
446
- sm: 2,
447
- DEFAULT: 4,
448
- md: 6,
449
- lg: 8,
450
- xl: 12,
451
- "2xl": 16,
452
- "3xl": 24,
453
- full: 9999
454
- },
455
- borderWidth: {
456
- DEFAULT: 1,
457
- 0: 0,
458
- 2: 2,
459
- 4: 4,
460
- 8: 8
461
- },
462
- opacity: {
463
- 0: 0,
464
- 5: 0.05,
465
- 10: 0.1,
466
- 15: 0.15,
467
- 20: 0.2,
468
- 25: 0.25,
469
- 30: 0.3,
470
- 40: 0.4,
471
- 50: 0.5,
472
- 60: 0.6,
473
- 70: 0.7,
474
- 75: 0.75,
475
- 80: 0.8,
476
- 90: 0.9,
477
- 95: 0.95,
478
- 100: 1
479
- },
480
- lineHeight: {
481
- none: 1,
482
- tight: 1.25,
483
- snug: 1.375,
484
- normal: 1.5,
485
- relaxed: 1.625,
486
- loose: 2,
487
- // Pixel values stored as strings; styleValueToCSS passes them through, toNativeValue strips the unit
488
- 3: "12px",
489
- 4: "16px",
490
- 5: "20px",
491
- 6: "24px",
492
- 7: "28px",
493
- 8: "32px",
494
- 9: "36px",
495
- 10: "40px"
496
- },
497
- letterSpacing: {
498
- tighter: -0.8,
499
- tight: -0.4,
500
- normal: 0,
501
- wide: 0.4,
502
- wider: 0.8,
503
- widest: 1.6
504
- },
505
- zIndex: {
506
- auto: "auto",
507
- 0: 0,
508
- 10: 10,
509
- 20: 20,
510
- 30: 30,
511
- 40: 40,
512
- 50: 50
513
- },
514
- flex: {
515
- 1: 1,
516
- auto: "auto",
517
- // CSS: flex: auto = 1 1 auto; native: mapped to 1 in resolver
518
- initial: "initial",
519
- // CSS: flex: initial = 0 1 auto; native: mapped to 1
520
- none: "none"
521
- // CSS: flex: none = 0 0 auto; native: mapped to 0
522
- },
523
- shadow: {
524
- sm: {
525
- shadowColor: "#000",
526
- shadowOffset: { width: 0, height: 1 },
527
- shadowOpacity: 0.05,
528
- shadowRadius: 2,
529
- elevation: 1
530
- },
531
- DEFAULT: {
532
- shadowColor: "#000",
533
- shadowOffset: { width: 0, height: 2 },
534
- shadowOpacity: 0.1,
535
- shadowRadius: 4,
536
- elevation: 2
537
- },
538
- md: {
539
- shadowColor: "#000",
540
- shadowOffset: { width: 0, height: 4 },
541
- shadowOpacity: 0.1,
542
- shadowRadius: 8,
543
- elevation: 3
544
- },
545
- lg: {
546
- shadowColor: "#000",
547
- shadowOffset: { width: 0, height: 8 },
548
- shadowOpacity: 0.1,
549
- shadowRadius: 15,
550
- elevation: 4
551
- },
552
- xl: {
553
- shadowColor: "#000",
554
- shadowOffset: { width: 0, height: 16 },
555
- shadowOpacity: 0.1,
556
- shadowRadius: 24,
557
- elevation: 6
558
- },
559
- "2xl": {
560
- shadowColor: "#000",
561
- shadowOffset: { width: 0, height: 24 },
562
- shadowOpacity: 0.25,
563
- shadowRadius: 48,
564
- elevation: 8
565
- },
566
- none: {
567
- shadowColor: "transparent",
568
- shadowOffset: { width: 0, height: 0 },
569
- shadowOpacity: 0,
570
- shadowRadius: 0,
571
- elevation: 0
572
- }
573
- },
574
- screens: {
575
- sm: 576,
576
- // small tablets / large phones (landscape)
577
- md: 768,
578
- // tablets (iPad and up)
579
- lg: 1024,
580
- // large tablets (iPad Pro)
581
- xl: 1280,
582
- // desktop
583
- "2xl": 1536
584
- },
585
- // Empty by default — the 4 built-in presets (spin/ping/pulse/bounce) are handled
586
- // directly in the `animate` resolver, not through this theme table. This exists so
587
- // user-defined ones (kbach.config.js theme.extend.keyframes/animation) merge in
588
- // alongside them without needing to redeclare the built-ins.
589
- keyframes: {},
590
- animation: {}
591
- };
592
-
593
- // src/core/reset.ts
594
- var RESET_STYLE_ID = "kbach-reset";
595
- var BASE_RESET = [
596
- // border-style: solid means border-N utilities show a visible border without an extra border-solid class.
597
- // border-width: 0 keeps all elements borderless by default.
598
- "*, *::before, *::after { box-sizing: border-box; border-width: 0; border-style: solid; border-color: currentColor; }",
599
- "body { margin: 0; padding: 0; }",
600
- "h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; font-weight: inherit; }",
601
- "p { margin: 0; }",
602
- "a { color: inherit; text-decoration: none; }",
603
- "ul, ol { margin: 0; padding: 0; list-style: none; }",
604
- "img, video, svg { display: block; max-width: 100%; }",
605
- // appearance: none is deliberately NOT applied to checkbox/radio/select below —
606
- // stripping it hides their native checkmark/arrow with nothing rendered in its
607
- // place, leaving an invisible checkbox or an arrow-less <select> that looks like
608
- // plain text. Text-like inputs, textarea, and button don't have that problem
609
- // (their native chrome is just a skin around content utilities can fully
610
- // restyle), so they keep the blank-canvas treatment.
611
- "input:not([type='checkbox']):not([type='radio']), textarea { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; line-height: inherit; }",
612
- // Native checkbox/radio/range still get typography + spacing normalized, and
613
- // accent-color re-themes their native indicator to the current text color
614
- // instead of the browser/OS default blue, so they stay on-brand without
615
- // needing to be rebuilt from scratch.
616
- "input[type='checkbox'], input[type='radio'], input[type='range'] { margin: 0; font: inherit; accent-color: currentColor; }",
617
- // select keeps its native chrome (border/background/arrow are all part of the
618
- // same OS-drawn widget that appearance: none would blank out) — only typography
619
- // and spacing are normalized so it still matches surrounding text.
620
- "select { margin: 0; font: inherit; color: inherit; line-height: inherit; }",
621
- "button { appearance: none; -webkit-appearance: none; background: transparent; padding: 0; margin: 0; font: inherit; color: inherit; cursor: pointer; line-height: inherit; text-align: inherit; }",
622
- "button, [role='button'] { cursor: pointer; }",
623
- ":disabled { cursor: default; }",
624
- "textarea { resize: vertical; }",
625
- // Firefox renders placeholders at ~54% opacity by default; every other browser uses 1 —
626
- // normalize to 1 so placeholder color is consistent and fully controlled by the placeholder: modifier.
627
- "::placeholder { opacity: 1; }",
628
- "input[type='number']::-webkit-inner-spin-button, input[type='number']::-webkit-outer-spin-button { margin: 0; }",
629
- "input[type='search']::-webkit-search-decoration, input[type='search']::-webkit-search-cancel-button { -webkit-appearance: none; }",
630
- "fieldset { padding: 0; margin: 0; }",
631
- "table { border-collapse: collapse; border-spacing: 0; }"
632
- ].join("\n");
633
-
634
- // src/core/cache.ts
635
- var LRUCache = class {
636
- constructor(capacity = 1e4, onEvict) {
637
- this.capacity = capacity;
638
- if (capacity <= 0) throw new Error("LRUCache: capacity must be a positive integer");
639
- this.cache = /* @__PURE__ */ new Map();
640
- this.onEvict = onEvict;
641
- }
642
- get(key) {
643
- if (!this.cache.has(key)) return void 0;
644
- const value = this.cache.get(key);
645
- this.cache.delete(key);
646
- this.cache.set(key, value);
647
- return value;
648
- }
649
- set(key, value) {
650
- if (this.cache.has(key)) {
651
- this.cache.delete(key);
652
- } else if (this.cache.size >= this.capacity) {
653
- const oldestKey = this.cache.keys().next().value;
654
- const oldestValue = this.cache.get(oldestKey);
655
- this.cache.delete(oldestKey);
656
- this.onEvict?.(oldestKey, oldestValue);
657
- }
658
- this.cache.set(key, value);
659
- return this;
660
- }
661
- has(key) {
662
- return this.cache.has(key);
663
- }
664
- delete(key) {
665
- return this.cache.delete(key);
666
- }
667
- clear() {
668
- this.cache.clear();
669
- }
670
- get size() {
671
- return this.cache.size;
672
- }
673
- };
674
-
675
- // src/core/platform.ts
676
- var isWeb = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
677
- var isNative = !isWeb && (typeof globalThis.HermesInternal !== "undefined" || typeof globalThis.__fbBatchedBridge !== "undefined" || typeof navigator !== "undefined" && navigator.product === "ReactNative" || typeof globalThis.__REACT_NATIVE__ !== "undefined");
678
- var _resolveTargetOverride = null;
679
- function getEffectiveIsWeb() {
680
- if (_resolveTargetOverride) return _resolveTargetOverride === "web";
681
- return isWeb || !isNative;
682
- }
683
- function toNativeValue(raw) {
684
- if (/^-?\d+(\.\d+)?px$/.test(raw)) return parseFloat(raw);
685
- if (/^-?\d+(\.\d+)?rem$/.test(raw)) return parseFloat(raw) * 16;
686
- if (/^-?\d+(\.\d+)?em$/.test(raw)) return parseFloat(raw) * 16;
687
- if (/^-?\d+(\.\d+)?$/.test(raw)) return parseFloat(raw);
688
- return raw;
689
- }
690
- function escapeCSSSelector(cls) {
691
- return cls.replace(/[ !"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
692
- }
693
-
694
- // src/core/devWarn.ts
695
- function kbachWarn(message) {
696
- console.warn(
697
- "%c[kbach]%c " + message,
698
- "color:#8b5cf6;font-weight:700",
699
- "color:inherit;font-weight:400"
700
- );
701
- }
702
-
703
- // src/core/registry.ts
704
- var BUILTIN_MODIFIERS = {
705
- // ── Mode ─────────────────────────────────────────────────────────────────
706
- dark: { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
707
- "not-light": { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
708
- light: { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
709
- "not-dark": { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
710
- // ── Interactive — JS state + CSS pseudo ───────────────────────────────────
711
- hover: { pseudo: ":hover", jsBehavior: "interactive", jsMatch: (_, s) => !!s.hover },
712
- "not-hover": { pseudo: ":not(:hover)", jsBehavior: "interactive", jsMatch: (_, s) => !s.hover },
713
- focus: { pseudo: ":focus", jsBehavior: "interactive", jsMatch: (_, s) => !!s.focus },
714
- "not-focus": { pseudo: ":not(:focus)", jsBehavior: "interactive", jsMatch: (_, s) => !s.focus },
715
- active: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.active || !!s.pressed },
716
- "not-active": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.active && !s.pressed },
717
- pressed: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.pressed || !!s.active },
718
- "not-pressed": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.pressed && !s.active },
719
- disabled: { pseudo: ":disabled", jsBehavior: "interactive", jsMatch: (_, s) => !!s.disabled },
720
- "not-disabled": { pseudo: ":not(:disabled)", jsBehavior: "interactive", jsMatch: (_, s) => !s.disabled },
721
- checked: { pseudo: ":checked", jsBehavior: "interactive", jsMatch: (_, s) => !!s.checked },
722
- "not-checked": { pseudo: ":not(:checked)", jsBehavior: "interactive", jsMatch: (_, s) => !s.checked },
723
- visited: { pseudo: ":visited", jsBehavior: "interactive", jsMatch: (_, s) => !!s.visited },
724
- "not-visited": { pseudo: ":not(:visited)", jsBehavior: "interactive", jsMatch: (_, s) => !s.visited },
725
- placeholder: { pseudo: "::placeholder", jsBehavior: "interactive", jsMatch: (_, s) => !!s.placeholder },
726
- // ── CSS-only pseudo-classes (structural) ──────────────────────────────────
727
- first: { pseudo: ":first-child", jsBehavior: "css-only", forcesImportant: true },
728
- last: { pseudo: ":last-child", jsBehavior: "css-only", forcesImportant: true },
729
- odd: { pseudo: ":nth-child(odd)", jsBehavior: "css-only", forcesImportant: true },
730
- even: { pseudo: ":nth-child(even)", jsBehavior: "css-only", forcesImportant: true },
731
- only: { pseudo: ":only-child", jsBehavior: "css-only", forcesImportant: true },
732
- "focus-within": { pseudo: ":focus-within", jsBehavior: "css-only", forcesImportant: true },
733
- "focus-visible": { pseudo: ":focus-visible", jsBehavior: "css-only", forcesImportant: true },
734
- // ── CSS-only pseudo-elements ───────────────────────────────────────────────
735
- before: { pseudo: "::before", jsBehavior: "css-only" },
736
- after: { pseudo: "::after", jsBehavior: "css-only" },
737
- selection: { pseudo: "::selection", jsBehavior: "css-only" },
738
- "first-letter": { pseudo: "::first-letter", jsBehavior: "css-only" },
739
- "first-line": { pseudo: "::first-line", jsBehavior: "css-only" },
740
- marker: { pseudo: "::marker", jsBehavior: "css-only" },
741
- // ── Group / peer ancestor selectors (CSS-only) ─────────────────────────────
742
- "group-hover": { ancestorSelector: ".group:hover ", jsBehavior: "css-only", forcesImportant: true },
743
- "group-focus": { ancestorSelector: ".group:focus ", jsBehavior: "css-only", forcesImportant: true },
744
- "peer-hover": { ancestorSelector: ".peer:hover ~ ", jsBehavior: "css-only", forcesImportant: true },
745
- "peer-focus": { ancestorSelector: ".peer:focus ~ ", jsBehavior: "css-only", forcesImportant: true },
746
- // ── Responsive — both CSS (@media min-width) and JS (breakpoints set) ──────
747
- sm: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("sm") },
748
- md: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("md") },
749
- lg: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("lg") },
750
- xl: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("xl") },
751
- "2xl": { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("2xl") },
752
- // ── Print media (CSS-only) ─────────────────────────────────────────────────
753
- print: { mediaQuery: "print", jsBehavior: "css-only", forcesImportant: true },
754
- // ── Orientation / accessibility media (CSS-only) ───────────────────────────
755
- landscape: { mediaQuery: "(orientation: landscape)", jsBehavior: "css-only", forcesImportant: true },
756
- portrait: { mediaQuery: "(orientation: portrait)", jsBehavior: "css-only", forcesImportant: true },
757
- "motion-reduce": { mediaQuery: "(prefers-reduced-motion: reduce)", jsBehavior: "css-only", forcesImportant: true },
758
- "motion-safe": { mediaQuery: "(prefers-reduced-motion: no-preference)", jsBehavior: "css-only", forcesImportant: true },
759
- "contrast-more": { mediaQuery: "(prefers-contrast: more)", jsBehavior: "css-only", forcesImportant: true },
760
- "contrast-less": { mediaQuery: "(prefers-contrast: less)", jsBehavior: "css-only", forcesImportant: true },
761
- // ── Directionality (CSS-only) ──────────────────────────────────────────────
762
- rtl: { dirSelector: '[dir="rtl"] ', jsBehavior: "css-only", forcesImportant: true },
763
- ltr: { dirSelector: '[dir="ltr"] ', jsBehavior: "css-only", forcesImportant: true }
764
- };
765
- var _pluginModifiers = {};
766
- var _allNames = null;
767
- var _interactiveNames = null;
768
- var _modeNames = null;
769
- var _responsiveNames = null;
770
- function _invalidate() {
771
- _allNames = null;
772
- _interactiveNames = null;
773
- _modeNames = null;
774
- _responsiveNames = null;
775
- }
776
- function registerModifier(name, def) {
777
- if (process.env.NODE_ENV !== "production" && name in BUILTIN_MODIFIERS) {
778
- kbachWarn(`"${name}" is built-in \u2014 pick another modifier name`);
779
- return;
780
- }
781
- _pluginModifiers[name] = def;
782
- _invalidate();
783
- }
784
- function clearPluginModifiers() {
785
- for (const k of Object.keys(_pluginModifiers)) delete _pluginModifiers[k];
786
- _invalidate();
787
- }
788
- var NAMED_GROUP_PEER_RE = /^(group|peer)-(hover|focus)\/(.+)$/;
789
- var _namedModifierCache = /* @__PURE__ */ new Map();
790
- function getNamedGroupPeerModifier(name) {
791
- const cached = _namedModifierCache.get(name);
792
- if (cached) return cached;
793
- const m = NAMED_GROUP_PEER_RE.exec(name);
794
- if (!m) return void 0;
795
- const [, kind, trigger, groupName] = m;
796
- const escapedName = escapeCSSSelector(groupName);
797
- const pseudo = trigger === "hover" ? ":hover" : ":focus";
798
- const combinator = kind === "group" ? " " : " ~ ";
799
- const def = {
800
- ancestorSelector: `.${kind}\\/${escapedName}${pseudo}${combinator}`,
801
- jsBehavior: "css-only",
802
- forcesImportant: true
803
- };
804
- _namedModifierCache.set(name, def);
805
- return def;
806
- }
807
- function getModifier(name) {
808
- return BUILTIN_MODIFIERS[name] ?? _pluginModifiers[name] ?? getNamedGroupPeerModifier(name);
809
- }
810
- function isKnownModifier(name) {
811
- return name in BUILTIN_MODIFIERS || name in _pluginModifiers || NAMED_GROUP_PEER_RE.test(name);
812
- }
813
- function _allEntries() {
814
- return [...Object.entries(BUILTIN_MODIFIERS), ...Object.entries(_pluginModifiers)];
815
- }
816
- function getInteractiveModifiers() {
817
- if (!_interactiveNames) {
818
- _interactiveNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "interactive").map(([k]) => k));
819
- }
820
- return _interactiveNames;
821
- }
822
- function getModeModifiers() {
823
- if (!_modeNames) {
824
- _modeNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "mode").map(([k]) => k));
825
- }
826
- return _modeNames;
827
- }
828
- function getResponsiveModifiers() {
829
- if (!_responsiveNames) {
830
- _responsiveNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "responsive").map(([k]) => k));
831
- }
832
- return _responsiveNames;
833
- }
834
- function matchModifier(name, isDark, state, breakpoints) {
835
- return getModifier(name)?.jsMatch?.(isDark, state, breakpoints) ?? false;
836
- }
837
-
838
- // src/core/utilities.ts
839
- function resolveColor(value, colors, isArbitrary) {
840
- if (isArbitrary) return value;
841
- const slashIdx = value.indexOf("/");
842
- const colorPart = slashIdx > 0 ? value.slice(0, slashIdx) : value;
843
- const opacityPart = slashIdx > 0 ? value.slice(slashIdx + 1) : null;
844
- let hex = null;
845
- if (colorPart in colors) {
846
- const entry = colors[colorPart];
847
- if (typeof entry === "string") hex = entry;
848
- else if (typeof entry === "object" && "6" in entry) hex = entry["6"];
849
- } else {
850
- const lastDash = colorPart.lastIndexOf("-");
851
- if (lastDash > 0) {
852
- const colorName = colorPart.slice(0, lastDash);
853
- const shade = colorPart.slice(lastDash + 1);
854
- const scale = colors[colorName];
855
- if (scale && typeof scale === "object" && shade in scale) {
856
- hex = scale[shade] ?? null;
857
- }
858
- }
859
- }
860
- if (!hex) return null;
861
- if (!opacityPart) {
862
- if (!getEffectiveIsWeb() && hex.startsWith("#") && hex.length === 9) {
863
- return hexToRgba(hex, Math.round(parseInt(hex.slice(7, 9), 16) / 255 * 1e3) / 1e3);
864
- }
865
- return hex;
866
- }
867
- let alpha;
868
- if (opacityPart.startsWith("[") && opacityPart.endsWith("]")) {
869
- const v = parseFloat(opacityPart.slice(1, -1));
870
- alpha = v > 1 ? v / 100 : v;
871
- } else {
872
- alpha = parseFloat(opacityPart) / 100;
873
- }
874
- if (isNaN(alpha)) return hex;
875
- if (alpha < 0) alpha = 0;
876
- else if (alpha > 1) alpha = 1;
877
- return hexToRgba(hex, alpha);
878
- }
879
- function parseHexRgb(hex) {
880
- const h = hex.replace("#", "");
881
- if (h.length === 3 || h.length === 4) {
882
- return [
883
- parseInt(h[0] + h[0], 16),
884
- parseInt(h[1] + h[1], 16),
885
- parseInt(h[2] + h[2], 16)
886
- ];
887
- }
888
- if (h.length === 6 || h.length === 8) {
889
- return [
890
- parseInt(h.slice(0, 2), 16),
891
- parseInt(h.slice(2, 4), 16),
892
- parseInt(h.slice(4, 6), 16)
893
- ];
894
- }
895
- return null;
896
- }
897
- function hexToRgba(hex, alpha) {
898
- const rgb = parseHexRgb(hex);
899
- if (!rgb) return hex;
900
- const [r, g, b] = rgb;
901
- return `rgba(${r},${g},${b},${alpha})`;
902
- }
903
- function withOpacityVar(color, varName) {
904
- if (!color.startsWith("#")) return color;
905
- const rgb = parseHexRgb(color);
906
- if (!rgb) return color;
907
- const [r, g, b] = rgb;
908
- return `rgba(${r},${g},${b},var(${varName},1))`;
909
- }
910
- function resolveSpacing(value, negative, spacing, isArbitrary) {
911
- if (isArbitrary) {
912
- const resolved = getEffectiveIsWeb() ? value : toNativeValue(value);
913
- if (negative) {
914
- if (typeof resolved === "number") return -resolved;
915
- if (typeof resolved === "string") {
916
- if (/^\d/.test(resolved)) return `-${resolved}`;
917
- if (/^(calc|var|min|max|clamp|env)\s*\(/.test(resolved)) return `calc(-1 * (${resolved}))`;
918
- }
919
- }
920
- return resolved;
921
- }
922
- const raw = spacing[value];
923
- if (raw === void 0) return null;
924
- if (typeof raw === "number") return negative ? -raw : raw;
925
- if (raw === "auto") return "auto";
926
- if (negative && typeof raw === "string" && raw.endsWith("%")) {
927
- return `-${raw}`;
928
- }
929
- return raw;
930
- }
931
- function resolveSizing(value, spacing, isArbitrary) {
932
- if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
933
- const raw = spacing[value];
934
- if (raw !== void 0) return raw;
935
- if (/^\d+\/\d+$/.test(value)) {
936
- const [num, den] = value.split("/").map(Number);
937
- if (!den) return null;
938
- return `${(num / den * 100).toFixed(6)}%`;
939
- }
940
- return null;
941
- }
942
- function resolveRadius(value, radii, isArbitrary) {
943
- if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
944
- const key = value === "" ? "DEFAULT" : value;
945
- return radii[key] ?? null;
946
- }
947
- function resolveFontSize(value, fontSizes, isArbitrary) {
948
- if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
949
- return fontSizes[value] ?? null;
950
- }
951
- var FILTER_COMPOSE = "var(--kb-blur,) var(--kb-brightness,) var(--kb-contrast,) var(--kb-grayscale,) var(--kb-hue-rotate,) var(--kb-invert,) var(--kb-saturate,) var(--kb-sepia,) var(--kb-drop-shadow,)";
952
- var BACKDROP_FILTER_COMPOSE = "var(--kb-backdrop-blur,) var(--kb-backdrop-brightness,) var(--kb-backdrop-contrast,) var(--kb-backdrop-grayscale,) var(--kb-backdrop-hue-rotate,) var(--kb-backdrop-invert,) var(--kb-backdrop-opacity,) var(--kb-backdrop-saturate,) var(--kb-backdrop-sepia,)";
953
- var _standalone = null;
954
- function buildStandalone() {
955
- const web = getEffectiveIsWeb();
956
- return {
957
- // Display
958
- // React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
959
- // a no-op normally, but is needed to re-show an element that was hidden via `hidden`.
960
- // `grid`, `contents`, `flow-root` have no native equivalent and stay null there.
961
- // The inline-* family (inline, inline-block, inline-flex, inline-grid) falls back
962
- // to 'flex' on native instead — like plain `flex`, this is a no-op most of the
963
- // time, but without it these utilities couldn't re-show a `hidden` element on
964
- // native either (null → no style applied → still display:'none').
965
- flex: { display: "flex" },
966
- block: web ? { display: "block" } : null,
967
- "inline-block": { display: web ? "inline-block" : "flex" },
968
- inline: { display: web ? "inline" : "flex" },
969
- grid: web ? { display: "grid" } : null,
970
- grd: web ? { display: "grid" } : null,
971
- "inline-flex": { display: web ? "inline-flex" : "flex" },
972
- "inline-grid": { display: web ? "inline-grid" : "flex" },
973
- hidden: { display: "none" },
974
- contents: web ? { display: "contents" } : null,
975
- "flow-root": web ? { display: "flow-root" } : null,
976
- // Flex direction (both web and native)
977
- "flex-row": { flexDirection: "row" },
978
- "flex-col": { flexDirection: "column" },
979
- "flex-row-reverse": { flexDirection: "row-reverse" },
980
- "flex-col-reverse": { flexDirection: "column-reverse" },
981
- // Flex wrap (both)
982
- "flex-wrap": { flexWrap: "wrap" },
983
- "flex-wrap-reverse": { flexWrap: "wrap-reverse" },
984
- "flex-nowrap": { flexWrap: "nowrap" },
985
- // Flex grow / shrink (both)
986
- "flex-grow": { flexGrow: 1 },
987
- "flex-grow-0": { flexGrow: 0 },
988
- "flex-shrink": { flexShrink: 1 },
989
- "flex-shrink-0": { flexShrink: 0 },
990
- // Align items (both)
991
- "items-start": { alignItems: "flex-start" },
992
- "items-end": { alignItems: "flex-end" },
993
- "items-center": { alignItems: "center" },
994
- "items-baseline": { alignItems: "baseline" },
995
- "items-stretch": { alignItems: "stretch" },
996
- // Justify content (both)
997
- "justify-start": { justifyContent: "flex-start" },
998
- "justify-end": { justifyContent: "flex-end" },
999
- "justify-center": { justifyContent: "center" },
1000
- "justify-between": { justifyContent: "space-between" },
1001
- "justify-around": { justifyContent: "space-around" },
1002
- "justify-evenly": { justifyContent: "space-evenly" },
1003
- // Align content (both)
1004
- "content-start": { alignContent: "flex-start" },
1005
- "content-end": { alignContent: "flex-end" },
1006
- "content-center": { alignContent: "center" },
1007
- "content-between": { alignContent: "space-between" },
1008
- "content-around": { alignContent: "space-around" },
1009
- "content-evenly": { alignContent: "space-evenly" },
1010
- "content-stretch": { alignContent: "stretch" },
1011
- // Align self (both)
1012
- "self-auto": { alignSelf: "auto" },
1013
- "self-start": { alignSelf: "flex-start" },
1014
- "self-end": { alignSelf: "flex-end" },
1015
- "self-center": { alignSelf: "center" },
1016
- "self-stretch": { alignSelf: "stretch" },
1017
- "self-baseline": { alignSelf: "baseline" },
1018
- // Text align (both)
1019
- "text-left": { textAlign: "left" },
1020
- "text-right": { textAlign: "right" },
1021
- "text-center": { textAlign: "center" },
1022
- "text-justify": { textAlign: "justify" },
1023
- // Font weight shortcuts (both)
1024
- "font-thin": { fontWeight: "100" },
1025
- "font-extralight": { fontWeight: "200" },
1026
- "font-light": { fontWeight: "300" },
1027
- "font-normal": { fontWeight: "400" },
1028
- "font-medium": { fontWeight: "500" },
1029
- "font-semibold": { fontWeight: "600" },
1030
- "font-bold": { fontWeight: "700" },
1031
- "font-extrabold": { fontWeight: "800" },
1032
- "font-black": { fontWeight: "900" },
1033
- // Text decoration (overline is web-only)
1034
- underline: { textDecorationLine: "underline" },
1035
- overline: web ? { textDecorationLine: "overline" } : null,
1036
- "line-through": { textDecorationLine: "line-through" },
1037
- "no-underline": { textDecorationLine: "none" },
1038
- // Text transform (both)
1039
- uppercase: { textTransform: "uppercase" },
1040
- lowercase: { textTransform: "lowercase" },
1041
- capitalize: { textTransform: "capitalize" },
1042
- "normal-case": { textTransform: "none" },
1043
- // Font style (both)
1044
- italic: { fontStyle: "italic" },
1045
- "non-italic": { fontStyle: "normal" },
1046
- // Position (fixed/sticky/static are web-only; RN only supports relative/absolute)
1047
- relative: { position: "relative" },
1048
- absolute: { position: "absolute" },
1049
- fixed: web ? { position: "fixed" } : null,
1050
- sticky: web ? { position: "sticky" } : null,
1051
- static: web ? { position: "static" } : null,
1052
- // Visibility (no `visibility` prop on native; use opacity instead)
1053
- visible: web ? { visibility: "visible" } : null,
1054
- invisible: web ? { visibility: "hidden" } : { opacity: 0 },
1055
- // Overflow (RN supports 'hidden' | 'visible' | 'scroll'; not 'auto')
1056
- "overflow-hidden": { overflow: "hidden" },
1057
- "overflow-visible": { overflow: "visible" },
1058
- "overflow-scroll": { overflow: "scroll" },
1059
- "overflow-auto": web ? { overflow: "auto" } : { overflow: "scroll" },
1060
- // overflowX / overflowY are web-only
1061
- "overflow-x-hidden": web ? { overflowX: "hidden" } : null,
1062
- "overflow-x-scroll": web ? { overflowX: "scroll" } : null,
1063
- "overflow-x-auto": web ? { overflowX: "auto" } : null,
1064
- "overflow-y-hidden": web ? { overflowY: "hidden" } : null,
1065
- "overflow-y-scroll": web ? { overflowY: "scroll" } : null,
1066
- "overflow-y-auto": web ? { overflowY: "auto" } : null,
1067
- // Object fit (web-only; use resizeMode prop on RN Image)
1068
- "object-contain": web ? { objectFit: "contain" } : null,
1069
- "object-cover": web ? { objectFit: "cover" } : null,
1070
- "object-fill": web ? { objectFit: "fill" } : null,
1071
- "object-none": web ? { objectFit: "none" } : null,
1072
- "object-scale-down": web ? { objectFit: "scale-down" } : null,
1073
- // Border style (both)
1074
- "border-solid": { borderStyle: "solid" },
1075
- "border-dashed": { borderStyle: "dashed" },
1076
- "border-dotted": { borderStyle: "dotted" },
1077
- "border-none": { borderWidth: 0 },
1078
- // Border sides default width (both)
1079
- "border-t": { borderTopWidth: 1 },
1080
- "border-r": { borderRightWidth: 1 },
1081
- "border-b": { borderBottomWidth: 1 },
1082
- "border-l": { borderLeftWidth: 1 },
1083
- // Cursor (web-only)
1084
- "cursor-auto": web ? { cursor: "auto" } : null,
1085
- "cursor-default": web ? { cursor: "default" } : null,
1086
- "cursor-pointer": web ? { cursor: "pointer" } : null,
1087
- "cursor-wait": web ? { cursor: "wait" } : null,
1088
- "cursor-text": web ? { cursor: "text" } : null,
1089
- "cursor-move": web ? { cursor: "move" } : null,
1090
- "cursor-not-allowed": web ? { cursor: "not-allowed" } : null,
1091
- // User select (web-only)
1092
- "select-none": web ? { userSelect: "none" } : null,
1093
- "select-text": web ? { userSelect: "text" } : null,
1094
- "select-all": web ? { userSelect: "all" } : null,
1095
- "select-auto": web ? { userSelect: "auto" } : null,
1096
- // Pointer events (both)
1097
- "pointer-events-none": { pointerEvents: "none" },
1098
- "pointer-events-auto": { pointerEvents: "auto" },
1099
- // Whitespace (web-only; RN Text uses numberOfLines prop instead)
1100
- "whitespace-normal": web ? { whiteSpace: "normal" } : null,
1101
- "whitespace-nowrap": web ? { whiteSpace: "nowrap" } : null,
1102
- "whitespace-pre": web ? { whiteSpace: "pre" } : null,
1103
- "whitespace-pre-wrap": web ? { whiteSpace: "pre-wrap" } : null,
1104
- "whitespace-pre-line": web ? { whiteSpace: "pre-line" } : null,
1105
- // Word break (web-only)
1106
- "break-normal": web ? { overflowWrap: "normal", wordBreak: "normal" } : null,
1107
- "break-words": web ? { overflowWrap: "break-word" } : null,
1108
- "break-all": web ? { wordBreak: "break-all" } : null,
1109
- // Misc web-only
1110
- truncate: web ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null,
1111
- "box-border": web ? { boxSizing: "border-box" } : null,
1112
- "box-content": web ? { boxSizing: "content-box" } : null,
1113
- "appearance-none": web ? { appearance: "none" } : null,
1114
- "outline-none": web ? { outline: "none", outlineOffset: "0" } : null,
1115
- outline: web ? { outline: "2px solid transparent", outlineOffset: "2px" } : null,
1116
- resize: web ? { resize: "both" } : null,
1117
- "resize-none": web ? { resize: "none" } : null,
1118
- "resize-y": web ? { resize: "vertical" } : null,
1119
- "resize-x": web ? { resize: "horizontal" } : null,
1120
- antialiased: web ? { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale" } : null,
1121
- "subpixel-antialiased": web ? { WebkitFontSmoothing: "subpixel-antialiased", MozOsxFontSmoothing: "auto" } : null,
1122
- "overflow-ellipsis": web ? { textOverflow: "ellipsis" } : null,
1123
- "sr-only": web ? {
1124
- position: "absolute",
1125
- width: 1,
1126
- height: 1,
1127
- padding: 0,
1128
- margin: -1,
1129
- overflow: "hidden",
1130
- clip: "rect(0,0,0,0)",
1131
- whiteSpace: "nowrap",
1132
- border: 0
1133
- } : null,
1134
- "not-sr-only": web ? {
1135
- position: "static",
1136
- width: "auto",
1137
- height: "auto",
1138
- padding: 0,
1139
- margin: 0,
1140
- overflow: "visible",
1141
- clip: "auto",
1142
- whiteSpace: "normal"
1143
- } : null,
1144
- // Lists (web-only)
1145
- "list-none": web ? { listStyleType: "none" } : null,
1146
- "list-disc": web ? { listStyleType: "disc" } : null,
1147
- "list-decimal": web ? { listStyleType: "decimal" } : null,
1148
- // Background clip (web-only)
1149
- "bg-clip-border": web ? { backgroundClip: "border-box" } : null,
1150
- "bg-clip-padding": web ? { backgroundClip: "padding-box" } : null,
1151
- "bg-clip-content": web ? { backgroundClip: "content-box" } : null,
1152
- "bg-clip-text": web ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
1153
- // Background image
1154
- "bg-none": web ? { backgroundImage: "none" } : null,
1155
- // Background size (web-only)
1156
- "bg-auto": web ? { backgroundSize: "auto" } : null,
1157
- "bg-cover": web ? { backgroundSize: "cover" } : null,
1158
- "bg-contain": web ? { backgroundSize: "contain" } : null,
1159
- // Background position (web-only)
1160
- "bg-center": web ? { backgroundPosition: "center" } : null,
1161
- "bg-top": web ? { backgroundPosition: "top" } : null,
1162
- "bg-bottom": web ? { backgroundPosition: "bottom" } : null,
1163
- "bg-left": web ? { backgroundPosition: "left" } : null,
1164
- "bg-right": web ? { backgroundPosition: "right" } : null,
1165
- "bg-left-top": web ? { backgroundPosition: "left top" } : null,
1166
- "bg-left-bottom": web ? { backgroundPosition: "left bottom" } : null,
1167
- "bg-right-top": web ? { backgroundPosition: "right top" } : null,
1168
- "bg-right-bottom": web ? { backgroundPosition: "right bottom" } : null,
1169
- // Background repeat (web-only)
1170
- "bg-repeat": web ? { backgroundRepeat: "repeat" } : null,
1171
- "bg-no-repeat": web ? { backgroundRepeat: "no-repeat" } : null,
1172
- "bg-repeat-x": web ? { backgroundRepeat: "repeat-x" } : null,
1173
- "bg-repeat-y": web ? { backgroundRepeat: "repeat-y" } : null,
1174
- "bg-repeat-round": web ? { backgroundRepeat: "round" } : null,
1175
- "bg-repeat-space": web ? { backgroundRepeat: "space" } : null,
1176
- // Background attachment (web-only)
1177
- "bg-fixed": web ? { backgroundAttachment: "fixed" } : null,
1178
- "bg-local": web ? { backgroundAttachment: "local" } : null,
1179
- "bg-scroll": web ? { backgroundAttachment: "scroll" } : null,
1180
- // Object position (web-only)
1181
- "object-center": web ? { objectPosition: "center" } : null,
1182
- "object-top": web ? { objectPosition: "top" } : null,
1183
- "object-bottom": web ? { objectPosition: "bottom" } : null,
1184
- "object-left": web ? { objectPosition: "left" } : null,
1185
- "object-right": web ? { objectPosition: "right" } : null,
1186
- "object-left-top": web ? { objectPosition: "left top" } : null,
1187
- "object-left-bottom": web ? { objectPosition: "left bottom" } : null,
1188
- "object-right-top": web ? { objectPosition: "right top" } : null,
1189
- "object-right-bottom": web ? { objectPosition: "right bottom" } : null,
1190
- // Table (web-only)
1191
- table: web ? { display: "table" } : null,
1192
- "table-auto": web ? { tableLayout: "auto" } : null,
1193
- "table-fixed": web ? { tableLayout: "fixed" } : null,
1194
- "caption-top": web ? { captionSide: "top" } : null,
1195
- "caption-bottom": web ? { captionSide: "bottom" } : null,
1196
- "border-collapse": web ? { borderCollapse: "collapse" } : null,
1197
- "border-separate": web ? { borderCollapse: "separate" } : null,
1198
- // List style position (web-only)
1199
- "list-inside": web ? { listStylePosition: "inside" } : null,
1200
- "list-outside": web ? { listStylePosition: "outside" } : null,
1201
- // Font variant numeric (web-only)
1202
- "normal-nums": web ? { fontVariantNumeric: "normal" } : null,
1203
- ordinal: web ? { fontVariantNumeric: "ordinal" } : null,
1204
- "slashed-zero": web ? { fontVariantNumeric: "slashed-zero" } : null,
1205
- "lining-nums": web ? { fontVariantNumeric: "lining-nums" } : null,
1206
- "oldstyle-nums": web ? { fontVariantNumeric: "oldstyle-nums" } : null,
1207
- "proportional-nums": web ? { fontVariantNumeric: "proportional-nums" } : null,
1208
- "tabular-nums": web ? { fontVariantNumeric: "tabular-nums" } : null,
1209
- "diagonal-fractions": web ? { fontVariantNumeric: "diagonal-fractions" } : null,
1210
- "stacked-fractions": web ? { fontVariantNumeric: "stacked-fractions" } : null,
1211
- // Isolation (web-only)
1212
- isolate: web ? { isolation: "isolate" } : null,
1213
- "isolation-auto": web ? { isolation: "auto" } : null,
1214
- // Backface visibility (both iOS and Android)
1215
- "backface-visible": { backfaceVisibility: "visible" },
1216
- "backface-hidden": { backfaceVisibility: "hidden" },
1217
- // CSS filters — standalone = default/full effect (web-only)
1218
- grayscale: web ? { "--kb-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
1219
- invert: web ? { "--kb-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
1220
- sepia: web ? { "--kb-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
1221
- // Divide none
1222
- "divide-none": web ? { __divideX: 0, __divideY: 0 } : null,
1223
- // Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
1224
- group: web ? {} : null,
1225
- peer: web ? {} : null,
1226
- // Text-wrap (web-only)
1227
- "text-wrap": web ? { textWrap: "wrap" } : null,
1228
- "text-nowrap": web ? { textWrap: "nowrap" } : null,
1229
- "text-balance": web ? { textWrap: "balance" } : null,
1230
- "text-pretty": web ? { textWrap: "pretty" } : null,
1231
- // Screen sizing — dvw/dvh (dynamic viewport units) instead of vw/vh: on mobile
1232
- // browsers, vh/vw are pinned to the LARGEST viewport size (address bar hidden),
1233
- // so `h-screen` overflows behind the address bar when it's shown. dvh/dvw track
1234
- // the actual visible viewport as browser chrome shows/hides. Desktop behavior
1235
- // is unchanged since there's no dynamic chrome to account for.
1236
- // (vw/dvw values are web-only; vh/dvh values work cross-platform via spacing scale for h-*)
1237
- "w-screen": web ? { width: "100dvw" } : null,
1238
- "min-h-screen": { minHeight: "100dvh" },
1239
- "max-h-screen": { maxHeight: "100dvh" },
1240
- "min-w-screen": web ? { minWidth: "100dvw" } : null,
1241
- "max-w-screen": web ? { maxWidth: "100dvw" } : null,
1242
- // max-w named container sizes (mirrors Tailwind's container scale)
1243
- "max-w-none": { maxWidth: "none" },
1244
- "max-w-xs": { maxWidth: 320 },
1245
- "max-w-sm": { maxWidth: 384 },
1246
- "max-w-md": { maxWidth: 448 },
1247
- "max-w-lg": { maxWidth: 512 },
1248
- "max-w-xl": { maxWidth: 576 },
1249
- "max-w-2xl": { maxWidth: 672 },
1250
- "max-w-3xl": { maxWidth: 768 },
1251
- "max-w-4xl": { maxWidth: 896 },
1252
- "max-w-5xl": { maxWidth: 1024 },
1253
- "max-w-6xl": { maxWidth: 1152 },
1254
- "max-w-7xl": { maxWidth: 1280 },
1255
- "max-w-prose": web ? { maxWidth: "65ch" } : null,
1256
- // Extended cursors (web-only)
1257
- "cursor-grab": web ? { cursor: "grab" } : null,
1258
- "cursor-grabbing": web ? { cursor: "grabbing" } : null,
1259
- "cursor-zoom-in": web ? { cursor: "zoom-in" } : null,
1260
- "cursor-zoom-out": web ? { cursor: "zoom-out" } : null,
1261
- "cursor-crosshair": web ? { cursor: "crosshair" } : null,
1262
- "cursor-help": web ? { cursor: "help" } : null,
1263
- "cursor-none": web ? { cursor: "none" } : null,
1264
- // Overflow clip (web-only)
1265
- "overflow-clip": web ? { overflow: "clip" } : null,
1266
- "overflow-x-clip": web ? { overflowX: "clip" } : null,
1267
- "overflow-y-clip": web ? { overflowY: "clip" } : null,
1268
- // Scroll behavior (web-only)
1269
- "scroll-smooth": web ? { scrollBehavior: "smooth" } : null,
1270
- "scroll-auto": web ? { scrollBehavior: "auto" } : null,
1271
- // Float (web-only)
1272
- "float-left": web ? { float: "left" } : null,
1273
- "float-right": web ? { float: "right" } : null,
1274
- "float-start": web ? { float: "inline-start" } : null,
1275
- "float-end": web ? { float: "inline-end" } : null,
1276
- "float-none": web ? { float: "none" } : null,
1277
- // Clear (web-only)
1278
- "clear-left": web ? { clear: "left" } : null,
1279
- "clear-right": web ? { clear: "right" } : null,
1280
- "clear-both": web ? { clear: "both" } : null,
1281
- "clear-start": web ? { clear: "inline-start" } : null,
1282
- "clear-end": web ? { clear: "inline-end" } : null,
1283
- "clear-none": web ? { clear: "none" } : null,
1284
- // Vertical align (web-only)
1285
- "align-baseline": web ? { verticalAlign: "baseline" } : null,
1286
- "align-top": web ? { verticalAlign: "top" } : null,
1287
- "align-middle": web ? { verticalAlign: "middle" } : null,
1288
- "align-bottom": web ? { verticalAlign: "bottom" } : null,
1289
- "align-text-top": web ? { verticalAlign: "text-top" } : null,
1290
- "align-text-bottom": web ? { verticalAlign: "text-bottom" } : null,
1291
- "align-sub": web ? { verticalAlign: "sub" } : null,
1292
- "align-super": web ? { verticalAlign: "super" } : null,
1293
- // Touch action (web-only)
1294
- "touch-auto": web ? { touchAction: "auto" } : null,
1295
- "touch-none": web ? { touchAction: "none" } : null,
1296
- "touch-pan-x": web ? { touchAction: "pan-x" } : null,
1297
- "touch-pan-y": web ? { touchAction: "pan-y" } : null,
1298
- "touch-pan-left": web ? { touchAction: "pan-left" } : null,
1299
- "touch-pan-right": web ? { touchAction: "pan-right" } : null,
1300
- "touch-pan-up": web ? { touchAction: "pan-up" } : null,
1301
- "touch-pan-down": web ? { touchAction: "pan-down" } : null,
1302
- "touch-pinch-zoom": web ? { touchAction: "pinch-zoom" } : null,
1303
- "touch-manipulation": web ? { touchAction: "manipulation" } : null
1304
- };
1305
- }
1306
- function getStandalone() {
1307
- if (!_standalone) _standalone = buildStandalone();
1308
- return _standalone;
1309
- }
1310
- function makeSpacingResolver(prop) {
1311
- return ({ value, negative, isArbitrary }, { spacing }) => {
1312
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
1313
- return v !== null ? { [prop]: v } : null;
1314
- };
1315
- }
1316
- var PADDING_MARGIN_PROPS = {
1317
- p: "padding",
1318
- px: "paddingHorizontal",
1319
- py: "paddingVertical",
1320
- pt: "paddingTop",
1321
- pr: "paddingRight",
1322
- pb: "paddingBottom",
1323
- pl: "paddingLeft",
1324
- m: "margin",
1325
- mx: "marginHorizontal",
1326
- my: "marginVertical",
1327
- mt: "marginTop",
1328
- mr: "marginRight",
1329
- mb: "marginBottom",
1330
- ml: "marginLeft"
1331
- };
1332
- function makeBorderSideResolver(widthProp, colorProp) {
1333
- return ({ value, isArbitrary }, { colors, borderWidth }) => {
1334
- if (!value) return { [widthProp]: 1 };
1335
- if (isArbitrary) {
1336
- const w2 = toNativeValue(value);
1337
- if (typeof w2 === "number") return { [widthProp]: w2 };
1338
- return { [colorProp]: value };
1339
- }
1340
- const color = resolveColor(value, colors, false);
1341
- if (color) return { [colorProp]: color };
1342
- const w = borderWidth[value];
1343
- return w !== void 0 ? { [widthProp]: w } : null;
1344
- };
1345
- }
1346
- var BORDER_SIDE_PROPS = {
1347
- "border-t": ["borderTopWidth", "borderTopColor"],
1348
- "border-r": ["borderRightWidth", "borderRightColor"],
1349
- "border-b": ["borderBottomWidth", "borderBottomColor"],
1350
- "border-l": ["borderLeftWidth", "borderLeftColor"]
1351
- };
1352
- function keyframeDeclToCSS(decl) {
1353
- return Object.entries(decl).map(([prop, val]) => `${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${val}`).join("; ");
1354
- }
1355
- function buildKeyframeCSS(name, steps) {
1356
- const body = Object.entries(steps).map(([selector, decl]) => `${selector} { ${keyframeDeclToCSS(decl)} }`).join(" ");
1357
- return `@keyframes ${name} { ${body} }`;
1358
- }
1359
- var BUILTIN_ANIMATIONS = {
1360
- none: { animation: "none" },
1361
- spin: {
1362
- animation: "kb-spin 1s linear infinite",
1363
- __keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
1364
- },
1365
- ping: {
1366
- animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
1367
- __keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
1368
- },
1369
- pulse: {
1370
- animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
1371
- __keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
1372
- },
1373
- bounce: {
1374
- animation: "kb-bounce 1s infinite",
1375
- __keyframe: "@keyframes kb-bounce { 0%, 100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(0.8,0,1,1) } 50% { transform: none; animation-timing-function: cubic-bezier(0,0,0.2,1) } }"
1376
- }
1377
- };
1378
- function buildAnimationValue(animation, keyframes) {
1379
- const words = animation.trim().split(/\s+/);
1380
- const name = words[0];
1381
- if (!name) return { animation };
1382
- const builtin = BUILTIN_ANIMATIONS[name];
1383
- if (builtin?.__keyframe) {
1384
- const kbName = builtin.animation.split(/\s+/, 1)[0];
1385
- return { animation: [kbName, ...words.slice(1)].join(" "), __keyframe: builtin.__keyframe };
1386
- }
1387
- const steps = keyframes?.[name];
1388
- return steps ? { animation, __keyframe: buildKeyframeCSS(name, steps) } : { animation };
1389
- }
1390
- var RESOLVERS = {
1391
- // ── Background ─────────────────────────────────────────────────────────────
1392
- bg: ({ value, isArbitrary }, { colors }) => {
1393
- const color = resolveColor(value, colors, isArbitrary);
1394
- if (!color) return null;
1395
- return { backgroundColor: getEffectiveIsWeb() ? withOpacityVar(color, "--bg-opacity") : color };
1396
- },
1397
- "bg-opacity": ({ value, isArbitrary }, _) => {
1398
- if (!getEffectiveIsWeb()) return null;
1399
- const n = parseFloat(value);
1400
- if (isNaN(n)) return null;
1401
- const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
1402
- return { "--bg-opacity": v };
1403
- },
1404
- // ── Text ───────────────────────────────────────────────────────────────────
1405
- text: ({ value, isArbitrary }, { colors, fontSize }) => {
1406
- const size = resolveFontSize(value, fontSize, false);
1407
- if (!isArbitrary && size !== null) return { fontSize: size };
1408
- if (isArbitrary) {
1409
- if (/^\d/.test(value) || /^(calc|min|max|clamp)/.test(value)) {
1410
- return { fontSize: getEffectiveIsWeb() ? value : toNativeValue(value) };
1411
- }
1412
- return { color: getEffectiveIsWeb() ? withOpacityVar(value, "--text-opacity") : value };
1413
- }
1414
- const color = resolveColor(value, colors, false);
1415
- if (!color) return null;
1416
- return { color: getEffectiveIsWeb() ? withOpacityVar(color, "--text-opacity") : color };
1417
- },
1418
- "text-opacity": ({ value, isArbitrary }, _) => {
1419
- if (!getEffectiveIsWeb()) return null;
1420
- const n = parseFloat(value);
1421
- if (isNaN(n)) return null;
1422
- const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
1423
- return { "--text-opacity": v };
1424
- },
1425
- // ── Padding & margin ───────────────────────────────────────────────────────
1426
- // Generated below via makeSpacingResolver() — see PADDING_MARGIN_PROPS.
1427
- // ── Sizing ─────────────────────────────────────────────────────────────────
1428
- w: ({ value, isArbitrary }, { spacing }) => {
1429
- const v = resolveSizing(value, spacing, isArbitrary);
1430
- return v !== null ? { width: v } : null;
1431
- },
1432
- h: ({ value, isArbitrary }, { spacing }) => {
1433
- const v = resolveSizing(value, spacing, isArbitrary);
1434
- return v !== null ? { height: v } : null;
1435
- },
1436
- "min-w": ({ value, isArbitrary }, { spacing }) => {
1437
- const v = resolveSizing(value, spacing, isArbitrary);
1438
- return v !== null ? { minWidth: v } : null;
1439
- },
1440
- "min-h": ({ value, isArbitrary }, { spacing }) => {
1441
- const v = resolveSizing(value, spacing, isArbitrary);
1442
- return v !== null ? { minHeight: v } : null;
1443
- },
1444
- "max-w": ({ value, isArbitrary }, { spacing }) => {
1445
- const v = resolveSizing(value, spacing, isArbitrary);
1446
- return v !== null ? { maxWidth: v } : null;
1447
- },
1448
- "max-h": ({ value, isArbitrary }, { spacing }) => {
1449
- const v = resolveSizing(value, spacing, isArbitrary);
1450
- return v !== null ? { maxHeight: v } : null;
1451
- },
1452
- // ── Border width ───────────────────────────────────────────────────────────
1453
- border: ({ value, isArbitrary }, { colors, borderWidth, spacing }) => {
1454
- if (!value) return { borderWidth: borderWidth["DEFAULT"] ?? 1 };
1455
- if (isArbitrary) {
1456
- const w2 = toNativeValue(value);
1457
- if (typeof w2 === "number") return { borderWidth: w2 };
1458
- return { borderColor: value };
1459
- }
1460
- const color = resolveColor(value, colors, false);
1461
- if (color) return { borderColor: color };
1462
- const w = borderWidth[value] ?? spacing[value];
1463
- if (w !== void 0) {
1464
- const numW = typeof w === "number" ? w : parseFloat(String(w));
1465
- if (isNaN(numW)) return null;
1466
- return { borderWidth: numW };
1467
- }
1468
- return null;
1469
- },
1470
- // border-t/-r/-b/-l generated below via makeBorderSideResolver() — see BORDER_SIDE_PROPS.
1471
- // ── Border radius ──────────────────────────────────────────────────────────
1472
- rounded: ({ value, isArbitrary }, { borderRadius }) => {
1473
- const r = resolveRadius(value, borderRadius, isArbitrary);
1474
- return r !== null ? { borderRadius: r } : null;
1475
- },
1476
- "rounded-t": ({ value, isArbitrary }, { borderRadius }) => {
1477
- const r = resolveRadius(value, borderRadius, isArbitrary);
1478
- return r !== null ? { borderTopLeftRadius: r, borderTopRightRadius: r } : null;
1479
- },
1480
- "rounded-r": ({ value, isArbitrary }, { borderRadius }) => {
1481
- const r = resolveRadius(value, borderRadius, isArbitrary);
1482
- return r !== null ? { borderTopRightRadius: r, borderBottomRightRadius: r } : null;
1483
- },
1484
- "rounded-b": ({ value, isArbitrary }, { borderRadius }) => {
1485
- const r = resolveRadius(value, borderRadius, isArbitrary);
1486
- return r !== null ? { borderBottomLeftRadius: r, borderBottomRightRadius: r } : null;
1487
- },
1488
- "rounded-l": ({ value, isArbitrary }, { borderRadius }) => {
1489
- const r = resolveRadius(value, borderRadius, isArbitrary);
1490
- return r !== null ? { borderTopLeftRadius: r, borderBottomLeftRadius: r } : null;
1491
- },
1492
- "rounded-tl": ({ value, isArbitrary }, { borderRadius }) => {
1493
- const r = resolveRadius(value, borderRadius, isArbitrary);
1494
- return r !== null ? { borderTopLeftRadius: r } : null;
1495
- },
1496
- "rounded-tr": ({ value, isArbitrary }, { borderRadius }) => {
1497
- const r = resolveRadius(value, borderRadius, isArbitrary);
1498
- return r !== null ? { borderTopRightRadius: r } : null;
1499
- },
1500
- "rounded-bl": ({ value, isArbitrary }, { borderRadius }) => {
1501
- const r = resolveRadius(value, borderRadius, isArbitrary);
1502
- return r !== null ? { borderBottomLeftRadius: r } : null;
1503
- },
1504
- "rounded-br": ({ value, isArbitrary }, { borderRadius }) => {
1505
- const r = resolveRadius(value, borderRadius, isArbitrary);
1506
- return r !== null ? { borderBottomRightRadius: r } : null;
1507
- },
1508
- // ── Grid (responsive column count: grid-1 … grid-12, or arbitrary) ───────
1509
- grid: ({ value, isArbitrary }) => {
1510
- if (!value) return null;
1511
- if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
1512
- const n = parseInt(value, 10);
1513
- if (isNaN(n) || n < 1 || n > 12) return null;
1514
- return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
1515
- },
1516
- // ── Grid template columns/rows (Tailwind-style aliases, web-only) ──────────
1517
- "grid-cols": ({ value, isArbitrary }) => {
1518
- if (!getEffectiveIsWeb()) return null;
1519
- if (!value) return null;
1520
- if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
1521
- if (value === "none") return { display: "grid", gridTemplateColumns: "none" };
1522
- const n = parseInt(value, 10);
1523
- if (isNaN(n) || n < 1 || n > 12) return null;
1524
- return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
1525
- },
1526
- "grid-rows": ({ value, isArbitrary }) => {
1527
- if (!getEffectiveIsWeb()) return null;
1528
- if (!value) return null;
1529
- if (isArbitrary) return { gridTemplateRows: value };
1530
- if (value === "none") return { gridTemplateRows: "none" };
1531
- const n = parseInt(value, 10);
1532
- if (isNaN(n) || n < 1) return null;
1533
- return { gridTemplateRows: `repeat(${n}, minmax(0, 1fr))` };
1534
- },
1535
- // ── Grid auto flow (web-only) ─────────────────────────────────────────────
1536
- "grid-flow": ({ value }) => {
1537
- if (!getEffectiveIsWeb()) return null;
1538
- const flows = {
1539
- row: "row",
1540
- col: "column",
1541
- dense: "dense",
1542
- "row-dense": "row dense",
1543
- "col-dense": "column dense"
1544
- };
1545
- const flow = flows[value];
1546
- return flow ? { gridAutoFlow: flow } : null;
1547
- },
1548
- // ── Grid auto sizing (web-only) ───────────────────────────────────────────
1549
- "auto-cols": ({ value, isArbitrary }) => {
1550
- if (!getEffectiveIsWeb()) return null;
1551
- if (isArbitrary) return { gridAutoColumns: value };
1552
- const presets = {
1553
- auto: "auto",
1554
- min: "min-content",
1555
- max: "max-content",
1556
- fr: "minmax(0, 1fr)"
1557
- };
1558
- const v = presets[value];
1559
- return v ? { gridAutoColumns: v } : null;
1560
- },
1561
- "auto-rows": ({ value, isArbitrary }) => {
1562
- if (!getEffectiveIsWeb()) return null;
1563
- if (isArbitrary) return { gridAutoRows: value };
1564
- const presets = {
1565
- auto: "auto",
1566
- min: "min-content",
1567
- max: "max-content",
1568
- fr: "minmax(0, 1fr)"
1569
- };
1570
- const v = presets[value];
1571
- return v ? { gridAutoRows: v } : null;
1572
- },
1573
- // ── Grid column placement (web-only) ──────────────────────────────────────
1574
- "col-span": ({ value }) => {
1575
- if (!getEffectiveIsWeb()) return null;
1576
- if (value === "full") return { gridColumn: "1 / -1" };
1577
- const n = parseInt(value, 10);
1578
- return isNaN(n) ? null : { gridColumn: `span ${n} / span ${n}` };
1579
- },
1580
- "col-start": ({ value, isArbitrary }) => {
1581
- if (!getEffectiveIsWeb()) return null;
1582
- if (value === "auto") return { gridColumnStart: "auto" };
1583
- if (isArbitrary) return { gridColumnStart: value };
1584
- const n = parseInt(value, 10);
1585
- return isNaN(n) ? null : { gridColumnStart: n };
1586
- },
1587
- "col-end": ({ value, isArbitrary }) => {
1588
- if (!getEffectiveIsWeb()) return null;
1589
- if (value === "auto") return { gridColumnEnd: "auto" };
1590
- if (isArbitrary) return { gridColumnEnd: value };
1591
- const n = parseInt(value, 10);
1592
- return isNaN(n) ? null : { gridColumnEnd: n };
1593
- },
1594
- col: ({ value, isArbitrary }) => {
1595
- if (!getEffectiveIsWeb()) return null;
1596
- if (!value || value === "auto") return { gridColumn: "auto" };
1597
- if (isArbitrary) return { gridColumn: value };
1598
- return null;
1599
- },
1600
- // ── Grid row placement (web-only) ─────────────────────────────────────────
1601
- "row-span": ({ value }) => {
1602
- if (!getEffectiveIsWeb()) return null;
1603
- if (value === "full") return { gridRow: "1 / -1" };
1604
- const n = parseInt(value, 10);
1605
- return isNaN(n) ? null : { gridRow: `span ${n} / span ${n}` };
1606
- },
1607
- "row-start": ({ value, isArbitrary }) => {
1608
- if (!getEffectiveIsWeb()) return null;
1609
- if (value === "auto") return { gridRowStart: "auto" };
1610
- if (isArbitrary) return { gridRowStart: value };
1611
- const n = parseInt(value, 10);
1612
- return isNaN(n) ? null : { gridRowStart: n };
1613
- },
1614
- "row-end": ({ value, isArbitrary }) => {
1615
- if (!getEffectiveIsWeb()) return null;
1616
- if (value === "auto") return { gridRowEnd: "auto" };
1617
- if (isArbitrary) return { gridRowEnd: value };
1618
- const n = parseInt(value, 10);
1619
- return isNaN(n) ? null : { gridRowEnd: n };
1620
- },
1621
- row: ({ value, isArbitrary }) => {
1622
- if (!getEffectiveIsWeb()) return null;
1623
- if (!value || value === "auto") return { gridRow: "auto" };
1624
- if (isArbitrary) return { gridRow: value };
1625
- return null;
1626
- },
1627
- // ── Grid alignment (web-only) ──────────────────────────────────────────────
1628
- // place-items is shorthand for align-items + justify-items on a grid container
1629
- "place-items": ({ value }) => {
1630
- if (!getEffectiveIsWeb()) return null;
1631
- const map = {
1632
- start: "start",
1633
- end: "end",
1634
- center: "center",
1635
- stretch: "stretch",
1636
- baseline: "baseline"
1637
- };
1638
- return map[value] ? { placeItems: map[value] } : null;
1639
- },
1640
- // place-content is shorthand for align-content + justify-content on a grid container
1641
- "place-content": ({ value }) => {
1642
- if (!getEffectiveIsWeb()) return null;
1643
- const map = {
1644
- start: "start",
1645
- end: "end",
1646
- center: "center",
1647
- stretch: "stretch",
1648
- between: "space-between",
1649
- around: "space-around",
1650
- evenly: "space-evenly",
1651
- baseline: "baseline"
1652
- };
1653
- return map[value] ? { placeContent: map[value] } : null;
1654
- },
1655
- // justify-items controls inline-axis alignment of grid items within their cells
1656
- "justify-items": ({ value }) => {
1657
- if (!getEffectiveIsWeb()) return null;
1658
- const map = {
1659
- start: "start",
1660
- end: "end",
1661
- center: "center",
1662
- stretch: "stretch"
1663
- };
1664
- return map[value] ? { justifyItems: map[value] } : null;
1665
- },
1666
- // place-self is shorthand for align-self + justify-self on a grid item
1667
- "place-self": ({ value }) => {
1668
- if (!getEffectiveIsWeb()) return null;
1669
- const map = {
1670
- auto: "auto",
1671
- start: "start",
1672
- end: "end",
1673
- center: "center",
1674
- stretch: "stretch"
1675
- };
1676
- return map[value] ? { placeSelf: map[value] } : null;
1677
- },
1678
- // justify-self controls inline-axis self-alignment of a grid item
1679
- "justify-self": ({ value }) => {
1680
- if (!getEffectiveIsWeb()) return null;
1681
- const map = {
1682
- auto: "auto",
1683
- start: "start",
1684
- end: "end",
1685
- center: "center",
1686
- stretch: "stretch"
1687
- };
1688
- return map[value] ? { justifySelf: map[value] } : null;
1689
- },
1690
- // ── CSS Filters (composable via CSS variables, web-only) ─────────────────
1691
- blur: ({ value, isArbitrary }) => {
1692
- if (!getEffectiveIsWeb()) return null;
1693
- const sizes = {
1694
- "": "blur(8px)",
1695
- sm: "blur(4px)",
1696
- md: "blur(12px)",
1697
- lg: "blur(16px)",
1698
- xl: "blur(24px)",
1699
- "2xl": "blur(40px)",
1700
- "3xl": "blur(64px)"
1701
- };
1702
- if (value === "none") return { "--kb-blur": "", filter: FILTER_COMPOSE };
1703
- const v = isArbitrary ? `blur(${value})` : sizes[value];
1704
- return v !== void 0 ? { "--kb-blur": v, filter: FILTER_COMPOSE } : null;
1705
- },
1706
- brightness: ({ value, isArbitrary }) => {
1707
- if (!getEffectiveIsWeb()) return null;
1708
- const v = isArbitrary ? `brightness(${value})` : `brightness(${parseFloat(value) / 100})`;
1709
- return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-brightness": v, filter: FILTER_COMPOSE };
1710
- },
1711
- contrast: ({ value, isArbitrary }) => {
1712
- if (!getEffectiveIsWeb()) return null;
1713
- const v = isArbitrary ? `contrast(${value})` : `contrast(${parseFloat(value) / 100})`;
1714
- return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-contrast": v, filter: FILTER_COMPOSE };
1715
- },
1716
- grayscale: ({ value }) => {
1717
- if (!getEffectiveIsWeb()) return null;
1718
- const v = value === "0" ? "grayscale(0)" : "grayscale(100%)";
1719
- return { "--kb-grayscale": v, filter: FILTER_COMPOSE };
1720
- },
1721
- "hue-rotate": ({ value, negative, isArbitrary }) => {
1722
- if (!getEffectiveIsWeb()) return null;
1723
- const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
1724
- if (isNaN(parseFloat(deg)) && !isArbitrary) return null;
1725
- return { "--kb-hue-rotate": `hue-rotate(${deg})`, filter: FILTER_COMPOSE };
1726
- },
1727
- invert: ({ value }) => {
1728
- if (!getEffectiveIsWeb()) return null;
1729
- const v = value === "0" ? "invert(0)" : "invert(100%)";
1730
- return { "--kb-invert": v, filter: FILTER_COMPOSE };
1731
- },
1732
- saturate: ({ value, isArbitrary }) => {
1733
- if (!getEffectiveIsWeb()) return null;
1734
- const v = isArbitrary ? `saturate(${value})` : `saturate(${parseFloat(value) / 100})`;
1735
- return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-saturate": v, filter: FILTER_COMPOSE };
1736
- },
1737
- sepia: ({ value }) => {
1738
- if (!getEffectiveIsWeb()) return null;
1739
- const v = value === "0" ? "sepia(0)" : "sepia(100%)";
1740
- return { "--kb-sepia": v, filter: FILTER_COMPOSE };
1741
- },
1742
- "drop-shadow": ({ value, isArbitrary }) => {
1743
- if (!getEffectiveIsWeb()) return null;
1744
- if (isArbitrary) return { "--kb-drop-shadow": `drop-shadow(${value.replace(/_/g, " ")})`, filter: FILTER_COMPOSE };
1745
- const presets = {
1746
- "": "drop-shadow(0 1px 2px rgb(0 0 0/0.1)) drop-shadow(0 1px 1px rgb(0 0 0/0.06))",
1747
- sm: "drop-shadow(0 1px 1px rgb(0 0 0/0.05))",
1748
- md: "drop-shadow(0 4px 3px rgb(0 0 0/0.07)) drop-shadow(0 2px 2px rgb(0 0 0/0.06))",
1749
- lg: "drop-shadow(0 10px 8px rgb(0 0 0/0.04)) drop-shadow(0 4px 3px rgb(0 0 0/0.1))",
1750
- xl: "drop-shadow(0 20px 13px rgb(0 0 0/0.03)) drop-shadow(0 8px 5px rgb(0 0 0/0.08))",
1751
- "2xl": "drop-shadow(0 25px 25px rgb(0 0 0/0.15))",
1752
- none: "drop-shadow(0 0 #0000)"
1753
- };
1754
- const v = presets[value];
1755
- return v !== void 0 ? { "--kb-drop-shadow": v, filter: FILTER_COMPOSE } : null;
1756
- },
1757
- // Arbitrary full filter string: filter-[blur(4px)_grayscale(1)]
1758
- filter: ({ value, isArbitrary }) => {
1759
- if (!getEffectiveIsWeb()) return null;
1760
- if (isArbitrary) return { filter: value.replace(/_/g, " ") };
1761
- if (value === "none") return { filter: "none" };
1762
- return null;
1763
- },
1764
- // ── Backdrop Filters (composable via CSS variables, web-only) ────────────
1765
- "backdrop-blur": ({ value, isArbitrary }) => {
1766
- if (!getEffectiveIsWeb()) return null;
1767
- const sizes = {
1768
- "": "blur(8px)",
1769
- sm: "blur(4px)",
1770
- md: "blur(12px)",
1771
- lg: "blur(16px)",
1772
- xl: "blur(24px)",
1773
- "2xl": "blur(40px)",
1774
- "3xl": "blur(64px)"
1775
- };
1776
- if (value === "none") return { "--kb-backdrop-blur": "", backdropFilter: BACKDROP_FILTER_COMPOSE };
1777
- const v = isArbitrary ? `blur(${value})` : sizes[value];
1778
- return v !== void 0 ? { "--kb-backdrop-blur": v, backdropFilter: BACKDROP_FILTER_COMPOSE } : null;
1779
- },
1780
- "backdrop-brightness": ({ value, isArbitrary }) => {
1781
- if (!getEffectiveIsWeb()) return null;
1782
- const v = isArbitrary ? `brightness(${value})` : `brightness(${parseFloat(value) / 100})`;
1783
- return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-backdrop-brightness": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1784
- },
1785
- "backdrop-contrast": ({ value, isArbitrary }) => {
1786
- if (!getEffectiveIsWeb()) return null;
1787
- const v = isArbitrary ? `contrast(${value})` : `contrast(${parseFloat(value) / 100})`;
1788
- return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-backdrop-contrast": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1789
- },
1790
- "backdrop-grayscale": ({ value }) => {
1791
- if (!getEffectiveIsWeb()) return null;
1792
- return { "--kb-backdrop-grayscale": value === "0" ? "grayscale(0)" : "grayscale(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
1793
- },
1794
- "backdrop-hue-rotate": ({ value, negative, isArbitrary }) => {
1795
- if (!getEffectiveIsWeb()) return null;
1796
- const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
1797
- if (isNaN(parseFloat(deg)) && !isArbitrary) return null;
1798
- return { "--kb-backdrop-hue-rotate": `hue-rotate(${deg})`, backdropFilter: BACKDROP_FILTER_COMPOSE };
1799
- },
1800
- "backdrop-invert": ({ value }) => {
1801
- if (!getEffectiveIsWeb()) return null;
1802
- return { "--kb-backdrop-invert": value === "0" ? "invert(0)" : "invert(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
1803
- },
1804
- "backdrop-opacity": ({ value, isArbitrary }) => {
1805
- if (!getEffectiveIsWeb()) return null;
1806
- const v = isArbitrary ? `opacity(${value})` : `opacity(${parseFloat(value) / 100})`;
1807
- return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-backdrop-opacity": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1808
- },
1809
- "backdrop-saturate": ({ value, isArbitrary }) => {
1810
- if (!getEffectiveIsWeb()) return null;
1811
- const v = isArbitrary ? `saturate(${value})` : `saturate(${parseFloat(value) / 100})`;
1812
- return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--kb-backdrop-saturate": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
1813
- },
1814
- "backdrop-sepia": ({ value }) => {
1815
- if (!getEffectiveIsWeb()) return null;
1816
- return { "--kb-backdrop-sepia": value === "0" ? "sepia(0)" : "sepia(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
1817
- },
1818
- "backdrop-filter": ({ value, isArbitrary }) => {
1819
- if (!getEffectiveIsWeb()) return null;
1820
- if (isArbitrary) return { backdropFilter: value.replace(/_/g, " ") };
1821
- if (value === "none") return { backdropFilter: "none" };
1822
- return null;
1823
- },
1824
- // ── Background gradient (CSS variable gradient stops, web-only) ──────────
1825
- "bg-gradient-to": ({ value }) => {
1826
- if (!getEffectiveIsWeb()) return null;
1827
- const directions = {
1828
- t: "to top",
1829
- tr: "to top right",
1830
- r: "to right",
1831
- br: "to bottom right",
1832
- b: "to bottom",
1833
- bl: "to bottom left",
1834
- l: "to left",
1835
- tl: "to top left"
1836
- };
1837
- const dir = directions[value];
1838
- if (!dir) return null;
1839
- return {
1840
- backgroundImage: `linear-gradient(${dir}, var(--kb-gradient-from, transparent), var(--kb-gradient-stops, transparent))`
1841
- };
1842
- },
1843
- from: ({ value, isArbitrary }, { colors }) => {
1844
- if (!getEffectiveIsWeb()) return null;
1845
- const color = resolveColor(value, colors, isArbitrary);
1846
- if (!color) return null;
1847
- return {
1848
- "--kb-gradient-from": color,
1849
- "--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-to, transparent)`
1850
- };
1851
- },
1852
- via: ({ value, isArbitrary }, { colors }) => {
1853
- if (!getEffectiveIsWeb()) return null;
1854
- const color = resolveColor(value, colors, isArbitrary);
1855
- if (!color) return null;
1856
- return {
1857
- "--kb-gradient-via": color,
1858
- "--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-via), var(--kb-gradient-to, transparent)`
1859
- };
1860
- },
1861
- to: ({ value, isArbitrary }, { colors }) => {
1862
- if (!getEffectiveIsWeb()) return null;
1863
- const color = resolveColor(value, colors, isArbitrary);
1864
- if (!color) return null;
1865
- return { "--kb-gradient-to": color };
1866
- },
1867
- // ── Transform extras (web-only) ───────────────────────────────────────────
1868
- "skew-x": ({ value, negative, isArbitrary }) => {
1869
- const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
1870
- if (!isArbitrary && isNaN(parseFloat(value))) return null;
1871
- return getEffectiveIsWeb() ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
1872
- },
1873
- "skew-y": ({ value, negative, isArbitrary }) => {
1874
- const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
1875
- if (!isArbitrary && isNaN(parseFloat(value))) return null;
1876
- return getEffectiveIsWeb() ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
1877
- },
1878
- // Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
1879
- transform: ({ value, isArbitrary }) => {
1880
- if (!getEffectiveIsWeb()) return null;
1881
- if (isArbitrary) return { transform: value.replace(/_/g, " ") };
1882
- if (value === "none") return { transform: "none" };
1883
- return null;
1884
- },
1885
- // Transform origin
1886
- origin: ({ value, isArbitrary }) => {
1887
- if (!getEffectiveIsWeb()) return null;
1888
- if (isArbitrary) return { transformOrigin: value.replace(/_/g, " ") };
1889
- const origins = {
1890
- center: "center",
1891
- top: "top",
1892
- "top-right": "top right",
1893
- right: "right",
1894
- "bottom-right": "bottom right",
1895
- bottom: "bottom",
1896
- "bottom-left": "bottom left",
1897
- left: "left",
1898
- "top-left": "top left"
1899
- };
1900
- return origins[value] ? { transformOrigin: origins[value] } : null;
1901
- },
1902
- // ── Text decoration advanced (web-only) ───────────────────────────────────
1903
- decoration: ({ value, isArbitrary }, { colors }) => {
1904
- if (!getEffectiveIsWeb()) return null;
1905
- if (isArbitrary) {
1906
- if (/^\d/.test(value) || value.startsWith("calc(")) return { textDecorationThickness: value };
1907
- return { textDecorationColor: value };
1908
- }
1909
- const thickTokens = {
1910
- auto: "auto",
1911
- "from-font": "from-font",
1912
- "0": "0px",
1913
- "1": "1px",
1914
- "2": "2px",
1915
- "4": "4px",
1916
- "8": "8px"
1917
- };
1918
- if (value in thickTokens) return { textDecorationThickness: thickTokens[value] };
1919
- const styleTokens = {
1920
- solid: "solid",
1921
- dashed: "dashed",
1922
- dotted: "dotted",
1923
- double: "double",
1924
- wavy: "wavy"
1925
- };
1926
- if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
1927
- const color = resolveColor(value, colors, false);
1928
- return color ? { textDecorationColor: color } : null;
1929
- },
1930
- "underline-offset": ({ value, isArbitrary }) => {
1931
- if (!getEffectiveIsWeb()) return null;
1932
- if (isArbitrary) return { textUnderlineOffset: value };
1933
- const offsets = {
1934
- auto: "auto",
1935
- "0": "0px",
1936
- "1": "1px",
1937
- "2": "2px",
1938
- "4": "4px",
1939
- "8": "8px"
1940
- };
1941
- return offsets[value] ? { textUnderlineOffset: offsets[value] } : null;
1942
- },
1943
- // ── Content (web-only — for before:/after: pseudo-elements, which don't exist on native) ──
1944
- // Arbitrary value carries its own quotes from the bracket syntax (content-['*'] parses to
1945
- // the literal string 'you can see it' quotes included), so it passes straight through as a
1946
- // valid `content: '*'` CSS value with no extra wrapping needed.
1947
- content: ({ value, isArbitrary }) => {
1948
- if (!getEffectiveIsWeb()) return null;
1949
- if (isArbitrary) return { content: value };
1950
- const presets = { none: "none" };
1951
- return value in presets ? { content: presets[value] } : null;
1952
- },
1953
- // ── Arbitrary CSS property (web-only): [property:value] with no utility prefix ──
1954
- // e.g. [mask-type:luminance], [--my-var:10px]. parser.ts already isolates this case
1955
- // as utility: '' — it's ALSO how a stray, prefix-less negative bracket ("-[10px]",
1956
- // presumably a typo) parses, which is why this only fires when the arbitrary value
1957
- // itself contains a "property:value" pair; anything else (no colon) still resolves
1958
- // to null exactly as before this resolver existed, rather than guessing a property.
1959
- //
1960
- // Only the FIRST colon splits property from value — the value itself may contain
1961
- // more colons (a URL's "http://…") and must stay intact: [background:url(http://x/a.png)].
1962
- // camelToKebab() in resolver.ts is a no-op on an already-kebab-case (or "--"-prefixed
1963
- // custom property) key, so it can be used as the style object key as-written with no
1964
- // extra case conversion — it only needs to look like a plausible CSS property name.
1965
- "": ({ value, isArbitrary, negative }) => {
1966
- if (!getEffectiveIsWeb() || !isArbitrary || !value) return null;
1967
- if (negative) return null;
1968
- const colonIdx = value.indexOf(":");
1969
- if (colonIdx <= 0) return null;
1970
- const prop = value.slice(0, colonIdx).trim();
1971
- const cssValue = value.slice(colonIdx + 1).trim();
1972
- if (!cssValue || !/^(--[\w-]+|[a-zA-Z-]+)$/.test(prop)) return null;
1973
- return { [prop]: cssValue };
1974
- },
1975
- // ── Outline extended (web-only) ───────────────────────────────────────────
1976
- outline: ({ value, isArbitrary }, { colors }) => {
1977
- if (!getEffectiveIsWeb()) return null;
1978
- if (!value) return { outline: "2px solid transparent", outlineOffset: "2px" };
1979
- if (value === "none") return { outline: "none", outlineOffset: "0" };
1980
- if (isArbitrary) {
1981
- if (/^\d/.test(value) || value.startsWith("calc(")) return { outlineWidth: value };
1982
- return { outlineColor: value };
1983
- }
1984
- const widths = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
1985
- if (value in widths) return { outlineWidth: widths[value] };
1986
- const color = resolveColor(value, colors, false);
1987
- return color ? { outlineColor: color } : null;
1988
- },
1989
- "outline-offset": ({ value, isArbitrary }) => {
1990
- if (!getEffectiveIsWeb()) return null;
1991
- if (isArbitrary) return { outlineOffset: value };
1992
- const offsets = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
1993
- return offsets[value] ? { outlineOffset: offsets[value] } : null;
1994
- },
1995
- // ── Columns (web-only) ─────────────────────────────────────────────────────
1996
- columns: ({ value, isArbitrary }) => {
1997
- if (!getEffectiveIsWeb()) return null;
1998
- if (isArbitrary) return { columnCount: value };
1999
- if (value === "auto") return { columnCount: "auto" };
2000
- const n = parseInt(value, 10);
2001
- if (!isNaN(n)) return { columnCount: n };
2002
- const widths = {
2003
- "3xs": "16rem",
2004
- "2xs": "18rem",
2005
- xs: "20rem",
2006
- sm: "24rem",
2007
- md: "28rem",
2008
- lg: "32rem",
2009
- xl: "36rem",
2010
- "2xl": "42rem",
2011
- "3xl": "48rem",
2012
- "4xl": "56rem",
2013
- "5xl": "64rem",
2014
- "6xl": "72rem",
2015
- "7xl": "80rem"
2016
- };
2017
- return widths[value] ? { columnWidth: widths[value] } : null;
2018
- },
2019
- // ── Mix / background blend mode (web-only) ───────────────────────────────
2020
- "mix-blend": ({ value }) => {
2021
- if (!getEffectiveIsWeb()) return null;
2022
- const modes = [
2023
- "normal",
2024
- "multiply",
2025
- "screen",
2026
- "overlay",
2027
- "darken",
2028
- "lighten",
2029
- "color-dodge",
2030
- "color-burn",
2031
- "hard-light",
2032
- "soft-light",
2033
- "difference",
2034
- "exclusion",
2035
- "hue",
2036
- "saturation",
2037
- "color",
2038
- "luminosity",
2039
- "plus-lighter"
2040
- ];
2041
- return modes.includes(value) ? { mixBlendMode: value } : null;
2042
- },
2043
- "bg-blend": ({ value }) => {
2044
- if (!getEffectiveIsWeb()) return null;
2045
- const modes = [
2046
- "normal",
2047
- "multiply",
2048
- "screen",
2049
- "overlay",
2050
- "darken",
2051
- "lighten",
2052
- "color-dodge",
2053
- "color-burn",
2054
- "hard-light",
2055
- "soft-light",
2056
- "difference",
2057
- "exclusion",
2058
- "hue",
2059
- "saturation",
2060
- "color",
2061
- "luminosity"
2062
- ];
2063
- return modes.includes(value) ? { backgroundBlendMode: value } : null;
2064
- },
2065
- // ── Will-change (web-only) ─────────────────────────────────────────────────
2066
- "will-change": ({ value, isArbitrary }) => {
2067
- if (!getEffectiveIsWeb()) return null;
2068
- if (isArbitrary) return { willChange: value.replace(/_/g, ", ") };
2069
- const presets = {
2070
- auto: "auto",
2071
- scroll: "scroll-position",
2072
- contents: "contents",
2073
- transform: "transform"
2074
- };
2075
- return presets[value] ? { willChange: presets[value] } : null;
2076
- },
2077
- // ── Divide (child combinator CSS, web-only) ───────────────────────────────
2078
- // These return special __divide* markers that resolver.ts converts to
2079
- // .cls > * + * { border-... } CSS rules. No inline style is applied.
2080
- "divide-x": ({ value, isArbitrary }) => {
2081
- if (!getEffectiveIsWeb()) return null;
2082
- if (value === "reverse") return null;
2083
- if (!value) return { __divideX: 1 };
2084
- const n = parseFloat(value);
2085
- return isNaN(n) ? null : { __divideX: n };
2086
- },
2087
- "divide-y": ({ value, isArbitrary }) => {
2088
- if (!getEffectiveIsWeb()) return null;
2089
- if (value === "reverse") return null;
2090
- if (!value) return { __divideY: 1 };
2091
- const n = parseFloat(value);
2092
- return isNaN(n) ? null : { __divideY: n };
2093
- },
2094
- divide: ({ value, isArbitrary }, { colors }) => {
2095
- if (!getEffectiveIsWeb()) return null;
2096
- if (isArbitrary) return { __divideColor: value };
2097
- const styleTokens = {
2098
- solid: "solid",
2099
- dashed: "dashed",
2100
- dotted: "dotted",
2101
- double: "double",
2102
- none: "none"
2103
- };
2104
- if (value in styleTokens) return { __divideStyle: styleTokens[value] };
2105
- const color = resolveColor(value, colors, false);
2106
- return color ? { __divideColor: color } : null;
2107
- },
2108
- // ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
2109
- // Named presets give cross-platform shadow; arbitrary is web-only.
2110
- "text-shadow": ({ value, isArbitrary }, { colors }) => {
2111
- if (value === "none") {
2112
- return getEffectiveIsWeb() ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
2113
- }
2114
- const webPresets = {
2115
- "": "0 2px 4px rgba(0,0,0,0.3)",
2116
- sm: "0 1px 2px rgba(0,0,0,0.3)",
2117
- md: "0 4px 6px rgba(0,0,0,0.3)",
2118
- lg: "0 8px 16px rgba(0,0,0,0.5)",
2119
- xl: "0 16px 32px rgba(0,0,0,0.5)"
2120
- };
2121
- const nativePresets = {
2122
- "": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
2123
- sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
2124
- md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
2125
- lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
2126
- xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
2127
- };
2128
- if (value in webPresets) {
2129
- if (getEffectiveIsWeb()) return { textShadow: webPresets[value] };
2130
- return nativePresets[value] ?? null;
2131
- }
2132
- if (isArbitrary) {
2133
- return getEffectiveIsWeb() ? { textShadow: value.replace(/_/g, " ") } : null;
2134
- }
2135
- const color = resolveColor(value, colors, false);
2136
- if (color) {
2137
- return getEffectiveIsWeb() ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
2138
- }
2139
- return null;
2140
- },
2141
- // ── Perspective transform (cross-platform: iOS, Android, web) ────────────
2142
- perspective: ({ value, isArbitrary }) => {
2143
- if (isArbitrary) {
2144
- const numPx = parseFloat(value);
2145
- if (getEffectiveIsWeb()) return { transform: `perspective(${value})` };
2146
- return isNaN(numPx) ? null : { transform: [{ perspective: numPx }] };
2147
- }
2148
- if (value === "none") return getEffectiveIsWeb() ? { transform: "none" } : null;
2149
- const n = parseFloat(value);
2150
- if (isNaN(n)) return null;
2151
- return getEffectiveIsWeb() ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
2152
- },
2153
- // ── Tint color (native-only, for Image and icon components) ──────────────
2154
- tint: ({ value, isArbitrary }, { colors }) => {
2155
- if (getEffectiveIsWeb()) return null;
2156
- const color = resolveColor(value, colors, isArbitrary);
2157
- return color ? { tintColor: color } : null;
2158
- },
2159
- // ── Size shorthand (sets width AND height in one utility) ────────────────
2160
- size: ({ value, isArbitrary }, { spacing }) => {
2161
- const v = resolveSizing(value, spacing, isArbitrary);
2162
- return v !== null ? { width: v, height: v } : null;
2163
- },
2164
- // ── Animations (CSS keyframe animations, web-only) ────────────────────────
2165
- // Each variant injects a @keyframes rule once via the __keyframe marker.
2166
- // resolver.ts detects __keyframe, injects the rule, then strips the marker
2167
- // so it never reaches element inline styles.
2168
- animate: ({ value, isArbitrary }, theme) => {
2169
- if (!getEffectiveIsWeb()) return null;
2170
- if (isArbitrary) return buildAnimationValue(value.replace(/_/g, " "), theme.keyframes);
2171
- if (value in BUILTIN_ANIMATIONS) return BUILTIN_ANIMATIONS[value];
2172
- const custom = theme.animation?.[value];
2173
- return custom ? buildAnimationValue(custom, theme.keyframes) : null;
2174
- },
2175
- // ── Line-clamp (web-only) ─────────────────────────────────────────────────
2176
- "line-clamp": ({ value }) => {
2177
- if (!getEffectiveIsWeb()) return null;
2178
- if (value === "none") return { overflow: "visible", display: "block", WebkitLineClamp: "unset" };
2179
- const n = parseInt(value, 10);
2180
- if (isNaN(n) || n < 1) return null;
2181
- return {
2182
- overflow: "hidden",
2183
- display: "-webkit-box",
2184
- WebkitBoxOrient: "vertical",
2185
- WebkitLineClamp: n
2186
- };
2187
- },
2188
- // ── Caret color (web-only) ────────────────────────────────────────────────
2189
- caret: ({ value, isArbitrary }, { colors }) => {
2190
- if (!getEffectiveIsWeb()) return null;
2191
- if (value === "auto" || value === "transparent") return { caretColor: value };
2192
- const color = resolveColor(value, colors, isArbitrary);
2193
- return color ? { caretColor: color } : null;
2194
- },
2195
- // ── Accent color (web-only) ───────────────────────────────────────────────
2196
- accent: ({ value, isArbitrary }, { colors }) => {
2197
- if (!getEffectiveIsWeb()) return null;
2198
- if (value === "auto") return { accentColor: "auto" };
2199
- const color = resolveColor(value, colors, isArbitrary);
2200
- return color ? { accentColor: color } : null;
2201
- },
2202
- // ── SVG stroke/fill (web-only) ────────────────────────────────────────────
2203
- // Native is intentionally excluded: react-native-svg's <Path>/<Circle>/etc.
2204
- // take stroke/fill as component PROPS, not style entries, so there's no
2205
- // reliable way to apply a resolved color through the `style` prop there.
2206
- // `stroke-{n}` sets strokeWidth (a plain number, unlike a color) — same
2207
- // color-first-then-numeric-fallback disambiguation `border` uses above.
2208
- stroke: ({ value, isArbitrary }, { colors }) => {
2209
- if (!getEffectiveIsWeb()) return null;
2210
- if (!value) return null;
2211
- if (value === "none") return { stroke: "none" };
2212
- if (isArbitrary) {
2213
- const w = toNativeValue(value);
2214
- return typeof w === "number" ? { strokeWidth: w } : { stroke: value };
2215
- }
2216
- const color = resolveColor(value, colors, false);
2217
- if (color) return { stroke: color };
2218
- const n = parseFloat(value);
2219
- return isNaN(n) ? null : { strokeWidth: n };
2220
- },
2221
- fill: ({ value, isArbitrary }, { colors }) => {
2222
- if (!getEffectiveIsWeb()) return null;
2223
- if (!value) return null;
2224
- if (value === "none") return { fill: "none" };
2225
- if (isArbitrary) return { fill: value };
2226
- const color = resolveColor(value, colors, false);
2227
- return color ? { fill: color } : null;
2228
- },
2229
- // ── Flex ───────────────────────────────────────────────────────────────────
2230
- flex: ({ value, isArbitrary }, { flex }) => {
2231
- if (!value) return { display: "flex" };
2232
- if (isArbitrary) {
2233
- const v = parseFloat(value);
2234
- return isNaN(v) ? null : { flex: v };
2235
- }
2236
- if (value in flex) {
2237
- const v = flex[value];
2238
- if (typeof v === "string" && !getEffectiveIsWeb()) {
2239
- if (v === "auto" || v === "initial") return { flex: 1 };
2240
- if (v === "none") return { flex: 0 };
2241
- return null;
2242
- }
2243
- return { flex: v };
2244
- }
2245
- const n = parseFloat(value);
2246
- return isNaN(n) ? null : { flex: n };
2247
- },
2248
- basis: ({ value, isArbitrary }, { spacing }) => {
2249
- const v = resolveSizing(value, spacing, isArbitrary);
2250
- return v !== null ? { flexBasis: v } : null;
2251
- },
2252
- grow: ({ value }, _) => {
2253
- if (!value) return { flexGrow: 1 };
2254
- const n = parseFloat(value);
2255
- return { flexGrow: isNaN(n) ? 1 : n };
2256
- },
2257
- shrink: ({ value }, _) => {
2258
- if (!value) return { flexShrink: 1 };
2259
- const n = parseFloat(value);
2260
- return { flexShrink: isNaN(n) ? 1 : n };
2261
- },
2262
- order: ({ value, negative }, _) => {
2263
- const n = parseInt(value, 10);
2264
- return isNaN(n) ? null : { order: negative ? -n : n };
2265
- },
2266
- // ── Gap ────────────────────────────────────────────────────────────────────
2267
- gap: ({ value, negative, isArbitrary }, { spacing }) => {
2268
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2269
- return v !== null ? { gap: v } : null;
2270
- },
2271
- "gap-x": ({ value, negative, isArbitrary }, { spacing }) => {
2272
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2273
- return v !== null ? { columnGap: v } : null;
2274
- },
2275
- "gap-y": ({ value, negative, isArbitrary }, { spacing }) => {
2276
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2277
- return v !== null ? { rowGap: v } : null;
2278
- },
2279
- // ── Position ───────────────────────────────────────────────────────────────
2280
- top: ({ value, negative, isArbitrary }, { spacing }) => {
2281
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2282
- return v !== null ? { top: v } : null;
2283
- },
2284
- right: ({ value, negative, isArbitrary }, { spacing }) => {
2285
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2286
- return v !== null ? { right: v } : null;
2287
- },
2288
- bottom: ({ value, negative, isArbitrary }, { spacing }) => {
2289
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2290
- return v !== null ? { bottom: v } : null;
2291
- },
2292
- left: ({ value, negative, isArbitrary }, { spacing }) => {
2293
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2294
- return v !== null ? { left: v } : null;
2295
- },
2296
- inset: ({ value, negative, isArbitrary }, { spacing }) => {
2297
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2298
- return v !== null ? { top: v, right: v, bottom: v, left: v } : null;
2299
- },
2300
- "inset-x": ({ value, negative, isArbitrary }, { spacing }) => {
2301
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2302
- return v !== null ? { left: v, right: v } : null;
2303
- },
2304
- "inset-y": ({ value, negative, isArbitrary }, { spacing }) => {
2305
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2306
- return v !== null ? { top: v, bottom: v } : null;
2307
- },
2308
- // ── Z-index ────────────────────────────────────────────────────────────────
2309
- z: ({ value, isArbitrary }, { zIndex }) => {
2310
- if (isArbitrary) {
2311
- const n2 = parseInt(value);
2312
- return isNaN(n2) ? null : { zIndex: n2 };
2313
- }
2314
- const v = zIndex[value];
2315
- if (v !== void 0) {
2316
- if (v === "auto") return getEffectiveIsWeb() ? { zIndex: "auto" } : null;
2317
- return { zIndex: v };
2318
- }
2319
- const n = parseInt(value);
2320
- return isNaN(n) ? null : { zIndex: n };
2321
- },
2322
- // ── Opacity ────────────────────────────────────────────────────────────────
2323
- opacity: ({ value, isArbitrary }, { opacity }) => {
2324
- if (isArbitrary) {
2325
- const v2 = parseFloat(value);
2326
- return isNaN(v2) ? null : { opacity: v2 > 1 ? v2 / 100 : v2 };
2327
- }
2328
- const v = opacity[value];
2329
- if (v !== void 0) return { opacity: v };
2330
- const n = parseFloat(value);
2331
- return isNaN(n) ? null : { opacity: n > 1 ? n / 100 : n };
2332
- },
2333
- // ── Font ───────────────────────────────────────────────────────────────────
2334
- font: ({ value, isArbitrary }, { fontFamily, fontWeight }) => {
2335
- if (isArbitrary) return { fontFamily: value };
2336
- if (value in fontFamily) {
2337
- const ff = fontFamily[value];
2338
- return { fontFamily: Array.isArray(ff) ? ff.join(", ") : ff };
2339
- }
2340
- if (value in fontWeight) return { fontWeight: String(fontWeight[value]) };
2341
- return null;
2342
- },
2343
- // ── Line height ────────────────────────────────────────────────────────────
2344
- leading: ({ value, isArbitrary }, { lineHeight }) => {
2345
- if (isArbitrary) return { lineHeight: getEffectiveIsWeb() ? value : toNativeValue(value) };
2346
- const v = lineHeight[value];
2347
- if (v === void 0) return null;
2348
- if (typeof v === "string" && !getEffectiveIsWeb()) return { lineHeight: toNativeValue(v) };
2349
- return { lineHeight: v };
2350
- },
2351
- // ── Letter spacing ─────────────────────────────────────────────────────────
2352
- tracking: ({ value, isArbitrary }, { letterSpacing }) => {
2353
- if (isArbitrary) return { letterSpacing: getEffectiveIsWeb() ? value : toNativeValue(value) };
2354
- const v = letterSpacing[value];
2355
- return v !== void 0 ? { letterSpacing: v } : null;
2356
- },
2357
- // ── Shadow ─────────────────────────────────────────────────────────────────
2358
- shadow: ({ value }, { shadow }) => {
2359
- const key = value === "" ? "DEFAULT" : value;
2360
- return shadow[key] ?? null;
2361
- },
2362
- // ── Scale ──────────────────────────────────────────────────────────────────
2363
- // Non-arbitrary: scale-150 → value='150' → 150/100 = 1.5
2364
- // Arbitrary: scale-[1.5] → value='1.5' → used as-is (already the factor)
2365
- scale: ({ value, isArbitrary }) => {
2366
- const n = isArbitrary ? parseFloat(value) : parseFloat(value) / 100;
2367
- if (isNaN(n)) return null;
2368
- return getEffectiveIsWeb() ? { transform: `scale(${n})` } : { transform: [{ scale: n }] };
2369
- },
2370
- "scale-x": ({ value, isArbitrary }) => {
2371
- const n = isArbitrary ? parseFloat(value) : parseFloat(value) / 100;
2372
- if (isNaN(n)) return null;
2373
- return getEffectiveIsWeb() ? { transform: `scaleX(${n})` } : { transform: [{ scaleX: n }] };
2374
- },
2375
- "scale-y": ({ value, isArbitrary }) => {
2376
- const n = isArbitrary ? parseFloat(value) : parseFloat(value) / 100;
2377
- if (isNaN(n)) return null;
2378
- return getEffectiveIsWeb() ? { transform: `scaleY(${n})` } : { transform: [{ scaleY: n }] };
2379
- },
2380
- // ── Rotate ─────────────────────────────────────────────────────────────────
2381
- rotate: ({ value, negative, isArbitrary }) => {
2382
- if (isArbitrary) {
2383
- const finalValue = negative ? `-${value}` : value;
2384
- return getEffectiveIsWeb() ? { transform: `rotate(${finalValue})` } : { transform: [{ rotate: finalValue }] };
2385
- }
2386
- const deg = parseFloat(value);
2387
- if (isNaN(deg)) return null;
2388
- const finalDeg = negative ? -deg : deg;
2389
- return getEffectiveIsWeb() ? { transform: `rotate(${finalDeg}deg)` } : { transform: [{ rotate: `${finalDeg}deg` }] };
2390
- },
2391
- // ── Translate ──────────────────────────────────────────────────────────────
2392
- "translate-x": ({ value, negative, isArbitrary }, { spacing }) => {
2393
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2394
- if (v === null) return null;
2395
- if (getEffectiveIsWeb()) return { transform: `translateX(${typeof v === "number" ? `${v}px` : v})` };
2396
- if (typeof v === "string") {
2397
- const n = parseFloat(v);
2398
- return isNaN(n) ? null : { transform: [{ translateX: n }] };
2399
- }
2400
- return { transform: [{ translateX: v }] };
2401
- },
2402
- "translate-y": ({ value, negative, isArbitrary }, { spacing }) => {
2403
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2404
- if (v === null) return null;
2405
- if (getEffectiveIsWeb()) return { transform: `translateY(${typeof v === "number" ? `${v}px` : v})` };
2406
- if (typeof v === "string") {
2407
- const n = parseFloat(v);
2408
- return isNaN(n) ? null : { transform: [{ translateY: n }] };
2409
- }
2410
- return { transform: [{ translateY: v }] };
2411
- },
2412
- // ── Aspect ratio ───────────────────────────────────────────────────────────
2413
- aspect: ({ value, isArbitrary }) => {
2414
- if (isArbitrary) return { aspectRatio: value };
2415
- const presets = { auto: "auto", square: 1, video: 16 / 9 };
2416
- if (!(value in presets)) return null;
2417
- const v = presets[value];
2418
- if (v === "auto") return getEffectiveIsWeb() ? { aspectRatio: "auto" } : null;
2419
- return { aspectRatio: v };
2420
- },
2421
- // ── Transition (web-only; use Animated API on native) ─────────────────────
2422
- transition: ({ value }) => {
2423
- if (!getEffectiveIsWeb()) return null;
2424
- const presets = {
2425
- "": "color 150ms, background-color 150ms, border-color 150ms, text-decoration-color 150ms, fill 150ms, stroke 150ms, opacity 150ms, box-shadow 150ms, transform 150ms, filter 150ms, backdrop-filter 150ms",
2426
- all: "all 150ms",
2427
- none: "none",
2428
- colors: "color 150ms, background-color 150ms, border-color 150ms",
2429
- opacity: "opacity 150ms",
2430
- shadow: "box-shadow 150ms",
2431
- transform: "transform 150ms"
2432
- };
2433
- const v = presets[value];
2434
- return v !== void 0 ? { transition: v } : null;
2435
- },
2436
- duration: ({ value, isArbitrary }) => {
2437
- if (!getEffectiveIsWeb()) return null;
2438
- if (!isArbitrary && isNaN(parseFloat(value))) return null;
2439
- const ms = isArbitrary ? value : `${value}ms`;
2440
- return { transitionDuration: ms };
2441
- },
2442
- delay: ({ value, isArbitrary }) => {
2443
- if (!getEffectiveIsWeb()) return null;
2444
- if (!isArbitrary && isNaN(parseFloat(value))) return null;
2445
- const ms = isArbitrary ? value : `${value}ms`;
2446
- return { transitionDelay: ms };
2447
- },
2448
- // ── Ring ───────────────────────────────────────────────────────────────────
2449
- // Web: box-shadow outline ring (doesn't affect layout).
2450
- // Native: React Native has no box-shadow, so this falls back to borderWidth/
2451
- // borderColor — the closest visual approximation (used by other RN Tailwind-
2452
- // likes for the same reason). Unlike the web ring, this DOES affect layout,
2453
- // and it shares its properties with the `border` utility — combining
2454
- // `border-*` and `ring-*` on the same native element means whichever class
2455
- // comes later wins, since both ultimately set borderWidth/borderColor.
2456
- ring: ({ value, isArbitrary }, { colors }) => {
2457
- const onWeb = getEffectiveIsWeb();
2458
- const DEFAULT_COLOR = "rgba(59, 130, 246, 0.5)";
2459
- const DEFAULT_WIDTH = 3;
2460
- const asNative = (w, color2) => w === 0 ? { borderWidth: 0 } : { borderWidth: w, borderColor: color2 };
2461
- if (!value) {
2462
- return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
2463
- }
2464
- if (value === "inset") {
2465
- return onWeb ? { boxShadow: `inset 0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
2466
- }
2467
- const widthTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
2468
- if (!isArbitrary && value in widthTokens) {
2469
- const w = widthTokens[value];
2470
- return onWeb ? { boxShadow: w === 0 ? "none" : `0 0 0 ${w}px ${DEFAULT_COLOR}` } : asNative(w, DEFAULT_COLOR);
2471
- }
2472
- if (isArbitrary) {
2473
- const numMatch = /^(\d+(?:\.\d+)?)(px|rem|em|vw|vh)?$/.exec(value);
2474
- if (numMatch) {
2475
- const unit = numMatch[2] ?? "px";
2476
- if (onWeb) return { boxShadow: `0 0 0 ${numMatch[1]}${unit} ${DEFAULT_COLOR}` };
2477
- return unit === "px" ? asNative(parseFloat(numMatch[1]), DEFAULT_COLOR) : null;
2478
- }
2479
- return onWeb ? { boxShadow: value.replace(/_/g, " ") } : null;
2480
- }
2481
- const color = resolveColor(value, colors, false);
2482
- if (color) {
2483
- return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${color}` } : asNative(DEFAULT_WIDTH, color);
2484
- }
2485
- return null;
2486
- },
2487
- // Web-only, unlike `ring` above: this stacks a second box-shadow layer to
2488
- // create a gap between the element and the ring. There's no native
2489
- // equivalent to approximate that with (a border can't create a gap outside
2490
- // its own element without an extra wrapper view), so this stays a no-op
2491
- // on native rather than rendering a misleading half-translation.
2492
- "ring-offset": ({ value, isArbitrary }, _theme) => {
2493
- if (!getEffectiveIsWeb()) return null;
2494
- const DEFAULT_RING_COLOR = "rgba(59, 130, 246, 0.5)";
2495
- const DEFAULT_RING_WIDTH = 3;
2496
- const offsetTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
2497
- let offsetWidth;
2498
- if (!isArbitrary) {
2499
- offsetWidth = value in offsetTokens ? offsetTokens[value] : null;
2500
- } else {
2501
- offsetWidth = /^-?\d+(\.\d+)?$/.test(value) ? parseFloat(value) : value;
2502
- }
2503
- if (offsetWidth === null || typeof offsetWidth === "number" && isNaN(offsetWidth)) return null;
2504
- const isZero = offsetWidth === 0 || offsetWidth === "0";
2505
- const offsetCss = typeof offsetWidth === "number" ? `${offsetWidth}px` : offsetWidth;
2506
- return {
2507
- boxShadow: isZero ? `0 0 0 ${DEFAULT_RING_WIDTH}px ${DEFAULT_RING_COLOR}` : `0 0 0 ${offsetCss} #fff, 0 0 0 calc(${offsetCss} + ${DEFAULT_RING_WIDTH}px) ${DEFAULT_RING_COLOR}`
2508
- };
2509
- },
2510
- // ── Space between ─────────────────────────────────────────────────────────
2511
- // On web: emits __spaceX/__spaceY markers → resolver generates > * + * CSS rules.
2512
- // On native (RN 0.71+): uses columnGap/rowGap directly.
2513
- "space-x": ({ value, negative, isArbitrary }, { spacing }) => {
2514
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2515
- if (v === null) return null;
2516
- if (getEffectiveIsWeb()) return { __spaceX: v };
2517
- return { columnGap: v };
2518
- },
2519
- "space-y": ({ value, negative, isArbitrary }, { spacing }) => {
2520
- const v = resolveSpacing(value, negative, spacing, isArbitrary);
2521
- if (v === null) return null;
2522
- if (getEffectiveIsWeb()) return { __spaceY: v };
2523
- return { rowGap: v };
2524
- }
2525
- };
2526
- for (const [utility, prop] of Object.entries(PADDING_MARGIN_PROPS)) {
2527
- RESOLVERS[utility] = makeSpacingResolver(prop);
2528
- }
2529
- for (const [utility, [widthProp, colorProp]] of Object.entries(BORDER_SIDE_PROPS)) {
2530
- RESOLVERS[utility] = makeBorderSideResolver(widthProp, colorProp);
2531
- }
2532
- var NAMED_GROUP_PEER_MARKER_RE = /^(group|peer)\/.+$/;
2533
- function resolveUtility(parsed, theme) {
2534
- if (!parsed.value) {
2535
- if (parsed.utility in PLUGIN_STANDALONE) return PLUGIN_STANDALONE[parsed.utility] ?? null;
2536
- if (parsed.utility in getStandalone()) return getStandalone()[parsed.utility] ?? null;
2537
- if (NAMED_GROUP_PEER_MARKER_RE.test(parsed.utility)) return getEffectiveIsWeb() ? {} : null;
2538
- }
2539
- const resolver = PLUGIN_RESOLVERS[parsed.utility] ?? RESOLVERS[parsed.utility];
2540
- if (resolver) return resolver(parsed, theme);
2541
- return null;
2542
- }
2543
- var PLUGIN_STANDALONE = {};
2544
- var PLUGIN_RESOLVERS = {};
2545
- function clearPluginUtilities() {
2546
- for (const key of Object.keys(PLUGIN_STANDALONE)) delete PLUGIN_STANDALONE[key];
2547
- for (const key of Object.keys(PLUGIN_RESOLVERS)) delete PLUGIN_RESOLVERS[key];
2548
- _sortedPrefixes = null;
2549
- _standaloneNames = null;
2550
- }
2551
- function getPluginStandaloneMap() {
2552
- return PLUGIN_STANDALONE;
2553
- }
2554
- function isKnownUtility(utility) {
2555
- return utility in getStandalone() || utility in RESOLVERS || utility in PLUGIN_STANDALONE || utility in PLUGIN_RESOLVERS || NAMED_GROUP_PEER_MARKER_RE.test(utility);
2556
- }
2557
- var _sortedPrefixes = null;
2558
- var _standaloneNames = null;
2559
- function getBuiltinUtilityPrefixes() {
2560
- if (!_sortedPrefixes) {
2561
- const all = [.../* @__PURE__ */ new Set([...Object.keys(RESOLVERS), ...Object.keys(PLUGIN_RESOLVERS)])];
2562
- _sortedPrefixes = all.sort((a, b) => b.length - a.length);
2563
- }
2564
- return _sortedPrefixes;
2565
- }
2566
- function getBuiltinStandaloneNames() {
2567
- if (!_standaloneNames) {
2568
- _standaloneNames = /* @__PURE__ */ new Set([...Object.keys(getStandalone()), ...Object.keys(PLUGIN_STANDALONE)]);
2569
- }
2570
- return _standaloneNames;
2571
- }
2572
-
2573
- // src/core/parser.ts
2574
- var UNSAFE_ARBITRARY_VALUE = /[{};\\]|\/\*|\*\//;
2575
- function isSafeArbitraryValue(value) {
2576
- if (!UNSAFE_ARBITRARY_VALUE.test(value)) return true;
2577
- if (process.env.NODE_ENV !== "production") {
2578
- kbachWarn(`Unsafe arbitrary value rejected: "${value}"`);
2579
- }
2580
- return false;
2581
- }
2582
- function parseClass(className) {
2583
- const trimmed = className.trim();
2584
- if (!trimmed) return null;
2585
- const modifiers = [];
2586
- let remaining = trimmed;
2587
- while (true) {
2588
- const colonIdx = findOuterColon(remaining);
2589
- if (colonIdx === -1) break;
2590
- const candidate = remaining.slice(0, colonIdx);
2591
- if (!isKnownModifier(candidate)) break;
2592
- modifiers.push(candidate);
2593
- remaining = remaining.slice(colonIdx + 1);
2594
- }
2595
- let important = false;
2596
- if (remaining.startsWith("!") && remaining.length > 1) {
2597
- important = true;
2598
- remaining = remaining.slice(1);
2599
- }
2600
- let negative = false;
2601
- if (remaining.startsWith("-") && remaining.length > 1 && remaining[1] !== "-") {
2602
- negative = true;
2603
- remaining = remaining.slice(1);
2604
- }
2605
- let bracketDepth = 0;
2606
- let bracketStart = -1;
2607
- for (let i = remaining.length - 1; i >= 0; i--) {
2608
- if (remaining[i] === "]") bracketDepth++;
2609
- else if (remaining[i] === "[") {
2610
- bracketDepth--;
2611
- if (bracketDepth === 0) {
2612
- bracketStart = i;
2613
- break;
2614
- }
2615
- }
2616
- }
2617
- if (bracketStart > 0 && remaining[bracketStart - 1] === "-" && remaining.endsWith("]")) {
2618
- const utility = remaining.slice(0, bracketStart - 1);
2619
- const value = remaining.slice(bracketStart + 1, -1).replace(/_/g, " ");
2620
- if (!isSafeArbitraryValue(value)) return null;
2621
- return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2622
- }
2623
- if (remaining.endsWith("]") && bracketStart === -1) {
2624
- if (process.env.NODE_ENV !== "production") {
2625
- kbachWarn(`Unbalanced brackets: "${trimmed}"`);
2626
- }
2627
- }
2628
- if (remaining.startsWith("[") && remaining.endsWith("]")) {
2629
- const value = remaining.slice(1, -1).replace(/_/g, " ");
2630
- if (!isSafeArbitraryValue(value)) return null;
2631
- return { original: trimmed, modifiers, negative, important, utility: "", value, isArbitrary: true };
2632
- }
2633
- if (getBuiltinStandaloneNames().has(remaining)) {
2634
- return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2635
- }
2636
- for (const prefix of getBuiltinUtilityPrefixes()) {
2637
- if (remaining === prefix) {
2638
- return { original: trimmed, modifiers, negative, important, utility: prefix, value: "", isArbitrary: false };
2639
- }
2640
- if (remaining.startsWith(prefix + "-")) {
2641
- const value = remaining.slice(prefix.length + 1);
2642
- return { original: trimmed, modifiers, negative, important, utility: prefix, value, isArbitrary: false };
2643
- }
2644
- }
2645
- const firstDash = remaining.indexOf("-");
2646
- if (firstDash > 0) {
2647
- return {
2648
- original: trimmed,
2649
- modifiers,
2650
- negative,
2651
- important,
2652
- utility: remaining.slice(0, firstDash),
2653
- value: remaining.slice(firstDash + 1),
2654
- isArbitrary: false
2655
- };
2656
- }
2657
- return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2658
- }
2659
- function splitClassTokens(classString) {
2660
- const tokens = [];
2661
- let current = "";
2662
- let depth = 0;
2663
- let parenDepth = 0;
2664
- for (let i = 0; i < classString.length; i++) {
2665
- const ch = classString[i];
2666
- if (ch === "[") {
2667
- depth++;
2668
- current += ch;
2669
- continue;
2670
- }
2671
- if (ch === "]") {
2672
- depth--;
2673
- current += ch;
2674
- continue;
2675
- }
2676
- if (ch === "(") {
2677
- parenDepth++;
2678
- current += ch;
2679
- continue;
2680
- }
2681
- if (ch === ")") {
2682
- parenDepth--;
2683
- current += ch;
2684
- continue;
2685
- }
2686
- if (/\s/.test(ch)) {
2687
- if (depth === 0 && parenDepth === 0) {
2688
- if (current) {
2689
- tokens.push(current);
2690
- current = "";
2691
- }
2692
- }
2693
- } else {
2694
- current += ch;
2695
- }
2696
- }
2697
- if (current) tokens.push(current);
2698
- return tokens;
2699
- }
2700
- function normalizeClassString(classString) {
2701
- return splitClassTokens(classString).join(" ");
2702
- }
2703
- function parseClasses(classString) {
2704
- const results = [];
2705
- for (const token of splitClassTokens(classString)) {
2706
- const parsed = parseClass(token);
2707
- if (parsed) results.push(parsed);
2708
- }
2709
- return results;
2710
- }
2711
- function findOuterColon(s) {
2712
- let depth = 0;
2713
- for (let i = 0; i < s.length; i++) {
2714
- const ch = s[i];
2715
- if (ch === "[") depth++;
2716
- else if (ch === "]") depth--;
2717
- else if (ch === ":" && depth === 0) return i;
2718
- }
2719
- return -1;
2720
- }
2721
-
2722
- // src/core/responsiveStore.ts
2723
- var RESPONSIVE_KEY = "__kbach_responsive__";
2724
- function getStore() {
2725
- const g = globalThis;
2726
- if (!g[RESPONSIVE_KEY]) {
2727
- g[RESPONSIVE_KEY] = { width: 0, notifiedWidth: 0, screens: {}, listeners: /* @__PURE__ */ new Set() };
2728
- }
2729
- return g[RESPONSIVE_KEY];
2730
- }
2731
- function getGlobalScreens() {
2732
- return getStore().screens;
2733
- }
2734
- function getGlobalWidth() {
2735
- return getStore().width;
2736
- }
2737
- function subscribeGlobalWidth(listener) {
2738
- const store = getStore();
2739
- store.listeners.add(listener);
2740
- return () => store.listeners.delete(listener);
2741
- }
2742
- function getActiveBreakpoints(width) {
2743
- const store = getStore();
2744
- const w = width ?? store.width;
2745
- const active = /* @__PURE__ */ new Set();
2746
- for (const [name, minW] of Object.entries(store.screens)) {
2747
- if (typeof minW === "number" && w >= minW) active.add(name);
2748
- }
2749
- return active;
2750
- }
2751
-
2752
- // src/core/resolver.ts
2753
- var _themeCache = /* @__PURE__ */ new WeakMap();
2754
- function getThemeCache(theme) {
2755
- let cache = _themeCache.get(theme);
2756
- if (!cache) {
2757
- cache = new LRUCache(1e4);
2758
- _themeCache.set(theme, cache);
2759
- }
2760
- return cache;
2761
- }
2762
- var _sortCache = /* @__PURE__ */ new WeakMap();
2763
- function getSortedEntries(resolved) {
2764
- let sorted = _sortCache.get(resolved);
2765
- if (!sorted) {
2766
- const entries = Object.entries(resolved);
2767
- entries.sort((a, b) => {
2768
- const pa = a[0] === "base" ? -1 : a[0].split(":").length;
2769
- const pb = b[0] === "base" ? -1 : b[0].split(":").length;
2770
- return pa - pb;
2771
- });
2772
- sorted = entries;
2773
- _sortCache.set(resolved, sorted);
2774
- }
2775
- return sorted;
2776
- }
2777
- var FONT_KEY = "__kbach_default_font__";
2778
- function setDefaultFontFamily(font) {
2779
- globalThis[FONT_KEY] = font;
2780
- }
2781
- function getDefaultFontFamily() {
2782
- return globalThis[FONT_KEY];
2783
- }
2784
- var _styleEl = null;
2785
- var _ruleIndexByKey = /* @__PURE__ */ new Map();
2786
- function evictInjectedRule(rule) {
2787
- const idx = _ruleIndexByKey.get(rule);
2788
- _ruleIndexByKey.delete(rule);
2789
- if (idx === void 0) return;
2790
- const sheet = _styleEl?.sheet;
2791
- if (!sheet) return;
2792
- try {
2793
- sheet.deleteRule(idx);
2794
- } catch {
2795
- return;
2796
- }
2797
- for (const [key, i] of _ruleIndexByKey) {
2798
- if (i > idx) _ruleIndexByKey.set(key, i - 1);
2799
- }
2800
- }
2801
- var _injectedRules = new LRUCache(5e4, evictInjectedRule);
2802
- var _CSS_DISABLED_KEY = "__kbach_runtime_css_disabled__";
2803
- function isRuntimeCSSDisabled() {
2804
- return !!globalThis[_CSS_DISABLED_KEY];
2805
- }
2806
- function getStyleEl() {
2807
- if (_styleEl) return _styleEl;
2808
- _styleEl = document.createElement("style");
2809
- _styleEl.setAttribute("data-kbach", "");
2810
- document.head.appendChild(_styleEl);
2811
- return _styleEl;
2812
- }
2813
- function injectRule(rule) {
2814
- if (isRuntimeCSSDisabled()) return;
2815
- if (_injectedRules.get(rule)) return;
2816
- try {
2817
- const sheet = getStyleEl().sheet;
2818
- if (sheet) {
2819
- const idx = sheet.cssRules.length;
2820
- sheet.insertRule(rule, idx);
2821
- _ruleIndexByKey.set(rule, idx);
2822
- _injectedRules.set(rule, true);
2823
- }
2824
- } catch {
2825
- }
2826
- }
2827
- var _globalStyleEl = null;
2828
- function getGlobalStyleEl() {
2829
- if (_globalStyleEl) return _globalStyleEl;
2830
- _globalStyleEl = document.createElement("style");
2831
- _globalStyleEl.setAttribute("data-kbach-global", "");
2832
- document.head.insertBefore(_globalStyleEl, getStyleEl());
2833
- return _globalStyleEl;
2834
- }
2835
- function injectGlobalStyles(theme) {
2836
- if (typeof document === "undefined" || isRuntimeCSSDisabled()) return;
2837
- const rules = document.getElementById(RESET_STYLE_ID) ? [] : [BASE_RESET];
2838
- const ff = theme.fontFamily;
2839
- if (ff?.sans && ff.sans !== "System") {
2840
- const family = Array.isArray(ff.sans) ? ff.sans.join(", ") : ff.sans;
2841
- rules.push(`body { font-family: ${family}; }`);
2842
- }
2843
- getGlobalStyleEl().textContent = rules.join("\n");
2844
- }
2845
- function buildDivideDecls(styles, forceImportant) {
2846
- const imp = forceImportant ? " !important" : "";
2847
- const parts = [];
2848
- if ("__divideX" in styles) {
2849
- const w = Number(styles.__divideX);
2850
- parts.push(`border-left-width: ${w}px${imp}`, `border-right-width: 0px${imp}`);
2851
- }
2852
- if ("__divideY" in styles) {
2853
- const w = Number(styles.__divideY);
2854
- parts.push(`border-top-width: ${w}px${imp}`, `border-bottom-width: 0px${imp}`);
2855
- }
2856
- if ("__divideColor" in styles) parts.push(`border-color: ${String(styles.__divideColor)}${imp}`);
2857
- if ("__divideStyle" in styles) parts.push(`border-style: ${String(styles.__divideStyle)}${imp}`);
2858
- return parts.join("; ");
2859
- }
2860
- function buildSpaceDecls(styles, forceImportant) {
2861
- const imp = forceImportant ? " !important" : "";
2862
- const parts = [];
2863
- if ("__spaceX" in styles) {
2864
- const v = styles.__spaceX;
2865
- const val = typeof v === "number" ? `${v}px` : String(v);
2866
- parts.push(`margin-left: ${val}${imp}`);
2867
- }
2868
- if ("__spaceY" in styles) {
2869
- const v = styles.__spaceY;
2870
- const val = typeof v === "number" ? `${v}px` : String(v);
2871
- parts.push(`margin-top: ${val}${imp}`);
2872
- }
2873
- return parts.join("; ");
2874
- }
2875
- var RN_ONLY_PROPS = /* @__PURE__ */ new Set([
2876
- "shadowColor",
2877
- "shadowOffset",
2878
- "shadowOpacity",
2879
- "shadowRadius",
2880
- "elevation",
2881
- "includeFontPadding",
2882
- "textAlignVertical",
2883
- "writingDirection",
2884
- "textShadowColor",
2885
- "textShadowOffset",
2886
- "textShadowRadius",
2887
- "tintColor",
2888
- "__divideX",
2889
- "__divideY",
2890
- "__divideColor",
2891
- "__divideStyle",
2892
- "__keyframe",
2893
- "__spaceX",
2894
- "__spaceY"
2895
- ]);
2896
- var CSS_UNITLESS = /* @__PURE__ */ new Set([
2897
- "opacity",
2898
- "fontWeight",
2899
- "flex",
2900
- "flexGrow",
2901
- "flexShrink",
2902
- "order",
2903
- "zIndex",
2904
- "aspectRatio",
2905
- "columnCount",
2906
- "lineHeight",
2907
- "gridColumnStart",
2908
- "gridColumnEnd",
2909
- "gridRowStart",
2910
- "gridRowEnd"
2911
- ]);
2912
- var RN_SHORTHAND_EXPAND = {
2913
- marginHorizontal: ["margin-left", "margin-right"],
2914
- marginVertical: ["margin-top", "margin-bottom"],
2915
- paddingHorizontal: ["padding-left", "padding-right"],
2916
- paddingVertical: ["padding-top", "padding-bottom"]
2917
- };
2918
- function styleValueToCSS(styles, forceImportant = false) {
2919
- const parts = [];
2920
- for (const [prop, val] of Object.entries(styles)) {
2921
- if (val === void 0 || val === null || typeof val === "object" || RN_ONLY_PROPS.has(prop)) continue;
2922
- let cssVal;
2923
- if (typeof val === "number") {
2924
- const isCustomProp = prop.startsWith("--");
2925
- cssVal = val === 0 || isCustomProp || CSS_UNITLESS.has(prop) ? String(val) : `${val}px`;
2926
- } else {
2927
- cssVal = String(val);
2928
- }
2929
- const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
2930
- if (prop in RN_SHORTHAND_EXPAND) {
2931
- const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
2932
- parts.push(`${p1}: ${cssVal}${imp}`, `${p2}: ${cssVal}${imp}`);
2933
- continue;
2934
- }
2935
- parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
2936
- }
2937
- return parts.join("; ");
2938
- }
2939
- function camelToKebab(str) {
2940
- return str.replace(/([A-Z])/g, "-$1").toLowerCase();
2941
- }
2942
- function buildClassCSSRules(cls, bucketKey, styles, darkMode, important, screens) {
2943
- const rules = [];
2944
- if ("__keyframe" in styles && typeof styles.__keyframe === "string") {
2945
- rules.push(styles.__keyframe);
2946
- }
2947
- const isDivide = "__divideX" in styles || "__divideY" in styles || "__divideColor" in styles || "__divideStyle" in styles;
2948
- const isSpace = "__spaceX" in styles || "__spaceY" in styles;
2949
- const isChildCombinator = isDivide || isSpace;
2950
- const escaped = escapeCSSSelector(cls);
2951
- const childSuffix = isChildCombinator ? " > * + *" : "";
2952
- if (bucketKey === "base") {
2953
- const decls2 = isDivide ? buildDivideDecls(styles, important) : isSpace ? buildSpaceDecls(styles, important) : styleValueToCSS(styles, important);
2954
- if (!decls2) return rules;
2955
- rules.push(`.${escaped}${childSuffix} { ${decls2} }`);
2956
- return rules;
2957
- }
2958
- const mods = bucketKey.split(":");
2959
- let darkScheme;
2960
- let needsImportant = important;
2961
- const pseudoParts = [];
2962
- const ancestorParts = [];
2963
- const dirParts = [];
2964
- const mediaWrappers = [];
2965
- let minWidth = 0;
2966
- for (const mod of mods) {
2967
- const def = getModifier(mod);
2968
- if (!def) continue;
2969
- if (def.darkScheme) darkScheme = def.darkScheme;
2970
- if (def.pseudo) pseudoParts.push(def.pseudo);
2971
- if (def.ancestorSelector) {
2972
- ancestorParts.push(def.ancestorSelector);
2973
- needsImportant = true;
2974
- }
2975
- if (def.dirSelector) {
2976
- dirParts.push(def.dirSelector);
2977
- needsImportant = true;
2978
- }
2979
- if (def.mediaQuery) {
2980
- mediaWrappers.push(`@media ${def.mediaQuery}`);
2981
- needsImportant = true;
2982
- }
2983
- if (def.isResponsive) {
2984
- const w = screens[mod] ?? 0;
2985
- if (w > minWidth) minWidth = w;
2986
- }
2987
- if (def.forcesImportant) needsImportant = true;
2988
- }
2989
- const pseudoSuffix = pseudoParts.join("");
2990
- const elementSelector = `.${escaped}${pseudoSuffix}${childSuffix}`;
2991
- const ancestorPrefix = ancestorParts.join("");
2992
- const dirPrefix = dirParts.join("");
2993
- const selector = `${dirPrefix}${ancestorPrefix}${elementSelector}`;
2994
- const decls = isDivide ? buildDivideDecls(styles, needsImportant) : isSpace ? buildSpaceDecls(styles, needsImportant) : styleValueToCSS(styles, needsImportant);
2995
- if (!decls) return rules;
2996
- let rule;
2997
- if (darkScheme === "dark") {
2998
- if (darkMode === "media") rule = `@media (prefers-color-scheme: dark) { ${selector} { ${decls} } }`;
2999
- else if (darkMode === "class") rule = `.dark ${selector} { ${decls} }`;
3000
- else rule = `[data-theme="dark"] ${selector} { ${decls} }`;
3001
- } else if (darkScheme === "light") {
3002
- if (darkMode === "media") rule = `@media (prefers-color-scheme: light) { ${selector} { ${decls} } }`;
3003
- else if (darkMode === "class") rule = `.light ${selector} { ${decls} }`;
3004
- else rule = `[data-theme="light"] ${selector} { ${decls} }`;
3005
- } else {
3006
- rule = `${selector} { ${decls} }`;
3007
- }
3008
- for (const mw of mediaWrappers) rule = `${mw} { ${rule} }`;
3009
- if (minWidth > 0) rule = `@media (min-width: ${minWidth}px) { ${rule} }`;
3010
- rules.push(rule);
3011
- return rules;
3012
- }
3013
- function injectClassRule(cls, bucketKey, styles, darkMode, important) {
3014
- const cssRules = buildClassCSSRules(cls, bucketKey, styles, darkMode, important, getGlobalScreens());
3015
- for (const r of cssRules) injectRule(r);
3016
- }
3017
- function resolve(classString, theme, darkMode = "attribute") {
3018
- const cache = getThemeCache(theme);
3019
- const cacheKey = `${classString}::${darkMode}`;
3020
- const cached = cache.get(cacheKey);
3021
- if (cached) return cached;
3022
- const result = {};
3023
- const onWeb = isWeb;
3024
- for (const parsed of parseClasses(classString)) {
3025
- const styles = resolveUtility(parsed, theme);
3026
- if (!styles) {
3027
- if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility) && !parsed.original.startsWith("__")) {
3028
- kbachWarn(`Unknown class "${parsed.original}"`);
3029
- }
3030
- continue;
3031
- }
3032
- const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
3033
- if (!result[bucketKey]) result[bucketKey] = {};
3034
- Object.assign(result[bucketKey], styles);
3035
- if (onWeb) {
3036
- injectClassRule(parsed.original, bucketKey, styles, darkMode, parsed.important);
3037
- }
3038
- }
3039
- cache.set(cacheKey, result);
3040
- return result;
3041
- }
3042
- function flatten(resolved, isDark, state = {}, breakpoints = /* @__PURE__ */ new Set()) {
3043
- const result = {};
3044
- for (const [key, styles] of getSortedEntries(resolved)) {
3045
- if (!styles) continue;
3046
- if (key === "base") {
3047
- Object.assign(result, styles);
3048
- continue;
3049
- }
3050
- const mods = key.split(":");
3051
- if (mods.every((mod) => matchModifier(mod, isDark, state, breakpoints))) {
3052
- Object.assign(result, styles);
3053
- }
3054
- }
3055
- if (isNative) {
3056
- const defaultFont = getDefaultFontFamily();
3057
- if (defaultFont && !("fontFamily" in result)) {
3058
- result.fontFamily = defaultFont;
3059
- }
3060
- }
3061
- if (!isNative) {
3062
- const r = result;
3063
- const ph = r.paddingHorizontal;
3064
- if (ph !== void 0) {
3065
- r.paddingLeft = ph;
3066
- r.paddingRight = ph;
3067
- delete r.paddingHorizontal;
3068
- }
3069
- const pv = r.paddingVertical;
3070
- if (pv !== void 0) {
3071
- r.paddingTop = pv;
3072
- r.paddingBottom = pv;
3073
- delete r.paddingVertical;
3074
- }
3075
- const mh = r.marginHorizontal;
3076
- if (mh !== void 0) {
3077
- r.marginLeft = mh;
3078
- r.marginRight = mh;
3079
- delete r.marginHorizontal;
3080
- }
3081
- const mv = r.marginVertical;
3082
- if (mv !== void 0) {
3083
- r.marginTop = mv;
3084
- r.marginBottom = mv;
3085
- delete r.marginVertical;
3086
- }
3087
- }
3088
- return result;
3089
- }
3090
-
3091
- // src/core/config.ts
3092
- function deepMerge(base, override) {
3093
- const result = { ...base };
3094
- for (const key of Object.keys(override)) {
3095
- const baseVal = base[key];
3096
- const overVal = override[key];
3097
- if (baseVal !== null && typeof baseVal === "object" && !Array.isArray(baseVal) && overVal !== null && typeof overVal === "object" && !Array.isArray(overVal)) {
3098
- result[key] = deepMerge(
3099
- baseVal,
3100
- overVal
3101
- );
3102
- } else if (overVal !== void 0) {
3103
- result[key] = overVal;
3104
- }
3105
- }
3106
- return result;
3107
- }
3108
- var CONFIG_KEY = "__kbach_config_store__";
3109
- function getConfigStore() {
3110
- const g = globalThis;
3111
- if (!g[CONFIG_KEY]) {
3112
- g[CONFIG_KEY] = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
3113
- }
3114
- return g[CONFIG_KEY];
3115
- }
3116
- function getConfig() {
3117
- const store = getConfigStore();
3118
- if (store.resolved) return store.resolved;
3119
- store.resolved = buildConfig({});
3120
- return store.resolved;
3121
- }
3122
- function resolveOneRef(ref, colors) {
3123
- const lastDash = ref.lastIndexOf("-");
3124
- if (lastDash <= 0) return null;
3125
- const name = ref.slice(0, lastDash);
3126
- const shade = ref.slice(lastDash + 1);
3127
- if (!/^\d+$/.test(shade)) return null;
3128
- const entry = colors[name];
3129
- if (!entry || typeof entry !== "object") return null;
3130
- return entry[shade] ?? null;
3131
- }
3132
- function resolveColorRefs(colors) {
3133
- const MAX_DEPTH = 5;
3134
- function resolveChain(raw) {
3135
- let current = raw;
3136
- for (let i = 0; i < MAX_DEPTH; i++) {
3137
- const next = resolveOneRef(current, colors);
3138
- if (!next || next === current) break;
3139
- current = next;
3140
- }
3141
- return current;
3142
- }
3143
- const out = {};
3144
- for (const [key, val] of Object.entries(colors)) {
3145
- if (typeof val === "string") {
3146
- out[key] = resolveChain(val);
3147
- } else {
3148
- const shades = {};
3149
- for (const [shade, hex] of Object.entries(val)) {
3150
- shades[shade] = resolveChain(hex);
3151
- }
3152
- out[key] = shades;
3153
- }
3154
- }
3155
- return out;
3156
- }
3157
- function buildConfig(userConfig) {
3158
- let theme = { ...defaultTheme };
3159
- if (userConfig.theme) {
3160
- theme = { ...theme, ...userConfig.theme };
3161
- }
3162
- if (userConfig.extend) {
3163
- const extendConfig = userConfig.extend;
3164
- const { theme: nestedTheme, ...directKeys } = extendConfig;
3165
- const extSources = [];
3166
- if (nestedTheme) extSources.push(nestedTheme);
3167
- if (Object.keys(directKeys).length) extSources.push(directKeys);
3168
- for (const ext of extSources) {
3169
- for (const [key, value] of Object.entries(ext)) {
3170
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
3171
- if (process.env.NODE_ENV !== "production") {
3172
- kbachWarn(`extend.${key} should be an object, got ${typeof value} \u2014 skipped`);
3173
- }
3174
- continue;
3175
- }
3176
- if (value !== null && typeof value === "object" && !Array.isArray(value)) {
3177
- theme[key] = deepMerge(
3178
- theme[key] ?? {},
3179
- value
3180
- );
3181
- }
3182
- }
3183
- }
3184
- }
3185
- theme = { ...theme, colors: resolveColorRefs(theme.colors) };
3186
- const resolved = {
3187
- darkMode: userConfig.darkMode ?? "attribute",
3188
- theme,
3189
- plugins: userConfig.plugins ?? []
3190
- };
3191
- if (userConfig.plugins !== void 0) {
3192
- clearPluginUtilities();
3193
- clearPluginModifiers();
3194
- }
3195
- const _store = getConfigStore();
3196
- for (const k of Object.keys(_store.customVariants)) delete _store.customVariants[k];
3197
- const pluginAPI = makePluginAPI(resolved.theme);
3198
- for (const plugin of resolved.plugins) {
3199
- plugin(pluginAPI);
3200
- }
3201
- const rawSans = theme.fontFamily?.sans;
3202
- const sansFontValue = Array.isArray(rawSans) ? rawSans[0] : rawSans;
3203
- setDefaultFontFamily(sansFontValue && sansFontValue !== "System" ? sansFontValue : void 0);
3204
- injectGlobalStyles(resolved.theme);
3205
- return resolved;
3206
- }
3207
- function _selectorToModifierDef(selector) {
3208
- const s = selector.trim();
3209
- if (s.startsWith("@media ")) {
3210
- return { mediaQuery: s.slice(7), jsBehavior: "css-only", forcesImportant: true };
3211
- }
3212
- if (s.startsWith("::") || s.startsWith(":") && !s.includes(" ") && !s.includes("&") && !s.includes("(")) {
3213
- return { pseudo: s, jsBehavior: "css-only", forcesImportant: true };
3214
- }
3215
- return { ancestorSelector: s.endsWith(" ") ? s : `${s} `, jsBehavior: "css-only", forcesImportant: true };
3216
- }
3217
- function makePluginAPI(theme) {
3218
- const standalone = getPluginStandaloneMap();
3219
- return {
3220
- addUtility(name, styles) {
3221
- standalone[name] = styles;
3222
- },
3223
- addVariant(name, selectorOrDef) {
3224
- const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
3225
- const selector = typeof selectorOrDef === "string" ? selectorOrDef : selectorOrDef.pseudo ?? selectorOrDef.mediaQuery ?? selectorOrDef.ancestorSelector ?? null;
3226
- if (selector !== null && selector !== name) customVariants[name] = selector;
3227
- registerModifier(name, def);
3228
- },
3229
- theme(path, defaultValue) {
3230
- const parts = path.replace(/\[([^\]]+)\]/g, ".$1").split(".");
3231
- let current = theme;
3232
- for (const part of parts) {
3233
- if (current === null || typeof current !== "object") return defaultValue;
3234
- current = current[part];
3235
- }
3236
- return current ?? defaultValue;
3237
- },
3238
- e(className) {
3239
- return className.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
3240
- }
3241
- };
3242
- }
3243
- function onConfigChange(listener) {
3244
- const store = getConfigStore();
3245
- store.listeners.add(listener);
3246
- return () => store.listeners.delete(listener);
3247
- }
3248
- var customVariants = new Proxy(
3249
- {},
3250
- {
3251
- get(_t, p) {
3252
- return typeof p === "string" ? getConfigStore().customVariants[p] : void 0;
3253
- },
3254
- set(_t, p, v) {
3255
- if (typeof p === "string") getConfigStore().customVariants[p] = v;
3256
- return true;
3257
- },
3258
- ownKeys() {
3259
- return Object.keys(getConfigStore().customVariants);
3260
- },
3261
- getOwnPropertyDescriptor(_t, p) {
3262
- if (typeof p !== "string") return void 0;
3263
- const v = getConfigStore().customVariants[p];
3264
- return v !== void 0 ? { value: v, writable: true, enumerable: true, configurable: true } : void 0;
3265
- }
3266
- }
3267
- );
3268
-
3269
- // src/core/darkModeStore.ts
3270
- var KEY = "__kbach_dark_store__";
3271
- function getStore2() {
3272
- const g = globalThis;
3273
- if (!g[KEY]) {
3274
- g[KEY] = { isDark: false, notifiedIsDark: false, subscribers: /* @__PURE__ */ new Set() };
3275
- }
3276
- return g[KEY];
3277
- }
3278
- function getGlobalDarkMode() {
3279
- return getStore2().isDark;
3280
- }
3281
- function subscribeGlobalDarkMode(callback) {
3282
- const store = getStore2();
3283
- store.subscribers.add(callback);
3284
- return () => store.subscribers.delete(callback);
3285
- }
43
+ var import_core6 = require("./core");
3286
44
 
3287
45
  // src/InteractiveWrapper.tsx
3288
46
  var import_react2 = __toESM(require("react"));
47
+ var import_core4 = require("./core");
48
+
49
+ // src/useGlobalDarkMode.ts
50
+ var import_core = require("./core");
3289
51
 
3290
52
  // src/useSyncExternalStoreShim.ts
3291
53
  var import_react = __toESM(require("react"));
3292
- var useSyncExternalStore = import_react.default.useSyncExternalStore ?? function useSyncExternalStoreFallback(subscribe, getSnapshot, _getServerSnapshot) {
54
+ var useSyncExternalStore = import_react.default.useSyncExternalStore ?? function useSyncExternalStoreFallback(subscribe, getSnapshot, getServerSnapshot) {
55
+ const isServer = typeof window === "undefined";
3293
56
  const [, forceUpdate] = import_react.default.useReducer((n) => n + 1, 0);
3294
- import_react.default.useEffect(() => subscribe(forceUpdate), [subscribe]);
3295
- return getSnapshot();
57
+ const value = isServer && getServerSnapshot ? getServerSnapshot() : getSnapshot();
58
+ import_react.default.useEffect(() => {
59
+ if (getSnapshot() !== value) forceUpdate();
60
+ return subscribe(forceUpdate);
61
+ }, [subscribe]);
62
+ return value;
3296
63
  };
3297
64
 
3298
65
  // src/useGlobalDarkMode.ts
@@ -3301,13 +68,14 @@ var NOOP_SUB = (_) => () => {
3301
68
  var FALSE_SNAP = () => false;
3302
69
  function useConditionalGlobalDarkMode(active) {
3303
70
  return useSyncExternalStore(
3304
- active ? subscribeGlobalDarkMode : NOOP_SUB,
3305
- active ? getGlobalDarkMode : FALSE_SNAP,
71
+ active ? import_core.subscribeGlobalDarkMode : NOOP_SUB,
72
+ active ? import_core.getGlobalDarkMode : FALSE_SNAP,
3306
73
  FALSE_SNAP
3307
74
  );
3308
75
  }
3309
76
 
3310
77
  // src/useGlobalWidth.ts
78
+ var import_core2 = require("./core");
3311
79
  var NOOP_SUB2 = (_) => () => {
3312
80
  };
3313
81
  var ZERO_SNAP = () => 0;
@@ -3342,15 +110,16 @@ function getWebWidth() {
3342
110
  }
3343
111
  function useConditionalWidth(active) {
3344
112
  return useSyncExternalStore(
3345
- active ? isWeb ? subscribeWebWidth : subscribeGlobalWidth : NOOP_SUB2,
3346
- active ? isWeb ? getWebWidth : getGlobalWidth : ZERO_SNAP,
113
+ active ? import_core2.isWeb ? subscribeWebWidth : import_core2.subscribeGlobalWidth : NOOP_SUB2,
114
+ active ? import_core2.isWeb ? getWebWidth : import_core2.getGlobalWidth : ZERO_SNAP,
3347
115
  ZERO_SNAP
3348
116
  );
3349
117
  }
3350
118
 
3351
119
  // src/shared-utils.ts
120
+ var import_core3 = require("./core");
3352
121
  function hasResponsiveBuckets(resolved) {
3353
- const responsiveMods = getResponsiveModifiers();
122
+ const responsiveMods = (0, import_core3.getResponsiveModifiers)();
3354
123
  for (const key of Object.keys(resolved)) {
3355
124
  if (key === "base") continue;
3356
125
  for (const mod of key.split(":")) {
@@ -3415,11 +184,11 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
3415
184
  onBlur,
3416
185
  ...rest
3417
186
  }, ref) {
3418
- const isWebPlatform = getEffectiveIsWeb();
187
+ const isWebPlatform = (0, import_core4.getEffectiveIsWeb)();
3419
188
  const isDark = useConditionalGlobalDarkMode(!isWebPlatform);
3420
189
  const needsWidth = hasResponsiveBuckets(resolvedStyle);
3421
190
  const width = useConditionalWidth(needsWidth && !isWebPlatform);
3422
- const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS;
191
+ const breakpoints = needsWidth ? (0, import_core4.getActiveBreakpoints)(width) : EMPTY_BREAKPOINTS;
3423
192
  const [pressed, setPressed] = (0, import_react2.useState)(false);
3424
193
  const [hovered, setHovered] = (0, import_react2.useState)(false);
3425
194
  const [focused, setFocused] = (0, import_react2.useState)(false);
@@ -3454,15 +223,16 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
3454
223
  if (!isWebPlatform) setFocused(false);
3455
224
  }), [onBlur, isWebPlatform]);
3456
225
  const { children, disabled, checked, ...restForComponent } = rest;
226
+ const isNonStringComponent = typeof Component !== "string";
3457
227
  const computedStyle = (0, import_react2.useMemo)(
3458
228
  () => {
3459
229
  if (isWebPlatform) return {};
3460
- const s = flatten(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused, disabled: !!disabled, checked: !!checked }, breakpoints);
230
+ const s = (0, import_core4.flatten)(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused, disabled: !!disabled, checked: !!checked }, breakpoints);
3461
231
  stripInternalMarkers(s);
3462
- if (typeof Component !== "string") stripWebOnlyProps(s);
232
+ if (isNonStringComponent) stripWebOnlyProps(s);
3463
233
  return s;
3464
234
  },
3465
- [resolvedStyle, isDark, pressed, hovered, focused, width, disabled, checked]
235
+ [resolvedStyle, isDark, pressed, hovered, focused, width, disabled, checked, isNonStringComponent]
3466
236
  );
3467
237
  const skipComputedInline = isWebPlatform;
3468
238
  const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
@@ -3472,7 +242,7 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
3472
242
  ...disabled !== void 0 ? { disabled } : {},
3473
243
  ...checked !== void 0 ? { checked } : {},
3474
244
  style: finalStyle,
3475
- ...!isNative && className ? { className } : {},
245
+ ...!import_core4.isNative && className ? { className } : {},
3476
246
  // On web, onPointerDown/Up drive the wrapper's own pressed state (covers mouse + touch) —
3477
247
  // onPressIn/onPressOut are RN-only prop names and are never forwarded here, even when
3478
248
  // Component isn't a literal HTML tag string. A non-string Component on web is just as
@@ -3486,7 +256,7 @@ var InteractiveWrapper = (0, import_react2.forwardRef)(
3486
256
  // in jsx-runtime.tsx swaps it for a plain host tag — so keeping them pre-hydration would
3487
257
  // only have traded one prop-mismatch warning for another.) Genuinely native code paths
3488
258
  // still get them via the isNative branch below.
3489
- ...!isNative ? {
259
+ ...!import_core4.isNative ? {
3490
260
  onPointerDown: handlePointerDown,
3491
261
  onPointerUp: handlePointerUp,
3492
262
  onPointerLeave: handlePointerLeave,
@@ -3504,18 +274,19 @@ InteractiveWrapper.displayName = "Kbach.InteractiveWrapper";
3504
274
 
3505
275
  // src/DarkWrapper.tsx
3506
276
  var import_react3 = __toESM(require("react"));
277
+ var import_core5 = require("./core");
3507
278
  var DarkWrapper = import_react3.default.forwardRef(
3508
279
  function DarkWrapper2({ Component, resolvedStyle, style: styleProp, children, ...rest }, ref) {
3509
- const isWebPlatform = getEffectiveIsWeb();
280
+ const isWebPlatform = (0, import_core5.getEffectiveIsWeb)();
3510
281
  const isDark = useConditionalGlobalDarkMode(!isWebPlatform);
3511
282
  const needsWidth = hasResponsiveBuckets(resolvedStyle);
3512
283
  const width = useConditionalWidth(needsWidth && !isWebPlatform);
3513
- const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS;
3514
- const screens = getGlobalScreens();
284
+ const breakpoints = needsWidth ? (0, import_core5.getActiveBreakpoints)(width) : EMPTY_BREAKPOINTS;
285
+ const screens = (0, import_core5.getGlobalScreens)();
3515
286
  const isNonStringComponent = typeof Component !== "string";
3516
287
  const computedStyle = (0, import_react3.useMemo)(() => {
3517
288
  if (isWebPlatform) return {};
3518
- const s = flatten(resolvedStyle, isDark, {}, breakpoints);
289
+ const s = (0, import_core5.flatten)(resolvedStyle, isDark, {}, breakpoints);
3519
290
  stripInternalMarkers(s);
3520
291
  if (isNonStringComponent) stripWebOnlyProps(s);
3521
292
  return s;
@@ -3814,11 +585,11 @@ function _invalidateDefaultFontCache() {
3814
585
  const _KEY = "__kbach_font_cache_unsub__";
3815
586
  const g = globalThis;
3816
587
  if (g[_KEY]) g[_KEY]();
3817
- g[_KEY] = onConfigChange(_invalidateDefaultFontCache);
588
+ g[_KEY] = (0, import_core6.onConfigChange)(_invalidateDefaultFontCache);
3818
589
  }
3819
590
  function getCachedDefaultFont() {
3820
591
  if (_lastFontVersion !== _defaultFontVersion) {
3821
- _cachedDefaultFont = getDefaultFontFamily();
592
+ _cachedDefaultFont = (0, import_core6.getDefaultFontFamily)();
3822
593
  _lastFontVersion = _defaultFontVersion;
3823
594
  }
3824
595
  return _cachedDefaultFont;
@@ -3827,9 +598,9 @@ var _bucketModsCache = /* @__PURE__ */ new WeakMap();
3827
598
  function bucketMods(resolved) {
3828
599
  const cached = _bucketModsCache.get(resolved);
3829
600
  if (cached) return cached;
3830
- const interactiveMods = getInteractiveModifiers();
3831
- const modeMods = getModeModifiers();
3832
- const responsiveMods = getResponsiveModifiers();
601
+ const interactiveMods = (0, import_core6.getInteractiveModifiers)();
602
+ const modeMods = (0, import_core6.getModeModifiers)();
603
+ const responsiveMods = (0, import_core6.getResponsiveModifiers)();
3833
604
  let interactive = false;
3834
605
  let modeOrResponsive = false;
3835
606
  for (const key of Object.keys(resolved)) {
@@ -3862,18 +633,22 @@ function makeElement(isStaticChildren, type, props, key) {
3862
633
  }
3863
634
  function processElement(type, rawProps, key, isStaticChildren) {
3864
635
  if (type === null || typeof type === "symbol") return makeElement(isStaticChildren, type, rawProps ?? {}, key);
3865
- const webTag = getEffectiveIsWeb() ? getWebTag(type, rawProps ?? void 0) : null;
636
+ const webTag = (0, import_core6.getEffectiveIsWeb)() ? getWebTag(type, rawProps ?? void 0) : null;
3866
637
  const effectiveType = webTag ?? type;
3867
638
  const originalName = webTag ? type?.displayName ?? type?.name : void 0;
3868
639
  if (!rawProps) return (0, import_jsx_runtime.jsx)(effectiveType, null, key);
3869
640
  const workingProps = webTag && originalName ? transformToWebProps(originalName, webTag, rawProps) : rawProps;
3870
641
  const { className, kb: kbProp, __kbachStyles, __kbachClasses } = workingProps;
3871
- const classStr = className ?? kbProp ?? __kbachClasses;
3872
- if (!isNative && isRuntimeCSSDisabled() && classStr && !__kbachStyles) {
642
+ const classStrRaw = className ?? kbProp ?? __kbachClasses;
643
+ if (classStrRaw !== void 0 && typeof classStrRaw !== "string") {
644
+ return makeElement(isStaticChildren, effectiveType, workingProps, key);
645
+ }
646
+ const classStr = classStrRaw;
647
+ if (!import_core6.isNative && (0, import_core6.isRuntimeCSSDisabled)() && classStr && !__kbachStyles) {
3873
648
  const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
3874
649
  return makeElement(isStaticChildren, effectiveType, {
3875
650
  ...passProps2,
3876
- className: normalizeClassString(classStr),
651
+ className: (0, import_core6.normalizeClassString)(classStr),
3877
652
  ...userStyle2 !== void 0 ? { style: userStyle2 } : {}
3878
653
  }, key);
3879
654
  }
@@ -3886,22 +661,22 @@ function processElement(type, rawProps, key, isStaticChildren) {
3886
661
  }, key);
3887
662
  }
3888
663
  if (!classStr && !__kbachStyles) {
3889
- if (getEffectiveIsWeb()) return makeElement(isStaticChildren, effectiveType, omitConsumed(workingProps), key);
664
+ if ((0, import_core6.getEffectiveIsWeb)()) return makeElement(isStaticChildren, effectiveType, omitConsumed(workingProps), key);
3890
665
  const defaultFont = getCachedDefaultFont();
3891
666
  if (!defaultFont) return makeElement(isStaticChildren, effectiveType, workingProps, key);
3892
667
  const { style: userStyle2, ...passProps2 } = omitConsumed(workingProps);
3893
668
  const finalStyle2 = userStyle2 ? Array.isArray(userStyle2) ? { fontFamily: defaultFont, ...Object.assign({}, ...userStyle2) } : { fontFamily: defaultFont, ...userStyle2 } : { fontFamily: defaultFont };
3894
669
  return makeElement(isStaticChildren, effectiveType, { ...passProps2, style: finalStyle2 }, key);
3895
670
  }
3896
- const config = getConfig();
3897
- const resolved = !isWeb && __kbachStyles != null ? __kbachStyles : classStr ? resolve(classStr, config.theme, config.darkMode) : {};
671
+ const config = (0, import_core6.getConfig)();
672
+ const resolved = !import_core6.isWeb && __kbachStyles != null ? __kbachStyles : classStr ? (0, import_core6.resolve)(classStr, config.theme, config.darkMode) : {};
3898
673
  const { style: userStyle, ...passProps } = omitConsumed(workingProps);
3899
674
  const { interactive, modeOrResponsive } = bucketMods(resolved);
3900
675
  if (interactive) {
3901
676
  return (0, import_jsx_runtime.jsx)(InteractiveWrapper, {
3902
677
  Component: effectiveType,
3903
678
  resolvedStyle: resolved,
3904
- ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
679
+ ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {},
3905
680
  style: userStyle,
3906
681
  ...passProps
3907
682
  }, key);
@@ -3910,15 +685,15 @@ function processElement(type, rawProps, key, isStaticChildren) {
3910
685
  return (0, import_jsx_runtime.jsx)(DarkWrapper, {
3911
686
  Component: effectiveType,
3912
687
  resolvedStyle: resolved,
3913
- ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {},
688
+ ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {},
3914
689
  style: userStyle,
3915
690
  ...passProps
3916
691
  }, key);
3917
692
  }
3918
- const skipComputedInline = getEffectiveIsWeb();
693
+ const skipComputedInline = (0, import_core6.getEffectiveIsWeb)();
3919
694
  let finalStyle;
3920
695
  if (!skipComputedInline) {
3921
- const computedStyle = flatten(resolved, false);
696
+ const computedStyle = (0, import_core6.flatten)(resolved, false);
3922
697
  stripInternalMarkers(computedStyle);
3923
698
  if (typeof effectiveType !== "string") stripWebOnlyProps(computedStyle);
3924
699
  finalStyle = mergeStyle(computedStyle, userStyle);
@@ -3928,7 +703,7 @@ function processElement(type, rawProps, key, isStaticChildren) {
3928
703
  return makeElement(isStaticChildren, effectiveType, {
3929
704
  ...passProps,
3930
705
  ...finalStyle !== void 0 ? { style: finalStyle } : {},
3931
- ...!isNative && classStr ? { className: normalizeClassString(classStr) } : {}
706
+ ...!import_core6.isNative && classStr ? { className: (0, import_core6.normalizeClassString)(classStr) } : {}
3932
707
  }, key);
3933
708
  }
3934
709
  function jsx(type, props, key) {