@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
package/dist/vite-plugin.js
CHANGED
|
@@ -649,14 +649,16 @@ var defaultTheme = {
|
|
|
649
649
|
animation: {}
|
|
650
650
|
};
|
|
651
651
|
|
|
652
|
-
// src/core/
|
|
652
|
+
// src/core/resolvers/color.ts
|
|
653
653
|
function resolveColor(value, colors, isArbitrary) {
|
|
654
654
|
if (isArbitrary) return value;
|
|
655
655
|
const slashIdx = value.indexOf("/");
|
|
656
656
|
const colorPart = slashIdx > 0 ? value.slice(0, slashIdx) : value;
|
|
657
657
|
const opacityPart = slashIdx > 0 ? value.slice(slashIdx + 1) : null;
|
|
658
658
|
let hex = null;
|
|
659
|
-
if (colorPart
|
|
659
|
+
if (colorPart.startsWith("[") && colorPart.endsWith("]")) {
|
|
660
|
+
hex = colorPart.slice(1, -1);
|
|
661
|
+
} else if (colorPart in colors) {
|
|
660
662
|
const entry = colors[colorPart];
|
|
661
663
|
if (typeof entry === "string") hex = entry;
|
|
662
664
|
else if (typeof entry === "object" && "6" in entry) hex = entry["6"];
|
|
@@ -721,6 +723,86 @@ function withOpacityVar(color, varName) {
|
|
|
721
723
|
const [r, g, b] = rgb;
|
|
722
724
|
return `rgba(${r},${g},${b},var(${varName},1))`;
|
|
723
725
|
}
|
|
726
|
+
var colorResolvers = {
|
|
727
|
+
// ── Background ─────────────────────────────────────────────────────────────
|
|
728
|
+
bg: ({ value, isArbitrary }, { colors }) => {
|
|
729
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
730
|
+
if (!color) return null;
|
|
731
|
+
return { backgroundColor: getEffectiveIsWeb() ? withOpacityVar(color, "--bg-opacity") : color };
|
|
732
|
+
},
|
|
733
|
+
"bg-opacity": ({ value, isArbitrary }, _) => {
|
|
734
|
+
if (!getEffectiveIsWeb()) return null;
|
|
735
|
+
const n = parseFloat(value);
|
|
736
|
+
if (isNaN(n)) return null;
|
|
737
|
+
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
738
|
+
return { "--bg-opacity": v };
|
|
739
|
+
},
|
|
740
|
+
// ── Background gradient (CSS variable gradient stops, web-only) ──────────
|
|
741
|
+
"bg-gradient-to": ({ value }) => {
|
|
742
|
+
if (!getEffectiveIsWeb()) return null;
|
|
743
|
+
const directions = {
|
|
744
|
+
t: "to top",
|
|
745
|
+
tr: "to top right",
|
|
746
|
+
r: "to right",
|
|
747
|
+
br: "to bottom right",
|
|
748
|
+
b: "to bottom",
|
|
749
|
+
bl: "to bottom left",
|
|
750
|
+
l: "to left",
|
|
751
|
+
tl: "to top left"
|
|
752
|
+
};
|
|
753
|
+
const dir = directions[value];
|
|
754
|
+
if (!dir) return null;
|
|
755
|
+
return {
|
|
756
|
+
backgroundImage: `linear-gradient(${dir}, var(--kb-gradient-from, transparent), var(--kb-gradient-stops, transparent))`
|
|
757
|
+
};
|
|
758
|
+
},
|
|
759
|
+
from: ({ value, isArbitrary }, { colors }) => {
|
|
760
|
+
if (!getEffectiveIsWeb()) return null;
|
|
761
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
762
|
+
if (!color) return null;
|
|
763
|
+
return {
|
|
764
|
+
"--kb-gradient-from": color,
|
|
765
|
+
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-to, transparent)`
|
|
766
|
+
};
|
|
767
|
+
},
|
|
768
|
+
via: ({ value, isArbitrary }, { colors }) => {
|
|
769
|
+
if (!getEffectiveIsWeb()) return null;
|
|
770
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
771
|
+
if (!color) return null;
|
|
772
|
+
return {
|
|
773
|
+
"--kb-gradient-via": color,
|
|
774
|
+
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-via), var(--kb-gradient-to, transparent)`
|
|
775
|
+
};
|
|
776
|
+
},
|
|
777
|
+
to: ({ value, isArbitrary }, { colors }) => {
|
|
778
|
+
if (!getEffectiveIsWeb()) return null;
|
|
779
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
780
|
+
if (!color) return null;
|
|
781
|
+
return { "--kb-gradient-to": color };
|
|
782
|
+
},
|
|
783
|
+
// ── Tint color (native-only, for Image and icon components) ──────────────
|
|
784
|
+
tint: ({ value, isArbitrary }, { colors }) => {
|
|
785
|
+
if (getEffectiveIsWeb()) return null;
|
|
786
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
787
|
+
return color ? { tintColor: color } : null;
|
|
788
|
+
},
|
|
789
|
+
// ── Caret color (web-only) ────────────────────────────────────────────────
|
|
790
|
+
caret: ({ value, isArbitrary }, { colors }) => {
|
|
791
|
+
if (!getEffectiveIsWeb()) return null;
|
|
792
|
+
if (value === "auto" || value === "transparent") return { caretColor: value };
|
|
793
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
794
|
+
return color ? { caretColor: color } : null;
|
|
795
|
+
},
|
|
796
|
+
// ── Accent color (web-only) ───────────────────────────────────────────────
|
|
797
|
+
accent: ({ value, isArbitrary }, { colors }) => {
|
|
798
|
+
if (!getEffectiveIsWeb()) return null;
|
|
799
|
+
if (value === "auto") return { accentColor: "auto" };
|
|
800
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
801
|
+
return color ? { accentColor: color } : null;
|
|
802
|
+
}
|
|
803
|
+
};
|
|
804
|
+
|
|
805
|
+
// src/core/resolvers/spacing.ts
|
|
724
806
|
function resolveSpacing(value, negative, spacing, isArbitrary) {
|
|
725
807
|
if (isArbitrary) {
|
|
726
808
|
const resolved = getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
@@ -753,516 +835,174 @@ function resolveSizing(value, spacing, isArbitrary) {
|
|
|
753
835
|
}
|
|
754
836
|
return null;
|
|
755
837
|
}
|
|
838
|
+
function makeSpacingResolver(prop) {
|
|
839
|
+
return ({ value, negative, isArbitrary }, { spacing }) => {
|
|
840
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
841
|
+
return v !== null ? { [prop]: v } : null;
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
var PADDING_MARGIN_PROPS = {
|
|
845
|
+
p: "padding",
|
|
846
|
+
px: "paddingHorizontal",
|
|
847
|
+
py: "paddingVertical",
|
|
848
|
+
pt: "paddingTop",
|
|
849
|
+
pr: "paddingRight",
|
|
850
|
+
pb: "paddingBottom",
|
|
851
|
+
pl: "paddingLeft",
|
|
852
|
+
m: "margin",
|
|
853
|
+
mx: "marginHorizontal",
|
|
854
|
+
my: "marginVertical",
|
|
855
|
+
mt: "marginTop",
|
|
856
|
+
mr: "marginRight",
|
|
857
|
+
mb: "marginBottom",
|
|
858
|
+
ml: "marginLeft"
|
|
859
|
+
};
|
|
860
|
+
var spacingResolvers = {
|
|
861
|
+
// ── Sizing ─────────────────────────────────────────────────────────────────
|
|
862
|
+
w: ({ value, isArbitrary }, { spacing }) => {
|
|
863
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
864
|
+
return v !== null ? { width: v } : null;
|
|
865
|
+
},
|
|
866
|
+
h: ({ value, isArbitrary }, { spacing }) => {
|
|
867
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
868
|
+
return v !== null ? { height: v } : null;
|
|
869
|
+
},
|
|
870
|
+
"min-w": ({ value, isArbitrary }, { spacing }) => {
|
|
871
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
872
|
+
return v !== null ? { minWidth: v } : null;
|
|
873
|
+
},
|
|
874
|
+
"min-h": ({ value, isArbitrary }, { spacing }) => {
|
|
875
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
876
|
+
return v !== null ? { minHeight: v } : null;
|
|
877
|
+
},
|
|
878
|
+
"max-w": ({ value, isArbitrary }, { spacing }) => {
|
|
879
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
880
|
+
return v !== null ? { maxWidth: v } : null;
|
|
881
|
+
},
|
|
882
|
+
"max-h": ({ value, isArbitrary }, { spacing }) => {
|
|
883
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
884
|
+
return v !== null ? { maxHeight: v } : null;
|
|
885
|
+
},
|
|
886
|
+
// ── Size shorthand (sets width AND height in one utility) ────────────────
|
|
887
|
+
size: ({ value, isArbitrary }, { spacing }) => {
|
|
888
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
889
|
+
return v !== null ? { width: v, height: v } : null;
|
|
890
|
+
},
|
|
891
|
+
// ── Flex basis ─────────────────────────────────────────────────────────────
|
|
892
|
+
basis: ({ value, isArbitrary }, { spacing }) => {
|
|
893
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
894
|
+
return v !== null ? { flexBasis: v } : null;
|
|
895
|
+
},
|
|
896
|
+
// ── Gap ────────────────────────────────────────────────────────────────────
|
|
897
|
+
gap: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
898
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
899
|
+
return v !== null ? { gap: v } : null;
|
|
900
|
+
},
|
|
901
|
+
"gap-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
902
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
903
|
+
return v !== null ? { columnGap: v } : null;
|
|
904
|
+
},
|
|
905
|
+
"gap-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
906
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
907
|
+
return v !== null ? { rowGap: v } : null;
|
|
908
|
+
},
|
|
909
|
+
// ── Position ───────────────────────────────────────────────────────────────
|
|
910
|
+
top: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
911
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
912
|
+
return v !== null ? { top: v } : null;
|
|
913
|
+
},
|
|
914
|
+
right: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
915
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
916
|
+
return v !== null ? { right: v } : null;
|
|
917
|
+
},
|
|
918
|
+
bottom: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
919
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
920
|
+
return v !== null ? { bottom: v } : null;
|
|
921
|
+
},
|
|
922
|
+
left: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
923
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
924
|
+
return v !== null ? { left: v } : null;
|
|
925
|
+
},
|
|
926
|
+
inset: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
927
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
928
|
+
return v !== null ? { top: v, right: v, bottom: v, left: v } : null;
|
|
929
|
+
},
|
|
930
|
+
"inset-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
931
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
932
|
+
return v !== null ? { left: v, right: v } : null;
|
|
933
|
+
},
|
|
934
|
+
"inset-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
935
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
936
|
+
return v !== null ? { top: v, bottom: v } : null;
|
|
937
|
+
},
|
|
938
|
+
// ── Translate ──────────────────────────────────────────────────────────────
|
|
939
|
+
"translate-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
940
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
941
|
+
if (v === null) return null;
|
|
942
|
+
if (getEffectiveIsWeb()) return { transform: `translateX(${typeof v === "number" ? `${v}px` : v})` };
|
|
943
|
+
if (typeof v === "string") {
|
|
944
|
+
const n = parseFloat(v);
|
|
945
|
+
return isNaN(n) ? null : { transform: [{ translateX: n }] };
|
|
946
|
+
}
|
|
947
|
+
return { transform: [{ translateX: v }] };
|
|
948
|
+
},
|
|
949
|
+
"translate-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
950
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
951
|
+
if (v === null) return null;
|
|
952
|
+
if (getEffectiveIsWeb()) return { transform: `translateY(${typeof v === "number" ? `${v}px` : v})` };
|
|
953
|
+
if (typeof v === "string") {
|
|
954
|
+
const n = parseFloat(v);
|
|
955
|
+
return isNaN(n) ? null : { transform: [{ translateY: n }] };
|
|
956
|
+
}
|
|
957
|
+
return { transform: [{ translateY: v }] };
|
|
958
|
+
},
|
|
959
|
+
// ── Space between ─────────────────────────────────────────────────────────
|
|
960
|
+
// On web: emits __spaceX/__spaceY markers → resolver generates > * + * CSS rules.
|
|
961
|
+
// On native (RN 0.71+): uses columnGap/rowGap directly.
|
|
962
|
+
"space-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
963
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
964
|
+
if (v === null) return null;
|
|
965
|
+
if (getEffectiveIsWeb()) return { __spaceX: v };
|
|
966
|
+
return { columnGap: v };
|
|
967
|
+
},
|
|
968
|
+
"space-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
969
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
970
|
+
if (v === null) return null;
|
|
971
|
+
if (getEffectiveIsWeb()) return { __spaceY: v };
|
|
972
|
+
return { rowGap: v };
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
for (const [utility, prop] of Object.entries(PADDING_MARGIN_PROPS)) {
|
|
976
|
+
spacingResolvers[utility] = makeSpacingResolver(prop);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
// src/core/resolvers/border.ts
|
|
756
980
|
function resolveRadius(value, radii, isArbitrary) {
|
|
757
981
|
if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
758
982
|
const key = value === "" ? "DEFAULT" : value;
|
|
759
983
|
return radii[key] ?? null;
|
|
760
984
|
}
|
|
761
|
-
function
|
|
762
|
-
|
|
763
|
-
|
|
985
|
+
function makeBorderSideResolver(widthProp, colorProp) {
|
|
986
|
+
return ({ value, isArbitrary }, { colors, borderWidth }) => {
|
|
987
|
+
if (!value) return { [widthProp]: 1 };
|
|
988
|
+
if (isArbitrary) {
|
|
989
|
+
const w2 = toNativeValue(value);
|
|
990
|
+
if (typeof w2 === "number") return { [widthProp]: w2 };
|
|
991
|
+
return { [colorProp]: value };
|
|
992
|
+
}
|
|
993
|
+
const color = resolveColor(value, colors, false);
|
|
994
|
+
if (color) return { [colorProp]: color };
|
|
995
|
+
const w = borderWidth[value];
|
|
996
|
+
return w !== void 0 ? { [widthProp]: w } : null;
|
|
997
|
+
};
|
|
764
998
|
}
|
|
765
|
-
var
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
// React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
|
|
773
|
-
// a no-op normally, but is needed to re-show an element that was hidden via `hidden`.
|
|
774
|
-
// `grid`, `contents`, `flow-root` have no native equivalent and stay null there.
|
|
775
|
-
// The inline-* family (inline, inline-block, inline-flex, inline-grid) falls back
|
|
776
|
-
// to 'flex' on native instead — like plain `flex`, this is a no-op most of the
|
|
777
|
-
// time, but without it these utilities couldn't re-show a `hidden` element on
|
|
778
|
-
// native either (null → no style applied → still display:'none').
|
|
779
|
-
flex: { display: "flex" },
|
|
780
|
-
block: web ? { display: "block" } : null,
|
|
781
|
-
"inline-block": { display: web ? "inline-block" : "flex" },
|
|
782
|
-
inline: { display: web ? "inline" : "flex" },
|
|
783
|
-
grid: web ? { display: "grid" } : null,
|
|
784
|
-
grd: web ? { display: "grid" } : null,
|
|
785
|
-
"inline-flex": { display: web ? "inline-flex" : "flex" },
|
|
786
|
-
"inline-grid": { display: web ? "inline-grid" : "flex" },
|
|
787
|
-
hidden: { display: "none" },
|
|
788
|
-
contents: web ? { display: "contents" } : null,
|
|
789
|
-
"flow-root": web ? { display: "flow-root" } : null,
|
|
790
|
-
// Flex direction (both web and native)
|
|
791
|
-
"flex-row": { flexDirection: "row" },
|
|
792
|
-
"flex-col": { flexDirection: "column" },
|
|
793
|
-
"flex-row-reverse": { flexDirection: "row-reverse" },
|
|
794
|
-
"flex-col-reverse": { flexDirection: "column-reverse" },
|
|
795
|
-
// Flex wrap (both)
|
|
796
|
-
"flex-wrap": { flexWrap: "wrap" },
|
|
797
|
-
"flex-wrap-reverse": { flexWrap: "wrap-reverse" },
|
|
798
|
-
"flex-nowrap": { flexWrap: "nowrap" },
|
|
799
|
-
// Flex grow / shrink (both)
|
|
800
|
-
"flex-grow": { flexGrow: 1 },
|
|
801
|
-
"flex-grow-0": { flexGrow: 0 },
|
|
802
|
-
"flex-shrink": { flexShrink: 1 },
|
|
803
|
-
"flex-shrink-0": { flexShrink: 0 },
|
|
804
|
-
// Align items (both)
|
|
805
|
-
"items-start": { alignItems: "flex-start" },
|
|
806
|
-
"items-end": { alignItems: "flex-end" },
|
|
807
|
-
"items-center": { alignItems: "center" },
|
|
808
|
-
"items-baseline": { alignItems: "baseline" },
|
|
809
|
-
"items-stretch": { alignItems: "stretch" },
|
|
810
|
-
// Justify content (both)
|
|
811
|
-
"justify-start": { justifyContent: "flex-start" },
|
|
812
|
-
"justify-end": { justifyContent: "flex-end" },
|
|
813
|
-
"justify-center": { justifyContent: "center" },
|
|
814
|
-
"justify-between": { justifyContent: "space-between" },
|
|
815
|
-
"justify-around": { justifyContent: "space-around" },
|
|
816
|
-
"justify-evenly": { justifyContent: "space-evenly" },
|
|
817
|
-
// Align content (both)
|
|
818
|
-
"content-start": { alignContent: "flex-start" },
|
|
819
|
-
"content-end": { alignContent: "flex-end" },
|
|
820
|
-
"content-center": { alignContent: "center" },
|
|
821
|
-
"content-between": { alignContent: "space-between" },
|
|
822
|
-
"content-around": { alignContent: "space-around" },
|
|
823
|
-
"content-evenly": { alignContent: "space-evenly" },
|
|
824
|
-
"content-stretch": { alignContent: "stretch" },
|
|
825
|
-
// Align self (both)
|
|
826
|
-
"self-auto": { alignSelf: "auto" },
|
|
827
|
-
"self-start": { alignSelf: "flex-start" },
|
|
828
|
-
"self-end": { alignSelf: "flex-end" },
|
|
829
|
-
"self-center": { alignSelf: "center" },
|
|
830
|
-
"self-stretch": { alignSelf: "stretch" },
|
|
831
|
-
"self-baseline": { alignSelf: "baseline" },
|
|
832
|
-
// Text align (both)
|
|
833
|
-
"text-left": { textAlign: "left" },
|
|
834
|
-
"text-right": { textAlign: "right" },
|
|
835
|
-
"text-center": { textAlign: "center" },
|
|
836
|
-
"text-justify": { textAlign: "justify" },
|
|
837
|
-
// Font weight shortcuts (both)
|
|
838
|
-
"font-thin": { fontWeight: "100" },
|
|
839
|
-
"font-extralight": { fontWeight: "200" },
|
|
840
|
-
"font-light": { fontWeight: "300" },
|
|
841
|
-
"font-normal": { fontWeight: "400" },
|
|
842
|
-
"font-medium": { fontWeight: "500" },
|
|
843
|
-
"font-semibold": { fontWeight: "600" },
|
|
844
|
-
"font-bold": { fontWeight: "700" },
|
|
845
|
-
"font-extrabold": { fontWeight: "800" },
|
|
846
|
-
"font-black": { fontWeight: "900" },
|
|
847
|
-
// Text decoration (overline is web-only)
|
|
848
|
-
underline: { textDecorationLine: "underline" },
|
|
849
|
-
overline: web ? { textDecorationLine: "overline" } : null,
|
|
850
|
-
"line-through": { textDecorationLine: "line-through" },
|
|
851
|
-
"no-underline": { textDecorationLine: "none" },
|
|
852
|
-
// Text transform (both)
|
|
853
|
-
uppercase: { textTransform: "uppercase" },
|
|
854
|
-
lowercase: { textTransform: "lowercase" },
|
|
855
|
-
capitalize: { textTransform: "capitalize" },
|
|
856
|
-
"normal-case": { textTransform: "none" },
|
|
857
|
-
// Font style (both)
|
|
858
|
-
italic: { fontStyle: "italic" },
|
|
859
|
-
"non-italic": { fontStyle: "normal" },
|
|
860
|
-
// Position (fixed/sticky/static are web-only; RN only supports relative/absolute)
|
|
861
|
-
relative: { position: "relative" },
|
|
862
|
-
absolute: { position: "absolute" },
|
|
863
|
-
fixed: web ? { position: "fixed" } : null,
|
|
864
|
-
sticky: web ? { position: "sticky" } : null,
|
|
865
|
-
static: web ? { position: "static" } : null,
|
|
866
|
-
// Visibility (no `visibility` prop on native; use opacity instead)
|
|
867
|
-
visible: web ? { visibility: "visible" } : null,
|
|
868
|
-
invisible: web ? { visibility: "hidden" } : { opacity: 0 },
|
|
869
|
-
// Overflow (RN supports 'hidden' | 'visible' | 'scroll'; not 'auto')
|
|
870
|
-
"overflow-hidden": { overflow: "hidden" },
|
|
871
|
-
"overflow-visible": { overflow: "visible" },
|
|
872
|
-
"overflow-scroll": { overflow: "scroll" },
|
|
873
|
-
"overflow-auto": web ? { overflow: "auto" } : { overflow: "scroll" },
|
|
874
|
-
// overflowX / overflowY are web-only
|
|
875
|
-
"overflow-x-hidden": web ? { overflowX: "hidden" } : null,
|
|
876
|
-
"overflow-x-scroll": web ? { overflowX: "scroll" } : null,
|
|
877
|
-
"overflow-x-auto": web ? { overflowX: "auto" } : null,
|
|
878
|
-
"overflow-y-hidden": web ? { overflowY: "hidden" } : null,
|
|
879
|
-
"overflow-y-scroll": web ? { overflowY: "scroll" } : null,
|
|
880
|
-
"overflow-y-auto": web ? { overflowY: "auto" } : null,
|
|
881
|
-
// Object fit (web-only; use resizeMode prop on RN Image)
|
|
882
|
-
"object-contain": web ? { objectFit: "contain" } : null,
|
|
883
|
-
"object-cover": web ? { objectFit: "cover" } : null,
|
|
884
|
-
"object-fill": web ? { objectFit: "fill" } : null,
|
|
885
|
-
"object-none": web ? { objectFit: "none" } : null,
|
|
886
|
-
"object-scale-down": web ? { objectFit: "scale-down" } : null,
|
|
887
|
-
// Border style (both)
|
|
888
|
-
"border-solid": { borderStyle: "solid" },
|
|
889
|
-
"border-dashed": { borderStyle: "dashed" },
|
|
890
|
-
"border-dotted": { borderStyle: "dotted" },
|
|
891
|
-
"border-none": { borderWidth: 0 },
|
|
892
|
-
// Border sides default width (both)
|
|
893
|
-
"border-t": { borderTopWidth: 1 },
|
|
894
|
-
"border-r": { borderRightWidth: 1 },
|
|
895
|
-
"border-b": { borderBottomWidth: 1 },
|
|
896
|
-
"border-l": { borderLeftWidth: 1 },
|
|
897
|
-
// Cursor (web-only)
|
|
898
|
-
"cursor-auto": web ? { cursor: "auto" } : null,
|
|
899
|
-
"cursor-default": web ? { cursor: "default" } : null,
|
|
900
|
-
"cursor-pointer": web ? { cursor: "pointer" } : null,
|
|
901
|
-
"cursor-wait": web ? { cursor: "wait" } : null,
|
|
902
|
-
"cursor-text": web ? { cursor: "text" } : null,
|
|
903
|
-
"cursor-move": web ? { cursor: "move" } : null,
|
|
904
|
-
"cursor-not-allowed": web ? { cursor: "not-allowed" } : null,
|
|
905
|
-
// User select (web-only)
|
|
906
|
-
"select-none": web ? { userSelect: "none" } : null,
|
|
907
|
-
"select-text": web ? { userSelect: "text" } : null,
|
|
908
|
-
"select-all": web ? { userSelect: "all" } : null,
|
|
909
|
-
"select-auto": web ? { userSelect: "auto" } : null,
|
|
910
|
-
// Pointer events (both)
|
|
911
|
-
"pointer-events-none": { pointerEvents: "none" },
|
|
912
|
-
"pointer-events-auto": { pointerEvents: "auto" },
|
|
913
|
-
// Whitespace (web-only; RN Text uses numberOfLines prop instead)
|
|
914
|
-
"whitespace-normal": web ? { whiteSpace: "normal" } : null,
|
|
915
|
-
"whitespace-nowrap": web ? { whiteSpace: "nowrap" } : null,
|
|
916
|
-
"whitespace-pre": web ? { whiteSpace: "pre" } : null,
|
|
917
|
-
"whitespace-pre-wrap": web ? { whiteSpace: "pre-wrap" } : null,
|
|
918
|
-
"whitespace-pre-line": web ? { whiteSpace: "pre-line" } : null,
|
|
919
|
-
// Word break (web-only)
|
|
920
|
-
"break-normal": web ? { overflowWrap: "normal", wordBreak: "normal" } : null,
|
|
921
|
-
"break-words": web ? { overflowWrap: "break-word" } : null,
|
|
922
|
-
"break-all": web ? { wordBreak: "break-all" } : null,
|
|
923
|
-
// Misc web-only
|
|
924
|
-
truncate: web ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null,
|
|
925
|
-
"box-border": web ? { boxSizing: "border-box" } : null,
|
|
926
|
-
"box-content": web ? { boxSizing: "content-box" } : null,
|
|
927
|
-
"appearance-none": web ? { appearance: "none" } : null,
|
|
928
|
-
"outline-none": web ? { outline: "none", outlineOffset: "0" } : null,
|
|
929
|
-
outline: web ? { outline: "2px solid transparent", outlineOffset: "2px" } : null,
|
|
930
|
-
resize: web ? { resize: "both" } : null,
|
|
931
|
-
"resize-none": web ? { resize: "none" } : null,
|
|
932
|
-
"resize-y": web ? { resize: "vertical" } : null,
|
|
933
|
-
"resize-x": web ? { resize: "horizontal" } : null,
|
|
934
|
-
antialiased: web ? { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale" } : null,
|
|
935
|
-
"subpixel-antialiased": web ? { WebkitFontSmoothing: "subpixel-antialiased", MozOsxFontSmoothing: "auto" } : null,
|
|
936
|
-
"overflow-ellipsis": web ? { textOverflow: "ellipsis" } : null,
|
|
937
|
-
"sr-only": web ? {
|
|
938
|
-
position: "absolute",
|
|
939
|
-
width: 1,
|
|
940
|
-
height: 1,
|
|
941
|
-
padding: 0,
|
|
942
|
-
margin: -1,
|
|
943
|
-
overflow: "hidden",
|
|
944
|
-
clip: "rect(0,0,0,0)",
|
|
945
|
-
whiteSpace: "nowrap",
|
|
946
|
-
border: 0
|
|
947
|
-
} : null,
|
|
948
|
-
"not-sr-only": web ? {
|
|
949
|
-
position: "static",
|
|
950
|
-
width: "auto",
|
|
951
|
-
height: "auto",
|
|
952
|
-
padding: 0,
|
|
953
|
-
margin: 0,
|
|
954
|
-
overflow: "visible",
|
|
955
|
-
clip: "auto",
|
|
956
|
-
whiteSpace: "normal"
|
|
957
|
-
} : null,
|
|
958
|
-
// Lists (web-only)
|
|
959
|
-
"list-none": web ? { listStyleType: "none" } : null,
|
|
960
|
-
"list-disc": web ? { listStyleType: "disc" } : null,
|
|
961
|
-
"list-decimal": web ? { listStyleType: "decimal" } : null,
|
|
962
|
-
// Background clip (web-only)
|
|
963
|
-
"bg-clip-border": web ? { backgroundClip: "border-box" } : null,
|
|
964
|
-
"bg-clip-padding": web ? { backgroundClip: "padding-box" } : null,
|
|
965
|
-
"bg-clip-content": web ? { backgroundClip: "content-box" } : null,
|
|
966
|
-
"bg-clip-text": web ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
|
|
967
|
-
// Background image
|
|
968
|
-
"bg-none": web ? { backgroundImage: "none" } : null,
|
|
969
|
-
// Background size (web-only)
|
|
970
|
-
"bg-auto": web ? { backgroundSize: "auto" } : null,
|
|
971
|
-
"bg-cover": web ? { backgroundSize: "cover" } : null,
|
|
972
|
-
"bg-contain": web ? { backgroundSize: "contain" } : null,
|
|
973
|
-
// Background position (web-only)
|
|
974
|
-
"bg-center": web ? { backgroundPosition: "center" } : null,
|
|
975
|
-
"bg-top": web ? { backgroundPosition: "top" } : null,
|
|
976
|
-
"bg-bottom": web ? { backgroundPosition: "bottom" } : null,
|
|
977
|
-
"bg-left": web ? { backgroundPosition: "left" } : null,
|
|
978
|
-
"bg-right": web ? { backgroundPosition: "right" } : null,
|
|
979
|
-
"bg-left-top": web ? { backgroundPosition: "left top" } : null,
|
|
980
|
-
"bg-left-bottom": web ? { backgroundPosition: "left bottom" } : null,
|
|
981
|
-
"bg-right-top": web ? { backgroundPosition: "right top" } : null,
|
|
982
|
-
"bg-right-bottom": web ? { backgroundPosition: "right bottom" } : null,
|
|
983
|
-
// Background repeat (web-only)
|
|
984
|
-
"bg-repeat": web ? { backgroundRepeat: "repeat" } : null,
|
|
985
|
-
"bg-no-repeat": web ? { backgroundRepeat: "no-repeat" } : null,
|
|
986
|
-
"bg-repeat-x": web ? { backgroundRepeat: "repeat-x" } : null,
|
|
987
|
-
"bg-repeat-y": web ? { backgroundRepeat: "repeat-y" } : null,
|
|
988
|
-
"bg-repeat-round": web ? { backgroundRepeat: "round" } : null,
|
|
989
|
-
"bg-repeat-space": web ? { backgroundRepeat: "space" } : null,
|
|
990
|
-
// Background attachment (web-only)
|
|
991
|
-
"bg-fixed": web ? { backgroundAttachment: "fixed" } : null,
|
|
992
|
-
"bg-local": web ? { backgroundAttachment: "local" } : null,
|
|
993
|
-
"bg-scroll": web ? { backgroundAttachment: "scroll" } : null,
|
|
994
|
-
// Object position (web-only)
|
|
995
|
-
"object-center": web ? { objectPosition: "center" } : null,
|
|
996
|
-
"object-top": web ? { objectPosition: "top" } : null,
|
|
997
|
-
"object-bottom": web ? { objectPosition: "bottom" } : null,
|
|
998
|
-
"object-left": web ? { objectPosition: "left" } : null,
|
|
999
|
-
"object-right": web ? { objectPosition: "right" } : null,
|
|
1000
|
-
"object-left-top": web ? { objectPosition: "left top" } : null,
|
|
1001
|
-
"object-left-bottom": web ? { objectPosition: "left bottom" } : null,
|
|
1002
|
-
"object-right-top": web ? { objectPosition: "right top" } : null,
|
|
1003
|
-
"object-right-bottom": web ? { objectPosition: "right bottom" } : null,
|
|
1004
|
-
// Table (web-only)
|
|
1005
|
-
table: web ? { display: "table" } : null,
|
|
1006
|
-
"table-auto": web ? { tableLayout: "auto" } : null,
|
|
1007
|
-
"table-fixed": web ? { tableLayout: "fixed" } : null,
|
|
1008
|
-
"caption-top": web ? { captionSide: "top" } : null,
|
|
1009
|
-
"caption-bottom": web ? { captionSide: "bottom" } : null,
|
|
1010
|
-
"border-collapse": web ? { borderCollapse: "collapse" } : null,
|
|
1011
|
-
"border-separate": web ? { borderCollapse: "separate" } : null,
|
|
1012
|
-
// List style position (web-only)
|
|
1013
|
-
"list-inside": web ? { listStylePosition: "inside" } : null,
|
|
1014
|
-
"list-outside": web ? { listStylePosition: "outside" } : null,
|
|
1015
|
-
// Font variant numeric (web-only)
|
|
1016
|
-
"normal-nums": web ? { fontVariantNumeric: "normal" } : null,
|
|
1017
|
-
ordinal: web ? { fontVariantNumeric: "ordinal" } : null,
|
|
1018
|
-
"slashed-zero": web ? { fontVariantNumeric: "slashed-zero" } : null,
|
|
1019
|
-
"lining-nums": web ? { fontVariantNumeric: "lining-nums" } : null,
|
|
1020
|
-
"oldstyle-nums": web ? { fontVariantNumeric: "oldstyle-nums" } : null,
|
|
1021
|
-
"proportional-nums": web ? { fontVariantNumeric: "proportional-nums" } : null,
|
|
1022
|
-
"tabular-nums": web ? { fontVariantNumeric: "tabular-nums" } : null,
|
|
1023
|
-
"diagonal-fractions": web ? { fontVariantNumeric: "diagonal-fractions" } : null,
|
|
1024
|
-
"stacked-fractions": web ? { fontVariantNumeric: "stacked-fractions" } : null,
|
|
1025
|
-
// Isolation (web-only)
|
|
1026
|
-
isolate: web ? { isolation: "isolate" } : null,
|
|
1027
|
-
"isolation-auto": web ? { isolation: "auto" } : null,
|
|
1028
|
-
// Backface visibility (both iOS and Android)
|
|
1029
|
-
"backface-visible": { backfaceVisibility: "visible" },
|
|
1030
|
-
"backface-hidden": { backfaceVisibility: "hidden" },
|
|
1031
|
-
// CSS filters — standalone = default/full effect (web-only)
|
|
1032
|
-
grayscale: web ? { "--kb-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
|
|
1033
|
-
invert: web ? { "--kb-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
|
|
1034
|
-
sepia: web ? { "--kb-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
|
|
1035
|
-
// Divide none
|
|
1036
|
-
"divide-none": web ? { __divideX: 0, __divideY: 0 } : null,
|
|
1037
|
-
// Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
|
|
1038
|
-
group: web ? {} : null,
|
|
1039
|
-
peer: web ? {} : null,
|
|
1040
|
-
// Text-wrap (web-only)
|
|
1041
|
-
"text-wrap": web ? { textWrap: "wrap" } : null,
|
|
1042
|
-
"text-nowrap": web ? { textWrap: "nowrap" } : null,
|
|
1043
|
-
"text-balance": web ? { textWrap: "balance" } : null,
|
|
1044
|
-
"text-pretty": web ? { textWrap: "pretty" } : null,
|
|
1045
|
-
// Screen sizing — dvw/dvh (dynamic viewport units) instead of vw/vh: on mobile
|
|
1046
|
-
// browsers, vh/vw are pinned to the LARGEST viewport size (address bar hidden),
|
|
1047
|
-
// so `h-screen` overflows behind the address bar when it's shown. dvh/dvw track
|
|
1048
|
-
// the actual visible viewport as browser chrome shows/hides. Desktop behavior
|
|
1049
|
-
// is unchanged since there's no dynamic chrome to account for.
|
|
1050
|
-
// (vw/dvw values are web-only; vh/dvh values work cross-platform via spacing scale for h-*)
|
|
1051
|
-
"w-screen": web ? { width: "100dvw" } : null,
|
|
1052
|
-
"min-h-screen": { minHeight: "100dvh" },
|
|
1053
|
-
"max-h-screen": { maxHeight: "100dvh" },
|
|
1054
|
-
"min-w-screen": web ? { minWidth: "100dvw" } : null,
|
|
1055
|
-
"max-w-screen": web ? { maxWidth: "100dvw" } : null,
|
|
1056
|
-
// max-w named container sizes (mirrors Tailwind's container scale)
|
|
1057
|
-
"max-w-none": { maxWidth: "none" },
|
|
1058
|
-
"max-w-xs": { maxWidth: 320 },
|
|
1059
|
-
"max-w-sm": { maxWidth: 384 },
|
|
1060
|
-
"max-w-md": { maxWidth: 448 },
|
|
1061
|
-
"max-w-lg": { maxWidth: 512 },
|
|
1062
|
-
"max-w-xl": { maxWidth: 576 },
|
|
1063
|
-
"max-w-2xl": { maxWidth: 672 },
|
|
1064
|
-
"max-w-3xl": { maxWidth: 768 },
|
|
1065
|
-
"max-w-4xl": { maxWidth: 896 },
|
|
1066
|
-
"max-w-5xl": { maxWidth: 1024 },
|
|
1067
|
-
"max-w-6xl": { maxWidth: 1152 },
|
|
1068
|
-
"max-w-7xl": { maxWidth: 1280 },
|
|
1069
|
-
"max-w-prose": web ? { maxWidth: "65ch" } : null,
|
|
1070
|
-
// Extended cursors (web-only)
|
|
1071
|
-
"cursor-grab": web ? { cursor: "grab" } : null,
|
|
1072
|
-
"cursor-grabbing": web ? { cursor: "grabbing" } : null,
|
|
1073
|
-
"cursor-zoom-in": web ? { cursor: "zoom-in" } : null,
|
|
1074
|
-
"cursor-zoom-out": web ? { cursor: "zoom-out" } : null,
|
|
1075
|
-
"cursor-crosshair": web ? { cursor: "crosshair" } : null,
|
|
1076
|
-
"cursor-help": web ? { cursor: "help" } : null,
|
|
1077
|
-
"cursor-none": web ? { cursor: "none" } : null,
|
|
1078
|
-
// Overflow clip (web-only)
|
|
1079
|
-
"overflow-clip": web ? { overflow: "clip" } : null,
|
|
1080
|
-
"overflow-x-clip": web ? { overflowX: "clip" } : null,
|
|
1081
|
-
"overflow-y-clip": web ? { overflowY: "clip" } : null,
|
|
1082
|
-
// Scroll behavior (web-only)
|
|
1083
|
-
"scroll-smooth": web ? { scrollBehavior: "smooth" } : null,
|
|
1084
|
-
"scroll-auto": web ? { scrollBehavior: "auto" } : null,
|
|
1085
|
-
// Float (web-only)
|
|
1086
|
-
"float-left": web ? { float: "left" } : null,
|
|
1087
|
-
"float-right": web ? { float: "right" } : null,
|
|
1088
|
-
"float-start": web ? { float: "inline-start" } : null,
|
|
1089
|
-
"float-end": web ? { float: "inline-end" } : null,
|
|
1090
|
-
"float-none": web ? { float: "none" } : null,
|
|
1091
|
-
// Clear (web-only)
|
|
1092
|
-
"clear-left": web ? { clear: "left" } : null,
|
|
1093
|
-
"clear-right": web ? { clear: "right" } : null,
|
|
1094
|
-
"clear-both": web ? { clear: "both" } : null,
|
|
1095
|
-
"clear-start": web ? { clear: "inline-start" } : null,
|
|
1096
|
-
"clear-end": web ? { clear: "inline-end" } : null,
|
|
1097
|
-
"clear-none": web ? { clear: "none" } : null,
|
|
1098
|
-
// Vertical align (web-only)
|
|
1099
|
-
"align-baseline": web ? { verticalAlign: "baseline" } : null,
|
|
1100
|
-
"align-top": web ? { verticalAlign: "top" } : null,
|
|
1101
|
-
"align-middle": web ? { verticalAlign: "middle" } : null,
|
|
1102
|
-
"align-bottom": web ? { verticalAlign: "bottom" } : null,
|
|
1103
|
-
"align-text-top": web ? { verticalAlign: "text-top" } : null,
|
|
1104
|
-
"align-text-bottom": web ? { verticalAlign: "text-bottom" } : null,
|
|
1105
|
-
"align-sub": web ? { verticalAlign: "sub" } : null,
|
|
1106
|
-
"align-super": web ? { verticalAlign: "super" } : null,
|
|
1107
|
-
// Touch action (web-only)
|
|
1108
|
-
"touch-auto": web ? { touchAction: "auto" } : null,
|
|
1109
|
-
"touch-none": web ? { touchAction: "none" } : null,
|
|
1110
|
-
"touch-pan-x": web ? { touchAction: "pan-x" } : null,
|
|
1111
|
-
"touch-pan-y": web ? { touchAction: "pan-y" } : null,
|
|
1112
|
-
"touch-pan-left": web ? { touchAction: "pan-left" } : null,
|
|
1113
|
-
"touch-pan-right": web ? { touchAction: "pan-right" } : null,
|
|
1114
|
-
"touch-pan-up": web ? { touchAction: "pan-up" } : null,
|
|
1115
|
-
"touch-pan-down": web ? { touchAction: "pan-down" } : null,
|
|
1116
|
-
"touch-pinch-zoom": web ? { touchAction: "pinch-zoom" } : null,
|
|
1117
|
-
"touch-manipulation": web ? { touchAction: "manipulation" } : null
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
function getStandalone() {
|
|
1121
|
-
if (!_standalone) _standalone = buildStandalone();
|
|
1122
|
-
return _standalone;
|
|
1123
|
-
}
|
|
1124
|
-
function makeSpacingResolver(prop) {
|
|
1125
|
-
return ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1126
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1127
|
-
return v !== null ? { [prop]: v } : null;
|
|
1128
|
-
};
|
|
1129
|
-
}
|
|
1130
|
-
var PADDING_MARGIN_PROPS = {
|
|
1131
|
-
p: "padding",
|
|
1132
|
-
px: "paddingHorizontal",
|
|
1133
|
-
py: "paddingVertical",
|
|
1134
|
-
pt: "paddingTop",
|
|
1135
|
-
pr: "paddingRight",
|
|
1136
|
-
pb: "paddingBottom",
|
|
1137
|
-
pl: "paddingLeft",
|
|
1138
|
-
m: "margin",
|
|
1139
|
-
mx: "marginHorizontal",
|
|
1140
|
-
my: "marginVertical",
|
|
1141
|
-
mt: "marginTop",
|
|
1142
|
-
mr: "marginRight",
|
|
1143
|
-
mb: "marginBottom",
|
|
1144
|
-
ml: "marginLeft"
|
|
1145
|
-
};
|
|
1146
|
-
function makeBorderSideResolver(widthProp, colorProp) {
|
|
1147
|
-
return ({ value, isArbitrary }, { colors, borderWidth }) => {
|
|
1148
|
-
if (!value) return { [widthProp]: 1 };
|
|
1149
|
-
if (isArbitrary) {
|
|
1150
|
-
const w2 = toNativeValue(value);
|
|
1151
|
-
if (typeof w2 === "number") return { [widthProp]: w2 };
|
|
1152
|
-
return { [colorProp]: value };
|
|
1153
|
-
}
|
|
1154
|
-
const color = resolveColor(value, colors, false);
|
|
1155
|
-
if (color) return { [colorProp]: color };
|
|
1156
|
-
const w = borderWidth[value];
|
|
1157
|
-
return w !== void 0 ? { [widthProp]: w } : null;
|
|
1158
|
-
};
|
|
1159
|
-
}
|
|
1160
|
-
var BORDER_SIDE_PROPS = {
|
|
1161
|
-
"border-t": ["borderTopWidth", "borderTopColor"],
|
|
1162
|
-
"border-r": ["borderRightWidth", "borderRightColor"],
|
|
1163
|
-
"border-b": ["borderBottomWidth", "borderBottomColor"],
|
|
1164
|
-
"border-l": ["borderLeftWidth", "borderLeftColor"]
|
|
1165
|
-
};
|
|
1166
|
-
function keyframeDeclToCSS(decl) {
|
|
1167
|
-
return Object.entries(decl).map(([prop, val]) => `${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${val}`).join("; ");
|
|
1168
|
-
}
|
|
1169
|
-
function buildKeyframeCSS(name, steps) {
|
|
1170
|
-
const body = Object.entries(steps).map(([selector, decl]) => `${selector} { ${keyframeDeclToCSS(decl)} }`).join(" ");
|
|
1171
|
-
return `@keyframes ${name} { ${body} }`;
|
|
1172
|
-
}
|
|
1173
|
-
var BUILTIN_ANIMATIONS = {
|
|
1174
|
-
none: { animation: "none" },
|
|
1175
|
-
spin: {
|
|
1176
|
-
animation: "kb-spin 1s linear infinite",
|
|
1177
|
-
__keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
|
|
1178
|
-
},
|
|
1179
|
-
ping: {
|
|
1180
|
-
animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
|
|
1181
|
-
__keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
|
|
1182
|
-
},
|
|
1183
|
-
pulse: {
|
|
1184
|
-
animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
|
|
1185
|
-
__keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
|
|
1186
|
-
},
|
|
1187
|
-
bounce: {
|
|
1188
|
-
animation: "kb-bounce 1s infinite",
|
|
1189
|
-
__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) } }"
|
|
1190
|
-
}
|
|
1191
|
-
};
|
|
1192
|
-
function buildAnimationValue(animation, keyframes) {
|
|
1193
|
-
const words = animation.trim().split(/\s+/);
|
|
1194
|
-
const name = words[0];
|
|
1195
|
-
if (!name) return { animation };
|
|
1196
|
-
const builtin = BUILTIN_ANIMATIONS[name];
|
|
1197
|
-
if (builtin?.__keyframe) {
|
|
1198
|
-
const kbName = builtin.animation.split(/\s+/, 1)[0];
|
|
1199
|
-
return { animation: [kbName, ...words.slice(1)].join(" "), __keyframe: builtin.__keyframe };
|
|
1200
|
-
}
|
|
1201
|
-
const steps = keyframes?.[name];
|
|
1202
|
-
return steps ? { animation, __keyframe: buildKeyframeCSS(name, steps) } : { animation };
|
|
1203
|
-
}
|
|
1204
|
-
var RESOLVERS = {
|
|
1205
|
-
// ── Background ─────────────────────────────────────────────────────────────
|
|
1206
|
-
bg: ({ value, isArbitrary }, { colors }) => {
|
|
1207
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1208
|
-
if (!color) return null;
|
|
1209
|
-
return { backgroundColor: getEffectiveIsWeb() ? withOpacityVar(color, "--bg-opacity") : color };
|
|
1210
|
-
},
|
|
1211
|
-
"bg-opacity": ({ value, isArbitrary }, _) => {
|
|
1212
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1213
|
-
const n = parseFloat(value);
|
|
1214
|
-
if (isNaN(n)) return null;
|
|
1215
|
-
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
1216
|
-
return { "--bg-opacity": v };
|
|
1217
|
-
},
|
|
1218
|
-
// ── Text ───────────────────────────────────────────────────────────────────
|
|
1219
|
-
text: ({ value, isArbitrary }, { colors, fontSize }) => {
|
|
1220
|
-
const size = resolveFontSize(value, fontSize, false);
|
|
1221
|
-
if (!isArbitrary && size !== null) return { fontSize: size };
|
|
1222
|
-
if (isArbitrary) {
|
|
1223
|
-
if (/^\d/.test(value) || /^(calc|min|max|clamp)/.test(value)) {
|
|
1224
|
-
return { fontSize: getEffectiveIsWeb() ? value : toNativeValue(value) };
|
|
1225
|
-
}
|
|
1226
|
-
return { color: getEffectiveIsWeb() ? withOpacityVar(value, "--text-opacity") : value };
|
|
1227
|
-
}
|
|
1228
|
-
const color = resolveColor(value, colors, false);
|
|
1229
|
-
if (!color) return null;
|
|
1230
|
-
return { color: getEffectiveIsWeb() ? withOpacityVar(color, "--text-opacity") : color };
|
|
1231
|
-
},
|
|
1232
|
-
"text-opacity": ({ value, isArbitrary }, _) => {
|
|
1233
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1234
|
-
const n = parseFloat(value);
|
|
1235
|
-
if (isNaN(n)) return null;
|
|
1236
|
-
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
1237
|
-
return { "--text-opacity": v };
|
|
1238
|
-
},
|
|
1239
|
-
// ── Padding & margin ───────────────────────────────────────────────────────
|
|
1240
|
-
// Generated below via makeSpacingResolver() — see PADDING_MARGIN_PROPS.
|
|
1241
|
-
// ── Sizing ─────────────────────────────────────────────────────────────────
|
|
1242
|
-
w: ({ value, isArbitrary }, { spacing }) => {
|
|
1243
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1244
|
-
return v !== null ? { width: v } : null;
|
|
1245
|
-
},
|
|
1246
|
-
h: ({ value, isArbitrary }, { spacing }) => {
|
|
1247
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1248
|
-
return v !== null ? { height: v } : null;
|
|
1249
|
-
},
|
|
1250
|
-
"min-w": ({ value, isArbitrary }, { spacing }) => {
|
|
1251
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1252
|
-
return v !== null ? { minWidth: v } : null;
|
|
1253
|
-
},
|
|
1254
|
-
"min-h": ({ value, isArbitrary }, { spacing }) => {
|
|
1255
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1256
|
-
return v !== null ? { minHeight: v } : null;
|
|
1257
|
-
},
|
|
1258
|
-
"max-w": ({ value, isArbitrary }, { spacing }) => {
|
|
1259
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1260
|
-
return v !== null ? { maxWidth: v } : null;
|
|
1261
|
-
},
|
|
1262
|
-
"max-h": ({ value, isArbitrary }, { spacing }) => {
|
|
1263
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1264
|
-
return v !== null ? { maxHeight: v } : null;
|
|
1265
|
-
},
|
|
999
|
+
var BORDER_SIDE_PROPS = {
|
|
1000
|
+
"border-t": ["borderTopWidth", "borderTopColor"],
|
|
1001
|
+
"border-r": ["borderRightWidth", "borderRightColor"],
|
|
1002
|
+
"border-b": ["borderBottomWidth", "borderBottomColor"],
|
|
1003
|
+
"border-l": ["borderLeftWidth", "borderLeftColor"]
|
|
1004
|
+
};
|
|
1005
|
+
var borderResolvers = {
|
|
1266
1006
|
// ── Border width ───────────────────────────────────────────────────────────
|
|
1267
1007
|
border: ({ value, isArbitrary }, { colors, borderWidth, spacing }) => {
|
|
1268
1008
|
if (!value) return { borderWidth: borderWidth["DEFAULT"] ?? 1 };
|
|
@@ -1319,188 +1059,128 @@ var RESOLVERS = {
|
|
|
1319
1059
|
const r = resolveRadius(value, borderRadius, isArbitrary);
|
|
1320
1060
|
return r !== null ? { borderBottomRightRadius: r } : null;
|
|
1321
1061
|
},
|
|
1322
|
-
// ──
|
|
1323
|
-
|
|
1324
|
-
if (!value) return null;
|
|
1325
|
-
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1326
|
-
const n = parseInt(value, 10);
|
|
1327
|
-
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1328
|
-
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1329
|
-
},
|
|
1330
|
-
// ── Grid template columns/rows (Tailwind-style aliases, web-only) ──────────
|
|
1331
|
-
"grid-cols": ({ value, isArbitrary }) => {
|
|
1332
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1333
|
-
if (!value) return null;
|
|
1334
|
-
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1335
|
-
if (value === "none") return { display: "grid", gridTemplateColumns: "none" };
|
|
1336
|
-
const n = parseInt(value, 10);
|
|
1337
|
-
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1338
|
-
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1339
|
-
},
|
|
1340
|
-
"grid-rows": ({ value, isArbitrary }) => {
|
|
1341
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1342
|
-
if (!value) return null;
|
|
1343
|
-
if (isArbitrary) return { gridTemplateRows: value };
|
|
1344
|
-
if (value === "none") return { gridTemplateRows: "none" };
|
|
1345
|
-
const n = parseInt(value, 10);
|
|
1346
|
-
if (isNaN(n) || n < 1) return null;
|
|
1347
|
-
return { gridTemplateRows: `repeat(${n}, minmax(0, 1fr))` };
|
|
1348
|
-
},
|
|
1349
|
-
// ── Grid auto flow (web-only) ─────────────────────────────────────────────
|
|
1350
|
-
"grid-flow": ({ value }) => {
|
|
1351
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1352
|
-
const flows = {
|
|
1353
|
-
row: "row",
|
|
1354
|
-
col: "column",
|
|
1355
|
-
dense: "dense",
|
|
1356
|
-
"row-dense": "row dense",
|
|
1357
|
-
"col-dense": "column dense"
|
|
1358
|
-
};
|
|
1359
|
-
const flow = flows[value];
|
|
1360
|
-
return flow ? { gridAutoFlow: flow } : null;
|
|
1361
|
-
},
|
|
1362
|
-
// ── Grid auto sizing (web-only) ───────────────────────────────────────────
|
|
1363
|
-
"auto-cols": ({ value, isArbitrary }) => {
|
|
1364
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1365
|
-
if (isArbitrary) return { gridAutoColumns: value };
|
|
1366
|
-
const presets = {
|
|
1367
|
-
auto: "auto",
|
|
1368
|
-
min: "min-content",
|
|
1369
|
-
max: "max-content",
|
|
1370
|
-
fr: "minmax(0, 1fr)"
|
|
1371
|
-
};
|
|
1372
|
-
const v = presets[value];
|
|
1373
|
-
return v ? { gridAutoColumns: v } : null;
|
|
1374
|
-
},
|
|
1375
|
-
"auto-rows": ({ value, isArbitrary }) => {
|
|
1376
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1377
|
-
if (isArbitrary) return { gridAutoRows: value };
|
|
1378
|
-
const presets = {
|
|
1379
|
-
auto: "auto",
|
|
1380
|
-
min: "min-content",
|
|
1381
|
-
max: "max-content",
|
|
1382
|
-
fr: "minmax(0, 1fr)"
|
|
1383
|
-
};
|
|
1384
|
-
const v = presets[value];
|
|
1385
|
-
return v ? { gridAutoRows: v } : null;
|
|
1386
|
-
},
|
|
1387
|
-
// ── Grid column placement (web-only) ──────────────────────────────────────
|
|
1388
|
-
"col-span": ({ value }) => {
|
|
1389
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1390
|
-
if (value === "full") return { gridColumn: "1 / -1" };
|
|
1391
|
-
const n = parseInt(value, 10);
|
|
1392
|
-
return isNaN(n) ? null : { gridColumn: `span ${n} / span ${n}` };
|
|
1393
|
-
},
|
|
1394
|
-
"col-start": ({ value, isArbitrary }) => {
|
|
1395
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1396
|
-
if (value === "auto") return { gridColumnStart: "auto" };
|
|
1397
|
-
if (isArbitrary) return { gridColumnStart: value };
|
|
1398
|
-
const n = parseInt(value, 10);
|
|
1399
|
-
return isNaN(n) ? null : { gridColumnStart: n };
|
|
1400
|
-
},
|
|
1401
|
-
"col-end": ({ value, isArbitrary }) => {
|
|
1402
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1403
|
-
if (value === "auto") return { gridColumnEnd: "auto" };
|
|
1404
|
-
if (isArbitrary) return { gridColumnEnd: value };
|
|
1405
|
-
const n = parseInt(value, 10);
|
|
1406
|
-
return isNaN(n) ? null : { gridColumnEnd: n };
|
|
1407
|
-
},
|
|
1408
|
-
col: ({ value, isArbitrary }) => {
|
|
1409
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1410
|
-
if (!value || value === "auto") return { gridColumn: "auto" };
|
|
1411
|
-
if (isArbitrary) return { gridColumn: value };
|
|
1412
|
-
return null;
|
|
1413
|
-
},
|
|
1414
|
-
// ── Grid row placement (web-only) ─────────────────────────────────────────
|
|
1415
|
-
"row-span": ({ value }) => {
|
|
1416
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1417
|
-
if (value === "full") return { gridRow: "1 / -1" };
|
|
1418
|
-
const n = parseInt(value, 10);
|
|
1419
|
-
return isNaN(n) ? null : { gridRow: `span ${n} / span ${n}` };
|
|
1420
|
-
},
|
|
1421
|
-
"row-start": ({ value, isArbitrary }) => {
|
|
1422
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1423
|
-
if (value === "auto") return { gridRowStart: "auto" };
|
|
1424
|
-
if (isArbitrary) return { gridRowStart: value };
|
|
1425
|
-
const n = parseInt(value, 10);
|
|
1426
|
-
return isNaN(n) ? null : { gridRowStart: n };
|
|
1427
|
-
},
|
|
1428
|
-
"row-end": ({ value, isArbitrary }) => {
|
|
1062
|
+
// ── Outline extended (web-only) ───────────────────────────────────────────
|
|
1063
|
+
outline: ({ value, isArbitrary }, { colors }) => {
|
|
1429
1064
|
if (!getEffectiveIsWeb()) return null;
|
|
1430
|
-
if (value
|
|
1431
|
-
if (
|
|
1432
|
-
|
|
1433
|
-
|
|
1065
|
+
if (!value) return { outline: "2px solid transparent", outlineOffset: "2px" };
|
|
1066
|
+
if (value === "none") return { outline: "none", outlineOffset: "0" };
|
|
1067
|
+
if (isArbitrary) {
|
|
1068
|
+
if (/^\d/.test(value) || value.startsWith("calc(")) return { outlineWidth: value };
|
|
1069
|
+
return { outlineColor: value };
|
|
1070
|
+
}
|
|
1071
|
+
const widths = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1072
|
+
if (value in widths) return { outlineWidth: widths[value] };
|
|
1073
|
+
const color = resolveColor(value, colors, false);
|
|
1074
|
+
return color ? { outlineColor: color } : null;
|
|
1434
1075
|
},
|
|
1435
|
-
|
|
1076
|
+
"outline-offset": ({ value, isArbitrary }) => {
|
|
1436
1077
|
if (!getEffectiveIsWeb()) return null;
|
|
1437
|
-
if (
|
|
1438
|
-
|
|
1439
|
-
return null;
|
|
1078
|
+
if (isArbitrary) return { outlineOffset: value };
|
|
1079
|
+
const offsets = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1080
|
+
return offsets[value] ? { outlineOffset: offsets[value] } : null;
|
|
1440
1081
|
},
|
|
1441
|
-
// ──
|
|
1442
|
-
//
|
|
1443
|
-
|
|
1082
|
+
// ── Divide (child combinator CSS, web-only) ───────────────────────────────
|
|
1083
|
+
// These return special __divide* markers that resolver.ts converts to
|
|
1084
|
+
// .cls > * + * { border-... } CSS rules. No inline style is applied.
|
|
1085
|
+
"divide-x": ({ value, isArbitrary }) => {
|
|
1444
1086
|
if (!getEffectiveIsWeb()) return null;
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
stretch: "stretch",
|
|
1450
|
-
baseline: "baseline"
|
|
1451
|
-
};
|
|
1452
|
-
return map[value] ? { placeItems: map[value] } : null;
|
|
1087
|
+
if (value === "reverse") return null;
|
|
1088
|
+
if (!value) return { __divideX: 1 };
|
|
1089
|
+
const n = parseFloat(value);
|
|
1090
|
+
return isNaN(n) ? null : { __divideX: n };
|
|
1453
1091
|
},
|
|
1454
|
-
|
|
1455
|
-
"place-content": ({ value }) => {
|
|
1092
|
+
"divide-y": ({ value, isArbitrary }) => {
|
|
1456
1093
|
if (!getEffectiveIsWeb()) return null;
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
stretch: "stretch",
|
|
1462
|
-
between: "space-between",
|
|
1463
|
-
around: "space-around",
|
|
1464
|
-
evenly: "space-evenly",
|
|
1465
|
-
baseline: "baseline"
|
|
1466
|
-
};
|
|
1467
|
-
return map[value] ? { placeContent: map[value] } : null;
|
|
1094
|
+
if (value === "reverse") return null;
|
|
1095
|
+
if (!value) return { __divideY: 1 };
|
|
1096
|
+
const n = parseFloat(value);
|
|
1097
|
+
return isNaN(n) ? null : { __divideY: n };
|
|
1468
1098
|
},
|
|
1469
|
-
|
|
1470
|
-
"justify-items": ({ value }) => {
|
|
1099
|
+
divide: ({ value, isArbitrary }, { colors }) => {
|
|
1471
1100
|
if (!getEffectiveIsWeb()) return null;
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1101
|
+
if (isArbitrary) return { __divideColor: value };
|
|
1102
|
+
const styleTokens = {
|
|
1103
|
+
solid: "solid",
|
|
1104
|
+
dashed: "dashed",
|
|
1105
|
+
dotted: "dotted",
|
|
1106
|
+
double: "double",
|
|
1107
|
+
none: "none"
|
|
1477
1108
|
};
|
|
1478
|
-
|
|
1109
|
+
if (value in styleTokens) return { __divideStyle: styleTokens[value] };
|
|
1110
|
+
const color = resolveColor(value, colors, false);
|
|
1111
|
+
return color ? { __divideColor: color } : null;
|
|
1479
1112
|
},
|
|
1480
|
-
//
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1113
|
+
// ── Ring ───────────────────────────────────────────────────────────────────
|
|
1114
|
+
// Web: box-shadow outline ring (doesn't affect layout).
|
|
1115
|
+
// Native: React Native has no box-shadow, so this falls back to borderWidth/
|
|
1116
|
+
// borderColor — the closest visual approximation (used by other RN Tailwind-
|
|
1117
|
+
// likes for the same reason). Unlike the web ring, this DOES affect layout,
|
|
1118
|
+
// and it shares its properties with the `border` utility — combining
|
|
1119
|
+
// `border-*` and `ring-*` on the same native element means whichever class
|
|
1120
|
+
// comes later wins, since both ultimately set borderWidth/borderColor.
|
|
1121
|
+
ring: ({ value, isArbitrary }, { colors }) => {
|
|
1122
|
+
const onWeb = getEffectiveIsWeb();
|
|
1123
|
+
const DEFAULT_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
1124
|
+
const DEFAULT_WIDTH = 3;
|
|
1125
|
+
const asNative = (w, color2) => w === 0 ? { borderWidth: 0 } : { borderWidth: w, borderColor: color2 };
|
|
1126
|
+
if (!value) {
|
|
1127
|
+
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
1128
|
+
}
|
|
1129
|
+
if (value === "inset") {
|
|
1130
|
+
return onWeb ? { boxShadow: `inset 0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
1131
|
+
}
|
|
1132
|
+
const widthTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
1133
|
+
if (!isArbitrary && value in widthTokens) {
|
|
1134
|
+
const w = widthTokens[value];
|
|
1135
|
+
return onWeb ? { boxShadow: w === 0 ? "none" : `0 0 0 ${w}px ${DEFAULT_COLOR}` } : asNative(w, DEFAULT_COLOR);
|
|
1136
|
+
}
|
|
1137
|
+
if (isArbitrary) {
|
|
1138
|
+
const numMatch = /^(\d+(?:\.\d+)?)(px|rem|em|vw|vh)?$/.exec(value);
|
|
1139
|
+
if (numMatch) {
|
|
1140
|
+
const unit = numMatch[2] ?? "px";
|
|
1141
|
+
if (onWeb) return { boxShadow: `0 0 0 ${numMatch[1]}${unit} ${DEFAULT_COLOR}` };
|
|
1142
|
+
return unit === "px" ? asNative(parseFloat(numMatch[1]), DEFAULT_COLOR) : null;
|
|
1143
|
+
}
|
|
1144
|
+
return onWeb ? { boxShadow: value.replace(/_/g, " ") } : null;
|
|
1145
|
+
}
|
|
1146
|
+
const color = resolveColor(value, colors, false);
|
|
1147
|
+
if (color) {
|
|
1148
|
+
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${color}` } : asNative(DEFAULT_WIDTH, color);
|
|
1149
|
+
}
|
|
1150
|
+
return null;
|
|
1491
1151
|
},
|
|
1492
|
-
//
|
|
1493
|
-
|
|
1152
|
+
// Web-only, unlike `ring` above: this stacks a second box-shadow layer to
|
|
1153
|
+
// create a gap between the element and the ring. There's no native
|
|
1154
|
+
// equivalent to approximate that with (a border can't create a gap outside
|
|
1155
|
+
// its own element without an extra wrapper view), so this stays a no-op
|
|
1156
|
+
// on native rather than rendering a misleading half-translation.
|
|
1157
|
+
"ring-offset": ({ value, isArbitrary }, _theme) => {
|
|
1494
1158
|
if (!getEffectiveIsWeb()) return null;
|
|
1495
|
-
const
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1159
|
+
const DEFAULT_RING_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
1160
|
+
const DEFAULT_RING_WIDTH = 3;
|
|
1161
|
+
const offsetTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
1162
|
+
let offsetWidth;
|
|
1163
|
+
if (!isArbitrary) {
|
|
1164
|
+
offsetWidth = value in offsetTokens ? offsetTokens[value] : null;
|
|
1165
|
+
} else {
|
|
1166
|
+
offsetWidth = /^-?\d+(\.\d+)?$/.test(value) ? parseFloat(value) : value;
|
|
1167
|
+
}
|
|
1168
|
+
if (offsetWidth === null || typeof offsetWidth === "number" && isNaN(offsetWidth)) return null;
|
|
1169
|
+
const isZero = offsetWidth === 0 || offsetWidth === "0";
|
|
1170
|
+
const offsetCss = typeof offsetWidth === "number" ? `${offsetWidth}px` : offsetWidth;
|
|
1171
|
+
return {
|
|
1172
|
+
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}`
|
|
1501
1173
|
};
|
|
1502
|
-
|
|
1503
|
-
|
|
1174
|
+
}
|
|
1175
|
+
};
|
|
1176
|
+
for (const [utility, [widthProp, colorProp]] of Object.entries(BORDER_SIDE_PROPS)) {
|
|
1177
|
+
borderResolvers[utility] = makeBorderSideResolver(widthProp, colorProp);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// src/core/resolvers/filters.ts
|
|
1181
|
+
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,)";
|
|
1182
|
+
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,)";
|
|
1183
|
+
var filterResolvers = {
|
|
1504
1184
|
// ── CSS Filters (composable via CSS variables, web-only) ─────────────────
|
|
1505
1185
|
blur: ({ value, isArbitrary }) => {
|
|
1506
1186
|
if (!getEffectiveIsWeb()) return null;
|
|
@@ -1635,412 +1315,629 @@ var RESOLVERS = {
|
|
|
1635
1315
|
if (value === "none") return { backdropFilter: "none" };
|
|
1636
1316
|
return null;
|
|
1637
1317
|
},
|
|
1638
|
-
// ──
|
|
1639
|
-
"
|
|
1640
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1641
|
-
const directions = {
|
|
1642
|
-
t: "to top",
|
|
1643
|
-
tr: "to top right",
|
|
1644
|
-
r: "to right",
|
|
1645
|
-
br: "to bottom right",
|
|
1646
|
-
b: "to bottom",
|
|
1647
|
-
bl: "to bottom left",
|
|
1648
|
-
l: "to left",
|
|
1649
|
-
tl: "to top left"
|
|
1650
|
-
};
|
|
1651
|
-
const dir = directions[value];
|
|
1652
|
-
if (!dir) return null;
|
|
1653
|
-
return {
|
|
1654
|
-
backgroundImage: `linear-gradient(${dir}, var(--kb-gradient-from, transparent), var(--kb-gradient-stops, transparent))`
|
|
1655
|
-
};
|
|
1656
|
-
},
|
|
1657
|
-
from: ({ value, isArbitrary }, { colors }) => {
|
|
1658
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1659
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1660
|
-
if (!color) return null;
|
|
1661
|
-
return {
|
|
1662
|
-
"--kb-gradient-from": color,
|
|
1663
|
-
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-to, transparent)`
|
|
1664
|
-
};
|
|
1665
|
-
},
|
|
1666
|
-
via: ({ value, isArbitrary }, { colors }) => {
|
|
1667
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1668
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1669
|
-
if (!color) return null;
|
|
1670
|
-
return {
|
|
1671
|
-
"--kb-gradient-via": color,
|
|
1672
|
-
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-via), var(--kb-gradient-to, transparent)`
|
|
1673
|
-
};
|
|
1674
|
-
},
|
|
1675
|
-
to: ({ value, isArbitrary }, { colors }) => {
|
|
1676
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1677
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1678
|
-
if (!color) return null;
|
|
1679
|
-
return { "--kb-gradient-to": color };
|
|
1680
|
-
},
|
|
1681
|
-
// ── Transform extras (web-only) ───────────────────────────────────────────
|
|
1682
|
-
"skew-x": ({ value, negative, isArbitrary }) => {
|
|
1683
|
-
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
1684
|
-
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
1685
|
-
return getEffectiveIsWeb() ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
|
|
1686
|
-
},
|
|
1687
|
-
"skew-y": ({ value, negative, isArbitrary }) => {
|
|
1688
|
-
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
1689
|
-
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
1690
|
-
return getEffectiveIsWeb() ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
|
|
1691
|
-
},
|
|
1692
|
-
// Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
|
|
1693
|
-
transform: ({ value, isArbitrary }) => {
|
|
1694
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1695
|
-
if (isArbitrary) return { transform: value.replace(/_/g, " ") };
|
|
1696
|
-
if (value === "none") return { transform: "none" };
|
|
1697
|
-
return null;
|
|
1698
|
-
},
|
|
1699
|
-
// Transform origin
|
|
1700
|
-
origin: ({ value, isArbitrary }) => {
|
|
1701
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1702
|
-
if (isArbitrary) return { transformOrigin: value.replace(/_/g, " ") };
|
|
1703
|
-
const origins = {
|
|
1704
|
-
center: "center",
|
|
1705
|
-
top: "top",
|
|
1706
|
-
"top-right": "top right",
|
|
1707
|
-
right: "right",
|
|
1708
|
-
"bottom-right": "bottom right",
|
|
1709
|
-
bottom: "bottom",
|
|
1710
|
-
"bottom-left": "bottom left",
|
|
1711
|
-
left: "left",
|
|
1712
|
-
"top-left": "top left"
|
|
1713
|
-
};
|
|
1714
|
-
return origins[value] ? { transformOrigin: origins[value] } : null;
|
|
1715
|
-
},
|
|
1716
|
-
// ── Text decoration advanced (web-only) ───────────────────────────────────
|
|
1717
|
-
decoration: ({ value, isArbitrary }, { colors }) => {
|
|
1718
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1719
|
-
if (isArbitrary) {
|
|
1720
|
-
if (/^\d/.test(value) || value.startsWith("calc(")) return { textDecorationThickness: value };
|
|
1721
|
-
return { textDecorationColor: value };
|
|
1722
|
-
}
|
|
1723
|
-
const thickTokens = {
|
|
1724
|
-
auto: "auto",
|
|
1725
|
-
"from-font": "from-font",
|
|
1726
|
-
"0": "0px",
|
|
1727
|
-
"1": "1px",
|
|
1728
|
-
"2": "2px",
|
|
1729
|
-
"4": "4px",
|
|
1730
|
-
"8": "8px"
|
|
1731
|
-
};
|
|
1732
|
-
if (value in thickTokens) return { textDecorationThickness: thickTokens[value] };
|
|
1733
|
-
const styleTokens = {
|
|
1734
|
-
solid: "solid",
|
|
1735
|
-
dashed: "dashed",
|
|
1736
|
-
dotted: "dotted",
|
|
1737
|
-
double: "double",
|
|
1738
|
-
wavy: "wavy"
|
|
1739
|
-
};
|
|
1740
|
-
if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
|
|
1741
|
-
const color = resolveColor(value, colors, false);
|
|
1742
|
-
return color ? { textDecorationColor: color } : null;
|
|
1743
|
-
},
|
|
1744
|
-
"underline-offset": ({ value, isArbitrary }) => {
|
|
1745
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1746
|
-
if (isArbitrary) return { textUnderlineOffset: value };
|
|
1747
|
-
const offsets = {
|
|
1748
|
-
auto: "auto",
|
|
1749
|
-
"0": "0px",
|
|
1750
|
-
"1": "1px",
|
|
1751
|
-
"2": "2px",
|
|
1752
|
-
"4": "4px",
|
|
1753
|
-
"8": "8px"
|
|
1754
|
-
};
|
|
1755
|
-
return offsets[value] ? { textUnderlineOffset: offsets[value] } : null;
|
|
1756
|
-
},
|
|
1757
|
-
// ── Content (web-only — for before:/after: pseudo-elements, which don't exist on native) ──
|
|
1758
|
-
// Arbitrary value carries its own quotes from the bracket syntax (content-['*'] parses to
|
|
1759
|
-
// the literal string 'you can see it' quotes included), so it passes straight through as a
|
|
1760
|
-
// valid `content: '*'` CSS value with no extra wrapping needed.
|
|
1761
|
-
content: ({ value, isArbitrary }) => {
|
|
1318
|
+
// ── Mix / background blend mode (web-only) ───────────────────────────────
|
|
1319
|
+
"mix-blend": ({ value }) => {
|
|
1762
1320
|
if (!getEffectiveIsWeb()) return null;
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
if (colonIdx <= 0) return null;
|
|
1784
|
-
const prop = value.slice(0, colonIdx).trim();
|
|
1785
|
-
const cssValue = value.slice(colonIdx + 1).trim();
|
|
1786
|
-
if (!cssValue || !/^(--[\w-]+|[a-zA-Z-]+)$/.test(prop)) return null;
|
|
1787
|
-
return { [prop]: cssValue };
|
|
1321
|
+
const modes = [
|
|
1322
|
+
"normal",
|
|
1323
|
+
"multiply",
|
|
1324
|
+
"screen",
|
|
1325
|
+
"overlay",
|
|
1326
|
+
"darken",
|
|
1327
|
+
"lighten",
|
|
1328
|
+
"color-dodge",
|
|
1329
|
+
"color-burn",
|
|
1330
|
+
"hard-light",
|
|
1331
|
+
"soft-light",
|
|
1332
|
+
"difference",
|
|
1333
|
+
"exclusion",
|
|
1334
|
+
"hue",
|
|
1335
|
+
"saturation",
|
|
1336
|
+
"color",
|
|
1337
|
+
"luminosity",
|
|
1338
|
+
"plus-lighter"
|
|
1339
|
+
];
|
|
1340
|
+
return modes.includes(value) ? { mixBlendMode: value } : null;
|
|
1788
1341
|
},
|
|
1789
|
-
|
|
1790
|
-
outline: ({ value, isArbitrary }, { colors }) => {
|
|
1342
|
+
"bg-blend": ({ value }) => {
|
|
1791
1343
|
if (!getEffectiveIsWeb()) return null;
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1344
|
+
const modes = [
|
|
1345
|
+
"normal",
|
|
1346
|
+
"multiply",
|
|
1347
|
+
"screen",
|
|
1348
|
+
"overlay",
|
|
1349
|
+
"darken",
|
|
1350
|
+
"lighten",
|
|
1351
|
+
"color-dodge",
|
|
1352
|
+
"color-burn",
|
|
1353
|
+
"hard-light",
|
|
1354
|
+
"soft-light",
|
|
1355
|
+
"difference",
|
|
1356
|
+
"exclusion",
|
|
1357
|
+
"hue",
|
|
1358
|
+
"saturation",
|
|
1359
|
+
"color",
|
|
1360
|
+
"luminosity"
|
|
1361
|
+
];
|
|
1362
|
+
return modes.includes(value) ? { backgroundBlendMode: value } : null;
|
|
1802
1363
|
},
|
|
1803
|
-
|
|
1364
|
+
// ── Will-change (web-only) ─────────────────────────────────────────────────
|
|
1365
|
+
"will-change": ({ value, isArbitrary }) => {
|
|
1804
1366
|
if (!getEffectiveIsWeb()) return null;
|
|
1805
|
-
if (isArbitrary) return {
|
|
1806
|
-
const
|
|
1807
|
-
|
|
1367
|
+
if (isArbitrary) return { willChange: value.replace(/_/g, ", ") };
|
|
1368
|
+
const presets = {
|
|
1369
|
+
auto: "auto",
|
|
1370
|
+
scroll: "scroll-position",
|
|
1371
|
+
contents: "contents",
|
|
1372
|
+
transform: "transform"
|
|
1373
|
+
};
|
|
1374
|
+
return presets[value] ? { willChange: presets[value] } : null;
|
|
1375
|
+
}
|
|
1376
|
+
};
|
|
1377
|
+
|
|
1378
|
+
// src/core/resolvers/layout.ts
|
|
1379
|
+
var _standalone = null;
|
|
1380
|
+
function buildStandalone() {
|
|
1381
|
+
const web = getEffectiveIsWeb();
|
|
1382
|
+
return {
|
|
1383
|
+
// Display
|
|
1384
|
+
// React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
|
|
1385
|
+
// a no-op normally, but is needed to re-show an element that was hidden via `hidden`.
|
|
1386
|
+
// `grid`, `contents`, `flow-root` have no native equivalent and stay null there.
|
|
1387
|
+
// The inline-* family (inline, inline-block, inline-flex, inline-grid) falls back
|
|
1388
|
+
// to 'flex' on native instead — like plain `flex`, this is a no-op most of the
|
|
1389
|
+
// time, but without it these utilities couldn't re-show a `hidden` element on
|
|
1390
|
+
// native either (null → no style applied → still display:'none').
|
|
1391
|
+
flex: { display: "flex" },
|
|
1392
|
+
block: web ? { display: "block" } : null,
|
|
1393
|
+
"inline-block": { display: web ? "inline-block" : "flex" },
|
|
1394
|
+
inline: { display: web ? "inline" : "flex" },
|
|
1395
|
+
grid: web ? { display: "grid" } : null,
|
|
1396
|
+
grd: web ? { display: "grid" } : null,
|
|
1397
|
+
"inline-flex": { display: web ? "inline-flex" : "flex" },
|
|
1398
|
+
"inline-grid": { display: web ? "inline-grid" : "flex" },
|
|
1399
|
+
hidden: { display: "none" },
|
|
1400
|
+
contents: web ? { display: "contents" } : null,
|
|
1401
|
+
"flow-root": web ? { display: "flow-root" } : null,
|
|
1402
|
+
// Flex direction, wrap, grow/shrink, and alignment (both web and native) —
|
|
1403
|
+
// every one of these is meaningless without the element also being a flex
|
|
1404
|
+
// container. React Native Views are ALWAYS flex containers by default, so
|
|
1405
|
+
// on native this was already true for free; on web a plain <div> defaults
|
|
1406
|
+
// to display:block, so e.g. `items-center` alone silently did nothing.
|
|
1407
|
+
// Folding `display: 'flex'` into these on web closes that native/web gap —
|
|
1408
|
+
// `flex-1 items-center justify-center` now behaves the same on both,
|
|
1409
|
+
// without also needing a separate `flex` class.
|
|
1410
|
+
"flex-row": { flexDirection: "row", ...web ? { display: "flex" } : {} },
|
|
1411
|
+
"flex-col": { flexDirection: "column", ...web ? { display: "flex" } : {} },
|
|
1412
|
+
"flex-row-reverse": { flexDirection: "row-reverse", ...web ? { display: "flex" } : {} },
|
|
1413
|
+
"flex-col-reverse": { flexDirection: "column-reverse", ...web ? { display: "flex" } : {} },
|
|
1414
|
+
// Flex wrap (both)
|
|
1415
|
+
"flex-wrap": { flexWrap: "wrap", ...web ? { display: "flex" } : {} },
|
|
1416
|
+
"flex-wrap-reverse": { flexWrap: "wrap-reverse", ...web ? { display: "flex" } : {} },
|
|
1417
|
+
"flex-nowrap": { flexWrap: "nowrap", ...web ? { display: "flex" } : {} },
|
|
1418
|
+
// Flex grow / shrink (both) — deliberately NOT folding in display:flex
|
|
1419
|
+
// like the container-level properties above. flex-grow/flex-shrink are
|
|
1420
|
+
// item-level: they already take effect purely via the PARENT already
|
|
1421
|
+
// being a flex container, with zero dependency on this element's own
|
|
1422
|
+
// display. Forcing display:flex here would instead be an unrelated side
|
|
1423
|
+
// effect on THIS element's own children (turning what may be an ordinary
|
|
1424
|
+
// block stack into a flex row) — exactly the kind of surprise the
|
|
1425
|
+
// container-level properties above can never cause, since those are
|
|
1426
|
+
// no-ops without display:flex to begin with.
|
|
1427
|
+
"flex-grow": { flexGrow: 1 },
|
|
1428
|
+
"flex-grow-0": { flexGrow: 0 },
|
|
1429
|
+
"flex-shrink": { flexShrink: 1 },
|
|
1430
|
+
"flex-shrink-0": { flexShrink: 0 },
|
|
1431
|
+
// Align items (both)
|
|
1432
|
+
"items-start": { alignItems: "flex-start", ...web ? { display: "flex" } : {} },
|
|
1433
|
+
"items-end": { alignItems: "flex-end", ...web ? { display: "flex" } : {} },
|
|
1434
|
+
"items-center": { alignItems: "center", ...web ? { display: "flex" } : {} },
|
|
1435
|
+
"items-baseline": { alignItems: "baseline", ...web ? { display: "flex" } : {} },
|
|
1436
|
+
"items-stretch": { alignItems: "stretch", ...web ? { display: "flex" } : {} },
|
|
1437
|
+
// Justify content (both)
|
|
1438
|
+
"justify-start": { justifyContent: "flex-start", ...web ? { display: "flex" } : {} },
|
|
1439
|
+
"justify-end": { justifyContent: "flex-end", ...web ? { display: "flex" } : {} },
|
|
1440
|
+
"justify-center": { justifyContent: "center", ...web ? { display: "flex" } : {} },
|
|
1441
|
+
"justify-between": { justifyContent: "space-between", ...web ? { display: "flex" } : {} },
|
|
1442
|
+
"justify-around": { justifyContent: "space-around", ...web ? { display: "flex" } : {} },
|
|
1443
|
+
"justify-evenly": { justifyContent: "space-evenly", ...web ? { display: "flex" } : {} },
|
|
1444
|
+
// Align content (both)
|
|
1445
|
+
"content-start": { alignContent: "flex-start", ...web ? { display: "flex" } : {} },
|
|
1446
|
+
"content-end": { alignContent: "flex-end", ...web ? { display: "flex" } : {} },
|
|
1447
|
+
"content-center": { alignContent: "center", ...web ? { display: "flex" } : {} },
|
|
1448
|
+
"content-between": { alignContent: "space-between", ...web ? { display: "flex" } : {} },
|
|
1449
|
+
"content-around": { alignContent: "space-around", ...web ? { display: "flex" } : {} },
|
|
1450
|
+
"content-evenly": { alignContent: "space-evenly", ...web ? { display: "flex" } : {} },
|
|
1451
|
+
"content-stretch": { alignContent: "stretch", ...web ? { display: "flex" } : {} },
|
|
1452
|
+
// Align self (both)
|
|
1453
|
+
"self-auto": { alignSelf: "auto" },
|
|
1454
|
+
"self-start": { alignSelf: "flex-start" },
|
|
1455
|
+
"self-end": { alignSelf: "flex-end" },
|
|
1456
|
+
"self-center": { alignSelf: "center" },
|
|
1457
|
+
"self-stretch": { alignSelf: "stretch" },
|
|
1458
|
+
"self-baseline": { alignSelf: "baseline" },
|
|
1459
|
+
// Text align (both)
|
|
1460
|
+
"text-left": { textAlign: "left" },
|
|
1461
|
+
"text-right": { textAlign: "right" },
|
|
1462
|
+
"text-center": { textAlign: "center" },
|
|
1463
|
+
"text-justify": { textAlign: "justify" },
|
|
1464
|
+
// Font weight shortcuts (both)
|
|
1465
|
+
"font-thin": { fontWeight: "100" },
|
|
1466
|
+
"font-extralight": { fontWeight: "200" },
|
|
1467
|
+
"font-light": { fontWeight: "300" },
|
|
1468
|
+
"font-normal": { fontWeight: "400" },
|
|
1469
|
+
"font-medium": { fontWeight: "500" },
|
|
1470
|
+
"font-semibold": { fontWeight: "600" },
|
|
1471
|
+
"font-bold": { fontWeight: "700" },
|
|
1472
|
+
"font-extrabold": { fontWeight: "800" },
|
|
1473
|
+
"font-black": { fontWeight: "900" },
|
|
1474
|
+
// Text decoration (overline is web-only)
|
|
1475
|
+
underline: { textDecorationLine: "underline" },
|
|
1476
|
+
overline: web ? { textDecorationLine: "overline" } : null,
|
|
1477
|
+
"line-through": { textDecorationLine: "line-through" },
|
|
1478
|
+
"no-underline": { textDecorationLine: "none" },
|
|
1479
|
+
// Text transform (both)
|
|
1480
|
+
uppercase: { textTransform: "uppercase" },
|
|
1481
|
+
lowercase: { textTransform: "lowercase" },
|
|
1482
|
+
capitalize: { textTransform: "capitalize" },
|
|
1483
|
+
"normal-case": { textTransform: "none" },
|
|
1484
|
+
// Font style (both)
|
|
1485
|
+
italic: { fontStyle: "italic" },
|
|
1486
|
+
"non-italic": { fontStyle: "normal" },
|
|
1487
|
+
// Position (fixed/sticky/static are web-only; RN only supports relative/absolute)
|
|
1488
|
+
relative: { position: "relative" },
|
|
1489
|
+
absolute: { position: "absolute" },
|
|
1490
|
+
fixed: web ? { position: "fixed" } : null,
|
|
1491
|
+
sticky: web ? { position: "sticky" } : null,
|
|
1492
|
+
static: web ? { position: "static" } : null,
|
|
1493
|
+
// Visibility (no `visibility` prop on native; use opacity instead)
|
|
1494
|
+
visible: web ? { visibility: "visible" } : null,
|
|
1495
|
+
invisible: web ? { visibility: "hidden" } : { opacity: 0 },
|
|
1496
|
+
// Overflow (RN supports 'hidden' | 'visible' | 'scroll'; not 'auto')
|
|
1497
|
+
"overflow-hidden": { overflow: "hidden" },
|
|
1498
|
+
"overflow-visible": { overflow: "visible" },
|
|
1499
|
+
"overflow-scroll": { overflow: "scroll" },
|
|
1500
|
+
"overflow-auto": web ? { overflow: "auto" } : { overflow: "scroll" },
|
|
1501
|
+
// overflowX / overflowY are web-only
|
|
1502
|
+
"overflow-x-hidden": web ? { overflowX: "hidden" } : null,
|
|
1503
|
+
"overflow-x-scroll": web ? { overflowX: "scroll" } : null,
|
|
1504
|
+
"overflow-x-auto": web ? { overflowX: "auto" } : null,
|
|
1505
|
+
"overflow-y-hidden": web ? { overflowY: "hidden" } : null,
|
|
1506
|
+
"overflow-y-scroll": web ? { overflowY: "scroll" } : null,
|
|
1507
|
+
"overflow-y-auto": web ? { overflowY: "auto" } : null,
|
|
1508
|
+
// Object fit (web-only; use resizeMode prop on RN Image)
|
|
1509
|
+
"object-contain": web ? { objectFit: "contain" } : null,
|
|
1510
|
+
"object-cover": web ? { objectFit: "cover" } : null,
|
|
1511
|
+
"object-fill": web ? { objectFit: "fill" } : null,
|
|
1512
|
+
"object-none": web ? { objectFit: "none" } : null,
|
|
1513
|
+
"object-scale-down": web ? { objectFit: "scale-down" } : null,
|
|
1514
|
+
// Border style (both)
|
|
1515
|
+
"border-solid": { borderStyle: "solid" },
|
|
1516
|
+
"border-dashed": { borderStyle: "dashed" },
|
|
1517
|
+
"border-dotted": { borderStyle: "dotted" },
|
|
1518
|
+
"border-none": { borderWidth: 0 },
|
|
1519
|
+
// Border sides default width (both)
|
|
1520
|
+
"border-t": { borderTopWidth: 1 },
|
|
1521
|
+
"border-r": { borderRightWidth: 1 },
|
|
1522
|
+
"border-b": { borderBottomWidth: 1 },
|
|
1523
|
+
"border-l": { borderLeftWidth: 1 },
|
|
1524
|
+
// Cursor (web-only)
|
|
1525
|
+
"cursor-auto": web ? { cursor: "auto" } : null,
|
|
1526
|
+
"cursor-default": web ? { cursor: "default" } : null,
|
|
1527
|
+
"cursor-pointer": web ? { cursor: "pointer" } : null,
|
|
1528
|
+
"cursor-wait": web ? { cursor: "wait" } : null,
|
|
1529
|
+
"cursor-text": web ? { cursor: "text" } : null,
|
|
1530
|
+
"cursor-move": web ? { cursor: "move" } : null,
|
|
1531
|
+
"cursor-not-allowed": web ? { cursor: "not-allowed" } : null,
|
|
1532
|
+
// User select (web-only)
|
|
1533
|
+
"select-none": web ? { userSelect: "none" } : null,
|
|
1534
|
+
"select-text": web ? { userSelect: "text" } : null,
|
|
1535
|
+
"select-all": web ? { userSelect: "all" } : null,
|
|
1536
|
+
"select-auto": web ? { userSelect: "auto" } : null,
|
|
1537
|
+
// Pointer events (both)
|
|
1538
|
+
"pointer-events-none": { pointerEvents: "none" },
|
|
1539
|
+
"pointer-events-auto": { pointerEvents: "auto" },
|
|
1540
|
+
// Whitespace (web-only; RN Text uses numberOfLines prop instead)
|
|
1541
|
+
"whitespace-normal": web ? { whiteSpace: "normal" } : null,
|
|
1542
|
+
"whitespace-nowrap": web ? { whiteSpace: "nowrap" } : null,
|
|
1543
|
+
"whitespace-pre": web ? { whiteSpace: "pre" } : null,
|
|
1544
|
+
"whitespace-pre-wrap": web ? { whiteSpace: "pre-wrap" } : null,
|
|
1545
|
+
"whitespace-pre-line": web ? { whiteSpace: "pre-line" } : null,
|
|
1546
|
+
// Word break (web-only)
|
|
1547
|
+
"break-normal": web ? { overflowWrap: "normal", wordBreak: "normal" } : null,
|
|
1548
|
+
"break-words": web ? { overflowWrap: "break-word" } : null,
|
|
1549
|
+
"break-all": web ? { wordBreak: "break-all" } : null,
|
|
1550
|
+
// Misc web-only
|
|
1551
|
+
truncate: web ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null,
|
|
1552
|
+
"box-border": web ? { boxSizing: "border-box" } : null,
|
|
1553
|
+
"box-content": web ? { boxSizing: "content-box" } : null,
|
|
1554
|
+
"appearance-none": web ? { appearance: "none" } : null,
|
|
1555
|
+
"outline-none": web ? { outline: "none", outlineOffset: "0" } : null,
|
|
1556
|
+
outline: web ? { outline: "2px solid transparent", outlineOffset: "2px" } : null,
|
|
1557
|
+
resize: web ? { resize: "both" } : null,
|
|
1558
|
+
"resize-none": web ? { resize: "none" } : null,
|
|
1559
|
+
"resize-y": web ? { resize: "vertical" } : null,
|
|
1560
|
+
"resize-x": web ? { resize: "horizontal" } : null,
|
|
1561
|
+
antialiased: web ? { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale" } : null,
|
|
1562
|
+
"subpixel-antialiased": web ? { WebkitFontSmoothing: "subpixel-antialiased", MozOsxFontSmoothing: "auto" } : null,
|
|
1563
|
+
"overflow-ellipsis": web ? { textOverflow: "ellipsis" } : null,
|
|
1564
|
+
"sr-only": web ? {
|
|
1565
|
+
position: "absolute",
|
|
1566
|
+
width: 1,
|
|
1567
|
+
height: 1,
|
|
1568
|
+
padding: 0,
|
|
1569
|
+
margin: -1,
|
|
1570
|
+
overflow: "hidden",
|
|
1571
|
+
clip: "rect(0,0,0,0)",
|
|
1572
|
+
whiteSpace: "nowrap",
|
|
1573
|
+
border: 0
|
|
1574
|
+
} : null,
|
|
1575
|
+
"not-sr-only": web ? {
|
|
1576
|
+
position: "static",
|
|
1577
|
+
width: "auto",
|
|
1578
|
+
height: "auto",
|
|
1579
|
+
padding: 0,
|
|
1580
|
+
margin: 0,
|
|
1581
|
+
overflow: "visible",
|
|
1582
|
+
clip: "auto",
|
|
1583
|
+
whiteSpace: "normal"
|
|
1584
|
+
} : null,
|
|
1585
|
+
// Lists (web-only)
|
|
1586
|
+
"list-none": web ? { listStyleType: "none" } : null,
|
|
1587
|
+
"list-disc": web ? { listStyleType: "disc" } : null,
|
|
1588
|
+
"list-decimal": web ? { listStyleType: "decimal" } : null,
|
|
1589
|
+
// Background clip (web-only)
|
|
1590
|
+
"bg-clip-border": web ? { backgroundClip: "border-box" } : null,
|
|
1591
|
+
"bg-clip-padding": web ? { backgroundClip: "padding-box" } : null,
|
|
1592
|
+
"bg-clip-content": web ? { backgroundClip: "content-box" } : null,
|
|
1593
|
+
"bg-clip-text": web ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
|
|
1594
|
+
// Background image
|
|
1595
|
+
"bg-none": web ? { backgroundImage: "none" } : null,
|
|
1596
|
+
// Background size (web-only)
|
|
1597
|
+
"bg-auto": web ? { backgroundSize: "auto" } : null,
|
|
1598
|
+
"bg-cover": web ? { backgroundSize: "cover" } : null,
|
|
1599
|
+
"bg-contain": web ? { backgroundSize: "contain" } : null,
|
|
1600
|
+
// Background position (web-only)
|
|
1601
|
+
"bg-center": web ? { backgroundPosition: "center" } : null,
|
|
1602
|
+
"bg-top": web ? { backgroundPosition: "top" } : null,
|
|
1603
|
+
"bg-bottom": web ? { backgroundPosition: "bottom" } : null,
|
|
1604
|
+
"bg-left": web ? { backgroundPosition: "left" } : null,
|
|
1605
|
+
"bg-right": web ? { backgroundPosition: "right" } : null,
|
|
1606
|
+
"bg-left-top": web ? { backgroundPosition: "left top" } : null,
|
|
1607
|
+
"bg-left-bottom": web ? { backgroundPosition: "left bottom" } : null,
|
|
1608
|
+
"bg-right-top": web ? { backgroundPosition: "right top" } : null,
|
|
1609
|
+
"bg-right-bottom": web ? { backgroundPosition: "right bottom" } : null,
|
|
1610
|
+
// Background repeat (web-only)
|
|
1611
|
+
"bg-repeat": web ? { backgroundRepeat: "repeat" } : null,
|
|
1612
|
+
"bg-no-repeat": web ? { backgroundRepeat: "no-repeat" } : null,
|
|
1613
|
+
"bg-repeat-x": web ? { backgroundRepeat: "repeat-x" } : null,
|
|
1614
|
+
"bg-repeat-y": web ? { backgroundRepeat: "repeat-y" } : null,
|
|
1615
|
+
"bg-repeat-round": web ? { backgroundRepeat: "round" } : null,
|
|
1616
|
+
"bg-repeat-space": web ? { backgroundRepeat: "space" } : null,
|
|
1617
|
+
// Background attachment (web-only)
|
|
1618
|
+
"bg-fixed": web ? { backgroundAttachment: "fixed" } : null,
|
|
1619
|
+
"bg-local": web ? { backgroundAttachment: "local" } : null,
|
|
1620
|
+
"bg-scroll": web ? { backgroundAttachment: "scroll" } : null,
|
|
1621
|
+
// Object position (web-only)
|
|
1622
|
+
"object-center": web ? { objectPosition: "center" } : null,
|
|
1623
|
+
"object-top": web ? { objectPosition: "top" } : null,
|
|
1624
|
+
"object-bottom": web ? { objectPosition: "bottom" } : null,
|
|
1625
|
+
"object-left": web ? { objectPosition: "left" } : null,
|
|
1626
|
+
"object-right": web ? { objectPosition: "right" } : null,
|
|
1627
|
+
"object-left-top": web ? { objectPosition: "left top" } : null,
|
|
1628
|
+
"object-left-bottom": web ? { objectPosition: "left bottom" } : null,
|
|
1629
|
+
"object-right-top": web ? { objectPosition: "right top" } : null,
|
|
1630
|
+
"object-right-bottom": web ? { objectPosition: "right bottom" } : null,
|
|
1631
|
+
// Table (web-only)
|
|
1632
|
+
table: web ? { display: "table" } : null,
|
|
1633
|
+
"table-auto": web ? { tableLayout: "auto" } : null,
|
|
1634
|
+
"table-fixed": web ? { tableLayout: "fixed" } : null,
|
|
1635
|
+
"caption-top": web ? { captionSide: "top" } : null,
|
|
1636
|
+
"caption-bottom": web ? { captionSide: "bottom" } : null,
|
|
1637
|
+
"border-collapse": web ? { borderCollapse: "collapse" } : null,
|
|
1638
|
+
"border-separate": web ? { borderCollapse: "separate" } : null,
|
|
1639
|
+
// List style position (web-only)
|
|
1640
|
+
"list-inside": web ? { listStylePosition: "inside" } : null,
|
|
1641
|
+
"list-outside": web ? { listStylePosition: "outside" } : null,
|
|
1642
|
+
// Font variant numeric (web-only)
|
|
1643
|
+
"normal-nums": web ? { fontVariantNumeric: "normal" } : null,
|
|
1644
|
+
ordinal: web ? { fontVariantNumeric: "ordinal" } : null,
|
|
1645
|
+
"slashed-zero": web ? { fontVariantNumeric: "slashed-zero" } : null,
|
|
1646
|
+
"lining-nums": web ? { fontVariantNumeric: "lining-nums" } : null,
|
|
1647
|
+
"oldstyle-nums": web ? { fontVariantNumeric: "oldstyle-nums" } : null,
|
|
1648
|
+
"proportional-nums": web ? { fontVariantNumeric: "proportional-nums" } : null,
|
|
1649
|
+
"tabular-nums": web ? { fontVariantNumeric: "tabular-nums" } : null,
|
|
1650
|
+
"diagonal-fractions": web ? { fontVariantNumeric: "diagonal-fractions" } : null,
|
|
1651
|
+
"stacked-fractions": web ? { fontVariantNumeric: "stacked-fractions" } : null,
|
|
1652
|
+
// Isolation (web-only)
|
|
1653
|
+
isolate: web ? { isolation: "isolate" } : null,
|
|
1654
|
+
"isolation-auto": web ? { isolation: "auto" } : null,
|
|
1655
|
+
// Backface visibility (both iOS and Android)
|
|
1656
|
+
"backface-visible": { backfaceVisibility: "visible" },
|
|
1657
|
+
"backface-hidden": { backfaceVisibility: "hidden" },
|
|
1658
|
+
// CSS filters — standalone = default/full effect (web-only)
|
|
1659
|
+
grayscale: web ? { "--kb-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
|
|
1660
|
+
invert: web ? { "--kb-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
|
|
1661
|
+
sepia: web ? { "--kb-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
|
|
1662
|
+
// Divide none
|
|
1663
|
+
"divide-none": web ? { __divideX: 0, __divideY: 0 } : null,
|
|
1664
|
+
// Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
|
|
1665
|
+
group: web ? {} : null,
|
|
1666
|
+
peer: web ? {} : null,
|
|
1667
|
+
// Text-wrap (web-only)
|
|
1668
|
+
"text-wrap": web ? { textWrap: "wrap" } : null,
|
|
1669
|
+
"text-nowrap": web ? { textWrap: "nowrap" } : null,
|
|
1670
|
+
"text-balance": web ? { textWrap: "balance" } : null,
|
|
1671
|
+
"text-pretty": web ? { textWrap: "pretty" } : null,
|
|
1672
|
+
// Screen sizing — dvw/dvh (dynamic viewport units) instead of vw/vh: on mobile
|
|
1673
|
+
// browsers, vh/vw are pinned to the LARGEST viewport size (address bar hidden),
|
|
1674
|
+
// so `h-screen` overflows behind the address bar when it's shown. dvh/dvw track
|
|
1675
|
+
// the actual visible viewport as browser chrome shows/hides. Desktop behavior
|
|
1676
|
+
// is unchanged since there's no dynamic chrome to account for.
|
|
1677
|
+
// (vw/dvw values are web-only; vh/dvh values work cross-platform via spacing scale for h-*)
|
|
1678
|
+
"w-screen": web ? { width: "100dvw" } : null,
|
|
1679
|
+
"min-h-screen": { minHeight: "100dvh" },
|
|
1680
|
+
"max-h-screen": { maxHeight: "100dvh" },
|
|
1681
|
+
"min-w-screen": web ? { minWidth: "100dvw" } : null,
|
|
1682
|
+
"max-w-screen": web ? { maxWidth: "100dvw" } : null,
|
|
1683
|
+
// max-w named container sizes (mirrors Tailwind's container scale)
|
|
1684
|
+
"max-w-none": { maxWidth: "none" },
|
|
1685
|
+
"max-w-xs": { maxWidth: 320 },
|
|
1686
|
+
"max-w-sm": { maxWidth: 384 },
|
|
1687
|
+
"max-w-md": { maxWidth: 448 },
|
|
1688
|
+
"max-w-lg": { maxWidth: 512 },
|
|
1689
|
+
"max-w-xl": { maxWidth: 576 },
|
|
1690
|
+
"max-w-2xl": { maxWidth: 672 },
|
|
1691
|
+
"max-w-3xl": { maxWidth: 768 },
|
|
1692
|
+
"max-w-4xl": { maxWidth: 896 },
|
|
1693
|
+
"max-w-5xl": { maxWidth: 1024 },
|
|
1694
|
+
"max-w-6xl": { maxWidth: 1152 },
|
|
1695
|
+
"max-w-7xl": { maxWidth: 1280 },
|
|
1696
|
+
"max-w-prose": web ? { maxWidth: "65ch" } : null,
|
|
1697
|
+
// Extended cursors (web-only)
|
|
1698
|
+
"cursor-grab": web ? { cursor: "grab" } : null,
|
|
1699
|
+
"cursor-grabbing": web ? { cursor: "grabbing" } : null,
|
|
1700
|
+
"cursor-zoom-in": web ? { cursor: "zoom-in" } : null,
|
|
1701
|
+
"cursor-zoom-out": web ? { cursor: "zoom-out" } : null,
|
|
1702
|
+
"cursor-crosshair": web ? { cursor: "crosshair" } : null,
|
|
1703
|
+
"cursor-help": web ? { cursor: "help" } : null,
|
|
1704
|
+
"cursor-none": web ? { cursor: "none" } : null,
|
|
1705
|
+
// Overflow clip (web-only)
|
|
1706
|
+
"overflow-clip": web ? { overflow: "clip" } : null,
|
|
1707
|
+
"overflow-x-clip": web ? { overflowX: "clip" } : null,
|
|
1708
|
+
"overflow-y-clip": web ? { overflowY: "clip" } : null,
|
|
1709
|
+
// Scroll behavior (web-only)
|
|
1710
|
+
"scroll-smooth": web ? { scrollBehavior: "smooth" } : null,
|
|
1711
|
+
"scroll-auto": web ? { scrollBehavior: "auto" } : null,
|
|
1712
|
+
// Float (web-only)
|
|
1713
|
+
"float-left": web ? { float: "left" } : null,
|
|
1714
|
+
"float-right": web ? { float: "right" } : null,
|
|
1715
|
+
"float-start": web ? { float: "inline-start" } : null,
|
|
1716
|
+
"float-end": web ? { float: "inline-end" } : null,
|
|
1717
|
+
"float-none": web ? { float: "none" } : null,
|
|
1718
|
+
// Clear (web-only)
|
|
1719
|
+
"clear-left": web ? { clear: "left" } : null,
|
|
1720
|
+
"clear-right": web ? { clear: "right" } : null,
|
|
1721
|
+
"clear-both": web ? { clear: "both" } : null,
|
|
1722
|
+
"clear-start": web ? { clear: "inline-start" } : null,
|
|
1723
|
+
"clear-end": web ? { clear: "inline-end" } : null,
|
|
1724
|
+
"clear-none": web ? { clear: "none" } : null,
|
|
1725
|
+
// Vertical align (web-only)
|
|
1726
|
+
"align-baseline": web ? { verticalAlign: "baseline" } : null,
|
|
1727
|
+
"align-top": web ? { verticalAlign: "top" } : null,
|
|
1728
|
+
"align-middle": web ? { verticalAlign: "middle" } : null,
|
|
1729
|
+
"align-bottom": web ? { verticalAlign: "bottom" } : null,
|
|
1730
|
+
"align-text-top": web ? { verticalAlign: "text-top" } : null,
|
|
1731
|
+
"align-text-bottom": web ? { verticalAlign: "text-bottom" } : null,
|
|
1732
|
+
"align-sub": web ? { verticalAlign: "sub" } : null,
|
|
1733
|
+
"align-super": web ? { verticalAlign: "super" } : null,
|
|
1734
|
+
// Touch action (web-only)
|
|
1735
|
+
"touch-auto": web ? { touchAction: "auto" } : null,
|
|
1736
|
+
"touch-none": web ? { touchAction: "none" } : null,
|
|
1737
|
+
"touch-pan-x": web ? { touchAction: "pan-x" } : null,
|
|
1738
|
+
"touch-pan-y": web ? { touchAction: "pan-y" } : null,
|
|
1739
|
+
"touch-pan-left": web ? { touchAction: "pan-left" } : null,
|
|
1740
|
+
"touch-pan-right": web ? { touchAction: "pan-right" } : null,
|
|
1741
|
+
"touch-pan-up": web ? { touchAction: "pan-up" } : null,
|
|
1742
|
+
"touch-pan-down": web ? { touchAction: "pan-down" } : null,
|
|
1743
|
+
"touch-pinch-zoom": web ? { touchAction: "pinch-zoom" } : null,
|
|
1744
|
+
"touch-manipulation": web ? { touchAction: "manipulation" } : null
|
|
1745
|
+
};
|
|
1746
|
+
}
|
|
1747
|
+
function getStandalone() {
|
|
1748
|
+
if (!_standalone) _standalone = buildStandalone();
|
|
1749
|
+
return _standalone;
|
|
1750
|
+
}
|
|
1751
|
+
var layoutResolvers = {
|
|
1752
|
+
// ── Grid (responsive column count: grid-1 … grid-12, or arbitrary) ───────
|
|
1753
|
+
grid: ({ value, isArbitrary }) => {
|
|
1754
|
+
if (!value) return null;
|
|
1755
|
+
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1756
|
+
const n = parseInt(value, 10);
|
|
1757
|
+
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1758
|
+
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1808
1759
|
},
|
|
1809
|
-
// ──
|
|
1810
|
-
|
|
1760
|
+
// ── Grid template columns/rows (Tailwind-style aliases, web-only) ──────────
|
|
1761
|
+
"grid-cols": ({ value, isArbitrary }) => {
|
|
1811
1762
|
if (!getEffectiveIsWeb()) return null;
|
|
1812
|
-
if (
|
|
1813
|
-
if (
|
|
1763
|
+
if (!value) return null;
|
|
1764
|
+
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1765
|
+
if (value === "none") return { display: "grid", gridTemplateColumns: "none" };
|
|
1814
1766
|
const n = parseInt(value, 10);
|
|
1815
|
-
if (
|
|
1816
|
-
|
|
1817
|
-
"3xs": "16rem",
|
|
1818
|
-
"2xs": "18rem",
|
|
1819
|
-
xs: "20rem",
|
|
1820
|
-
sm: "24rem",
|
|
1821
|
-
md: "28rem",
|
|
1822
|
-
lg: "32rem",
|
|
1823
|
-
xl: "36rem",
|
|
1824
|
-
"2xl": "42rem",
|
|
1825
|
-
"3xl": "48rem",
|
|
1826
|
-
"4xl": "56rem",
|
|
1827
|
-
"5xl": "64rem",
|
|
1828
|
-
"6xl": "72rem",
|
|
1829
|
-
"7xl": "80rem"
|
|
1830
|
-
};
|
|
1831
|
-
return widths[value] ? { columnWidth: widths[value] } : null;
|
|
1767
|
+
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1768
|
+
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1832
1769
|
},
|
|
1833
|
-
|
|
1834
|
-
"mix-blend": ({ value }) => {
|
|
1770
|
+
"grid-rows": ({ value, isArbitrary }) => {
|
|
1835
1771
|
if (!getEffectiveIsWeb()) return null;
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
"lighten",
|
|
1843
|
-
"color-dodge",
|
|
1844
|
-
"color-burn",
|
|
1845
|
-
"hard-light",
|
|
1846
|
-
"soft-light",
|
|
1847
|
-
"difference",
|
|
1848
|
-
"exclusion",
|
|
1849
|
-
"hue",
|
|
1850
|
-
"saturation",
|
|
1851
|
-
"color",
|
|
1852
|
-
"luminosity",
|
|
1853
|
-
"plus-lighter"
|
|
1854
|
-
];
|
|
1855
|
-
return modes.includes(value) ? { mixBlendMode: value } : null;
|
|
1772
|
+
if (!value) return null;
|
|
1773
|
+
if (isArbitrary) return { gridTemplateRows: value };
|
|
1774
|
+
if (value === "none") return { gridTemplateRows: "none" };
|
|
1775
|
+
const n = parseInt(value, 10);
|
|
1776
|
+
if (isNaN(n) || n < 1) return null;
|
|
1777
|
+
return { gridTemplateRows: `repeat(${n}, minmax(0, 1fr))` };
|
|
1856
1778
|
},
|
|
1857
|
-
|
|
1779
|
+
// ── Grid auto flow (web-only) ─────────────────────────────────────────────
|
|
1780
|
+
"grid-flow": ({ value }) => {
|
|
1858
1781
|
if (!getEffectiveIsWeb()) return null;
|
|
1859
|
-
const
|
|
1860
|
-
"
|
|
1861
|
-
"
|
|
1862
|
-
"
|
|
1863
|
-
"
|
|
1864
|
-
"
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
"hard-light",
|
|
1869
|
-
"soft-light",
|
|
1870
|
-
"difference",
|
|
1871
|
-
"exclusion",
|
|
1872
|
-
"hue",
|
|
1873
|
-
"saturation",
|
|
1874
|
-
"color",
|
|
1875
|
-
"luminosity"
|
|
1876
|
-
];
|
|
1877
|
-
return modes.includes(value) ? { backgroundBlendMode: value } : null;
|
|
1782
|
+
const flows = {
|
|
1783
|
+
row: "row",
|
|
1784
|
+
col: "column",
|
|
1785
|
+
dense: "dense",
|
|
1786
|
+
"row-dense": "row dense",
|
|
1787
|
+
"col-dense": "column dense"
|
|
1788
|
+
};
|
|
1789
|
+
const flow = flows[value];
|
|
1790
|
+
return flow ? { gridAutoFlow: flow } : null;
|
|
1878
1791
|
},
|
|
1879
|
-
// ──
|
|
1880
|
-
"
|
|
1792
|
+
// ── Grid auto sizing (web-only) ───────────────────────────────────────────
|
|
1793
|
+
"auto-cols": ({ value, isArbitrary }) => {
|
|
1881
1794
|
if (!getEffectiveIsWeb()) return null;
|
|
1882
|
-
if (isArbitrary) return {
|
|
1795
|
+
if (isArbitrary) return { gridAutoColumns: value };
|
|
1883
1796
|
const presets = {
|
|
1884
1797
|
auto: "auto",
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1798
|
+
min: "min-content",
|
|
1799
|
+
max: "max-content",
|
|
1800
|
+
fr: "minmax(0, 1fr)"
|
|
1888
1801
|
};
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
// ── Divide (child combinator CSS, web-only) ───────────────────────────────
|
|
1892
|
-
// These return special __divide* markers that resolver.ts converts to
|
|
1893
|
-
// .cls > * + * { border-... } CSS rules. No inline style is applied.
|
|
1894
|
-
"divide-x": ({ value, isArbitrary }) => {
|
|
1895
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1896
|
-
if (value === "reverse") return null;
|
|
1897
|
-
if (!value) return { __divideX: 1 };
|
|
1898
|
-
const n = parseFloat(value);
|
|
1899
|
-
return isNaN(n) ? null : { __divideX: n };
|
|
1900
|
-
},
|
|
1901
|
-
"divide-y": ({ value, isArbitrary }) => {
|
|
1902
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1903
|
-
if (value === "reverse") return null;
|
|
1904
|
-
if (!value) return { __divideY: 1 };
|
|
1905
|
-
const n = parseFloat(value);
|
|
1906
|
-
return isNaN(n) ? null : { __divideY: n };
|
|
1802
|
+
const v = presets[value];
|
|
1803
|
+
return v ? { gridAutoColumns: v } : null;
|
|
1907
1804
|
},
|
|
1908
|
-
|
|
1805
|
+
"auto-rows": ({ value, isArbitrary }) => {
|
|
1909
1806
|
if (!getEffectiveIsWeb()) return null;
|
|
1910
|
-
if (isArbitrary) return {
|
|
1911
|
-
const
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
none: "none"
|
|
1917
|
-
};
|
|
1918
|
-
if (value in styleTokens) return { __divideStyle: styleTokens[value] };
|
|
1919
|
-
const color = resolveColor(value, colors, false);
|
|
1920
|
-
return color ? { __divideColor: color } : null;
|
|
1921
|
-
},
|
|
1922
|
-
// ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
|
|
1923
|
-
// Named presets give cross-platform shadow; arbitrary is web-only.
|
|
1924
|
-
"text-shadow": ({ value, isArbitrary }, { colors }) => {
|
|
1925
|
-
if (value === "none") {
|
|
1926
|
-
return getEffectiveIsWeb() ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
|
|
1927
|
-
}
|
|
1928
|
-
const webPresets = {
|
|
1929
|
-
"": "0 2px 4px rgba(0,0,0,0.3)",
|
|
1930
|
-
sm: "0 1px 2px rgba(0,0,0,0.3)",
|
|
1931
|
-
md: "0 4px 6px rgba(0,0,0,0.3)",
|
|
1932
|
-
lg: "0 8px 16px rgba(0,0,0,0.5)",
|
|
1933
|
-
xl: "0 16px 32px rgba(0,0,0,0.5)"
|
|
1934
|
-
};
|
|
1935
|
-
const nativePresets = {
|
|
1936
|
-
"": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
|
|
1937
|
-
sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
|
|
1938
|
-
md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
|
|
1939
|
-
lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
|
|
1940
|
-
xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
|
|
1807
|
+
if (isArbitrary) return { gridAutoRows: value };
|
|
1808
|
+
const presets = {
|
|
1809
|
+
auto: "auto",
|
|
1810
|
+
min: "min-content",
|
|
1811
|
+
max: "max-content",
|
|
1812
|
+
fr: "minmax(0, 1fr)"
|
|
1941
1813
|
};
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
return nativePresets[value] ?? null;
|
|
1945
|
-
}
|
|
1946
|
-
if (isArbitrary) {
|
|
1947
|
-
return getEffectiveIsWeb() ? { textShadow: value.replace(/_/g, " ") } : null;
|
|
1948
|
-
}
|
|
1949
|
-
const color = resolveColor(value, colors, false);
|
|
1950
|
-
if (color) {
|
|
1951
|
-
return getEffectiveIsWeb() ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
|
|
1952
|
-
}
|
|
1953
|
-
return null;
|
|
1814
|
+
const v = presets[value];
|
|
1815
|
+
return v ? { gridAutoRows: v } : null;
|
|
1954
1816
|
},
|
|
1955
|
-
// ──
|
|
1956
|
-
|
|
1957
|
-
if (
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
}
|
|
1962
|
-
if (value === "none") return getEffectiveIsWeb() ? { transform: "none" } : null;
|
|
1963
|
-
const n = parseFloat(value);
|
|
1964
|
-
if (isNaN(n)) return null;
|
|
1965
|
-
return getEffectiveIsWeb() ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
|
|
1817
|
+
// ── Grid column placement (web-only) ──────────────────────────────────────
|
|
1818
|
+
"col-span": ({ value }) => {
|
|
1819
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1820
|
+
if (value === "full") return { gridColumn: "1 / -1" };
|
|
1821
|
+
const n = parseInt(value, 10);
|
|
1822
|
+
return isNaN(n) ? null : { gridColumn: `span ${n} / span ${n}` };
|
|
1966
1823
|
},
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
if (
|
|
1970
|
-
|
|
1971
|
-
|
|
1824
|
+
"col-start": ({ value, isArbitrary }) => {
|
|
1825
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1826
|
+
if (value === "auto") return { gridColumnStart: "auto" };
|
|
1827
|
+
if (isArbitrary) return { gridColumnStart: value };
|
|
1828
|
+
const n = parseInt(value, 10);
|
|
1829
|
+
return isNaN(n) ? null : { gridColumnStart: n };
|
|
1972
1830
|
},
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1831
|
+
"col-end": ({ value, isArbitrary }) => {
|
|
1832
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1833
|
+
if (value === "auto") return { gridColumnEnd: "auto" };
|
|
1834
|
+
if (isArbitrary) return { gridColumnEnd: value };
|
|
1835
|
+
const n = parseInt(value, 10);
|
|
1836
|
+
return isNaN(n) ? null : { gridColumnEnd: n };
|
|
1977
1837
|
},
|
|
1978
|
-
|
|
1979
|
-
// Each variant injects a @keyframes rule once via the __keyframe marker.
|
|
1980
|
-
// resolver.ts detects __keyframe, injects the rule, then strips the marker
|
|
1981
|
-
// so it never reaches element inline styles.
|
|
1982
|
-
animate: ({ value, isArbitrary }, theme) => {
|
|
1838
|
+
col: ({ value, isArbitrary }) => {
|
|
1983
1839
|
if (!getEffectiveIsWeb()) return null;
|
|
1984
|
-
if (
|
|
1985
|
-
if (
|
|
1986
|
-
|
|
1987
|
-
return custom ? buildAnimationValue(custom, theme.keyframes) : null;
|
|
1840
|
+
if (!value || value === "auto") return { gridColumn: "auto" };
|
|
1841
|
+
if (isArbitrary) return { gridColumn: value };
|
|
1842
|
+
return null;
|
|
1988
1843
|
},
|
|
1989
|
-
// ──
|
|
1990
|
-
"
|
|
1844
|
+
// ── Grid row placement (web-only) ─────────────────────────────────────────
|
|
1845
|
+
"row-span": ({ value }) => {
|
|
1991
1846
|
if (!getEffectiveIsWeb()) return null;
|
|
1992
|
-
if (value === "
|
|
1847
|
+
if (value === "full") return { gridRow: "1 / -1" };
|
|
1993
1848
|
const n = parseInt(value, 10);
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
1849
|
+
return isNaN(n) ? null : { gridRow: `span ${n} / span ${n}` };
|
|
1850
|
+
},
|
|
1851
|
+
"row-start": ({ value, isArbitrary }) => {
|
|
1852
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1853
|
+
if (value === "auto") return { gridRowStart: "auto" };
|
|
1854
|
+
if (isArbitrary) return { gridRowStart: value };
|
|
1855
|
+
const n = parseInt(value, 10);
|
|
1856
|
+
return isNaN(n) ? null : { gridRowStart: n };
|
|
1857
|
+
},
|
|
1858
|
+
"row-end": ({ value, isArbitrary }) => {
|
|
1859
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1860
|
+
if (value === "auto") return { gridRowEnd: "auto" };
|
|
1861
|
+
if (isArbitrary) return { gridRowEnd: value };
|
|
1862
|
+
const n = parseInt(value, 10);
|
|
1863
|
+
return isNaN(n) ? null : { gridRowEnd: n };
|
|
1864
|
+
},
|
|
1865
|
+
row: ({ value, isArbitrary }) => {
|
|
1866
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1867
|
+
if (!value || value === "auto") return { gridRow: "auto" };
|
|
1868
|
+
if (isArbitrary) return { gridRow: value };
|
|
1869
|
+
return null;
|
|
1870
|
+
},
|
|
1871
|
+
// ── Grid alignment (web-only) ──────────────────────────────────────────────
|
|
1872
|
+
// place-items is shorthand for align-items + justify-items on a grid container
|
|
1873
|
+
"place-items": ({ value }) => {
|
|
1874
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1875
|
+
const map = {
|
|
1876
|
+
start: "start",
|
|
1877
|
+
end: "end",
|
|
1878
|
+
center: "center",
|
|
1879
|
+
stretch: "stretch",
|
|
1880
|
+
baseline: "baseline"
|
|
2000
1881
|
};
|
|
1882
|
+
return map[value] ? { placeItems: map[value] } : null;
|
|
2001
1883
|
},
|
|
2002
|
-
//
|
|
2003
|
-
|
|
1884
|
+
// place-content is shorthand for align-content + justify-content on a grid container
|
|
1885
|
+
"place-content": ({ value }) => {
|
|
2004
1886
|
if (!getEffectiveIsWeb()) return null;
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
1887
|
+
const map = {
|
|
1888
|
+
start: "start",
|
|
1889
|
+
end: "end",
|
|
1890
|
+
center: "center",
|
|
1891
|
+
stretch: "stretch",
|
|
1892
|
+
between: "space-between",
|
|
1893
|
+
around: "space-around",
|
|
1894
|
+
evenly: "space-evenly",
|
|
1895
|
+
baseline: "baseline"
|
|
1896
|
+
};
|
|
1897
|
+
return map[value] ? { placeContent: map[value] } : null;
|
|
2008
1898
|
},
|
|
2009
|
-
//
|
|
2010
|
-
|
|
1899
|
+
// justify-items controls inline-axis alignment of grid items within their cells
|
|
1900
|
+
"justify-items": ({ value }) => {
|
|
2011
1901
|
if (!getEffectiveIsWeb()) return null;
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
1902
|
+
const map = {
|
|
1903
|
+
start: "start",
|
|
1904
|
+
end: "end",
|
|
1905
|
+
center: "center",
|
|
1906
|
+
stretch: "stretch"
|
|
1907
|
+
};
|
|
1908
|
+
return map[value] ? { justifyItems: map[value] } : null;
|
|
2015
1909
|
},
|
|
2016
|
-
//
|
|
2017
|
-
|
|
2018
|
-
// take stroke/fill as component PROPS, not style entries, so there's no
|
|
2019
|
-
// reliable way to apply a resolved color through the `style` prop there.
|
|
2020
|
-
// `stroke-{n}` sets strokeWidth (a plain number, unlike a color) — same
|
|
2021
|
-
// color-first-then-numeric-fallback disambiguation `border` uses above.
|
|
2022
|
-
stroke: ({ value, isArbitrary }, { colors }) => {
|
|
1910
|
+
// place-self is shorthand for align-self + justify-self on a grid item
|
|
1911
|
+
"place-self": ({ value }) => {
|
|
2023
1912
|
if (!getEffectiveIsWeb()) return null;
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
const n = parseFloat(value);
|
|
2033
|
-
return isNaN(n) ? null : { strokeWidth: n };
|
|
1913
|
+
const map = {
|
|
1914
|
+
auto: "auto",
|
|
1915
|
+
start: "start",
|
|
1916
|
+
end: "end",
|
|
1917
|
+
center: "center",
|
|
1918
|
+
stretch: "stretch"
|
|
1919
|
+
};
|
|
1920
|
+
return map[value] ? { placeSelf: map[value] } : null;
|
|
2034
1921
|
},
|
|
2035
|
-
|
|
1922
|
+
// justify-self controls inline-axis self-alignment of a grid item
|
|
1923
|
+
"justify-self": ({ value }) => {
|
|
2036
1924
|
if (!getEffectiveIsWeb()) return null;
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
1925
|
+
const map = {
|
|
1926
|
+
auto: "auto",
|
|
1927
|
+
start: "start",
|
|
1928
|
+
end: "end",
|
|
1929
|
+
center: "center",
|
|
1930
|
+
stretch: "stretch"
|
|
1931
|
+
};
|
|
1932
|
+
return map[value] ? { justifySelf: map[value] } : null;
|
|
2042
1933
|
},
|
|
2043
1934
|
// ── Flex ───────────────────────────────────────────────────────────────────
|
|
1935
|
+
// flex-1/flex-auto/flex-none/grow/shrink are item-level sizing properties —
|
|
1936
|
+
// deliberately NOT implying display:flex here. See the "Flex grow / shrink"
|
|
1937
|
+
// comment in the standalone table above for why: these already work via the
|
|
1938
|
+
// PARENT's flex context regardless of this element's own display, so
|
|
1939
|
+
// forcing display:flex here would only be a surprising, unrelated side
|
|
1940
|
+
// effect on this element's OWN children.
|
|
2044
1941
|
flex: ({ value, isArbitrary }, { flex }) => {
|
|
2045
1942
|
if (!value) return { display: "flex" };
|
|
2046
1943
|
if (isArbitrary) {
|
|
@@ -2059,10 +1956,6 @@ var RESOLVERS = {
|
|
|
2059
1956
|
const n = parseFloat(value);
|
|
2060
1957
|
return isNaN(n) ? null : { flex: n };
|
|
2061
1958
|
},
|
|
2062
|
-
basis: ({ value, isArbitrary }, { spacing }) => {
|
|
2063
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
2064
|
-
return v !== null ? { flexBasis: v } : null;
|
|
2065
|
-
},
|
|
2066
1959
|
grow: ({ value }, _) => {
|
|
2067
1960
|
if (!value) return { flexGrow: 1 };
|
|
2068
1961
|
const n = parseFloat(value);
|
|
@@ -2077,72 +1970,132 @@ var RESOLVERS = {
|
|
|
2077
1970
|
const n = parseInt(value, 10);
|
|
2078
1971
|
return isNaN(n) ? null : { order: negative ? -n : n };
|
|
2079
1972
|
},
|
|
2080
|
-
// ── Gap ────────────────────────────────────────────────────────────────────
|
|
2081
|
-
gap: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2082
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2083
|
-
return v !== null ? { gap: v } : null;
|
|
2084
|
-
},
|
|
2085
|
-
"gap-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2086
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2087
|
-
return v !== null ? { columnGap: v } : null;
|
|
2088
|
-
},
|
|
2089
|
-
"gap-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2090
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2091
|
-
return v !== null ? { rowGap: v } : null;
|
|
2092
|
-
},
|
|
2093
|
-
// ── Position ───────────────────────────────────────────────────────────────
|
|
2094
|
-
top: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2095
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2096
|
-
return v !== null ? { top: v } : null;
|
|
2097
|
-
},
|
|
2098
|
-
right: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2099
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2100
|
-
return v !== null ? { right: v } : null;
|
|
2101
|
-
},
|
|
2102
|
-
bottom: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2103
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2104
|
-
return v !== null ? { bottom: v } : null;
|
|
2105
|
-
},
|
|
2106
|
-
left: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2107
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2108
|
-
return v !== null ? { left: v } : null;
|
|
2109
|
-
},
|
|
2110
|
-
inset: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2111
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2112
|
-
return v !== null ? { top: v, right: v, bottom: v, left: v } : null;
|
|
2113
|
-
},
|
|
2114
|
-
"inset-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2115
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2116
|
-
return v !== null ? { left: v, right: v } : null;
|
|
2117
|
-
},
|
|
2118
|
-
"inset-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2119
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2120
|
-
return v !== null ? { top: v, bottom: v } : null;
|
|
2121
|
-
},
|
|
2122
1973
|
// ── Z-index ────────────────────────────────────────────────────────────────
|
|
2123
1974
|
z: ({ value, isArbitrary }, { zIndex }) => {
|
|
2124
1975
|
if (isArbitrary) {
|
|
2125
|
-
const n2 = parseInt(value);
|
|
2126
|
-
return isNaN(n2) ? null : { zIndex: n2 };
|
|
2127
|
-
}
|
|
2128
|
-
const v = zIndex[value];
|
|
2129
|
-
if (v !== void 0) {
|
|
2130
|
-
if (v === "auto") return getEffectiveIsWeb() ? { zIndex: "auto" } : null;
|
|
2131
|
-
return { zIndex: v };
|
|
1976
|
+
const n2 = parseInt(value);
|
|
1977
|
+
return isNaN(n2) ? null : { zIndex: n2 };
|
|
1978
|
+
}
|
|
1979
|
+
const v = zIndex[value];
|
|
1980
|
+
if (v !== void 0) {
|
|
1981
|
+
if (v === "auto") return getEffectiveIsWeb() ? { zIndex: "auto" } : null;
|
|
1982
|
+
return { zIndex: v };
|
|
1983
|
+
}
|
|
1984
|
+
const n = parseInt(value);
|
|
1985
|
+
return isNaN(n) ? null : { zIndex: n };
|
|
1986
|
+
},
|
|
1987
|
+
// ── Aspect ratio ───────────────────────────────────────────────────────────
|
|
1988
|
+
aspect: ({ value, isArbitrary }) => {
|
|
1989
|
+
if (isArbitrary) return { aspectRatio: value };
|
|
1990
|
+
const presets = { auto: "auto", square: 1, video: 16 / 9 };
|
|
1991
|
+
if (!(value in presets)) return null;
|
|
1992
|
+
const v = presets[value];
|
|
1993
|
+
if (v === "auto") return getEffectiveIsWeb() ? { aspectRatio: "auto" } : null;
|
|
1994
|
+
return { aspectRatio: v };
|
|
1995
|
+
},
|
|
1996
|
+
// ── Columns (web-only) ─────────────────────────────────────────────────────
|
|
1997
|
+
columns: ({ value, isArbitrary }) => {
|
|
1998
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1999
|
+
if (isArbitrary) return { columnCount: value };
|
|
2000
|
+
if (value === "auto") return { columnCount: "auto" };
|
|
2001
|
+
const n = parseInt(value, 10);
|
|
2002
|
+
if (!isNaN(n)) return { columnCount: n };
|
|
2003
|
+
const widths = {
|
|
2004
|
+
"3xs": "16rem",
|
|
2005
|
+
"2xs": "18rem",
|
|
2006
|
+
xs: "20rem",
|
|
2007
|
+
sm: "24rem",
|
|
2008
|
+
md: "28rem",
|
|
2009
|
+
lg: "32rem",
|
|
2010
|
+
xl: "36rem",
|
|
2011
|
+
"2xl": "42rem",
|
|
2012
|
+
"3xl": "48rem",
|
|
2013
|
+
"4xl": "56rem",
|
|
2014
|
+
"5xl": "64rem",
|
|
2015
|
+
"6xl": "72rem",
|
|
2016
|
+
"7xl": "80rem"
|
|
2017
|
+
};
|
|
2018
|
+
return widths[value] ? { columnWidth: widths[value] } : null;
|
|
2019
|
+
}
|
|
2020
|
+
};
|
|
2021
|
+
|
|
2022
|
+
// src/core/resolvers/typography.ts
|
|
2023
|
+
function resolveFontSize(value, fontSizes, isArbitrary) {
|
|
2024
|
+
if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
2025
|
+
return fontSizes[value] ?? null;
|
|
2026
|
+
}
|
|
2027
|
+
var typographyResolvers = {
|
|
2028
|
+
// ── Text ───────────────────────────────────────────────────────────────────
|
|
2029
|
+
text: ({ value, isArbitrary }, { colors, fontSize }) => {
|
|
2030
|
+
const size = resolveFontSize(value, fontSize, false);
|
|
2031
|
+
if (!isArbitrary && size !== null) return { fontSize: size };
|
|
2032
|
+
if (isArbitrary) {
|
|
2033
|
+
if (/^\d/.test(value) || /^(calc|min|max|clamp)/.test(value)) {
|
|
2034
|
+
return { fontSize: getEffectiveIsWeb() ? value : toNativeValue(value) };
|
|
2035
|
+
}
|
|
2036
|
+
return { color: getEffectiveIsWeb() ? withOpacityVar(value, "--text-opacity") : value };
|
|
2132
2037
|
}
|
|
2133
|
-
const
|
|
2134
|
-
|
|
2038
|
+
const color = resolveColor(value, colors, false);
|
|
2039
|
+
if (!color) return null;
|
|
2040
|
+
return { color: getEffectiveIsWeb() ? withOpacityVar(color, "--text-opacity") : color };
|
|
2135
2041
|
},
|
|
2136
|
-
|
|
2137
|
-
|
|
2042
|
+
"text-opacity": ({ value, isArbitrary }, _) => {
|
|
2043
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2044
|
+
const n = parseFloat(value);
|
|
2045
|
+
if (isNaN(n)) return null;
|
|
2046
|
+
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
2047
|
+
return { "--text-opacity": v };
|
|
2048
|
+
},
|
|
2049
|
+
// ── Text decoration advanced (web-only) ───────────────────────────────────
|
|
2050
|
+
decoration: ({ value, isArbitrary }, { colors }) => {
|
|
2051
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2138
2052
|
if (isArbitrary) {
|
|
2139
|
-
|
|
2140
|
-
return
|
|
2053
|
+
if (/^\d/.test(value) || value.startsWith("calc(")) return { textDecorationThickness: value };
|
|
2054
|
+
return { textDecorationColor: value };
|
|
2141
2055
|
}
|
|
2142
|
-
const
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2056
|
+
const thickTokens = {
|
|
2057
|
+
auto: "auto",
|
|
2058
|
+
"from-font": "from-font",
|
|
2059
|
+
"0": "0px",
|
|
2060
|
+
"1": "1px",
|
|
2061
|
+
"2": "2px",
|
|
2062
|
+
"4": "4px",
|
|
2063
|
+
"8": "8px"
|
|
2064
|
+
};
|
|
2065
|
+
if (value in thickTokens) return { textDecorationThickness: thickTokens[value] };
|
|
2066
|
+
const styleTokens = {
|
|
2067
|
+
solid: "solid",
|
|
2068
|
+
dashed: "dashed",
|
|
2069
|
+
dotted: "dotted",
|
|
2070
|
+
double: "double",
|
|
2071
|
+
wavy: "wavy"
|
|
2072
|
+
};
|
|
2073
|
+
if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
|
|
2074
|
+
const color = resolveColor(value, colors, false);
|
|
2075
|
+
return color ? { textDecorationColor: color } : null;
|
|
2076
|
+
},
|
|
2077
|
+
"underline-offset": ({ value, isArbitrary }) => {
|
|
2078
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2079
|
+
if (isArbitrary) return { textUnderlineOffset: value };
|
|
2080
|
+
const offsets = {
|
|
2081
|
+
auto: "auto",
|
|
2082
|
+
"0": "0px",
|
|
2083
|
+
"1": "1px",
|
|
2084
|
+
"2": "2px",
|
|
2085
|
+
"4": "4px",
|
|
2086
|
+
"8": "8px"
|
|
2087
|
+
};
|
|
2088
|
+
return offsets[value] ? { textUnderlineOffset: offsets[value] } : null;
|
|
2089
|
+
},
|
|
2090
|
+
// ── Content (web-only — for before:/after: pseudo-elements, which don't exist on native) ──
|
|
2091
|
+
// Arbitrary value carries its own quotes from the bracket syntax (content-['*'] parses to
|
|
2092
|
+
// the literal string 'you can see it' quotes included), so it passes straight through as a
|
|
2093
|
+
// valid `content: '*'` CSS value with no extra wrapping needed.
|
|
2094
|
+
content: ({ value, isArbitrary }) => {
|
|
2095
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2096
|
+
if (isArbitrary) return { content: value };
|
|
2097
|
+
const presets = { none: "none" };
|
|
2098
|
+
return value in presets ? { content: presets[value] } : null;
|
|
2146
2099
|
},
|
|
2147
2100
|
// ── Font ───────────────────────────────────────────────────────────────────
|
|
2148
2101
|
font: ({ value, isArbitrary }, { fontFamily, fontWeight }) => {
|
|
@@ -2168,10 +2121,57 @@ var RESOLVERS = {
|
|
|
2168
2121
|
const v = letterSpacing[value];
|
|
2169
2122
|
return v !== void 0 ? { letterSpacing: v } : null;
|
|
2170
2123
|
},
|
|
2171
|
-
// ──
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
return
|
|
2124
|
+
// ── Line-clamp (web-only) ─────────────────────────────────────────────────
|
|
2125
|
+
"line-clamp": ({ value }) => {
|
|
2126
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2127
|
+
if (value === "none") return { overflow: "visible", display: "block", WebkitLineClamp: "unset" };
|
|
2128
|
+
const n = parseInt(value, 10);
|
|
2129
|
+
if (isNaN(n) || n < 1) return null;
|
|
2130
|
+
return {
|
|
2131
|
+
overflow: "hidden",
|
|
2132
|
+
display: "-webkit-box",
|
|
2133
|
+
WebkitBoxOrient: "vertical",
|
|
2134
|
+
WebkitLineClamp: n
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
2137
|
+
};
|
|
2138
|
+
|
|
2139
|
+
// src/core/resolvers/transform.ts
|
|
2140
|
+
var transformResolvers = {
|
|
2141
|
+
// ── Transform extras (web-only) ───────────────────────────────────────────
|
|
2142
|
+
"skew-x": ({ value, negative, isArbitrary }) => {
|
|
2143
|
+
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
2144
|
+
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2145
|
+
return getEffectiveIsWeb() ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
|
|
2146
|
+
},
|
|
2147
|
+
"skew-y": ({ value, negative, isArbitrary }) => {
|
|
2148
|
+
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
2149
|
+
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2150
|
+
return getEffectiveIsWeb() ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
|
|
2151
|
+
},
|
|
2152
|
+
// Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
|
|
2153
|
+
transform: ({ value, isArbitrary }) => {
|
|
2154
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2155
|
+
if (isArbitrary) return { transform: value.replace(/_/g, " ") };
|
|
2156
|
+
if (value === "none") return { transform: "none" };
|
|
2157
|
+
return null;
|
|
2158
|
+
},
|
|
2159
|
+
// Transform origin
|
|
2160
|
+
origin: ({ value, isArbitrary }) => {
|
|
2161
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2162
|
+
if (isArbitrary) return { transformOrigin: value.replace(/_/g, " ") };
|
|
2163
|
+
const origins = {
|
|
2164
|
+
center: "center",
|
|
2165
|
+
top: "top",
|
|
2166
|
+
"top-right": "top right",
|
|
2167
|
+
right: "right",
|
|
2168
|
+
"bottom-right": "bottom right",
|
|
2169
|
+
bottom: "bottom",
|
|
2170
|
+
"bottom-left": "bottom left",
|
|
2171
|
+
left: "left",
|
|
2172
|
+
"top-left": "top left"
|
|
2173
|
+
};
|
|
2174
|
+
return origins[value] ? { transformOrigin: origins[value] } : null;
|
|
2175
2175
|
},
|
|
2176
2176
|
// ── Scale ──────────────────────────────────────────────────────────────────
|
|
2177
2177
|
// Non-arbitrary: scale-150 → value='150' → 150/100 = 1.5
|
|
@@ -2202,35 +2202,86 @@ var RESOLVERS = {
|
|
|
2202
2202
|
const finalDeg = negative ? -deg : deg;
|
|
2203
2203
|
return getEffectiveIsWeb() ? { transform: `rotate(${finalDeg}deg)` } : { transform: [{ rotate: `${finalDeg}deg` }] };
|
|
2204
2204
|
},
|
|
2205
|
-
// ──
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
const n = parseFloat(v);
|
|
2212
|
-
return isNaN(n) ? null : { transform: [{ translateX: n }] };
|
|
2205
|
+
// ── Perspective transform (cross-platform: iOS, Android, web) ────────────
|
|
2206
|
+
perspective: ({ value, isArbitrary }) => {
|
|
2207
|
+
if (isArbitrary) {
|
|
2208
|
+
const numPx = parseFloat(value);
|
|
2209
|
+
if (getEffectiveIsWeb()) return { transform: `perspective(${value})` };
|
|
2210
|
+
return isNaN(numPx) ? null : { transform: [{ perspective: numPx }] };
|
|
2213
2211
|
}
|
|
2214
|
-
return
|
|
2212
|
+
if (value === "none") return getEffectiveIsWeb() ? { transform: "none" } : null;
|
|
2213
|
+
const n = parseFloat(value);
|
|
2214
|
+
if (isNaN(n)) return null;
|
|
2215
|
+
return getEffectiveIsWeb() ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
|
|
2216
|
+
}
|
|
2217
|
+
};
|
|
2218
|
+
|
|
2219
|
+
// src/core/resolvers/effects.ts
|
|
2220
|
+
function keyframeDeclToCSS(decl) {
|
|
2221
|
+
return Object.entries(decl).map(([prop, val]) => `${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${val}`).join("; ");
|
|
2222
|
+
}
|
|
2223
|
+
function buildKeyframeCSS(name, steps) {
|
|
2224
|
+
const body = Object.entries(steps).map(([selector, decl]) => `${selector} { ${keyframeDeclToCSS(decl)} }`).join(" ");
|
|
2225
|
+
return `@keyframes ${name} { ${body} }`;
|
|
2226
|
+
}
|
|
2227
|
+
var BUILTIN_ANIMATIONS = {
|
|
2228
|
+
none: { animation: "none" },
|
|
2229
|
+
spin: {
|
|
2230
|
+
animation: "kb-spin 1s linear infinite",
|
|
2231
|
+
__keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
|
|
2215
2232
|
},
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2233
|
+
ping: {
|
|
2234
|
+
animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
|
|
2235
|
+
__keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
|
|
2236
|
+
},
|
|
2237
|
+
pulse: {
|
|
2238
|
+
animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
|
|
2239
|
+
__keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
|
|
2240
|
+
},
|
|
2241
|
+
bounce: {
|
|
2242
|
+
animation: "kb-bounce 1s infinite",
|
|
2243
|
+
__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) } }"
|
|
2244
|
+
}
|
|
2245
|
+
};
|
|
2246
|
+
function buildAnimationValue(animation, keyframes) {
|
|
2247
|
+
const words = animation.trim().split(/\s+/);
|
|
2248
|
+
const name = words[0];
|
|
2249
|
+
if (!name) return { animation };
|
|
2250
|
+
const builtin = BUILTIN_ANIMATIONS[name];
|
|
2251
|
+
if (builtin?.__keyframe) {
|
|
2252
|
+
const kbName = builtin.animation.split(/\s+/, 1)[0];
|
|
2253
|
+
return { animation: [kbName, ...words.slice(1)].join(" "), __keyframe: builtin.__keyframe };
|
|
2254
|
+
}
|
|
2255
|
+
const steps = keyframes?.[name];
|
|
2256
|
+
return steps ? { animation, __keyframe: buildKeyframeCSS(name, steps) } : { animation };
|
|
2257
|
+
}
|
|
2258
|
+
var effectResolvers = {
|
|
2259
|
+
// ── Opacity ────────────────────────────────────────────────────────────────
|
|
2260
|
+
opacity: ({ value, isArbitrary }, { opacity }) => {
|
|
2261
|
+
if (isArbitrary) {
|
|
2262
|
+
const v2 = parseFloat(value);
|
|
2263
|
+
return isNaN(v2) ? null : { opacity: v2 > 1 ? v2 / 100 : v2 };
|
|
2223
2264
|
}
|
|
2224
|
-
|
|
2265
|
+
const v = opacity[value];
|
|
2266
|
+
if (v !== void 0) return { opacity: v };
|
|
2267
|
+
const n = parseFloat(value);
|
|
2268
|
+
return isNaN(n) ? null : { opacity: n > 1 ? n / 100 : n };
|
|
2225
2269
|
},
|
|
2226
|
-
// ──
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2270
|
+
// ── Shadow ─────────────────────────────────────────────────────────────────
|
|
2271
|
+
shadow: ({ value }, { shadow }) => {
|
|
2272
|
+
const key = value === "" ? "DEFAULT" : value;
|
|
2273
|
+
return shadow[key] ?? null;
|
|
2274
|
+
},
|
|
2275
|
+
// ── Animations (CSS keyframe animations, web-only) ────────────────────────
|
|
2276
|
+
// Each variant injects a @keyframes rule once via the __keyframe marker.
|
|
2277
|
+
// resolver.ts detects __keyframe, injects the rule, then strips the marker
|
|
2278
|
+
// so it never reaches element inline styles.
|
|
2279
|
+
animate: ({ value, isArbitrary }, theme) => {
|
|
2280
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2281
|
+
if (isArbitrary) return buildAnimationValue(value.replace(/_/g, " "), theme.keyframes);
|
|
2282
|
+
if (value in BUILTIN_ANIMATIONS) return BUILTIN_ANIMATIONS[value];
|
|
2283
|
+
const custom = theme.animation?.[value];
|
|
2284
|
+
return custom ? buildAnimationValue(custom, theme.keyframes) : null;
|
|
2234
2285
|
},
|
|
2235
2286
|
// ── Transition (web-only; use Animated API on native) ─────────────────────
|
|
2236
2287
|
transition: ({ value }) => {
|
|
@@ -2258,91 +2309,107 @@ var RESOLVERS = {
|
|
|
2258
2309
|
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2259
2310
|
const ms = isArbitrary ? value : `${value}ms`;
|
|
2260
2311
|
return { transitionDelay: ms };
|
|
2312
|
+
}
|
|
2313
|
+
};
|
|
2314
|
+
|
|
2315
|
+
// src/core/resolvers/misc.ts
|
|
2316
|
+
var miscResolvers = {
|
|
2317
|
+
// ── Arbitrary CSS property (web-only): [property:value] with no utility prefix ──
|
|
2318
|
+
// e.g. [mask-type:luminance], [--my-var:10px]. parser.ts already isolates this case
|
|
2319
|
+
// as utility: '' — it's ALSO how a stray, prefix-less negative bracket ("-[10px]",
|
|
2320
|
+
// presumably a typo) parses, which is why this only fires when the arbitrary value
|
|
2321
|
+
// itself contains a "property:value" pair; anything else (no colon) still resolves
|
|
2322
|
+
// to null exactly as before this resolver existed, rather than guessing a property.
|
|
2323
|
+
//
|
|
2324
|
+
// Only the FIRST colon splits property from value — the value itself may contain
|
|
2325
|
+
// more colons (a URL's "http://…") and must stay intact: [background:url(http://x/a.png)].
|
|
2326
|
+
// camelToKebab() in resolver.ts is a no-op on an already-kebab-case (or "--"-prefixed
|
|
2327
|
+
// custom property) key, so it can be used as the style object key as-written with no
|
|
2328
|
+
// extra case conversion — it only needs to look like a plausible CSS property name.
|
|
2329
|
+
"": ({ value, isArbitrary, negative }) => {
|
|
2330
|
+
if (!getEffectiveIsWeb() || !isArbitrary || !value) return null;
|
|
2331
|
+
if (negative) return null;
|
|
2332
|
+
const colonIdx = value.indexOf(":");
|
|
2333
|
+
if (colonIdx <= 0) return null;
|
|
2334
|
+
const prop = value.slice(0, colonIdx).trim();
|
|
2335
|
+
const cssValue = value.slice(colonIdx + 1).trim();
|
|
2336
|
+
if (!cssValue || !/^(--[\w-]+|[a-zA-Z-]+)$/.test(prop)) return null;
|
|
2337
|
+
return { [prop]: cssValue };
|
|
2261
2338
|
},
|
|
2262
|
-
// ──
|
|
2263
|
-
//
|
|
2264
|
-
//
|
|
2265
|
-
//
|
|
2266
|
-
//
|
|
2267
|
-
//
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
if (!value) {
|
|
2276
|
-
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
2339
|
+
// ── SVG stroke/fill (web-only) ────────────────────────────────────────────
|
|
2340
|
+
// Native is intentionally excluded: react-native-svg's <Path>/<Circle>/etc.
|
|
2341
|
+
// take stroke/fill as component PROPS, not style entries, so there's no
|
|
2342
|
+
// reliable way to apply a resolved color through the `style` prop there.
|
|
2343
|
+
// `stroke-{n}` sets strokeWidth (a plain number, unlike a color) — same
|
|
2344
|
+
// color-first-then-numeric-fallback disambiguation `border` uses above.
|
|
2345
|
+
stroke: ({ value, isArbitrary }, { colors }) => {
|
|
2346
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2347
|
+
if (!value) return null;
|
|
2348
|
+
if (value === "none") return { stroke: "none" };
|
|
2349
|
+
if (isArbitrary) {
|
|
2350
|
+
const w = toNativeValue(value);
|
|
2351
|
+
return typeof w === "number" ? { strokeWidth: w } : { stroke: value };
|
|
2277
2352
|
}
|
|
2278
|
-
|
|
2279
|
-
|
|
2353
|
+
const color = resolveColor(value, colors, false);
|
|
2354
|
+
if (color) return { stroke: color };
|
|
2355
|
+
const n = parseFloat(value);
|
|
2356
|
+
return isNaN(n) ? null : { strokeWidth: n };
|
|
2357
|
+
},
|
|
2358
|
+
fill: ({ value, isArbitrary }, { colors }) => {
|
|
2359
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2360
|
+
if (!value) return null;
|
|
2361
|
+
if (value === "none") return { fill: "none" };
|
|
2362
|
+
if (isArbitrary) return { fill: value };
|
|
2363
|
+
const color = resolveColor(value, colors, false);
|
|
2364
|
+
return color ? { fill: color } : null;
|
|
2365
|
+
},
|
|
2366
|
+
// ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
|
|
2367
|
+
// Named presets give cross-platform shadow; arbitrary is web-only.
|
|
2368
|
+
"text-shadow": ({ value, isArbitrary }, { colors }) => {
|
|
2369
|
+
if (value === "none") {
|
|
2370
|
+
return getEffectiveIsWeb() ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
|
|
2280
2371
|
}
|
|
2281
|
-
const
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2372
|
+
const webPresets = {
|
|
2373
|
+
"": "0 2px 4px rgba(0,0,0,0.3)",
|
|
2374
|
+
sm: "0 1px 2px rgba(0,0,0,0.3)",
|
|
2375
|
+
md: "0 4px 6px rgba(0,0,0,0.3)",
|
|
2376
|
+
lg: "0 8px 16px rgba(0,0,0,0.5)",
|
|
2377
|
+
xl: "0 16px 32px rgba(0,0,0,0.5)"
|
|
2378
|
+
};
|
|
2379
|
+
const nativePresets = {
|
|
2380
|
+
"": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
|
|
2381
|
+
sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
|
|
2382
|
+
md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
|
|
2383
|
+
lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
|
|
2384
|
+
xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
|
|
2385
|
+
};
|
|
2386
|
+
if (value in webPresets) {
|
|
2387
|
+
if (getEffectiveIsWeb()) return { textShadow: webPresets[value] };
|
|
2388
|
+
return nativePresets[value] ?? null;
|
|
2285
2389
|
}
|
|
2286
2390
|
if (isArbitrary) {
|
|
2287
|
-
|
|
2288
|
-
if (numMatch) {
|
|
2289
|
-
const unit = numMatch[2] ?? "px";
|
|
2290
|
-
if (onWeb) return { boxShadow: `0 0 0 ${numMatch[1]}${unit} ${DEFAULT_COLOR}` };
|
|
2291
|
-
return unit === "px" ? asNative(parseFloat(numMatch[1]), DEFAULT_COLOR) : null;
|
|
2292
|
-
}
|
|
2293
|
-
return onWeb ? { boxShadow: value.replace(/_/g, " ") } : null;
|
|
2391
|
+
return getEffectiveIsWeb() ? { textShadow: value.replace(/_/g, " ") } : null;
|
|
2294
2392
|
}
|
|
2295
2393
|
const color = resolveColor(value, colors, false);
|
|
2296
2394
|
if (color) {
|
|
2297
|
-
return
|
|
2395
|
+
return getEffectiveIsWeb() ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
|
|
2298
2396
|
}
|
|
2299
2397
|
return null;
|
|
2300
|
-
},
|
|
2301
|
-
// Web-only, unlike `ring` above: this stacks a second box-shadow layer to
|
|
2302
|
-
// create a gap between the element and the ring. There's no native
|
|
2303
|
-
// equivalent to approximate that with (a border can't create a gap outside
|
|
2304
|
-
// its own element without an extra wrapper view), so this stays a no-op
|
|
2305
|
-
// on native rather than rendering a misleading half-translation.
|
|
2306
|
-
"ring-offset": ({ value, isArbitrary }, _theme) => {
|
|
2307
|
-
if (!getEffectiveIsWeb()) return null;
|
|
2308
|
-
const DEFAULT_RING_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
2309
|
-
const DEFAULT_RING_WIDTH = 3;
|
|
2310
|
-
const offsetTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
2311
|
-
let offsetWidth;
|
|
2312
|
-
if (!isArbitrary) {
|
|
2313
|
-
offsetWidth = value in offsetTokens ? offsetTokens[value] : null;
|
|
2314
|
-
} else {
|
|
2315
|
-
offsetWidth = /^-?\d+(\.\d+)?$/.test(value) ? parseFloat(value) : value;
|
|
2316
|
-
}
|
|
2317
|
-
if (offsetWidth === null || typeof offsetWidth === "number" && isNaN(offsetWidth)) return null;
|
|
2318
|
-
const isZero = offsetWidth === 0 || offsetWidth === "0";
|
|
2319
|
-
const offsetCss = typeof offsetWidth === "number" ? `${offsetWidth}px` : offsetWidth;
|
|
2320
|
-
return {
|
|
2321
|
-
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}`
|
|
2322
|
-
};
|
|
2323
|
-
},
|
|
2324
|
-
// ── Space between ─────────────────────────────────────────────────────────
|
|
2325
|
-
// On web: emits __spaceX/__spaceY markers → resolver generates > * + * CSS rules.
|
|
2326
|
-
// On native (RN 0.71+): uses columnGap/rowGap directly.
|
|
2327
|
-
"space-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2328
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2329
|
-
if (v === null) return null;
|
|
2330
|
-
if (getEffectiveIsWeb()) return { __spaceX: v };
|
|
2331
|
-
return { columnGap: v };
|
|
2332
|
-
},
|
|
2333
|
-
"space-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2334
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2335
|
-
if (v === null) return null;
|
|
2336
|
-
if (getEffectiveIsWeb()) return { __spaceY: v };
|
|
2337
|
-
return { rowGap: v };
|
|
2338
2398
|
}
|
|
2339
2399
|
};
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2400
|
+
|
|
2401
|
+
// src/core/utilities.ts
|
|
2402
|
+
var RESOLVERS = {
|
|
2403
|
+
...colorResolvers,
|
|
2404
|
+
...spacingResolvers,
|
|
2405
|
+
...borderResolvers,
|
|
2406
|
+
...layoutResolvers,
|
|
2407
|
+
...typographyResolvers,
|
|
2408
|
+
...filterResolvers,
|
|
2409
|
+
...transformResolvers,
|
|
2410
|
+
...effectResolvers,
|
|
2411
|
+
...miscResolvers
|
|
2412
|
+
};
|
|
2346
2413
|
var NAMED_GROUP_PEER_MARKER_RE = /^(group|peer)\/.+$/;
|
|
2347
2414
|
function resolveUtility(parsed, theme) {
|
|
2348
2415
|
if (!parsed.value) {
|
|
@@ -2390,6 +2457,47 @@ function kbachWarn(message) {
|
|
|
2390
2457
|
);
|
|
2391
2458
|
}
|
|
2392
2459
|
|
|
2460
|
+
// src/core/cache.ts
|
|
2461
|
+
var LRUCache = class {
|
|
2462
|
+
constructor(capacity = 1e4, onEvict) {
|
|
2463
|
+
this.capacity = capacity;
|
|
2464
|
+
if (capacity <= 0) throw new Error("LRUCache: capacity must be a positive integer");
|
|
2465
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
2466
|
+
this.onEvict = onEvict;
|
|
2467
|
+
}
|
|
2468
|
+
get(key) {
|
|
2469
|
+
if (!this.cache.has(key)) return void 0;
|
|
2470
|
+
const value = this.cache.get(key);
|
|
2471
|
+
this.cache.delete(key);
|
|
2472
|
+
this.cache.set(key, value);
|
|
2473
|
+
return value;
|
|
2474
|
+
}
|
|
2475
|
+
set(key, value) {
|
|
2476
|
+
if (this.cache.has(key)) {
|
|
2477
|
+
this.cache.delete(key);
|
|
2478
|
+
} else if (this.cache.size >= this.capacity) {
|
|
2479
|
+
const oldestKey = this.cache.keys().next().value;
|
|
2480
|
+
const oldestValue = this.cache.get(oldestKey);
|
|
2481
|
+
this.cache.delete(oldestKey);
|
|
2482
|
+
this.onEvict?.(oldestKey, oldestValue);
|
|
2483
|
+
}
|
|
2484
|
+
this.cache.set(key, value);
|
|
2485
|
+
return this;
|
|
2486
|
+
}
|
|
2487
|
+
has(key) {
|
|
2488
|
+
return this.cache.has(key);
|
|
2489
|
+
}
|
|
2490
|
+
delete(key) {
|
|
2491
|
+
return this.cache.delete(key);
|
|
2492
|
+
}
|
|
2493
|
+
clear() {
|
|
2494
|
+
this.cache.clear();
|
|
2495
|
+
}
|
|
2496
|
+
get size() {
|
|
2497
|
+
return this.cache.size;
|
|
2498
|
+
}
|
|
2499
|
+
};
|
|
2500
|
+
|
|
2393
2501
|
// src/core/registry.ts
|
|
2394
2502
|
var BUILTIN_MODIFIERS = {
|
|
2395
2503
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -2476,7 +2584,7 @@ function clearPluginModifiers() {
|
|
|
2476
2584
|
_invalidate();
|
|
2477
2585
|
}
|
|
2478
2586
|
var NAMED_GROUP_PEER_RE = /^(group|peer)-(hover|focus)\/(.+)$/;
|
|
2479
|
-
var _namedModifierCache =
|
|
2587
|
+
var _namedModifierCache = new LRUCache(1e4);
|
|
2480
2588
|
function getNamedGroupPeerModifier(name) {
|
|
2481
2589
|
const cached = _namedModifierCache.get(name);
|
|
2482
2590
|
if (cached) return cached;
|
|
@@ -2647,51 +2755,10 @@ function findOuterColon(s) {
|
|
|
2647
2755
|
return -1;
|
|
2648
2756
|
}
|
|
2649
2757
|
|
|
2650
|
-
// src/core/cache.ts
|
|
2651
|
-
var LRUCache = class {
|
|
2652
|
-
constructor(capacity = 1e4, onEvict) {
|
|
2653
|
-
this.capacity = capacity;
|
|
2654
|
-
if (capacity <= 0) throw new Error("LRUCache: capacity must be a positive integer");
|
|
2655
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
2656
|
-
this.onEvict = onEvict;
|
|
2657
|
-
}
|
|
2658
|
-
get(key) {
|
|
2659
|
-
if (!this.cache.has(key)) return void 0;
|
|
2660
|
-
const value = this.cache.get(key);
|
|
2661
|
-
this.cache.delete(key);
|
|
2662
|
-
this.cache.set(key, value);
|
|
2663
|
-
return value;
|
|
2664
|
-
}
|
|
2665
|
-
set(key, value) {
|
|
2666
|
-
if (this.cache.has(key)) {
|
|
2667
|
-
this.cache.delete(key);
|
|
2668
|
-
} else if (this.cache.size >= this.capacity) {
|
|
2669
|
-
const oldestKey = this.cache.keys().next().value;
|
|
2670
|
-
const oldestValue = this.cache.get(oldestKey);
|
|
2671
|
-
this.cache.delete(oldestKey);
|
|
2672
|
-
this.onEvict?.(oldestKey, oldestValue);
|
|
2673
|
-
}
|
|
2674
|
-
this.cache.set(key, value);
|
|
2675
|
-
return this;
|
|
2676
|
-
}
|
|
2677
|
-
has(key) {
|
|
2678
|
-
return this.cache.has(key);
|
|
2679
|
-
}
|
|
2680
|
-
delete(key) {
|
|
2681
|
-
return this.cache.delete(key);
|
|
2682
|
-
}
|
|
2683
|
-
clear() {
|
|
2684
|
-
this.cache.clear();
|
|
2685
|
-
}
|
|
2686
|
-
get size() {
|
|
2687
|
-
return this.cache.size;
|
|
2688
|
-
}
|
|
2689
|
-
};
|
|
2690
|
-
|
|
2691
2758
|
// src/core/resolver.ts
|
|
2692
|
-
var
|
|
2759
|
+
var _defaultFontFamily;
|
|
2693
2760
|
function setDefaultFontFamily(font) {
|
|
2694
|
-
|
|
2761
|
+
_defaultFontFamily = font;
|
|
2695
2762
|
}
|
|
2696
2763
|
var _styleEl = null;
|
|
2697
2764
|
var _ruleIndexByKey = /* @__PURE__ */ new Map();
|
|
@@ -2711,9 +2778,9 @@ function evictInjectedRule(rule) {
|
|
|
2711
2778
|
}
|
|
2712
2779
|
}
|
|
2713
2780
|
var _injectedRules = new LRUCache(5e4, evictInjectedRule);
|
|
2714
|
-
var
|
|
2781
|
+
var _runtimeCSSDisabled = false;
|
|
2715
2782
|
function isRuntimeCSSDisabled() {
|
|
2716
|
-
return
|
|
2783
|
+
return _runtimeCSSDisabled;
|
|
2717
2784
|
}
|
|
2718
2785
|
function getStyleEl() {
|
|
2719
2786
|
if (_styleEl) return _styleEl;
|
|
@@ -2936,14 +3003,7 @@ function deepMerge(base, override) {
|
|
|
2936
3003
|
}
|
|
2937
3004
|
return result;
|
|
2938
3005
|
}
|
|
2939
|
-
var
|
|
2940
|
-
function getConfigStore() {
|
|
2941
|
-
const g = globalThis;
|
|
2942
|
-
if (!g[CONFIG_KEY]) {
|
|
2943
|
-
g[CONFIG_KEY] = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
2944
|
-
}
|
|
2945
|
-
return g[CONFIG_KEY];
|
|
2946
|
-
}
|
|
3006
|
+
var configStore = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
2947
3007
|
function resolveOneRef(ref, colors) {
|
|
2948
3008
|
const lastDash = ref.lastIndexOf("-");
|
|
2949
3009
|
if (lastDash <= 0) return null;
|
|
@@ -3017,8 +3077,7 @@ function buildConfig(userConfig) {
|
|
|
3017
3077
|
clearPluginUtilities();
|
|
3018
3078
|
clearPluginModifiers();
|
|
3019
3079
|
}
|
|
3020
|
-
const
|
|
3021
|
-
for (const k of Object.keys(_store.customVariants)) delete _store.customVariants[k];
|
|
3080
|
+
for (const k of Object.keys(configStore.customVariants)) delete configStore.customVariants[k];
|
|
3022
3081
|
const pluginAPI = makePluginAPI(resolved.theme);
|
|
3023
3082
|
for (const plugin of resolved.plugins) {
|
|
3024
3083
|
plugin(pluginAPI);
|
|
@@ -3065,26 +3124,7 @@ function makePluginAPI(theme) {
|
|
|
3065
3124
|
}
|
|
3066
3125
|
};
|
|
3067
3126
|
}
|
|
3068
|
-
var customVariants =
|
|
3069
|
-
{},
|
|
3070
|
-
{
|
|
3071
|
-
get(_t, p) {
|
|
3072
|
-
return typeof p === "string" ? getConfigStore().customVariants[p] : void 0;
|
|
3073
|
-
},
|
|
3074
|
-
set(_t, p, v) {
|
|
3075
|
-
if (typeof p === "string") getConfigStore().customVariants[p] = v;
|
|
3076
|
-
return true;
|
|
3077
|
-
},
|
|
3078
|
-
ownKeys() {
|
|
3079
|
-
return Object.keys(getConfigStore().customVariants);
|
|
3080
|
-
},
|
|
3081
|
-
getOwnPropertyDescriptor(_t, p) {
|
|
3082
|
-
if (typeof p !== "string") return void 0;
|
|
3083
|
-
const v = getConfigStore().customVariants[p];
|
|
3084
|
-
return v !== void 0 ? { value: v, writable: true, enumerable: true, configurable: true } : void 0;
|
|
3085
|
-
}
|
|
3086
|
-
}
|
|
3087
|
-
);
|
|
3127
|
+
var customVariants = configStore.customVariants;
|
|
3088
3128
|
|
|
3089
3129
|
// src/vite-plugin.ts
|
|
3090
3130
|
var process2 = import_node_process.default;
|
|
@@ -3444,7 +3484,9 @@ function pushTokens(str, into) {
|
|
|
3444
3484
|
if (tok && !NOT_A_CLASS_NAME_RE.test(tok)) into.add(tok);
|
|
3445
3485
|
}
|
|
3446
3486
|
}
|
|
3447
|
-
|
|
3487
|
+
var MAX_SCAN_DEPTH = 10;
|
|
3488
|
+
function scanDir(dir, onFile, depth = 0) {
|
|
3489
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
3448
3490
|
let entries;
|
|
3449
3491
|
try {
|
|
3450
3492
|
entries = (0, import_fs.readdirSync)(dir);
|
|
@@ -3459,7 +3501,7 @@ function scanDir(dir, onFile) {
|
|
|
3459
3501
|
const full = (0, import_path.join)(dir, entry);
|
|
3460
3502
|
try {
|
|
3461
3503
|
const st = (0, import_fs.statSync)(full);
|
|
3462
|
-
if (st.isDirectory()) scanDir(full, onFile);
|
|
3504
|
+
if (st.isDirectory()) scanDir(full, onFile, depth + 1);
|
|
3463
3505
|
else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, (0, import_fs.readFileSync)(full, "utf-8"));
|
|
3464
3506
|
} catch (err) {
|
|
3465
3507
|
warn(`Can't process ${full}: ${err.message}`);
|
|
@@ -3477,7 +3519,8 @@ function scanCssFileInto(filePath, into) {
|
|
|
3477
3519
|
} catch {
|
|
3478
3520
|
}
|
|
3479
3521
|
}
|
|
3480
|
-
function scanCssSelectorsInto(dir, into) {
|
|
3522
|
+
function scanCssSelectorsInto(dir, into, depth = 0) {
|
|
3523
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
3481
3524
|
let entries;
|
|
3482
3525
|
try {
|
|
3483
3526
|
entries = (0, import_fs.readdirSync)(dir);
|
|
@@ -3489,7 +3532,7 @@ function scanCssSelectorsInto(dir, into) {
|
|
|
3489
3532
|
const full = (0, import_path.join)(dir, entry);
|
|
3490
3533
|
try {
|
|
3491
3534
|
const st = (0, import_fs.statSync)(full);
|
|
3492
|
-
if (st.isDirectory()) scanCssSelectorsInto(full, into);
|
|
3535
|
+
if (st.isDirectory()) scanCssSelectorsInto(full, into, depth + 1);
|
|
3493
3536
|
else if (CSS_FILE_RE.test(entry)) scanCssFileInto(full, into);
|
|
3494
3537
|
} catch {
|
|
3495
3538
|
}
|
|
@@ -3556,6 +3599,17 @@ function kbach(userConfigOrOptions) {
|
|
|
3556
3599
|
function generateCSS() {
|
|
3557
3600
|
return formatKbachCSS(buildTokenCSSView(), cfg.theme, responsiveRe);
|
|
3558
3601
|
}
|
|
3602
|
+
function syncMainCSSFile(server) {
|
|
3603
|
+
const active = /* @__PURE__ */ new Set();
|
|
3604
|
+
for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
|
|
3605
|
+
for (const tok of tokenCSS.keys()) {
|
|
3606
|
+
if (!active.has(tok)) tokenCSS.delete(tok);
|
|
3607
|
+
}
|
|
3608
|
+
if (mainCSSFile) {
|
|
3609
|
+
const changed = writeKbachToFile(mainCSSFile, generateCSS());
|
|
3610
|
+
if (changed) server.watcher.emit("change", mainCSSFile);
|
|
3611
|
+
}
|
|
3612
|
+
}
|
|
3559
3613
|
return {
|
|
3560
3614
|
name: "kbach",
|
|
3561
3615
|
enforce: "pre",
|
|
@@ -3615,6 +3669,37 @@ ${code}`,
|
|
|
3615
3669
|
initialScan();
|
|
3616
3670
|
if (mainCSSFile) writeKbachToFile(mainCSSFile, generateCSS());
|
|
3617
3671
|
},
|
|
3672
|
+
// Vite's `handleHotUpdate` hook only fires for `type === "update"` (plain
|
|
3673
|
+
// file edits) — it's never called for file create/delete, which land on
|
|
3674
|
+
// the watcher's own 'add'/'unlink' events instead (confirmed against
|
|
3675
|
+
// vite's own onHMRUpdate/handleHMRUpdate: the hook loop is gated on
|
|
3676
|
+
// `type === "update"`). Without also listening on those two events here,
|
|
3677
|
+
// creating a new file with new Kbach classes never adds them to
|
|
3678
|
+
// kbach.css, and deleting a file never removes its classes, until a full
|
|
3679
|
+
// dev-server restart. configureServer gives access to the raw watcher so
|
|
3680
|
+
// both cases can share the same sync logic as a plain edit.
|
|
3681
|
+
configureServer(server) {
|
|
3682
|
+
const onAddOrUnlink = (file, isUnlink) => {
|
|
3683
|
+
if (file.includes("node_modules")) return;
|
|
3684
|
+
if (CSS_FILE_RE.test(file)) {
|
|
3685
|
+
if (!isUnlink) scanCssFileInto(file, projectCssClasses);
|
|
3686
|
+
return;
|
|
3687
|
+
}
|
|
3688
|
+
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
3689
|
+
if (isUnlink) {
|
|
3690
|
+
fileTokens.delete(normPath(file));
|
|
3691
|
+
} else {
|
|
3692
|
+
try {
|
|
3693
|
+
processFile(file, (0, import_fs.readFileSync)(file, "utf-8"));
|
|
3694
|
+
} catch {
|
|
3695
|
+
fileTokens.delete(normPath(file));
|
|
3696
|
+
}
|
|
3697
|
+
}
|
|
3698
|
+
syncMainCSSFile(server);
|
|
3699
|
+
};
|
|
3700
|
+
server.watcher.on("add", (file) => onAddOrUnlink(file, false));
|
|
3701
|
+
server.watcher.on("unlink", (file) => onAddOrUnlink(file, true));
|
|
3702
|
+
},
|
|
3618
3703
|
handleHotUpdate({ file, server }) {
|
|
3619
3704
|
if (file.includes("node_modules")) return;
|
|
3620
3705
|
if (CSS_FILE_RE.test(file)) {
|
|
@@ -3627,15 +3712,7 @@ ${code}`,
|
|
|
3627
3712
|
} catch {
|
|
3628
3713
|
fileTokens.delete(normPath(file));
|
|
3629
3714
|
}
|
|
3630
|
-
|
|
3631
|
-
for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
|
|
3632
|
-
for (const tok of tokenCSS.keys()) {
|
|
3633
|
-
if (!active.has(tok)) tokenCSS.delete(tok);
|
|
3634
|
-
}
|
|
3635
|
-
if (mainCSSFile) {
|
|
3636
|
-
const changed = writeKbachToFile(mainCSSFile, generateCSS());
|
|
3637
|
-
if (changed) server.watcher.emit("change", mainCSSFile);
|
|
3638
|
-
}
|
|
3715
|
+
syncMainCSSFile(server);
|
|
3639
3716
|
}
|
|
3640
3717
|
};
|
|
3641
3718
|
}
|