@kbach/react 0.6.25 → 0.6.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -27
- package/dist/{chunk-XISB5W3A.mjs → chunk-TKBIGAR2.mjs} +1326 -1301
- package/dist/{chunk-RUI5EQDF.mjs → chunk-X4XQQZN6.mjs} +6 -2
- package/dist/core/index.d.ts +1274 -0
- package/dist/core/index.js +3478 -0
- package/dist/index.d.ts +50 -224
- package/dist/index.js +215 -3445
- package/dist/index.mjs +77 -36
- package/dist/jsx-dev-runtime.js +54 -3279
- package/dist/jsx-dev-runtime.mjs +2 -2
- package/dist/jsx-runtime.js +54 -3279
- package/dist/jsx-runtime.mjs +2 -2
- package/dist/vite-plugin.js +1372 -1295
- package/dist/vite-plugin.mjs +1372 -1295
- package/kbach-react.md +15 -1
- package/package.json +11 -8
- package/dist/index.d.mts +0 -455
- package/dist/jsx-dev-runtime.d.mts +0 -21
- package/dist/jsx-runtime.d.mts +0 -17
- package/dist/vite-plugin-client.d.mts +0 -8
- package/dist/vite-plugin-client.d.ts +0 -8
- package/dist/web-substitute-CfpYFnE7.d.mts +0 -22
|
@@ -580,6 +580,47 @@ function kbachWarn(message) {
|
|
|
580
580
|
);
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
+
// src/core/cache.ts
|
|
584
|
+
var LRUCache = class {
|
|
585
|
+
constructor(capacity = 1e4, onEvict) {
|
|
586
|
+
this.capacity = capacity;
|
|
587
|
+
if (capacity <= 0) throw new Error("LRUCache: capacity must be a positive integer");
|
|
588
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
589
|
+
this.onEvict = onEvict;
|
|
590
|
+
}
|
|
591
|
+
get(key) {
|
|
592
|
+
if (!this.cache.has(key)) return void 0;
|
|
593
|
+
const value = this.cache.get(key);
|
|
594
|
+
this.cache.delete(key);
|
|
595
|
+
this.cache.set(key, value);
|
|
596
|
+
return value;
|
|
597
|
+
}
|
|
598
|
+
set(key, value) {
|
|
599
|
+
if (this.cache.has(key)) {
|
|
600
|
+
this.cache.delete(key);
|
|
601
|
+
} else if (this.cache.size >= this.capacity) {
|
|
602
|
+
const oldestKey = this.cache.keys().next().value;
|
|
603
|
+
const oldestValue = this.cache.get(oldestKey);
|
|
604
|
+
this.cache.delete(oldestKey);
|
|
605
|
+
this.onEvict?.(oldestKey, oldestValue);
|
|
606
|
+
}
|
|
607
|
+
this.cache.set(key, value);
|
|
608
|
+
return this;
|
|
609
|
+
}
|
|
610
|
+
has(key) {
|
|
611
|
+
return this.cache.has(key);
|
|
612
|
+
}
|
|
613
|
+
delete(key) {
|
|
614
|
+
return this.cache.delete(key);
|
|
615
|
+
}
|
|
616
|
+
clear() {
|
|
617
|
+
this.cache.clear();
|
|
618
|
+
}
|
|
619
|
+
get size() {
|
|
620
|
+
return this.cache.size;
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
|
|
583
624
|
// src/core/registry.ts
|
|
584
625
|
var BUILTIN_MODIFIERS = {
|
|
585
626
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -666,7 +707,7 @@ function clearPluginModifiers() {
|
|
|
666
707
|
_invalidate();
|
|
667
708
|
}
|
|
668
709
|
var NAMED_GROUP_PEER_RE = /^(group|peer)-(hover|focus)\/(.+)$/;
|
|
669
|
-
var _namedModifierCache =
|
|
710
|
+
var _namedModifierCache = new LRUCache(1e4);
|
|
670
711
|
function getNamedGroupPeerModifier(name) {
|
|
671
712
|
const cached = _namedModifierCache.get(name);
|
|
672
713
|
if (cached) return cached;
|
|
@@ -715,14 +756,16 @@ function matchModifier(name, isDark, state, breakpoints) {
|
|
|
715
756
|
return getModifier(name)?.jsMatch?.(isDark, state, breakpoints) ?? false;
|
|
716
757
|
}
|
|
717
758
|
|
|
718
|
-
// src/core/
|
|
759
|
+
// src/core/resolvers/color.ts
|
|
719
760
|
function resolveColor(value, colors, isArbitrary) {
|
|
720
761
|
if (isArbitrary) return value;
|
|
721
762
|
const slashIdx = value.indexOf("/");
|
|
722
763
|
const colorPart = slashIdx > 0 ? value.slice(0, slashIdx) : value;
|
|
723
764
|
const opacityPart = slashIdx > 0 ? value.slice(slashIdx + 1) : null;
|
|
724
765
|
let hex = null;
|
|
725
|
-
if (colorPart
|
|
766
|
+
if (colorPart.startsWith("[") && colorPart.endsWith("]")) {
|
|
767
|
+
hex = colorPart.slice(1, -1);
|
|
768
|
+
} else if (colorPart in colors) {
|
|
726
769
|
const entry = colors[colorPart];
|
|
727
770
|
if (typeof entry === "string") hex = entry;
|
|
728
771
|
else if (typeof entry === "object" && "6" in entry) hex = entry["6"];
|
|
@@ -787,6 +830,86 @@ function withOpacityVar(color, varName) {
|
|
|
787
830
|
const [r, g, b] = rgb;
|
|
788
831
|
return `rgba(${r},${g},${b},var(${varName},1))`;
|
|
789
832
|
}
|
|
833
|
+
var colorResolvers = {
|
|
834
|
+
// ── Background ─────────────────────────────────────────────────────────────
|
|
835
|
+
bg: ({ value, isArbitrary }, { colors }) => {
|
|
836
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
837
|
+
if (!color) return null;
|
|
838
|
+
return { backgroundColor: getEffectiveIsWeb() ? withOpacityVar(color, "--bg-opacity") : color };
|
|
839
|
+
},
|
|
840
|
+
"bg-opacity": ({ value, isArbitrary }, _) => {
|
|
841
|
+
if (!getEffectiveIsWeb()) return null;
|
|
842
|
+
const n = parseFloat(value);
|
|
843
|
+
if (isNaN(n)) return null;
|
|
844
|
+
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
845
|
+
return { "--bg-opacity": v };
|
|
846
|
+
},
|
|
847
|
+
// ── Background gradient (CSS variable gradient stops, web-only) ──────────
|
|
848
|
+
"bg-gradient-to": ({ value }) => {
|
|
849
|
+
if (!getEffectiveIsWeb()) return null;
|
|
850
|
+
const directions = {
|
|
851
|
+
t: "to top",
|
|
852
|
+
tr: "to top right",
|
|
853
|
+
r: "to right",
|
|
854
|
+
br: "to bottom right",
|
|
855
|
+
b: "to bottom",
|
|
856
|
+
bl: "to bottom left",
|
|
857
|
+
l: "to left",
|
|
858
|
+
tl: "to top left"
|
|
859
|
+
};
|
|
860
|
+
const dir = directions[value];
|
|
861
|
+
if (!dir) return null;
|
|
862
|
+
return {
|
|
863
|
+
backgroundImage: `linear-gradient(${dir}, var(--kb-gradient-from, transparent), var(--kb-gradient-stops, transparent))`
|
|
864
|
+
};
|
|
865
|
+
},
|
|
866
|
+
from: ({ value, isArbitrary }, { colors }) => {
|
|
867
|
+
if (!getEffectiveIsWeb()) return null;
|
|
868
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
869
|
+
if (!color) return null;
|
|
870
|
+
return {
|
|
871
|
+
"--kb-gradient-from": color,
|
|
872
|
+
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-to, transparent)`
|
|
873
|
+
};
|
|
874
|
+
},
|
|
875
|
+
via: ({ value, isArbitrary }, { colors }) => {
|
|
876
|
+
if (!getEffectiveIsWeb()) return null;
|
|
877
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
878
|
+
if (!color) return null;
|
|
879
|
+
return {
|
|
880
|
+
"--kb-gradient-via": color,
|
|
881
|
+
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-via), var(--kb-gradient-to, transparent)`
|
|
882
|
+
};
|
|
883
|
+
},
|
|
884
|
+
to: ({ value, isArbitrary }, { colors }) => {
|
|
885
|
+
if (!getEffectiveIsWeb()) return null;
|
|
886
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
887
|
+
if (!color) return null;
|
|
888
|
+
return { "--kb-gradient-to": color };
|
|
889
|
+
},
|
|
890
|
+
// ── Tint color (native-only, for Image and icon components) ──────────────
|
|
891
|
+
tint: ({ value, isArbitrary }, { colors }) => {
|
|
892
|
+
if (getEffectiveIsWeb()) return null;
|
|
893
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
894
|
+
return color ? { tintColor: color } : null;
|
|
895
|
+
},
|
|
896
|
+
// ── Caret color (web-only) ────────────────────────────────────────────────
|
|
897
|
+
caret: ({ value, isArbitrary }, { colors }) => {
|
|
898
|
+
if (!getEffectiveIsWeb()) return null;
|
|
899
|
+
if (value === "auto" || value === "transparent") return { caretColor: value };
|
|
900
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
901
|
+
return color ? { caretColor: color } : null;
|
|
902
|
+
},
|
|
903
|
+
// ── Accent color (web-only) ───────────────────────────────────────────────
|
|
904
|
+
accent: ({ value, isArbitrary }, { colors }) => {
|
|
905
|
+
if (!getEffectiveIsWeb()) return null;
|
|
906
|
+
if (value === "auto") return { accentColor: "auto" };
|
|
907
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
908
|
+
return color ? { accentColor: color } : null;
|
|
909
|
+
}
|
|
910
|
+
};
|
|
911
|
+
|
|
912
|
+
// src/core/resolvers/spacing.ts
|
|
790
913
|
function resolveSpacing(value, negative, spacing, isArbitrary) {
|
|
791
914
|
if (isArbitrary) {
|
|
792
915
|
const resolved = getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
@@ -819,379 +942,11 @@ function resolveSizing(value, spacing, isArbitrary) {
|
|
|
819
942
|
}
|
|
820
943
|
return null;
|
|
821
944
|
}
|
|
822
|
-
function
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
}
|
|
827
|
-
function resolveFontSize(value, fontSizes, isArbitrary) {
|
|
828
|
-
if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
829
|
-
return fontSizes[value] ?? null;
|
|
830
|
-
}
|
|
831
|
-
var FILTER_COMPOSE = "var(--kb-blur,) var(--kb-brightness,) var(--kb-contrast,) var(--kb-grayscale,) var(--kb-hue-rotate,) var(--kb-invert,) var(--kb-saturate,) var(--kb-sepia,) var(--kb-drop-shadow,)";
|
|
832
|
-
var BACKDROP_FILTER_COMPOSE = "var(--kb-backdrop-blur,) var(--kb-backdrop-brightness,) var(--kb-backdrop-contrast,) var(--kb-backdrop-grayscale,) var(--kb-backdrop-hue-rotate,) var(--kb-backdrop-invert,) var(--kb-backdrop-opacity,) var(--kb-backdrop-saturate,) var(--kb-backdrop-sepia,)";
|
|
833
|
-
var _standalone = null;
|
|
834
|
-
function buildStandalone() {
|
|
835
|
-
const web = getEffectiveIsWeb();
|
|
836
|
-
return {
|
|
837
|
-
// Display
|
|
838
|
-
// React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
|
|
839
|
-
// a no-op normally, but is needed to re-show an element that was hidden via `hidden`.
|
|
840
|
-
// `grid`, `contents`, `flow-root` have no native equivalent and stay null there.
|
|
841
|
-
// The inline-* family (inline, inline-block, inline-flex, inline-grid) falls back
|
|
842
|
-
// to 'flex' on native instead — like plain `flex`, this is a no-op most of the
|
|
843
|
-
// time, but without it these utilities couldn't re-show a `hidden` element on
|
|
844
|
-
// native either (null → no style applied → still display:'none').
|
|
845
|
-
flex: { display: "flex" },
|
|
846
|
-
block: web ? { display: "block" } : null,
|
|
847
|
-
"inline-block": { display: web ? "inline-block" : "flex" },
|
|
848
|
-
inline: { display: web ? "inline" : "flex" },
|
|
849
|
-
grid: web ? { display: "grid" } : null,
|
|
850
|
-
grd: web ? { display: "grid" } : null,
|
|
851
|
-
"inline-flex": { display: web ? "inline-flex" : "flex" },
|
|
852
|
-
"inline-grid": { display: web ? "inline-grid" : "flex" },
|
|
853
|
-
hidden: { display: "none" },
|
|
854
|
-
contents: web ? { display: "contents" } : null,
|
|
855
|
-
"flow-root": web ? { display: "flow-root" } : null,
|
|
856
|
-
// Flex direction (both web and native)
|
|
857
|
-
"flex-row": { flexDirection: "row" },
|
|
858
|
-
"flex-col": { flexDirection: "column" },
|
|
859
|
-
"flex-row-reverse": { flexDirection: "row-reverse" },
|
|
860
|
-
"flex-col-reverse": { flexDirection: "column-reverse" },
|
|
861
|
-
// Flex wrap (both)
|
|
862
|
-
"flex-wrap": { flexWrap: "wrap" },
|
|
863
|
-
"flex-wrap-reverse": { flexWrap: "wrap-reverse" },
|
|
864
|
-
"flex-nowrap": { flexWrap: "nowrap" },
|
|
865
|
-
// Flex grow / shrink (both)
|
|
866
|
-
"flex-grow": { flexGrow: 1 },
|
|
867
|
-
"flex-grow-0": { flexGrow: 0 },
|
|
868
|
-
"flex-shrink": { flexShrink: 1 },
|
|
869
|
-
"flex-shrink-0": { flexShrink: 0 },
|
|
870
|
-
// Align items (both)
|
|
871
|
-
"items-start": { alignItems: "flex-start" },
|
|
872
|
-
"items-end": { alignItems: "flex-end" },
|
|
873
|
-
"items-center": { alignItems: "center" },
|
|
874
|
-
"items-baseline": { alignItems: "baseline" },
|
|
875
|
-
"items-stretch": { alignItems: "stretch" },
|
|
876
|
-
// Justify content (both)
|
|
877
|
-
"justify-start": { justifyContent: "flex-start" },
|
|
878
|
-
"justify-end": { justifyContent: "flex-end" },
|
|
879
|
-
"justify-center": { justifyContent: "center" },
|
|
880
|
-
"justify-between": { justifyContent: "space-between" },
|
|
881
|
-
"justify-around": { justifyContent: "space-around" },
|
|
882
|
-
"justify-evenly": { justifyContent: "space-evenly" },
|
|
883
|
-
// Align content (both)
|
|
884
|
-
"content-start": { alignContent: "flex-start" },
|
|
885
|
-
"content-end": { alignContent: "flex-end" },
|
|
886
|
-
"content-center": { alignContent: "center" },
|
|
887
|
-
"content-between": { alignContent: "space-between" },
|
|
888
|
-
"content-around": { alignContent: "space-around" },
|
|
889
|
-
"content-evenly": { alignContent: "space-evenly" },
|
|
890
|
-
"content-stretch": { alignContent: "stretch" },
|
|
891
|
-
// Align self (both)
|
|
892
|
-
"self-auto": { alignSelf: "auto" },
|
|
893
|
-
"self-start": { alignSelf: "flex-start" },
|
|
894
|
-
"self-end": { alignSelf: "flex-end" },
|
|
895
|
-
"self-center": { alignSelf: "center" },
|
|
896
|
-
"self-stretch": { alignSelf: "stretch" },
|
|
897
|
-
"self-baseline": { alignSelf: "baseline" },
|
|
898
|
-
// Text align (both)
|
|
899
|
-
"text-left": { textAlign: "left" },
|
|
900
|
-
"text-right": { textAlign: "right" },
|
|
901
|
-
"text-center": { textAlign: "center" },
|
|
902
|
-
"text-justify": { textAlign: "justify" },
|
|
903
|
-
// Font weight shortcuts (both)
|
|
904
|
-
"font-thin": { fontWeight: "100" },
|
|
905
|
-
"font-extralight": { fontWeight: "200" },
|
|
906
|
-
"font-light": { fontWeight: "300" },
|
|
907
|
-
"font-normal": { fontWeight: "400" },
|
|
908
|
-
"font-medium": { fontWeight: "500" },
|
|
909
|
-
"font-semibold": { fontWeight: "600" },
|
|
910
|
-
"font-bold": { fontWeight: "700" },
|
|
911
|
-
"font-extrabold": { fontWeight: "800" },
|
|
912
|
-
"font-black": { fontWeight: "900" },
|
|
913
|
-
// Text decoration (overline is web-only)
|
|
914
|
-
underline: { textDecorationLine: "underline" },
|
|
915
|
-
overline: web ? { textDecorationLine: "overline" } : null,
|
|
916
|
-
"line-through": { textDecorationLine: "line-through" },
|
|
917
|
-
"no-underline": { textDecorationLine: "none" },
|
|
918
|
-
// Text transform (both)
|
|
919
|
-
uppercase: { textTransform: "uppercase" },
|
|
920
|
-
lowercase: { textTransform: "lowercase" },
|
|
921
|
-
capitalize: { textTransform: "capitalize" },
|
|
922
|
-
"normal-case": { textTransform: "none" },
|
|
923
|
-
// Font style (both)
|
|
924
|
-
italic: { fontStyle: "italic" },
|
|
925
|
-
"non-italic": { fontStyle: "normal" },
|
|
926
|
-
// Position (fixed/sticky/static are web-only; RN only supports relative/absolute)
|
|
927
|
-
relative: { position: "relative" },
|
|
928
|
-
absolute: { position: "absolute" },
|
|
929
|
-
fixed: web ? { position: "fixed" } : null,
|
|
930
|
-
sticky: web ? { position: "sticky" } : null,
|
|
931
|
-
static: web ? { position: "static" } : null,
|
|
932
|
-
// Visibility (no `visibility` prop on native; use opacity instead)
|
|
933
|
-
visible: web ? { visibility: "visible" } : null,
|
|
934
|
-
invisible: web ? { visibility: "hidden" } : { opacity: 0 },
|
|
935
|
-
// Overflow (RN supports 'hidden' | 'visible' | 'scroll'; not 'auto')
|
|
936
|
-
"overflow-hidden": { overflow: "hidden" },
|
|
937
|
-
"overflow-visible": { overflow: "visible" },
|
|
938
|
-
"overflow-scroll": { overflow: "scroll" },
|
|
939
|
-
"overflow-auto": web ? { overflow: "auto" } : { overflow: "scroll" },
|
|
940
|
-
// overflowX / overflowY are web-only
|
|
941
|
-
"overflow-x-hidden": web ? { overflowX: "hidden" } : null,
|
|
942
|
-
"overflow-x-scroll": web ? { overflowX: "scroll" } : null,
|
|
943
|
-
"overflow-x-auto": web ? { overflowX: "auto" } : null,
|
|
944
|
-
"overflow-y-hidden": web ? { overflowY: "hidden" } : null,
|
|
945
|
-
"overflow-y-scroll": web ? { overflowY: "scroll" } : null,
|
|
946
|
-
"overflow-y-auto": web ? { overflowY: "auto" } : null,
|
|
947
|
-
// Object fit (web-only; use resizeMode prop on RN Image)
|
|
948
|
-
"object-contain": web ? { objectFit: "contain" } : null,
|
|
949
|
-
"object-cover": web ? { objectFit: "cover" } : null,
|
|
950
|
-
"object-fill": web ? { objectFit: "fill" } : null,
|
|
951
|
-
"object-none": web ? { objectFit: "none" } : null,
|
|
952
|
-
"object-scale-down": web ? { objectFit: "scale-down" } : null,
|
|
953
|
-
// Border style (both)
|
|
954
|
-
"border-solid": { borderStyle: "solid" },
|
|
955
|
-
"border-dashed": { borderStyle: "dashed" },
|
|
956
|
-
"border-dotted": { borderStyle: "dotted" },
|
|
957
|
-
"border-none": { borderWidth: 0 },
|
|
958
|
-
// Border sides default width (both)
|
|
959
|
-
"border-t": { borderTopWidth: 1 },
|
|
960
|
-
"border-r": { borderRightWidth: 1 },
|
|
961
|
-
"border-b": { borderBottomWidth: 1 },
|
|
962
|
-
"border-l": { borderLeftWidth: 1 },
|
|
963
|
-
// Cursor (web-only)
|
|
964
|
-
"cursor-auto": web ? { cursor: "auto" } : null,
|
|
965
|
-
"cursor-default": web ? { cursor: "default" } : null,
|
|
966
|
-
"cursor-pointer": web ? { cursor: "pointer" } : null,
|
|
967
|
-
"cursor-wait": web ? { cursor: "wait" } : null,
|
|
968
|
-
"cursor-text": web ? { cursor: "text" } : null,
|
|
969
|
-
"cursor-move": web ? { cursor: "move" } : null,
|
|
970
|
-
"cursor-not-allowed": web ? { cursor: "not-allowed" } : null,
|
|
971
|
-
// User select (web-only)
|
|
972
|
-
"select-none": web ? { userSelect: "none" } : null,
|
|
973
|
-
"select-text": web ? { userSelect: "text" } : null,
|
|
974
|
-
"select-all": web ? { userSelect: "all" } : null,
|
|
975
|
-
"select-auto": web ? { userSelect: "auto" } : null,
|
|
976
|
-
// Pointer events (both)
|
|
977
|
-
"pointer-events-none": { pointerEvents: "none" },
|
|
978
|
-
"pointer-events-auto": { pointerEvents: "auto" },
|
|
979
|
-
// Whitespace (web-only; RN Text uses numberOfLines prop instead)
|
|
980
|
-
"whitespace-normal": web ? { whiteSpace: "normal" } : null,
|
|
981
|
-
"whitespace-nowrap": web ? { whiteSpace: "nowrap" } : null,
|
|
982
|
-
"whitespace-pre": web ? { whiteSpace: "pre" } : null,
|
|
983
|
-
"whitespace-pre-wrap": web ? { whiteSpace: "pre-wrap" } : null,
|
|
984
|
-
"whitespace-pre-line": web ? { whiteSpace: "pre-line" } : null,
|
|
985
|
-
// Word break (web-only)
|
|
986
|
-
"break-normal": web ? { overflowWrap: "normal", wordBreak: "normal" } : null,
|
|
987
|
-
"break-words": web ? { overflowWrap: "break-word" } : null,
|
|
988
|
-
"break-all": web ? { wordBreak: "break-all" } : null,
|
|
989
|
-
// Misc web-only
|
|
990
|
-
truncate: web ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null,
|
|
991
|
-
"box-border": web ? { boxSizing: "border-box" } : null,
|
|
992
|
-
"box-content": web ? { boxSizing: "content-box" } : null,
|
|
993
|
-
"appearance-none": web ? { appearance: "none" } : null,
|
|
994
|
-
"outline-none": web ? { outline: "none", outlineOffset: "0" } : null,
|
|
995
|
-
outline: web ? { outline: "2px solid transparent", outlineOffset: "2px" } : null,
|
|
996
|
-
resize: web ? { resize: "both" } : null,
|
|
997
|
-
"resize-none": web ? { resize: "none" } : null,
|
|
998
|
-
"resize-y": web ? { resize: "vertical" } : null,
|
|
999
|
-
"resize-x": web ? { resize: "horizontal" } : null,
|
|
1000
|
-
antialiased: web ? { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale" } : null,
|
|
1001
|
-
"subpixel-antialiased": web ? { WebkitFontSmoothing: "subpixel-antialiased", MozOsxFontSmoothing: "auto" } : null,
|
|
1002
|
-
"overflow-ellipsis": web ? { textOverflow: "ellipsis" } : null,
|
|
1003
|
-
"sr-only": web ? {
|
|
1004
|
-
position: "absolute",
|
|
1005
|
-
width: 1,
|
|
1006
|
-
height: 1,
|
|
1007
|
-
padding: 0,
|
|
1008
|
-
margin: -1,
|
|
1009
|
-
overflow: "hidden",
|
|
1010
|
-
clip: "rect(0,0,0,0)",
|
|
1011
|
-
whiteSpace: "nowrap",
|
|
1012
|
-
border: 0
|
|
1013
|
-
} : null,
|
|
1014
|
-
"not-sr-only": web ? {
|
|
1015
|
-
position: "static",
|
|
1016
|
-
width: "auto",
|
|
1017
|
-
height: "auto",
|
|
1018
|
-
padding: 0,
|
|
1019
|
-
margin: 0,
|
|
1020
|
-
overflow: "visible",
|
|
1021
|
-
clip: "auto",
|
|
1022
|
-
whiteSpace: "normal"
|
|
1023
|
-
} : null,
|
|
1024
|
-
// Lists (web-only)
|
|
1025
|
-
"list-none": web ? { listStyleType: "none" } : null,
|
|
1026
|
-
"list-disc": web ? { listStyleType: "disc" } : null,
|
|
1027
|
-
"list-decimal": web ? { listStyleType: "decimal" } : null,
|
|
1028
|
-
// Background clip (web-only)
|
|
1029
|
-
"bg-clip-border": web ? { backgroundClip: "border-box" } : null,
|
|
1030
|
-
"bg-clip-padding": web ? { backgroundClip: "padding-box" } : null,
|
|
1031
|
-
"bg-clip-content": web ? { backgroundClip: "content-box" } : null,
|
|
1032
|
-
"bg-clip-text": web ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
|
|
1033
|
-
// Background image
|
|
1034
|
-
"bg-none": web ? { backgroundImage: "none" } : null,
|
|
1035
|
-
// Background size (web-only)
|
|
1036
|
-
"bg-auto": web ? { backgroundSize: "auto" } : null,
|
|
1037
|
-
"bg-cover": web ? { backgroundSize: "cover" } : null,
|
|
1038
|
-
"bg-contain": web ? { backgroundSize: "contain" } : null,
|
|
1039
|
-
// Background position (web-only)
|
|
1040
|
-
"bg-center": web ? { backgroundPosition: "center" } : null,
|
|
1041
|
-
"bg-top": web ? { backgroundPosition: "top" } : null,
|
|
1042
|
-
"bg-bottom": web ? { backgroundPosition: "bottom" } : null,
|
|
1043
|
-
"bg-left": web ? { backgroundPosition: "left" } : null,
|
|
1044
|
-
"bg-right": web ? { backgroundPosition: "right" } : null,
|
|
1045
|
-
"bg-left-top": web ? { backgroundPosition: "left top" } : null,
|
|
1046
|
-
"bg-left-bottom": web ? { backgroundPosition: "left bottom" } : null,
|
|
1047
|
-
"bg-right-top": web ? { backgroundPosition: "right top" } : null,
|
|
1048
|
-
"bg-right-bottom": web ? { backgroundPosition: "right bottom" } : null,
|
|
1049
|
-
// Background repeat (web-only)
|
|
1050
|
-
"bg-repeat": web ? { backgroundRepeat: "repeat" } : null,
|
|
1051
|
-
"bg-no-repeat": web ? { backgroundRepeat: "no-repeat" } : null,
|
|
1052
|
-
"bg-repeat-x": web ? { backgroundRepeat: "repeat-x" } : null,
|
|
1053
|
-
"bg-repeat-y": web ? { backgroundRepeat: "repeat-y" } : null,
|
|
1054
|
-
"bg-repeat-round": web ? { backgroundRepeat: "round" } : null,
|
|
1055
|
-
"bg-repeat-space": web ? { backgroundRepeat: "space" } : null,
|
|
1056
|
-
// Background attachment (web-only)
|
|
1057
|
-
"bg-fixed": web ? { backgroundAttachment: "fixed" } : null,
|
|
1058
|
-
"bg-local": web ? { backgroundAttachment: "local" } : null,
|
|
1059
|
-
"bg-scroll": web ? { backgroundAttachment: "scroll" } : null,
|
|
1060
|
-
// Object position (web-only)
|
|
1061
|
-
"object-center": web ? { objectPosition: "center" } : null,
|
|
1062
|
-
"object-top": web ? { objectPosition: "top" } : null,
|
|
1063
|
-
"object-bottom": web ? { objectPosition: "bottom" } : null,
|
|
1064
|
-
"object-left": web ? { objectPosition: "left" } : null,
|
|
1065
|
-
"object-right": web ? { objectPosition: "right" } : null,
|
|
1066
|
-
"object-left-top": web ? { objectPosition: "left top" } : null,
|
|
1067
|
-
"object-left-bottom": web ? { objectPosition: "left bottom" } : null,
|
|
1068
|
-
"object-right-top": web ? { objectPosition: "right top" } : null,
|
|
1069
|
-
"object-right-bottom": web ? { objectPosition: "right bottom" } : null,
|
|
1070
|
-
// Table (web-only)
|
|
1071
|
-
table: web ? { display: "table" } : null,
|
|
1072
|
-
"table-auto": web ? { tableLayout: "auto" } : null,
|
|
1073
|
-
"table-fixed": web ? { tableLayout: "fixed" } : null,
|
|
1074
|
-
"caption-top": web ? { captionSide: "top" } : null,
|
|
1075
|
-
"caption-bottom": web ? { captionSide: "bottom" } : null,
|
|
1076
|
-
"border-collapse": web ? { borderCollapse: "collapse" } : null,
|
|
1077
|
-
"border-separate": web ? { borderCollapse: "separate" } : null,
|
|
1078
|
-
// List style position (web-only)
|
|
1079
|
-
"list-inside": web ? { listStylePosition: "inside" } : null,
|
|
1080
|
-
"list-outside": web ? { listStylePosition: "outside" } : null,
|
|
1081
|
-
// Font variant numeric (web-only)
|
|
1082
|
-
"normal-nums": web ? { fontVariantNumeric: "normal" } : null,
|
|
1083
|
-
ordinal: web ? { fontVariantNumeric: "ordinal" } : null,
|
|
1084
|
-
"slashed-zero": web ? { fontVariantNumeric: "slashed-zero" } : null,
|
|
1085
|
-
"lining-nums": web ? { fontVariantNumeric: "lining-nums" } : null,
|
|
1086
|
-
"oldstyle-nums": web ? { fontVariantNumeric: "oldstyle-nums" } : null,
|
|
1087
|
-
"proportional-nums": web ? { fontVariantNumeric: "proportional-nums" } : null,
|
|
1088
|
-
"tabular-nums": web ? { fontVariantNumeric: "tabular-nums" } : null,
|
|
1089
|
-
"diagonal-fractions": web ? { fontVariantNumeric: "diagonal-fractions" } : null,
|
|
1090
|
-
"stacked-fractions": web ? { fontVariantNumeric: "stacked-fractions" } : null,
|
|
1091
|
-
// Isolation (web-only)
|
|
1092
|
-
isolate: web ? { isolation: "isolate" } : null,
|
|
1093
|
-
"isolation-auto": web ? { isolation: "auto" } : null,
|
|
1094
|
-
// Backface visibility (both iOS and Android)
|
|
1095
|
-
"backface-visible": { backfaceVisibility: "visible" },
|
|
1096
|
-
"backface-hidden": { backfaceVisibility: "hidden" },
|
|
1097
|
-
// CSS filters — standalone = default/full effect (web-only)
|
|
1098
|
-
grayscale: web ? { "--kb-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
|
|
1099
|
-
invert: web ? { "--kb-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
|
|
1100
|
-
sepia: web ? { "--kb-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
|
|
1101
|
-
// Divide none
|
|
1102
|
-
"divide-none": web ? { __divideX: 0, __divideY: 0 } : null,
|
|
1103
|
-
// Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
|
|
1104
|
-
group: web ? {} : null,
|
|
1105
|
-
peer: web ? {} : null,
|
|
1106
|
-
// Text-wrap (web-only)
|
|
1107
|
-
"text-wrap": web ? { textWrap: "wrap" } : null,
|
|
1108
|
-
"text-nowrap": web ? { textWrap: "nowrap" } : null,
|
|
1109
|
-
"text-balance": web ? { textWrap: "balance" } : null,
|
|
1110
|
-
"text-pretty": web ? { textWrap: "pretty" } : null,
|
|
1111
|
-
// Screen sizing — dvw/dvh (dynamic viewport units) instead of vw/vh: on mobile
|
|
1112
|
-
// browsers, vh/vw are pinned to the LARGEST viewport size (address bar hidden),
|
|
1113
|
-
// so `h-screen` overflows behind the address bar when it's shown. dvh/dvw track
|
|
1114
|
-
// the actual visible viewport as browser chrome shows/hides. Desktop behavior
|
|
1115
|
-
// is unchanged since there's no dynamic chrome to account for.
|
|
1116
|
-
// (vw/dvw values are web-only; vh/dvh values work cross-platform via spacing scale for h-*)
|
|
1117
|
-
"w-screen": web ? { width: "100dvw" } : null,
|
|
1118
|
-
"min-h-screen": { minHeight: "100dvh" },
|
|
1119
|
-
"max-h-screen": { maxHeight: "100dvh" },
|
|
1120
|
-
"min-w-screen": web ? { minWidth: "100dvw" } : null,
|
|
1121
|
-
"max-w-screen": web ? { maxWidth: "100dvw" } : null,
|
|
1122
|
-
// max-w named container sizes (mirrors Tailwind's container scale)
|
|
1123
|
-
"max-w-none": { maxWidth: "none" },
|
|
1124
|
-
"max-w-xs": { maxWidth: 320 },
|
|
1125
|
-
"max-w-sm": { maxWidth: 384 },
|
|
1126
|
-
"max-w-md": { maxWidth: 448 },
|
|
1127
|
-
"max-w-lg": { maxWidth: 512 },
|
|
1128
|
-
"max-w-xl": { maxWidth: 576 },
|
|
1129
|
-
"max-w-2xl": { maxWidth: 672 },
|
|
1130
|
-
"max-w-3xl": { maxWidth: 768 },
|
|
1131
|
-
"max-w-4xl": { maxWidth: 896 },
|
|
1132
|
-
"max-w-5xl": { maxWidth: 1024 },
|
|
1133
|
-
"max-w-6xl": { maxWidth: 1152 },
|
|
1134
|
-
"max-w-7xl": { maxWidth: 1280 },
|
|
1135
|
-
"max-w-prose": web ? { maxWidth: "65ch" } : null,
|
|
1136
|
-
// Extended cursors (web-only)
|
|
1137
|
-
"cursor-grab": web ? { cursor: "grab" } : null,
|
|
1138
|
-
"cursor-grabbing": web ? { cursor: "grabbing" } : null,
|
|
1139
|
-
"cursor-zoom-in": web ? { cursor: "zoom-in" } : null,
|
|
1140
|
-
"cursor-zoom-out": web ? { cursor: "zoom-out" } : null,
|
|
1141
|
-
"cursor-crosshair": web ? { cursor: "crosshair" } : null,
|
|
1142
|
-
"cursor-help": web ? { cursor: "help" } : null,
|
|
1143
|
-
"cursor-none": web ? { cursor: "none" } : null,
|
|
1144
|
-
// Overflow clip (web-only)
|
|
1145
|
-
"overflow-clip": web ? { overflow: "clip" } : null,
|
|
1146
|
-
"overflow-x-clip": web ? { overflowX: "clip" } : null,
|
|
1147
|
-
"overflow-y-clip": web ? { overflowY: "clip" } : null,
|
|
1148
|
-
// Scroll behavior (web-only)
|
|
1149
|
-
"scroll-smooth": web ? { scrollBehavior: "smooth" } : null,
|
|
1150
|
-
"scroll-auto": web ? { scrollBehavior: "auto" } : null,
|
|
1151
|
-
// Float (web-only)
|
|
1152
|
-
"float-left": web ? { float: "left" } : null,
|
|
1153
|
-
"float-right": web ? { float: "right" } : null,
|
|
1154
|
-
"float-start": web ? { float: "inline-start" } : null,
|
|
1155
|
-
"float-end": web ? { float: "inline-end" } : null,
|
|
1156
|
-
"float-none": web ? { float: "none" } : null,
|
|
1157
|
-
// Clear (web-only)
|
|
1158
|
-
"clear-left": web ? { clear: "left" } : null,
|
|
1159
|
-
"clear-right": web ? { clear: "right" } : null,
|
|
1160
|
-
"clear-both": web ? { clear: "both" } : null,
|
|
1161
|
-
"clear-start": web ? { clear: "inline-start" } : null,
|
|
1162
|
-
"clear-end": web ? { clear: "inline-end" } : null,
|
|
1163
|
-
"clear-none": web ? { clear: "none" } : null,
|
|
1164
|
-
// Vertical align (web-only)
|
|
1165
|
-
"align-baseline": web ? { verticalAlign: "baseline" } : null,
|
|
1166
|
-
"align-top": web ? { verticalAlign: "top" } : null,
|
|
1167
|
-
"align-middle": web ? { verticalAlign: "middle" } : null,
|
|
1168
|
-
"align-bottom": web ? { verticalAlign: "bottom" } : null,
|
|
1169
|
-
"align-text-top": web ? { verticalAlign: "text-top" } : null,
|
|
1170
|
-
"align-text-bottom": web ? { verticalAlign: "text-bottom" } : null,
|
|
1171
|
-
"align-sub": web ? { verticalAlign: "sub" } : null,
|
|
1172
|
-
"align-super": web ? { verticalAlign: "super" } : null,
|
|
1173
|
-
// Touch action (web-only)
|
|
1174
|
-
"touch-auto": web ? { touchAction: "auto" } : null,
|
|
1175
|
-
"touch-none": web ? { touchAction: "none" } : null,
|
|
1176
|
-
"touch-pan-x": web ? { touchAction: "pan-x" } : null,
|
|
1177
|
-
"touch-pan-y": web ? { touchAction: "pan-y" } : null,
|
|
1178
|
-
"touch-pan-left": web ? { touchAction: "pan-left" } : null,
|
|
1179
|
-
"touch-pan-right": web ? { touchAction: "pan-right" } : null,
|
|
1180
|
-
"touch-pan-up": web ? { touchAction: "pan-up" } : null,
|
|
1181
|
-
"touch-pan-down": web ? { touchAction: "pan-down" } : null,
|
|
1182
|
-
"touch-pinch-zoom": web ? { touchAction: "pinch-zoom" } : null,
|
|
1183
|
-
"touch-manipulation": web ? { touchAction: "manipulation" } : null
|
|
1184
|
-
};
|
|
1185
|
-
}
|
|
1186
|
-
function getStandalone() {
|
|
1187
|
-
if (!_standalone) _standalone = buildStandalone();
|
|
1188
|
-
return _standalone;
|
|
1189
|
-
}
|
|
1190
|
-
function makeSpacingResolver(prop) {
|
|
1191
|
-
return ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1192
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1193
|
-
return v !== null ? { [prop]: v } : null;
|
|
1194
|
-
};
|
|
945
|
+
function makeSpacingResolver(prop) {
|
|
946
|
+
return ({ value, negative, isArbitrary }, { spacing }) => {
|
|
947
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
948
|
+
return v !== null ? { [prop]: v } : null;
|
|
949
|
+
};
|
|
1195
950
|
}
|
|
1196
951
|
var PADDING_MARGIN_PROPS = {
|
|
1197
952
|
p: "padding",
|
|
@@ -1209,105 +964,11 @@ var PADDING_MARGIN_PROPS = {
|
|
|
1209
964
|
mb: "marginBottom",
|
|
1210
965
|
ml: "marginLeft"
|
|
1211
966
|
};
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
if (typeof w2 === "number") return { [widthProp]: w2 };
|
|
1218
|
-
return { [colorProp]: value };
|
|
1219
|
-
}
|
|
1220
|
-
const color = resolveColor(value, colors, false);
|
|
1221
|
-
if (color) return { [colorProp]: color };
|
|
1222
|
-
const w = borderWidth[value];
|
|
1223
|
-
return w !== void 0 ? { [widthProp]: w } : null;
|
|
1224
|
-
};
|
|
1225
|
-
}
|
|
1226
|
-
var BORDER_SIDE_PROPS = {
|
|
1227
|
-
"border-t": ["borderTopWidth", "borderTopColor"],
|
|
1228
|
-
"border-r": ["borderRightWidth", "borderRightColor"],
|
|
1229
|
-
"border-b": ["borderBottomWidth", "borderBottomColor"],
|
|
1230
|
-
"border-l": ["borderLeftWidth", "borderLeftColor"]
|
|
1231
|
-
};
|
|
1232
|
-
function keyframeDeclToCSS(decl) {
|
|
1233
|
-
return Object.entries(decl).map(([prop, val]) => `${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${val}`).join("; ");
|
|
1234
|
-
}
|
|
1235
|
-
function buildKeyframeCSS(name, steps) {
|
|
1236
|
-
const body = Object.entries(steps).map(([selector, decl]) => `${selector} { ${keyframeDeclToCSS(decl)} }`).join(" ");
|
|
1237
|
-
return `@keyframes ${name} { ${body} }`;
|
|
1238
|
-
}
|
|
1239
|
-
var BUILTIN_ANIMATIONS = {
|
|
1240
|
-
none: { animation: "none" },
|
|
1241
|
-
spin: {
|
|
1242
|
-
animation: "kb-spin 1s linear infinite",
|
|
1243
|
-
__keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
|
|
1244
|
-
},
|
|
1245
|
-
ping: {
|
|
1246
|
-
animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
|
|
1247
|
-
__keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
|
|
1248
|
-
},
|
|
1249
|
-
pulse: {
|
|
1250
|
-
animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
|
|
1251
|
-
__keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
|
|
1252
|
-
},
|
|
1253
|
-
bounce: {
|
|
1254
|
-
animation: "kb-bounce 1s infinite",
|
|
1255
|
-
__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) } }"
|
|
1256
|
-
}
|
|
1257
|
-
};
|
|
1258
|
-
function buildAnimationValue(animation, keyframes) {
|
|
1259
|
-
const words = animation.trim().split(/\s+/);
|
|
1260
|
-
const name = words[0];
|
|
1261
|
-
if (!name) return { animation };
|
|
1262
|
-
const builtin = BUILTIN_ANIMATIONS[name];
|
|
1263
|
-
if (builtin?.__keyframe) {
|
|
1264
|
-
const kbName = builtin.animation.split(/\s+/, 1)[0];
|
|
1265
|
-
return { animation: [kbName, ...words.slice(1)].join(" "), __keyframe: builtin.__keyframe };
|
|
1266
|
-
}
|
|
1267
|
-
const steps = keyframes?.[name];
|
|
1268
|
-
return steps ? { animation, __keyframe: buildKeyframeCSS(name, steps) } : { animation };
|
|
1269
|
-
}
|
|
1270
|
-
var RESOLVERS = {
|
|
1271
|
-
// ── Background ─────────────────────────────────────────────────────────────
|
|
1272
|
-
bg: ({ value, isArbitrary }, { colors }) => {
|
|
1273
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1274
|
-
if (!color) return null;
|
|
1275
|
-
return { backgroundColor: getEffectiveIsWeb() ? withOpacityVar(color, "--bg-opacity") : color };
|
|
1276
|
-
},
|
|
1277
|
-
"bg-opacity": ({ value, isArbitrary }, _) => {
|
|
1278
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1279
|
-
const n = parseFloat(value);
|
|
1280
|
-
if (isNaN(n)) return null;
|
|
1281
|
-
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
1282
|
-
return { "--bg-opacity": v };
|
|
1283
|
-
},
|
|
1284
|
-
// ── Text ───────────────────────────────────────────────────────────────────
|
|
1285
|
-
text: ({ value, isArbitrary }, { colors, fontSize }) => {
|
|
1286
|
-
const size = resolveFontSize(value, fontSize, false);
|
|
1287
|
-
if (!isArbitrary && size !== null) return { fontSize: size };
|
|
1288
|
-
if (isArbitrary) {
|
|
1289
|
-
if (/^\d/.test(value) || /^(calc|min|max|clamp)/.test(value)) {
|
|
1290
|
-
return { fontSize: getEffectiveIsWeb() ? value : toNativeValue(value) };
|
|
1291
|
-
}
|
|
1292
|
-
return { color: getEffectiveIsWeb() ? withOpacityVar(value, "--text-opacity") : value };
|
|
1293
|
-
}
|
|
1294
|
-
const color = resolveColor(value, colors, false);
|
|
1295
|
-
if (!color) return null;
|
|
1296
|
-
return { color: getEffectiveIsWeb() ? withOpacityVar(color, "--text-opacity") : color };
|
|
1297
|
-
},
|
|
1298
|
-
"text-opacity": ({ value, isArbitrary }, _) => {
|
|
1299
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1300
|
-
const n = parseFloat(value);
|
|
1301
|
-
if (isNaN(n)) return null;
|
|
1302
|
-
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
1303
|
-
return { "--text-opacity": v };
|
|
1304
|
-
},
|
|
1305
|
-
// ── Padding & margin ───────────────────────────────────────────────────────
|
|
1306
|
-
// Generated below via makeSpacingResolver() — see PADDING_MARGIN_PROPS.
|
|
1307
|
-
// ── Sizing ─────────────────────────────────────────────────────────────────
|
|
1308
|
-
w: ({ value, isArbitrary }, { spacing }) => {
|
|
1309
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1310
|
-
return v !== null ? { width: v } : null;
|
|
967
|
+
var spacingResolvers = {
|
|
968
|
+
// ── Sizing ─────────────────────────────────────────────────────────────────
|
|
969
|
+
w: ({ value, isArbitrary }, { spacing }) => {
|
|
970
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
971
|
+
return v !== null ? { width: v } : null;
|
|
1311
972
|
},
|
|
1312
973
|
h: ({ value, isArbitrary }, { spacing }) => {
|
|
1313
974
|
const v = resolveSizing(value, spacing, isArbitrary);
|
|
@@ -1329,6 +990,126 @@ var RESOLVERS = {
|
|
|
1329
990
|
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1330
991
|
return v !== null ? { maxHeight: v } : null;
|
|
1331
992
|
},
|
|
993
|
+
// ── Size shorthand (sets width AND height in one utility) ────────────────
|
|
994
|
+
size: ({ value, isArbitrary }, { spacing }) => {
|
|
995
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
996
|
+
return v !== null ? { width: v, height: v } : null;
|
|
997
|
+
},
|
|
998
|
+
// ── Flex basis ─────────────────────────────────────────────────────────────
|
|
999
|
+
basis: ({ value, isArbitrary }, { spacing }) => {
|
|
1000
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1001
|
+
return v !== null ? { flexBasis: v } : null;
|
|
1002
|
+
},
|
|
1003
|
+
// ── Gap ────────────────────────────────────────────────────────────────────
|
|
1004
|
+
gap: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1005
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1006
|
+
return v !== null ? { gap: v } : null;
|
|
1007
|
+
},
|
|
1008
|
+
"gap-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1009
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1010
|
+
return v !== null ? { columnGap: v } : null;
|
|
1011
|
+
},
|
|
1012
|
+
"gap-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1013
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1014
|
+
return v !== null ? { rowGap: v } : null;
|
|
1015
|
+
},
|
|
1016
|
+
// ── Position ───────────────────────────────────────────────────────────────
|
|
1017
|
+
top: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1018
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1019
|
+
return v !== null ? { top: v } : null;
|
|
1020
|
+
},
|
|
1021
|
+
right: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1022
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1023
|
+
return v !== null ? { right: v } : null;
|
|
1024
|
+
},
|
|
1025
|
+
bottom: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1026
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1027
|
+
return v !== null ? { bottom: v } : null;
|
|
1028
|
+
},
|
|
1029
|
+
left: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1030
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1031
|
+
return v !== null ? { left: v } : null;
|
|
1032
|
+
},
|
|
1033
|
+
inset: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1034
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1035
|
+
return v !== null ? { top: v, right: v, bottom: v, left: v } : null;
|
|
1036
|
+
},
|
|
1037
|
+
"inset-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1038
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1039
|
+
return v !== null ? { left: v, right: v } : null;
|
|
1040
|
+
},
|
|
1041
|
+
"inset-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1042
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1043
|
+
return v !== null ? { top: v, bottom: v } : null;
|
|
1044
|
+
},
|
|
1045
|
+
// ── Translate ──────────────────────────────────────────────────────────────
|
|
1046
|
+
"translate-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1047
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1048
|
+
if (v === null) return null;
|
|
1049
|
+
if (getEffectiveIsWeb()) return { transform: `translateX(${typeof v === "number" ? `${v}px` : v})` };
|
|
1050
|
+
if (typeof v === "string") {
|
|
1051
|
+
const n = parseFloat(v);
|
|
1052
|
+
return isNaN(n) ? null : { transform: [{ translateX: n }] };
|
|
1053
|
+
}
|
|
1054
|
+
return { transform: [{ translateX: v }] };
|
|
1055
|
+
},
|
|
1056
|
+
"translate-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1057
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1058
|
+
if (v === null) return null;
|
|
1059
|
+
if (getEffectiveIsWeb()) return { transform: `translateY(${typeof v === "number" ? `${v}px` : v})` };
|
|
1060
|
+
if (typeof v === "string") {
|
|
1061
|
+
const n = parseFloat(v);
|
|
1062
|
+
return isNaN(n) ? null : { transform: [{ translateY: n }] };
|
|
1063
|
+
}
|
|
1064
|
+
return { transform: [{ translateY: v }] };
|
|
1065
|
+
},
|
|
1066
|
+
// ── Space between ─────────────────────────────────────────────────────────
|
|
1067
|
+
// On web: emits __spaceX/__spaceY markers → resolver generates > * + * CSS rules.
|
|
1068
|
+
// On native (RN 0.71+): uses columnGap/rowGap directly.
|
|
1069
|
+
"space-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1070
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1071
|
+
if (v === null) return null;
|
|
1072
|
+
if (getEffectiveIsWeb()) return { __spaceX: v };
|
|
1073
|
+
return { columnGap: v };
|
|
1074
|
+
},
|
|
1075
|
+
"space-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1076
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1077
|
+
if (v === null) return null;
|
|
1078
|
+
if (getEffectiveIsWeb()) return { __spaceY: v };
|
|
1079
|
+
return { rowGap: v };
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
for (const [utility, prop] of Object.entries(PADDING_MARGIN_PROPS)) {
|
|
1083
|
+
spacingResolvers[utility] = makeSpacingResolver(prop);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/core/resolvers/border.ts
|
|
1087
|
+
function resolveRadius(value, radii, isArbitrary) {
|
|
1088
|
+
if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
1089
|
+
const key = value === "" ? "DEFAULT" : value;
|
|
1090
|
+
return radii[key] ?? null;
|
|
1091
|
+
}
|
|
1092
|
+
function makeBorderSideResolver(widthProp, colorProp) {
|
|
1093
|
+
return ({ value, isArbitrary }, { colors, borderWidth }) => {
|
|
1094
|
+
if (!value) return { [widthProp]: 1 };
|
|
1095
|
+
if (isArbitrary) {
|
|
1096
|
+
const w2 = toNativeValue(value);
|
|
1097
|
+
if (typeof w2 === "number") return { [widthProp]: w2 };
|
|
1098
|
+
return { [colorProp]: value };
|
|
1099
|
+
}
|
|
1100
|
+
const color = resolveColor(value, colors, false);
|
|
1101
|
+
if (color) return { [colorProp]: color };
|
|
1102
|
+
const w = borderWidth[value];
|
|
1103
|
+
return w !== void 0 ? { [widthProp]: w } : null;
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
var BORDER_SIDE_PROPS = {
|
|
1107
|
+
"border-t": ["borderTopWidth", "borderTopColor"],
|
|
1108
|
+
"border-r": ["borderRightWidth", "borderRightColor"],
|
|
1109
|
+
"border-b": ["borderBottomWidth", "borderBottomColor"],
|
|
1110
|
+
"border-l": ["borderLeftWidth", "borderLeftColor"]
|
|
1111
|
+
};
|
|
1112
|
+
var borderResolvers = {
|
|
1332
1113
|
// ── Border width ───────────────────────────────────────────────────────────
|
|
1333
1114
|
border: ({ value, isArbitrary }, { colors, borderWidth, spacing }) => {
|
|
1334
1115
|
if (!value) return { borderWidth: borderWidth["DEFAULT"] ?? 1 };
|
|
@@ -1385,188 +1166,128 @@ var RESOLVERS = {
|
|
|
1385
1166
|
const r = resolveRadius(value, borderRadius, isArbitrary);
|
|
1386
1167
|
return r !== null ? { borderBottomRightRadius: r } : null;
|
|
1387
1168
|
},
|
|
1388
|
-
// ──
|
|
1389
|
-
|
|
1390
|
-
if (!value) return null;
|
|
1391
|
-
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1392
|
-
const n = parseInt(value, 10);
|
|
1393
|
-
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1394
|
-
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1395
|
-
},
|
|
1396
|
-
// ── Grid template columns/rows (Tailwind-style aliases, web-only) ──────────
|
|
1397
|
-
"grid-cols": ({ value, isArbitrary }) => {
|
|
1169
|
+
// ── Outline extended (web-only) ───────────────────────────────────────────
|
|
1170
|
+
outline: ({ value, isArbitrary }, { colors }) => {
|
|
1398
1171
|
if (!getEffectiveIsWeb()) return null;
|
|
1399
|
-
if (!value) return
|
|
1400
|
-
if (
|
|
1401
|
-
if (
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1172
|
+
if (!value) return { outline: "2px solid transparent", outlineOffset: "2px" };
|
|
1173
|
+
if (value === "none") return { outline: "none", outlineOffset: "0" };
|
|
1174
|
+
if (isArbitrary) {
|
|
1175
|
+
if (/^\d/.test(value) || value.startsWith("calc(")) return { outlineWidth: value };
|
|
1176
|
+
return { outlineColor: value };
|
|
1177
|
+
}
|
|
1178
|
+
const widths = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1179
|
+
if (value in widths) return { outlineWidth: widths[value] };
|
|
1180
|
+
const color = resolveColor(value, colors, false);
|
|
1181
|
+
return color ? { outlineColor: color } : null;
|
|
1405
1182
|
},
|
|
1406
|
-
"
|
|
1183
|
+
"outline-offset": ({ value, isArbitrary }) => {
|
|
1407
1184
|
if (!getEffectiveIsWeb()) return null;
|
|
1408
|
-
if (
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
const n = parseInt(value, 10);
|
|
1412
|
-
if (isNaN(n) || n < 1) return null;
|
|
1413
|
-
return { gridTemplateRows: `repeat(${n}, minmax(0, 1fr))` };
|
|
1185
|
+
if (isArbitrary) return { outlineOffset: value };
|
|
1186
|
+
const offsets = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1187
|
+
return offsets[value] ? { outlineOffset: offsets[value] } : null;
|
|
1414
1188
|
},
|
|
1415
|
-
// ──
|
|
1416
|
-
|
|
1189
|
+
// ── Divide (child combinator CSS, web-only) ───────────────────────────────
|
|
1190
|
+
// These return special __divide* markers that resolver.ts converts to
|
|
1191
|
+
// .cls > * + * { border-... } CSS rules. No inline style is applied.
|
|
1192
|
+
"divide-x": ({ value, isArbitrary }) => {
|
|
1417
1193
|
if (!getEffectiveIsWeb()) return null;
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
"row-dense": "row dense",
|
|
1423
|
-
"col-dense": "column dense"
|
|
1424
|
-
};
|
|
1425
|
-
const flow = flows[value];
|
|
1426
|
-
return flow ? { gridAutoFlow: flow } : null;
|
|
1194
|
+
if (value === "reverse") return null;
|
|
1195
|
+
if (!value) return { __divideX: 1 };
|
|
1196
|
+
const n = parseFloat(value);
|
|
1197
|
+
return isNaN(n) ? null : { __divideX: n };
|
|
1427
1198
|
},
|
|
1428
|
-
|
|
1429
|
-
"auto-cols": ({ value, isArbitrary }) => {
|
|
1199
|
+
"divide-y": ({ value, isArbitrary }) => {
|
|
1430
1200
|
if (!getEffectiveIsWeb()) return null;
|
|
1431
|
-
if (
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
max: "max-content",
|
|
1436
|
-
fr: "minmax(0, 1fr)"
|
|
1437
|
-
};
|
|
1438
|
-
const v = presets[value];
|
|
1439
|
-
return v ? { gridAutoColumns: v } : null;
|
|
1201
|
+
if (value === "reverse") return null;
|
|
1202
|
+
if (!value) return { __divideY: 1 };
|
|
1203
|
+
const n = parseFloat(value);
|
|
1204
|
+
return isNaN(n) ? null : { __divideY: n };
|
|
1440
1205
|
},
|
|
1441
|
-
|
|
1206
|
+
divide: ({ value, isArbitrary }, { colors }) => {
|
|
1442
1207
|
if (!getEffectiveIsWeb()) return null;
|
|
1443
|
-
if (isArbitrary) return {
|
|
1444
|
-
const
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1208
|
+
if (isArbitrary) return { __divideColor: value };
|
|
1209
|
+
const styleTokens = {
|
|
1210
|
+
solid: "solid",
|
|
1211
|
+
dashed: "dashed",
|
|
1212
|
+
dotted: "dotted",
|
|
1213
|
+
double: "double",
|
|
1214
|
+
none: "none"
|
|
1449
1215
|
};
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
// ── Grid column placement (web-only) ──────────────────────────────────────
|
|
1454
|
-
"col-span": ({ value }) => {
|
|
1455
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1456
|
-
if (value === "full") return { gridColumn: "1 / -1" };
|
|
1457
|
-
const n = parseInt(value, 10);
|
|
1458
|
-
return isNaN(n) ? null : { gridColumn: `span ${n} / span ${n}` };
|
|
1459
|
-
},
|
|
1460
|
-
"col-start": ({ value, isArbitrary }) => {
|
|
1461
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1462
|
-
if (value === "auto") return { gridColumnStart: "auto" };
|
|
1463
|
-
if (isArbitrary) return { gridColumnStart: value };
|
|
1464
|
-
const n = parseInt(value, 10);
|
|
1465
|
-
return isNaN(n) ? null : { gridColumnStart: n };
|
|
1466
|
-
},
|
|
1467
|
-
"col-end": ({ value, isArbitrary }) => {
|
|
1468
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1469
|
-
if (value === "auto") return { gridColumnEnd: "auto" };
|
|
1470
|
-
if (isArbitrary) return { gridColumnEnd: value };
|
|
1471
|
-
const n = parseInt(value, 10);
|
|
1472
|
-
return isNaN(n) ? null : { gridColumnEnd: n };
|
|
1473
|
-
},
|
|
1474
|
-
col: ({ value, isArbitrary }) => {
|
|
1475
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1476
|
-
if (!value || value === "auto") return { gridColumn: "auto" };
|
|
1477
|
-
if (isArbitrary) return { gridColumn: value };
|
|
1478
|
-
return null;
|
|
1479
|
-
},
|
|
1480
|
-
// ── Grid row placement (web-only) ─────────────────────────────────────────
|
|
1481
|
-
"row-span": ({ value }) => {
|
|
1482
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1483
|
-
if (value === "full") return { gridRow: "1 / -1" };
|
|
1484
|
-
const n = parseInt(value, 10);
|
|
1485
|
-
return isNaN(n) ? null : { gridRow: `span ${n} / span ${n}` };
|
|
1486
|
-
},
|
|
1487
|
-
"row-start": ({ value, isArbitrary }) => {
|
|
1488
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1489
|
-
if (value === "auto") return { gridRowStart: "auto" };
|
|
1490
|
-
if (isArbitrary) return { gridRowStart: value };
|
|
1491
|
-
const n = parseInt(value, 10);
|
|
1492
|
-
return isNaN(n) ? null : { gridRowStart: n };
|
|
1493
|
-
},
|
|
1494
|
-
"row-end": ({ value, isArbitrary }) => {
|
|
1495
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1496
|
-
if (value === "auto") return { gridRowEnd: "auto" };
|
|
1497
|
-
if (isArbitrary) return { gridRowEnd: value };
|
|
1498
|
-
const n = parseInt(value, 10);
|
|
1499
|
-
return isNaN(n) ? null : { gridRowEnd: n };
|
|
1216
|
+
if (value in styleTokens) return { __divideStyle: styleTokens[value] };
|
|
1217
|
+
const color = resolveColor(value, colors, false);
|
|
1218
|
+
return color ? { __divideColor: color } : null;
|
|
1500
1219
|
},
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1220
|
+
// ── Ring ───────────────────────────────────────────────────────────────────
|
|
1221
|
+
// Web: box-shadow outline ring (doesn't affect layout).
|
|
1222
|
+
// Native: React Native has no box-shadow, so this falls back to borderWidth/
|
|
1223
|
+
// borderColor — the closest visual approximation (used by other RN Tailwind-
|
|
1224
|
+
// likes for the same reason). Unlike the web ring, this DOES affect layout,
|
|
1225
|
+
// and it shares its properties with the `border` utility — combining
|
|
1226
|
+
// `border-*` and `ring-*` on the same native element means whichever class
|
|
1227
|
+
// comes later wins, since both ultimately set borderWidth/borderColor.
|
|
1228
|
+
ring: ({ value, isArbitrary }, { colors }) => {
|
|
1229
|
+
const onWeb = getEffectiveIsWeb();
|
|
1230
|
+
const DEFAULT_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
1231
|
+
const DEFAULT_WIDTH = 3;
|
|
1232
|
+
const asNative = (w, color2) => w === 0 ? { borderWidth: 0 } : { borderWidth: w, borderColor: color2 };
|
|
1233
|
+
if (!value) {
|
|
1234
|
+
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
1235
|
+
}
|
|
1236
|
+
if (value === "inset") {
|
|
1237
|
+
return onWeb ? { boxShadow: `inset 0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
1238
|
+
}
|
|
1239
|
+
const widthTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
1240
|
+
if (!isArbitrary && value in widthTokens) {
|
|
1241
|
+
const w = widthTokens[value];
|
|
1242
|
+
return onWeb ? { boxShadow: w === 0 ? "none" : `0 0 0 ${w}px ${DEFAULT_COLOR}` } : asNative(w, DEFAULT_COLOR);
|
|
1243
|
+
}
|
|
1244
|
+
if (isArbitrary) {
|
|
1245
|
+
const numMatch = /^(\d+(?:\.\d+)?)(px|rem|em|vw|vh)?$/.exec(value);
|
|
1246
|
+
if (numMatch) {
|
|
1247
|
+
const unit = numMatch[2] ?? "px";
|
|
1248
|
+
if (onWeb) return { boxShadow: `0 0 0 ${numMatch[1]}${unit} ${DEFAULT_COLOR}` };
|
|
1249
|
+
return unit === "px" ? asNative(parseFloat(numMatch[1]), DEFAULT_COLOR) : null;
|
|
1250
|
+
}
|
|
1251
|
+
return onWeb ? { boxShadow: value.replace(/_/g, " ") } : null;
|
|
1252
|
+
}
|
|
1253
|
+
const color = resolveColor(value, colors, false);
|
|
1254
|
+
if (color) {
|
|
1255
|
+
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${color}` } : asNative(DEFAULT_WIDTH, color);
|
|
1256
|
+
}
|
|
1505
1257
|
return null;
|
|
1506
1258
|
},
|
|
1507
|
-
//
|
|
1508
|
-
//
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
end: "end",
|
|
1514
|
-
center: "center",
|
|
1515
|
-
stretch: "stretch",
|
|
1516
|
-
baseline: "baseline"
|
|
1517
|
-
};
|
|
1518
|
-
return map[value] ? { placeItems: map[value] } : null;
|
|
1519
|
-
},
|
|
1520
|
-
// place-content is shorthand for align-content + justify-content on a grid container
|
|
1521
|
-
"place-content": ({ value }) => {
|
|
1522
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1523
|
-
const map = {
|
|
1524
|
-
start: "start",
|
|
1525
|
-
end: "end",
|
|
1526
|
-
center: "center",
|
|
1527
|
-
stretch: "stretch",
|
|
1528
|
-
between: "space-between",
|
|
1529
|
-
around: "space-around",
|
|
1530
|
-
evenly: "space-evenly",
|
|
1531
|
-
baseline: "baseline"
|
|
1532
|
-
};
|
|
1533
|
-
return map[value] ? { placeContent: map[value] } : null;
|
|
1534
|
-
},
|
|
1535
|
-
// justify-items controls inline-axis alignment of grid items within their cells
|
|
1536
|
-
"justify-items": ({ value }) => {
|
|
1537
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1538
|
-
const map = {
|
|
1539
|
-
start: "start",
|
|
1540
|
-
end: "end",
|
|
1541
|
-
center: "center",
|
|
1542
|
-
stretch: "stretch"
|
|
1543
|
-
};
|
|
1544
|
-
return map[value] ? { justifyItems: map[value] } : null;
|
|
1545
|
-
},
|
|
1546
|
-
// place-self is shorthand for align-self + justify-self on a grid item
|
|
1547
|
-
"place-self": ({ value }) => {
|
|
1548
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1549
|
-
const map = {
|
|
1550
|
-
auto: "auto",
|
|
1551
|
-
start: "start",
|
|
1552
|
-
end: "end",
|
|
1553
|
-
center: "center",
|
|
1554
|
-
stretch: "stretch"
|
|
1555
|
-
};
|
|
1556
|
-
return map[value] ? { placeSelf: map[value] } : null;
|
|
1557
|
-
},
|
|
1558
|
-
// justify-self controls inline-axis self-alignment of a grid item
|
|
1559
|
-
"justify-self": ({ value }) => {
|
|
1259
|
+
// Web-only, unlike `ring` above: this stacks a second box-shadow layer to
|
|
1260
|
+
// create a gap between the element and the ring. There's no native
|
|
1261
|
+
// equivalent to approximate that with (a border can't create a gap outside
|
|
1262
|
+
// its own element without an extra wrapper view), so this stays a no-op
|
|
1263
|
+
// on native rather than rendering a misleading half-translation.
|
|
1264
|
+
"ring-offset": ({ value, isArbitrary }, _theme) => {
|
|
1560
1265
|
if (!getEffectiveIsWeb()) return null;
|
|
1561
|
-
const
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1266
|
+
const DEFAULT_RING_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
1267
|
+
const DEFAULT_RING_WIDTH = 3;
|
|
1268
|
+
const offsetTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
1269
|
+
let offsetWidth;
|
|
1270
|
+
if (!isArbitrary) {
|
|
1271
|
+
offsetWidth = value in offsetTokens ? offsetTokens[value] : null;
|
|
1272
|
+
} else {
|
|
1273
|
+
offsetWidth = /^-?\d+(\.\d+)?$/.test(value) ? parseFloat(value) : value;
|
|
1274
|
+
}
|
|
1275
|
+
if (offsetWidth === null || typeof offsetWidth === "number" && isNaN(offsetWidth)) return null;
|
|
1276
|
+
const isZero = offsetWidth === 0 || offsetWidth === "0";
|
|
1277
|
+
const offsetCss = typeof offsetWidth === "number" ? `${offsetWidth}px` : offsetWidth;
|
|
1278
|
+
return {
|
|
1279
|
+
boxShadow: isZero ? `0 0 0 ${DEFAULT_RING_WIDTH}px ${DEFAULT_RING_COLOR}` : `0 0 0 ${offsetCss} #fff, 0 0 0 calc(${offsetCss} + ${DEFAULT_RING_WIDTH}px) ${DEFAULT_RING_COLOR}`
|
|
1567
1280
|
};
|
|
1568
|
-
|
|
1569
|
-
|
|
1281
|
+
}
|
|
1282
|
+
};
|
|
1283
|
+
for (const [utility, [widthProp, colorProp]] of Object.entries(BORDER_SIDE_PROPS)) {
|
|
1284
|
+
borderResolvers[utility] = makeBorderSideResolver(widthProp, colorProp);
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
// src/core/resolvers/filters.ts
|
|
1288
|
+
var FILTER_COMPOSE = "var(--kb-blur,) var(--kb-brightness,) var(--kb-contrast,) var(--kb-grayscale,) var(--kb-hue-rotate,) var(--kb-invert,) var(--kb-saturate,) var(--kb-sepia,) var(--kb-drop-shadow,)";
|
|
1289
|
+
var BACKDROP_FILTER_COMPOSE = "var(--kb-backdrop-blur,) var(--kb-backdrop-brightness,) var(--kb-backdrop-contrast,) var(--kb-backdrop-grayscale,) var(--kb-backdrop-hue-rotate,) var(--kb-backdrop-invert,) var(--kb-backdrop-opacity,) var(--kb-backdrop-saturate,) var(--kb-backdrop-sepia,)";
|
|
1290
|
+
var filterResolvers = {
|
|
1570
1291
|
// ── CSS Filters (composable via CSS variables, web-only) ─────────────────
|
|
1571
1292
|
blur: ({ value, isArbitrary }) => {
|
|
1572
1293
|
if (!getEffectiveIsWeb()) return null;
|
|
@@ -1701,226 +1422,31 @@ var RESOLVERS = {
|
|
|
1701
1422
|
if (value === "none") return { backdropFilter: "none" };
|
|
1702
1423
|
return null;
|
|
1703
1424
|
},
|
|
1704
|
-
// ──
|
|
1705
|
-
"
|
|
1706
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1707
|
-
const directions = {
|
|
1708
|
-
t: "to top",
|
|
1709
|
-
tr: "to top right",
|
|
1710
|
-
r: "to right",
|
|
1711
|
-
br: "to bottom right",
|
|
1712
|
-
b: "to bottom",
|
|
1713
|
-
bl: "to bottom left",
|
|
1714
|
-
l: "to left",
|
|
1715
|
-
tl: "to top left"
|
|
1716
|
-
};
|
|
1717
|
-
const dir = directions[value];
|
|
1718
|
-
if (!dir) return null;
|
|
1719
|
-
return {
|
|
1720
|
-
backgroundImage: `linear-gradient(${dir}, var(--kb-gradient-from, transparent), var(--kb-gradient-stops, transparent))`
|
|
1721
|
-
};
|
|
1722
|
-
},
|
|
1723
|
-
from: ({ value, isArbitrary }, { colors }) => {
|
|
1724
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1725
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1726
|
-
if (!color) return null;
|
|
1727
|
-
return {
|
|
1728
|
-
"--kb-gradient-from": color,
|
|
1729
|
-
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-to, transparent)`
|
|
1730
|
-
};
|
|
1731
|
-
},
|
|
1732
|
-
via: ({ value, isArbitrary }, { colors }) => {
|
|
1425
|
+
// ── Mix / background blend mode (web-only) ───────────────────────────────
|
|
1426
|
+
"mix-blend": ({ value }) => {
|
|
1733
1427
|
if (!getEffectiveIsWeb()) return null;
|
|
1734
|
-
const
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
"
|
|
1738
|
-
"
|
|
1739
|
-
|
|
1428
|
+
const modes = [
|
|
1429
|
+
"normal",
|
|
1430
|
+
"multiply",
|
|
1431
|
+
"screen",
|
|
1432
|
+
"overlay",
|
|
1433
|
+
"darken",
|
|
1434
|
+
"lighten",
|
|
1435
|
+
"color-dodge",
|
|
1436
|
+
"color-burn",
|
|
1437
|
+
"hard-light",
|
|
1438
|
+
"soft-light",
|
|
1439
|
+
"difference",
|
|
1440
|
+
"exclusion",
|
|
1441
|
+
"hue",
|
|
1442
|
+
"saturation",
|
|
1443
|
+
"color",
|
|
1444
|
+
"luminosity",
|
|
1445
|
+
"plus-lighter"
|
|
1446
|
+
];
|
|
1447
|
+
return modes.includes(value) ? { mixBlendMode: value } : null;
|
|
1740
1448
|
},
|
|
1741
|
-
|
|
1742
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1743
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1744
|
-
if (!color) return null;
|
|
1745
|
-
return { "--kb-gradient-to": color };
|
|
1746
|
-
},
|
|
1747
|
-
// ── Transform extras (web-only) ───────────────────────────────────────────
|
|
1748
|
-
"skew-x": ({ value, negative, isArbitrary }) => {
|
|
1749
|
-
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
1750
|
-
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
1751
|
-
return getEffectiveIsWeb() ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
|
|
1752
|
-
},
|
|
1753
|
-
"skew-y": ({ value, negative, isArbitrary }) => {
|
|
1754
|
-
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
1755
|
-
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
1756
|
-
return getEffectiveIsWeb() ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
|
|
1757
|
-
},
|
|
1758
|
-
// Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
|
|
1759
|
-
transform: ({ value, isArbitrary }) => {
|
|
1760
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1761
|
-
if (isArbitrary) return { transform: value.replace(/_/g, " ") };
|
|
1762
|
-
if (value === "none") return { transform: "none" };
|
|
1763
|
-
return null;
|
|
1764
|
-
},
|
|
1765
|
-
// Transform origin
|
|
1766
|
-
origin: ({ value, isArbitrary }) => {
|
|
1767
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1768
|
-
if (isArbitrary) return { transformOrigin: value.replace(/_/g, " ") };
|
|
1769
|
-
const origins = {
|
|
1770
|
-
center: "center",
|
|
1771
|
-
top: "top",
|
|
1772
|
-
"top-right": "top right",
|
|
1773
|
-
right: "right",
|
|
1774
|
-
"bottom-right": "bottom right",
|
|
1775
|
-
bottom: "bottom",
|
|
1776
|
-
"bottom-left": "bottom left",
|
|
1777
|
-
left: "left",
|
|
1778
|
-
"top-left": "top left"
|
|
1779
|
-
};
|
|
1780
|
-
return origins[value] ? { transformOrigin: origins[value] } : null;
|
|
1781
|
-
},
|
|
1782
|
-
// ── Text decoration advanced (web-only) ───────────────────────────────────
|
|
1783
|
-
decoration: ({ value, isArbitrary }, { colors }) => {
|
|
1784
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1785
|
-
if (isArbitrary) {
|
|
1786
|
-
if (/^\d/.test(value) || value.startsWith("calc(")) return { textDecorationThickness: value };
|
|
1787
|
-
return { textDecorationColor: value };
|
|
1788
|
-
}
|
|
1789
|
-
const thickTokens = {
|
|
1790
|
-
auto: "auto",
|
|
1791
|
-
"from-font": "from-font",
|
|
1792
|
-
"0": "0px",
|
|
1793
|
-
"1": "1px",
|
|
1794
|
-
"2": "2px",
|
|
1795
|
-
"4": "4px",
|
|
1796
|
-
"8": "8px"
|
|
1797
|
-
};
|
|
1798
|
-
if (value in thickTokens) return { textDecorationThickness: thickTokens[value] };
|
|
1799
|
-
const styleTokens = {
|
|
1800
|
-
solid: "solid",
|
|
1801
|
-
dashed: "dashed",
|
|
1802
|
-
dotted: "dotted",
|
|
1803
|
-
double: "double",
|
|
1804
|
-
wavy: "wavy"
|
|
1805
|
-
};
|
|
1806
|
-
if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
|
|
1807
|
-
const color = resolveColor(value, colors, false);
|
|
1808
|
-
return color ? { textDecorationColor: color } : null;
|
|
1809
|
-
},
|
|
1810
|
-
"underline-offset": ({ value, isArbitrary }) => {
|
|
1811
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1812
|
-
if (isArbitrary) return { textUnderlineOffset: value };
|
|
1813
|
-
const offsets = {
|
|
1814
|
-
auto: "auto",
|
|
1815
|
-
"0": "0px",
|
|
1816
|
-
"1": "1px",
|
|
1817
|
-
"2": "2px",
|
|
1818
|
-
"4": "4px",
|
|
1819
|
-
"8": "8px"
|
|
1820
|
-
};
|
|
1821
|
-
return offsets[value] ? { textUnderlineOffset: offsets[value] } : null;
|
|
1822
|
-
},
|
|
1823
|
-
// ── Content (web-only — for before:/after: pseudo-elements, which don't exist on native) ──
|
|
1824
|
-
// Arbitrary value carries its own quotes from the bracket syntax (content-['*'] parses to
|
|
1825
|
-
// the literal string 'you can see it' quotes included), so it passes straight through as a
|
|
1826
|
-
// valid `content: '*'` CSS value with no extra wrapping needed.
|
|
1827
|
-
content: ({ value, isArbitrary }) => {
|
|
1828
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1829
|
-
if (isArbitrary) return { content: value };
|
|
1830
|
-
const presets = { none: "none" };
|
|
1831
|
-
return value in presets ? { content: presets[value] } : null;
|
|
1832
|
-
},
|
|
1833
|
-
// ── Arbitrary CSS property (web-only): [property:value] with no utility prefix ──
|
|
1834
|
-
// e.g. [mask-type:luminance], [--my-var:10px]. parser.ts already isolates this case
|
|
1835
|
-
// as utility: '' — it's ALSO how a stray, prefix-less negative bracket ("-[10px]",
|
|
1836
|
-
// presumably a typo) parses, which is why this only fires when the arbitrary value
|
|
1837
|
-
// itself contains a "property:value" pair; anything else (no colon) still resolves
|
|
1838
|
-
// to null exactly as before this resolver existed, rather than guessing a property.
|
|
1839
|
-
//
|
|
1840
|
-
// Only the FIRST colon splits property from value — the value itself may contain
|
|
1841
|
-
// more colons (a URL's "http://…") and must stay intact: [background:url(http://x/a.png)].
|
|
1842
|
-
// camelToKebab() in resolver.ts is a no-op on an already-kebab-case (or "--"-prefixed
|
|
1843
|
-
// custom property) key, so it can be used as the style object key as-written with no
|
|
1844
|
-
// extra case conversion — it only needs to look like a plausible CSS property name.
|
|
1845
|
-
"": ({ value, isArbitrary, negative }) => {
|
|
1846
|
-
if (!getEffectiveIsWeb() || !isArbitrary || !value) return null;
|
|
1847
|
-
if (negative) return null;
|
|
1848
|
-
const colonIdx = value.indexOf(":");
|
|
1849
|
-
if (colonIdx <= 0) return null;
|
|
1850
|
-
const prop = value.slice(0, colonIdx).trim();
|
|
1851
|
-
const cssValue = value.slice(colonIdx + 1).trim();
|
|
1852
|
-
if (!cssValue || !/^(--[\w-]+|[a-zA-Z-]+)$/.test(prop)) return null;
|
|
1853
|
-
return { [prop]: cssValue };
|
|
1854
|
-
},
|
|
1855
|
-
// ── Outline extended (web-only) ───────────────────────────────────────────
|
|
1856
|
-
outline: ({ value, isArbitrary }, { colors }) => {
|
|
1857
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1858
|
-
if (!value) return { outline: "2px solid transparent", outlineOffset: "2px" };
|
|
1859
|
-
if (value === "none") return { outline: "none", outlineOffset: "0" };
|
|
1860
|
-
if (isArbitrary) {
|
|
1861
|
-
if (/^\d/.test(value) || value.startsWith("calc(")) return { outlineWidth: value };
|
|
1862
|
-
return { outlineColor: value };
|
|
1863
|
-
}
|
|
1864
|
-
const widths = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1865
|
-
if (value in widths) return { outlineWidth: widths[value] };
|
|
1866
|
-
const color = resolveColor(value, colors, false);
|
|
1867
|
-
return color ? { outlineColor: color } : null;
|
|
1868
|
-
},
|
|
1869
|
-
"outline-offset": ({ value, isArbitrary }) => {
|
|
1870
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1871
|
-
if (isArbitrary) return { outlineOffset: value };
|
|
1872
|
-
const offsets = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1873
|
-
return offsets[value] ? { outlineOffset: offsets[value] } : null;
|
|
1874
|
-
},
|
|
1875
|
-
// ── Columns (web-only) ─────────────────────────────────────────────────────
|
|
1876
|
-
columns: ({ value, isArbitrary }) => {
|
|
1877
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1878
|
-
if (isArbitrary) return { columnCount: value };
|
|
1879
|
-
if (value === "auto") return { columnCount: "auto" };
|
|
1880
|
-
const n = parseInt(value, 10);
|
|
1881
|
-
if (!isNaN(n)) return { columnCount: n };
|
|
1882
|
-
const widths = {
|
|
1883
|
-
"3xs": "16rem",
|
|
1884
|
-
"2xs": "18rem",
|
|
1885
|
-
xs: "20rem",
|
|
1886
|
-
sm: "24rem",
|
|
1887
|
-
md: "28rem",
|
|
1888
|
-
lg: "32rem",
|
|
1889
|
-
xl: "36rem",
|
|
1890
|
-
"2xl": "42rem",
|
|
1891
|
-
"3xl": "48rem",
|
|
1892
|
-
"4xl": "56rem",
|
|
1893
|
-
"5xl": "64rem",
|
|
1894
|
-
"6xl": "72rem",
|
|
1895
|
-
"7xl": "80rem"
|
|
1896
|
-
};
|
|
1897
|
-
return widths[value] ? { columnWidth: widths[value] } : null;
|
|
1898
|
-
},
|
|
1899
|
-
// ── Mix / background blend mode (web-only) ───────────────────────────────
|
|
1900
|
-
"mix-blend": ({ value }) => {
|
|
1901
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1902
|
-
const modes = [
|
|
1903
|
-
"normal",
|
|
1904
|
-
"multiply",
|
|
1905
|
-
"screen",
|
|
1906
|
-
"overlay",
|
|
1907
|
-
"darken",
|
|
1908
|
-
"lighten",
|
|
1909
|
-
"color-dodge",
|
|
1910
|
-
"color-burn",
|
|
1911
|
-
"hard-light",
|
|
1912
|
-
"soft-light",
|
|
1913
|
-
"difference",
|
|
1914
|
-
"exclusion",
|
|
1915
|
-
"hue",
|
|
1916
|
-
"saturation",
|
|
1917
|
-
"color",
|
|
1918
|
-
"luminosity",
|
|
1919
|
-
"plus-lighter"
|
|
1920
|
-
];
|
|
1921
|
-
return modes.includes(value) ? { mixBlendMode: value } : null;
|
|
1922
|
-
},
|
|
1923
|
-
"bg-blend": ({ value }) => {
|
|
1449
|
+
"bg-blend": ({ value }) => {
|
|
1924
1450
|
if (!getEffectiveIsWeb()) return null;
|
|
1925
1451
|
const modes = [
|
|
1926
1452
|
"normal",
|
|
@@ -1953,237 +1479,603 @@ var RESOLVERS = {
|
|
|
1953
1479
|
transform: "transform"
|
|
1954
1480
|
};
|
|
1955
1481
|
return presets[value] ? { willChange: presets[value] } : null;
|
|
1482
|
+
}
|
|
1483
|
+
};
|
|
1484
|
+
|
|
1485
|
+
// src/core/resolvers/layout.ts
|
|
1486
|
+
var _standalone = null;
|
|
1487
|
+
function buildStandalone() {
|
|
1488
|
+
const web = getEffectiveIsWeb();
|
|
1489
|
+
return {
|
|
1490
|
+
// Display
|
|
1491
|
+
// React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
|
|
1492
|
+
// a no-op normally, but is needed to re-show an element that was hidden via `hidden`.
|
|
1493
|
+
// `grid`, `contents`, `flow-root` have no native equivalent and stay null there.
|
|
1494
|
+
// The inline-* family (inline, inline-block, inline-flex, inline-grid) falls back
|
|
1495
|
+
// to 'flex' on native instead — like plain `flex`, this is a no-op most of the
|
|
1496
|
+
// time, but without it these utilities couldn't re-show a `hidden` element on
|
|
1497
|
+
// native either (null → no style applied → still display:'none').
|
|
1498
|
+
flex: { display: "flex" },
|
|
1499
|
+
block: web ? { display: "block" } : null,
|
|
1500
|
+
"inline-block": { display: web ? "inline-block" : "flex" },
|
|
1501
|
+
inline: { display: web ? "inline" : "flex" },
|
|
1502
|
+
grid: web ? { display: "grid" } : null,
|
|
1503
|
+
grd: web ? { display: "grid" } : null,
|
|
1504
|
+
"inline-flex": { display: web ? "inline-flex" : "flex" },
|
|
1505
|
+
"inline-grid": { display: web ? "inline-grid" : "flex" },
|
|
1506
|
+
hidden: { display: "none" },
|
|
1507
|
+
contents: web ? { display: "contents" } : null,
|
|
1508
|
+
"flow-root": web ? { display: "flow-root" } : null,
|
|
1509
|
+
// Flex direction, wrap, grow/shrink, and alignment (both web and native) —
|
|
1510
|
+
// every one of these is meaningless without the element also being a flex
|
|
1511
|
+
// container. React Native Views are ALWAYS flex containers by default, so
|
|
1512
|
+
// on native this was already true for free; on web a plain <div> defaults
|
|
1513
|
+
// to display:block, so e.g. `items-center` alone silently did nothing.
|
|
1514
|
+
// Folding `display: 'flex'` into these on web closes that native/web gap —
|
|
1515
|
+
// `flex-1 items-center justify-center` now behaves the same on both,
|
|
1516
|
+
// without also needing a separate `flex` class.
|
|
1517
|
+
"flex-row": { flexDirection: "row", ...web ? { display: "flex" } : {} },
|
|
1518
|
+
"flex-col": { flexDirection: "column", ...web ? { display: "flex" } : {} },
|
|
1519
|
+
"flex-row-reverse": { flexDirection: "row-reverse", ...web ? { display: "flex" } : {} },
|
|
1520
|
+
"flex-col-reverse": { flexDirection: "column-reverse", ...web ? { display: "flex" } : {} },
|
|
1521
|
+
// Flex wrap (both)
|
|
1522
|
+
"flex-wrap": { flexWrap: "wrap", ...web ? { display: "flex" } : {} },
|
|
1523
|
+
"flex-wrap-reverse": { flexWrap: "wrap-reverse", ...web ? { display: "flex" } : {} },
|
|
1524
|
+
"flex-nowrap": { flexWrap: "nowrap", ...web ? { display: "flex" } : {} },
|
|
1525
|
+
// Flex grow / shrink (both) — deliberately NOT folding in display:flex
|
|
1526
|
+
// like the container-level properties above. flex-grow/flex-shrink are
|
|
1527
|
+
// item-level: they already take effect purely via the PARENT already
|
|
1528
|
+
// being a flex container, with zero dependency on this element's own
|
|
1529
|
+
// display. Forcing display:flex here would instead be an unrelated side
|
|
1530
|
+
// effect on THIS element's own children (turning what may be an ordinary
|
|
1531
|
+
// block stack into a flex row) — exactly the kind of surprise the
|
|
1532
|
+
// container-level properties above can never cause, since those are
|
|
1533
|
+
// no-ops without display:flex to begin with.
|
|
1534
|
+
"flex-grow": { flexGrow: 1 },
|
|
1535
|
+
"flex-grow-0": { flexGrow: 0 },
|
|
1536
|
+
"flex-shrink": { flexShrink: 1 },
|
|
1537
|
+
"flex-shrink-0": { flexShrink: 0 },
|
|
1538
|
+
// Align items (both)
|
|
1539
|
+
"items-start": { alignItems: "flex-start", ...web ? { display: "flex" } : {} },
|
|
1540
|
+
"items-end": { alignItems: "flex-end", ...web ? { display: "flex" } : {} },
|
|
1541
|
+
"items-center": { alignItems: "center", ...web ? { display: "flex" } : {} },
|
|
1542
|
+
"items-baseline": { alignItems: "baseline", ...web ? { display: "flex" } : {} },
|
|
1543
|
+
"items-stretch": { alignItems: "stretch", ...web ? { display: "flex" } : {} },
|
|
1544
|
+
// Justify content (both)
|
|
1545
|
+
"justify-start": { justifyContent: "flex-start", ...web ? { display: "flex" } : {} },
|
|
1546
|
+
"justify-end": { justifyContent: "flex-end", ...web ? { display: "flex" } : {} },
|
|
1547
|
+
"justify-center": { justifyContent: "center", ...web ? { display: "flex" } : {} },
|
|
1548
|
+
"justify-between": { justifyContent: "space-between", ...web ? { display: "flex" } : {} },
|
|
1549
|
+
"justify-around": { justifyContent: "space-around", ...web ? { display: "flex" } : {} },
|
|
1550
|
+
"justify-evenly": { justifyContent: "space-evenly", ...web ? { display: "flex" } : {} },
|
|
1551
|
+
// Align content (both)
|
|
1552
|
+
"content-start": { alignContent: "flex-start", ...web ? { display: "flex" } : {} },
|
|
1553
|
+
"content-end": { alignContent: "flex-end", ...web ? { display: "flex" } : {} },
|
|
1554
|
+
"content-center": { alignContent: "center", ...web ? { display: "flex" } : {} },
|
|
1555
|
+
"content-between": { alignContent: "space-between", ...web ? { display: "flex" } : {} },
|
|
1556
|
+
"content-around": { alignContent: "space-around", ...web ? { display: "flex" } : {} },
|
|
1557
|
+
"content-evenly": { alignContent: "space-evenly", ...web ? { display: "flex" } : {} },
|
|
1558
|
+
"content-stretch": { alignContent: "stretch", ...web ? { display: "flex" } : {} },
|
|
1559
|
+
// Align self (both)
|
|
1560
|
+
"self-auto": { alignSelf: "auto" },
|
|
1561
|
+
"self-start": { alignSelf: "flex-start" },
|
|
1562
|
+
"self-end": { alignSelf: "flex-end" },
|
|
1563
|
+
"self-center": { alignSelf: "center" },
|
|
1564
|
+
"self-stretch": { alignSelf: "stretch" },
|
|
1565
|
+
"self-baseline": { alignSelf: "baseline" },
|
|
1566
|
+
// Text align (both)
|
|
1567
|
+
"text-left": { textAlign: "left" },
|
|
1568
|
+
"text-right": { textAlign: "right" },
|
|
1569
|
+
"text-center": { textAlign: "center" },
|
|
1570
|
+
"text-justify": { textAlign: "justify" },
|
|
1571
|
+
// Font weight shortcuts (both)
|
|
1572
|
+
"font-thin": { fontWeight: "100" },
|
|
1573
|
+
"font-extralight": { fontWeight: "200" },
|
|
1574
|
+
"font-light": { fontWeight: "300" },
|
|
1575
|
+
"font-normal": { fontWeight: "400" },
|
|
1576
|
+
"font-medium": { fontWeight: "500" },
|
|
1577
|
+
"font-semibold": { fontWeight: "600" },
|
|
1578
|
+
"font-bold": { fontWeight: "700" },
|
|
1579
|
+
"font-extrabold": { fontWeight: "800" },
|
|
1580
|
+
"font-black": { fontWeight: "900" },
|
|
1581
|
+
// Text decoration (overline is web-only)
|
|
1582
|
+
underline: { textDecorationLine: "underline" },
|
|
1583
|
+
overline: web ? { textDecorationLine: "overline" } : null,
|
|
1584
|
+
"line-through": { textDecorationLine: "line-through" },
|
|
1585
|
+
"no-underline": { textDecorationLine: "none" },
|
|
1586
|
+
// Text transform (both)
|
|
1587
|
+
uppercase: { textTransform: "uppercase" },
|
|
1588
|
+
lowercase: { textTransform: "lowercase" },
|
|
1589
|
+
capitalize: { textTransform: "capitalize" },
|
|
1590
|
+
"normal-case": { textTransform: "none" },
|
|
1591
|
+
// Font style (both)
|
|
1592
|
+
italic: { fontStyle: "italic" },
|
|
1593
|
+
"non-italic": { fontStyle: "normal" },
|
|
1594
|
+
// Position (fixed/sticky/static are web-only; RN only supports relative/absolute)
|
|
1595
|
+
relative: { position: "relative" },
|
|
1596
|
+
absolute: { position: "absolute" },
|
|
1597
|
+
fixed: web ? { position: "fixed" } : null,
|
|
1598
|
+
sticky: web ? { position: "sticky" } : null,
|
|
1599
|
+
static: web ? { position: "static" } : null,
|
|
1600
|
+
// Visibility (no `visibility` prop on native; use opacity instead)
|
|
1601
|
+
visible: web ? { visibility: "visible" } : null,
|
|
1602
|
+
invisible: web ? { visibility: "hidden" } : { opacity: 0 },
|
|
1603
|
+
// Overflow (RN supports 'hidden' | 'visible' | 'scroll'; not 'auto')
|
|
1604
|
+
"overflow-hidden": { overflow: "hidden" },
|
|
1605
|
+
"overflow-visible": { overflow: "visible" },
|
|
1606
|
+
"overflow-scroll": { overflow: "scroll" },
|
|
1607
|
+
"overflow-auto": web ? { overflow: "auto" } : { overflow: "scroll" },
|
|
1608
|
+
// overflowX / overflowY are web-only
|
|
1609
|
+
"overflow-x-hidden": web ? { overflowX: "hidden" } : null,
|
|
1610
|
+
"overflow-x-scroll": web ? { overflowX: "scroll" } : null,
|
|
1611
|
+
"overflow-x-auto": web ? { overflowX: "auto" } : null,
|
|
1612
|
+
"overflow-y-hidden": web ? { overflowY: "hidden" } : null,
|
|
1613
|
+
"overflow-y-scroll": web ? { overflowY: "scroll" } : null,
|
|
1614
|
+
"overflow-y-auto": web ? { overflowY: "auto" } : null,
|
|
1615
|
+
// Object fit (web-only; use resizeMode prop on RN Image)
|
|
1616
|
+
"object-contain": web ? { objectFit: "contain" } : null,
|
|
1617
|
+
"object-cover": web ? { objectFit: "cover" } : null,
|
|
1618
|
+
"object-fill": web ? { objectFit: "fill" } : null,
|
|
1619
|
+
"object-none": web ? { objectFit: "none" } : null,
|
|
1620
|
+
"object-scale-down": web ? { objectFit: "scale-down" } : null,
|
|
1621
|
+
// Border style (both)
|
|
1622
|
+
"border-solid": { borderStyle: "solid" },
|
|
1623
|
+
"border-dashed": { borderStyle: "dashed" },
|
|
1624
|
+
"border-dotted": { borderStyle: "dotted" },
|
|
1625
|
+
"border-none": { borderWidth: 0 },
|
|
1626
|
+
// Border sides default width (both)
|
|
1627
|
+
"border-t": { borderTopWidth: 1 },
|
|
1628
|
+
"border-r": { borderRightWidth: 1 },
|
|
1629
|
+
"border-b": { borderBottomWidth: 1 },
|
|
1630
|
+
"border-l": { borderLeftWidth: 1 },
|
|
1631
|
+
// Cursor (web-only)
|
|
1632
|
+
"cursor-auto": web ? { cursor: "auto" } : null,
|
|
1633
|
+
"cursor-default": web ? { cursor: "default" } : null,
|
|
1634
|
+
"cursor-pointer": web ? { cursor: "pointer" } : null,
|
|
1635
|
+
"cursor-wait": web ? { cursor: "wait" } : null,
|
|
1636
|
+
"cursor-text": web ? { cursor: "text" } : null,
|
|
1637
|
+
"cursor-move": web ? { cursor: "move" } : null,
|
|
1638
|
+
"cursor-not-allowed": web ? { cursor: "not-allowed" } : null,
|
|
1639
|
+
// User select (web-only)
|
|
1640
|
+
"select-none": web ? { userSelect: "none" } : null,
|
|
1641
|
+
"select-text": web ? { userSelect: "text" } : null,
|
|
1642
|
+
"select-all": web ? { userSelect: "all" } : null,
|
|
1643
|
+
"select-auto": web ? { userSelect: "auto" } : null,
|
|
1644
|
+
// Pointer events (both)
|
|
1645
|
+
"pointer-events-none": { pointerEvents: "none" },
|
|
1646
|
+
"pointer-events-auto": { pointerEvents: "auto" },
|
|
1647
|
+
// Whitespace (web-only; RN Text uses numberOfLines prop instead)
|
|
1648
|
+
"whitespace-normal": web ? { whiteSpace: "normal" } : null,
|
|
1649
|
+
"whitespace-nowrap": web ? { whiteSpace: "nowrap" } : null,
|
|
1650
|
+
"whitespace-pre": web ? { whiteSpace: "pre" } : null,
|
|
1651
|
+
"whitespace-pre-wrap": web ? { whiteSpace: "pre-wrap" } : null,
|
|
1652
|
+
"whitespace-pre-line": web ? { whiteSpace: "pre-line" } : null,
|
|
1653
|
+
// Word break (web-only)
|
|
1654
|
+
"break-normal": web ? { overflowWrap: "normal", wordBreak: "normal" } : null,
|
|
1655
|
+
"break-words": web ? { overflowWrap: "break-word" } : null,
|
|
1656
|
+
"break-all": web ? { wordBreak: "break-all" } : null,
|
|
1657
|
+
// Misc web-only
|
|
1658
|
+
truncate: web ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null,
|
|
1659
|
+
"box-border": web ? { boxSizing: "border-box" } : null,
|
|
1660
|
+
"box-content": web ? { boxSizing: "content-box" } : null,
|
|
1661
|
+
"appearance-none": web ? { appearance: "none" } : null,
|
|
1662
|
+
"outline-none": web ? { outline: "none", outlineOffset: "0" } : null,
|
|
1663
|
+
outline: web ? { outline: "2px solid transparent", outlineOffset: "2px" } : null,
|
|
1664
|
+
resize: web ? { resize: "both" } : null,
|
|
1665
|
+
"resize-none": web ? { resize: "none" } : null,
|
|
1666
|
+
"resize-y": web ? { resize: "vertical" } : null,
|
|
1667
|
+
"resize-x": web ? { resize: "horizontal" } : null,
|
|
1668
|
+
antialiased: web ? { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale" } : null,
|
|
1669
|
+
"subpixel-antialiased": web ? { WebkitFontSmoothing: "subpixel-antialiased", MozOsxFontSmoothing: "auto" } : null,
|
|
1670
|
+
"overflow-ellipsis": web ? { textOverflow: "ellipsis" } : null,
|
|
1671
|
+
"sr-only": web ? {
|
|
1672
|
+
position: "absolute",
|
|
1673
|
+
width: 1,
|
|
1674
|
+
height: 1,
|
|
1675
|
+
padding: 0,
|
|
1676
|
+
margin: -1,
|
|
1677
|
+
overflow: "hidden",
|
|
1678
|
+
clip: "rect(0,0,0,0)",
|
|
1679
|
+
whiteSpace: "nowrap",
|
|
1680
|
+
border: 0
|
|
1681
|
+
} : null,
|
|
1682
|
+
"not-sr-only": web ? {
|
|
1683
|
+
position: "static",
|
|
1684
|
+
width: "auto",
|
|
1685
|
+
height: "auto",
|
|
1686
|
+
padding: 0,
|
|
1687
|
+
margin: 0,
|
|
1688
|
+
overflow: "visible",
|
|
1689
|
+
clip: "auto",
|
|
1690
|
+
whiteSpace: "normal"
|
|
1691
|
+
} : null,
|
|
1692
|
+
// Lists (web-only)
|
|
1693
|
+
"list-none": web ? { listStyleType: "none" } : null,
|
|
1694
|
+
"list-disc": web ? { listStyleType: "disc" } : null,
|
|
1695
|
+
"list-decimal": web ? { listStyleType: "decimal" } : null,
|
|
1696
|
+
// Background clip (web-only)
|
|
1697
|
+
"bg-clip-border": web ? { backgroundClip: "border-box" } : null,
|
|
1698
|
+
"bg-clip-padding": web ? { backgroundClip: "padding-box" } : null,
|
|
1699
|
+
"bg-clip-content": web ? { backgroundClip: "content-box" } : null,
|
|
1700
|
+
"bg-clip-text": web ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
|
|
1701
|
+
// Background image
|
|
1702
|
+
"bg-none": web ? { backgroundImage: "none" } : null,
|
|
1703
|
+
// Background size (web-only)
|
|
1704
|
+
"bg-auto": web ? { backgroundSize: "auto" } : null,
|
|
1705
|
+
"bg-cover": web ? { backgroundSize: "cover" } : null,
|
|
1706
|
+
"bg-contain": web ? { backgroundSize: "contain" } : null,
|
|
1707
|
+
// Background position (web-only)
|
|
1708
|
+
"bg-center": web ? { backgroundPosition: "center" } : null,
|
|
1709
|
+
"bg-top": web ? { backgroundPosition: "top" } : null,
|
|
1710
|
+
"bg-bottom": web ? { backgroundPosition: "bottom" } : null,
|
|
1711
|
+
"bg-left": web ? { backgroundPosition: "left" } : null,
|
|
1712
|
+
"bg-right": web ? { backgroundPosition: "right" } : null,
|
|
1713
|
+
"bg-left-top": web ? { backgroundPosition: "left top" } : null,
|
|
1714
|
+
"bg-left-bottom": web ? { backgroundPosition: "left bottom" } : null,
|
|
1715
|
+
"bg-right-top": web ? { backgroundPosition: "right top" } : null,
|
|
1716
|
+
"bg-right-bottom": web ? { backgroundPosition: "right bottom" } : null,
|
|
1717
|
+
// Background repeat (web-only)
|
|
1718
|
+
"bg-repeat": web ? { backgroundRepeat: "repeat" } : null,
|
|
1719
|
+
"bg-no-repeat": web ? { backgroundRepeat: "no-repeat" } : null,
|
|
1720
|
+
"bg-repeat-x": web ? { backgroundRepeat: "repeat-x" } : null,
|
|
1721
|
+
"bg-repeat-y": web ? { backgroundRepeat: "repeat-y" } : null,
|
|
1722
|
+
"bg-repeat-round": web ? { backgroundRepeat: "round" } : null,
|
|
1723
|
+
"bg-repeat-space": web ? { backgroundRepeat: "space" } : null,
|
|
1724
|
+
// Background attachment (web-only)
|
|
1725
|
+
"bg-fixed": web ? { backgroundAttachment: "fixed" } : null,
|
|
1726
|
+
"bg-local": web ? { backgroundAttachment: "local" } : null,
|
|
1727
|
+
"bg-scroll": web ? { backgroundAttachment: "scroll" } : null,
|
|
1728
|
+
// Object position (web-only)
|
|
1729
|
+
"object-center": web ? { objectPosition: "center" } : null,
|
|
1730
|
+
"object-top": web ? { objectPosition: "top" } : null,
|
|
1731
|
+
"object-bottom": web ? { objectPosition: "bottom" } : null,
|
|
1732
|
+
"object-left": web ? { objectPosition: "left" } : null,
|
|
1733
|
+
"object-right": web ? { objectPosition: "right" } : null,
|
|
1734
|
+
"object-left-top": web ? { objectPosition: "left top" } : null,
|
|
1735
|
+
"object-left-bottom": web ? { objectPosition: "left bottom" } : null,
|
|
1736
|
+
"object-right-top": web ? { objectPosition: "right top" } : null,
|
|
1737
|
+
"object-right-bottom": web ? { objectPosition: "right bottom" } : null,
|
|
1738
|
+
// Table (web-only)
|
|
1739
|
+
table: web ? { display: "table" } : null,
|
|
1740
|
+
"table-auto": web ? { tableLayout: "auto" } : null,
|
|
1741
|
+
"table-fixed": web ? { tableLayout: "fixed" } : null,
|
|
1742
|
+
"caption-top": web ? { captionSide: "top" } : null,
|
|
1743
|
+
"caption-bottom": web ? { captionSide: "bottom" } : null,
|
|
1744
|
+
"border-collapse": web ? { borderCollapse: "collapse" } : null,
|
|
1745
|
+
"border-separate": web ? { borderCollapse: "separate" } : null,
|
|
1746
|
+
// List style position (web-only)
|
|
1747
|
+
"list-inside": web ? { listStylePosition: "inside" } : null,
|
|
1748
|
+
"list-outside": web ? { listStylePosition: "outside" } : null,
|
|
1749
|
+
// Font variant numeric (web-only)
|
|
1750
|
+
"normal-nums": web ? { fontVariantNumeric: "normal" } : null,
|
|
1751
|
+
ordinal: web ? { fontVariantNumeric: "ordinal" } : null,
|
|
1752
|
+
"slashed-zero": web ? { fontVariantNumeric: "slashed-zero" } : null,
|
|
1753
|
+
"lining-nums": web ? { fontVariantNumeric: "lining-nums" } : null,
|
|
1754
|
+
"oldstyle-nums": web ? { fontVariantNumeric: "oldstyle-nums" } : null,
|
|
1755
|
+
"proportional-nums": web ? { fontVariantNumeric: "proportional-nums" } : null,
|
|
1756
|
+
"tabular-nums": web ? { fontVariantNumeric: "tabular-nums" } : null,
|
|
1757
|
+
"diagonal-fractions": web ? { fontVariantNumeric: "diagonal-fractions" } : null,
|
|
1758
|
+
"stacked-fractions": web ? { fontVariantNumeric: "stacked-fractions" } : null,
|
|
1759
|
+
// Isolation (web-only)
|
|
1760
|
+
isolate: web ? { isolation: "isolate" } : null,
|
|
1761
|
+
"isolation-auto": web ? { isolation: "auto" } : null,
|
|
1762
|
+
// Backface visibility (both iOS and Android)
|
|
1763
|
+
"backface-visible": { backfaceVisibility: "visible" },
|
|
1764
|
+
"backface-hidden": { backfaceVisibility: "hidden" },
|
|
1765
|
+
// CSS filters — standalone = default/full effect (web-only)
|
|
1766
|
+
grayscale: web ? { "--kb-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
|
|
1767
|
+
invert: web ? { "--kb-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
|
|
1768
|
+
sepia: web ? { "--kb-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
|
|
1769
|
+
// Divide none
|
|
1770
|
+
"divide-none": web ? { __divideX: 0, __divideY: 0 } : null,
|
|
1771
|
+
// Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
|
|
1772
|
+
group: web ? {} : null,
|
|
1773
|
+
peer: web ? {} : null,
|
|
1774
|
+
// Text-wrap (web-only)
|
|
1775
|
+
"text-wrap": web ? { textWrap: "wrap" } : null,
|
|
1776
|
+
"text-nowrap": web ? { textWrap: "nowrap" } : null,
|
|
1777
|
+
"text-balance": web ? { textWrap: "balance" } : null,
|
|
1778
|
+
"text-pretty": web ? { textWrap: "pretty" } : null,
|
|
1779
|
+
// Screen sizing — dvw/dvh (dynamic viewport units) instead of vw/vh: on mobile
|
|
1780
|
+
// browsers, vh/vw are pinned to the LARGEST viewport size (address bar hidden),
|
|
1781
|
+
// so `h-screen` overflows behind the address bar when it's shown. dvh/dvw track
|
|
1782
|
+
// the actual visible viewport as browser chrome shows/hides. Desktop behavior
|
|
1783
|
+
// is unchanged since there's no dynamic chrome to account for.
|
|
1784
|
+
// (vw/dvw values are web-only; vh/dvh values work cross-platform via spacing scale for h-*)
|
|
1785
|
+
"w-screen": web ? { width: "100dvw" } : null,
|
|
1786
|
+
"min-h-screen": { minHeight: "100dvh" },
|
|
1787
|
+
"max-h-screen": { maxHeight: "100dvh" },
|
|
1788
|
+
"min-w-screen": web ? { minWidth: "100dvw" } : null,
|
|
1789
|
+
"max-w-screen": web ? { maxWidth: "100dvw" } : null,
|
|
1790
|
+
// max-w named container sizes (mirrors Tailwind's container scale)
|
|
1791
|
+
"max-w-none": { maxWidth: "none" },
|
|
1792
|
+
"max-w-xs": { maxWidth: 320 },
|
|
1793
|
+
"max-w-sm": { maxWidth: 384 },
|
|
1794
|
+
"max-w-md": { maxWidth: 448 },
|
|
1795
|
+
"max-w-lg": { maxWidth: 512 },
|
|
1796
|
+
"max-w-xl": { maxWidth: 576 },
|
|
1797
|
+
"max-w-2xl": { maxWidth: 672 },
|
|
1798
|
+
"max-w-3xl": { maxWidth: 768 },
|
|
1799
|
+
"max-w-4xl": { maxWidth: 896 },
|
|
1800
|
+
"max-w-5xl": { maxWidth: 1024 },
|
|
1801
|
+
"max-w-6xl": { maxWidth: 1152 },
|
|
1802
|
+
"max-w-7xl": { maxWidth: 1280 },
|
|
1803
|
+
"max-w-prose": web ? { maxWidth: "65ch" } : null,
|
|
1804
|
+
// Extended cursors (web-only)
|
|
1805
|
+
"cursor-grab": web ? { cursor: "grab" } : null,
|
|
1806
|
+
"cursor-grabbing": web ? { cursor: "grabbing" } : null,
|
|
1807
|
+
"cursor-zoom-in": web ? { cursor: "zoom-in" } : null,
|
|
1808
|
+
"cursor-zoom-out": web ? { cursor: "zoom-out" } : null,
|
|
1809
|
+
"cursor-crosshair": web ? { cursor: "crosshair" } : null,
|
|
1810
|
+
"cursor-help": web ? { cursor: "help" } : null,
|
|
1811
|
+
"cursor-none": web ? { cursor: "none" } : null,
|
|
1812
|
+
// Overflow clip (web-only)
|
|
1813
|
+
"overflow-clip": web ? { overflow: "clip" } : null,
|
|
1814
|
+
"overflow-x-clip": web ? { overflowX: "clip" } : null,
|
|
1815
|
+
"overflow-y-clip": web ? { overflowY: "clip" } : null,
|
|
1816
|
+
// Scroll behavior (web-only)
|
|
1817
|
+
"scroll-smooth": web ? { scrollBehavior: "smooth" } : null,
|
|
1818
|
+
"scroll-auto": web ? { scrollBehavior: "auto" } : null,
|
|
1819
|
+
// Float (web-only)
|
|
1820
|
+
"float-left": web ? { float: "left" } : null,
|
|
1821
|
+
"float-right": web ? { float: "right" } : null,
|
|
1822
|
+
"float-start": web ? { float: "inline-start" } : null,
|
|
1823
|
+
"float-end": web ? { float: "inline-end" } : null,
|
|
1824
|
+
"float-none": web ? { float: "none" } : null,
|
|
1825
|
+
// Clear (web-only)
|
|
1826
|
+
"clear-left": web ? { clear: "left" } : null,
|
|
1827
|
+
"clear-right": web ? { clear: "right" } : null,
|
|
1828
|
+
"clear-both": web ? { clear: "both" } : null,
|
|
1829
|
+
"clear-start": web ? { clear: "inline-start" } : null,
|
|
1830
|
+
"clear-end": web ? { clear: "inline-end" } : null,
|
|
1831
|
+
"clear-none": web ? { clear: "none" } : null,
|
|
1832
|
+
// Vertical align (web-only)
|
|
1833
|
+
"align-baseline": web ? { verticalAlign: "baseline" } : null,
|
|
1834
|
+
"align-top": web ? { verticalAlign: "top" } : null,
|
|
1835
|
+
"align-middle": web ? { verticalAlign: "middle" } : null,
|
|
1836
|
+
"align-bottom": web ? { verticalAlign: "bottom" } : null,
|
|
1837
|
+
"align-text-top": web ? { verticalAlign: "text-top" } : null,
|
|
1838
|
+
"align-text-bottom": web ? { verticalAlign: "text-bottom" } : null,
|
|
1839
|
+
"align-sub": web ? { verticalAlign: "sub" } : null,
|
|
1840
|
+
"align-super": web ? { verticalAlign: "super" } : null,
|
|
1841
|
+
// Touch action (web-only)
|
|
1842
|
+
"touch-auto": web ? { touchAction: "auto" } : null,
|
|
1843
|
+
"touch-none": web ? { touchAction: "none" } : null,
|
|
1844
|
+
"touch-pan-x": web ? { touchAction: "pan-x" } : null,
|
|
1845
|
+
"touch-pan-y": web ? { touchAction: "pan-y" } : null,
|
|
1846
|
+
"touch-pan-left": web ? { touchAction: "pan-left" } : null,
|
|
1847
|
+
"touch-pan-right": web ? { touchAction: "pan-right" } : null,
|
|
1848
|
+
"touch-pan-up": web ? { touchAction: "pan-up" } : null,
|
|
1849
|
+
"touch-pan-down": web ? { touchAction: "pan-down" } : null,
|
|
1850
|
+
"touch-pinch-zoom": web ? { touchAction: "pinch-zoom" } : null,
|
|
1851
|
+
"touch-manipulation": web ? { touchAction: "manipulation" } : null
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
function getStandalone() {
|
|
1855
|
+
if (!_standalone) _standalone = buildStandalone();
|
|
1856
|
+
return _standalone;
|
|
1857
|
+
}
|
|
1858
|
+
var layoutResolvers = {
|
|
1859
|
+
// ── Grid (responsive column count: grid-1 … grid-12, or arbitrary) ───────
|
|
1860
|
+
grid: ({ value, isArbitrary }) => {
|
|
1861
|
+
if (!value) return null;
|
|
1862
|
+
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1863
|
+
const n = parseInt(value, 10);
|
|
1864
|
+
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1865
|
+
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1956
1866
|
},
|
|
1957
|
-
// ──
|
|
1958
|
-
|
|
1959
|
-
// .cls > * + * { border-... } CSS rules. No inline style is applied.
|
|
1960
|
-
"divide-x": ({ value, isArbitrary }) => {
|
|
1961
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1962
|
-
if (value === "reverse") return null;
|
|
1963
|
-
if (!value) return { __divideX: 1 };
|
|
1964
|
-
const n = parseFloat(value);
|
|
1965
|
-
return isNaN(n) ? null : { __divideX: n };
|
|
1966
|
-
},
|
|
1967
|
-
"divide-y": ({ value, isArbitrary }) => {
|
|
1968
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1969
|
-
if (value === "reverse") return null;
|
|
1970
|
-
if (!value) return { __divideY: 1 };
|
|
1971
|
-
const n = parseFloat(value);
|
|
1972
|
-
return isNaN(n) ? null : { __divideY: n };
|
|
1973
|
-
},
|
|
1974
|
-
divide: ({ value, isArbitrary }, { colors }) => {
|
|
1975
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1976
|
-
if (isArbitrary) return { __divideColor: value };
|
|
1977
|
-
const styleTokens = {
|
|
1978
|
-
solid: "solid",
|
|
1979
|
-
dashed: "dashed",
|
|
1980
|
-
dotted: "dotted",
|
|
1981
|
-
double: "double",
|
|
1982
|
-
none: "none"
|
|
1983
|
-
};
|
|
1984
|
-
if (value in styleTokens) return { __divideStyle: styleTokens[value] };
|
|
1985
|
-
const color = resolveColor(value, colors, false);
|
|
1986
|
-
return color ? { __divideColor: color } : null;
|
|
1987
|
-
},
|
|
1988
|
-
// ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
|
|
1989
|
-
// Named presets give cross-platform shadow; arbitrary is web-only.
|
|
1990
|
-
"text-shadow": ({ value, isArbitrary }, { colors }) => {
|
|
1991
|
-
if (value === "none") {
|
|
1992
|
-
return getEffectiveIsWeb() ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
|
|
1993
|
-
}
|
|
1994
|
-
const webPresets = {
|
|
1995
|
-
"": "0 2px 4px rgba(0,0,0,0.3)",
|
|
1996
|
-
sm: "0 1px 2px rgba(0,0,0,0.3)",
|
|
1997
|
-
md: "0 4px 6px rgba(0,0,0,0.3)",
|
|
1998
|
-
lg: "0 8px 16px rgba(0,0,0,0.5)",
|
|
1999
|
-
xl: "0 16px 32px rgba(0,0,0,0.5)"
|
|
2000
|
-
};
|
|
2001
|
-
const nativePresets = {
|
|
2002
|
-
"": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
|
|
2003
|
-
sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
|
|
2004
|
-
md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
|
|
2005
|
-
lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
|
|
2006
|
-
xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
|
|
2007
|
-
};
|
|
2008
|
-
if (value in webPresets) {
|
|
2009
|
-
if (getEffectiveIsWeb()) return { textShadow: webPresets[value] };
|
|
2010
|
-
return nativePresets[value] ?? null;
|
|
2011
|
-
}
|
|
2012
|
-
if (isArbitrary) {
|
|
2013
|
-
return getEffectiveIsWeb() ? { textShadow: value.replace(/_/g, " ") } : null;
|
|
2014
|
-
}
|
|
2015
|
-
const color = resolveColor(value, colors, false);
|
|
2016
|
-
if (color) {
|
|
2017
|
-
return getEffectiveIsWeb() ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
|
|
2018
|
-
}
|
|
2019
|
-
return null;
|
|
2020
|
-
},
|
|
2021
|
-
// ── Perspective transform (cross-platform: iOS, Android, web) ────────────
|
|
2022
|
-
perspective: ({ value, isArbitrary }) => {
|
|
2023
|
-
if (isArbitrary) {
|
|
2024
|
-
const numPx = parseFloat(value);
|
|
2025
|
-
if (getEffectiveIsWeb()) return { transform: `perspective(${value})` };
|
|
2026
|
-
return isNaN(numPx) ? null : { transform: [{ perspective: numPx }] };
|
|
2027
|
-
}
|
|
2028
|
-
if (value === "none") return getEffectiveIsWeb() ? { transform: "none" } : null;
|
|
2029
|
-
const n = parseFloat(value);
|
|
2030
|
-
if (isNaN(n)) return null;
|
|
2031
|
-
return getEffectiveIsWeb() ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
|
|
2032
|
-
},
|
|
2033
|
-
// ── Tint color (native-only, for Image and icon components) ──────────────
|
|
2034
|
-
tint: ({ value, isArbitrary }, { colors }) => {
|
|
2035
|
-
if (getEffectiveIsWeb()) return null;
|
|
2036
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
2037
|
-
return color ? { tintColor: color } : null;
|
|
2038
|
-
},
|
|
2039
|
-
// ── Size shorthand (sets width AND height in one utility) ────────────────
|
|
2040
|
-
size: ({ value, isArbitrary }, { spacing }) => {
|
|
2041
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
2042
|
-
return v !== null ? { width: v, height: v } : null;
|
|
2043
|
-
},
|
|
2044
|
-
// ── Animations (CSS keyframe animations, web-only) ────────────────────────
|
|
2045
|
-
// Each variant injects a @keyframes rule once via the __keyframe marker.
|
|
2046
|
-
// resolver.ts detects __keyframe, injects the rule, then strips the marker
|
|
2047
|
-
// so it never reaches element inline styles.
|
|
2048
|
-
animate: ({ value, isArbitrary }, theme) => {
|
|
1867
|
+
// ── Grid template columns/rows (Tailwind-style aliases, web-only) ──────────
|
|
1868
|
+
"grid-cols": ({ value, isArbitrary }) => {
|
|
2049
1869
|
if (!getEffectiveIsWeb()) return null;
|
|
2050
|
-
if (
|
|
2051
|
-
if (
|
|
2052
|
-
|
|
2053
|
-
|
|
1870
|
+
if (!value) return null;
|
|
1871
|
+
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1872
|
+
if (value === "none") return { display: "grid", gridTemplateColumns: "none" };
|
|
1873
|
+
const n = parseInt(value, 10);
|
|
1874
|
+
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1875
|
+
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
2054
1876
|
},
|
|
2055
|
-
|
|
2056
|
-
"line-clamp": ({ value }) => {
|
|
1877
|
+
"grid-rows": ({ value, isArbitrary }) => {
|
|
2057
1878
|
if (!getEffectiveIsWeb()) return null;
|
|
2058
|
-
if (value
|
|
1879
|
+
if (!value) return null;
|
|
1880
|
+
if (isArbitrary) return { gridTemplateRows: value };
|
|
1881
|
+
if (value === "none") return { gridTemplateRows: "none" };
|
|
2059
1882
|
const n = parseInt(value, 10);
|
|
2060
1883
|
if (isNaN(n) || n < 1) return null;
|
|
2061
|
-
return {
|
|
2062
|
-
overflow: "hidden",
|
|
2063
|
-
display: "-webkit-box",
|
|
2064
|
-
WebkitBoxOrient: "vertical",
|
|
2065
|
-
WebkitLineClamp: n
|
|
2066
|
-
};
|
|
1884
|
+
return { gridTemplateRows: `repeat(${n}, minmax(0, 1fr))` };
|
|
2067
1885
|
},
|
|
2068
|
-
// ──
|
|
2069
|
-
|
|
1886
|
+
// ── Grid auto flow (web-only) ─────────────────────────────────────────────
|
|
1887
|
+
"grid-flow": ({ value }) => {
|
|
2070
1888
|
if (!getEffectiveIsWeb()) return null;
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
1889
|
+
const flows = {
|
|
1890
|
+
row: "row",
|
|
1891
|
+
col: "column",
|
|
1892
|
+
dense: "dense",
|
|
1893
|
+
"row-dense": "row dense",
|
|
1894
|
+
"col-dense": "column dense"
|
|
1895
|
+
};
|
|
1896
|
+
const flow = flows[value];
|
|
1897
|
+
return flow ? { gridAutoFlow: flow } : null;
|
|
2074
1898
|
},
|
|
2075
|
-
// ──
|
|
2076
|
-
|
|
1899
|
+
// ── Grid auto sizing (web-only) ───────────────────────────────────────────
|
|
1900
|
+
"auto-cols": ({ value, isArbitrary }) => {
|
|
2077
1901
|
if (!getEffectiveIsWeb()) return null;
|
|
2078
|
-
if (
|
|
2079
|
-
const
|
|
2080
|
-
|
|
1902
|
+
if (isArbitrary) return { gridAutoColumns: value };
|
|
1903
|
+
const presets = {
|
|
1904
|
+
auto: "auto",
|
|
1905
|
+
min: "min-content",
|
|
1906
|
+
max: "max-content",
|
|
1907
|
+
fr: "minmax(0, 1fr)"
|
|
1908
|
+
};
|
|
1909
|
+
const v = presets[value];
|
|
1910
|
+
return v ? { gridAutoColumns: v } : null;
|
|
2081
1911
|
},
|
|
2082
|
-
|
|
2083
|
-
// Native is intentionally excluded: react-native-svg's <Path>/<Circle>/etc.
|
|
2084
|
-
// take stroke/fill as component PROPS, not style entries, so there's no
|
|
2085
|
-
// reliable way to apply a resolved color through the `style` prop there.
|
|
2086
|
-
// `stroke-{n}` sets strokeWidth (a plain number, unlike a color) — same
|
|
2087
|
-
// color-first-then-numeric-fallback disambiguation `border` uses above.
|
|
2088
|
-
stroke: ({ value, isArbitrary }, { colors }) => {
|
|
1912
|
+
"auto-rows": ({ value, isArbitrary }) => {
|
|
2089
1913
|
if (!getEffectiveIsWeb()) return null;
|
|
2090
|
-
if (
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
return isNaN(n) ? null : { strokeWidth: n };
|
|
1914
|
+
if (isArbitrary) return { gridAutoRows: value };
|
|
1915
|
+
const presets = {
|
|
1916
|
+
auto: "auto",
|
|
1917
|
+
min: "min-content",
|
|
1918
|
+
max: "max-content",
|
|
1919
|
+
fr: "minmax(0, 1fr)"
|
|
1920
|
+
};
|
|
1921
|
+
const v = presets[value];
|
|
1922
|
+
return v ? { gridAutoRows: v } : null;
|
|
2100
1923
|
},
|
|
2101
|
-
|
|
1924
|
+
// ── Grid column placement (web-only) ──────────────────────────────────────
|
|
1925
|
+
"col-span": ({ value }) => {
|
|
2102
1926
|
if (!getEffectiveIsWeb()) return null;
|
|
2103
|
-
if (
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
const color = resolveColor(value, colors, false);
|
|
2107
|
-
return color ? { fill: color } : null;
|
|
1927
|
+
if (value === "full") return { gridColumn: "1 / -1" };
|
|
1928
|
+
const n = parseInt(value, 10);
|
|
1929
|
+
return isNaN(n) ? null : { gridColumn: `span ${n} / span ${n}` };
|
|
2108
1930
|
},
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
if (
|
|
2112
|
-
if (isArbitrary) {
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
}
|
|
2116
|
-
if (value in flex) {
|
|
2117
|
-
const v = flex[value];
|
|
2118
|
-
if (typeof v === "string" && !getEffectiveIsWeb()) {
|
|
2119
|
-
if (v === "auto" || v === "initial") return { flex: 1 };
|
|
2120
|
-
if (v === "none") return { flex: 0 };
|
|
2121
|
-
return null;
|
|
2122
|
-
}
|
|
2123
|
-
return { flex: v };
|
|
2124
|
-
}
|
|
2125
|
-
const n = parseFloat(value);
|
|
2126
|
-
return isNaN(n) ? null : { flex: n };
|
|
1931
|
+
"col-start": ({ value, isArbitrary }) => {
|
|
1932
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1933
|
+
if (value === "auto") return { gridColumnStart: "auto" };
|
|
1934
|
+
if (isArbitrary) return { gridColumnStart: value };
|
|
1935
|
+
const n = parseInt(value, 10);
|
|
1936
|
+
return isNaN(n) ? null : { gridColumnStart: n };
|
|
2127
1937
|
},
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
1938
|
+
"col-end": ({ value, isArbitrary }) => {
|
|
1939
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1940
|
+
if (value === "auto") return { gridColumnEnd: "auto" };
|
|
1941
|
+
if (isArbitrary) return { gridColumnEnd: value };
|
|
1942
|
+
const n = parseInt(value, 10);
|
|
1943
|
+
return isNaN(n) ? null : { gridColumnEnd: n };
|
|
2131
1944
|
},
|
|
2132
|
-
|
|
2133
|
-
if (!
|
|
2134
|
-
|
|
2135
|
-
|
|
1945
|
+
col: ({ value, isArbitrary }) => {
|
|
1946
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1947
|
+
if (!value || value === "auto") return { gridColumn: "auto" };
|
|
1948
|
+
if (isArbitrary) return { gridColumn: value };
|
|
1949
|
+
return null;
|
|
2136
1950
|
},
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
return {
|
|
1951
|
+
// ── Grid row placement (web-only) ─────────────────────────────────────────
|
|
1952
|
+
"row-span": ({ value }) => {
|
|
1953
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1954
|
+
if (value === "full") return { gridRow: "1 / -1" };
|
|
1955
|
+
const n = parseInt(value, 10);
|
|
1956
|
+
return isNaN(n) ? null : { gridRow: `span ${n} / span ${n}` };
|
|
2141
1957
|
},
|
|
2142
|
-
|
|
1958
|
+
"row-start": ({ value, isArbitrary }) => {
|
|
1959
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1960
|
+
if (value === "auto") return { gridRowStart: "auto" };
|
|
1961
|
+
if (isArbitrary) return { gridRowStart: value };
|
|
2143
1962
|
const n = parseInt(value, 10);
|
|
2144
|
-
return isNaN(n) ? null : {
|
|
1963
|
+
return isNaN(n) ? null : { gridRowStart: n };
|
|
2145
1964
|
},
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
1965
|
+
"row-end": ({ value, isArbitrary }) => {
|
|
1966
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1967
|
+
if (value === "auto") return { gridRowEnd: "auto" };
|
|
1968
|
+
if (isArbitrary) return { gridRowEnd: value };
|
|
1969
|
+
const n = parseInt(value, 10);
|
|
1970
|
+
return isNaN(n) ? null : { gridRowEnd: n };
|
|
2150
1971
|
},
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
1972
|
+
row: ({ value, isArbitrary }) => {
|
|
1973
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1974
|
+
if (!value || value === "auto") return { gridRow: "auto" };
|
|
1975
|
+
if (isArbitrary) return { gridRow: value };
|
|
1976
|
+
return null;
|
|
2154
1977
|
},
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
1978
|
+
// ── Grid alignment (web-only) ──────────────────────────────────────────────
|
|
1979
|
+
// place-items is shorthand for align-items + justify-items on a grid container
|
|
1980
|
+
"place-items": ({ value }) => {
|
|
1981
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1982
|
+
const map = {
|
|
1983
|
+
start: "start",
|
|
1984
|
+
end: "end",
|
|
1985
|
+
center: "center",
|
|
1986
|
+
stretch: "stretch",
|
|
1987
|
+
baseline: "baseline"
|
|
1988
|
+
};
|
|
1989
|
+
return map[value] ? { placeItems: map[value] } : null;
|
|
2158
1990
|
},
|
|
2159
|
-
//
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
1991
|
+
// place-content is shorthand for align-content + justify-content on a grid container
|
|
1992
|
+
"place-content": ({ value }) => {
|
|
1993
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1994
|
+
const map = {
|
|
1995
|
+
start: "start",
|
|
1996
|
+
end: "end",
|
|
1997
|
+
center: "center",
|
|
1998
|
+
stretch: "stretch",
|
|
1999
|
+
between: "space-between",
|
|
2000
|
+
around: "space-around",
|
|
2001
|
+
evenly: "space-evenly",
|
|
2002
|
+
baseline: "baseline"
|
|
2003
|
+
};
|
|
2004
|
+
return map[value] ? { placeContent: map[value] } : null;
|
|
2163
2005
|
},
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2006
|
+
// justify-items controls inline-axis alignment of grid items within their cells
|
|
2007
|
+
"justify-items": ({ value }) => {
|
|
2008
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2009
|
+
const map = {
|
|
2010
|
+
start: "start",
|
|
2011
|
+
end: "end",
|
|
2012
|
+
center: "center",
|
|
2013
|
+
stretch: "stretch"
|
|
2014
|
+
};
|
|
2015
|
+
return map[value] ? { justifyItems: map[value] } : null;
|
|
2167
2016
|
},
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2017
|
+
// place-self is shorthand for align-self + justify-self on a grid item
|
|
2018
|
+
"place-self": ({ value }) => {
|
|
2019
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2020
|
+
const map = {
|
|
2021
|
+
auto: "auto",
|
|
2022
|
+
start: "start",
|
|
2023
|
+
end: "end",
|
|
2024
|
+
center: "center",
|
|
2025
|
+
stretch: "stretch"
|
|
2026
|
+
};
|
|
2027
|
+
return map[value] ? { placeSelf: map[value] } : null;
|
|
2171
2028
|
},
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2029
|
+
// justify-self controls inline-axis self-alignment of a grid item
|
|
2030
|
+
"justify-self": ({ value }) => {
|
|
2031
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2032
|
+
const map = {
|
|
2033
|
+
auto: "auto",
|
|
2034
|
+
start: "start",
|
|
2035
|
+
end: "end",
|
|
2036
|
+
center: "center",
|
|
2037
|
+
stretch: "stretch"
|
|
2038
|
+
};
|
|
2039
|
+
return map[value] ? { justifySelf: map[value] } : null;
|
|
2175
2040
|
},
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2041
|
+
// ── Flex ───────────────────────────────────────────────────────────────────
|
|
2042
|
+
// flex-1/flex-auto/flex-none/grow/shrink are item-level sizing properties —
|
|
2043
|
+
// deliberately NOT implying display:flex here. See the "Flex grow / shrink"
|
|
2044
|
+
// comment in the standalone table above for why: these already work via the
|
|
2045
|
+
// PARENT's flex context regardless of this element's own display, so
|
|
2046
|
+
// forcing display:flex here would only be a surprising, unrelated side
|
|
2047
|
+
// effect on this element's OWN children.
|
|
2048
|
+
flex: ({ value, isArbitrary }, { flex }) => {
|
|
2049
|
+
if (!value) return { display: "flex" };
|
|
2050
|
+
if (isArbitrary) {
|
|
2051
|
+
const v = parseFloat(value);
|
|
2052
|
+
return isNaN(v) ? null : { flex: v };
|
|
2053
|
+
}
|
|
2054
|
+
if (value in flex) {
|
|
2055
|
+
const v = flex[value];
|
|
2056
|
+
if (typeof v === "string" && !getEffectiveIsWeb()) {
|
|
2057
|
+
if (v === "auto" || v === "initial") return { flex: 1 };
|
|
2058
|
+
if (v === "none") return { flex: 0 };
|
|
2059
|
+
return null;
|
|
2060
|
+
}
|
|
2061
|
+
return { flex: v };
|
|
2062
|
+
}
|
|
2063
|
+
const n = parseFloat(value);
|
|
2064
|
+
return isNaN(n) ? null : { flex: n };
|
|
2179
2065
|
},
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2066
|
+
grow: ({ value }, _) => {
|
|
2067
|
+
if (!value) return { flexGrow: 1 };
|
|
2068
|
+
const n = parseFloat(value);
|
|
2069
|
+
return { flexGrow: isNaN(n) ? 1 : n };
|
|
2183
2070
|
},
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2071
|
+
shrink: ({ value }, _) => {
|
|
2072
|
+
if (!value) return { flexShrink: 1 };
|
|
2073
|
+
const n = parseFloat(value);
|
|
2074
|
+
return { flexShrink: isNaN(n) ? 1 : n };
|
|
2075
|
+
},
|
|
2076
|
+
order: ({ value, negative }, _) => {
|
|
2077
|
+
const n = parseInt(value, 10);
|
|
2078
|
+
return isNaN(n) ? null : { order: negative ? -n : n };
|
|
2187
2079
|
},
|
|
2188
2080
|
// ── Z-index ────────────────────────────────────────────────────────────────
|
|
2189
2081
|
z: ({ value, isArbitrary }, { zIndex }) => {
|
|
@@ -2199,16 +2091,118 @@ var RESOLVERS = {
|
|
|
2199
2091
|
const n = parseInt(value);
|
|
2200
2092
|
return isNaN(n) ? null : { zIndex: n };
|
|
2201
2093
|
},
|
|
2202
|
-
// ──
|
|
2203
|
-
|
|
2094
|
+
// ── Aspect ratio ───────────────────────────────────────────────────────────
|
|
2095
|
+
aspect: ({ value, isArbitrary }) => {
|
|
2096
|
+
if (isArbitrary) return { aspectRatio: value };
|
|
2097
|
+
const presets = { auto: "auto", square: 1, video: 16 / 9 };
|
|
2098
|
+
if (!(value in presets)) return null;
|
|
2099
|
+
const v = presets[value];
|
|
2100
|
+
if (v === "auto") return getEffectiveIsWeb() ? { aspectRatio: "auto" } : null;
|
|
2101
|
+
return { aspectRatio: v };
|
|
2102
|
+
},
|
|
2103
|
+
// ── Columns (web-only) ─────────────────────────────────────────────────────
|
|
2104
|
+
columns: ({ value, isArbitrary }) => {
|
|
2105
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2106
|
+
if (isArbitrary) return { columnCount: value };
|
|
2107
|
+
if (value === "auto") return { columnCount: "auto" };
|
|
2108
|
+
const n = parseInt(value, 10);
|
|
2109
|
+
if (!isNaN(n)) return { columnCount: n };
|
|
2110
|
+
const widths = {
|
|
2111
|
+
"3xs": "16rem",
|
|
2112
|
+
"2xs": "18rem",
|
|
2113
|
+
xs: "20rem",
|
|
2114
|
+
sm: "24rem",
|
|
2115
|
+
md: "28rem",
|
|
2116
|
+
lg: "32rem",
|
|
2117
|
+
xl: "36rem",
|
|
2118
|
+
"2xl": "42rem",
|
|
2119
|
+
"3xl": "48rem",
|
|
2120
|
+
"4xl": "56rem",
|
|
2121
|
+
"5xl": "64rem",
|
|
2122
|
+
"6xl": "72rem",
|
|
2123
|
+
"7xl": "80rem"
|
|
2124
|
+
};
|
|
2125
|
+
return widths[value] ? { columnWidth: widths[value] } : null;
|
|
2126
|
+
}
|
|
2127
|
+
};
|
|
2128
|
+
|
|
2129
|
+
// src/core/resolvers/typography.ts
|
|
2130
|
+
function resolveFontSize(value, fontSizes, isArbitrary) {
|
|
2131
|
+
if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
2132
|
+
return fontSizes[value] ?? null;
|
|
2133
|
+
}
|
|
2134
|
+
var typographyResolvers = {
|
|
2135
|
+
// ── Text ───────────────────────────────────────────────────────────────────
|
|
2136
|
+
text: ({ value, isArbitrary }, { colors, fontSize }) => {
|
|
2137
|
+
const size = resolveFontSize(value, fontSize, false);
|
|
2138
|
+
if (!isArbitrary && size !== null) return { fontSize: size };
|
|
2204
2139
|
if (isArbitrary) {
|
|
2205
|
-
|
|
2206
|
-
|
|
2140
|
+
if (/^\d/.test(value) || /^(calc|min|max|clamp)/.test(value)) {
|
|
2141
|
+
return { fontSize: getEffectiveIsWeb() ? value : toNativeValue(value) };
|
|
2142
|
+
}
|
|
2143
|
+
return { color: getEffectiveIsWeb() ? withOpacityVar(value, "--text-opacity") : value };
|
|
2207
2144
|
}
|
|
2208
|
-
const
|
|
2209
|
-
if (
|
|
2145
|
+
const color = resolveColor(value, colors, false);
|
|
2146
|
+
if (!color) return null;
|
|
2147
|
+
return { color: getEffectiveIsWeb() ? withOpacityVar(color, "--text-opacity") : color };
|
|
2148
|
+
},
|
|
2149
|
+
"text-opacity": ({ value, isArbitrary }, _) => {
|
|
2150
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2210
2151
|
const n = parseFloat(value);
|
|
2211
|
-
|
|
2152
|
+
if (isNaN(n)) return null;
|
|
2153
|
+
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
2154
|
+
return { "--text-opacity": v };
|
|
2155
|
+
},
|
|
2156
|
+
// ── Text decoration advanced (web-only) ───────────────────────────────────
|
|
2157
|
+
decoration: ({ value, isArbitrary }, { colors }) => {
|
|
2158
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2159
|
+
if (isArbitrary) {
|
|
2160
|
+
if (/^\d/.test(value) || value.startsWith("calc(")) return { textDecorationThickness: value };
|
|
2161
|
+
return { textDecorationColor: value };
|
|
2162
|
+
}
|
|
2163
|
+
const thickTokens = {
|
|
2164
|
+
auto: "auto",
|
|
2165
|
+
"from-font": "from-font",
|
|
2166
|
+
"0": "0px",
|
|
2167
|
+
"1": "1px",
|
|
2168
|
+
"2": "2px",
|
|
2169
|
+
"4": "4px",
|
|
2170
|
+
"8": "8px"
|
|
2171
|
+
};
|
|
2172
|
+
if (value in thickTokens) return { textDecorationThickness: thickTokens[value] };
|
|
2173
|
+
const styleTokens = {
|
|
2174
|
+
solid: "solid",
|
|
2175
|
+
dashed: "dashed",
|
|
2176
|
+
dotted: "dotted",
|
|
2177
|
+
double: "double",
|
|
2178
|
+
wavy: "wavy"
|
|
2179
|
+
};
|
|
2180
|
+
if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
|
|
2181
|
+
const color = resolveColor(value, colors, false);
|
|
2182
|
+
return color ? { textDecorationColor: color } : null;
|
|
2183
|
+
},
|
|
2184
|
+
"underline-offset": ({ value, isArbitrary }) => {
|
|
2185
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2186
|
+
if (isArbitrary) return { textUnderlineOffset: value };
|
|
2187
|
+
const offsets = {
|
|
2188
|
+
auto: "auto",
|
|
2189
|
+
"0": "0px",
|
|
2190
|
+
"1": "1px",
|
|
2191
|
+
"2": "2px",
|
|
2192
|
+
"4": "4px",
|
|
2193
|
+
"8": "8px"
|
|
2194
|
+
};
|
|
2195
|
+
return offsets[value] ? { textUnderlineOffset: offsets[value] } : null;
|
|
2196
|
+
},
|
|
2197
|
+
// ── Content (web-only — for before:/after: pseudo-elements, which don't exist on native) ──
|
|
2198
|
+
// Arbitrary value carries its own quotes from the bracket syntax (content-['*'] parses to
|
|
2199
|
+
// the literal string 'you can see it' quotes included), so it passes straight through as a
|
|
2200
|
+
// valid `content: '*'` CSS value with no extra wrapping needed.
|
|
2201
|
+
content: ({ value, isArbitrary }) => {
|
|
2202
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2203
|
+
if (isArbitrary) return { content: value };
|
|
2204
|
+
const presets = { none: "none" };
|
|
2205
|
+
return value in presets ? { content: presets[value] } : null;
|
|
2212
2206
|
},
|
|
2213
2207
|
// ── Font ───────────────────────────────────────────────────────────────────
|
|
2214
2208
|
font: ({ value, isArbitrary }, { fontFamily, fontWeight }) => {
|
|
@@ -2234,10 +2228,57 @@ var RESOLVERS = {
|
|
|
2234
2228
|
const v = letterSpacing[value];
|
|
2235
2229
|
return v !== void 0 ? { letterSpacing: v } : null;
|
|
2236
2230
|
},
|
|
2237
|
-
// ──
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
return
|
|
2231
|
+
// ── Line-clamp (web-only) ─────────────────────────────────────────────────
|
|
2232
|
+
"line-clamp": ({ value }) => {
|
|
2233
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2234
|
+
if (value === "none") return { overflow: "visible", display: "block", WebkitLineClamp: "unset" };
|
|
2235
|
+
const n = parseInt(value, 10);
|
|
2236
|
+
if (isNaN(n) || n < 1) return null;
|
|
2237
|
+
return {
|
|
2238
|
+
overflow: "hidden",
|
|
2239
|
+
display: "-webkit-box",
|
|
2240
|
+
WebkitBoxOrient: "vertical",
|
|
2241
|
+
WebkitLineClamp: n
|
|
2242
|
+
};
|
|
2243
|
+
}
|
|
2244
|
+
};
|
|
2245
|
+
|
|
2246
|
+
// src/core/resolvers/transform.ts
|
|
2247
|
+
var transformResolvers = {
|
|
2248
|
+
// ── Transform extras (web-only) ───────────────────────────────────────────
|
|
2249
|
+
"skew-x": ({ value, negative, isArbitrary }) => {
|
|
2250
|
+
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
2251
|
+
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2252
|
+
return getEffectiveIsWeb() ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
|
|
2253
|
+
},
|
|
2254
|
+
"skew-y": ({ value, negative, isArbitrary }) => {
|
|
2255
|
+
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
2256
|
+
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2257
|
+
return getEffectiveIsWeb() ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
|
|
2258
|
+
},
|
|
2259
|
+
// Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
|
|
2260
|
+
transform: ({ value, isArbitrary }) => {
|
|
2261
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2262
|
+
if (isArbitrary) return { transform: value.replace(/_/g, " ") };
|
|
2263
|
+
if (value === "none") return { transform: "none" };
|
|
2264
|
+
return null;
|
|
2265
|
+
},
|
|
2266
|
+
// Transform origin
|
|
2267
|
+
origin: ({ value, isArbitrary }) => {
|
|
2268
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2269
|
+
if (isArbitrary) return { transformOrigin: value.replace(/_/g, " ") };
|
|
2270
|
+
const origins = {
|
|
2271
|
+
center: "center",
|
|
2272
|
+
top: "top",
|
|
2273
|
+
"top-right": "top right",
|
|
2274
|
+
right: "right",
|
|
2275
|
+
"bottom-right": "bottom right",
|
|
2276
|
+
bottom: "bottom",
|
|
2277
|
+
"bottom-left": "bottom left",
|
|
2278
|
+
left: "left",
|
|
2279
|
+
"top-left": "top left"
|
|
2280
|
+
};
|
|
2281
|
+
return origins[value] ? { transformOrigin: origins[value] } : null;
|
|
2241
2282
|
},
|
|
2242
2283
|
// ── Scale ──────────────────────────────────────────────────────────────────
|
|
2243
2284
|
// Non-arbitrary: scale-150 → value='150' → 150/100 = 1.5
|
|
@@ -2268,35 +2309,86 @@ var RESOLVERS = {
|
|
|
2268
2309
|
const finalDeg = negative ? -deg : deg;
|
|
2269
2310
|
return getEffectiveIsWeb() ? { transform: `rotate(${finalDeg}deg)` } : { transform: [{ rotate: `${finalDeg}deg` }] };
|
|
2270
2311
|
},
|
|
2271
|
-
// ──
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2312
|
+
// ── Perspective transform (cross-platform: iOS, Android, web) ────────────
|
|
2313
|
+
perspective: ({ value, isArbitrary }) => {
|
|
2314
|
+
if (isArbitrary) {
|
|
2315
|
+
const numPx = parseFloat(value);
|
|
2316
|
+
if (getEffectiveIsWeb()) return { transform: `perspective(${value})` };
|
|
2317
|
+
return isNaN(numPx) ? null : { transform: [{ perspective: numPx }] };
|
|
2318
|
+
}
|
|
2319
|
+
if (value === "none") return getEffectiveIsWeb() ? { transform: "none" } : null;
|
|
2320
|
+
const n = parseFloat(value);
|
|
2321
|
+
if (isNaN(n)) return null;
|
|
2322
|
+
return getEffectiveIsWeb() ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
|
|
2323
|
+
}
|
|
2324
|
+
};
|
|
2325
|
+
|
|
2326
|
+
// src/core/resolvers/effects.ts
|
|
2327
|
+
function keyframeDeclToCSS(decl) {
|
|
2328
|
+
return Object.entries(decl).map(([prop, val]) => `${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${val}`).join("; ");
|
|
2329
|
+
}
|
|
2330
|
+
function buildKeyframeCSS(name, steps) {
|
|
2331
|
+
const body = Object.entries(steps).map(([selector, decl]) => `${selector} { ${keyframeDeclToCSS(decl)} }`).join(" ");
|
|
2332
|
+
return `@keyframes ${name} { ${body} }`;
|
|
2333
|
+
}
|
|
2334
|
+
var BUILTIN_ANIMATIONS = {
|
|
2335
|
+
none: { animation: "none" },
|
|
2336
|
+
spin: {
|
|
2337
|
+
animation: "kb-spin 1s linear infinite",
|
|
2338
|
+
__keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
|
|
2339
|
+
},
|
|
2340
|
+
ping: {
|
|
2341
|
+
animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
|
|
2342
|
+
__keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
|
|
2343
|
+
},
|
|
2344
|
+
pulse: {
|
|
2345
|
+
animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
|
|
2346
|
+
__keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
|
|
2347
|
+
},
|
|
2348
|
+
bounce: {
|
|
2349
|
+
animation: "kb-bounce 1s infinite",
|
|
2350
|
+
__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) } }"
|
|
2351
|
+
}
|
|
2352
|
+
};
|
|
2353
|
+
function buildAnimationValue(animation, keyframes) {
|
|
2354
|
+
const words = animation.trim().split(/\s+/);
|
|
2355
|
+
const name = words[0];
|
|
2356
|
+
if (!name) return { animation };
|
|
2357
|
+
const builtin = BUILTIN_ANIMATIONS[name];
|
|
2358
|
+
if (builtin?.__keyframe) {
|
|
2359
|
+
const kbName = builtin.animation.split(/\s+/, 1)[0];
|
|
2360
|
+
return { animation: [kbName, ...words.slice(1)].join(" "), __keyframe: builtin.__keyframe };
|
|
2361
|
+
}
|
|
2362
|
+
const steps = keyframes?.[name];
|
|
2363
|
+
return steps ? { animation, __keyframe: buildKeyframeCSS(name, steps) } : { animation };
|
|
2364
|
+
}
|
|
2365
|
+
var effectResolvers = {
|
|
2366
|
+
// ── Opacity ────────────────────────────────────────────────────────────────
|
|
2367
|
+
opacity: ({ value, isArbitrary }, { opacity }) => {
|
|
2368
|
+
if (isArbitrary) {
|
|
2369
|
+
const v2 = parseFloat(value);
|
|
2370
|
+
return isNaN(v2) ? null : { opacity: v2 > 1 ? v2 / 100 : v2 };
|
|
2279
2371
|
}
|
|
2280
|
-
|
|
2372
|
+
const v = opacity[value];
|
|
2373
|
+
if (v !== void 0) return { opacity: v };
|
|
2374
|
+
const n = parseFloat(value);
|
|
2375
|
+
return isNaN(n) ? null : { opacity: n > 1 ? n / 100 : n };
|
|
2281
2376
|
},
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
if (typeof v === "string") {
|
|
2287
|
-
const n = parseFloat(v);
|
|
2288
|
-
return isNaN(n) ? null : { transform: [{ translateY: n }] };
|
|
2289
|
-
}
|
|
2290
|
-
return { transform: [{ translateY: v }] };
|
|
2377
|
+
// ── Shadow ─────────────────────────────────────────────────────────────────
|
|
2378
|
+
shadow: ({ value }, { shadow }) => {
|
|
2379
|
+
const key = value === "" ? "DEFAULT" : value;
|
|
2380
|
+
return shadow[key] ?? null;
|
|
2291
2381
|
},
|
|
2292
|
-
// ──
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
if (
|
|
2299
|
-
|
|
2382
|
+
// ── Animations (CSS keyframe animations, web-only) ────────────────────────
|
|
2383
|
+
// Each variant injects a @keyframes rule once via the __keyframe marker.
|
|
2384
|
+
// resolver.ts detects __keyframe, injects the rule, then strips the marker
|
|
2385
|
+
// so it never reaches element inline styles.
|
|
2386
|
+
animate: ({ value, isArbitrary }, theme) => {
|
|
2387
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2388
|
+
if (isArbitrary) return buildAnimationValue(value.replace(/_/g, " "), theme.keyframes);
|
|
2389
|
+
if (value in BUILTIN_ANIMATIONS) return BUILTIN_ANIMATIONS[value];
|
|
2390
|
+
const custom = theme.animation?.[value];
|
|
2391
|
+
return custom ? buildAnimationValue(custom, theme.keyframes) : null;
|
|
2300
2392
|
},
|
|
2301
2393
|
// ── Transition (web-only; use Animated API on native) ─────────────────────
|
|
2302
2394
|
transition: ({ value }) => {
|
|
@@ -2324,91 +2416,107 @@ var RESOLVERS = {
|
|
|
2324
2416
|
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2325
2417
|
const ms = isArbitrary ? value : `${value}ms`;
|
|
2326
2418
|
return { transitionDelay: ms };
|
|
2419
|
+
}
|
|
2420
|
+
};
|
|
2421
|
+
|
|
2422
|
+
// src/core/resolvers/misc.ts
|
|
2423
|
+
var miscResolvers = {
|
|
2424
|
+
// ── Arbitrary CSS property (web-only): [property:value] with no utility prefix ──
|
|
2425
|
+
// e.g. [mask-type:luminance], [--my-var:10px]. parser.ts already isolates this case
|
|
2426
|
+
// as utility: '' — it's ALSO how a stray, prefix-less negative bracket ("-[10px]",
|
|
2427
|
+
// presumably a typo) parses, which is why this only fires when the arbitrary value
|
|
2428
|
+
// itself contains a "property:value" pair; anything else (no colon) still resolves
|
|
2429
|
+
// to null exactly as before this resolver existed, rather than guessing a property.
|
|
2430
|
+
//
|
|
2431
|
+
// Only the FIRST colon splits property from value — the value itself may contain
|
|
2432
|
+
// more colons (a URL's "http://…") and must stay intact: [background:url(http://x/a.png)].
|
|
2433
|
+
// camelToKebab() in resolver.ts is a no-op on an already-kebab-case (or "--"-prefixed
|
|
2434
|
+
// custom property) key, so it can be used as the style object key as-written with no
|
|
2435
|
+
// extra case conversion — it only needs to look like a plausible CSS property name.
|
|
2436
|
+
"": ({ value, isArbitrary, negative }) => {
|
|
2437
|
+
if (!getEffectiveIsWeb() || !isArbitrary || !value) return null;
|
|
2438
|
+
if (negative) return null;
|
|
2439
|
+
const colonIdx = value.indexOf(":");
|
|
2440
|
+
if (colonIdx <= 0) return null;
|
|
2441
|
+
const prop = value.slice(0, colonIdx).trim();
|
|
2442
|
+
const cssValue = value.slice(colonIdx + 1).trim();
|
|
2443
|
+
if (!cssValue || !/^(--[\w-]+|[a-zA-Z-]+)$/.test(prop)) return null;
|
|
2444
|
+
return { [prop]: cssValue };
|
|
2327
2445
|
},
|
|
2328
|
-
// ──
|
|
2329
|
-
//
|
|
2330
|
-
//
|
|
2331
|
-
//
|
|
2332
|
-
//
|
|
2333
|
-
//
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
if (!value) {
|
|
2342
|
-
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
2446
|
+
// ── SVG stroke/fill (web-only) ────────────────────────────────────────────
|
|
2447
|
+
// Native is intentionally excluded: react-native-svg's <Path>/<Circle>/etc.
|
|
2448
|
+
// take stroke/fill as component PROPS, not style entries, so there's no
|
|
2449
|
+
// reliable way to apply a resolved color through the `style` prop there.
|
|
2450
|
+
// `stroke-{n}` sets strokeWidth (a plain number, unlike a color) — same
|
|
2451
|
+
// color-first-then-numeric-fallback disambiguation `border` uses above.
|
|
2452
|
+
stroke: ({ value, isArbitrary }, { colors }) => {
|
|
2453
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2454
|
+
if (!value) return null;
|
|
2455
|
+
if (value === "none") return { stroke: "none" };
|
|
2456
|
+
if (isArbitrary) {
|
|
2457
|
+
const w = toNativeValue(value);
|
|
2458
|
+
return typeof w === "number" ? { strokeWidth: w } : { stroke: value };
|
|
2343
2459
|
}
|
|
2344
|
-
|
|
2345
|
-
|
|
2460
|
+
const color = resolveColor(value, colors, false);
|
|
2461
|
+
if (color) return { stroke: color };
|
|
2462
|
+
const n = parseFloat(value);
|
|
2463
|
+
return isNaN(n) ? null : { strokeWidth: n };
|
|
2464
|
+
},
|
|
2465
|
+
fill: ({ value, isArbitrary }, { colors }) => {
|
|
2466
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2467
|
+
if (!value) return null;
|
|
2468
|
+
if (value === "none") return { fill: "none" };
|
|
2469
|
+
if (isArbitrary) return { fill: value };
|
|
2470
|
+
const color = resolveColor(value, colors, false);
|
|
2471
|
+
return color ? { fill: color } : null;
|
|
2472
|
+
},
|
|
2473
|
+
// ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
|
|
2474
|
+
// Named presets give cross-platform shadow; arbitrary is web-only.
|
|
2475
|
+
"text-shadow": ({ value, isArbitrary }, { colors }) => {
|
|
2476
|
+
if (value === "none") {
|
|
2477
|
+
return getEffectiveIsWeb() ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
|
|
2346
2478
|
}
|
|
2347
|
-
const
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2479
|
+
const webPresets = {
|
|
2480
|
+
"": "0 2px 4px rgba(0,0,0,0.3)",
|
|
2481
|
+
sm: "0 1px 2px rgba(0,0,0,0.3)",
|
|
2482
|
+
md: "0 4px 6px rgba(0,0,0,0.3)",
|
|
2483
|
+
lg: "0 8px 16px rgba(0,0,0,0.5)",
|
|
2484
|
+
xl: "0 16px 32px rgba(0,0,0,0.5)"
|
|
2485
|
+
};
|
|
2486
|
+
const nativePresets = {
|
|
2487
|
+
"": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
|
|
2488
|
+
sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
|
|
2489
|
+
md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
|
|
2490
|
+
lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
|
|
2491
|
+
xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
|
|
2492
|
+
};
|
|
2493
|
+
if (value in webPresets) {
|
|
2494
|
+
if (getEffectiveIsWeb()) return { textShadow: webPresets[value] };
|
|
2495
|
+
return nativePresets[value] ?? null;
|
|
2351
2496
|
}
|
|
2352
2497
|
if (isArbitrary) {
|
|
2353
|
-
|
|
2354
|
-
if (numMatch) {
|
|
2355
|
-
const unit = numMatch[2] ?? "px";
|
|
2356
|
-
if (onWeb) return { boxShadow: `0 0 0 ${numMatch[1]}${unit} ${DEFAULT_COLOR}` };
|
|
2357
|
-
return unit === "px" ? asNative(parseFloat(numMatch[1]), DEFAULT_COLOR) : null;
|
|
2358
|
-
}
|
|
2359
|
-
return onWeb ? { boxShadow: value.replace(/_/g, " ") } : null;
|
|
2498
|
+
return getEffectiveIsWeb() ? { textShadow: value.replace(/_/g, " ") } : null;
|
|
2360
2499
|
}
|
|
2361
2500
|
const color = resolveColor(value, colors, false);
|
|
2362
2501
|
if (color) {
|
|
2363
|
-
return
|
|
2502
|
+
return getEffectiveIsWeb() ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
|
|
2364
2503
|
}
|
|
2365
2504
|
return null;
|
|
2366
|
-
},
|
|
2367
|
-
// Web-only, unlike `ring` above: this stacks a second box-shadow layer to
|
|
2368
|
-
// create a gap between the element and the ring. There's no native
|
|
2369
|
-
// equivalent to approximate that with (a border can't create a gap outside
|
|
2370
|
-
// its own element without an extra wrapper view), so this stays a no-op
|
|
2371
|
-
// on native rather than rendering a misleading half-translation.
|
|
2372
|
-
"ring-offset": ({ value, isArbitrary }, _theme) => {
|
|
2373
|
-
if (!getEffectiveIsWeb()) return null;
|
|
2374
|
-
const DEFAULT_RING_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
2375
|
-
const DEFAULT_RING_WIDTH = 3;
|
|
2376
|
-
const offsetTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
2377
|
-
let offsetWidth;
|
|
2378
|
-
if (!isArbitrary) {
|
|
2379
|
-
offsetWidth = value in offsetTokens ? offsetTokens[value] : null;
|
|
2380
|
-
} else {
|
|
2381
|
-
offsetWidth = /^-?\d+(\.\d+)?$/.test(value) ? parseFloat(value) : value;
|
|
2382
|
-
}
|
|
2383
|
-
if (offsetWidth === null || typeof offsetWidth === "number" && isNaN(offsetWidth)) return null;
|
|
2384
|
-
const isZero = offsetWidth === 0 || offsetWidth === "0";
|
|
2385
|
-
const offsetCss = typeof offsetWidth === "number" ? `${offsetWidth}px` : offsetWidth;
|
|
2386
|
-
return {
|
|
2387
|
-
boxShadow: isZero ? `0 0 0 ${DEFAULT_RING_WIDTH}px ${DEFAULT_RING_COLOR}` : `0 0 0 ${offsetCss} #fff, 0 0 0 calc(${offsetCss} + ${DEFAULT_RING_WIDTH}px) ${DEFAULT_RING_COLOR}`
|
|
2388
|
-
};
|
|
2389
|
-
},
|
|
2390
|
-
// ── Space between ─────────────────────────────────────────────────────────
|
|
2391
|
-
// On web: emits __spaceX/__spaceY markers → resolver generates > * + * CSS rules.
|
|
2392
|
-
// On native (RN 0.71+): uses columnGap/rowGap directly.
|
|
2393
|
-
"space-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2394
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2395
|
-
if (v === null) return null;
|
|
2396
|
-
if (getEffectiveIsWeb()) return { __spaceX: v };
|
|
2397
|
-
return { columnGap: v };
|
|
2398
|
-
},
|
|
2399
|
-
"space-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2400
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2401
|
-
if (v === null) return null;
|
|
2402
|
-
if (getEffectiveIsWeb()) return { __spaceY: v };
|
|
2403
|
-
return { rowGap: v };
|
|
2404
2505
|
}
|
|
2405
2506
|
};
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2507
|
+
|
|
2508
|
+
// src/core/utilities.ts
|
|
2509
|
+
var RESOLVERS = {
|
|
2510
|
+
...colorResolvers,
|
|
2511
|
+
...spacingResolvers,
|
|
2512
|
+
...borderResolvers,
|
|
2513
|
+
...layoutResolvers,
|
|
2514
|
+
...typographyResolvers,
|
|
2515
|
+
...filterResolvers,
|
|
2516
|
+
...transformResolvers,
|
|
2517
|
+
...effectResolvers,
|
|
2518
|
+
...miscResolvers
|
|
2519
|
+
};
|
|
2412
2520
|
var NAMED_GROUP_PEER_MARKER_RE = /^(group|peer)\/.+$/;
|
|
2413
2521
|
function resolveUtility(parsed, theme) {
|
|
2414
2522
|
if (!parsed.value) {
|
|
@@ -2640,85 +2748,35 @@ var BASE_RESET = [
|
|
|
2640
2748
|
"table { border-collapse: collapse; border-spacing: 0; }"
|
|
2641
2749
|
].join("\n");
|
|
2642
2750
|
|
|
2643
|
-
// src/core/cache.ts
|
|
2644
|
-
var LRUCache = class {
|
|
2645
|
-
constructor(capacity = 1e4, onEvict) {
|
|
2646
|
-
this.capacity = capacity;
|
|
2647
|
-
if (capacity <= 0) throw new Error("LRUCache: capacity must be a positive integer");
|
|
2648
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
2649
|
-
this.onEvict = onEvict;
|
|
2650
|
-
}
|
|
2651
|
-
get(key) {
|
|
2652
|
-
if (!this.cache.has(key)) return void 0;
|
|
2653
|
-
const value = this.cache.get(key);
|
|
2654
|
-
this.cache.delete(key);
|
|
2655
|
-
this.cache.set(key, value);
|
|
2656
|
-
return value;
|
|
2657
|
-
}
|
|
2658
|
-
set(key, value) {
|
|
2659
|
-
if (this.cache.has(key)) {
|
|
2660
|
-
this.cache.delete(key);
|
|
2661
|
-
} else if (this.cache.size >= this.capacity) {
|
|
2662
|
-
const oldestKey = this.cache.keys().next().value;
|
|
2663
|
-
const oldestValue = this.cache.get(oldestKey);
|
|
2664
|
-
this.cache.delete(oldestKey);
|
|
2665
|
-
this.onEvict?.(oldestKey, oldestValue);
|
|
2666
|
-
}
|
|
2667
|
-
this.cache.set(key, value);
|
|
2668
|
-
return this;
|
|
2669
|
-
}
|
|
2670
|
-
has(key) {
|
|
2671
|
-
return this.cache.has(key);
|
|
2672
|
-
}
|
|
2673
|
-
delete(key) {
|
|
2674
|
-
return this.cache.delete(key);
|
|
2675
|
-
}
|
|
2676
|
-
clear() {
|
|
2677
|
-
this.cache.clear();
|
|
2678
|
-
}
|
|
2679
|
-
get size() {
|
|
2680
|
-
return this.cache.size;
|
|
2681
|
-
}
|
|
2682
|
-
};
|
|
2683
|
-
|
|
2684
2751
|
// src/core/responsiveStore.ts
|
|
2685
|
-
var
|
|
2686
|
-
function getStore() {
|
|
2687
|
-
const g = globalThis;
|
|
2688
|
-
if (!g[RESPONSIVE_KEY]) {
|
|
2689
|
-
g[RESPONSIVE_KEY] = { width: 0, notifiedWidth: 0, screens: {}, listeners: /* @__PURE__ */ new Set() };
|
|
2690
|
-
}
|
|
2691
|
-
return g[RESPONSIVE_KEY];
|
|
2692
|
-
}
|
|
2752
|
+
var store = { width: 0, notifiedWidth: 0, screens: {}, listeners: /* @__PURE__ */ new Set() };
|
|
2693
2753
|
function syncGlobalWidth(width) {
|
|
2694
|
-
|
|
2754
|
+
store.width = width;
|
|
2695
2755
|
}
|
|
2696
2756
|
function syncGlobalScreens(screens) {
|
|
2697
|
-
|
|
2757
|
+
store.screens = screens;
|
|
2698
2758
|
}
|
|
2699
2759
|
function getGlobalScreens() {
|
|
2700
|
-
return
|
|
2760
|
+
return store.screens;
|
|
2701
2761
|
}
|
|
2702
2762
|
function setGlobalWidth(width) {
|
|
2703
|
-
const store = getStore();
|
|
2704
2763
|
store.width = width;
|
|
2705
2764
|
if (store.notifiedWidth === width) return;
|
|
2706
2765
|
store.notifiedWidth = width;
|
|
2707
2766
|
for (const l of store.listeners) l();
|
|
2708
2767
|
}
|
|
2709
2768
|
function getGlobalWidth() {
|
|
2710
|
-
return
|
|
2769
|
+
return store.width;
|
|
2711
2770
|
}
|
|
2712
2771
|
function subscribeGlobalWidth(listener) {
|
|
2713
|
-
const store = getStore();
|
|
2714
2772
|
store.listeners.add(listener);
|
|
2715
2773
|
return () => store.listeners.delete(listener);
|
|
2716
2774
|
}
|
|
2717
|
-
function getActiveBreakpoints(width) {
|
|
2718
|
-
const store = getStore();
|
|
2775
|
+
function getActiveBreakpoints(width, screens) {
|
|
2719
2776
|
const w = width ?? store.width;
|
|
2777
|
+
const s = screens ?? store.screens;
|
|
2720
2778
|
const active = /* @__PURE__ */ new Set();
|
|
2721
|
-
for (const [name, minW] of Object.entries(
|
|
2779
|
+
for (const [name, minW] of Object.entries(s)) {
|
|
2722
2780
|
if (typeof minW === "number" && w >= minW) active.add(name);
|
|
2723
2781
|
}
|
|
2724
2782
|
return active;
|
|
@@ -2749,12 +2807,12 @@ function getSortedEntries(resolved) {
|
|
|
2749
2807
|
}
|
|
2750
2808
|
return sorted;
|
|
2751
2809
|
}
|
|
2752
|
-
var
|
|
2810
|
+
var _defaultFontFamily;
|
|
2753
2811
|
function setDefaultFontFamily(font) {
|
|
2754
|
-
|
|
2812
|
+
_defaultFontFamily = font;
|
|
2755
2813
|
}
|
|
2756
2814
|
function getDefaultFontFamily() {
|
|
2757
|
-
return
|
|
2815
|
+
return _defaultFontFamily;
|
|
2758
2816
|
}
|
|
2759
2817
|
var _styleEl = null;
|
|
2760
2818
|
var _ruleIndexByKey = /* @__PURE__ */ new Map();
|
|
@@ -2774,12 +2832,12 @@ function evictInjectedRule(rule) {
|
|
|
2774
2832
|
}
|
|
2775
2833
|
}
|
|
2776
2834
|
var _injectedRules = new LRUCache(5e4, evictInjectedRule);
|
|
2777
|
-
var
|
|
2835
|
+
var _runtimeCSSDisabled = false;
|
|
2778
2836
|
function disableRuntimeCSS() {
|
|
2779
|
-
|
|
2837
|
+
_runtimeCSSDisabled = true;
|
|
2780
2838
|
}
|
|
2781
2839
|
function isRuntimeCSSDisabled() {
|
|
2782
|
-
return
|
|
2840
|
+
return _runtimeCSSDisabled;
|
|
2783
2841
|
}
|
|
2784
2842
|
function getStyleEl() {
|
|
2785
2843
|
if (_styleEl) return _styleEl;
|
|
@@ -3095,19 +3153,11 @@ function deepMerge(base, override) {
|
|
|
3095
3153
|
}
|
|
3096
3154
|
return result;
|
|
3097
3155
|
}
|
|
3098
|
-
var
|
|
3099
|
-
function getConfigStore() {
|
|
3100
|
-
const g = globalThis;
|
|
3101
|
-
if (!g[CONFIG_KEY]) {
|
|
3102
|
-
g[CONFIG_KEY] = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
3103
|
-
}
|
|
3104
|
-
return g[CONFIG_KEY];
|
|
3105
|
-
}
|
|
3156
|
+
var configStore = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
3106
3157
|
function getConfig() {
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
return store.resolved;
|
|
3158
|
+
if (configStore.resolved) return configStore.resolved;
|
|
3159
|
+
configStore.resolved = buildConfig({});
|
|
3160
|
+
return configStore.resolved;
|
|
3111
3161
|
}
|
|
3112
3162
|
function resolveOneRef(ref, colors) {
|
|
3113
3163
|
const lastDash = ref.lastIndexOf("-");
|
|
@@ -3182,8 +3232,7 @@ function buildConfig(userConfig) {
|
|
|
3182
3232
|
clearPluginUtilities();
|
|
3183
3233
|
clearPluginModifiers();
|
|
3184
3234
|
}
|
|
3185
|
-
const
|
|
3186
|
-
for (const k of Object.keys(_store.customVariants)) delete _store.customVariants[k];
|
|
3235
|
+
for (const k of Object.keys(configStore.customVariants)) delete configStore.customVariants[k];
|
|
3187
3236
|
const pluginAPI = makePluginAPI(resolved.theme);
|
|
3188
3237
|
for (const plugin of resolved.plugins) {
|
|
3189
3238
|
plugin(pluginAPI);
|
|
@@ -3231,78 +3280,53 @@ function makePluginAPI(theme) {
|
|
|
3231
3280
|
};
|
|
3232
3281
|
}
|
|
3233
3282
|
function onConfigChange(listener) {
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
return () => store.listeners.delete(listener);
|
|
3283
|
+
configStore.listeners.add(listener);
|
|
3284
|
+
return () => configStore.listeners.delete(listener);
|
|
3237
3285
|
}
|
|
3238
3286
|
function updateConfig(userConfig) {
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
store._src = userConfig;
|
|
3287
|
+
configStore.resolved = buildConfig(userConfig);
|
|
3288
|
+
configStore._src = userConfig;
|
|
3242
3289
|
clearCache();
|
|
3243
|
-
for (const listener of
|
|
3244
|
-
listener(
|
|
3290
|
+
for (const listener of configStore.listeners) {
|
|
3291
|
+
listener(configStore.resolved);
|
|
3245
3292
|
}
|
|
3246
3293
|
}
|
|
3247
3294
|
function initConfig(userConfig) {
|
|
3248
|
-
if (
|
|
3295
|
+
if (configStore._src === userConfig) return;
|
|
3249
3296
|
updateConfig(userConfig);
|
|
3250
3297
|
}
|
|
3251
|
-
var customVariants =
|
|
3252
|
-
{},
|
|
3253
|
-
{
|
|
3254
|
-
get(_t, p) {
|
|
3255
|
-
return typeof p === "string" ? getConfigStore().customVariants[p] : void 0;
|
|
3256
|
-
},
|
|
3257
|
-
set(_t, p, v) {
|
|
3258
|
-
if (typeof p === "string") getConfigStore().customVariants[p] = v;
|
|
3259
|
-
return true;
|
|
3260
|
-
},
|
|
3261
|
-
ownKeys() {
|
|
3262
|
-
return Object.keys(getConfigStore().customVariants);
|
|
3263
|
-
},
|
|
3264
|
-
getOwnPropertyDescriptor(_t, p) {
|
|
3265
|
-
if (typeof p !== "string") return void 0;
|
|
3266
|
-
const v = getConfigStore().customVariants[p];
|
|
3267
|
-
return v !== void 0 ? { value: v, writable: true, enumerable: true, configurable: true } : void 0;
|
|
3268
|
-
}
|
|
3269
|
-
}
|
|
3270
|
-
);
|
|
3298
|
+
var customVariants = configStore.customVariants;
|
|
3271
3299
|
|
|
3272
3300
|
// src/core/darkModeStore.ts
|
|
3273
|
-
var
|
|
3274
|
-
function getStore2() {
|
|
3275
|
-
const g = globalThis;
|
|
3276
|
-
if (!g[KEY]) {
|
|
3277
|
-
g[KEY] = { isDark: false, notifiedIsDark: false, subscribers: /* @__PURE__ */ new Set() };
|
|
3278
|
-
}
|
|
3279
|
-
return g[KEY];
|
|
3280
|
-
}
|
|
3301
|
+
var store2 = { isDark: false, notifiedIsDark: false, subscribers: /* @__PURE__ */ new Set() };
|
|
3281
3302
|
function syncGlobalDarkMode(isDark) {
|
|
3282
|
-
|
|
3303
|
+
store2.isDark = isDark;
|
|
3283
3304
|
}
|
|
3284
3305
|
function setGlobalDarkMode(isDark) {
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
for (const sub of store.subscribers) sub();
|
|
3306
|
+
store2.isDark = isDark;
|
|
3307
|
+
if (store2.notifiedIsDark === isDark) return;
|
|
3308
|
+
store2.notifiedIsDark = isDark;
|
|
3309
|
+
for (const sub of store2.subscribers) sub();
|
|
3290
3310
|
}
|
|
3291
3311
|
function getGlobalDarkMode() {
|
|
3292
|
-
return
|
|
3312
|
+
return store2.isDark;
|
|
3293
3313
|
}
|
|
3294
3314
|
function subscribeGlobalDarkMode(callback) {
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
return () => store.subscribers.delete(callback);
|
|
3315
|
+
store2.subscribers.add(callback);
|
|
3316
|
+
return () => store2.subscribers.delete(callback);
|
|
3298
3317
|
}
|
|
3299
3318
|
|
|
3300
3319
|
// src/useSyncExternalStoreShim.ts
|
|
3301
3320
|
import React from "react";
|
|
3302
|
-
var useSyncExternalStore = React.useSyncExternalStore ?? function useSyncExternalStoreFallback(subscribe, getSnapshot,
|
|
3321
|
+
var useSyncExternalStore = React.useSyncExternalStore ?? function useSyncExternalStoreFallback(subscribe, getSnapshot, getServerSnapshot) {
|
|
3322
|
+
const isServer = typeof window === "undefined";
|
|
3303
3323
|
const [, forceUpdate] = React.useReducer((n) => n + 1, 0);
|
|
3304
|
-
|
|
3305
|
-
|
|
3324
|
+
const value = isServer && getServerSnapshot ? getServerSnapshot() : getSnapshot();
|
|
3325
|
+
React.useEffect(() => {
|
|
3326
|
+
if (getSnapshot() !== value) forceUpdate();
|
|
3327
|
+
return subscribe(forceUpdate);
|
|
3328
|
+
}, [subscribe]);
|
|
3329
|
+
return value;
|
|
3306
3330
|
};
|
|
3307
3331
|
|
|
3308
3332
|
// src/useGlobalDarkMode.ts
|
|
@@ -3767,15 +3791,16 @@ var InteractiveWrapper = forwardRef(
|
|
|
3767
3791
|
if (!isWebPlatform) setFocused(false);
|
|
3768
3792
|
}), [onBlur, isWebPlatform]);
|
|
3769
3793
|
const { children, disabled, checked, ...restForComponent } = rest;
|
|
3794
|
+
const isNonStringComponent = typeof Component !== "string";
|
|
3770
3795
|
const computedStyle = useMemo(
|
|
3771
3796
|
() => {
|
|
3772
3797
|
if (isWebPlatform) return {};
|
|
3773
3798
|
const s = flatten(resolvedStyle, isDark, { pressed, hover: hovered, focus: focused, disabled: !!disabled, checked: !!checked }, breakpoints);
|
|
3774
3799
|
stripInternalMarkers(s);
|
|
3775
|
-
if (
|
|
3800
|
+
if (isNonStringComponent) stripWebOnlyProps(s);
|
|
3776
3801
|
return s;
|
|
3777
3802
|
},
|
|
3778
|
-
[resolvedStyle, isDark, pressed, hovered, focused, width, disabled, checked]
|
|
3803
|
+
[resolvedStyle, isDark, pressed, hovered, focused, width, disabled, checked, isNonStringComponent]
|
|
3779
3804
|
);
|
|
3780
3805
|
const skipComputedInline = isWebPlatform;
|
|
3781
3806
|
const finalStyle = skipComputedInline ? styleProp ?? void 0 : styleProp ? Array.isArray(styleProp) ? Object.assign({}, computedStyle, ...styleProp) : { ...computedStyle, ...styleProp } : computedStyle;
|