@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.
@@ -598,7 +598,11 @@ var LRUCache = class {
598
598
  return this;
599
599
  }
600
600
  has(key) {
601
- return this.cache.has(key);
601
+ if (!this.cache.has(key)) return false;
602
+ const value = this.cache.get(key);
603
+ this.cache.delete(key);
604
+ this.cache.set(key, value);
605
+ return true;
602
606
  }
603
607
  delete(key) {
604
608
  return this.cache.delete(key);
@@ -628,773 +632,116 @@ function escapeCSSSelector(cls) {
628
632
  return cls.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
629
633
  }
630
634
 
631
- // src/core/parser.ts
632
- var PLUGIN_MODIFIERS = /* @__PURE__ */ new Set();
633
- function registerModifier(name) {
634
- PLUGIN_MODIFIERS.add(name);
635
+ // src/core/registry.ts
636
+ var BUILTIN_MODIFIERS = {
637
+ // ── Mode ─────────────────────────────────────────────────────────────────
638
+ dark: { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
639
+ "not-light": { darkScheme: "dark", jsBehavior: "mode", jsMatch: (d) => d },
640
+ light: { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
641
+ "not-dark": { darkScheme: "light", jsBehavior: "mode", jsMatch: (d) => !d },
642
+ // ── Interactive — JS state + CSS pseudo ───────────────────────────────────
643
+ hover: { pseudo: ":hover", jsBehavior: "interactive", jsMatch: (_, s) => !!s.hover },
644
+ "not-hover": { pseudo: ":not(:hover)", jsBehavior: "interactive", jsMatch: (_, s) => !s.hover },
645
+ focus: { pseudo: ":focus", jsBehavior: "interactive", jsMatch: (_, s) => !!s.focus },
646
+ "not-focus": { pseudo: ":not(:focus)", jsBehavior: "interactive", jsMatch: (_, s) => !s.focus },
647
+ active: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.active || !!s.pressed },
648
+ "not-active": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.active && !s.pressed },
649
+ pressed: { pseudo: ":active", jsBehavior: "interactive", jsMatch: (_, s) => !!s.pressed || !!s.active },
650
+ "not-pressed": { pseudo: ":not(:active)", jsBehavior: "interactive", jsMatch: (_, s) => !s.pressed && !s.active },
651
+ disabled: { pseudo: ":disabled", jsBehavior: "interactive", jsMatch: (_, s) => !!s.disabled },
652
+ "not-disabled": { pseudo: ":not(:disabled)", jsBehavior: "interactive", jsMatch: (_, s) => !s.disabled },
653
+ checked: { pseudo: ":checked", jsBehavior: "interactive", jsMatch: (_, s) => !!s.checked },
654
+ "not-checked": { pseudo: ":not(:checked)", jsBehavior: "interactive", jsMatch: (_, s) => !s.checked },
655
+ visited: { pseudo: ":visited", jsBehavior: "interactive", jsMatch: (_, s) => !!s.visited },
656
+ "not-visited": { pseudo: ":not(:visited)", jsBehavior: "interactive", jsMatch: (_, s) => !s.visited },
657
+ placeholder: { pseudo: "::placeholder", jsBehavior: "interactive", jsMatch: (_, s) => !!s.placeholder },
658
+ // ── CSS-only pseudo-classes (structural) ──────────────────────────────────
659
+ first: { pseudo: ":first-child", jsBehavior: "css-only", forcesImportant: true },
660
+ last: { pseudo: ":last-child", jsBehavior: "css-only", forcesImportant: true },
661
+ odd: { pseudo: ":nth-child(odd)", jsBehavior: "css-only", forcesImportant: true },
662
+ even: { pseudo: ":nth-child(even)", jsBehavior: "css-only", forcesImportant: true },
663
+ only: { pseudo: ":only-child", jsBehavior: "css-only", forcesImportant: true },
664
+ "focus-within": { pseudo: ":focus-within", jsBehavior: "css-only", forcesImportant: true },
665
+ "focus-visible": { pseudo: ":focus-visible", jsBehavior: "css-only", forcesImportant: true },
666
+ // ── CSS-only pseudo-elements ───────────────────────────────────────────────
667
+ before: { pseudo: "::before", jsBehavior: "css-only" },
668
+ after: { pseudo: "::after", jsBehavior: "css-only" },
669
+ selection: { pseudo: "::selection", jsBehavior: "css-only" },
670
+ "first-letter": { pseudo: "::first-letter", jsBehavior: "css-only" },
671
+ "first-line": { pseudo: "::first-line", jsBehavior: "css-only" },
672
+ marker: { pseudo: "::marker", jsBehavior: "css-only" },
673
+ // ── Group / peer ancestor selectors (CSS-only) ─────────────────────────────
674
+ "group-hover": { ancestorSelector: ".group:hover ", jsBehavior: "css-only", forcesImportant: true },
675
+ "group-focus": { ancestorSelector: ".group:focus ", jsBehavior: "css-only", forcesImportant: true },
676
+ "peer-hover": { ancestorSelector: ".peer:hover ~ ", jsBehavior: "css-only", forcesImportant: true },
677
+ "peer-focus": { ancestorSelector: ".peer:focus ~ ", jsBehavior: "css-only", forcesImportant: true },
678
+ // ── Responsive — both CSS (@media min-width) and JS (breakpoints set) ──────
679
+ sm: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("sm") },
680
+ md: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("md") },
681
+ lg: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("lg") },
682
+ xl: { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("xl") },
683
+ "2xl": { isResponsive: true, jsBehavior: "responsive", jsMatch: (_, __, bp) => bp.has("2xl") },
684
+ // ── Print media (CSS-only) ─────────────────────────────────────────────────
685
+ print: { mediaQuery: "print", jsBehavior: "css-only", forcesImportant: true },
686
+ // ── Orientation / accessibility media (CSS-only) ───────────────────────────
687
+ landscape: { mediaQuery: "(orientation: landscape)", jsBehavior: "css-only", forcesImportant: true },
688
+ portrait: { mediaQuery: "(orientation: portrait)", jsBehavior: "css-only", forcesImportant: true },
689
+ "motion-reduce": { mediaQuery: "(prefers-reduced-motion: reduce)", jsBehavior: "css-only", forcesImportant: true },
690
+ "motion-safe": { mediaQuery: "(prefers-reduced-motion: no-preference)", jsBehavior: "css-only", forcesImportant: true },
691
+ "contrast-more": { mediaQuery: "(prefers-contrast: more)", jsBehavior: "css-only", forcesImportant: true },
692
+ "contrast-less": { mediaQuery: "(prefers-contrast: less)", jsBehavior: "css-only", forcesImportant: true },
693
+ // ── Directionality (CSS-only) ──────────────────────────────────────────────
694
+ rtl: { dirSelector: '[dir="rtl"] ', jsBehavior: "css-only", forcesImportant: true },
695
+ ltr: { dirSelector: '[dir="ltr"] ', jsBehavior: "css-only", forcesImportant: true }
696
+ };
697
+ var _pluginModifiers = {};
698
+ var _allNames = null;
699
+ var _interactiveNames = null;
700
+ var _modeNames = null;
701
+ var _responsiveNames = null;
702
+ function _invalidate() {
703
+ _allNames = null;
704
+ _interactiveNames = null;
705
+ _modeNames = null;
706
+ _responsiveNames = null;
707
+ }
708
+ function registerModifier(name, def) {
709
+ _pluginModifiers[name] = def;
710
+ _invalidate();
635
711
  }
636
712
  function clearPluginModifiers() {
637
- PLUGIN_MODIFIERS.clear();
638
- }
639
- var MODIFIERS = /* @__PURE__ */ new Set([
640
- // Theme
641
- "dark",
642
- "light",
643
- "not-dark",
644
- "not-light",
645
- // Interaction
646
- "hover",
647
- "focus",
648
- "active",
649
- "visited",
650
- "disabled",
651
- "checked",
652
- "pressed",
653
- "placeholder",
654
- "focus-within",
655
- "focus-visible",
656
- // Negated interaction
657
- "not-hover",
658
- "not-focus",
659
- "not-active",
660
- "not-visited",
661
- "not-disabled",
662
- "not-checked",
663
- "not-pressed",
664
- // Structural
665
- "first",
666
- "last",
667
- "odd",
668
- "even",
669
- "only",
670
- // Group / peer
671
- "group-hover",
672
- "group-focus",
673
- "peer-hover",
674
- "peer-focus",
675
- // Responsive (handled separately but accepted)
676
- "sm",
677
- "md",
678
- "lg",
679
- "xl",
680
- "2xl",
681
- // Pseudo-elements (CSS-injection only; matchesMods returns false for these)
682
- "before",
683
- "after",
684
- "selection",
685
- "first-letter",
686
- "first-line",
687
- "marker",
688
- // Print media modifier
689
- "print",
690
- // Orientation media modifiers (CSS-injection only)
691
- "landscape",
692
- "portrait",
693
- // Accessibility media modifiers (CSS-injection only)
694
- "motion-reduce",
695
- "motion-safe",
696
- "contrast-more",
697
- "contrast-less",
698
- // Directionality modifiers (CSS-injection only)
699
- "rtl",
700
- "ltr"
701
- ]);
702
- var UTILITY_PREFIXES = [
703
- // Multi-word flex
704
- "flex-row-reverse",
705
- "flex-col-reverse",
706
- "flex-row",
707
- "flex-col",
708
- "flex-wrap-reverse",
709
- "flex-wrap",
710
- "flex-nowrap",
711
- "flex-shrink-0",
712
- "flex-shrink",
713
- "flex-grow-0",
714
- "flex-grow",
715
- "items-start",
716
- "items-end",
717
- "items-center",
718
- "items-baseline",
719
- "items-stretch",
720
- "justify-start",
721
- "justify-end",
722
- "justify-center",
723
- "justify-between",
724
- "justify-around",
725
- "justify-evenly",
726
- "content-start",
727
- "content-end",
728
- "content-center",
729
- "content-between",
730
- "content-around",
731
- "content-evenly",
732
- "self-start",
733
- "self-end",
734
- "self-center",
735
- "self-auto",
736
- "self-stretch",
737
- "text-left",
738
- "text-right",
739
- "text-center",
740
- "text-justify",
741
- "font-thin",
742
- "font-extralight",
743
- "font-light",
744
- "font-normal",
745
- "font-medium",
746
- "font-semibold",
747
- "font-bold",
748
- "font-extrabold",
749
- "font-black",
750
- "overflow-hidden",
751
- "overflow-visible",
752
- "overflow-scroll",
753
- "overflow-auto",
754
- "overflow-x-hidden",
755
- "overflow-x-scroll",
756
- "overflow-x-auto",
757
- "overflow-y-hidden",
758
- "overflow-y-scroll",
759
- "overflow-y-auto",
760
- "object-contain",
761
- "object-cover",
762
- "object-fill",
763
- "object-none",
764
- "object-scale-down",
765
- "border-solid",
766
- "border-dashed",
767
- "border-dotted",
768
- "border-none",
769
- "border-t",
770
- "border-r",
771
- "border-b",
772
- "border-l",
773
- "rounded-tl",
774
- "rounded-tr",
775
- "rounded-bl",
776
- "rounded-br",
777
- "rounded-t",
778
- "rounded-r",
779
- "rounded-b",
780
- "rounded-l",
781
- "list-none",
782
- "list-disc",
783
- "list-decimal",
784
- "cursor-auto",
785
- "cursor-default",
786
- "cursor-pointer",
787
- "cursor-wait",
788
- "cursor-text",
789
- "cursor-move",
790
- "cursor-not-allowed",
791
- "select-none",
792
- "select-text",
793
- "select-all",
794
- "select-auto",
795
- "pointer-events-none",
796
- "pointer-events-auto",
797
- "whitespace-normal",
798
- "whitespace-nowrap",
799
- "whitespace-pre-wrap",
800
- "whitespace-pre-line",
801
- "whitespace-pre",
802
- "break-normal",
803
- "break-words",
804
- "break-all",
805
- "break-keep",
806
- "bg-clip-border",
807
- "bg-clip-padding",
808
- "bg-clip-content",
809
- "bg-clip-text",
810
- "bg-gradient-to",
811
- "resize-none",
812
- "resize-y",
813
- "resize-x",
814
- "box-border",
815
- "box-content",
816
- "gap-x",
817
- "gap-y",
818
- "inset-x",
819
- "inset-y",
820
- "divide-x",
821
- "divide-y",
822
- "space-x",
823
- "space-y",
824
- "translate-x",
825
- "translate-y",
826
- "scale-x",
827
- "scale-y",
828
- "skew-x",
829
- "skew-y",
830
- // Transform origin (single prefix, value carries direction)
831
- "origin",
832
- "min-w",
833
- "min-h",
834
- "max-w",
835
- "max-h",
836
- "ring-offset",
837
- "bg-opacity",
838
- "text-opacity",
839
- "border-opacity",
840
- // Grid placement
841
- "col-span",
842
- "col-start",
843
- "col-end",
844
- "row-span",
845
- "row-start",
846
- "row-end",
847
- "grid-cols",
848
- "grid-rows",
849
- "grid-flow",
850
- "auto-cols",
851
- "auto-rows",
852
- // Grid alignment
853
- "place-items",
854
- "place-content",
855
- "place-self",
856
- "justify-items",
857
- "justify-self",
858
- // Backdrop filters (longer than 'backdrop' alone)
859
- "backdrop-blur",
860
- "backdrop-brightness",
861
- "backdrop-contrast",
862
- "backdrop-grayscale",
863
- "backdrop-hue-rotate",
864
- "backdrop-invert",
865
- "backdrop-opacity",
866
- "backdrop-saturate",
867
- "backdrop-sepia",
868
- "backdrop-filter",
869
- // Filters
870
- "drop-shadow",
871
- "hue-rotate",
872
- "text-shadow",
873
- "underline-offset",
874
- "outline-offset",
875
- "will-change",
876
- "mix-blend",
877
- "bg-blend",
878
- "decoration",
879
- "perspective",
880
- "tint",
881
- "animate",
882
- // Single-word prefixes last
883
- "appearance-none",
884
- "outline-none",
885
- "outline",
886
- "inline-flex",
887
- "inline-block",
888
- "inline-grid",
889
- "italic",
890
- "non-italic",
891
- "underline",
892
- "overline",
893
- "line-through",
894
- "no-underline",
895
- "uppercase",
896
- "lowercase",
897
- "capitalize",
898
- "normal-case",
899
- "antialiased",
900
- "subpixel-antialiased",
901
- "overflow-ellipsis",
902
- "truncate",
903
- "sr-only",
904
- "not-sr-only",
905
- "relative",
906
- "absolute",
907
- "fixed",
908
- "sticky",
909
- "static",
910
- "visible",
911
- "invisible",
912
- "hidden",
913
- "contents",
914
- "flow-root",
915
- "block",
916
- "inline",
917
- "flex",
918
- "grid",
919
- "resize",
920
- "appearance",
921
- "border",
922
- "rounded",
923
- "shadow",
924
- "size",
925
- "opacity",
926
- "leading",
927
- "tracking",
928
- "line-clamp",
929
- "basis",
930
- "grow",
931
- "shrink",
932
- "order",
933
- "delay",
934
- "duration",
935
- "scale",
936
- "rotate",
937
- "aspect",
938
- "columns",
939
- "ring",
940
- "gap",
941
- "inset",
942
- "filter",
943
- "transform",
944
- "blur",
945
- "brightness",
946
- "contrast",
947
- "grayscale",
948
- "invert",
949
- "saturate",
950
- "sepia",
951
- "bg",
952
- "text",
953
- "font",
954
- "caret",
955
- "accent",
956
- "from",
957
- "via",
958
- "to",
959
- "divide",
960
- "space",
961
- "transition",
962
- "px",
963
- "py",
964
- "pt",
965
- "pr",
966
- "pb",
967
- "pl",
968
- "p",
969
- "mx",
970
- "my",
971
- "mt",
972
- "mr",
973
- "mb",
974
- "ml",
975
- "m",
976
- "w",
977
- "h",
978
- "top",
979
- "right",
980
- "bottom",
981
- "left",
982
- "z",
983
- "col",
984
- "row"
985
- ];
986
- var SORTED_PREFIXES = [...new Set(UTILITY_PREFIXES)].sort((a, b) => b.length - a.length);
987
- var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
988
- // Display
989
- "flex",
990
- "block",
991
- "inline-block",
992
- "inline",
993
- "grid",
994
- "inline-flex",
995
- "inline-grid",
996
- "grd",
997
- "hidden",
998
- "contents",
999
- "flow-root",
1000
- // Position
1001
- "relative",
1002
- "absolute",
1003
- "fixed",
1004
- "sticky",
1005
- "static",
1006
- // Visibility
1007
- "visible",
1008
- "invisible",
1009
- // Typography
1010
- "uppercase",
1011
- "lowercase",
1012
- "capitalize",
1013
- "normal-case",
1014
- "italic",
1015
- "non-italic",
1016
- "underline",
1017
- "overline",
1018
- "line-through",
1019
- "no-underline",
1020
- "truncate",
1021
- "antialiased",
1022
- "sr-only",
1023
- "not-sr-only",
1024
- // Font variant numeric
1025
- "normal-nums",
1026
- "ordinal",
1027
- "slashed-zero",
1028
- "lining-nums",
1029
- "oldstyle-nums",
1030
- "proportional-nums",
1031
- "tabular-nums",
1032
- "diagonal-fractions",
1033
- "stacked-fractions",
1034
- // Flexbox
1035
- "flex-row",
1036
- "flex-col",
1037
- "flex-row-reverse",
1038
- "flex-col-reverse",
1039
- "flex-wrap",
1040
- "flex-wrap-reverse",
1041
- "flex-nowrap",
1042
- "flex-shrink",
1043
- "flex-shrink-0",
1044
- "flex-grow",
1045
- "flex-grow-0",
1046
- "items-start",
1047
- "items-end",
1048
- "items-center",
1049
- "items-baseline",
1050
- "items-stretch",
1051
- "justify-start",
1052
- "justify-end",
1053
- "justify-center",
1054
- "justify-between",
1055
- "justify-around",
1056
- "justify-evenly",
1057
- "content-start",
1058
- "content-end",
1059
- "content-center",
1060
- "content-between",
1061
- "content-around",
1062
- "content-evenly",
1063
- "content-stretch",
1064
- "self-start",
1065
- "self-end",
1066
- "self-center",
1067
- "self-auto",
1068
- "self-stretch",
1069
- "self-baseline",
1070
- // Text align
1071
- "text-left",
1072
- "text-right",
1073
- "text-center",
1074
- "text-justify",
1075
- // Font weight shortcuts
1076
- "font-thin",
1077
- "font-extralight",
1078
- "font-light",
1079
- "font-normal",
1080
- "font-medium",
1081
- "font-semibold",
1082
- "font-bold",
1083
- "font-extrabold",
1084
- "font-black",
1085
- // Overflow
1086
- "overflow-hidden",
1087
- "overflow-visible",
1088
- "overflow-scroll",
1089
- "overflow-auto",
1090
- "overflow-x-hidden",
1091
- "overflow-x-scroll",
1092
- "overflow-x-auto",
1093
- "overflow-y-hidden",
1094
- "overflow-y-scroll",
1095
- "overflow-y-auto",
1096
- // Object fit
1097
- "object-contain",
1098
- "object-cover",
1099
- "object-fill",
1100
- "object-none",
1101
- "object-scale-down",
1102
- // Object position
1103
- "object-center",
1104
- "object-top",
1105
- "object-bottom",
1106
- "object-left",
1107
- "object-right",
1108
- "object-left-top",
1109
- "object-left-bottom",
1110
- "object-right-top",
1111
- "object-right-bottom",
1112
- // Border
1113
- "border-solid",
1114
- "border-dashed",
1115
- "border-dotted",
1116
- "border-none",
1117
- "border-t",
1118
- "border-r",
1119
- "border-b",
1120
- "border-l",
1121
- "border-collapse",
1122
- "border-separate",
1123
- // Lists
1124
- "list-none",
1125
- "list-disc",
1126
- "list-decimal",
1127
- "list-inside",
1128
- "list-outside",
1129
- // Cursor / select
1130
- "cursor-auto",
1131
- "cursor-default",
1132
- "cursor-pointer",
1133
- "cursor-wait",
1134
- "cursor-text",
1135
- "cursor-move",
1136
- "cursor-not-allowed",
1137
- "select-none",
1138
- "select-text",
1139
- "select-all",
1140
- "select-auto",
1141
- "pointer-events-none",
1142
- "pointer-events-auto",
1143
- // Whitespace / word break
1144
- "whitespace-normal",
1145
- "whitespace-nowrap",
1146
- "whitespace-pre",
1147
- "whitespace-pre-wrap",
1148
- "whitespace-pre-line",
1149
- "break-normal",
1150
- "break-words",
1151
- "break-all",
1152
- // Background clip
1153
- "bg-clip-border",
1154
- "bg-clip-padding",
1155
- "bg-clip-content",
1156
- "bg-clip-text",
1157
- // Background size
1158
- "bg-auto",
1159
- "bg-cover",
1160
- "bg-contain",
1161
- // Background position
1162
- "bg-center",
1163
- "bg-top",
1164
- "bg-bottom",
1165
- "bg-left",
1166
- "bg-right",
1167
- "bg-left-top",
1168
- "bg-left-bottom",
1169
- "bg-right-top",
1170
- "bg-right-bottom",
1171
- // Background repeat
1172
- "bg-repeat",
1173
- "bg-no-repeat",
1174
- "bg-repeat-x",
1175
- "bg-repeat-y",
1176
- "bg-repeat-round",
1177
- "bg-repeat-space",
1178
- // Background attachment
1179
- "bg-fixed",
1180
- "bg-local",
1181
- "bg-scroll",
1182
- // Background image
1183
- "bg-none",
1184
- // Box sizing
1185
- "box-border",
1186
- "box-content",
1187
- // Resize
1188
- "resize",
1189
- "resize-none",
1190
- "resize-y",
1191
- "resize-x",
1192
- // Outline
1193
- "appearance-none",
1194
- "outline-none",
1195
- "outline",
1196
- // Table
1197
- "table",
1198
- "table-auto",
1199
- "table-fixed",
1200
- "caption-top",
1201
- "caption-bottom",
1202
- // CSS filters (standalone = default/full effect)
1203
- "grayscale",
1204
- "invert",
1205
- "sepia",
1206
- // Isolation
1207
- "isolate",
1208
- "isolation-auto",
1209
- // Backface visibility (both platforms)
1210
- "backface-visible",
1211
- "backface-hidden",
1212
- // Divide none
1213
- "divide-none",
1214
- // Group / peer markers (no-op style; needed so isKnownUtility recognises them)
1215
- "group",
1216
- "peer",
1217
- // Text-wrap (web-only)
1218
- "text-wrap",
1219
- "text-nowrap",
1220
- "text-balance",
1221
- "text-pretty",
1222
- // Screen sizing
1223
- "w-screen",
1224
- "min-h-screen",
1225
- "max-h-screen",
1226
- "min-w-screen",
1227
- "max-w-screen",
1228
- // max-w named container sizes (Tailwind compat)
1229
- "max-w-none",
1230
- "max-w-xs",
1231
- "max-w-sm",
1232
- "max-w-md",
1233
- "max-w-lg",
1234
- "max-w-xl",
1235
- "max-w-2xl",
1236
- "max-w-3xl",
1237
- "max-w-4xl",
1238
- "max-w-5xl",
1239
- "max-w-6xl",
1240
- "max-w-7xl",
1241
- "max-w-prose",
1242
- // Extended cursors (web-only)
1243
- "cursor-grab",
1244
- "cursor-grabbing",
1245
- "cursor-zoom-in",
1246
- "cursor-zoom-out",
1247
- "cursor-crosshair",
1248
- "cursor-help",
1249
- "cursor-none",
1250
- // Overflow clip (web-only)
1251
- "overflow-clip",
1252
- "overflow-x-clip",
1253
- "overflow-y-clip",
1254
- // Scroll behavior (web-only)
1255
- "scroll-smooth",
1256
- "scroll-auto",
1257
- // Float & clear (web-only)
1258
- "float-left",
1259
- "float-right",
1260
- "float-start",
1261
- "float-end",
1262
- "float-none",
1263
- "clear-left",
1264
- "clear-right",
1265
- "clear-both",
1266
- "clear-start",
1267
- "clear-end",
1268
- "clear-none",
1269
- // Vertical align (web-only)
1270
- "align-baseline",
1271
- "align-top",
1272
- "align-middle",
1273
- "align-bottom",
1274
- "align-text-top",
1275
- "align-text-bottom",
1276
- "align-sub",
1277
- "align-super",
1278
- // Touch action (web-only)
1279
- "touch-auto",
1280
- "touch-none",
1281
- "touch-pan-x",
1282
- "touch-pan-y",
1283
- "touch-pan-left",
1284
- "touch-pan-right",
1285
- "touch-pan-up",
1286
- "touch-pan-down",
1287
- "touch-pinch-zoom",
1288
- "touch-manipulation"
1289
- ]);
1290
- function parseClass(className) {
1291
- const trimmed = className.trim();
1292
- if (!trimmed) return null;
1293
- const modifiers = [];
1294
- let remaining = trimmed;
1295
- for (let i = 0; i < 3; i++) {
1296
- const colonIdx = findOuterColon(remaining);
1297
- if (colonIdx === -1) break;
1298
- const candidate = remaining.slice(0, colonIdx);
1299
- if (MODIFIERS.has(candidate) || PLUGIN_MODIFIERS.has(candidate)) {
1300
- modifiers.push(candidate);
1301
- remaining = remaining.slice(colonIdx + 1);
1302
- } else {
1303
- break;
1304
- }
1305
- }
1306
- let important = false;
1307
- if (remaining.startsWith("!") && remaining.length > 1) {
1308
- important = true;
1309
- remaining = remaining.slice(1);
1310
- }
1311
- let negative = false;
1312
- if (remaining.startsWith("-") && remaining.length > 1 && remaining[1] !== "-") {
1313
- negative = true;
1314
- remaining = remaining.slice(1);
1315
- }
1316
- const bracketStart = remaining.lastIndexOf("-[");
1317
- if (bracketStart > 0 && remaining.endsWith("]")) {
1318
- const utility = remaining.slice(0, bracketStart);
1319
- const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
1320
- return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
1321
- }
1322
- if (STANDALONE_UTILITIES.has(remaining)) {
1323
- return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
1324
- }
1325
- for (const prefix of SORTED_PREFIXES) {
1326
- if (remaining === prefix) {
1327
- return { original: trimmed, modifiers, negative, important, utility: prefix, value: "", isArbitrary: false };
1328
- }
1329
- if (remaining.startsWith(prefix + "-")) {
1330
- const value = remaining.slice(prefix.length + 1);
1331
- return { original: trimmed, modifiers, negative, important, utility: prefix, value, isArbitrary: false };
1332
- }
1333
- }
1334
- const firstDash = remaining.indexOf("-");
1335
- if (firstDash > 0) {
1336
- return {
1337
- original: trimmed,
1338
- modifiers,
1339
- negative,
1340
- important,
1341
- utility: remaining.slice(0, firstDash),
1342
- value: remaining.slice(firstDash + 1),
1343
- isArbitrary: false
1344
- };
1345
- }
1346
- return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
713
+ for (const k of Object.keys(_pluginModifiers)) delete _pluginModifiers[k];
714
+ _invalidate();
1347
715
  }
1348
- function splitClassTokens(classString) {
1349
- const tokens = [];
1350
- let current = "";
1351
- let depth = 0;
1352
- for (let i = 0; i < classString.length; i++) {
1353
- const ch = classString[i];
1354
- if (ch === "[") {
1355
- depth++;
1356
- current += ch;
1357
- continue;
1358
- }
1359
- if (ch === "]") {
1360
- depth--;
1361
- current += ch;
1362
- continue;
1363
- }
1364
- if (/\s/.test(ch)) {
1365
- if (depth === 0) {
1366
- if (current) {
1367
- tokens.push(current);
1368
- current = "";
1369
- }
1370
- }
1371
- } else {
1372
- current += ch;
1373
- }
1374
- }
1375
- if (current) tokens.push(current);
1376
- return tokens;
716
+ function getModifier(name) {
717
+ return BUILTIN_MODIFIERS[name] ?? _pluginModifiers[name];
1377
718
  }
1378
- function normalizeClassString(classString) {
1379
- return splitClassTokens(classString).join(" ");
719
+ function isKnownModifier(name) {
720
+ return name in BUILTIN_MODIFIERS || name in _pluginModifiers;
1380
721
  }
1381
- function parseClasses(classString) {
1382
- const results = [];
1383
- for (const token of splitClassTokens(classString)) {
1384
- const parsed = parseClass(token);
1385
- if (parsed) results.push(parsed);
722
+ function _allEntries() {
723
+ return [...Object.entries(BUILTIN_MODIFIERS), ...Object.entries(_pluginModifiers)];
724
+ }
725
+ function getInteractiveModifiers() {
726
+ if (!_interactiveNames) {
727
+ _interactiveNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "interactive").map(([k]) => k));
1386
728
  }
1387
- return results;
729
+ return _interactiveNames;
1388
730
  }
1389
- function findOuterColon(s) {
1390
- let depth = 0;
1391
- for (let i = 0; i < s.length; i++) {
1392
- const ch = s[i];
1393
- if (ch === "[") depth++;
1394
- else if (ch === "]") depth--;
1395
- else if (ch === ":" && depth === 0) return i;
731
+ function getModeModifiers() {
732
+ if (!_modeNames) {
733
+ _modeNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "mode").map(([k]) => k));
1396
734
  }
1397
- return -1;
735
+ return _modeNames;
736
+ }
737
+ function getResponsiveModifiers() {
738
+ if (!_responsiveNames) {
739
+ _responsiveNames = new Set(_allEntries().filter(([, d]) => d.jsBehavior === "responsive").map(([k]) => k));
740
+ }
741
+ return _responsiveNames;
742
+ }
743
+ function matchModifier(name, isDark, state, breakpoints) {
744
+ return getModifier(name)?.jsMatch?.(isDark, state, breakpoints) ?? false;
1398
745
  }
1399
746
 
1400
747
  // src/core/utilities.ts
@@ -1488,6 +835,7 @@ function resolveSizing(value, spacing, isArbitrary) {
1488
835
  if (raw !== void 0) return raw;
1489
836
  if (/^\d+\/\d+$/.test(value)) {
1490
837
  const [num, den] = value.split("/").map(Number);
838
+ if (!den) return null;
1491
839
  return `${(num / den * 100).toFixed(6)}%`;
1492
840
  }
1493
841
  return null;
@@ -3002,10 +2350,10 @@ function resolveUtility(parsed, theme) {
3002
2350
  if (!parsed.value) {
3003
2351
  if (parsed.utility in PLUGIN_STANDALONE) return PLUGIN_STANDALONE[parsed.utility] ?? null;
3004
2352
  if (parsed.utility === "grd" || parsed.utility === "grid") {
3005
- return { display: "grid" };
2353
+ return getEffectiveIsWeb() ? { display: "grid" } : null;
3006
2354
  }
3007
2355
  if (parsed.utility === "inline-grid") {
3008
- return { display: "inline-grid" };
2356
+ return getEffectiveIsWeb() ? { display: "inline-grid" } : null;
3009
2357
  }
3010
2358
  if (parsed.utility in getStandalone()) return getStandalone()[parsed.utility] ?? null;
3011
2359
  }
@@ -3018,6 +2366,8 @@ var PLUGIN_RESOLVERS = {};
3018
2366
  function clearPluginUtilities() {
3019
2367
  for (const key of Object.keys(PLUGIN_STANDALONE)) delete PLUGIN_STANDALONE[key];
3020
2368
  for (const key of Object.keys(PLUGIN_RESOLVERS)) delete PLUGIN_RESOLVERS[key];
2369
+ _sortedPrefixes = null;
2370
+ _standaloneNames = null;
3021
2371
  }
3022
2372
  function getPluginStandaloneMap() {
3023
2373
  return PLUGIN_STANDALONE;
@@ -3025,6 +2375,129 @@ function getPluginStandaloneMap() {
3025
2375
  function isKnownUtility(utility) {
3026
2376
  return utility in getStandalone() || utility in RESOLVERS || utility in PLUGIN_STANDALONE || utility in PLUGIN_RESOLVERS;
3027
2377
  }
2378
+ var _sortedPrefixes = null;
2379
+ var _standaloneNames = null;
2380
+ function getBuiltinUtilityPrefixes() {
2381
+ if (!_sortedPrefixes) {
2382
+ const all = [.../* @__PURE__ */ new Set([...Object.keys(RESOLVERS), ...Object.keys(PLUGIN_RESOLVERS)])];
2383
+ _sortedPrefixes = all.sort((a, b) => b.length - a.length);
2384
+ }
2385
+ return _sortedPrefixes;
2386
+ }
2387
+ function getBuiltinStandaloneNames() {
2388
+ if (!_standaloneNames) {
2389
+ _standaloneNames = /* @__PURE__ */ new Set([...Object.keys(getStandalone()), ...Object.keys(PLUGIN_STANDALONE)]);
2390
+ }
2391
+ return _standaloneNames;
2392
+ }
2393
+
2394
+ // src/core/parser.ts
2395
+ function parseClass(className) {
2396
+ const trimmed = className.trim();
2397
+ if (!trimmed) return null;
2398
+ const modifiers = [];
2399
+ let remaining = trimmed;
2400
+ while (true) {
2401
+ const colonIdx = findOuterColon(remaining);
2402
+ if (colonIdx === -1) break;
2403
+ const candidate = remaining.slice(0, colonIdx);
2404
+ if (!isKnownModifier(candidate)) break;
2405
+ modifiers.push(candidate);
2406
+ remaining = remaining.slice(colonIdx + 1);
2407
+ }
2408
+ let important = false;
2409
+ if (remaining.startsWith("!") && remaining.length > 1) {
2410
+ important = true;
2411
+ remaining = remaining.slice(1);
2412
+ }
2413
+ let negative = false;
2414
+ if (remaining.startsWith("-") && remaining.length > 1 && remaining[1] !== "-") {
2415
+ negative = true;
2416
+ remaining = remaining.slice(1);
2417
+ }
2418
+ const bracketStart = remaining.lastIndexOf("-[");
2419
+ if (bracketStart > 0 && remaining.endsWith("]")) {
2420
+ const utility = remaining.slice(0, bracketStart);
2421
+ const value = remaining.slice(bracketStart + 2, -1).replace(/_/g, " ");
2422
+ return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
2423
+ }
2424
+ if (getBuiltinStandaloneNames().has(remaining)) {
2425
+ return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2426
+ }
2427
+ for (const prefix of getBuiltinUtilityPrefixes()) {
2428
+ if (remaining === prefix) {
2429
+ return { original: trimmed, modifiers, negative, important, utility: prefix, value: "", isArbitrary: false };
2430
+ }
2431
+ if (remaining.startsWith(prefix + "-")) {
2432
+ const value = remaining.slice(prefix.length + 1);
2433
+ return { original: trimmed, modifiers, negative, important, utility: prefix, value, isArbitrary: false };
2434
+ }
2435
+ }
2436
+ const firstDash = remaining.indexOf("-");
2437
+ if (firstDash > 0) {
2438
+ return {
2439
+ original: trimmed,
2440
+ modifiers,
2441
+ negative,
2442
+ important,
2443
+ utility: remaining.slice(0, firstDash),
2444
+ value: remaining.slice(firstDash + 1),
2445
+ isArbitrary: false
2446
+ };
2447
+ }
2448
+ return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
2449
+ }
2450
+ function splitClassTokens(classString) {
2451
+ const tokens = [];
2452
+ let current = "";
2453
+ let depth = 0;
2454
+ for (let i = 0; i < classString.length; i++) {
2455
+ const ch = classString[i];
2456
+ if (ch === "[") {
2457
+ depth++;
2458
+ current += ch;
2459
+ continue;
2460
+ }
2461
+ if (ch === "]") {
2462
+ depth--;
2463
+ current += ch;
2464
+ continue;
2465
+ }
2466
+ if (/\s/.test(ch)) {
2467
+ if (depth === 0) {
2468
+ if (current) {
2469
+ tokens.push(current);
2470
+ current = "";
2471
+ }
2472
+ }
2473
+ } else {
2474
+ current += ch;
2475
+ }
2476
+ }
2477
+ if (current) tokens.push(current);
2478
+ return tokens;
2479
+ }
2480
+ function normalizeClassString(classString) {
2481
+ return splitClassTokens(classString).join(" ");
2482
+ }
2483
+ function parseClasses(classString) {
2484
+ const results = [];
2485
+ for (const token of splitClassTokens(classString)) {
2486
+ const parsed = parseClass(token);
2487
+ if (parsed) results.push(parsed);
2488
+ }
2489
+ return results;
2490
+ }
2491
+ function findOuterColon(s) {
2492
+ let depth = 0;
2493
+ for (let i = 0; i < s.length; i++) {
2494
+ const ch = s[i];
2495
+ if (ch === "[") depth++;
2496
+ else if (ch === "]") depth--;
2497
+ else if (ch === ":" && depth === 0) return i;
2498
+ }
2499
+ return -1;
2500
+ }
3028
2501
 
3029
2502
  // src/core/responsiveStore.ts
3030
2503
  var RESPONSIVE_KEY = "__kbach_responsive__";
@@ -3057,7 +2530,30 @@ function getActiveBreakpoints(width) {
3057
2530
  }
3058
2531
 
3059
2532
  // src/core/resolver.ts
3060
- var styleCache = new LRUCache(1e4);
2533
+ var _themeCache = /* @__PURE__ */ new WeakMap();
2534
+ function getThemeCache(theme) {
2535
+ let cache = _themeCache.get(theme);
2536
+ if (!cache) {
2537
+ cache = new LRUCache(1e4);
2538
+ _themeCache.set(theme, cache);
2539
+ }
2540
+ return cache;
2541
+ }
2542
+ var _sortCache = /* @__PURE__ */ new WeakMap();
2543
+ function getSortedEntries(resolved) {
2544
+ let sorted = _sortCache.get(resolved);
2545
+ if (!sorted) {
2546
+ const entries = Object.entries(resolved);
2547
+ entries.sort((a, b) => {
2548
+ const pa = a[0] === "base" ? -1 : a[0].split(":").length;
2549
+ const pb = b[0] === "base" ? -1 : b[0].split(":").length;
2550
+ return pa - pb;
2551
+ });
2552
+ sorted = entries;
2553
+ _sortCache.set(resolved, sorted);
2554
+ }
2555
+ return sorted;
2556
+ }
3061
2557
  var FONT_KEY = "__kbach_default_font__";
3062
2558
  function setDefaultFontFamily(font) {
3063
2559
  globalThis[FONT_KEY] = font;
@@ -3066,7 +2562,7 @@ function getDefaultFontFamily() {
3066
2562
  return globalThis[FONT_KEY];
3067
2563
  }
3068
2564
  var _styleEl = null;
3069
- var _injectedRules = /* @__PURE__ */ new Set();
2565
+ var _injectedRules = new LRUCache(5e4);
3070
2566
  function getStyleEl() {
3071
2567
  if (_styleEl) return _styleEl;
3072
2568
  _styleEl = document.createElement("style");
@@ -3076,7 +2572,7 @@ function getStyleEl() {
3076
2572
  }
3077
2573
  function injectRule(rule) {
3078
2574
  if (_injectedRules.has(rule)) return;
3079
- _injectedRules.add(rule);
2575
+ _injectedRules.set(rule, true);
3080
2576
  try {
3081
2577
  getStyleEl().sheet?.insertRule(rule, getStyleEl().sheet.cssRules.length);
3082
2578
  } catch {
@@ -3100,150 +2596,20 @@ function injectGlobalStyles(theme) {
3100
2596
  }
3101
2597
  getGlobalStyleEl().textContent = rules.join("\n");
3102
2598
  }
3103
- var MODIFIER_TO_PSEUDO = {
3104
- hover: ":hover",
3105
- focus: ":focus",
3106
- "focus-within": ":focus-within",
3107
- "focus-visible": ":focus-visible",
3108
- active: ":active",
3109
- pressed: ":active",
3110
- disabled: ":disabled",
3111
- checked: ":checked",
3112
- visited: ":visited",
3113
- placeholder: "::placeholder",
3114
- first: ":first-child",
3115
- last: ":last-child",
3116
- odd: ":nth-child(odd)",
3117
- even: ":nth-child(even)",
3118
- only: ":only-child",
3119
- "not-hover": ":not(:hover)",
3120
- "not-focus": ":not(:focus)",
3121
- "not-active": ":not(:active)",
3122
- "not-pressed": ":not(:active)",
3123
- "not-disabled": ":not(:disabled)",
3124
- "not-checked": ":not(:checked)",
3125
- "not-visited": ":not(:visited)",
3126
- // Pseudo-elements (CSS-injection only; never applied as inline styles)
3127
- before: "::before",
3128
- after: "::after",
3129
- selection: "::selection",
3130
- "first-letter": "::first-letter",
3131
- "first-line": "::first-line",
3132
- marker: "::marker"
3133
- };
3134
- var GROUP_PEER_PREFIX = {
3135
- "group-hover": ".group:hover",
3136
- "group-focus": ".group:focus",
3137
- "peer-hover": ".peer:hover ~",
3138
- "peer-focus": ".peer:focus ~"
3139
- };
3140
- var MODE_MODS = /* @__PURE__ */ new Set(["dark", "light", "not-dark", "not-light"]);
3141
- var RESPONSIVE_MODS = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
3142
- var PRINT_MODS = /* @__PURE__ */ new Set(["print"]);
3143
- var MEDIA_MODS = {
3144
- landscape: "(orientation: landscape)",
3145
- portrait: "(orientation: portrait)",
3146
- "motion-reduce": "(prefers-reduced-motion: reduce)",
3147
- "motion-safe": "(prefers-reduced-motion: no-preference)",
3148
- "contrast-more": "(prefers-contrast: more)",
3149
- "contrast-less": "(prefers-contrast: less)"
3150
- };
3151
- var DIR_MODS = {
3152
- rtl: '[dir="rtl"]',
3153
- ltr: '[dir="ltr"]'
3154
- };
3155
2599
  function buildDivideDecls(styles) {
3156
2600
  const parts = [];
3157
2601
  if ("__divideX" in styles) {
3158
2602
  const w = Number(styles.__divideX);
3159
- parts.push(`border-left-width: ${w}px`);
3160
- parts.push("border-right-width: 0px");
2603
+ parts.push(`border-left-width: ${w}px`, "border-right-width: 0px");
3161
2604
  }
3162
2605
  if ("__divideY" in styles) {
3163
2606
  const w = Number(styles.__divideY);
3164
- parts.push(`border-top-width: ${w}px`);
3165
- parts.push("border-bottom-width: 0px");
2607
+ parts.push(`border-top-width: ${w}px`, "border-bottom-width: 0px");
3166
2608
  }
3167
2609
  if ("__divideColor" in styles) parts.push(`border-color: ${String(styles.__divideColor)}`);
3168
2610
  if ("__divideStyle" in styles) parts.push(`border-style: ${String(styles.__divideStyle)}`);
3169
2611
  return parts.join("; ");
3170
2612
  }
3171
- function buildClassCSSRules(cls, bucketKey, styles, darkMode, important, screens) {
3172
- const rules = [];
3173
- if ("__keyframe" in styles && typeof styles.__keyframe === "string") {
3174
- rules.push(styles.__keyframe);
3175
- }
3176
- const isDivide = "__divideX" in styles || "__divideY" in styles || "__divideColor" in styles || "__divideStyle" in styles;
3177
- const escaped = escapeCSSSelector(cls);
3178
- const childSuffix = isDivide ? " > * + *" : "";
3179
- if (bucketKey === "base") {
3180
- const baseCssDecls = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, important);
3181
- if (!baseCssDecls) return rules;
3182
- rules.push(`.${escaped}${childSuffix} { ${baseCssDecls} }`);
3183
- return rules;
3184
- }
3185
- const mods = bucketKey.split(":");
3186
- const responsiveMods = mods.filter((m) => RESPONSIVE_MODS.has(m));
3187
- const nonResponsiveMods = mods.filter((m) => !RESPONSIVE_MODS.has(m));
3188
- const hasDark = nonResponsiveMods.includes("dark") || nonResponsiveMods.includes("not-light");
3189
- const hasLight = nonResponsiveMods.includes("light") || nonResponsiveMods.includes("not-dark");
3190
- const hasPrint = nonResponsiveMods.includes("print");
3191
- const mediaMods = nonResponsiveMods.filter((m) => m in MEDIA_MODS);
3192
- const dirMods = nonResponsiveMods.filter((m) => m in DIR_MODS);
3193
- const ancestorMods = nonResponsiveMods.filter((m) => m in GROUP_PEER_PREFIX);
3194
- const pseudoMods = nonResponsiveMods.filter(
3195
- (m) => !MODE_MODS.has(m) && !(m in GROUP_PEER_PREFIX) && !PRINT_MODS.has(m) && !(m in MEDIA_MODS) && !(m in DIR_MODS)
3196
- );
3197
- const pseudoSuffix = pseudoMods.map((p) => MODIFIER_TO_PSEUDO[p] ?? `:${p}`).join("");
3198
- const elementSelector = `.${escaped}${pseudoSuffix}${childSuffix}`;
3199
- const ancestorPrefix = ancestorMods.length ? ancestorMods.map((m) => GROUP_PEER_PREFIX[m]).join(" ") + " " : "";
3200
- const dirPrefix = dirMods.length ? dirMods.map((m) => DIR_MODS[m]).join(" ") + " " : "";
3201
- const selector = `${dirPrefix}${ancestorPrefix}${elementSelector}`;
3202
- const CSS_ONLY_PSEUDOS = /* @__PURE__ */ new Set([
3203
- "first",
3204
- "last",
3205
- "odd",
3206
- "even",
3207
- "only",
3208
- "focus-within",
3209
- "focus-visible"
3210
- ]);
3211
- const needsImportant = important || hasPrint || mediaMods.length > 0 || dirMods.length > 0 || ancestorMods.length > 0 || pseudoMods.some((m) => CSS_ONLY_PSEUDOS.has(m));
3212
- const cssDecls = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, needsImportant);
3213
- if (!cssDecls) return rules;
3214
- let rule;
3215
- if (hasDark) {
3216
- if (darkMode === "media") {
3217
- rule = `@media (prefers-color-scheme: dark) { ${selector} { ${cssDecls} } }`;
3218
- } else if (darkMode === "class") {
3219
- rule = `.dark ${selector} { ${cssDecls} }`;
3220
- } else {
3221
- rule = `[data-theme="dark"] ${selector} { ${cssDecls} }`;
3222
- }
3223
- } else if (hasLight) {
3224
- if (darkMode === "media") {
3225
- rule = `@media (prefers-color-scheme: light) { ${selector} { ${cssDecls} } }`;
3226
- } else if (darkMode === "class") {
3227
- rule = `:not(.dark) ${selector} { ${cssDecls} }`;
3228
- } else {
3229
- rule = `[data-theme="light"] ${selector} { ${cssDecls} }`;
3230
- }
3231
- } else {
3232
- rule = `${selector} { ${cssDecls} }`;
3233
- }
3234
- if (hasPrint) rule = `@media print { ${rule} }`;
3235
- for (const m of mediaMods) rule = `@media ${MEDIA_MODS[m]} { ${rule} }`;
3236
- if (responsiveMods.length > 0) {
3237
- const minWidth = Math.max(...responsiveMods.map((m) => screens[m] ?? 0));
3238
- if (minWidth > 0) rule = `@media (min-width: ${minWidth}px) { ${rule} }`;
3239
- }
3240
- rules.push(rule);
3241
- return rules;
3242
- }
3243
- function injectClassRule(cls, bucketKey, styles, darkMode, important = false) {
3244
- const cssRules = buildClassCSSRules(cls, bucketKey, styles, darkMode, important, getGlobalScreens());
3245
- for (const r of cssRules) injectRule(r);
3246
- }
3247
2613
  var RN_ONLY_PROPS = /* @__PURE__ */ new Set([
3248
2614
  "shadowColor",
3249
2615
  "shadowOffset",
@@ -3253,13 +2619,10 @@ var RN_ONLY_PROPS = /* @__PURE__ */ new Set([
3253
2619
  "includeFontPadding",
3254
2620
  "textAlignVertical",
3255
2621
  "writingDirection",
3256
- // Text shadow native props — web uses the textShadow CSS shorthand instead
3257
2622
  "textShadowColor",
3258
2623
  "textShadowOffset",
3259
2624
  "textShadowRadius",
3260
- // tintColor is native-only (Image/icon tinting)
3261
2625
  "tintColor",
3262
- // Internal markers — handled specially, never serialized as CSS props
3263
2626
  "__divideX",
3264
2627
  "__divideY",
3265
2628
  "__divideColor",
@@ -3301,8 +2664,7 @@ function styleValueToCSS(styles, forceImportant = false) {
3301
2664
  const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3302
2665
  if (prop in RN_SHORTHAND_EXPAND) {
3303
2666
  const [p1, p2] = RN_SHORTHAND_EXPAND[prop];
3304
- parts.push(`${p1}: ${cssVal}${imp}`);
3305
- parts.push(`${p2}: ${cssVal}${imp}`);
2667
+ parts.push(`${p1}: ${cssVal}${imp}`, `${p2}: ${cssVal}${imp}`);
3306
2668
  continue;
3307
2669
  }
3308
2670
  parts.push(`${camelToKebab(prop)}: ${cssVal}${imp}`);
@@ -3312,14 +2674,87 @@ function styleValueToCSS(styles, forceImportant = false) {
3312
2674
  function camelToKebab(str) {
3313
2675
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
3314
2676
  }
2677
+ function buildClassCSSRules(cls, bucketKey, styles, darkMode, important, screens) {
2678
+ const rules = [];
2679
+ if ("__keyframe" in styles && typeof styles.__keyframe === "string") {
2680
+ rules.push(styles.__keyframe);
2681
+ }
2682
+ const isDivide = "__divideX" in styles || "__divideY" in styles || "__divideColor" in styles || "__divideStyle" in styles;
2683
+ const escaped = escapeCSSSelector(cls);
2684
+ const childSuffix = isDivide ? " > * + *" : "";
2685
+ if (bucketKey === "base") {
2686
+ const decls2 = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, important);
2687
+ if (!decls2) return rules;
2688
+ rules.push(`.${escaped}${childSuffix} { ${decls2} }`);
2689
+ return rules;
2690
+ }
2691
+ const mods = bucketKey.split(":");
2692
+ let darkScheme;
2693
+ let needsImportant = important;
2694
+ const pseudoParts = [];
2695
+ const ancestorParts = [];
2696
+ const dirParts = [];
2697
+ const mediaWrappers = [];
2698
+ let minWidth = 0;
2699
+ for (const mod of mods) {
2700
+ const def = getModifier(mod);
2701
+ if (!def) continue;
2702
+ if (def.darkScheme) darkScheme = def.darkScheme;
2703
+ if (def.pseudo) pseudoParts.push(def.pseudo);
2704
+ if (def.ancestorSelector) {
2705
+ ancestorParts.push(def.ancestorSelector);
2706
+ needsImportant = true;
2707
+ }
2708
+ if (def.dirSelector) {
2709
+ dirParts.push(def.dirSelector);
2710
+ needsImportant = true;
2711
+ }
2712
+ if (def.mediaQuery) {
2713
+ mediaWrappers.push(`@media ${def.mediaQuery}`);
2714
+ needsImportant = true;
2715
+ }
2716
+ if (def.isResponsive) {
2717
+ const w = screens[mod] ?? 0;
2718
+ if (w > minWidth) minWidth = w;
2719
+ }
2720
+ if (def.forcesImportant) needsImportant = true;
2721
+ }
2722
+ const pseudoSuffix = pseudoParts.join("");
2723
+ const elementSelector = `.${escaped}${pseudoSuffix}${childSuffix}`;
2724
+ const ancestorPrefix = ancestorParts.join("");
2725
+ const dirPrefix = dirParts.join("");
2726
+ const selector = `${dirPrefix}${ancestorPrefix}${elementSelector}`;
2727
+ const decls = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, needsImportant);
2728
+ if (!decls) return rules;
2729
+ let rule;
2730
+ if (darkScheme === "dark") {
2731
+ if (darkMode === "media") rule = `@media (prefers-color-scheme: dark) { ${selector} { ${decls} } }`;
2732
+ else if (darkMode === "class") rule = `.dark ${selector} { ${decls} }`;
2733
+ else rule = `[data-theme="dark"] ${selector} { ${decls} }`;
2734
+ } else if (darkScheme === "light") {
2735
+ if (darkMode === "media") rule = `@media (prefers-color-scheme: light) { ${selector} { ${decls} } }`;
2736
+ else if (darkMode === "class") rule = `:not(.dark) ${selector} { ${decls} }`;
2737
+ else rule = `[data-theme="light"] ${selector} { ${decls} }`;
2738
+ } else {
2739
+ rule = `${selector} { ${decls} }`;
2740
+ }
2741
+ for (const mw of mediaWrappers) rule = `${mw} { ${rule} }`;
2742
+ if (minWidth > 0) rule = `@media (min-width: ${minWidth}px) { ${rule} }`;
2743
+ rules.push(rule);
2744
+ return rules;
2745
+ }
2746
+ function injectClassRule(cls, bucketKey, styles, darkMode, important) {
2747
+ const cssRules = buildClassCSSRules(cls, bucketKey, styles, darkMode, important, getGlobalScreens());
2748
+ for (const r of cssRules) injectRule(r);
2749
+ }
3315
2750
  function resolve(classString, theme, darkMode = "attribute") {
2751
+ const cache = getThemeCache(theme);
3316
2752
  const cacheKey = `${classString}::${darkMode}`;
3317
- const cached = styleCache.get(cacheKey);
2753
+ const cached = cache.get(cacheKey);
3318
2754
  if (cached) return cached;
3319
2755
  const result = {};
3320
- const parsedClasses = parseClasses(classString);
3321
- const injectQueue = [];
3322
- for (const parsed of parsedClasses) {
2756
+ const onWeb = typeof document !== "undefined";
2757
+ for (const parsed of parseClasses(classString)) {
3323
2758
  const styles = resolveUtility(parsed, theme);
3324
2759
  if (!styles) {
3325
2760
  if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility)) {
@@ -3330,114 +2765,59 @@ function resolve(classString, theme, darkMode = "attribute") {
3330
2765
  const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
3331
2766
  if (!result[bucketKey]) result[bucketKey] = {};
3332
2767
  Object.assign(result[bucketKey], styles);
3333
- if (typeof document !== "undefined") {
3334
- injectQueue.push({ cls: parsed.original, bucketKey, styles, important: parsed.important });
3335
- }
3336
- }
3337
- styleCache.set(cacheKey, result);
3338
- if (typeof document !== "undefined") {
3339
- for (const { cls, bucketKey, styles, important } of injectQueue) {
3340
- injectClassRule(cls, bucketKey, styles, darkMode, important);
2768
+ if (onWeb) {
2769
+ injectClassRule(parsed.original, bucketKey, styles, darkMode, parsed.important);
3341
2770
  }
3342
2771
  }
2772
+ cache.set(cacheKey, result);
3343
2773
  return result;
3344
2774
  }
3345
2775
  function flatten(resolved, isDark, state = {}, breakpoints = /* @__PURE__ */ new Set()) {
3346
2776
  const result = {};
3347
- const entries = Object.entries(resolved);
3348
- entries.sort((a, b) => {
3349
- const pa = a[0] === "base" ? -1 : a[0].split(":").length;
3350
- const pb = b[0] === "base" ? -1 : b[0].split(":").length;
3351
- return pa - pb;
3352
- });
3353
- for (const [key, styles] of entries) {
2777
+ for (const [key, styles] of getSortedEntries(resolved)) {
3354
2778
  if (!styles) continue;
3355
2779
  if (key === "base") {
3356
2780
  Object.assign(result, styles);
3357
2781
  continue;
3358
2782
  }
3359
2783
  const mods = key.split(":");
3360
- if (matchesMods(mods, isDark, state, breakpoints)) {
2784
+ if (mods.every((mod) => matchModifier(mod, isDark, state, breakpoints))) {
3361
2785
  Object.assign(result, styles);
3362
2786
  }
3363
2787
  }
3364
- const _df = getDefaultFontFamily();
3365
- if (_df && !("fontFamily" in result)) {
3366
- result.fontFamily = _df;
2788
+ const defaultFont = getDefaultFontFamily();
2789
+ if (defaultFont && !("fontFamily" in result)) {
2790
+ result.fontFamily = defaultFont;
3367
2791
  }
3368
2792
  if (isWeb) {
3369
2793
  const r = result;
3370
- for (const [rnProp, [p1, p2]] of Object.entries(RN_SHORTHAND_EXPAND)) {
3371
- const v = r[rnProp];
3372
- if (v !== void 0) {
3373
- r[p1] = v;
3374
- r[p2] = v;
3375
- delete r[rnProp];
3376
- }
2794
+ const ph = r.paddingHorizontal;
2795
+ if (ph !== void 0) {
2796
+ r.paddingLeft = ph;
2797
+ r.paddingRight = ph;
2798
+ delete r.paddingHorizontal;
2799
+ }
2800
+ const pv = r.paddingVertical;
2801
+ if (pv !== void 0) {
2802
+ r.paddingTop = pv;
2803
+ r.paddingBottom = pv;
2804
+ delete r.paddingVertical;
2805
+ }
2806
+ const mh = r.marginHorizontal;
2807
+ if (mh !== void 0) {
2808
+ r.marginLeft = mh;
2809
+ r.marginRight = mh;
2810
+ delete r.marginHorizontal;
2811
+ }
2812
+ const mv = r.marginVertical;
2813
+ if (mv !== void 0) {
2814
+ r.marginTop = mv;
2815
+ r.marginBottom = mv;
2816
+ delete r.marginVertical;
3377
2817
  }
3378
2818
  }
3379
2819
  return result;
3380
2820
  }
3381
- function matchesMods(mods, isDark, state, breakpoints) {
3382
- return mods.every((mod) => {
3383
- switch (mod) {
3384
- case "dark":
3385
- return isDark;
3386
- case "light":
3387
- case "not-dark":
3388
- return !isDark;
3389
- case "not-light":
3390
- return isDark;
3391
- case "hover":
3392
- return !!state.hover;
3393
- case "not-hover":
3394
- return !state.hover;
3395
- case "focus":
3396
- return !!state.focus;
3397
- case "not-focus":
3398
- return !state.focus;
3399
- case "pressed":
3400
- case "active":
3401
- return !!state.pressed || !!state.active;
3402
- case "not-pressed":
3403
- case "not-active":
3404
- return !state.pressed && !state.active;
3405
- case "disabled":
3406
- return !!state.disabled;
3407
- case "not-disabled":
3408
- return !state.disabled;
3409
- case "checked":
3410
- return !!state.checked;
3411
- case "not-checked":
3412
- return !state.checked;
3413
- case "visited":
3414
- return !!state.visited;
3415
- case "not-visited":
3416
- return !state.visited;
3417
- case "placeholder":
3418
- return !!state.placeholder;
3419
- case "sm":
3420
- case "md":
3421
- case "lg":
3422
- case "xl":
3423
- case "2xl":
3424
- return breakpoints.has(mod);
3425
- // CSS-only modifiers — never applied as inline styles
3426
- case "print":
3427
- case "landscape":
3428
- case "portrait":
3429
- case "motion-reduce":
3430
- case "motion-safe":
3431
- case "contrast-more":
3432
- case "contrast-less":
3433
- case "rtl":
3434
- case "ltr":
3435
- return false;
3436
- default:
3437
- return false;
3438
- }
3439
- });
3440
- }
3441
2821
 
3442
2822
  // src/core/config.ts
3443
2823
  function deepMerge(base, override) {
@@ -3478,14 +2858,24 @@ function resolveOneRef(ref, colors) {
3478
2858
  return entry[m[2]] ?? null;
3479
2859
  }
3480
2860
  function resolveColorRefs(colors) {
2861
+ const MAX_DEPTH = 5;
2862
+ function resolveChain(raw) {
2863
+ let current = raw;
2864
+ for (let i = 0; i < MAX_DEPTH; i++) {
2865
+ const next = resolveOneRef(current, colors);
2866
+ if (!next || next === current) break;
2867
+ current = next;
2868
+ }
2869
+ return current;
2870
+ }
3481
2871
  const out = {};
3482
2872
  for (const [key, val] of Object.entries(colors)) {
3483
2873
  if (typeof val === "string") {
3484
- out[key] = resolveOneRef(val, colors) ?? val;
2874
+ out[key] = resolveChain(val);
3485
2875
  } else {
3486
2876
  const shades = {};
3487
2877
  for (const [shade, hex] of Object.entries(val)) {
3488
- shades[shade] = resolveOneRef(hex, colors) ?? hex;
2878
+ shades[shade] = resolveChain(hex);
3489
2879
  }
3490
2880
  out[key] = shades;
3491
2881
  }
@@ -3533,15 +2923,26 @@ function buildConfig(userConfig) {
3533
2923
  injectGlobalStyles(resolved.theme);
3534
2924
  return resolved;
3535
2925
  }
2926
+ function _selectorToModifierDef(selector) {
2927
+ const s = selector.trim();
2928
+ if (s.startsWith("@media ")) {
2929
+ return { mediaQuery: s.slice(7), jsBehavior: "css-only", forcesImportant: true };
2930
+ }
2931
+ if (s.startsWith("::") || s.startsWith(":")) {
2932
+ return { pseudo: s, jsBehavior: "css-only", forcesImportant: true };
2933
+ }
2934
+ return { ancestorSelector: s.endsWith(" ") ? s : `${s} `, jsBehavior: "css-only", forcesImportant: true };
2935
+ }
3536
2936
  function makePluginAPI(theme) {
3537
2937
  const standalone = getPluginStandaloneMap();
3538
2938
  return {
3539
2939
  addUtility(name, styles) {
3540
2940
  standalone[name] = styles;
3541
2941
  },
3542
- addVariant(name, selector) {
3543
- customVariants[name] = selector;
3544
- registerModifier(name);
2942
+ addVariant(name, selectorOrDef) {
2943
+ const def = typeof selectorOrDef === "string" ? _selectorToModifierDef(selectorOrDef) : selectorOrDef;
2944
+ customVariants[name] = typeof selectorOrDef === "string" ? selectorOrDef : name;
2945
+ registerModifier(name, def);
3545
2946
  },
3546
2947
  theme(path, defaultValue) {
3547
2948
  const parts = path.replace(/\[([^\]]+)\]/g, ".$1").split(".");
@@ -3662,23 +3063,26 @@ function useConditionalWidth(active) {
3662
3063
  );
3663
3064
  }
3664
3065
 
3665
- // src/InteractiveWrapper.tsx
3666
- function chain(original, extra) {
3667
- return (...args) => {
3668
- original?.(...args);
3669
- extra();
3670
- };
3671
- }
3672
- var RESPONSIVE_MODS2 = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
3066
+ // src/shared-utils.ts
3673
3067
  function hasResponsiveBuckets(resolved) {
3068
+ const responsiveMods = getResponsiveModifiers();
3674
3069
  for (const key of Object.keys(resolved)) {
3675
3070
  if (key === "base") continue;
3676
3071
  for (const mod of key.split(":")) {
3677
- if (RESPONSIVE_MODS2.has(mod)) return true;
3072
+ if (responsiveMods.has(mod)) return true;
3678
3073
  }
3679
3074
  }
3680
3075
  return false;
3681
3076
  }
3077
+ var EMPTY_BREAKPOINTS2 = /* @__PURE__ */ new Set();
3078
+
3079
+ // src/InteractiveWrapper.tsx
3080
+ function chain(original, extra) {
3081
+ return (...args) => {
3082
+ original?.(...args);
3083
+ extra();
3084
+ };
3085
+ }
3682
3086
  var InteractiveWrapper = (0, import_react3.forwardRef)(
3683
3087
  function InteractiveWrapper2({
3684
3088
  Component,
@@ -3770,22 +3174,12 @@ InteractiveWrapper.displayName = "Kbach.InteractiveWrapper";
3770
3174
 
3771
3175
  // src/DarkWrapper.tsx
3772
3176
  var import_react4 = __toESM(require("react"));
3773
- var RESPONSIVE_MODS3 = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
3774
- function hasResponsiveBuckets2(resolved) {
3775
- for (const key of Object.keys(resolved)) {
3776
- if (key === "base") continue;
3777
- for (const mod of key.split(":")) {
3778
- if (RESPONSIVE_MODS3.has(mod)) return true;
3779
- }
3780
- }
3781
- return false;
3782
- }
3783
3177
  var DarkWrapper = import_react4.default.forwardRef(
3784
3178
  function DarkWrapper2({ Component, resolvedStyle, style: styleProp, children, ...rest }, ref) {
3785
3179
  const isDark = useGlobalDarkMode();
3786
- const needsWidth = hasResponsiveBuckets2(resolvedStyle);
3180
+ const needsWidth = hasResponsiveBuckets(resolvedStyle);
3787
3181
  const width = useConditionalWidth(needsWidth);
3788
- const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS;
3182
+ const breakpoints = needsWidth ? getActiveBreakpoints(width) : EMPTY_BREAKPOINTS2;
3789
3183
  const computedStyle = flatten(resolvedStyle, isDark, {}, breakpoints);
3790
3184
  stripInternalMarkers(computedStyle);
3791
3185
  if (typeof Component !== "string") stripWebOnlyProps(computedStyle);
@@ -3827,51 +3221,36 @@ function stripWebOnlyProps(s) {
3827
3221
  }
3828
3222
 
3829
3223
  // src/jsx-runtime.tsx
3830
- var INTERACTIVE_MODS = /* @__PURE__ */ new Set([
3831
- "hover",
3832
- "not-hover",
3833
- "focus",
3834
- "not-focus",
3835
- "active",
3836
- "not-active",
3837
- "pressed",
3838
- "not-pressed",
3839
- "disabled",
3840
- "not-disabled",
3841
- "checked",
3842
- "not-checked",
3843
- "visited",
3844
- "not-visited",
3845
- "placeholder",
3846
- "group-hover",
3847
- "group-focus",
3848
- "peer-hover",
3849
- "peer-focus"
3850
- // focus-within / focus-visible / first / last / odd / even / only are CSS-only —
3851
- // they have no JS state to track, so they don't need InteractiveWrapper.
3852
- ]);
3853
- var RESPONSIVE_MODS4 = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
3854
- var MODE_MODS_JSX = /* @__PURE__ */ new Set(["dark", "light", "not-dark", "not-light"]);
3224
+ var _cachedDefaultFont = void 0;
3225
+ var _defaultFontVersion = 0;
3226
+ var _lastFontVersion = -1;
3227
+ function getCachedDefaultFont() {
3228
+ if (_lastFontVersion !== _defaultFontVersion) {
3229
+ _cachedDefaultFont = getDefaultFontFamily();
3230
+ _lastFontVersion = _defaultFontVersion;
3231
+ }
3232
+ return _cachedDefaultFont;
3233
+ }
3234
+ var _bucketModsCache = /* @__PURE__ */ new WeakMap();
3855
3235
  function bucketMods(resolved) {
3236
+ const cached = _bucketModsCache.get(resolved);
3237
+ if (cached) return cached;
3238
+ const interactiveMods = getInteractiveModifiers();
3239
+ const modeMods = getModeModifiers();
3240
+ const responsiveMods = getResponsiveModifiers();
3856
3241
  let interactive = false;
3857
3242
  let modeOrResponsive = false;
3858
3243
  for (const key of Object.keys(resolved)) {
3859
3244
  if (key === "base") continue;
3860
- const parts = key.split(":");
3861
- for (const mod of parts) {
3862
- if (INTERACTIVE_MODS.has(mod)) {
3863
- interactive = true;
3864
- break;
3865
- }
3866
- }
3867
- for (const mod of parts) {
3868
- if (MODE_MODS_JSX.has(mod) || RESPONSIVE_MODS4.has(mod)) {
3869
- modeOrResponsive = true;
3870
- break;
3871
- }
3245
+ for (const mod of key.split(":")) {
3246
+ if (!interactive && interactiveMods.has(mod)) interactive = true;
3247
+ if (!modeOrResponsive && (modeMods.has(mod) || responsiveMods.has(mod))) modeOrResponsive = true;
3872
3248
  }
3249
+ if (interactive && modeOrResponsive) break;
3873
3250
  }
3874
- return { interactive, modeOrResponsive };
3251
+ const result = { interactive, modeOrResponsive };
3252
+ _bucketModsCache.set(resolved, result);
3253
+ return result;
3875
3254
  }
3876
3255
  var CONSUMED_PROPS = /* @__PURE__ */ new Set(["className", "kb", "__kbachStyles", "__kbachClasses"]);
3877
3256
  function omitConsumed(props) {
@@ -3946,10 +3325,8 @@ function processElement(type, rawProps, key, isStaticChildren) {
3946
3325
  const { className, kb: kbProp, __kbachStyles, __kbachClasses } = rawProps;
3947
3326
  const classStr = className ?? kbProp ?? __kbachClasses;
3948
3327
  if (!classStr && !__kbachStyles) {
3949
- const defaultFont = getDefaultFontFamily();
3950
- if (!defaultFont) {
3951
- return makeElement(isStaticChildren, type, rawProps, key);
3952
- }
3328
+ const defaultFont = getCachedDefaultFont();
3329
+ if (!defaultFont) return makeElement(isStaticChildren, type, rawProps, key);
3953
3330
  const { style: userStyle2, ...passProps2 } = omitConsumed(rawProps);
3954
3331
  const finalStyle2 = userStyle2 ? Array.isArray(userStyle2) ? { fontFamily: defaultFont, ...Object.assign({}, ...userStyle2) } : { fontFamily: defaultFont, ...userStyle2 } : { fontFamily: defaultFont };
3955
3332
  return makeElement(isStaticChildren, type, { ...passProps2, style: finalStyle2 }, key);
@@ -3997,8 +3374,13 @@ function jsxs(type, props, key) {
3997
3374
  }
3998
3375
 
3999
3376
  // src/jsx-dev-runtime.tsx
4000
- function jsxDEV(type, props, key, isStaticChildren, _source, _self) {
4001
- return (isStaticChildren ? jsxs : jsx)(type, props, key);
3377
+ function jsxDEV(type, props, key, isStaticChildren, source, self) {
3378
+ const element = (isStaticChildren ? jsxs : jsx)(type, props, key);
3379
+ if (source && element && typeof element === "object" && "_source" in Object.getPrototypeOf(element ?? {})) {
3380
+ element._source = source;
3381
+ element._self = self;
3382
+ }
3383
+ return element;
4002
3384
  }
4003
3385
  // Annotate the CommonJS export names for ESM import in node:
4004
3386
  0 && (module.exports = {