@kbach/react-native 1.0.0-beta.7 → 1.0.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -21,16 +21,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
23
  ThemeProvider: () => ThemeProvider,
24
+ applyKbachConfig: () => applyKbachConfig,
24
25
  defaultTheme: () => defaultTheme,
25
26
  getGlobalDarkMode: () => getGlobalDarkMode,
26
27
  getGlobalThemeMode: () => getGlobalThemeMode,
27
28
  getTheme: () => getTheme,
29
+ resolveKbachConfig: () => resolveKbachConfig,
28
30
  resolveStyle: () => resolveStyle,
29
31
  setGlobalThemeMode: () => setGlobalThemeMode,
30
32
  setTheme: () => setTheme,
31
33
  subscribeGlobalDarkMode: () => subscribeGlobalDarkMode,
32
34
  toggleGlobalDarkMode: () => toggleGlobalDarkMode,
33
- useGlobalDarkMode: () => useGlobalDarkMode,
35
+ useColors: () => useColors,
34
36
  useTheme: () => useTheme
35
37
  });
36
38
  module.exports = __toCommonJS(src_exports);
@@ -315,16 +317,51 @@ var PALETTE = {
315
317
  // src/theme.ts
316
318
  var defaultTheme = {
317
319
  colors: PALETTE,
320
+ // Real Tailwind's default spacing scale in full — every step is exactly
321
+ // `n * 4px`, including the fractional `.5` steps (`1.5` -> 6px, `2.5` ->
322
+ // 10px, `3.5` -> 14px) and the "px" literal (a bare 1px). Only the
323
+ // "usual stops", though — `jsEngine/shared.ts`'s `spacingPx` (and the
324
+ // native Rust dispatcher's own `spacing_px`) falls back to Tailwind v4's
325
+ // live `n * 4px` formula for any bare numeric step not listed here
326
+ // (`p-0.25`, `w-13`, ...), so this table names the common values and
327
+ // gives a theme override something to target, not the full resolvable
328
+ // set. Mirrors @kbach/react's theme.ts exactly.
318
329
  spacing: {
319
- // "0" is always a hardcoded zero in real Tailwind's own scale too,
320
- // regardless of the base spacing unit — needed for `p-0`/`m-0`/etc.
321
- // Mirrors the identical fix in @kbach/react's theme.ts.
322
330
  "0": 0,
331
+ "px": 1,
332
+ "0.5": 2,
323
333
  "1": 4,
334
+ "1.5": 6,
324
335
  "2": 8,
336
+ "2.5": 10,
337
+ "3": 12,
338
+ "3.5": 14,
325
339
  "4": 16,
340
+ "5": 20,
326
341
  "6": 24,
327
- "8": 32
342
+ "7": 28,
343
+ "8": 32,
344
+ "9": 36,
345
+ "10": 40,
346
+ "11": 44,
347
+ "12": 48,
348
+ "14": 56,
349
+ "16": 64,
350
+ "20": 80,
351
+ "24": 96,
352
+ "28": 112,
353
+ "32": 128,
354
+ "36": 144,
355
+ "40": 160,
356
+ "44": 176,
357
+ "48": 192,
358
+ "52": 208,
359
+ "56": 224,
360
+ "60": 240,
361
+ "64": 256,
362
+ "72": 288,
363
+ "80": 320,
364
+ "96": 384
328
365
  },
329
366
  screens: {
330
367
  sm: 640,
@@ -333,7 +370,20 @@ var defaultTheme = {
333
370
  xl: 1280,
334
371
  "2xl": 1536
335
372
  },
336
- darkMode: "attribute"
373
+ // Byte-for-byte the same three stacks
374
+ // packages/core-engine/src/resolvers/typography.rs's `font_family_value`
375
+ // falls back to. On native these three still effectively no-op (see
376
+ // `first_font_name`'s own doc comment for why a generic CSS keyword
377
+ // isn't a real loadable font) — only a caller-configured custom name
378
+ // changes native rendering; Expo Web uses the full stack as-is.
379
+ fontFamily: {
380
+ sans: 'ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"',
381
+ serif: 'ui-serif, Georgia, Cambria, "Times New Roman", Times, serif',
382
+ mono: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'
383
+ },
384
+ darkMode: "attribute",
385
+ // Empty by default, matching real Tailwind's own defaults.
386
+ container: {}
337
387
  };
338
388
  var activeTheme = defaultTheme;
339
389
  var activeThemeJson = JSON.stringify(defaultTheme);
@@ -397,80 +447,1381 @@ function seedDefaultMode(fallback) {
397
447
  notify();
398
448
  }
399
449
 
450
+ // src/jsEngine/parser.ts
451
+ var VALUE_PREFIXES = [
452
+ "bg-opacity-",
453
+ "text-opacity-",
454
+ "bg-blend-",
455
+ "text-shadow-",
456
+ "bg-",
457
+ "text-",
458
+ "border-x-",
459
+ "border-y-",
460
+ "border-t-",
461
+ "border-r-",
462
+ "border-b-",
463
+ "border-l-",
464
+ "border-",
465
+ "caret-",
466
+ "accent-",
467
+ "fill-",
468
+ "stroke-width-",
469
+ "stroke-",
470
+ "resize-",
471
+ "touch-",
472
+ "will-change-",
473
+ "scroll-mx-",
474
+ "scroll-my-",
475
+ "scroll-mt-",
476
+ "scroll-mr-",
477
+ "scroll-mb-",
478
+ "scroll-ml-",
479
+ "scroll-m-",
480
+ "scroll-px-",
481
+ "scroll-py-",
482
+ "scroll-pt-",
483
+ "scroll-pr-",
484
+ "scroll-pb-",
485
+ "scroll-pl-",
486
+ "scroll-p-",
487
+ "px-",
488
+ "py-",
489
+ "pt-",
490
+ "pr-",
491
+ "pb-",
492
+ "pl-",
493
+ "p-",
494
+ "mx-",
495
+ "my-",
496
+ "mt-",
497
+ "mr-",
498
+ "mb-",
499
+ "ml-",
500
+ "m-",
501
+ "gap-x-",
502
+ "gap-y-",
503
+ "gap-",
504
+ "min-w-",
505
+ "max-w-",
506
+ "w-",
507
+ "min-h-",
508
+ "max-h-",
509
+ "h-",
510
+ "size-",
511
+ "basis-",
512
+ "rounded-tl-",
513
+ "rounded-tr-",
514
+ "rounded-br-",
515
+ "rounded-bl-",
516
+ "rounded-t-",
517
+ "rounded-r-",
518
+ "rounded-b-",
519
+ "rounded-l-",
520
+ "rounded-",
521
+ "ring-offset-",
522
+ "ring-",
523
+ "outline-offset-",
524
+ "outline-",
525
+ "shadow-",
526
+ "opacity-",
527
+ "duration-",
528
+ "delay-",
529
+ "ease-",
530
+ "cursor-",
531
+ "mix-blend-",
532
+ "animate-",
533
+ "leading-",
534
+ "tracking-",
535
+ "font-",
536
+ "z-",
537
+ "inset-",
538
+ "top-",
539
+ "right-",
540
+ "bottom-",
541
+ "left-",
542
+ "divide-color-",
543
+ "space-x-",
544
+ "space-y-",
545
+ "flex-",
546
+ "grow-",
547
+ "shrink-",
548
+ "order-",
549
+ "grid-cols-",
550
+ "grid-rows-",
551
+ "grid-flow-",
552
+ "auto-cols-",
553
+ "auto-rows-",
554
+ "col-span-",
555
+ "col-start-",
556
+ "col-end-",
557
+ "col-",
558
+ "row-span-",
559
+ "row-start-",
560
+ "row-end-",
561
+ "row-",
562
+ "place-items-",
563
+ "place-content-",
564
+ "place-self-",
565
+ "justify-items-",
566
+ "justify-self-",
567
+ "scale-x-",
568
+ "scale-y-",
569
+ "scale-",
570
+ "rotate-",
571
+ "translate-x-",
572
+ "translate-y-",
573
+ "skew-x-",
574
+ "skew-y-",
575
+ "origin-",
576
+ "blur-",
577
+ "brightness-",
578
+ "contrast-",
579
+ "grayscale-",
580
+ "hue-rotate-",
581
+ "invert-",
582
+ "saturate-",
583
+ "sepia-",
584
+ "drop-shadow-",
585
+ "filter-",
586
+ "backdrop-blur-",
587
+ "backdrop-brightness-",
588
+ "backdrop-contrast-",
589
+ "backdrop-grayscale-",
590
+ "backdrop-hue-rotate-",
591
+ "backdrop-invert-",
592
+ "backdrop-opacity-",
593
+ "backdrop-saturate-",
594
+ "backdrop-sepia-",
595
+ "backdrop-filter-",
596
+ "decoration-",
597
+ "underline-offset-",
598
+ "indent-",
599
+ "from-",
600
+ "via-",
601
+ "to-"
602
+ ];
603
+ var ARBITRARY_PROPERTY_SENTINEL = "[arbitrary-property]";
604
+ function isSafeArbitraryValue(value) {
605
+ return !value.includes("{") && !value.includes("}") && !value.includes(";");
606
+ }
607
+ function splitRespectingBrackets(token) {
608
+ const parts = [];
609
+ let depth = 0;
610
+ let start = 0;
611
+ for (let i = 0; i < token.length; i++) {
612
+ const ch = token[i];
613
+ if (ch === "[") depth += 1;
614
+ else if (ch === "]") depth -= 1;
615
+ else if (ch === ":" && depth <= 0) {
616
+ parts.push(token.slice(start, i));
617
+ start = i + 1;
618
+ }
619
+ }
620
+ parts.push(token.slice(start));
621
+ return parts;
622
+ }
623
+ function parseClass(token) {
624
+ const parts = splitRespectingBrackets(token);
625
+ let base = parts.pop() ?? token;
626
+ const modifiers = parts;
627
+ const important = base.startsWith("!");
628
+ if (important) {
629
+ base = base.slice(1);
630
+ }
631
+ const negative = base.startsWith("-");
632
+ if (negative) {
633
+ base = base.slice(1);
634
+ }
635
+ if (base.length >= 2 && base.startsWith("[") && base.endsWith("]")) {
636
+ const raw = base.slice(1, -1);
637
+ const colonIdx = raw.indexOf(":");
638
+ if (colonIdx !== -1) {
639
+ const property = raw.slice(0, colonIdx);
640
+ const rawValue = raw.slice(colonIdx + 1);
641
+ if (property !== "" && rawValue !== "" && isSafeArbitraryValue(raw)) {
642
+ const value = rawValue.replace(/_/g, " ");
643
+ return {
644
+ modifiers,
645
+ utility: ARBITRARY_PROPERTY_SENTINEL,
646
+ value: `${property}:${value}`,
647
+ isArbitrary: true,
648
+ important,
649
+ negative,
650
+ original: token
651
+ };
652
+ }
653
+ }
654
+ }
655
+ for (const prefix of VALUE_PREFIXES) {
656
+ if (!base.startsWith(prefix)) continue;
657
+ const value = base.slice(prefix.length);
658
+ if (value === "") continue;
659
+ if (value.length >= 2 && value.startsWith("[") && value.endsWith("]")) {
660
+ const raw = value.slice(1, -1);
661
+ if (!isSafeArbitraryValue(raw)) {
662
+ continue;
663
+ }
664
+ const spaced = raw.replace(/_/g, " ");
665
+ return {
666
+ modifiers,
667
+ utility: prefix.slice(0, -1),
668
+ value: spaced,
669
+ isArbitrary: true,
670
+ important,
671
+ negative,
672
+ original: token
673
+ };
674
+ }
675
+ return {
676
+ modifiers,
677
+ utility: prefix.slice(0, -1),
678
+ value,
679
+ isArbitrary: false,
680
+ important,
681
+ negative,
682
+ original: token
683
+ };
684
+ }
685
+ return {
686
+ modifiers,
687
+ utility: base,
688
+ value: null,
689
+ isArbitrary: false,
690
+ important,
691
+ negative,
692
+ original: token
693
+ };
694
+ }
695
+
696
+ // src/jsEngine/shared.ts
697
+ function decl(property, value) {
698
+ return { property, value };
699
+ }
700
+ function spacingPx(theme, value) {
701
+ const fromTable = theme.spacing[value];
702
+ if (fromTable !== void 0) return fromTable;
703
+ const n = Number(value);
704
+ return Number.isFinite(n) && value.trim() !== "" ? n * 4 : void 0;
705
+ }
706
+ function resolveLength(theme, parsed) {
707
+ if (parsed.negative) return null;
708
+ const value = parsed.value;
709
+ if (value === null) return null;
710
+ if (parsed.isArbitrary) return value;
711
+ if (value === "full") return "100%";
712
+ if (value === "auto") return "auto";
713
+ const px = spacingPx(theme, value);
714
+ return px === void 0 ? null : `${px}px`;
715
+ }
716
+ function resolveNegatableLength(theme, parsed) {
717
+ if (!parsed.negative) return resolveLength(theme, parsed);
718
+ if (parsed.isArbitrary) return null;
719
+ const value = parsed.value;
720
+ if (value === null) return null;
721
+ const px = spacingPx(theme, value);
722
+ if (px === void 0) return null;
723
+ if (px === 0) return "0px";
724
+ return `-${px}px`;
725
+ }
726
+
727
+ // src/jsEngine/resolvers/layout.ts
728
+ function negateRaw(value, negative) {
729
+ return negative ? `-${value}` : value;
730
+ }
731
+ function resolve(parsed, theme) {
732
+ switch (parsed.utility) {
733
+ case "flex":
734
+ return parsed.value === null ? [decl("display", "flex")] : null;
735
+ case "grid":
736
+ return [decl("display", "grid")];
737
+ case "block":
738
+ return [decl("display", "block")];
739
+ case "inline-block":
740
+ return [decl("display", "inline-block")];
741
+ case "inline":
742
+ return [decl("display", "inline")];
743
+ case "inline-flex":
744
+ return [decl("display", "inline-flex")];
745
+ case "inline-grid":
746
+ return [decl("display", "inline-grid")];
747
+ case "contents":
748
+ return [decl("display", "contents")];
749
+ case "flow-root":
750
+ return [decl("display", "flow-root")];
751
+ case "hidden":
752
+ return [decl("display", "none")];
753
+ case "@container":
754
+ return [decl("container-type", "inline-size")];
755
+ case "items-center":
756
+ return [decl("align-items", "center")];
757
+ case "items-start":
758
+ return [decl("align-items", "flex-start")];
759
+ case "items-end":
760
+ return [decl("align-items", "flex-end")];
761
+ case "items-baseline":
762
+ return [decl("align-items", "baseline")];
763
+ case "items-stretch":
764
+ return [decl("align-items", "stretch")];
765
+ case "justify-center":
766
+ return [decl("justify-content", "center")];
767
+ case "justify-start":
768
+ return [decl("justify-content", "flex-start")];
769
+ case "justify-end":
770
+ return [decl("justify-content", "flex-end")];
771
+ case "justify-between":
772
+ return [decl("justify-content", "space-between")];
773
+ case "justify-around":
774
+ return [decl("justify-content", "space-around")];
775
+ case "justify-evenly":
776
+ return [decl("justify-content", "space-evenly")];
777
+ case "content-start":
778
+ return [decl("align-content", "flex-start")];
779
+ case "content-end":
780
+ return [decl("align-content", "flex-end")];
781
+ case "content-center":
782
+ return [decl("align-content", "center")];
783
+ case "content-between":
784
+ return [decl("align-content", "space-between")];
785
+ case "content-around":
786
+ return [decl("align-content", "space-around")];
787
+ case "content-evenly":
788
+ return [decl("align-content", "space-evenly")];
789
+ case "content-stretch":
790
+ return [decl("align-content", "stretch")];
791
+ case "self-auto":
792
+ return [decl("align-self", "auto")];
793
+ case "self-center":
794
+ return [decl("align-self", "center")];
795
+ case "self-start":
796
+ return [decl("align-self", "flex-start")];
797
+ case "self-end":
798
+ return [decl("align-self", "flex-end")];
799
+ case "self-stretch":
800
+ return [decl("align-self", "stretch")];
801
+ case "self-baseline":
802
+ return [decl("align-self", "baseline")];
803
+ case "overflow-hidden":
804
+ return [decl("overflow", "hidden")];
805
+ case "overflow-auto":
806
+ return [decl("overflow", "auto")];
807
+ case "overflow-scroll":
808
+ return [decl("overflow", "scroll")];
809
+ case "overflow-visible":
810
+ return [decl("overflow", "visible")];
811
+ case "static":
812
+ return [decl("position", "static")];
813
+ case "relative":
814
+ return [decl("position", "relative")];
815
+ case "absolute":
816
+ return [decl("position", "absolute")];
817
+ case "fixed":
818
+ return [decl("position", "fixed")];
819
+ case "sticky":
820
+ return [decl("position", "sticky")];
821
+ case "z":
822
+ return parsed.value === null ? null : [decl("z-index", negateRaw(parsed.value, parsed.negative))];
823
+ case "order":
824
+ return parsed.value === null ? null : [decl("order", negateRaw(parsed.value, parsed.negative))];
825
+ case "grow":
826
+ return [decl("flex-grow", parsed.value ?? "1")];
827
+ case "shrink":
828
+ return [decl("flex-shrink", parsed.value ?? "1")];
829
+ // top/right/bottom/left/inset support real Tailwind's negative-value
830
+ // convention ("-top-4") — see resolveNegatableLength's own doc comment.
831
+ case "top": {
832
+ const v = resolveNegatableLength(theme, parsed);
833
+ return v === null ? null : [decl("top", v)];
834
+ }
835
+ case "right": {
836
+ const v = resolveNegatableLength(theme, parsed);
837
+ return v === null ? null : [decl("right", v)];
838
+ }
839
+ case "bottom": {
840
+ const v = resolveNegatableLength(theme, parsed);
841
+ return v === null ? null : [decl("bottom", v)];
842
+ }
843
+ case "left": {
844
+ const v = resolveNegatableLength(theme, parsed);
845
+ return v === null ? null : [decl("left", v)];
846
+ }
847
+ case "inset": {
848
+ const v = resolveNegatableLength(theme, parsed);
849
+ return v === null ? null : [decl("inset", v)];
850
+ }
851
+ case "aspect-square":
852
+ return [decl("aspect-ratio", "1 / 1")];
853
+ case "aspect-video":
854
+ return [decl("aspect-ratio", "16 / 9")];
855
+ default:
856
+ return null;
857
+ }
858
+ }
859
+ function resolveFlex(parsed, web) {
860
+ if (parsed.utility !== "flex") return null;
861
+ const value = parsed.value;
862
+ if (value === null) return null;
863
+ if (parsed.isArbitrary) return [decl("flex", value)];
864
+ switch (value) {
865
+ case "row":
866
+ return [decl("flex-direction", "row")];
867
+ case "col":
868
+ return [decl("flex-direction", "column")];
869
+ case "row-reverse":
870
+ return [decl("flex-direction", "row-reverse")];
871
+ case "col-reverse":
872
+ return [decl("flex-direction", "column-reverse")];
873
+ case "wrap":
874
+ return [decl("flex-wrap", "wrap")];
875
+ case "wrap-reverse":
876
+ return [decl("flex-wrap", "wrap-reverse")];
877
+ case "nowrap":
878
+ return [decl("flex-wrap", "nowrap")];
879
+ case "1":
880
+ return [decl("flex", "1")];
881
+ case "auto":
882
+ return [decl("flex", web ? "auto" : "1")];
883
+ case "initial":
884
+ return [decl("flex", web ? "initial" : "1")];
885
+ case "none":
886
+ return [decl("flex", web ? "none" : "0")];
887
+ case "grow":
888
+ return [decl("flex-grow", "1")];
889
+ case "grow-0":
890
+ return [decl("flex-grow", "0")];
891
+ case "shrink":
892
+ return [decl("flex-shrink", "1")];
893
+ case "shrink-0":
894
+ return [decl("flex-shrink", "0")];
895
+ default:
896
+ return null;
897
+ }
898
+ }
899
+
900
+ // src/jsEngine/resolvers/spacing.ts
901
+ function namedSize(key) {
902
+ switch (key) {
903
+ case "sm":
904
+ return "24rem";
905
+ case "md":
906
+ return "28rem";
907
+ case "lg":
908
+ return "32rem";
909
+ case "xl":
910
+ return "36rem";
911
+ case "2xl":
912
+ return "42rem";
913
+ case "3xl":
914
+ return "48rem";
915
+ case "4xl":
916
+ return "56rem";
917
+ case "5xl":
918
+ return "64rem";
919
+ case "6xl":
920
+ return "72rem";
921
+ case "7xl":
922
+ return "80rem";
923
+ case "8xl":
924
+ return "88rem";
925
+ case "9xl":
926
+ return "96rem";
927
+ default:
928
+ return null;
929
+ }
930
+ }
931
+ function fractionPercent(value) {
932
+ const slashIdx = value.indexOf("/");
933
+ if (slashIdx === -1) return null;
934
+ const numStr = value.slice(0, slashIdx);
935
+ const denStr = value.slice(slashIdx + 1);
936
+ const num = Number(numStr);
937
+ const den = Number(denStr);
938
+ if (!Number.isFinite(num) || !Number.isFinite(den) || numStr.trim() === "" || denStr.trim() === "") return null;
939
+ if (den === 0) return null;
940
+ const pct = num / den * 100;
941
+ const formatted = pct.toFixed(6);
942
+ const trimmed = formatted.replace(/0+$/, "").replace(/\.$/, "");
943
+ return `${trimmed}%`;
944
+ }
945
+ function cssSizeKeyword(key) {
946
+ switch (key) {
947
+ case "min":
948
+ return "min-content";
949
+ case "max":
950
+ return "max-content";
951
+ case "fit":
952
+ return "fit-content";
953
+ default:
954
+ return null;
955
+ }
956
+ }
957
+ function resolveSize(theme, parsed) {
958
+ if (!parsed.isArbitrary && parsed.value !== null) {
959
+ const named = namedSize(parsed.value);
960
+ if (named !== null) return named;
961
+ const kw = cssSizeKeyword(parsed.value);
962
+ if (kw !== null) return kw;
963
+ const fraction = fractionPercent(parsed.value);
964
+ if (fraction !== null) return fraction;
965
+ }
966
+ return resolveLength(theme, parsed);
967
+ }
968
+ function resolve2(parsed, theme) {
969
+ const length = () => resolveLength(theme, parsed);
970
+ const size = () => resolveSize(theme, parsed);
971
+ const negatableLength = () => resolveNegatableLength(theme, parsed);
972
+ switch (parsed.utility) {
973
+ case "p": {
974
+ const v = length();
975
+ return v === null ? null : [decl("padding", v)];
976
+ }
977
+ case "px": {
978
+ const v = length();
979
+ return v === null ? null : [decl("padding-left", v), decl("padding-right", v)];
980
+ }
981
+ case "py": {
982
+ const v = length();
983
+ return v === null ? null : [decl("padding-top", v), decl("padding-bottom", v)];
984
+ }
985
+ case "pt": {
986
+ const v = length();
987
+ return v === null ? null : [decl("padding-top", v)];
988
+ }
989
+ case "pr": {
990
+ const v = length();
991
+ return v === null ? null : [decl("padding-right", v)];
992
+ }
993
+ case "pb": {
994
+ const v = length();
995
+ return v === null ? null : [decl("padding-bottom", v)];
996
+ }
997
+ case "pl": {
998
+ const v = length();
999
+ return v === null ? null : [decl("padding-left", v)];
1000
+ }
1001
+ case "m": {
1002
+ const v = negatableLength();
1003
+ return v === null ? null : [decl("margin", v)];
1004
+ }
1005
+ case "mx": {
1006
+ const v = negatableLength();
1007
+ return v === null ? null : [decl("margin-left", v), decl("margin-right", v)];
1008
+ }
1009
+ case "my": {
1010
+ const v = negatableLength();
1011
+ return v === null ? null : [decl("margin-top", v), decl("margin-bottom", v)];
1012
+ }
1013
+ case "mt": {
1014
+ const v = negatableLength();
1015
+ return v === null ? null : [decl("margin-top", v)];
1016
+ }
1017
+ case "mr": {
1018
+ const v = negatableLength();
1019
+ return v === null ? null : [decl("margin-right", v)];
1020
+ }
1021
+ case "mb": {
1022
+ const v = negatableLength();
1023
+ return v === null ? null : [decl("margin-bottom", v)];
1024
+ }
1025
+ case "ml": {
1026
+ const v = negatableLength();
1027
+ return v === null ? null : [decl("margin-left", v)];
1028
+ }
1029
+ case "gap": {
1030
+ const v = length();
1031
+ return v === null ? null : [decl("gap", v)];
1032
+ }
1033
+ case "gap-x": {
1034
+ const v = length();
1035
+ return v === null ? null : [decl("column-gap", v)];
1036
+ }
1037
+ case "gap-y": {
1038
+ const v = length();
1039
+ return v === null ? null : [decl("row-gap", v)];
1040
+ }
1041
+ case "w": {
1042
+ const v = size();
1043
+ return v === null ? null : [decl("width", v)];
1044
+ }
1045
+ case "h": {
1046
+ const v = size();
1047
+ return v === null ? null : [decl("height", v)];
1048
+ }
1049
+ case "min-w": {
1050
+ const v = size();
1051
+ return v === null ? null : [decl("min-width", v)];
1052
+ }
1053
+ case "max-w": {
1054
+ const v = size();
1055
+ return v === null ? null : [decl("max-width", v)];
1056
+ }
1057
+ case "min-h": {
1058
+ const v = size();
1059
+ return v === null ? null : [decl("min-height", v)];
1060
+ }
1061
+ case "max-h": {
1062
+ const v = size();
1063
+ return v === null ? null : [decl("max-height", v)];
1064
+ }
1065
+ case "size": {
1066
+ const v = size();
1067
+ return v === null ? null : [decl("width", v), decl("height", v)];
1068
+ }
1069
+ case "basis": {
1070
+ const v = size();
1071
+ return v === null ? null : [decl("flex-basis", v)];
1072
+ }
1073
+ default:
1074
+ return null;
1075
+ }
1076
+ }
1077
+
1078
+ // src/jsEngine/resolvers/color.ts
1079
+ function lookupHex(theme, key) {
1080
+ const entry = theme.colors[key];
1081
+ return typeof entry === "string" ? entry : null;
1082
+ }
1083
+
1084
+ // src/jsEngine/resolvers/border.ts
1085
+ function radiusSize(key) {
1086
+ switch (key) {
1087
+ case "none":
1088
+ return "0px";
1089
+ case "sm":
1090
+ return "0.125rem";
1091
+ case "md":
1092
+ return "0.375rem";
1093
+ case "lg":
1094
+ return "0.5rem";
1095
+ case "xl":
1096
+ return "0.75rem";
1097
+ case "2xl":
1098
+ return "1rem";
1099
+ case "3xl":
1100
+ return "1.5rem";
1101
+ case "full":
1102
+ return "9999px";
1103
+ default:
1104
+ return null;
1105
+ }
1106
+ }
1107
+ function borderSideProperty(side) {
1108
+ switch (side) {
1109
+ case "t":
1110
+ return "border-top";
1111
+ case "r":
1112
+ return "border-right";
1113
+ case "b":
1114
+ return "border-bottom";
1115
+ case "l":
1116
+ return "border-left";
1117
+ default:
1118
+ return null;
1119
+ }
1120
+ }
1121
+ function borderValue(theme, parsed) {
1122
+ const value = parsed.value;
1123
+ if (value === null) return null;
1124
+ if (!parsed.isArbitrary) {
1125
+ const side = borderSideProperty(value);
1126
+ if (side !== null) {
1127
+ return [decl(`${side}-width`, "1px"), decl(`${side}-style`, "solid")];
1128
+ }
1129
+ if (value === "collapse") return [decl("border-collapse", "collapse")];
1130
+ if (value === "separate") return [decl("border-collapse", "separate")];
1131
+ }
1132
+ if (parsed.isArbitrary) {
1133
+ return [decl("border-width", value)];
1134
+ }
1135
+ if (Number.isFinite(Number(value)) && value.trim() !== "") {
1136
+ const v = resolveLength(theme, parsed);
1137
+ return v === null ? null : [decl("border-width", v)];
1138
+ }
1139
+ if (value === "solid" || value === "dashed" || value === "dotted" || value === "double" || value === "hidden" || value === "none") {
1140
+ return [decl("border-style", value)];
1141
+ }
1142
+ const hex = lookupHex(theme, value);
1143
+ return hex === null ? null : [decl("border-color", hex)];
1144
+ }
1145
+ function borderSideValue(theme, parsed, sideProperty) {
1146
+ const value = parsed.value;
1147
+ if (value === null) return null;
1148
+ if (parsed.isArbitrary) return [decl(`${sideProperty}-width`, value)];
1149
+ if (Number.isFinite(Number(value)) && value.trim() !== "") {
1150
+ const v = resolveLength(theme, parsed);
1151
+ return v === null ? null : [decl(`${sideProperty}-width`, v)];
1152
+ }
1153
+ if (value === "solid" || value === "dashed" || value === "dotted" || value === "double" || value === "hidden" || value === "none") {
1154
+ return [decl(`${sideProperty}-style`, value)];
1155
+ }
1156
+ const hex = lookupHex(theme, value);
1157
+ return hex === null ? null : [decl(`${sideProperty}-color`, hex)];
1158
+ }
1159
+ function borderAxisValue(theme, parsed, sideA, sideB) {
1160
+ const value = parsed.value;
1161
+ if (value === null) return null;
1162
+ if (parsed.isArbitrary) return [decl(`${sideA}-width`, value), decl(`${sideB}-width`, value)];
1163
+ if (Number.isFinite(Number(value)) && value.trim() !== "") {
1164
+ const v = resolveLength(theme, parsed);
1165
+ return v === null ? null : [decl(`${sideA}-width`, v), decl(`${sideB}-width`, v)];
1166
+ }
1167
+ if (value === "solid" || value === "dashed" || value === "dotted" || value === "double" || value === "hidden" || value === "none") {
1168
+ return [decl(`${sideA}-style`, value), decl(`${sideB}-style`, value)];
1169
+ }
1170
+ const hex = lookupHex(theme, value);
1171
+ return hex === null ? null : [decl(`${sideA}-color`, hex), decl(`${sideB}-color`, hex)];
1172
+ }
1173
+ function radiusProperties(side) {
1174
+ switch (side) {
1175
+ case "t":
1176
+ return ["border-top-left-radius", "border-top-right-radius"];
1177
+ case "r":
1178
+ return ["border-top-right-radius", "border-bottom-right-radius"];
1179
+ case "b":
1180
+ return ["border-bottom-right-radius", "border-bottom-left-radius"];
1181
+ case "l":
1182
+ return ["border-top-left-radius", "border-bottom-left-radius"];
1183
+ case "tl":
1184
+ return ["border-top-left-radius"];
1185
+ case "tr":
1186
+ return ["border-top-right-radius"];
1187
+ case "br":
1188
+ return ["border-bottom-right-radius"];
1189
+ case "bl":
1190
+ return ["border-bottom-left-radius"];
1191
+ default:
1192
+ return null;
1193
+ }
1194
+ }
1195
+ function resolveRadiusValue(theme, parsed) {
1196
+ if (!parsed.isArbitrary && parsed.value !== null) {
1197
+ const size = radiusSize(parsed.value);
1198
+ if (size !== null) return size;
1199
+ }
1200
+ return resolveLength(theme, parsed);
1201
+ }
1202
+ function resolveRadiusSide(theme, parsed, side) {
1203
+ const properties = radiusProperties(side);
1204
+ if (properties === null) return null;
1205
+ const value = resolveRadiusValue(theme, parsed);
1206
+ if (value === null) return null;
1207
+ return properties.map((p) => decl(p, value));
1208
+ }
1209
+ var OUTLINE_STYLES = ["solid", "dashed", "dotted", "double"];
1210
+ function outlineWidthValue(key) {
1211
+ switch (key) {
1212
+ case "0":
1213
+ return "0px";
1214
+ case "1":
1215
+ return "1px";
1216
+ case "2":
1217
+ return "2px";
1218
+ case "4":
1219
+ return "4px";
1220
+ case "8":
1221
+ return "8px";
1222
+ default:
1223
+ return null;
1224
+ }
1225
+ }
1226
+ function outlineValue(theme, parsed) {
1227
+ const value = parsed.value;
1228
+ if (value === null) return null;
1229
+ if (parsed.isArbitrary) return [decl("outline-width", value)];
1230
+ const w = outlineWidthValue(value);
1231
+ if (w !== null) return [decl("outline-width", w)];
1232
+ if (OUTLINE_STYLES.includes(value)) return [decl("outline-style", value)];
1233
+ const hex = lookupHex(theme, value);
1234
+ return hex === null ? null : [decl("outline-color", hex)];
1235
+ }
1236
+ function outlineOffsetValue(parsed) {
1237
+ const value = parsed.value;
1238
+ if (value === null) return null;
1239
+ if (parsed.isArbitrary) return [decl("outline-offset", value)];
1240
+ const w = outlineWidthValue(value);
1241
+ return w === null ? null : [decl("outline-offset", w)];
1242
+ }
1243
+ var RING_BOX_SHADOW = "var(--kb-ring-inset,) 0 0 0 var(--kb-ring-offset-width, 0px) var(--kb-ring-offset-color, #fff), var(--kb-ring-inset,) 0 0 0 calc(var(--kb-ring-width, 0px) + var(--kb-ring-offset-width, 0px)) var(--kb-ring-color, rgba(59,130,246,0.5))";
1244
+ function ringWidth(key) {
1245
+ switch (key) {
1246
+ case "0":
1247
+ return "0px";
1248
+ case "1":
1249
+ return "1px";
1250
+ case "2":
1251
+ return "2px";
1252
+ case "4":
1253
+ return "4px";
1254
+ case "8":
1255
+ return "8px";
1256
+ default:
1257
+ return null;
1258
+ }
1259
+ }
1260
+ function ringValue(theme, parsed) {
1261
+ const value = parsed.value;
1262
+ if (value === null) return null;
1263
+ if (value === "inset") {
1264
+ return [decl("--kb-ring-inset", "inset"), decl("box-shadow", RING_BOX_SHADOW)];
1265
+ }
1266
+ if (!parsed.isArbitrary) {
1267
+ const w = ringWidth(value);
1268
+ if (w !== null) return [decl("--kb-ring-width", w), decl("box-shadow", RING_BOX_SHADOW)];
1269
+ }
1270
+ const color = parsed.isArbitrary ? value : lookupHex(theme, value);
1271
+ if (color === null) return null;
1272
+ return [decl("--kb-ring-color", color), decl("box-shadow", RING_BOX_SHADOW)];
1273
+ }
1274
+ function ringOffsetValue(theme, parsed) {
1275
+ const value = parsed.value;
1276
+ if (value === null) return null;
1277
+ if (!parsed.isArbitrary) {
1278
+ const w = ringWidth(value);
1279
+ if (w !== null) return [decl("--kb-ring-offset-width", w), decl("box-shadow", RING_BOX_SHADOW)];
1280
+ }
1281
+ const color = parsed.isArbitrary ? value : lookupHex(theme, value);
1282
+ if (color === null) return null;
1283
+ return [decl("--kb-ring-offset-color", color), decl("box-shadow", RING_BOX_SHADOW)];
1284
+ }
1285
+ var RADIUS_SIDES = /* @__PURE__ */ new Set(["t", "r", "b", "l", "tl", "tr", "br", "bl"]);
1286
+ function resolve3(parsed, theme) {
1287
+ switch (parsed.utility) {
1288
+ case "border":
1289
+ if (parsed.value === null) return [decl("border-width", "1px"), decl("border-style", "solid")];
1290
+ return borderValue(theme, parsed);
1291
+ case "border-t":
1292
+ return borderSideValue(theme, parsed, "border-top");
1293
+ case "border-r":
1294
+ return borderSideValue(theme, parsed, "border-right");
1295
+ case "border-b":
1296
+ return borderSideValue(theme, parsed, "border-bottom");
1297
+ case "border-l":
1298
+ return borderSideValue(theme, parsed, "border-left");
1299
+ case "border-x":
1300
+ return borderAxisValue(theme, parsed, "border-left", "border-right");
1301
+ case "border-y":
1302
+ return borderAxisValue(theme, parsed, "border-top", "border-bottom");
1303
+ case "rounded": {
1304
+ if (parsed.value === null) return [decl("border-radius", "0.25rem")];
1305
+ const value = parsed.value;
1306
+ if (!parsed.isArbitrary) {
1307
+ const size = radiusSize(value);
1308
+ if (size !== null) return [decl("border-radius", size)];
1309
+ }
1310
+ const v = resolveLength(theme, parsed);
1311
+ return v === null ? null : [decl("border-radius", v)];
1312
+ }
1313
+ case "ring":
1314
+ if (parsed.value === null) return [decl("--kb-ring-width", "3px"), decl("box-shadow", RING_BOX_SHADOW)];
1315
+ return ringValue(theme, parsed);
1316
+ case "ring-offset":
1317
+ return ringOffsetValue(theme, parsed);
1318
+ case "outline":
1319
+ if (parsed.value === null) return [decl("outline-style", "solid")];
1320
+ if (parsed.value === "none") return [decl("outline", "none")];
1321
+ return outlineValue(theme, parsed);
1322
+ case "outline-offset":
1323
+ return outlineOffsetValue(parsed);
1324
+ default:
1325
+ if (parsed.utility.startsWith("rounded-") && RADIUS_SIDES.has(parsed.utility.slice("rounded-".length))) {
1326
+ return resolveRadiusSide(theme, parsed, parsed.utility.slice("rounded-".length));
1327
+ }
1328
+ return null;
1329
+ }
1330
+ }
1331
+
1332
+ // src/jsEngine/resolvers/typography.ts
1333
+ function textSize(key) {
1334
+ switch (key) {
1335
+ case "xs":
1336
+ return "0.75rem";
1337
+ case "sm":
1338
+ return "0.875rem";
1339
+ case "base":
1340
+ return "1rem";
1341
+ case "lg":
1342
+ return "1.125rem";
1343
+ case "xl":
1344
+ return "1.25rem";
1345
+ case "2xl":
1346
+ return "1.5rem";
1347
+ case "3xl":
1348
+ return "1.875rem";
1349
+ case "4xl":
1350
+ return "2.25rem";
1351
+ default:
1352
+ return null;
1353
+ }
1354
+ }
1355
+ function lineHeightSize(key) {
1356
+ switch (key) {
1357
+ case "3":
1358
+ return "0.75rem";
1359
+ case "4":
1360
+ return "1rem";
1361
+ case "5":
1362
+ return "1.25rem";
1363
+ case "6":
1364
+ return "1.5rem";
1365
+ case "7":
1366
+ return "1.75rem";
1367
+ case "8":
1368
+ return "2rem";
1369
+ case "9":
1370
+ return "2.25rem";
1371
+ case "10":
1372
+ return "2.5rem";
1373
+ default:
1374
+ return null;
1375
+ }
1376
+ }
1377
+ function textAlign(key) {
1378
+ switch (key) {
1379
+ case "left":
1380
+ return "left";
1381
+ case "center":
1382
+ return "center";
1383
+ case "right":
1384
+ return "right";
1385
+ case "justify":
1386
+ return "justify";
1387
+ default:
1388
+ return null;
1389
+ }
1390
+ }
1391
+ function fontWeight(key) {
1392
+ switch (key) {
1393
+ case "thin":
1394
+ return "100";
1395
+ case "normal":
1396
+ return "400";
1397
+ case "medium":
1398
+ return "500";
1399
+ case "semibold":
1400
+ return "600";
1401
+ case "bold":
1402
+ return "700";
1403
+ case "extrabold":
1404
+ return "800";
1405
+ default:
1406
+ return null;
1407
+ }
1408
+ }
1409
+
1410
+ // src/jsEngine/resolvers/effects.ts
1411
+ function nativeShadowValue(key) {
1412
+ switch (key) {
1413
+ case "sm":
1414
+ return { offsetY: 1, radius: 2, opacity: 0.05, elevation: 1 };
1415
+ case "DEFAULT":
1416
+ return { offsetY: 1, radius: 3, opacity: 0.1, elevation: 2 };
1417
+ case "md":
1418
+ return { offsetY: 4, radius: 6, opacity: 0.1, elevation: 4 };
1419
+ case "lg":
1420
+ return { offsetY: 10, radius: 15, opacity: 0.1, elevation: 8 };
1421
+ case "xl":
1422
+ return { offsetY: 20, radius: 25, opacity: 0.1, elevation: 12 };
1423
+ case "2xl":
1424
+ return { offsetY: 25, radius: 50, opacity: 0.25, elevation: 16 };
1425
+ case "none":
1426
+ return { offsetY: 0, radius: 0, opacity: 0, elevation: 0 };
1427
+ default:
1428
+ return null;
1429
+ }
1430
+ }
1431
+ function nativeShadowDeclarations(parsed) {
1432
+ if (parsed.utility !== "shadow" || parsed.isArbitrary) return null;
1433
+ const key = parsed.value ?? "DEFAULT";
1434
+ const s = nativeShadowValue(key);
1435
+ if (s === null) return null;
1436
+ return [
1437
+ decl("shadow-color", "#000000"),
1438
+ decl("shadow-offset-x", "0"),
1439
+ decl("shadow-offset-y", String(s.offsetY)),
1440
+ decl("shadow-opacity", String(s.opacity)),
1441
+ decl("shadow-radius", String(s.radius)),
1442
+ decl("elevation", String(s.elevation))
1443
+ ];
1444
+ }
1445
+
1446
+ // src/jsEngine/resolveUtilityNative.ts
1447
+ function resolveTypographyNative(parsed) {
1448
+ switch (parsed.utility) {
1449
+ case "font": {
1450
+ if (parsed.value === null) return null;
1451
+ const w = fontWeight(parsed.value);
1452
+ return w === null ? null : [decl("font-weight", w)];
1453
+ }
1454
+ case "uppercase":
1455
+ return [decl("text-transform", "uppercase")];
1456
+ case "lowercase":
1457
+ return [decl("text-transform", "lowercase")];
1458
+ case "capitalize":
1459
+ return [decl("text-transform", "capitalize")];
1460
+ case "underline":
1461
+ return [decl("text-decoration-line", "underline")];
1462
+ case "line-through":
1463
+ return [decl("text-decoration-line", "line-through")];
1464
+ case "no-underline":
1465
+ return [decl("text-decoration-line", "none")];
1466
+ case "italic":
1467
+ return [decl("font-style", "italic")];
1468
+ case "not-italic":
1469
+ return [decl("font-style", "normal")];
1470
+ default:
1471
+ return null;
1472
+ }
1473
+ }
1474
+ function resolveLeadingTrackingNative(parsed) {
1475
+ const value = parsed.value;
1476
+ if (value === null) return null;
1477
+ if (parsed.utility === "leading") {
1478
+ if (parsed.isArbitrary) return [decl("line-height", value)];
1479
+ const v = lineHeightSize(value);
1480
+ return v === null ? null : [decl("line-height", v)];
1481
+ }
1482
+ if (parsed.utility === "tracking" && parsed.isArbitrary) {
1483
+ return [decl("letter-spacing", value)];
1484
+ }
1485
+ return null;
1486
+ }
1487
+ function nativeHexColor(parsed, theme) {
1488
+ const value = parsed.value;
1489
+ if (value === null) return null;
1490
+ return parsed.isArbitrary ? value : lookupHex(theme, value);
1491
+ }
1492
+ function resolveTextNative(parsed, theme) {
1493
+ if (!parsed.isArbitrary && parsed.value !== null) {
1494
+ const size = textSize(parsed.value);
1495
+ if (size !== null) return [decl("font-size", size)];
1496
+ const align = textAlign(parsed.value);
1497
+ if (align !== null) return [decl("text-align", align)];
1498
+ }
1499
+ const hex = nativeHexColor(parsed, theme);
1500
+ return hex === null ? null : [decl("color", hex)];
1501
+ }
1502
+ function resolveColorNative(parsed, theme) {
1503
+ switch (parsed.utility) {
1504
+ case "bg": {
1505
+ const hex = nativeHexColor(parsed, theme);
1506
+ return hex === null ? null : [decl("background-color", hex)];
1507
+ }
1508
+ case "text":
1509
+ return resolveTextNative(parsed, theme);
1510
+ default:
1511
+ return null;
1512
+ }
1513
+ }
1514
+ function resolveUtilityNative(parsed, theme) {
1515
+ return resolveFlex(parsed, false) ?? resolve(parsed, theme) ?? resolve2(parsed, theme) ?? resolve3(parsed, theme) ?? resolveColorNative(parsed, theme) ?? resolveLeadingTrackingNative(parsed) ?? resolveTypographyNative(parsed) ?? nativeShadowDeclarations(parsed);
1516
+ }
1517
+
1518
+ // src/jsEngine/resolveStyle.ts
1519
+ var RESPONSIVE_BREAKPOINTS = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
1520
+ function nativeModifierState(modifier, theme, colorScheme, pressed, width) {
1521
+ if (modifier === "dark") return colorScheme === "dark";
1522
+ if (modifier === "active") return pressed;
1523
+ if (RESPONSIVE_BREAKPOINTS.has(modifier)) {
1524
+ const minWidth = theme.screens[modifier];
1525
+ if (minWidth === void 0) return null;
1526
+ return width >= minWidth;
1527
+ }
1528
+ return null;
1529
+ }
1530
+ function kebabToCamel(s) {
1531
+ return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1532
+ }
1533
+ var NUMERIC_LENGTH_PROPS = /* @__PURE__ */ new Set([
1534
+ "padding",
1535
+ "padding-top",
1536
+ "padding-right",
1537
+ "padding-bottom",
1538
+ "padding-left",
1539
+ "margin",
1540
+ "margin-top",
1541
+ "margin-right",
1542
+ "margin-bottom",
1543
+ "margin-left",
1544
+ "gap",
1545
+ "column-gap",
1546
+ "row-gap",
1547
+ "width",
1548
+ "height",
1549
+ "min-width",
1550
+ "max-width",
1551
+ "min-height",
1552
+ "max-height",
1553
+ "top",
1554
+ "right",
1555
+ "bottom",
1556
+ "left",
1557
+ "inset",
1558
+ "border-radius",
1559
+ "border-width",
1560
+ "font-size",
1561
+ "z-index",
1562
+ "line-height",
1563
+ "letter-spacing",
1564
+ "flex",
1565
+ "flex-grow",
1566
+ "flex-shrink",
1567
+ "order",
1568
+ "flex-basis",
1569
+ "shadow-opacity",
1570
+ "shadow-radius",
1571
+ "elevation",
1572
+ // Per-side border width + per-corner radius — see resolvers/border.ts's
1573
+ // new borderSideValue/borderAxisValue/resolveRadiusSide additions; RN's
1574
+ // style system wants plain numbers for these exactly like the generic
1575
+ // "border-width"/"border-radius" forms above.
1576
+ "border-top-width",
1577
+ "border-right-width",
1578
+ "border-bottom-width",
1579
+ "border-left-width",
1580
+ "border-top-left-radius",
1581
+ "border-top-right-radius",
1582
+ "border-bottom-right-radius",
1583
+ "border-bottom-left-radius",
1584
+ "outline-width",
1585
+ "outline-offset"
1586
+ ]);
1587
+ function rnStyleValue(property, value) {
1588
+ if (NUMERIC_LENGTH_PROPS.has(property)) {
1589
+ let px = null;
1590
+ if (value.endsWith("px")) {
1591
+ const n = Number(value.slice(0, -2));
1592
+ px = Number.isFinite(n) ? n : null;
1593
+ } else if (value.endsWith("rem")) {
1594
+ const n = Number(value.slice(0, -3));
1595
+ px = Number.isFinite(n) ? n * 16 : null;
1596
+ } else {
1597
+ const n = Number(value);
1598
+ px = value.trim() !== "" && Number.isFinite(n) ? n : null;
1599
+ }
1600
+ if (px !== null) return px;
1601
+ }
1602
+ return value;
1603
+ }
1604
+ function resolveStyleJs(classString, theme, colorScheme, pressed, width) {
1605
+ const style = {};
1606
+ let shadowOffset = null;
1607
+ for (const token of classString.split(/\s+/).filter(Boolean)) {
1608
+ const parsed = parseClass(token);
1609
+ const allModifiersHold = parsed.modifiers.every(
1610
+ (m) => nativeModifierState(m, theme, colorScheme, pressed, width) === true
1611
+ );
1612
+ if (!allModifiersHold) continue;
1613
+ const decls = resolveUtilityNative(parsed, theme);
1614
+ if (decls === null) continue;
1615
+ for (const d of decls) {
1616
+ if (d.property.startsWith("__")) {
1617
+ continue;
1618
+ }
1619
+ if (d.property === "shadow-offset-x" || d.property === "shadow-offset-y") {
1620
+ const n = Number(d.value);
1621
+ if (!Number.isFinite(n)) continue;
1622
+ if (shadowOffset === null) shadowOffset = {};
1623
+ shadowOffset[d.property === "shadow-offset-x" ? "width" : "height"] = n;
1624
+ continue;
1625
+ }
1626
+ style[kebabToCamel(d.property)] = rnStyleValue(d.property, d.value);
1627
+ }
1628
+ }
1629
+ if (shadowOffset !== null) {
1630
+ style.shadowOffset = { width: shadowOffset.width ?? 0, height: shadowOffset.height ?? 0 };
1631
+ }
1632
+ return style;
1633
+ }
1634
+
400
1635
  // src/nativeBridge.ts
401
1636
  function resolveStyle(classString, pressed = false) {
402
- const KbachModule = import_react_native2.TurboModuleRegistry.getEnforcing("KbachModule");
403
1637
  const colorScheme = getGlobalDarkMode() ? "dark" : "light";
404
1638
  const width = import_react_native2.Dimensions.get("window").width;
1639
+ const KbachModule = import_react_native2.TurboModuleRegistry.get("KbachModule");
1640
+ if (!KbachModule) {
1641
+ return resolveStyleJs(classString, getTheme(), colorScheme, pressed, width);
1642
+ }
405
1643
  const json = KbachModule.resolveStyle(classString, getThemeJson(), colorScheme, pressed, width);
406
1644
  return JSON.parse(json);
407
1645
  }
408
1646
 
409
- // src/useGlobalDarkMode.ts
410
- var import_react = require("react");
411
- function useGlobalDarkMode() {
412
- return (0, import_react.useSyncExternalStore)(subscribeGlobalDarkMode, getGlobalDarkMode);
1647
+ // src/config.ts
1648
+ function parseHexRgb(hex) {
1649
+ const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
1650
+ if (!m) return null;
1651
+ let h = m[1];
1652
+ if (h.length === 3) h = h.split("").map((c) => c + c).join("");
1653
+ const n = parseInt(h, 16);
1654
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
1655
+ }
1656
+ function applyOpacityToHex(hex, opacityText) {
1657
+ const rgb = parseHexRgb(hex);
1658
+ if (!rgb) return hex;
1659
+ const a = Number(opacityText) / 100;
1660
+ const clamped = Number.isFinite(a) ? Math.min(1, Math.max(0, a)) : 1;
1661
+ return `rgba(${rgb.join(",")},${clamped})`;
1662
+ }
1663
+ function resolveColorEntry(value, lookup) {
1664
+ const slash = value.indexOf("/");
1665
+ const name = slash === -1 ? value : value.slice(0, slash);
1666
+ const opacity = slash === -1 ? void 0 : value.slice(slash + 1);
1667
+ const base = lookup(name);
1668
+ if (base === void 0) return value;
1669
+ return opacity === void 0 ? base : applyOpacityToHex(base, opacity);
1670
+ }
1671
+ function resolveColors(extend, existing) {
1672
+ const resolved = {};
1673
+ const lookup = (name) => {
1674
+ const found = resolved[name] ?? existing[name];
1675
+ return typeof found === "string" ? found : void 0;
1676
+ };
1677
+ for (const [name, value] of Object.entries(extend)) {
1678
+ resolved[name] = resolveColorEntry(value, lookup);
1679
+ }
1680
+ return resolved;
1681
+ }
1682
+ function resolveKbachConfig(config) {
1683
+ let theme = { ...defaultTheme, ...config.theme };
1684
+ if (config.extend?.colors) {
1685
+ theme = { ...theme, colors: { ...theme.colors, ...resolveColors(config.extend.colors, theme.colors) } };
1686
+ }
1687
+ if (config.extend?.spacing) {
1688
+ theme = { ...theme, spacing: { ...theme.spacing, ...config.extend.spacing } };
1689
+ }
1690
+ if (config.extend?.screens) {
1691
+ theme = { ...theme, screens: { ...theme.screens, ...config.extend.screens } };
1692
+ }
1693
+ if (config.extend?.fontFamily) {
1694
+ theme = { ...theme, fontFamily: { ...theme.fontFamily, ...config.extend.fontFamily } };
1695
+ }
1696
+ if (config.extend?.container) {
1697
+ theme = { ...theme, container: { ...theme.container, ...config.extend.container } };
1698
+ }
1699
+ if (config.darkMode) {
1700
+ theme = { ...theme, darkMode: config.darkMode };
1701
+ }
1702
+ return theme;
1703
+ }
1704
+ function applyKbachConfig(config) {
1705
+ const theme = resolveKbachConfig(config);
1706
+ setTheme(theme);
1707
+ return theme;
413
1708
  }
414
1709
 
415
- // src/ThemeProvider.tsx
416
- var import_react3 = require("react");
417
-
418
- // src/ThemeContext.tsx
419
- var import_react2 = require("react");
420
- var ThemeContext = (0, import_react2.createContext)(null);
1710
+ // src/useTheme.ts
1711
+ var import_react = require("react");
421
1712
  function useTheme() {
422
- const ctx = (0, import_react2.useContext)(ThemeContext);
423
- if (!ctx) {
424
- throw new Error(
425
- 'useTheme() must be called within a <ThemeProvider>. For dark-mode state without a provider, use useGlobalDarkMode() (read) or toggleGlobalDarkMode()/setGlobalThemeMode() (write) from "@kbach/react-native" instead.'
426
- );
427
- }
428
- return ctx;
1713
+ const isDark2 = (0, import_react.useSyncExternalStore)(subscribeGlobalDarkMode, getGlobalDarkMode);
1714
+ const mode2 = (0, import_react.useSyncExternalStore)(subscribeGlobalDarkMode, getGlobalThemeMode);
1715
+ return (0, import_react.useMemo)(
1716
+ () => ({ mode: mode2, isDark: isDark2, setMode: setGlobalThemeMode, toggle: toggleGlobalDarkMode }),
1717
+ [mode2, isDark2]
1718
+ );
429
1719
  }
430
1720
 
431
1721
  // src/ThemeProvider.tsx
1722
+ var import_react2 = require("react");
432
1723
  var import_jsx_runtime = require("react/jsx-runtime");
433
1724
  var mountedProviderCount = 0;
434
1725
  var warnedMultipleProviders = false;
435
1726
  function ThemeProvider({ children, defaultMode = "system" }) {
436
- (0, import_react3.useEffect)(() => {
1727
+ (0, import_react2.useEffect)(() => {
437
1728
  mountedProviderCount++;
438
1729
  if (mountedProviderCount > 1 && !warnedMultipleProviders) {
439
1730
  warnedMultipleProviders = true;
440
1731
  console.warn(
441
- "[kbach] Multiple <ThemeProvider> instances are mounted at once. Dark-mode state is one global store (the same one useGlobalDarkMode()/toggleGlobalDarkMode() read and write), not scoped per-provider, so they will fight over the same state instead of each getting their own."
1732
+ "[kbach] Multiple <ThemeProvider> instances are mounted at once. Dark-mode state is one global store useTheme() reads everywhere, not scoped per-provider, so their defaultMode seeds will fight over the same state."
442
1733
  );
443
1734
  }
444
1735
  return () => {
445
1736
  mountedProviderCount--;
446
1737
  };
447
1738
  }, []);
448
- const seeded = (0, import_react3.useRef)(false);
449
- (0, import_react3.useEffect)(() => {
1739
+ const seeded = (0, import_react2.useRef)(false);
1740
+ (0, import_react2.useEffect)(() => {
450
1741
  if (seeded.current) return;
451
1742
  seeded.current = true;
452
1743
  seedDefaultMode(defaultMode);
453
1744
  }, []);
454
- const isDark2 = (0, import_react3.useSyncExternalStore)(subscribeGlobalDarkMode, getGlobalDarkMode);
455
- const mode2 = (0, import_react3.useSyncExternalStore)(subscribeGlobalDarkMode, getGlobalThemeMode);
456
- const value = (0, import_react3.useMemo)(
457
- () => ({ mode: mode2, isDark: isDark2, setMode: setGlobalThemeMode, toggle: toggleGlobalDarkMode }),
458
- [mode2, isDark2]
459
- );
460
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ThemeContext.Provider, { value, children });
1745
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children });
1746
+ }
1747
+
1748
+ // src/useColors.ts
1749
+ function parseHexRgb2(hex) {
1750
+ const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(hex.trim());
1751
+ if (!m) return null;
1752
+ let h = m[1];
1753
+ if (h.length === 3) h = h.split("").map((c) => c + c).join("");
1754
+ const n = parseInt(h, 16);
1755
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
1756
+ }
1757
+ function applyOpacity(color, opacity) {
1758
+ const a = Math.max(0, Math.min(1, opacity / 100));
1759
+ if (color.startsWith("#")) {
1760
+ const rgb = parseHexRgb2(color);
1761
+ return rgb ? `rgba(${rgb.join(",")},${a})` : color;
1762
+ }
1763
+ if (color.startsWith("rgb(")) return color.replace("rgb(", "rgba(").replace(")", `,${a})`);
1764
+ if (color.startsWith("rgba(")) return color.replace(/,\s*[\d.]+\)$/, `,${a})`);
1765
+ return color;
1766
+ }
1767
+ function resolveEntry(entry, isDark2) {
1768
+ return typeof entry === "string" ? entry : isDark2 ? entry.dark : entry.light;
1769
+ }
1770
+ function makeColorsProxy(theme, isDark2) {
1771
+ const alpha = (color, opacity) => opacity === void 0 ? color : applyOpacity(color, opacity);
1772
+ const cache = /* @__PURE__ */ new Map();
1773
+ function resolveNamed(key) {
1774
+ let name = key;
1775
+ let opacity;
1776
+ if (key.includes("/")) {
1777
+ const slash = key.indexOf("/");
1778
+ name = key.slice(0, slash);
1779
+ opacity = Number(key.slice(slash + 1));
1780
+ }
1781
+ const entry = theme.colors[name];
1782
+ if (entry === void 0) return void 0;
1783
+ const value = resolveEntry(entry, isDark2);
1784
+ return opacity === void 0 ? value : applyOpacity(value, opacity);
1785
+ }
1786
+ function makeFamilyProxy(family) {
1787
+ return new Proxy({}, {
1788
+ get(_, prop) {
1789
+ const key = String(prop);
1790
+ if (key === "then") return void 0;
1791
+ return resolveNamed(`${family}-${key}`);
1792
+ }
1793
+ });
1794
+ }
1795
+ return new Proxy({ alpha }, {
1796
+ get(_, prop) {
1797
+ const key = String(prop);
1798
+ if (key === "then") return void 0;
1799
+ if (key === "alpha") return alpha;
1800
+ const direct = resolveNamed(key);
1801
+ if (direct !== void 0) return direct;
1802
+ if (!cache.has(key)) cache.set(key, makeFamilyProxy(key));
1803
+ return cache.get(key);
1804
+ }
1805
+ });
1806
+ }
1807
+ function useColors() {
1808
+ const { isDark: isDark2 } = useTheme();
1809
+ return makeColorsProxy(getTheme(), isDark2);
461
1810
  }
462
1811
  // Annotate the CommonJS export names for ESM import in node:
463
1812
  0 && (module.exports = {
464
1813
  ThemeProvider,
1814
+ applyKbachConfig,
465
1815
  defaultTheme,
466
1816
  getGlobalDarkMode,
467
1817
  getGlobalThemeMode,
468
1818
  getTheme,
1819
+ resolveKbachConfig,
469
1820
  resolveStyle,
470
1821
  setGlobalThemeMode,
471
1822
  setTheme,
472
1823
  subscribeGlobalDarkMode,
473
1824
  toggleGlobalDarkMode,
474
- useGlobalDarkMode,
1825
+ useColors,
475
1826
  useTheme
476
1827
  });