@kbach/react 0.5.37 → 0.5.40

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.
@@ -561,773 +561,116 @@ function escapeCSSSelector(cls) {
561
561
  return cls.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
562
562
  }
563
563
 
564
- // src/core/parser.ts
565
- var PLUGIN_MODIFIERS = /* @__PURE__ */ new Set();
566
- function registerModifier(name) {
567
- PLUGIN_MODIFIERS.add(name);
564
+ // src/core/registry.ts
565
+ var BUILTIN_MODIFIERS = {
566
+ // ── Mode ─────────────────────────────────────────────────────────────────
567
+ dark: { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
568
+ "not-light": { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
569
+ light: { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
570
+ "not-dark": { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
571
+ // ── Interactive — JS state + CSS pseudo ───────────────────────────────────
572
+ hover: { pseudo: ":hover", jsBehavior: "interactive", jsMatch: (_, s) => !!s.hover },
573
+ "not-hover": { pseudo: ":not(:hover)", jsBehavior: "interactive", jsMatch: (_, s) => !s.hover },
574
+ focus: { pseudo: ":focus", jsBehavior: "interactive", jsMatch: (_, s) => !!s.focus },
575
+ "not-focus": { pseudo: ":not(:focus)", jsBehavior: "interactive", jsMatch: (_, s) => !s.focus },
576
+ active: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.active || !!s.pressed },
577
+ "not-active": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.active && !s.pressed },
578
+ pressed: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.pressed || !!s.active },
579
+ "not-pressed": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.pressed && !s.active },
580
+ disabled: { pseudo: ":disabled", jsBehavior: "interactive", jsMatch: (_, s) => !!s.disabled },
581
+ "not-disabled": { pseudo: ":not(:disabled)", jsBehavior: "interactive", jsMatch: (_, s) => !s.disabled },
582
+ checked: { pseudo: ":checked", jsBehavior: "interactive", jsMatch: (_, s) => !!s.checked },
583
+ "not-checked": { pseudo: ":not(:checked)", jsBehavior: "interactive", jsMatch: (_, s) => !s.checked },
584
+ visited: { pseudo: ":visited", jsBehavior: "interactive", jsMatch: (_, s) => !!s.visited },
585
+ "not-visited": { pseudo: ":not(:visited)", jsBehavior: "interactive", jsMatch: (_, s) => !s.visited },
586
+ placeholder: { pseudo: "::placeholder", jsBehavior: "interactive", jsMatch: (_, s) => !!s.placeholder },
587
+ // ── CSS-only pseudo-classes (structural) ──────────────────────────────────
588
+ first: { pseudo: ":first-child", jsBehavior: "css-only", forcesImportant: true },
589
+ last: { pseudo: ":last-child", jsBehavior: "css-only", forcesImportant: true },
590
+ odd: { pseudo: ":nth-child(odd)", jsBehavior: "css-only", forcesImportant: true },
591
+ even: { pseudo: ":nth-child(even)", jsBehavior: "css-only", forcesImportant: true },
592
+ only: { pseudo: ":only-child", jsBehavior: "css-only", forcesImportant: true },
593
+ "focus-within": { pseudo: ":focus-within", jsBehavior: "css-only", forcesImportant: true },
594
+ "focus-visible": { pseudo: ":focus-visible", jsBehavior: "css-only", forcesImportant: true },
595
+ // ── CSS-only pseudo-elements ───────────────────────────────────────────────
596
+ before: { pseudo: "::before", jsBehavior: "css-only" },
597
+ after: { pseudo: "::after", jsBehavior: "css-only" },
598
+ selection: { pseudo: "::selection", jsBehavior: "css-only" },
599
+ "first-letter": { pseudo: "::first-letter", jsBehavior: "css-only" },
600
+ "first-line": { pseudo: "::first-line", jsBehavior: "css-only" },
601
+ marker: { pseudo: "::marker", jsBehavior: "css-only" },
602
+ // ── Group / peer ancestor selectors (CSS-only) ─────────────────────────────
603
+ "group-hover": { ancestorSelector: ".group:hover ", jsBehavior: "css-only", forcesImportant: true },
604
+ "group-focus": { ancestorSelector: ".group:focus ", jsBehavior: "css-only", forcesImportant: true },
605
+ "peer-hover": { ancestorSelector: ".peer:hover ~ ", jsBehavior: "css-only", forcesImportant: true },
606
+ "peer-focus": { ancestorSelector: ".peer:focus ~ ", jsBehavior: "css-only", forcesImportant: true },
607
+ // ── Responsive — both CSS (@media min-width) and JS (breakpoints set) ──────
608
+ sm: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("sm") },
609
+ md: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("md") },
610
+ lg: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("lg") },
611
+ xl: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("xl") },
612
+ "2xl": { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("2xl") },
613
+ // ── Print media (CSS-only) ─────────────────────────────────────────────────
614
+ print: { mediaQuery: "print", jsBehavior: "css-only", forcesImportant: true },
615
+ // ── Orientation / accessibility media (CSS-only) ───────────────────────────
616
+ landscape: { mediaQuery: "(orientation: landscape)", jsBehavior: "css-only", forcesImportant: true },
617
+ portrait: { mediaQuery: "(orientation: portrait)", jsBehavior: "css-only", forcesImportant: true },
618
+ "motion-reduce": { mediaQuery: "(prefers-reduced-motion: reduce)", jsBehavior: "css-only", forcesImportant: true },
619
+ "motion-safe": { mediaQuery: "(prefers-reduced-motion: no-preference)", jsBehavior: "css-only", forcesImportant: true },
620
+ "contrast-more": { mediaQuery: "(prefers-contrast: more)", jsBehavior: "css-only", forcesImportant: true },
621
+ "contrast-less": { mediaQuery: "(prefers-contrast: less)", jsBehavior: "css-only", forcesImportant: true },
622
+ // ── Directionality (CSS-only) ──────────────────────────────────────────────
623
+ rtl: { dirSelector: '[dir="rtl"] ', jsBehavior: "css-only", forcesImportant: true },
624
+ ltr: { dirSelector: '[dir="ltr"] ', jsBehavior: "css-only", forcesImportant: true }
625
+ };
626
+ var _pluginModifiers = {};
627
+ var _allNames = null;
628
+ var _interactiveNames = null;
629
+ var _modeNames = null;
630
+ var _responsiveNames = null;
631
+ function _invalidate() {
632
+ _allNames = null;
633
+ _interactiveNames = null;
634
+ _modeNames = null;
635
+ _responsiveNames = null;
636
+ }
637
+ function registerModifier(name, def) {
638
+ _pluginModifiers[name] = def;
639
+ _invalidate();
568
640
  }
569
641
  function clearPluginModifiers() {
570
- PLUGIN_MODIFIERS.clear();
571
- }
572
- var MODIFIERS = /* @__PURE__ */ new Set([
573
- // Theme
574
- "dark",
575
- "light",
576
- "not-dark",
577
- "not-light",
578
- // Interaction
579
- "hover",
580
- "focus",
581
- "active",
582
- "visited",
583
- "disabled",
584
- "checked",
585
- "pressed",
586
- "placeholder",
587
- "focus-within",
588
- "focus-visible",
589
- // Negated interaction
590
- "not-hover",
591
- "not-focus",
592
- "not-active",
593
- "not-visited",
594
- "not-disabled",
595
- "not-checked",
596
- "not-pressed",
597
- // Structural
598
- "first",
599
- "last",
600
- "odd",
601
- "even",
602
- "only",
603
- // Group / peer
604
- "group-hover",
605
- "group-focus",
606
- "peer-hover",
607
- "peer-focus",
608
- // Responsive (handled separately but accepted)
609
- "sm",
610
- "md",
611
- "lg",
612
- "xl",
613
- "2xl",
614
- // Pseudo-elements (CSS-injection only; matchesMods returns false for these)
615
- "before",
616
- "after",
617
- "selection",
618
- "first-letter",
619
- "first-line",
620
- "marker",
621
- // Print media modifier
622
- "print",
623
- // Orientation media modifiers (CSS-injection only)
624
- "landscape",
625
- "portrait",
626
- // Accessibility media modifiers (CSS-injection only)
627
- "motion-reduce",
628
- "motion-safe",
629
- "contrast-more",
630
- "contrast-less",
631
- // Directionality modifiers (CSS-injection only)
632
- "rtl",
633
- "ltr"
634
- ]);
635
- var UTILITY_PREFIXES = [
636
- // Multi-word flex
637
- "flex-row-reverse",
638
- "flex-col-reverse",
639
- "flex-row",
640
- "flex-col",
641
- "flex-wrap-reverse",
642
- "flex-wrap",
643
- "flex-nowrap",
644
- "flex-shrink-0",
645
- "flex-shrink",
646
- "flex-grow-0",
647
- "flex-grow",
648
- "items-start",
649
- "items-end",
650
- "items-center",
651
- "items-baseline",
652
- "items-stretch",
653
- "justify-start",
654
- "justify-end",
655
- "justify-center",
656
- "justify-between",
657
- "justify-around",
658
- "justify-evenly",
659
- "content-start",
660
- "content-end",
661
- "content-center",
662
- "content-between",
663
- "content-around",
664
- "content-evenly",
665
- "self-start",
666
- "self-end",
667
- "self-center",
668
- "self-auto",
669
- "self-stretch",
670
- "text-left",
671
- "text-right",
672
- "text-center",
673
- "text-justify",
674
- "font-thin",
675
- "font-extralight",
676
- "font-light",
677
- "font-normal",
678
- "font-medium",
679
- "font-semibold",
680
- "font-bold",
681
- "font-extrabold",
682
- "font-black",
683
- "overflow-hidden",
684
- "overflow-visible",
685
- "overflow-scroll",
686
- "overflow-auto",
687
- "overflow-x-hidden",
688
- "overflow-x-scroll",
689
- "overflow-x-auto",
690
- "overflow-y-hidden",
691
- "overflow-y-scroll",
692
- "overflow-y-auto",
693
- "object-contain",
694
- "object-cover",
695
- "object-fill",
696
- "object-none",
697
- "object-scale-down",
698
- "border-solid",
699
- "border-dashed",
700
- "border-dotted",
701
- "border-none",
702
- "border-t",
703
- "border-r",
704
- "border-b",
705
- "border-l",
706
- "rounded-tl",
707
- "rounded-tr",
708
- "rounded-bl",
709
- "rounded-br",
710
- "rounded-t",
711
- "rounded-r",
712
- "rounded-b",
713
- "rounded-l",
714
- "list-none",
715
- "list-disc",
716
- "list-decimal",
717
- "cursor-auto",
718
- "cursor-default",
719
- "cursor-pointer",
720
- "cursor-wait",
721
- "cursor-text",
722
- "cursor-move",
723
- "cursor-not-allowed",
724
- "select-none",
725
- "select-text",
726
- "select-all",
727
- "select-auto",
728
- "pointer-events-none",
729
- "pointer-events-auto",
730
- "whitespace-normal",
731
- "whitespace-nowrap",
732
- "whitespace-pre-wrap",
733
- "whitespace-pre-line",
734
- "whitespace-pre",
735
- "break-normal",
736
- "break-words",
737
- "break-all",
738
- "break-keep",
739
- "bg-clip-border",
740
- "bg-clip-padding",
741
- "bg-clip-content",
742
- "bg-clip-text",
743
- "bg-gradient-to",
744
- "resize-none",
745
- "resize-y",
746
- "resize-x",
747
- "box-border",
748
- "box-content",
749
- "gap-x",
750
- "gap-y",
751
- "inset-x",
752
- "inset-y",
753
- "divide-x",
754
- "divide-y",
755
- "space-x",
756
- "space-y",
757
- "translate-x",
758
- "translate-y",
759
- "scale-x",
760
- "scale-y",
761
- "skew-x",
762
- "skew-y",
763
- // Transform origin (single prefix, value carries direction)
764
- "origin",
765
- "min-w",
766
- "min-h",
767
- "max-w",
768
- "max-h",
769
- "ring-offset",
770
- "bg-opacity",
771
- "text-opacity",
772
- "border-opacity",
773
- // Grid placement
774
- "col-span",
775
- "col-start",
776
- "col-end",
777
- "row-span",
778
- "row-start",
779
- "row-end",
780
- "grid-cols",
781
- "grid-rows",
782
- "grid-flow",
783
- "auto-cols",
784
- "auto-rows",
785
- // Grid alignment
786
- "place-items",
787
- "place-content",
788
- "place-self",
789
- "justify-items",
790
- "justify-self",
791
- // Backdrop filters (longer than 'backdrop' alone)
792
- "backdrop-blur",
793
- "backdrop-brightness",
794
- "backdrop-contrast",
795
- "backdrop-grayscale",
796
- "backdrop-hue-rotate",
797
- "backdrop-invert",
798
- "backdrop-opacity",
799
- "backdrop-saturate",
800
- "backdrop-sepia",
801
- "backdrop-filter",
802
- // Filters
803
- "drop-shadow",
804
- "hue-rotate",
805
- "text-shadow",
806
- "underline-offset",
807
- "outline-offset",
808
- "will-change",
809
- "mix-blend",
810
- "bg-blend",
811
- "decoration",
812
- "perspective",
813
- "tint",
814
- "animate",
815
- // Single-word prefixes last
816
- "appearance-none",
817
- "outline-none",
818
- "outline",
819
- "inline-flex",
820
- "inline-block",
821
- "inline-grid",
822
- "italic",
823
- "non-italic",
824
- "underline",
825
- "overline",
826
- "line-through",
827
- "no-underline",
828
- "uppercase",
829
- "lowercase",
830
- "capitalize",
831
- "normal-case",
832
- "antialiased",
833
- "subpixel-antialiased",
834
- "overflow-ellipsis",
835
- "truncate",
836
- "sr-only",
837
- "not-sr-only",
838
- "relative",
839
- "absolute",
840
- "fixed",
841
- "sticky",
842
- "static",
843
- "visible",
844
- "invisible",
845
- "hidden",
846
- "contents",
847
- "flow-root",
848
- "block",
849
- "inline",
850
- "flex",
851
- "grid",
852
- "resize",
853
- "appearance",
854
- "border",
855
- "rounded",
856
- "shadow",
857
- "size",
858
- "opacity",
859
- "leading",
860
- "tracking",
861
- "line-clamp",
862
- "basis",
863
- "grow",
864
- "shrink",
865
- "order",
866
- "delay",
867
- "duration",
868
- "scale",
869
- "rotate",
870
- "aspect",
871
- "columns",
872
- "ring",
873
- "gap",
874
- "inset",
875
- "filter",
876
- "transform",
877
- "blur",
878
- "brightness",
879
- "contrast",
880
- "grayscale",
881
- "invert",
882
- "saturate",
883
- "sepia",
884
- "bg",
885
- "text",
886
- "font",
887
- "caret",
888
- "accent",
889
- "from",
890
- "via",
891
- "to",
892
- "divide",
893
- "space",
894
- "transition",
895
- "px",
896
- "py",
897
- "pt",
898
- "pr",
899
- "pb",
900
- "pl",
901
- "p",
902
- "mx",
903
- "my",
904
- "mt",
905
- "mr",
906
- "mb",
907
- "ml",
908
- "m",
909
- "w",
910
- "h",
911
- "top",
912
- "right",
913
- "bottom",
914
- "left",
915
- "z",
916
- "col",
917
- "row"
918
- ];
919
- var SORTED_PREFIXES = [...new Set(UTILITY_PREFIXES)].sort((a, b) => b.length - a.length);
920
- var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
921
- // Display
922
- "flex",
923
- "block",
924
- "inline-block",
925
- "inline",
926
- "grid",
927
- "inline-flex",
928
- "inline-grid",
929
- "grd",
930
- "hidden",
931
- "contents",
932
- "flow-root",
933
- // Position
934
- "relative",
935
- "absolute",
936
- "fixed",
937
- "sticky",
938
- "static",
939
- // Visibility
940
- "visible",
941
- "invisible",
942
- // Typography
943
- "uppercase",
944
- "lowercase",
945
- "capitalize",
946
- "normal-case",
947
- "italic",
948
- "non-italic",
949
- "underline",
950
- "overline",
951
- "line-through",
952
- "no-underline",
953
- "truncate",
954
- "antialiased",
955
- "sr-only",
956
- "not-sr-only",
957
- // Font variant numeric
958
- "normal-nums",
959
- "ordinal",
960
- "slashed-zero",
961
- "lining-nums",
962
- "oldstyle-nums",
963
- "proportional-nums",
964
- "tabular-nums",
965
- "diagonal-fractions",
966
- "stacked-fractions",
967
- // Flexbox
968
- "flex-row",
969
- "flex-col",
970
- "flex-row-reverse",
971
- "flex-col-reverse",
972
- "flex-wrap",
973
- "flex-wrap-reverse",
974
- "flex-nowrap",
975
- "flex-shrink",
976
- "flex-shrink-0",
977
- "flex-grow",
978
- "flex-grow-0",
979
- "items-start",
980
- "items-end",
981
- "items-center",
982
- "items-baseline",
983
- "items-stretch",
984
- "justify-start",
985
- "justify-end",
986
- "justify-center",
987
- "justify-between",
988
- "justify-around",
989
- "justify-evenly",
990
- "content-start",
991
- "content-end",
992
- "content-center",
993
- "content-between",
994
- "content-around",
995
- "content-evenly",
996
- "content-stretch",
997
- "self-start",
998
- "self-end",
999
- "self-center",
1000
- "self-auto",
1001
- "self-stretch",
1002
- "self-baseline",
1003
- // Text align
1004
- "text-left",
1005
- "text-right",
1006
- "text-center",
1007
- "text-justify",
1008
- // Font weight shortcuts
1009
- "font-thin",
1010
- "font-extralight",
1011
- "font-light",
1012
- "font-normal",
1013
- "font-medium",
1014
- "font-semibold",
1015
- "font-bold",
1016
- "font-extrabold",
1017
- "font-black",
1018
- // Overflow
1019
- "overflow-hidden",
1020
- "overflow-visible",
1021
- "overflow-scroll",
1022
- "overflow-auto",
1023
- "overflow-x-hidden",
1024
- "overflow-x-scroll",
1025
- "overflow-x-auto",
1026
- "overflow-y-hidden",
1027
- "overflow-y-scroll",
1028
- "overflow-y-auto",
1029
- // Object fit
1030
- "object-contain",
1031
- "object-cover",
1032
- "object-fill",
1033
- "object-none",
1034
- "object-scale-down",
1035
- // Object position
1036
- "object-center",
1037
- "object-top",
1038
- "object-bottom",
1039
- "object-left",
1040
- "object-right",
1041
- "object-left-top",
1042
- "object-left-bottom",
1043
- "object-right-top",
1044
- "object-right-bottom",
1045
- // Border
1046
- "border-solid",
1047
- "border-dashed",
1048
- "border-dotted",
1049
- "border-none",
1050
- "border-t",
1051
- "border-r",
1052
- "border-b",
1053
- "border-l",
1054
- "border-collapse",
1055
- "border-separate",
1056
- // Lists
1057
- "list-none",
1058
- "list-disc",
1059
- "list-decimal",
1060
- "list-inside",
1061
- "list-outside",
1062
- // Cursor / select
1063
- "cursor-auto",
1064
- "cursor-default",
1065
- "cursor-pointer",
1066
- "cursor-wait",
1067
- "cursor-text",
1068
- "cursor-move",
1069
- "cursor-not-allowed",
1070
- "select-none",
1071
- "select-text",
1072
- "select-all",
1073
- "select-auto",
1074
- "pointer-events-none",
1075
- "pointer-events-auto",
1076
- // Whitespace / word break
1077
- "whitespace-normal",
1078
- "whitespace-nowrap",
1079
- "whitespace-pre",
1080
- "whitespace-pre-wrap",
1081
- "whitespace-pre-line",
1082
- "break-normal",
1083
- "break-words",
1084
- "break-all",
1085
- // Background clip
1086
- "bg-clip-border",
1087
- "bg-clip-padding",
1088
- "bg-clip-content",
1089
- "bg-clip-text",
1090
- // Background size
1091
- "bg-auto",
1092
- "bg-cover",
1093
- "bg-contain",
1094
- // Background position
1095
- "bg-center",
1096
- "bg-top",
1097
- "bg-bottom",
1098
- "bg-left",
1099
- "bg-right",
1100
- "bg-left-top",
1101
- "bg-left-bottom",
1102
- "bg-right-top",
1103
- "bg-right-bottom",
1104
- // Background repeat
1105
- "bg-repeat",
1106
- "bg-no-repeat",
1107
- "bg-repeat-x",
1108
- "bg-repeat-y",
1109
- "bg-repeat-round",
1110
- "bg-repeat-space",
1111
- // Background attachment
1112
- "bg-fixed",
1113
- "bg-local",
1114
- "bg-scroll",
1115
- // Background image
1116
- "bg-none",
1117
- // Box sizing
1118
- "box-border",
1119
- "box-content",
1120
- // Resize
1121
- "resize",
1122
- "resize-none",
1123
- "resize-y",
1124
- "resize-x",
1125
- // Outline
1126
- "appearance-none",
1127
- "outline-none",
1128
- "outline",
1129
- // Table
1130
- "table",
1131
- "table-auto",
1132
- "table-fixed",
1133
- "caption-top",
1134
- "caption-bottom",
1135
- // CSS filters (standalone = default/full effect)
1136
- "grayscale",
1137
- "invert",
1138
- "sepia",
1139
- // Isolation
1140
- "isolate",
1141
- "isolation-auto",
1142
- // Backface visibility (both platforms)
1143
- "backface-visible",
1144
- "backface-hidden",
1145
- // Divide none
1146
- "divide-none",
1147
- // Group / peer markers (no-op style; needed so isKnownUtility recognises them)
1148
- "group",
1149
- "peer",
1150
- // Text-wrap (web-only)
1151
- "text-wrap",
1152
- "text-nowrap",
1153
- "text-balance",
1154
- "text-pretty",
1155
- // Screen sizing
1156
- "w-screen",
1157
- "min-h-screen",
1158
- "max-h-screen",
1159
- "min-w-screen",
1160
- "max-w-screen",
1161
- // max-w named container sizes (Tailwind compat)
1162
- "max-w-none",
1163
- "max-w-xs",
1164
- "max-w-sm",
1165
- "max-w-md",
1166
- "max-w-lg",
1167
- "max-w-xl",
1168
- "max-w-2xl",
1169
- "max-w-3xl",
1170
- "max-w-4xl",
1171
- "max-w-5xl",
1172
- "max-w-6xl",
1173
- "max-w-7xl",
1174
- "max-w-prose",
1175
- // Extended cursors (web-only)
1176
- "cursor-grab",
1177
- "cursor-grabbing",
1178
- "cursor-zoom-in",
1179
- "cursor-zoom-out",
1180
- "cursor-crosshair",
1181
- "cursor-help",
1182
- "cursor-none",
1183
- // Overflow clip (web-only)
1184
- "overflow-clip",
1185
- "overflow-x-clip",
1186
- "overflow-y-clip",
1187
- // Scroll behavior (web-only)
1188
- "scroll-smooth",
1189
- "scroll-auto",
1190
- // Float & clear (web-only)
1191
- "float-left",
1192
- "float-right",
1193
- "float-start",
1194
- "float-end",
1195
- "float-none",
1196
- "clear-left",
1197
- "clear-right",
1198
- "clear-both",
1199
- "clear-start",
1200
- "clear-end",
1201
- "clear-none",
1202
- // Vertical align (web-only)
1203
- "align-baseline",
1204
- "align-top",
1205
- "align-middle",
1206
- "align-bottom",
1207
- "align-text-top",
1208
- "align-text-bottom",
1209
- "align-sub",
1210
- "align-super",
1211
- // Touch action (web-only)
1212
- "touch-auto",
1213
- "touch-none",
1214
- "touch-pan-x",
1215
- "touch-pan-y",
1216
- "touch-pan-left",
1217
- "touch-pan-right",
1218
- "touch-pan-up",
1219
- "touch-pan-down",
1220
- "touch-pinch-zoom",
1221
- "touch-manipulation"
1222
- ]);
1223
- function parseClass(className) {
1224
- const trimmed = className.trim();
1225
- if (!trimmed) return null;
1226
- const modifiers = [];
1227
- let remaining = trimmed;
1228
- for (let i = 0; i < 3; i++) {
1229
- const colonIdx = findOuterColon(remaining);
1230
- if (colonIdx === -1) break;
1231
- const candidate = remaining.slice(0, colonIdx);
1232
- if (MODIFIERS.has(candidate) || PLUGIN_MODIFIERS.has(candidate)) {
1233
- modifiers.push(candidate);
1234
- remaining = remaining.slice(colonIdx + 1);
1235
- } else {
1236
- break;
1237
- }
1238
- }
1239
- let important = false;
1240
- if (remaining.startsWith("!") && remaining.length > 1) {
1241
- important = true;
1242
- remaining = remaining.slice(1);
1243
- }
1244
- let negative = false;
1245
- if (remaining.startsWith("-") && remaining.length > 1 && remaining[1] !== "-") {
1246
- negative = true;
1247
- remaining = remaining.slice(1);
1248
- }
1249
- const bracketStart = remaining.lastIndexOf("-[");
1250
- if (bracketStart > 0 && remaining.endsWith("]")) {
1251
- const utility = remaining.slice(0, bracketStart);
1252
- const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
1253
- return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
1254
- }
1255
- if (STANDALONE_UTILITIES.has(remaining)) {
1256
- return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
1257
- }
1258
- for (const prefix of SORTED_PREFIXES) {
1259
- if (remaining === prefix) {
1260
- return { original: trimmed, modifiers, negative, important, utility: prefix, value: "", isArbitrary: false };
1261
- }
1262
- if (remaining.startsWith(prefix + "-")) {
1263
- const value = remaining.slice(prefix.length + 1);
1264
- return { original: trimmed, modifiers, negative, important, utility: prefix, value, isArbitrary: false };
1265
- }
1266
- }
1267
- const firstDash = remaining.indexOf("-");
1268
- if (firstDash > 0) {
1269
- return {
1270
- original: trimmed,
1271
- modifiers,
1272
- negative,
1273
- important,
1274
- utility: remaining.slice(0, firstDash),
1275
- value: remaining.slice(firstDash + 1),
1276
- isArbitrary: false
1277
- };
1278
- }
1279
- return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
642
+ for (const k of Object.keys(_pluginModifiers)) delete _pluginModifiers[k];
643
+ _invalidate();
1280
644
  }
1281
- function splitClassTokens(classString) {
1282
- const tokens = [];
1283
- let current = "";
1284
- let depth = 0;
1285
- for (let i = 0; i < classString.length; i++) {
1286
- const ch = classString[i];
1287
- if (ch === "[") {
1288
- depth++;
1289
- current += ch;
1290
- continue;
1291
- }
1292
- if (ch === "]") {
1293
- depth--;
1294
- current += ch;
1295
- continue;
1296
- }
1297
- if (/\s/.test(ch)) {
1298
- if (depth === 0) {
1299
- if (current) {
1300
- tokens.push(current);
1301
- current = "";
1302
- }
1303
- }
1304
- } else {
1305
- current += ch;
1306
- }
1307
- }
1308
- if (current) tokens.push(current);
1309
- return tokens;
645
+ function getModifier(name) {
646
+ return BUILTIN_MODIFIERS[name] ?? _pluginModifiers[name];
1310
647
  }
1311
- function normalizeClassString(classString) {
1312
- return splitClassTokens(classString).join(" ");
648
+ function isKnownModifier(name) {
649
+ return name in BUILTIN_MODIFIERS || name in _pluginModifiers;
1313
650
  }
1314
- function parseClasses(classString) {
1315
- const results = [];
1316
- for (const token of splitClassTokens(classString)) {
1317
- const parsed = parseClass(token);
1318
- if (parsed) results.push(parsed);
651
+ function _allEntries() {
652
+ return [...Object.entries(BUILTIN_MODIFIERS), ...Object.entries(_pluginModifiers)];
653
+ }
654
+ function getInteractiveModifiers() {
655
+ if (!_interactiveNames) {
656
+ _interactiveNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "interactive").map(([k]) => k));
1319
657
  }
1320
- return results;
658
+ return _interactiveNames;
1321
659
  }
1322
- function findOuterColon(s) {
1323
- let depth = 0;
1324
- for (let i = 0; i < s.length; i++) {
1325
- const ch = s[i];
1326
- if (ch === "[") depth++;
1327
- else if (ch === "]") depth--;
1328
- else if (ch === ":" && depth === 0) return i;
660
+ function getModeModifiers() {
661
+ if (!_modeNames) {
662
+ _modeNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "mode").map(([k]) => k));
1329
663
  }
1330
- return -1;
664
+ return _modeNames;
665
+ }
666
+ function getResponsiveModifiers() {
667
+ if (!_responsiveNames) {
668
+ _responsiveNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "responsive").map(([k]) => k));
669
+ }
670
+ return _responsiveNames;
671
+ }
672
+ function matchModifier(name, isDark, state, breakpoints) {
673
+ return getModifier(name)?.jsMatch?.(isDark, state, breakpoints) ?? false;
1331
674
  }
1332
675
 
1333
676
  // src/core/utilities.ts
@@ -1421,6 +764,7 @@ function resolveSizing(value, spacing, isArbitrary) {
1421
764
  if (raw !== void 0) return raw;
1422
765
  if (/^\d+\/\d+$/.test(value)) {
1423
766
  const [num, den] = value.split("/").map(Number);
767
+ if (!den) return null;
1424
768
  return `${(num / den * 100).toFixed(6)}%`;
1425
769
  }
1426
770
  return null;
@@ -2935,10 +2279,10 @@ function resolveUtility(parsed, theme) {
2935
2279
  if (!parsed.value) {
2936
2280
  if (parsed.utility in PLUGIN_STANDALONE) return PLUGIN_STANDALONE[parsed.utility] ?? null;
2937
2281
  if (parsed.utility === "grd" || parsed.utility === "grid") {
2938
- return { display: "grid" };
2282
+ return getEffectiveIsWeb() ? { display: "grid" } : null;
2939
2283
  }
2940
2284
  if (parsed.utility === "inline-grid") {
2941
- return { display: "inline-grid" };
2285
+ return getEffectiveIsWeb() ? { display: "inline-grid" } : null;
2942
2286
  }
2943
2287
  if (parsed.utility in getStandalone()) return getStandalone()[parsed.utility] ?? null;
2944
2288
  }
@@ -2951,6 +2295,8 @@ var PLUGIN_RESOLVERS = {};
2951
2295
  function clearPluginUtilities() {
2952
2296
  for (const key of Object.keys(PLUGIN_STANDALONE)) delete PLUGIN_STANDALONE[key];
2953
2297
  for (const key of Object.keys(PLUGIN_RESOLVERS)) delete PLUGIN_RESOLVERS[key];
2298
+ _sortedPrefixes = null;
2299
+ _standaloneNames = null;
2954
2300
  }
2955
2301
  function getPluginStandaloneMap() {
2956
2302
  return PLUGIN_STANDALONE;
@@ -2958,6 +2304,129 @@ function getPluginStandaloneMap() {
2958
2304
  function isKnownUtility(utility) {
2959
2305
  return utility in getStandalone() || utility in RESOLVERS || utility in PLUGIN_STANDALONE || utility in PLUGIN_RESOLVERS;
2960
2306
  }
2307
+ var _sortedPrefixes = null;
2308
+ var _standaloneNames = null;
2309
+ function getBuiltinUtilityPrefixes() {
2310
+ if (!_sortedPrefixes) {
2311
+ const all = [.../* @__PURE__ */ new Set([...Object.keys(RESOLVERS), ...Object.keys(PLUGIN_RESOLVERS)])];
2312
+ _sortedPrefixes = all.sort((a, b) => b.length - a.length);
2313
+ }
2314
+ return _sortedPrefixes;
2315
+ }
2316
+ function getBuiltinStandaloneNames() {
2317
+ if (!_standaloneNames) {
2318
+ _standaloneNames = /* @__PURE__ */ new Set([...Object.keys(getStandalone()), ...Object.keys(PLUGIN_STANDALONE)]);
2319
+ }
2320
+ return _standaloneNames;
2321
+ }
2322
+
2323
+ // src/core/parser.ts
2324
+ function parseClass(className) {
2325
+ const trimmed = className.trim();
2326
+ if (!trimmed) return null;
2327
+ const modifiers = [];
2328
+ let remaining = trimmed;
2329
+ while (true) {
2330
+ const colonIdx = findOuterColon(remaining);
2331
+ if (colonIdx === -1) break;
2332
+ const candidate = remaining.slice(0, colonIdx);
2333
+ if (!isKnownModifier(candidate)) break;
2334
+ modifiers.push(candidate);
2335
+ remaining = remaining.slice(colonIdx + 1);
2336
+ }
2337
+ let important = false;
2338
+ if (remaining.startsWith("!") && remaining.length > 1) {
2339
+ important = true;
2340
+ remaining = remaining.slice(1);
2341
+ }
2342
+ let negative = false;
2343
+ if (remaining.startsWith("-") && remaining.length > 1 && remaining[1] !== "-") {
2344
+ negative = true;
2345
+ remaining = remaining.slice(1);
2346
+ }
2347
+ const bracketStart = remaining.lastIndexOf("-[");
2348
+ if (bracketStart > 0 && remaining.endsWith("]")) {
2349
+ const utility = remaining.slice(0, bracketStart);
2350
+ const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
2351
+ return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2352
+ }
2353
+ if (getBuiltinStandaloneNames().has(remaining)) {
2354
+ return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2355
+ }
2356
+ for (const prefix of getBuiltinUtilityPrefixes()) {
2357
+ if (remaining === prefix) {
2358
+ return { original: trimmed, modifiers, negative, important, utility: prefix, value: "", isArbitrary: false };
2359
+ }
2360
+ if (remaining.startsWith(prefix + "-")) {
2361
+ const value = remaining.slice(prefix.length + 1);
2362
+ return { original: trimmed, modifiers, negative, important, utility: prefix, value, isArbitrary: false };
2363
+ }
2364
+ }
2365
+ const firstDash = remaining.indexOf("-");
2366
+ if (firstDash > 0) {
2367
+ return {
2368
+ original: trimmed,
2369
+ modifiers,
2370
+ negative,
2371
+ important,
2372
+ utility: remaining.slice(0, firstDash),
2373
+ value: remaining.slice(firstDash + 1),
2374
+ isArbitrary: false
2375
+ };
2376
+ }
2377
+ return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2378
+ }
2379
+ function splitClassTokens(classString) {
2380
+ const tokens = [];
2381
+ let current = "";
2382
+ let depth = 0;
2383
+ for (let i = 0; i < classString.length; i++) {
2384
+ const ch = classString[i];
2385
+ if (ch === "[") {
2386
+ depth++;
2387
+ current += ch;
2388
+ continue;
2389
+ }
2390
+ if (ch === "]") {
2391
+ depth--;
2392
+ current += ch;
2393
+ continue;
2394
+ }
2395
+ if (/\s/.test(ch)) {
2396
+ if (depth === 0) {
2397
+ if (current) {
2398
+ tokens.push(current);
2399
+ current = "";
2400
+ }
2401
+ }
2402
+ } else {
2403
+ current += ch;
2404
+ }
2405
+ }
2406
+ if (current) tokens.push(current);
2407
+ return tokens;
2408
+ }
2409
+ function normalizeClassString(classString) {
2410
+ return splitClassTokens(classString).join(" ");
2411
+ }
2412
+ function parseClasses(classString) {
2413
+ const results = [];
2414
+ for (const token of splitClassTokens(classString)) {
2415
+ const parsed = parseClass(token);
2416
+ if (parsed) results.push(parsed);
2417
+ }
2418
+ return results;
2419
+ }
2420
+ function findOuterColon(s) {
2421
+ let depth = 0;
2422
+ for (let i = 0; i < s.length; i++) {
2423
+ const ch = s[i];
2424
+ if (ch === "[") depth++;
2425
+ else if (ch === "]") depth--;
2426
+ else if (ch === ":" && depth === 0) return i;
2427
+ }
2428
+ return -1;
2429
+ }
2961
2430
 
2962
2431
  // src/core/cache.ts
2963
2432
  var LRUCache = class {
@@ -2982,7 +2451,11 @@ var LRUCache = class {
2982
2451
  return this;
2983
2452
  }
2984
2453
  has(key) {
2985
- return this.cache.has(key);
2454
+ if (!this.cache.has(key)) return false;
2455
+ const value = this.cache.get(key);
2456
+ this.cache.delete(key);
2457
+ this.cache.set(key, value);
2458
+ return true;
2986
2459
  }
2987
2460
  delete(key) {
2988
2461
  return this.cache.delete(key);
@@ -3038,7 +2511,30 @@ function getActiveBreakpoints(width) {
3038
2511
  }
3039
2512
 
3040
2513
  // src/core/resolver.ts
3041
- var styleCache = new LRUCache(1e4);
2514
+ var _themeCache = /* @__PURE__ */ new WeakMap();
2515
+ function getThemeCache(theme) {
2516
+ let cache = _themeCache.get(theme);
2517
+ if (!cache) {
2518
+ cache = new LRUCache(1e4);
2519
+ _themeCache.set(theme, cache);
2520
+ }
2521
+ return cache;
2522
+ }
2523
+ var _sortCache = /* @__PURE__ */ new WeakMap();
2524
+ function getSortedEntries(resolved) {
2525
+ let sorted = _sortCache.get(resolved);
2526
+ if (!sorted) {
2527
+ const entries = Object.entries(resolved);
2528
+ entries.sort((a, b) => {
2529
+ const pa = a[0] === "base" ? -1 : a[0].split(":").length;
2530
+ const pb = b[0] === "base" ? -1 : b[0].split(":").length;
2531
+ return pa - pb;
2532
+ });
2533
+ sorted = entries;
2534
+ _sortCache.set(resolved, sorted);
2535
+ }
2536
+ return sorted;
2537
+ }
3042
2538
  var FONT_KEY = "__kbach_default_font__";
3043
2539
  function setDefaultFontFamily(font) {
3044
2540
  globalThis[FONT_KEY] = font;
@@ -3047,7 +2543,7 @@ function getDefaultFontFamily() {
3047
2543
  return globalThis[FONT_KEY];
3048
2544
  }
3049
2545
  var _styleEl = null;
3050
- var _injectedRules = /* @__PURE__ */ new Set();
2546
+ var _injectedRules = new LRUCache(5e4);
3051
2547
  function getStyleEl() {
3052
2548
  if (_styleEl) return _styleEl;
3053
2549
  _styleEl = document.createElement("style");
@@ -3057,7 +2553,7 @@ function getStyleEl() {
3057
2553
  }
3058
2554
  function injectRule(rule) {
3059
2555
  if (_injectedRules.has(rule)) return;
3060
- _injectedRules.add(rule);
2556
+ _injectedRules.set(rule, true);
3061
2557
  try {
3062
2558
  getStyleEl().sheet?.insertRule(rule, getStyleEl().sheet.cssRules.length);
3063
2559
  } catch {
@@ -3081,160 +2577,20 @@ function injectGlobalStyles(theme) {
3081
2577
  }
3082
2578
  getGlobalStyleEl().textContent = rules.join("\n");
3083
2579
  }
3084
- var MODIFIER_TO_PSEUDO = {
3085
- hover: ":hover",
3086
- focus: ":focus",
3087
- "focus-within": ":focus-within",
3088
- "focus-visible": ":focus-visible",
3089
- active: ":active",
3090
- pressed: ":active",
3091
- disabled: ":disabled",
3092
- checked: ":checked",
3093
- visited: ":visited",
3094
- placeholder: "::placeholder",
3095
- first: ":first-child",
3096
- last: ":last-child",
3097
- odd: ":nth-child(odd)",
3098
- even: ":nth-child(even)",
3099
- only: ":only-child",
3100
- "not-hover": ":not(:hover)",
3101
- "not-focus": ":not(:focus)",
3102
- "not-active": ":not(:active)",
3103
- "not-pressed": ":not(:active)",
3104
- "not-disabled": ":not(:disabled)",
3105
- "not-checked": ":not(:checked)",
3106
- "not-visited": ":not(:visited)",
3107
- // Pseudo-elements (CSS-injection only; never applied as inline styles)
3108
- before: "::before",
3109
- after: "::after",
3110
- selection: "::selection",
3111
- "first-letter": "::first-letter",
3112
- "first-line": "::first-line",
3113
- marker: "::marker"
3114
- };
3115
- var GROUP_PEER_PREFIX = {
3116
- "group-hover": ".group:hover",
3117
- "group-focus": ".group:focus",
3118
- "peer-hover": ".peer:hover ~",
3119
- "peer-focus": ".peer:focus ~"
3120
- };
3121
- var MODE_MODS = /* @__PURE__ */ new Set(["dark", "light", "not-dark", "not-light"]);
3122
- var RESPONSIVE_MODS = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
3123
- var PRINT_MODS = /* @__PURE__ */ new Set(["print"]);
3124
- var MEDIA_MODS = {
3125
- landscape: "(orientation: landscape)",
3126
- portrait: "(orientation: portrait)",
3127
- "motion-reduce": "(prefers-reduced-motion: reduce)",
3128
- "motion-safe": "(prefers-reduced-motion: no-preference)",
3129
- "contrast-more": "(prefers-contrast: more)",
3130
- "contrast-less": "(prefers-contrast: less)"
3131
- };
3132
- var DIR_MODS = {
3133
- rtl: '[dir="rtl"]',
3134
- ltr: '[dir="ltr"]'
3135
- };
3136
2580
  function buildDivideDecls(styles) {
3137
2581
  const parts = [];
3138
2582
  if ("__divideX" in styles) {
3139
2583
  const w = Number(styles.__divideX);
3140
- parts.push(`border-left-width: ${w}px`);
3141
- parts.push("border-right-width: 0px");
2584
+ parts.push(`border-left-width: ${w}px`, "border-right-width: 0px");
3142
2585
  }
3143
2586
  if ("__divideY" in styles) {
3144
2587
  const w = Number(styles.__divideY);
3145
- parts.push(`border-top-width: ${w}px`);
3146
- parts.push("border-bottom-width: 0px");
2588
+ parts.push(`border-top-width: ${w}px`, "border-bottom-width: 0px");
3147
2589
  }
3148
2590
  if ("__divideColor" in styles) parts.push(`border-color: ${String(styles.__divideColor)}`);
3149
2591
  if ("__divideStyle" in styles) parts.push(`border-style: ${String(styles.__divideStyle)}`);
3150
2592
  return parts.join("; ");
3151
2593
  }
3152
- function buildClassCSSRules(cls, bucketKey, styles, darkMode, important, screens) {
3153
- const rules = [];
3154
- if ("__keyframe" in styles && typeof styles.__keyframe === "string") {
3155
- rules.push(styles.__keyframe);
3156
- }
3157
- const isDivide = "__divideX" in styles || "__divideY" in styles || "__divideColor" in styles || "__divideStyle" in styles;
3158
- const escaped = escapeCSSSelector(cls);
3159
- const childSuffix = isDivide ? " > * + *" : "";
3160
- if (bucketKey === "base") {
3161
- const baseCssDecls = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, important);
3162
- if (!baseCssDecls) return rules;
3163
- rules.push(`.${escaped}${childSuffix} { ${baseCssDecls} }`);
3164
- return rules;
3165
- }
3166
- const mods = bucketKey.split(":");
3167
- const responsiveMods = mods.filter((m) => RESPONSIVE_MODS.has(m));
3168
- const nonResponsiveMods = mods.filter((m) => !RESPONSIVE_MODS.has(m));
3169
- const hasDark = nonResponsiveMods.includes("dark") || nonResponsiveMods.includes("not-light");
3170
- const hasLight = nonResponsiveMods.includes("light") || nonResponsiveMods.includes("not-dark");
3171
- const hasPrint = nonResponsiveMods.includes("print");
3172
- const mediaMods = nonResponsiveMods.filter((m) => m in MEDIA_MODS);
3173
- const dirMods = nonResponsiveMods.filter((m) => m in DIR_MODS);
3174
- const ancestorMods = nonResponsiveMods.filter((m) => m in GROUP_PEER_PREFIX);
3175
- const pseudoMods = nonResponsiveMods.filter(
3176
- (m) => !MODE_MODS.has(m) && !(m in GROUP_PEER_PREFIX) && !PRINT_MODS.has(m) && !(m in MEDIA_MODS) && !(m in DIR_MODS)
3177
- );
3178
- const pseudoSuffix = pseudoMods.map((p) => MODIFIER_TO_PSEUDO[p] ?? `:${p}`).join("");
3179
- const elementSelector = `.${escaped}${pseudoSuffix}${childSuffix}`;
3180
- const ancestorPrefix = ancestorMods.length ? ancestorMods.map((m) => GROUP_PEER_PREFIX[m]).join(" ") + " " : "";
3181
- const dirPrefix = dirMods.length ? dirMods.map((m) => DIR_MODS[m]).join(" ") + " " : "";
3182
- const selector = `${dirPrefix}${ancestorPrefix}${elementSelector}`;
3183
- const CSS_ONLY_PSEUDOS = /* @__PURE__ */ new Set([
3184
- "first",
3185
- "last",
3186
- "odd",
3187
- "even",
3188
- "only",
3189
- "focus-within",
3190
- "focus-visible"
3191
- ]);
3192
- const needsImportant = important || hasPrint || mediaMods.length > 0 || dirMods.length > 0 || ancestorMods.length > 0 || pseudoMods.some((m) => CSS_ONLY_PSEUDOS.has(m));
3193
- const cssDecls = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, needsImportant);
3194
- if (!cssDecls) return rules;
3195
- let rule;
3196
- if (hasDark) {
3197
- if (darkMode === "media") {
3198
- rule = `@media (prefers-color-scheme: dark) { ${selector} { ${cssDecls} } }`;
3199
- } else if (darkMode === "class") {
3200
- rule = `.dark ${selector} { ${cssDecls} }`;
3201
- } else {
3202
- rule = `[data-theme="dark"] ${selector} { ${cssDecls} }`;
3203
- }
3204
- } else if (hasLight) {
3205
- if (darkMode === "media") {
3206
- rule = `@media (prefers-color-scheme: light) { ${selector} { ${cssDecls} } }`;
3207
- } else if (darkMode === "class") {
3208
- rule = `:not(.dark) ${selector} { ${cssDecls} }`;
3209
- } else {
3210
- rule = `[data-theme="light"] ${selector} { ${cssDecls} }`;
3211
- }
3212
- } else {
3213
- rule = `${selector} { ${cssDecls} }`;
3214
- }
3215
- if (hasPrint) rule = `@media print { ${rule} }`;
3216
- for (const m of mediaMods) rule = `@media ${MEDIA_MODS[m]} { ${rule} }`;
3217
- if (responsiveMods.length > 0) {
3218
- const minWidth = Math.max(...responsiveMods.map((m) => screens[m] ?? 0));
3219
- if (minWidth > 0) rule = `@media (min-width: ${minWidth}px) { ${rule} }`;
3220
- }
3221
- rules.push(rule);
3222
- return rules;
3223
- }
3224
- function injectClassRule(cls, bucketKey, styles, darkMode, important = false) {
3225
- const cssRules = buildClassCSSRules(cls, bucketKey, styles, darkMode, important, getGlobalScreens());
3226
- for (const r of cssRules) injectRule(r);
3227
- }
3228
- function generateClassCSS(classString, theme, darkMode = "attribute", screens = {}) {
3229
- const rules = [];
3230
- for (const parsed of parseClasses(classString)) {
3231
- const styles = resolveUtility(parsed, theme);
3232
- if (!styles) continue;
3233
- const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
3234
- rules.push(...buildClassCSSRules(parsed.original, bucketKey, styles, darkMode, parsed.important, screens));
3235
- }
3236
- return rules.join("\n");
3237
- }
3238
2594
  var RN_ONLY_PROPS = /* @__PURE__ */ new Set([
3239
2595
  "shadowColor",
3240
2596
  "shadowOffset",
@@ -3244,13 +2600,10 @@ var RN_ONLY_PROPS = /* @__PURE__ */ new Set([
3244
2600
  "includeFontPadding",
3245
2601
  "textAlignVertical",
3246
2602
  "writingDirection",
3247
- // Text shadow native props — web uses the textShadow CSS shorthand instead
3248
2603
  "textShadowColor",
3249
2604
  "textShadowOffset",
3250
2605
  "textShadowRadius",
3251
- // tintColor is native-only (Image/icon tinting)
3252
2606
  "tintColor",
3253
- // Internal markers — handled specially, never serialized as CSS props
3254
2607
  "__divideX",
3255
2608
  "__divideY",
3256
2609
  "__divideColor",
@@ -3292,8 +2645,7 @@ function styleValueToCSS(styles, forceImportant = false) {
3292
2645
  const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3293
2646
  if (prop in RN_SHORTHAND_EXPAND) {
3294
2647
  const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
3295
- parts.push(`${p1}: ${cssVal}${imp}`);
3296
- parts.push(`${p2}: ${cssVal}${imp}`);
2648
+ parts.push(`${p1}: ${cssVal}${imp}`, `${p2}: ${cssVal}${imp}`);
3297
2649
  continue;
3298
2650
  }
3299
2651
  parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
@@ -3303,14 +2655,97 @@ function styleValueToCSS(styles, forceImportant = false) {
3303
2655
  function camelToKebab(str) {
3304
2656
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
3305
2657
  }
2658
+ function buildClassCSSRules(cls, bucketKey, styles, darkMode, important, screens) {
2659
+ const rules = [];
2660
+ if ("__keyframe" in styles && typeof styles.__keyframe === "string") {
2661
+ rules.push(styles.__keyframe);
2662
+ }
2663
+ const isDivide = "__divideX" in styles || "__divideY" in styles || "__divideColor" in styles || "__divideStyle" in styles;
2664
+ const escaped = escapeCSSSelector(cls);
2665
+ const childSuffix = isDivide ? " > * + *" : "";
2666
+ if (bucketKey === "base") {
2667
+ const decls2 = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, important);
2668
+ if (!decls2) return rules;
2669
+ rules.push(`.${escaped}${childSuffix} { ${decls2} }`);
2670
+ return rules;
2671
+ }
2672
+ const mods = bucketKey.split(":");
2673
+ let darkScheme;
2674
+ let needsImportant = important;
2675
+ const pseudoParts = [];
2676
+ const ancestorParts = [];
2677
+ const dirParts = [];
2678
+ const mediaWrappers = [];
2679
+ let minWidth = 0;
2680
+ for (const mod of mods) {
2681
+ const def = getModifier(mod);
2682
+ if (!def) continue;
2683
+ if (def.darkScheme) darkScheme = def.darkScheme;
2684
+ if (def.pseudo) pseudoParts.push(def.pseudo);
2685
+ if (def.ancestorSelector) {
2686
+ ancestorParts.push(def.ancestorSelector);
2687
+ needsImportant = true;
2688
+ }
2689
+ if (def.dirSelector) {
2690
+ dirParts.push(def.dirSelector);
2691
+ needsImportant = true;
2692
+ }
2693
+ if (def.mediaQuery) {
2694
+ mediaWrappers.push(`@media ${def.mediaQuery}`);
2695
+ needsImportant = true;
2696
+ }
2697
+ if (def.isResponsive) {
2698
+ const w = screens[mod] ?? 0;
2699
+ if (w > minWidth) minWidth = w;
2700
+ }
2701
+ if (def.forcesImportant) needsImportant = true;
2702
+ }
2703
+ const pseudoSuffix = pseudoParts.join("");
2704
+ const elementSelector = `.${escaped}${pseudoSuffix}${childSuffix}`;
2705
+ const ancestorPrefix = ancestorParts.join("");
2706
+ const dirPrefix = dirParts.join("");
2707
+ const selector = `${dirPrefix}${ancestorPrefix}${elementSelector}`;
2708
+ const decls = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, needsImportant);
2709
+ if (!decls) return rules;
2710
+ let rule;
2711
+ if (darkScheme === "dark") {
2712
+ if (darkMode === "media") rule = `@media (prefers-color-scheme: dark) { ${selector} { ${decls} } }`;
2713
+ else if (darkMode === "class") rule = `.dark ${selector} { ${decls} }`;
2714
+ else rule = `[data-theme="dark"] ${selector} { ${decls} }`;
2715
+ } else if (darkScheme === "light") {
2716
+ if (darkMode === "media") rule = `@media (prefers-color-scheme: light) { ${selector} { ${decls} } }`;
2717
+ else if (darkMode === "class") rule = `:not(.dark) ${selector} { ${decls} }`;
2718
+ else rule = `[data-theme="light"] ${selector} { ${decls} }`;
2719
+ } else {
2720
+ rule = `${selector} { ${decls} }`;
2721
+ }
2722
+ for (const mw of mediaWrappers) rule = `${mw} { ${rule} }`;
2723
+ if (minWidth > 0) rule = `@media (min-width: ${minWidth}px) { ${rule} }`;
2724
+ rules.push(rule);
2725
+ return rules;
2726
+ }
2727
+ function injectClassRule(cls, bucketKey, styles, darkMode, important) {
2728
+ const cssRules = buildClassCSSRules(cls, bucketKey, styles, darkMode, important, getGlobalScreens());
2729
+ for (const r of cssRules) injectRule(r);
2730
+ }
2731
+ function generateClassCSS(classString, theme, darkMode = "attribute", screens = {}) {
2732
+ const rules = [];
2733
+ for (const parsed of parseClasses(classString)) {
2734
+ const styles = resolveUtility(parsed, theme);
2735
+ if (!styles) continue;
2736
+ const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
2737
+ rules.push(...buildClassCSSRules(parsed.original, bucketKey, styles, darkMode, parsed.important, screens));
2738
+ }
2739
+ return rules.join("\n");
2740
+ }
3306
2741
  function resolve(classString, theme, darkMode = "attribute") {
2742
+ const cache = getThemeCache(theme);
3307
2743
  const cacheKey = `${classString}::${darkMode}`;
3308
- const cached = styleCache.get(cacheKey);
2744
+ const cached = cache.get(cacheKey);
3309
2745
  if (cached) return cached;
3310
2746
  const result = {};
3311
- const parsedClasses = parseClasses(classString);
3312
- const injectQueue = [];
3313
- for (const parsed of parsedClasses) {
2747
+ const onWeb = typeof document !== "undefined";
2748
+ for (const parsed of parseClasses(classString)) {
3314
2749
  const styles = resolveUtility(parsed, theme);
3315
2750
  if (!styles) {
3316
2751
  if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility)) {
@@ -3321,116 +2756,60 @@ function resolve(classString, theme, darkMode = "attribute") {
3321
2756
  const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
3322
2757
  if (!result[bucketKey]) result[bucketKey] = {};
3323
2758
  Object.assign(result[bucketKey], styles);
3324
- if (typeof document !== "undefined") {
3325
- injectQueue.push({ cls: parsed.original, bucketKey, styles, important: parsed.important });
3326
- }
3327
- }
3328
- styleCache.set(cacheKey, result);
3329
- if (typeof document !== "undefined") {
3330
- for (const { cls, bucketKey, styles, important } of injectQueue) {
3331
- injectClassRule(cls, bucketKey, styles, darkMode, important);
2759
+ if (onWeb) {
2760
+ injectClassRule(parsed.original, bucketKey, styles, darkMode, parsed.important);
3332
2761
  }
3333
2762
  }
2763
+ cache.set(cacheKey, result);
3334
2764
  return result;
3335
2765
  }
3336
2766
  function flatten(resolved, isDark, state = {}, breakpoints = /* @__PURE__ */ new Set()) {
3337
2767
  const result = {};
3338
- const entries = Object.entries(resolved);
3339
- entries.sort((a, b) => {
3340
- const pa = a[0] === "base" ? -1 : a[0].split(":").length;
3341
- const pb = b[0] === "base" ? -1 : b[0].split(":").length;
3342
- return pa - pb;
3343
- });
3344
- for (const [key, styles] of entries) {
2768
+ for (const [key, styles] of getSortedEntries(resolved)) {
3345
2769
  if (!styles) continue;
3346
2770
  if (key === "base") {
3347
2771
  Object.assign(result, styles);
3348
2772
  continue;
3349
2773
  }
3350
2774
  const mods = key.split(":");
3351
- if (matchesMods(mods, isDark, state, breakpoints)) {
2775
+ if (mods.every((mod) => matchModifier(mod, isDark, state, breakpoints))) {
3352
2776
  Object.assign(result, styles);
3353
2777
  }
3354
2778
  }
3355
- const _df = getDefaultFontFamily();
3356
- if (_df && !("fontFamily" in result)) {
3357
- result.fontFamily = _df;
2779
+ const defaultFont = getDefaultFontFamily();
2780
+ if (defaultFont && !("fontFamily" in result)) {
2781
+ result.fontFamily = defaultFont;
3358
2782
  }
3359
2783
  if (isWeb) {
3360
2784
  const r = result;
3361
- for (const [rnProp, [p1, p2]] of Object.entries(RN_SHORTHAND_EXPAND)) {
3362
- const v = r[rnProp];
3363
- if (v !== void 0) {
3364
- r[p1] = v;
3365
- r[p2] = v;
3366
- delete r[rnProp];
3367
- }
2785
+ const ph = r.paddingHorizontal;
2786
+ if (ph !== void 0) {
2787
+ r.paddingLeft = ph;
2788
+ r.paddingRight = ph;
2789
+ delete r.paddingHorizontal;
2790
+ }
2791
+ const pv = r.paddingVertical;
2792
+ if (pv !== void 0) {
2793
+ r.paddingTop = pv;
2794
+ r.paddingBottom = pv;
2795
+ delete r.paddingVertical;
2796
+ }
2797
+ const mh = r.marginHorizontal;
2798
+ if (mh !== void 0) {
2799
+ r.marginLeft = mh;
2800
+ r.marginRight = mh;
2801
+ delete r.marginHorizontal;
2802
+ }
2803
+ const mv = r.marginVertical;
2804
+ if (mv !== void 0) {
2805
+ r.marginTop = mv;
2806
+ r.marginBottom = mv;
2807
+ delete r.marginVertical;
3368
2808
  }
3369
2809
  }
3370
2810
  return result;
3371
2811
  }
3372
- function matchesMods(mods, isDark, state, breakpoints) {
3373
- return mods.every((mod) => {
3374
- switch (mod) {
3375
- case "dark":
3376
- return isDark;
3377
- case "light":
3378
- case "not-dark":
3379
- return !isDark;
3380
- case "not-light":
3381
- return isDark;
3382
- case "hover":
3383
- return !!state.hover;
3384
- case "not-hover":
3385
- return !state.hover;
3386
- case "focus":
3387
- return !!state.focus;
3388
- case "not-focus":
3389
- return !state.focus;
3390
- case "pressed":
3391
- case "active":
3392
- return !!state.pressed || !!state.active;
3393
- case "not-pressed":
3394
- case "not-active":
3395
- return !state.pressed && !state.active;
3396
- case "disabled":
3397
- return !!state.disabled;
3398
- case "not-disabled":
3399
- return !state.disabled;
3400
- case "checked":
3401
- return !!state.checked;
3402
- case "not-checked":
3403
- return !state.checked;
3404
- case "visited":
3405
- return !!state.visited;
3406
- case "not-visited":
3407
- return !state.visited;
3408
- case "placeholder":
3409
- return !!state.placeholder;
3410
- case "sm":
3411
- case "md":
3412
- case "lg":
3413
- case "xl":
3414
- case "2xl":
3415
- return breakpoints.has(mod);
3416
- // CSS-only modifiers — never applied as inline styles
3417
- case "print":
3418
- case "landscape":
3419
- case "portrait":
3420
- case "motion-reduce":
3421
- case "motion-safe":
3422
- case "contrast-more":
3423
- case "contrast-less":
3424
- case "rtl":
3425
- case "ltr":
3426
- return false;
3427
- default:
3428
- return false;
3429
- }
3430
- });
3431
- }
3432
2812
  function clearCache() {
3433
- styleCache.clear();
3434
2813
  _injectedRules.clear();
3435
2814
  if (_styleEl) {
3436
2815
  _styleEl.remove();
@@ -3477,14 +2856,24 @@ function resolveOneRef(ref, colors) {
3477
2856
  return entry[m[2]] ?? null;
3478
2857
  }
3479
2858
  function resolveColorRefs(colors) {
2859
+ const MAX_DEPTH = 5;
2860
+ function resolveChain(raw) {
2861
+ let current = raw;
2862
+ for (let i = 0; i < MAX_DEPTH; i++) {
2863
+ const next = resolveOneRef(current, colors);
2864
+ if (!next || next === current) break;
2865
+ current = next;
2866
+ }
2867
+ return current;
2868
+ }
3480
2869
  const out = {};
3481
2870
  for (const [key, val] of Object.entries(colors)) {
3482
2871
  if (typeof val === "string") {
3483
- out[key] = resolveOneRef(val, colors) ?? val;
2872
+ out[key] = resolveChain(val);
3484
2873
  } else {
3485
2874
  const shades = {};
3486
2875
  for (const [shade, hex] of Object.entries(val)) {
3487
- shades[shade] = resolveOneRef(hex, colors) ?? hex;
2876
+ shades[shade] = resolveChain(hex);
3488
2877
  }
3489
2878
  out[key] = shades;
3490
2879
  }
@@ -3532,15 +2921,26 @@ function buildConfig(userConfig) {
3532
2921
  injectGlobalStyles(resolved.theme);
3533
2922
  return resolved;
3534
2923
  }
2924
+ function _selectorToModifierDef(selector) {
2925
+ const s = selector.trim();
2926
+ if (s.startsWith("@media ")) {
2927
+ return { mediaQuery: s.slice(7), jsBehavior: "css-only", forcesImportant: true };
2928
+ }
2929
+ if (s.startsWith("::") || s.startsWith(":")) {
2930
+ return { pseudo: s, jsBehavior: "css-only", forcesImportant: true };
2931
+ }
2932
+ return { ancestorSelector: s.endsWith(" ") ? s : `${s} `, jsBehavior: "css-only", forcesImportant: true };
2933
+ }
3535
2934
  function makePluginAPI(theme) {
3536
2935
  const standalone = getPluginStandaloneMap();
3537
2936
  return {
3538
2937
  addUtility(name, styles) {
3539
2938
  standalone[name] = styles;
3540
2939
  },
3541
- addVariant(name, selector) {
3542
- customVariants[name] = selector;
3543
- registerModifier(name);
2940
+ addVariant(name, selectorOrDef) {
2941
+ const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
2942
+ customVariants[name] = typeof selectorOrDef === "string" ? selectorOrDef : name;
2943
+ registerModifier(name, def);
3544
2944
  },
3545
2945
  theme(path, defaultValue) {
3546
2946
  const parts = path.replace(/\[([^\]]+)\]/g, ".$1").split(".");
@@ -3601,6 +3001,9 @@ export {
3601
3001
  defaultTheme,
3602
3002
  isWeb,
3603
3003
  setCSSGenMode,
3004
+ getInteractiveModifiers,
3005
+ getModeModifiers,
3006
+ getResponsiveModifiers,
3604
3007
  parseClass,
3605
3008
  splitClassTokens,
3606
3009
  normalizeClassString,