@kbach/react 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -581,10 +581,19 @@ var MODIFIERS = /* @__PURE__ */ new Set([
581
581
  "md",
582
582
  "lg",
583
583
  "xl",
584
- "2xl"
584
+ "2xl",
585
+ // Pseudo-elements (CSS-injection only; matchesMods returns false for these)
586
+ "before",
587
+ "after",
588
+ "selection",
589
+ "first-letter",
590
+ "first-line",
591
+ "marker",
592
+ // Print media modifier
593
+ "print"
585
594
  ]);
586
595
  var UTILITY_PREFIXES = [
587
- // Multi-word order matters
596
+ // Multi-word flex
588
597
  "flex-row-reverse",
589
598
  "flex-col-reverse",
590
599
  "flex-row",
@@ -662,7 +671,6 @@ var UTILITY_PREFIXES = [
662
671
  "rounded-r",
663
672
  "rounded-b",
664
673
  "rounded-l",
665
- "text-decoration-none",
666
674
  "list-none",
667
675
  "list-disc",
668
676
  "list-decimal",
@@ -692,6 +700,7 @@ var UTILITY_PREFIXES = [
692
700
  "bg-clip-padding",
693
701
  "bg-clip-content",
694
702
  "bg-clip-text",
703
+ "bg-gradient-to",
695
704
  "resize-none",
696
705
  "resize-y",
697
706
  "resize-x",
@@ -711,15 +720,8 @@ var UTILITY_PREFIXES = [
711
720
  "scale-y",
712
721
  "skew-x",
713
722
  "skew-y",
714
- "origin-center",
715
- "origin-top",
716
- "origin-top-right",
717
- "origin-right",
718
- "origin-bottom-right",
719
- "origin-bottom",
720
- "origin-bottom-left",
721
- "origin-left",
722
- "origin-top-left",
723
+ // Transform origin (single prefix, value carries direction)
724
+ "origin",
723
725
  "min-w",
724
726
  "min-h",
725
727
  "max-w",
@@ -728,7 +730,7 @@ var UTILITY_PREFIXES = [
728
730
  "bg-opacity",
729
731
  "text-opacity",
730
732
  "border-opacity",
731
- // Grid placement (longer prefixes before shorter ones)
733
+ // Grid placement
732
734
  "col-span",
733
735
  "col-start",
734
736
  "col-end",
@@ -740,6 +742,35 @@ var UTILITY_PREFIXES = [
740
742
  "grid-flow",
741
743
  "auto-cols",
742
744
  "auto-rows",
745
+ // Grid alignment
746
+ "place-items",
747
+ "place-content",
748
+ "place-self",
749
+ "justify-items",
750
+ "justify-self",
751
+ // Backdrop filters (longer than 'backdrop' alone)
752
+ "backdrop-blur",
753
+ "backdrop-brightness",
754
+ "backdrop-contrast",
755
+ "backdrop-grayscale",
756
+ "backdrop-hue-rotate",
757
+ "backdrop-invert",
758
+ "backdrop-opacity",
759
+ "backdrop-saturate",
760
+ "backdrop-sepia",
761
+ "backdrop-filter",
762
+ // Filters
763
+ "drop-shadow",
764
+ "hue-rotate",
765
+ "text-shadow",
766
+ "underline-offset",
767
+ "outline-offset",
768
+ "will-change",
769
+ "mix-blend",
770
+ "decoration",
771
+ "perspective",
772
+ "tint",
773
+ "animate",
743
774
  // Single-word prefixes last
744
775
  "appearance-none",
745
776
  "outline-none",
@@ -780,9 +811,11 @@ var UTILITY_PREFIXES = [
780
811
  "border",
781
812
  "rounded",
782
813
  "shadow",
814
+ "size",
783
815
  "opacity",
784
816
  "leading",
785
817
  "tracking",
818
+ "line-clamp",
786
819
  "basis",
787
820
  "grow",
788
821
  "shrink",
@@ -793,13 +826,23 @@ var UTILITY_PREFIXES = [
793
826
  "rotate",
794
827
  "aspect",
795
828
  "columns",
796
- "placeholder",
797
829
  "ring",
798
830
  "gap",
799
831
  "inset",
832
+ "filter",
833
+ "transform",
834
+ "blur",
835
+ "brightness",
836
+ "contrast",
837
+ "grayscale",
838
+ "invert",
839
+ "saturate",
840
+ "sepia",
800
841
  "bg",
801
842
  "text",
802
843
  "font",
844
+ "caret",
845
+ "accent",
803
846
  "from",
804
847
  "via",
805
848
  "to",
@@ -828,12 +871,11 @@ var UTILITY_PREFIXES = [
828
871
  "left",
829
872
  "z",
830
873
  "col",
831
- "row",
832
- "flex"
833
- // also a standalone
874
+ "row"
834
875
  ];
835
876
  var SORTED_PREFIXES = [...new Set(UTILITY_PREFIXES)].sort((a, b) => b.length - a.length);
836
877
  var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
878
+ // Display
837
879
  "flex",
838
880
  "block",
839
881
  "inline-block",
@@ -845,13 +887,16 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
845
887
  "hidden",
846
888
  "contents",
847
889
  "flow-root",
890
+ // Position
848
891
  "relative",
849
892
  "absolute",
850
893
  "fixed",
851
894
  "sticky",
852
895
  "static",
896
+ // Visibility
853
897
  "visible",
854
898
  "invisible",
899
+ // Typography
855
900
  "uppercase",
856
901
  "lowercase",
857
902
  "capitalize",
@@ -866,6 +911,17 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
866
911
  "antialiased",
867
912
  "sr-only",
868
913
  "not-sr-only",
914
+ // Font variant numeric
915
+ "normal-nums",
916
+ "ordinal",
917
+ "slashed-zero",
918
+ "lining-nums",
919
+ "oldstyle-nums",
920
+ "proportional-nums",
921
+ "tabular-nums",
922
+ "diagonal-fractions",
923
+ "stacked-fractions",
924
+ // Flexbox
869
925
  "flex-row",
870
926
  "flex-col",
871
927
  "flex-row-reverse",
@@ -894,15 +950,19 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
894
950
  "content-between",
895
951
  "content-around",
896
952
  "content-evenly",
953
+ "content-stretch",
897
954
  "self-start",
898
955
  "self-end",
899
956
  "self-center",
900
957
  "self-auto",
901
958
  "self-stretch",
959
+ "self-baseline",
960
+ // Text align
902
961
  "text-left",
903
962
  "text-right",
904
963
  "text-center",
905
964
  "text-justify",
965
+ // Font weight shortcuts
906
966
  "font-thin",
907
967
  "font-extralight",
908
968
  "font-light",
@@ -912,6 +972,7 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
912
972
  "font-bold",
913
973
  "font-extrabold",
914
974
  "font-black",
975
+ // Overflow
915
976
  "overflow-hidden",
916
977
  "overflow-visible",
917
978
  "overflow-scroll",
@@ -922,11 +983,23 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
922
983
  "overflow-y-hidden",
923
984
  "overflow-y-scroll",
924
985
  "overflow-y-auto",
986
+ // Object fit
925
987
  "object-contain",
926
988
  "object-cover",
927
989
  "object-fill",
928
990
  "object-none",
929
991
  "object-scale-down",
992
+ // Object position
993
+ "object-center",
994
+ "object-top",
995
+ "object-bottom",
996
+ "object-left",
997
+ "object-right",
998
+ "object-left-top",
999
+ "object-left-bottom",
1000
+ "object-right-top",
1001
+ "object-right-bottom",
1002
+ // Border
930
1003
  "border-solid",
931
1004
  "border-dashed",
932
1005
  "border-dotted",
@@ -935,9 +1008,15 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
935
1008
  "border-r",
936
1009
  "border-b",
937
1010
  "border-l",
1011
+ "border-collapse",
1012
+ "border-separate",
1013
+ // Lists
938
1014
  "list-none",
939
1015
  "list-disc",
940
1016
  "list-decimal",
1017
+ "list-inside",
1018
+ "list-outside",
1019
+ // Cursor / select
941
1020
  "cursor-auto",
942
1021
  "cursor-default",
943
1022
  "cursor-pointer",
@@ -951,6 +1030,7 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
951
1030
  "select-auto",
952
1031
  "pointer-events-none",
953
1032
  "pointer-events-auto",
1033
+ // Whitespace / word break
954
1034
  "whitespace-normal",
955
1035
  "whitespace-nowrap",
956
1036
  "whitespace-pre",
@@ -959,19 +1039,129 @@ var STANDALONE_UTILITIES = /* @__PURE__ */ new Set([
959
1039
  "break-normal",
960
1040
  "break-words",
961
1041
  "break-all",
1042
+ // Background clip
962
1043
  "bg-clip-border",
963
1044
  "bg-clip-padding",
964
1045
  "bg-clip-content",
965
1046
  "bg-clip-text",
1047
+ // Background size
1048
+ "bg-auto",
1049
+ "bg-cover",
1050
+ "bg-contain",
1051
+ // Background position
1052
+ "bg-center",
1053
+ "bg-top",
1054
+ "bg-bottom",
1055
+ "bg-left",
1056
+ "bg-right",
1057
+ "bg-left-top",
1058
+ "bg-left-bottom",
1059
+ "bg-right-top",
1060
+ "bg-right-bottom",
1061
+ // Background repeat
1062
+ "bg-repeat",
1063
+ "bg-no-repeat",
1064
+ "bg-repeat-x",
1065
+ "bg-repeat-y",
1066
+ "bg-repeat-round",
1067
+ "bg-repeat-space",
1068
+ // Background attachment
1069
+ "bg-fixed",
1070
+ "bg-local",
1071
+ "bg-scroll",
1072
+ // Background image
1073
+ "bg-none",
1074
+ // Box sizing
966
1075
  "box-border",
967
1076
  "box-content",
1077
+ // Resize
968
1078
  "resize",
969
1079
  "resize-none",
970
1080
  "resize-y",
971
1081
  "resize-x",
1082
+ // Outline
972
1083
  "appearance-none",
973
1084
  "outline-none",
974
- "outline"
1085
+ "outline",
1086
+ // Table
1087
+ "table",
1088
+ "table-auto",
1089
+ "table-fixed",
1090
+ "caption-top",
1091
+ "caption-bottom",
1092
+ // CSS filters (standalone = default/full effect)
1093
+ "grayscale",
1094
+ "invert",
1095
+ "sepia",
1096
+ // Isolation
1097
+ "isolate",
1098
+ "isolation-auto",
1099
+ // Backface visibility (both platforms)
1100
+ "backface-visible",
1101
+ "backface-hidden",
1102
+ // Divide none
1103
+ "divide-none",
1104
+ // Group / peer markers (no-op style; needed so isKnownUtility recognises them)
1105
+ "group",
1106
+ "peer",
1107
+ // Text-wrap (web-only)
1108
+ "text-wrap",
1109
+ "text-nowrap",
1110
+ "text-balance",
1111
+ "text-pretty",
1112
+ // Screen sizing
1113
+ "w-screen",
1114
+ "min-h-screen",
1115
+ "max-h-screen",
1116
+ "min-w-screen",
1117
+ "max-w-screen",
1118
+ // Extended cursors (web-only)
1119
+ "cursor-grab",
1120
+ "cursor-grabbing",
1121
+ "cursor-zoom-in",
1122
+ "cursor-zoom-out",
1123
+ "cursor-crosshair",
1124
+ "cursor-help",
1125
+ "cursor-none",
1126
+ // Overflow clip (web-only)
1127
+ "overflow-clip",
1128
+ "overflow-x-clip",
1129
+ "overflow-y-clip",
1130
+ // Scroll behavior (web-only)
1131
+ "scroll-smooth",
1132
+ "scroll-auto",
1133
+ // Float & clear (web-only)
1134
+ "float-left",
1135
+ "float-right",
1136
+ "float-start",
1137
+ "float-end",
1138
+ "float-none",
1139
+ "clear-left",
1140
+ "clear-right",
1141
+ "clear-both",
1142
+ "clear-start",
1143
+ "clear-end",
1144
+ "clear-none",
1145
+ // Vertical align (web-only)
1146
+ "align-baseline",
1147
+ "align-top",
1148
+ "align-middle",
1149
+ "align-bottom",
1150
+ "align-text-top",
1151
+ "align-text-bottom",
1152
+ "align-sub",
1153
+ "align-super",
1154
+ // Touch action (web-only)
1155
+ "touch-auto",
1156
+ "touch-none",
1157
+ "touch-pan-x",
1158
+ "touch-pan-y",
1159
+ "touch-pan-left",
1160
+ "touch-pan-right",
1161
+ "touch-pan-up",
1162
+ "touch-pan-down",
1163
+ "touch-pinch-zoom",
1164
+ "touch-manipulation"
975
1165
  ]);
976
1166
  function parseClass(className) {
977
1167
  const trimmed = className.trim();
@@ -989,6 +1179,11 @@ function parseClass(className) {
989
1179
  break;
990
1180
  }
991
1181
  }
1182
+ let important = false;
1183
+ if (remaining.startsWith("!") && remaining.length > 1) {
1184
+ important = true;
1185
+ remaining = remaining.slice(1);
1186
+ }
992
1187
  let negative = false;
993
1188
  if (remaining.startsWith("-") && remaining.length > 1 && remaining[1] !== "-") {
994
1189
  negative = true;
@@ -998,18 +1193,18 @@ function parseClass(className) {
998
1193
  if (bracketStart > 0 && remaining.endsWith("]")) {
999
1194
  const utility = remaining.slice(0, bracketStart);
1000
1195
  const value = remaining.slice(bracketStart + 2, -1);
1001
- return { original: trimmed, modifiers, negative, utility, value, isArbitrary: true };
1196
+ return { original: trimmed, modifiers, negative, important, utility, value, isArbitrary: true };
1002
1197
  }
1003
1198
  if (STANDALONE_UTILITIES.has(remaining)) {
1004
- return { original: trimmed, modifiers, negative, utility: remaining, value: "", isArbitrary: false };
1199
+ return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
1005
1200
  }
1006
1201
  for (const prefix of SORTED_PREFIXES) {
1007
1202
  if (remaining === prefix) {
1008
- return { original: trimmed, modifiers, negative, utility: prefix, value: "", isArbitrary: false };
1203
+ return { original: trimmed, modifiers, negative, important, utility: prefix, value: "", isArbitrary: false };
1009
1204
  }
1010
1205
  if (remaining.startsWith(prefix + "-")) {
1011
1206
  const value = remaining.slice(prefix.length + 1);
1012
- return { original: trimmed, modifiers, negative, utility: prefix, value, isArbitrary: false };
1207
+ return { original: trimmed, modifiers, negative, important, utility: prefix, value, isArbitrary: false };
1013
1208
  }
1014
1209
  }
1015
1210
  const firstDash = remaining.indexOf("-");
@@ -1018,12 +1213,13 @@ function parseClass(className) {
1018
1213
  original: trimmed,
1019
1214
  modifiers,
1020
1215
  negative,
1216
+ important,
1021
1217
  utility: remaining.slice(0, firstDash),
1022
1218
  value: remaining.slice(firstDash + 1),
1023
1219
  isArbitrary: false
1024
1220
  };
1025
1221
  }
1026
- return { original: trimmed, modifiers, negative, utility: remaining, value: "", isArbitrary: false };
1222
+ return { original: trimmed, modifiers, negative, important, utility: remaining, value: "", isArbitrary: false };
1027
1223
  }
1028
1224
  function parseClasses(classString) {
1029
1225
  const results = [];
@@ -1145,6 +1341,8 @@ function resolveFontSize(value, fontSizes, isArbitrary) {
1145
1341
  if (isArbitrary) return isWeb ? value : toNativeValue(value);
1146
1342
  return fontSizes[value] ?? null;
1147
1343
  }
1344
+ var FILTER_COMPOSE = "var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)";
1345
+ var BACKDROP_FILTER_COMPOSE = "var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)";
1148
1346
  var STANDALONE = {
1149
1347
  // Display
1150
1348
  // React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
@@ -1195,12 +1393,14 @@ var STANDALONE = {
1195
1393
  "content-between": { alignContent: "space-between" },
1196
1394
  "content-around": { alignContent: "space-around" },
1197
1395
  "content-evenly": { alignContent: "space-evenly" },
1396
+ "content-stretch": { alignContent: "stretch" },
1198
1397
  // Align self (both)
1199
1398
  "self-auto": { alignSelf: "auto" },
1200
1399
  "self-start": { alignSelf: "flex-start" },
1201
1400
  "self-end": { alignSelf: "flex-end" },
1202
1401
  "self-center": { alignSelf: "center" },
1203
1402
  "self-stretch": { alignSelf: "stretch" },
1403
+ "self-baseline": { alignSelf: "baseline" },
1204
1404
  // Text align (both)
1205
1405
  "text-left": { textAlign: "left" },
1206
1406
  "text-right": { textAlign: "right" },
@@ -1333,7 +1533,139 @@ var STANDALONE = {
1333
1533
  "bg-clip-border": isWeb ? { backgroundClip: "border-box" } : null,
1334
1534
  "bg-clip-padding": isWeb ? { backgroundClip: "padding-box" } : null,
1335
1535
  "bg-clip-content": isWeb ? { backgroundClip: "content-box" } : null,
1336
- "bg-clip-text": isWeb ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null
1536
+ "bg-clip-text": isWeb ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
1537
+ // Background image
1538
+ "bg-none": isWeb ? { backgroundImage: "none" } : null,
1539
+ // Background size (web-only)
1540
+ "bg-auto": isWeb ? { backgroundSize: "auto" } : null,
1541
+ "bg-cover": isWeb ? { backgroundSize: "cover" } : null,
1542
+ "bg-contain": isWeb ? { backgroundSize: "contain" } : null,
1543
+ // Background position (web-only)
1544
+ "bg-center": isWeb ? { backgroundPosition: "center" } : null,
1545
+ "bg-top": isWeb ? { backgroundPosition: "top" } : null,
1546
+ "bg-bottom": isWeb ? { backgroundPosition: "bottom" } : null,
1547
+ "bg-left": isWeb ? { backgroundPosition: "left" } : null,
1548
+ "bg-right": isWeb ? { backgroundPosition: "right" } : null,
1549
+ "bg-left-top": isWeb ? { backgroundPosition: "left top" } : null,
1550
+ "bg-left-bottom": isWeb ? { backgroundPosition: "left bottom" } : null,
1551
+ "bg-right-top": isWeb ? { backgroundPosition: "right top" } : null,
1552
+ "bg-right-bottom": isWeb ? { backgroundPosition: "right bottom" } : null,
1553
+ // Background repeat (web-only)
1554
+ "bg-repeat": isWeb ? { backgroundRepeat: "repeat" } : null,
1555
+ "bg-no-repeat": isWeb ? { backgroundRepeat: "no-repeat" } : null,
1556
+ "bg-repeat-x": isWeb ? { backgroundRepeat: "repeat-x" } : null,
1557
+ "bg-repeat-y": isWeb ? { backgroundRepeat: "repeat-y" } : null,
1558
+ "bg-repeat-round": isWeb ? { backgroundRepeat: "round" } : null,
1559
+ "bg-repeat-space": isWeb ? { backgroundRepeat: "space" } : null,
1560
+ // Background attachment (web-only)
1561
+ "bg-fixed": isWeb ? { backgroundAttachment: "fixed" } : null,
1562
+ "bg-local": isWeb ? { backgroundAttachment: "local" } : null,
1563
+ "bg-scroll": isWeb ? { backgroundAttachment: "scroll" } : null,
1564
+ // Object position (web-only)
1565
+ "object-center": isWeb ? { objectPosition: "center" } : null,
1566
+ "object-top": isWeb ? { objectPosition: "top" } : null,
1567
+ "object-bottom": isWeb ? { objectPosition: "bottom" } : null,
1568
+ "object-left": isWeb ? { objectPosition: "left" } : null,
1569
+ "object-right": isWeb ? { objectPosition: "right" } : null,
1570
+ "object-left-top": isWeb ? { objectPosition: "left top" } : null,
1571
+ "object-left-bottom": isWeb ? { objectPosition: "left bottom" } : null,
1572
+ "object-right-top": isWeb ? { objectPosition: "right top" } : null,
1573
+ "object-right-bottom": isWeb ? { objectPosition: "right bottom" } : null,
1574
+ // Table (web-only)
1575
+ table: isWeb ? { display: "table" } : null,
1576
+ "table-auto": isWeb ? { tableLayout: "auto" } : null,
1577
+ "table-fixed": isWeb ? { tableLayout: "fixed" } : null,
1578
+ "caption-top": isWeb ? { captionSide: "top" } : null,
1579
+ "caption-bottom": isWeb ? { captionSide: "bottom" } : null,
1580
+ "border-collapse": isWeb ? { borderCollapse: "collapse" } : null,
1581
+ "border-separate": isWeb ? { borderCollapse: "separate" } : null,
1582
+ // List style position (web-only)
1583
+ "list-inside": isWeb ? { listStylePosition: "inside" } : null,
1584
+ "list-outside": isWeb ? { listStylePosition: "outside" } : null,
1585
+ // Font variant numeric (web-only)
1586
+ "normal-nums": isWeb ? { fontVariantNumeric: "normal" } : null,
1587
+ ordinal: isWeb ? { fontVariantNumeric: "ordinal" } : null,
1588
+ "slashed-zero": isWeb ? { fontVariantNumeric: "slashed-zero" } : null,
1589
+ "lining-nums": isWeb ? { fontVariantNumeric: "lining-nums" } : null,
1590
+ "oldstyle-nums": isWeb ? { fontVariantNumeric: "oldstyle-nums" } : null,
1591
+ "proportional-nums": isWeb ? { fontVariantNumeric: "proportional-nums" } : null,
1592
+ "tabular-nums": isWeb ? { fontVariantNumeric: "tabular-nums" } : null,
1593
+ "diagonal-fractions": isWeb ? { fontVariantNumeric: "diagonal-fractions" } : null,
1594
+ "stacked-fractions": isWeb ? { fontVariantNumeric: "stacked-fractions" } : null,
1595
+ // Isolation (web-only)
1596
+ isolate: isWeb ? { isolation: "isolate" } : null,
1597
+ "isolation-auto": isWeb ? { isolation: "auto" } : null,
1598
+ // Backface visibility (both iOS and Android)
1599
+ "backface-visible": { backfaceVisibility: "visible" },
1600
+ "backface-hidden": { backfaceVisibility: "hidden" },
1601
+ // CSS filters — standalone = default/full effect (web-only)
1602
+ grayscale: isWeb ? { "--tw-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
1603
+ invert: isWeb ? { "--tw-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
1604
+ sepia: isWeb ? { "--tw-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
1605
+ // Divide none
1606
+ "divide-none": isWeb ? { __divideX: 0, __divideY: 0 } : null,
1607
+ // Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
1608
+ group: isWeb ? {} : null,
1609
+ peer: isWeb ? {} : null,
1610
+ // Text-wrap (web-only)
1611
+ "text-wrap": isWeb ? { textWrap: "wrap" } : null,
1612
+ "text-nowrap": isWeb ? { textWrap: "nowrap" } : null,
1613
+ "text-balance": isWeb ? { textWrap: "balance" } : null,
1614
+ "text-pretty": isWeb ? { textWrap: "pretty" } : null,
1615
+ // Screen sizing (vw values are web-only; vh values work cross-platform via spacing scale for h-*)
1616
+ "w-screen": isWeb ? { width: "100vw" } : null,
1617
+ "min-h-screen": { minHeight: "100vh" },
1618
+ "max-h-screen": { maxHeight: "100vh" },
1619
+ "min-w-screen": isWeb ? { minWidth: "100vw" } : null,
1620
+ "max-w-screen": isWeb ? { maxWidth: "100vw" } : null,
1621
+ // Extended cursors (web-only)
1622
+ "cursor-grab": isWeb ? { cursor: "grab" } : null,
1623
+ "cursor-grabbing": isWeb ? { cursor: "grabbing" } : null,
1624
+ "cursor-zoom-in": isWeb ? { cursor: "zoom-in" } : null,
1625
+ "cursor-zoom-out": isWeb ? { cursor: "zoom-out" } : null,
1626
+ "cursor-crosshair": isWeb ? { cursor: "crosshair" } : null,
1627
+ "cursor-help": isWeb ? { cursor: "help" } : null,
1628
+ "cursor-none": isWeb ? { cursor: "none" } : null,
1629
+ // Overflow clip (web-only)
1630
+ "overflow-clip": isWeb ? { overflow: "clip" } : null,
1631
+ "overflow-x-clip": isWeb ? { overflowX: "clip" } : null,
1632
+ "overflow-y-clip": isWeb ? { overflowY: "clip" } : null,
1633
+ // Scroll behavior (web-only)
1634
+ "scroll-smooth": isWeb ? { scrollBehavior: "smooth" } : null,
1635
+ "scroll-auto": isWeb ? { scrollBehavior: "auto" } : null,
1636
+ // Float (web-only)
1637
+ "float-left": isWeb ? { float: "left" } : null,
1638
+ "float-right": isWeb ? { float: "right" } : null,
1639
+ "float-start": isWeb ? { float: "inline-start" } : null,
1640
+ "float-end": isWeb ? { float: "inline-end" } : null,
1641
+ "float-none": isWeb ? { float: "none" } : null,
1642
+ // Clear (web-only)
1643
+ "clear-left": isWeb ? { clear: "left" } : null,
1644
+ "clear-right": isWeb ? { clear: "right" } : null,
1645
+ "clear-both": isWeb ? { clear: "both" } : null,
1646
+ "clear-start": isWeb ? { clear: "inline-start" } : null,
1647
+ "clear-end": isWeb ? { clear: "inline-end" } : null,
1648
+ "clear-none": isWeb ? { clear: "none" } : null,
1649
+ // Vertical align (web-only)
1650
+ "align-baseline": isWeb ? { verticalAlign: "baseline" } : null,
1651
+ "align-top": isWeb ? { verticalAlign: "top" } : null,
1652
+ "align-middle": isWeb ? { verticalAlign: "middle" } : null,
1653
+ "align-bottom": isWeb ? { verticalAlign: "bottom" } : null,
1654
+ "align-text-top": isWeb ? { verticalAlign: "text-top" } : null,
1655
+ "align-text-bottom": isWeb ? { verticalAlign: "text-bottom" } : null,
1656
+ "align-sub": isWeb ? { verticalAlign: "sub" } : null,
1657
+ "align-super": isWeb ? { verticalAlign: "super" } : null,
1658
+ // Touch action (web-only)
1659
+ "touch-auto": isWeb ? { touchAction: "auto" } : null,
1660
+ "touch-none": isWeb ? { touchAction: "none" } : null,
1661
+ "touch-pan-x": isWeb ? { touchAction: "pan-x" } : null,
1662
+ "touch-pan-y": isWeb ? { touchAction: "pan-y" } : null,
1663
+ "touch-pan-left": isWeb ? { touchAction: "pan-left" } : null,
1664
+ "touch-pan-right": isWeb ? { touchAction: "pan-right" } : null,
1665
+ "touch-pan-up": isWeb ? { touchAction: "pan-up" } : null,
1666
+ "touch-pan-down": isWeb ? { touchAction: "pan-down" } : null,
1667
+ "touch-pinch-zoom": isWeb ? { touchAction: "pinch-zoom" } : null,
1668
+ "touch-manipulation": isWeb ? { touchAction: "manipulation" } : null
1337
1669
  };
1338
1670
  var RESOLVERS = {
1339
1671
  // ── Background ─────────────────────────────────────────────────────────────
@@ -1665,6 +1997,545 @@ var RESOLVERS = {
1665
1997
  if (isArbitrary) return { gridRow: value };
1666
1998
  return null;
1667
1999
  },
2000
+ // ── Grid alignment (web-only) ──────────────────────────────────────────────
2001
+ // place-items is shorthand for align-items + justify-items on a grid container
2002
+ "place-items": ({ value }) => {
2003
+ if (!isWeb) return null;
2004
+ const map = {
2005
+ start: "start",
2006
+ end: "end",
2007
+ center: "center",
2008
+ stretch: "stretch",
2009
+ baseline: "baseline"
2010
+ };
2011
+ return map[value] ? { placeItems: map[value] } : null;
2012
+ },
2013
+ // place-content is shorthand for align-content + justify-content on a grid container
2014
+ "place-content": ({ value }) => {
2015
+ if (!isWeb) return null;
2016
+ const map = {
2017
+ start: "start",
2018
+ end: "end",
2019
+ center: "center",
2020
+ stretch: "stretch",
2021
+ between: "space-between",
2022
+ around: "space-around",
2023
+ evenly: "space-evenly",
2024
+ baseline: "baseline"
2025
+ };
2026
+ return map[value] ? { placeContent: map[value] } : null;
2027
+ },
2028
+ // justify-items controls inline-axis alignment of grid items within their cells
2029
+ "justify-items": ({ value }) => {
2030
+ if (!isWeb) return null;
2031
+ const map = {
2032
+ start: "start",
2033
+ end: "end",
2034
+ center: "center",
2035
+ stretch: "stretch"
2036
+ };
2037
+ return map[value] ? { justifyItems: map[value] } : null;
2038
+ },
2039
+ // place-self is shorthand for align-self + justify-self on a grid item
2040
+ "place-self": ({ value }) => {
2041
+ if (!isWeb) return null;
2042
+ const map = {
2043
+ auto: "auto",
2044
+ start: "start",
2045
+ end: "end",
2046
+ center: "center",
2047
+ stretch: "stretch"
2048
+ };
2049
+ return map[value] ? { placeSelf: map[value] } : null;
2050
+ },
2051
+ // justify-self controls inline-axis self-alignment of a grid item
2052
+ "justify-self": ({ value }) => {
2053
+ if (!isWeb) return null;
2054
+ const map = {
2055
+ auto: "auto",
2056
+ start: "start",
2057
+ end: "end",
2058
+ center: "center",
2059
+ stretch: "stretch"
2060
+ };
2061
+ return map[value] ? { justifySelf: map[value] } : null;
2062
+ },
2063
+ // ── CSS Filters (composable via CSS variables, web-only) ─────────────────
2064
+ blur: ({ value, isArbitrary }) => {
2065
+ if (!isWeb) return null;
2066
+ const sizes = {
2067
+ "": "blur(8px)",
2068
+ sm: "blur(4px)",
2069
+ md: "blur(12px)",
2070
+ lg: "blur(16px)",
2071
+ xl: "blur(24px)",
2072
+ "2xl": "blur(40px)",
2073
+ "3xl": "blur(64px)"
2074
+ };
2075
+ if (value === "none") return { "--tw-blur": "", filter: FILTER_COMPOSE };
2076
+ const v = isArbitrary ? `blur(${value})` : sizes[value];
2077
+ return v !== void 0 ? { "--tw-blur": v, filter: FILTER_COMPOSE } : null;
2078
+ },
2079
+ brightness: ({ value, isArbitrary }) => {
2080
+ if (!isWeb) return null;
2081
+ const v = isArbitrary ? `brightness(${value})` : `brightness(${parseFloat(value) / 100})`;
2082
+ return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--tw-brightness": v, filter: FILTER_COMPOSE };
2083
+ },
2084
+ contrast: ({ value, isArbitrary }) => {
2085
+ if (!isWeb) return null;
2086
+ const v = isArbitrary ? `contrast(${value})` : `contrast(${parseFloat(value) / 100})`;
2087
+ return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--tw-contrast": v, filter: FILTER_COMPOSE };
2088
+ },
2089
+ grayscale: ({ value }) => {
2090
+ if (!isWeb) return null;
2091
+ const v = value === "0" ? "grayscale(0)" : "grayscale(100%)";
2092
+ return { "--tw-grayscale": v, filter: FILTER_COMPOSE };
2093
+ },
2094
+ "hue-rotate": ({ value, negative, isArbitrary }) => {
2095
+ if (!isWeb) return null;
2096
+ const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
2097
+ if (isNaN(parseFloat(deg)) && !isArbitrary) return null;
2098
+ return { "--tw-hue-rotate": `hue-rotate(${deg})`, filter: FILTER_COMPOSE };
2099
+ },
2100
+ invert: ({ value }) => {
2101
+ if (!isWeb) return null;
2102
+ const v = value === "0" ? "invert(0)" : "invert(100%)";
2103
+ return { "--tw-invert": v, filter: FILTER_COMPOSE };
2104
+ },
2105
+ saturate: ({ value, isArbitrary }) => {
2106
+ if (!isWeb) return null;
2107
+ const v = isArbitrary ? `saturate(${value})` : `saturate(${parseFloat(value) / 100})`;
2108
+ return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--tw-saturate": v, filter: FILTER_COMPOSE };
2109
+ },
2110
+ sepia: ({ value }) => {
2111
+ if (!isWeb) return null;
2112
+ const v = value === "0" ? "sepia(0)" : "sepia(100%)";
2113
+ return { "--tw-sepia": v, filter: FILTER_COMPOSE };
2114
+ },
2115
+ "drop-shadow": ({ value, isArbitrary }) => {
2116
+ if (!isWeb) return null;
2117
+ if (isArbitrary) return { "--tw-drop-shadow": `drop-shadow(${value.replace(/_/g, " ")})`, filter: FILTER_COMPOSE };
2118
+ const presets = {
2119
+ "": "drop-shadow(0 1px 2px rgb(0 0 0/0.1)) drop-shadow(0 1px 1px rgb(0 0 0/0.06))",
2120
+ sm: "drop-shadow(0 1px 1px rgb(0 0 0/0.05))",
2121
+ md: "drop-shadow(0 4px 3px rgb(0 0 0/0.07)) drop-shadow(0 2px 2px rgb(0 0 0/0.06))",
2122
+ lg: "drop-shadow(0 10px 8px rgb(0 0 0/0.04)) drop-shadow(0 4px 3px rgb(0 0 0/0.1))",
2123
+ xl: "drop-shadow(0 20px 13px rgb(0 0 0/0.03)) drop-shadow(0 8px 5px rgb(0 0 0/0.08))",
2124
+ "2xl": "drop-shadow(0 25px 25px rgb(0 0 0/0.15))",
2125
+ none: "drop-shadow(0 0 #0000)"
2126
+ };
2127
+ const v = presets[value];
2128
+ return v !== void 0 ? { "--tw-drop-shadow": v, filter: FILTER_COMPOSE } : null;
2129
+ },
2130
+ // Arbitrary full filter string: filter-[blur(4px)_grayscale(1)]
2131
+ filter: ({ value, isArbitrary }) => {
2132
+ if (!isWeb) return null;
2133
+ if (isArbitrary) return { filter: value.replace(/_/g, " ") };
2134
+ if (value === "none") return { filter: "none" };
2135
+ return null;
2136
+ },
2137
+ // ── Backdrop Filters (composable via CSS variables, web-only) ────────────
2138
+ "backdrop-blur": ({ value, isArbitrary }) => {
2139
+ if (!isWeb) return null;
2140
+ const sizes = {
2141
+ "": "blur(8px)",
2142
+ sm: "blur(4px)",
2143
+ md: "blur(12px)",
2144
+ lg: "blur(16px)",
2145
+ xl: "blur(24px)",
2146
+ "2xl": "blur(40px)",
2147
+ "3xl": "blur(64px)"
2148
+ };
2149
+ if (value === "none") return { "--tw-backdrop-blur": "", backdropFilter: BACKDROP_FILTER_COMPOSE };
2150
+ const v = isArbitrary ? `blur(${value})` : sizes[value];
2151
+ return v !== void 0 ? { "--tw-backdrop-blur": v, backdropFilter: BACKDROP_FILTER_COMPOSE } : null;
2152
+ },
2153
+ "backdrop-brightness": ({ value, isArbitrary }) => {
2154
+ if (!isWeb) return null;
2155
+ const v = isArbitrary ? `brightness(${value})` : `brightness(${parseFloat(value) / 100})`;
2156
+ return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--tw-backdrop-brightness": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
2157
+ },
2158
+ "backdrop-contrast": ({ value, isArbitrary }) => {
2159
+ if (!isWeb) return null;
2160
+ const v = isArbitrary ? `contrast(${value})` : `contrast(${parseFloat(value) / 100})`;
2161
+ return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--tw-backdrop-contrast": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
2162
+ },
2163
+ "backdrop-grayscale": ({ value }) => {
2164
+ if (!isWeb) return null;
2165
+ return { "--tw-backdrop-grayscale": value === "0" ? "grayscale(0)" : "grayscale(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
2166
+ },
2167
+ "backdrop-hue-rotate": ({ value, negative, isArbitrary }) => {
2168
+ if (!isWeb) return null;
2169
+ const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
2170
+ if (isNaN(parseFloat(deg)) && !isArbitrary) return null;
2171
+ return { "--tw-backdrop-hue-rotate": `hue-rotate(${deg})`, backdropFilter: BACKDROP_FILTER_COMPOSE };
2172
+ },
2173
+ "backdrop-invert": ({ value }) => {
2174
+ if (!isWeb) return null;
2175
+ return { "--tw-backdrop-invert": value === "0" ? "invert(0)" : "invert(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
2176
+ },
2177
+ "backdrop-opacity": ({ value, isArbitrary }) => {
2178
+ if (!isWeb) return null;
2179
+ const v = isArbitrary ? `opacity(${value})` : `opacity(${parseFloat(value) / 100})`;
2180
+ return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--tw-backdrop-opacity": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
2181
+ },
2182
+ "backdrop-saturate": ({ value, isArbitrary }) => {
2183
+ if (!isWeb) return null;
2184
+ const v = isArbitrary ? `saturate(${value})` : `saturate(${parseFloat(value) / 100})`;
2185
+ return isNaN(parseFloat(value)) && !isArbitrary ? null : { "--tw-backdrop-saturate": v, backdropFilter: BACKDROP_FILTER_COMPOSE };
2186
+ },
2187
+ "backdrop-sepia": ({ value }) => {
2188
+ if (!isWeb) return null;
2189
+ return { "--tw-backdrop-sepia": value === "0" ? "sepia(0)" : "sepia(100%)", backdropFilter: BACKDROP_FILTER_COMPOSE };
2190
+ },
2191
+ "backdrop-filter": ({ value, isArbitrary }) => {
2192
+ if (!isWeb) return null;
2193
+ if (isArbitrary) return { backdropFilter: value.replace(/_/g, " ") };
2194
+ if (value === "none") return { backdropFilter: "none" };
2195
+ return null;
2196
+ },
2197
+ // ── Background gradient (CSS variable gradient stops, web-only) ──────────
2198
+ "bg-gradient-to": ({ value }) => {
2199
+ if (!isWeb) return null;
2200
+ const directions = {
2201
+ t: "to top",
2202
+ tr: "to top right",
2203
+ r: "to right",
2204
+ br: "to bottom right",
2205
+ b: "to bottom",
2206
+ bl: "to bottom left",
2207
+ l: "to left",
2208
+ tl: "to top left"
2209
+ };
2210
+ const dir = directions[value];
2211
+ if (!dir) return null;
2212
+ return {
2213
+ backgroundImage: `linear-gradient(${dir}, var(--tw-gradient-from, transparent), var(--tw-gradient-stops, transparent))`
2214
+ };
2215
+ },
2216
+ from: ({ value, isArbitrary }, { colors }) => {
2217
+ if (!isWeb) return null;
2218
+ const color = resolveColor(value, colors, isArbitrary);
2219
+ if (!color) return null;
2220
+ return {
2221
+ "--tw-gradient-from": color,
2222
+ "--tw-gradient-stops": `var(--tw-gradient-from), var(--tw-gradient-to, transparent)`
2223
+ };
2224
+ },
2225
+ via: ({ value, isArbitrary }, { colors }) => {
2226
+ if (!isWeb) return null;
2227
+ const color = resolveColor(value, colors, isArbitrary);
2228
+ if (!color) return null;
2229
+ return {
2230
+ "--tw-gradient-via": color,
2231
+ "--tw-gradient-stops": `var(--tw-gradient-from), var(--tw-gradient-via), var(--tw-gradient-to, transparent)`
2232
+ };
2233
+ },
2234
+ to: ({ value, isArbitrary }, { colors }) => {
2235
+ if (!isWeb) return null;
2236
+ const color = resolveColor(value, colors, isArbitrary);
2237
+ if (!color) return null;
2238
+ return { "--tw-gradient-to": color };
2239
+ },
2240
+ // ── Transform extras (web-only) ───────────────────────────────────────────
2241
+ "skew-x": ({ value, negative, isArbitrary }) => {
2242
+ const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
2243
+ if (!isArbitrary && isNaN(parseFloat(value))) return null;
2244
+ return isWeb ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
2245
+ },
2246
+ "skew-y": ({ value, negative, isArbitrary }) => {
2247
+ const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
2248
+ if (!isArbitrary && isNaN(parseFloat(value))) return null;
2249
+ return isWeb ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
2250
+ },
2251
+ // Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
2252
+ transform: ({ value, isArbitrary }) => {
2253
+ if (!isWeb) return null;
2254
+ if (isArbitrary) return { transform: value.replace(/_/g, " ") };
2255
+ if (value === "none") return { transform: "none" };
2256
+ return null;
2257
+ },
2258
+ // Transform origin
2259
+ origin: ({ value, isArbitrary }) => {
2260
+ if (!isWeb) return null;
2261
+ if (isArbitrary) return { transformOrigin: value.replace(/_/g, " ") };
2262
+ const origins = {
2263
+ center: "center",
2264
+ top: "top",
2265
+ "top-right": "top right",
2266
+ right: "right",
2267
+ "bottom-right": "bottom right",
2268
+ bottom: "bottom",
2269
+ "bottom-left": "bottom left",
2270
+ left: "left",
2271
+ "top-left": "top left"
2272
+ };
2273
+ return origins[value] ? { transformOrigin: origins[value] } : null;
2274
+ },
2275
+ // ── Text decoration advanced (web-only) ───────────────────────────────────
2276
+ decoration: ({ value, isArbitrary }, { colors }) => {
2277
+ if (!isWeb) return null;
2278
+ if (isArbitrary) {
2279
+ if (/^\d/.test(value) || value.startsWith("calc(")) return { textDecorationThickness: value };
2280
+ return { textDecorationColor: value };
2281
+ }
2282
+ const thickTokens = {
2283
+ auto: "auto",
2284
+ "from-font": "from-font",
2285
+ "0": "0px",
2286
+ "1": "1px",
2287
+ "2": "2px",
2288
+ "4": "4px",
2289
+ "8": "8px"
2290
+ };
2291
+ if (value in thickTokens) return { textDecorationThickness: thickTokens[value] };
2292
+ const styleTokens = {
2293
+ solid: "solid",
2294
+ dashed: "dashed",
2295
+ dotted: "dotted",
2296
+ double: "double",
2297
+ wavy: "wavy"
2298
+ };
2299
+ if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
2300
+ const color = resolveColor(value, colors, false);
2301
+ return color ? { textDecorationColor: color } : null;
2302
+ },
2303
+ "underline-offset": ({ value, isArbitrary }) => {
2304
+ if (!isWeb) return null;
2305
+ if (isArbitrary) return { textUnderlineOffset: value };
2306
+ const offsets = {
2307
+ auto: "auto",
2308
+ "0": "0px",
2309
+ "1": "1px",
2310
+ "2": "2px",
2311
+ "4": "4px",
2312
+ "8": "8px"
2313
+ };
2314
+ return offsets[value] ? { textUnderlineOffset: offsets[value] } : null;
2315
+ },
2316
+ // ── Outline extended (web-only) ───────────────────────────────────────────
2317
+ outline: ({ value, isArbitrary }, { colors }) => {
2318
+ if (!isWeb) return null;
2319
+ if (!value) return { outline: "2px solid transparent", outlineOffset: "2px" };
2320
+ if (value === "none") return { outline: "none", outlineOffset: "0" };
2321
+ if (isArbitrary) {
2322
+ if (/^\d/.test(value) || value.startsWith("calc(")) return { outlineWidth: value };
2323
+ return { outlineColor: value };
2324
+ }
2325
+ const widths = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
2326
+ if (value in widths) return { outlineWidth: widths[value] };
2327
+ const color = resolveColor(value, colors, false);
2328
+ return color ? { outlineColor: color } : null;
2329
+ },
2330
+ "outline-offset": ({ value, isArbitrary }) => {
2331
+ if (!isWeb) return null;
2332
+ if (isArbitrary) return { outlineOffset: value };
2333
+ const offsets = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
2334
+ return offsets[value] ? { outlineOffset: offsets[value] } : null;
2335
+ },
2336
+ // ── Columns (web-only) ─────────────────────────────────────────────────────
2337
+ columns: ({ value, isArbitrary }) => {
2338
+ if (!isWeb) return null;
2339
+ if (isArbitrary) return { columnCount: value };
2340
+ if (value === "auto") return { columnCount: "auto" };
2341
+ const n = parseInt(value, 10);
2342
+ if (!isNaN(n)) return { columnCount: n };
2343
+ const widths = {
2344
+ "3xs": "16rem",
2345
+ "2xs": "18rem",
2346
+ xs: "20rem",
2347
+ sm: "24rem",
2348
+ md: "28rem",
2349
+ lg: "32rem",
2350
+ xl: "36rem",
2351
+ "2xl": "42rem",
2352
+ "3xl": "48rem",
2353
+ "4xl": "56rem",
2354
+ "5xl": "64rem",
2355
+ "6xl": "72rem",
2356
+ "7xl": "80rem"
2357
+ };
2358
+ return widths[value] ? { columnWidth: widths[value] } : null;
2359
+ },
2360
+ // ── Mix blend mode (web-only) ─────────────────────────────────────────────
2361
+ "mix-blend": ({ value }) => {
2362
+ if (!isWeb) return null;
2363
+ const modes = [
2364
+ "normal",
2365
+ "multiply",
2366
+ "screen",
2367
+ "overlay",
2368
+ "darken",
2369
+ "lighten",
2370
+ "color-dodge",
2371
+ "color-burn",
2372
+ "hard-light",
2373
+ "soft-light",
2374
+ "difference",
2375
+ "exclusion",
2376
+ "hue",
2377
+ "saturation",
2378
+ "color",
2379
+ "luminosity",
2380
+ "plus-lighter"
2381
+ ];
2382
+ return modes.includes(value) ? { mixBlendMode: value } : null;
2383
+ },
2384
+ // ── Will-change (web-only) ─────────────────────────────────────────────────
2385
+ "will-change": ({ value, isArbitrary }) => {
2386
+ if (!isWeb) return null;
2387
+ if (isArbitrary) return { willChange: value.replace(/_/g, ", ") };
2388
+ const presets = {
2389
+ auto: "auto",
2390
+ scroll: "scroll-position",
2391
+ contents: "contents",
2392
+ transform: "transform"
2393
+ };
2394
+ return presets[value] ? { willChange: presets[value] } : null;
2395
+ },
2396
+ // ── Divide (child combinator CSS, web-only) ───────────────────────────────
2397
+ // These return special __divide* markers that resolver.ts converts to
2398
+ // .cls > * + * { border-... } CSS rules. No inline style is applied.
2399
+ "divide-x": ({ value, isArbitrary }) => {
2400
+ if (!isWeb) return null;
2401
+ if (value === "reverse") return null;
2402
+ if (!value) return { __divideX: 1 };
2403
+ const n = parseFloat(value);
2404
+ return isNaN(n) ? null : { __divideX: n };
2405
+ },
2406
+ "divide-y": ({ value, isArbitrary }) => {
2407
+ if (!isWeb) return null;
2408
+ if (value === "reverse") return null;
2409
+ if (!value) return { __divideY: 1 };
2410
+ const n = parseFloat(value);
2411
+ return isNaN(n) ? null : { __divideY: n };
2412
+ },
2413
+ divide: ({ value, isArbitrary }, { colors }) => {
2414
+ if (!isWeb) return null;
2415
+ if (isArbitrary) return { __divideColor: value };
2416
+ const styleTokens = {
2417
+ solid: "solid",
2418
+ dashed: "dashed",
2419
+ dotted: "dotted",
2420
+ double: "double",
2421
+ none: "none"
2422
+ };
2423
+ if (value in styleTokens) return { __divideStyle: styleTokens[value] };
2424
+ const color = resolveColor(value, colors, false);
2425
+ return color ? { __divideColor: color } : null;
2426
+ },
2427
+ // ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
2428
+ // Named presets give cross-platform shadow; arbitrary is web-only.
2429
+ "text-shadow": ({ value, isArbitrary }, { colors }) => {
2430
+ if (value === "none") {
2431
+ return isWeb ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
2432
+ }
2433
+ const webPresets = {
2434
+ "": "0 2px 4px rgba(0,0,0,0.3)",
2435
+ sm: "0 1px 2px rgba(0,0,0,0.3)",
2436
+ md: "0 4px 6px rgba(0,0,0,0.3)",
2437
+ lg: "0 8px 16px rgba(0,0,0,0.5)",
2438
+ xl: "0 16px 32px rgba(0,0,0,0.5)"
2439
+ };
2440
+ const nativePresets = {
2441
+ "": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
2442
+ sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
2443
+ md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
2444
+ lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
2445
+ xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
2446
+ };
2447
+ if (value in webPresets) {
2448
+ if (isWeb) return { textShadow: webPresets[value] };
2449
+ return nativePresets[value] ?? null;
2450
+ }
2451
+ if (isArbitrary) {
2452
+ return isWeb ? { textShadow: value.replace(/_/g, " ") } : null;
2453
+ }
2454
+ const color = resolveColor(value, colors, false);
2455
+ if (color) {
2456
+ return isWeb ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
2457
+ }
2458
+ return null;
2459
+ },
2460
+ // ── Perspective transform (cross-platform: iOS, Android, web) ────────────
2461
+ perspective: ({ value, isArbitrary }) => {
2462
+ if (isArbitrary) {
2463
+ const numPx = parseFloat(value);
2464
+ if (isWeb) return { transform: `perspective(${value})` };
2465
+ return isNaN(numPx) ? null : { transform: [{ perspective: numPx }] };
2466
+ }
2467
+ if (value === "none") return isWeb ? { transform: "none" } : null;
2468
+ const n = parseFloat(value);
2469
+ if (isNaN(n)) return null;
2470
+ return isWeb ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
2471
+ },
2472
+ // ── Tint color (native-only, for Image and icon components) ──────────────
2473
+ tint: ({ value, isArbitrary }, { colors }) => {
2474
+ if (isWeb) return null;
2475
+ const color = resolveColor(value, colors, isArbitrary);
2476
+ return color ? { tintColor: color } : null;
2477
+ },
2478
+ // ── Size shorthand (sets width AND height in one utility) ────────────────
2479
+ size: ({ value, isArbitrary }, { spacing }) => {
2480
+ const v = resolveSizing(value, spacing, isArbitrary);
2481
+ return v !== null ? { width: v, height: v } : null;
2482
+ },
2483
+ // ── Animations (CSS keyframe animations, web-only) ────────────────────────
2484
+ // Each variant injects a @keyframes rule once via the __keyframe marker.
2485
+ // resolver.ts detects __keyframe, injects the rule, then strips the marker
2486
+ // so it never reaches element inline styles.
2487
+ animate: ({ value, isArbitrary }) => {
2488
+ if (!isWeb) return null;
2489
+ if (isArbitrary) return { animation: value.replace(/_/g, " ") };
2490
+ const defs = {
2491
+ none: { animation: "none" },
2492
+ spin: {
2493
+ animation: "kb-spin 1s linear infinite",
2494
+ __keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
2495
+ },
2496
+ ping: {
2497
+ animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
2498
+ __keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
2499
+ },
2500
+ pulse: {
2501
+ animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
2502
+ __keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
2503
+ },
2504
+ bounce: {
2505
+ animation: "kb-bounce 1s infinite",
2506
+ __keyframe: "@keyframes kb-bounce { 0%, 100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(0.8,0,1,1) } 50% { transform: none; animation-timing-function: cubic-bezier(0,0,0.2,1) } }"
2507
+ }
2508
+ };
2509
+ const def = defs[value];
2510
+ return def ? def : null;
2511
+ },
2512
+ // ── Line-clamp (web-only) ─────────────────────────────────────────────────
2513
+ "line-clamp": ({ value }) => {
2514
+ if (!isWeb) return null;
2515
+ if (value === "none") return { overflow: "visible", display: "block", WebkitLineClamp: "unset" };
2516
+ const n = parseInt(value, 10);
2517
+ if (isNaN(n) || n < 1) return null;
2518
+ return {
2519
+ overflow: "hidden",
2520
+ display: "-webkit-box",
2521
+ WebkitBoxOrient: "vertical",
2522
+ WebkitLineClamp: n
2523
+ };
2524
+ },
2525
+ // ── Caret color (web-only) ────────────────────────────────────────────────
2526
+ caret: ({ value, isArbitrary }, { colors }) => {
2527
+ if (!isWeb) return null;
2528
+ if (value === "auto" || value === "transparent") return { caretColor: value };
2529
+ const color = resolveColor(value, colors, isArbitrary);
2530
+ return color ? { caretColor: color } : null;
2531
+ },
2532
+ // ── Accent color (web-only) ───────────────────────────────────────────────
2533
+ accent: ({ value, isArbitrary }, { colors }) => {
2534
+ if (!isWeb) return null;
2535
+ if (value === "auto") return { accentColor: "auto" };
2536
+ const color = resolveColor(value, colors, isArbitrary);
2537
+ return color ? { accentColor: color } : null;
2538
+ },
1668
2539
  // ── Flex ───────────────────────────────────────────────────────────────────
1669
2540
  flex: ({ value, isArbitrary }, { flex }) => {
1670
2541
  if (!value) return { display: "flex" };
@@ -1945,6 +2816,9 @@ function clearPluginUtilities() {
1945
2816
  function getPluginStandaloneMap() {
1946
2817
  return PLUGIN_STANDALONE;
1947
2818
  }
2819
+ function isKnownUtility(utility) {
2820
+ return utility in STANDALONE || utility in RESOLVERS || utility in PLUGIN_STANDALONE || utility in PLUGIN_RESOLVERS;
2821
+ }
1948
2822
 
1949
2823
  // src/core/cache.ts
1950
2824
  var LRUCache = class {
@@ -2065,7 +2939,14 @@ var MODIFIER_TO_PSEUDO = {
2065
2939
  "not-pressed": ":not(:active)",
2066
2940
  "not-disabled": ":not(:disabled)",
2067
2941
  "not-checked": ":not(:checked)",
2068
- "not-visited": ":not(:visited)"
2942
+ "not-visited": ":not(:visited)",
2943
+ // Pseudo-elements (CSS-injection only; never applied as inline styles)
2944
+ before: "::before",
2945
+ after: "::after",
2946
+ selection: "::selection",
2947
+ "first-letter": "::first-letter",
2948
+ "first-line": "::first-line",
2949
+ marker: "::marker"
2069
2950
  };
2070
2951
  var GROUP_PEER_PREFIX = {
2071
2952
  "group-hover": ".group:hover",
@@ -2075,12 +2956,34 @@ var GROUP_PEER_PREFIX = {
2075
2956
  };
2076
2957
  var MODE_MODS = /* @__PURE__ */ new Set(["dark", "light", "not-dark", "not-light"]);
2077
2958
  var RESPONSIVE_MODS = /* @__PURE__ */ new Set(["sm", "md", "lg", "xl", "2xl"]);
2078
- function injectClassRule(cls, bucketKey, styles, darkMode) {
2079
- const cssDecls = styleValueToCSS(styles);
2959
+ var PRINT_MODS = /* @__PURE__ */ new Set(["print"]);
2960
+ function buildDivideDecls(styles) {
2961
+ const parts = [];
2962
+ if ("__divideX" in styles) {
2963
+ const w = Number(styles.__divideX);
2964
+ parts.push(`border-left-width: ${w}px`);
2965
+ parts.push("border-right-width: 0px");
2966
+ }
2967
+ if ("__divideY" in styles) {
2968
+ const w = Number(styles.__divideY);
2969
+ parts.push(`border-top-width: ${w}px`);
2970
+ parts.push("border-bottom-width: 0px");
2971
+ }
2972
+ if ("__divideColor" in styles) parts.push(`border-color: ${String(styles.__divideColor)}`);
2973
+ if ("__divideStyle" in styles) parts.push(`border-style: ${String(styles.__divideStyle)}`);
2974
+ return parts.join("; ");
2975
+ }
2976
+ function injectClassRule(cls, bucketKey, styles, darkMode, important = false) {
2977
+ if ("__keyframe" in styles && typeof styles.__keyframe === "string") {
2978
+ injectRule(styles.__keyframe);
2979
+ }
2980
+ const isDivide = "__divideX" in styles || "__divideY" in styles || "__divideColor" in styles || "__divideStyle" in styles;
2981
+ const cssDecls = isDivide ? buildDivideDecls(styles) : styleValueToCSS(styles, important);
2080
2982
  if (!cssDecls) return;
2081
2983
  const escaped = escapeCSSSelector(cls);
2984
+ const childSuffix = isDivide ? " > * + *" : "";
2082
2985
  if (bucketKey === "base") {
2083
- injectRule(`.${escaped} { ${cssDecls} }`);
2986
+ injectRule(`.${escaped}${childSuffix} { ${cssDecls} }`);
2084
2987
  return;
2085
2988
  }
2086
2989
  const mods = bucketKey.split(":");
@@ -2088,10 +2991,11 @@ function injectClassRule(cls, bucketKey, styles, darkMode) {
2088
2991
  const nonResponsiveMods = mods.filter((m) => !RESPONSIVE_MODS.has(m));
2089
2992
  const hasDark = nonResponsiveMods.includes("dark") || nonResponsiveMods.includes("not-light");
2090
2993
  const hasLight = nonResponsiveMods.includes("light") || nonResponsiveMods.includes("not-dark");
2994
+ const hasPrint = nonResponsiveMods.includes("print");
2091
2995
  const ancestorMods = nonResponsiveMods.filter((m) => m in GROUP_PEER_PREFIX);
2092
- const pseudoMods = nonResponsiveMods.filter((m) => !MODE_MODS.has(m) && !(m in GROUP_PEER_PREFIX));
2996
+ const pseudoMods = nonResponsiveMods.filter((m) => !MODE_MODS.has(m) && !(m in GROUP_PEER_PREFIX) && !PRINT_MODS.has(m));
2093
2997
  const pseudoSuffix = pseudoMods.map((p) => MODIFIER_TO_PSEUDO[p] ?? `:${p}`).join("");
2094
- const elementSelector = `.${escaped}${pseudoSuffix}`;
2998
+ const elementSelector = `.${escaped}${pseudoSuffix}${childSuffix}`;
2095
2999
  const ancestorPrefix = ancestorMods.length ? ancestorMods.map((m) => GROUP_PEER_PREFIX[m]).join(" ") + " " : "";
2096
3000
  const selector = `${ancestorPrefix}${elementSelector}`;
2097
3001
  let rule;
@@ -2114,6 +3018,9 @@ function injectClassRule(cls, bucketKey, styles, darkMode) {
2114
3018
  } else {
2115
3019
  rule = `${selector} { ${cssDecls} }`;
2116
3020
  }
3021
+ if (hasPrint) {
3022
+ rule = `@media print { ${rule} }`;
3023
+ }
2117
3024
  if (responsiveMods.length > 0) {
2118
3025
  const screens = getGlobalScreens();
2119
3026
  const minWidth = Math.max(...responsiveMods.map((m) => screens[m] ?? 0));
@@ -2131,7 +3038,19 @@ var RN_ONLY_PROPS = /* @__PURE__ */ new Set([
2131
3038
  "elevation",
2132
3039
  "includeFontPadding",
2133
3040
  "textAlignVertical",
2134
- "writingDirection"
3041
+ "writingDirection",
3042
+ // Text shadow native props — web uses the textShadow CSS shorthand instead
3043
+ "textShadowColor",
3044
+ "textShadowOffset",
3045
+ "textShadowRadius",
3046
+ // tintColor is native-only (Image/icon tinting)
3047
+ "tintColor",
3048
+ // Internal markers — handled specially, never serialized as CSS props
3049
+ "__divideX",
3050
+ "__divideY",
3051
+ "__divideColor",
3052
+ "__divideStyle",
3053
+ "__keyframe"
2135
3054
  ]);
2136
3055
  var CSS_UNITLESS = /* @__PURE__ */ new Set([
2137
3056
  "opacity",
@@ -2149,7 +3068,7 @@ var CSS_UNITLESS = /* @__PURE__ */ new Set([
2149
3068
  "gridRowStart",
2150
3069
  "gridRowEnd"
2151
3070
  ]);
2152
- function styleValueToCSS(styles) {
3071
+ function styleValueToCSS(styles, forceImportant = false) {
2153
3072
  return Object.entries(styles).filter(
2154
3073
  ([prop, v]) => v !== void 0 && v !== null && typeof v !== "object" && !RN_ONLY_PROPS.has(prop)
2155
3074
  ).map(([prop, val]) => {
@@ -2160,8 +3079,8 @@ function styleValueToCSS(styles) {
2160
3079
  } else {
2161
3080
  cssVal = String(val);
2162
3081
  }
2163
- const important = prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
2164
- return `${cssProp}: ${cssVal}${important}`;
3082
+ const imp = forceImportant || prop === "display" && (cssVal === "grid" || cssVal === "inline-grid") || prop === "position" && (cssVal === "sticky" || cssVal === "fixed" || cssVal === "static") ? " !important" : "";
3083
+ return `${cssProp}: ${cssVal}${imp}`;
2165
3084
  }).join("; ");
2166
3085
  }
2167
3086
  function camelToKebab(str) {
@@ -2176,18 +3095,23 @@ function resolve(classString, theme, darkMode = "attribute") {
2176
3095
  const injectQueue = [];
2177
3096
  for (const parsed of parsedClasses) {
2178
3097
  const styles = resolveUtility(parsed, theme);
2179
- if (!styles) continue;
3098
+ if (!styles) {
3099
+ if (process.env.NODE_ENV !== "production" && !parsed.isArbitrary && !isKnownUtility(parsed.utility)) {
3100
+ console.warn(`[kbach] Unknown utility "${parsed.utility}" in class "${parsed.original}"`);
3101
+ }
3102
+ continue;
3103
+ }
2180
3104
  const bucketKey = parsed.modifiers.length === 0 ? "base" : parsed.modifiers.join(":");
2181
3105
  if (!result[bucketKey]) result[bucketKey] = {};
2182
3106
  Object.assign(result[bucketKey], styles);
2183
3107
  if (typeof document !== "undefined") {
2184
- injectQueue.push({ cls: parsed.original, bucketKey, styles });
3108
+ injectQueue.push({ cls: parsed.original, bucketKey, styles, important: parsed.important });
2185
3109
  }
2186
3110
  }
2187
3111
  styleCache.set(cacheKey, result);
2188
3112
  if (typeof document !== "undefined") {
2189
- for (const { cls, bucketKey, styles } of injectQueue) {
2190
- injectClassRule(cls, bucketKey, styles, darkMode);
3113
+ for (const { cls, bucketKey, styles, important } of injectQueue) {
3114
+ injectClassRule(cls, bucketKey, styles, darkMode, important);
2191
3115
  }
2192
3116
  }
2193
3117
  return result;
@@ -2254,6 +3178,11 @@ function matchesMods(mods, isDark, state, breakpoints) {
2254
3178
  }
2255
3179
  function clearCache() {
2256
3180
  styleCache.clear();
3181
+ _injectedRules.clear();
3182
+ if (_styleEl) {
3183
+ _styleEl.remove();
3184
+ _styleEl = null;
3185
+ }
2257
3186
  }
2258
3187
 
2259
3188
  // src/core/config.ts
@@ -2552,6 +3481,11 @@ var InteractiveWrapper = forwardRef(
2552
3481
  const computedStyle = useMemo(
2553
3482
  () => {
2554
3483
  const s = flatten(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused }, breakpoints);
3484
+ delete s.__divideX;
3485
+ delete s.__divideY;
3486
+ delete s.__divideColor;
3487
+ delete s.__divideStyle;
3488
+ delete s.__keyframe;
2555
3489
  if (typeof Component !== "string") {
2556
3490
  if (s.display === "grid" || s.display === "inline-grid") delete s.display;
2557
3491
  delete s.gridTemplateColumns;
@@ -2559,9 +3493,18 @@ var InteractiveWrapper = forwardRef(
2559
3493
  delete s.gridColumn;
2560
3494
  delete s.gridRow;
2561
3495
  delete s.gridArea;
3496
+ delete s.gridColumnStart;
3497
+ delete s.gridColumnEnd;
3498
+ delete s.gridRowStart;
3499
+ delete s.gridRowEnd;
2562
3500
  delete s.gridAutoFlow;
2563
3501
  delete s.gridAutoColumns;
2564
3502
  delete s.gridAutoRows;
3503
+ delete s.placeItems;
3504
+ delete s.placeContent;
3505
+ delete s.justifyItems;
3506
+ delete s.placeSelf;
3507
+ delete s.justifySelf;
2565
3508
  if (s.position === "sticky" || s.position === "fixed" || s.position === "static") {
2566
3509
  delete s.position;
2567
3510
  }