@kbach/react 0.6.24 → 0.6.26
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-GJSZUC6Q.mjs → chunk-AKX6I7WP.mjs} +1303 -1297
- package/dist/{chunk-YUX2JPTM.mjs → chunk-NWQIZZCW.mjs} +6 -2
- package/dist/core/index.d.ts +1274 -0
- package/dist/core/index.js +3457 -0
- package/dist/index.d.ts +50 -224
- package/dist/index.js +215 -3443
- 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 +1348 -1292
- package/dist/vite-plugin.mjs +1348 -1292
- package/kbach-react.md +15 -1
- package/package.json +4 -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.mjs
CHANGED
|
@@ -615,14 +615,16 @@ var defaultTheme = {
|
|
|
615
615
|
animation: {}
|
|
616
616
|
};
|
|
617
617
|
|
|
618
|
-
// src/core/
|
|
618
|
+
// src/core/resolvers/color.ts
|
|
619
619
|
function resolveColor(value, colors, isArbitrary) {
|
|
620
620
|
if (isArbitrary) return value;
|
|
621
621
|
const slashIdx = value.indexOf("/");
|
|
622
622
|
const colorPart = slashIdx > 0 ? value.slice(0, slashIdx) : value;
|
|
623
623
|
const opacityPart = slashIdx > 0 ? value.slice(slashIdx + 1) : null;
|
|
624
624
|
let hex = null;
|
|
625
|
-
if (colorPart
|
|
625
|
+
if (colorPart.startsWith("[") && colorPart.endsWith("]")) {
|
|
626
|
+
hex = colorPart.slice(1, -1);
|
|
627
|
+
} else if (colorPart in colors) {
|
|
626
628
|
const entry = colors[colorPart];
|
|
627
629
|
if (typeof entry === "string") hex = entry;
|
|
628
630
|
else if (typeof entry === "object" && "6" in entry) hex = entry["6"];
|
|
@@ -687,6 +689,86 @@ function withOpacityVar(color, varName) {
|
|
|
687
689
|
const [r, g, b] = rgb;
|
|
688
690
|
return `rgba(${r},${g},${b},var(${varName},1))`;
|
|
689
691
|
}
|
|
692
|
+
var colorResolvers = {
|
|
693
|
+
// ── Background ─────────────────────────────────────────────────────────────
|
|
694
|
+
bg: ({ value, isArbitrary }, { colors }) => {
|
|
695
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
696
|
+
if (!color) return null;
|
|
697
|
+
return { backgroundColor: getEffectiveIsWeb() ? withOpacityVar(color, "--bg-opacity") : color };
|
|
698
|
+
},
|
|
699
|
+
"bg-opacity": ({ value, isArbitrary }, _) => {
|
|
700
|
+
if (!getEffectiveIsWeb()) return null;
|
|
701
|
+
const n = parseFloat(value);
|
|
702
|
+
if (isNaN(n)) return null;
|
|
703
|
+
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
704
|
+
return { "--bg-opacity": v };
|
|
705
|
+
},
|
|
706
|
+
// ── Background gradient (CSS variable gradient stops, web-only) ──────────
|
|
707
|
+
"bg-gradient-to": ({ value }) => {
|
|
708
|
+
if (!getEffectiveIsWeb()) return null;
|
|
709
|
+
const directions = {
|
|
710
|
+
t: "to top",
|
|
711
|
+
tr: "to top right",
|
|
712
|
+
r: "to right",
|
|
713
|
+
br: "to bottom right",
|
|
714
|
+
b: "to bottom",
|
|
715
|
+
bl: "to bottom left",
|
|
716
|
+
l: "to left",
|
|
717
|
+
tl: "to top left"
|
|
718
|
+
};
|
|
719
|
+
const dir = directions[value];
|
|
720
|
+
if (!dir) return null;
|
|
721
|
+
return {
|
|
722
|
+
backgroundImage: `linear-gradient(${dir}, var(--kb-gradient-from, transparent), var(--kb-gradient-stops, transparent))`
|
|
723
|
+
};
|
|
724
|
+
},
|
|
725
|
+
from: ({ value, isArbitrary }, { colors }) => {
|
|
726
|
+
if (!getEffectiveIsWeb()) return null;
|
|
727
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
728
|
+
if (!color) return null;
|
|
729
|
+
return {
|
|
730
|
+
"--kb-gradient-from": color,
|
|
731
|
+
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-to, transparent)`
|
|
732
|
+
};
|
|
733
|
+
},
|
|
734
|
+
via: ({ value, isArbitrary }, { colors }) => {
|
|
735
|
+
if (!getEffectiveIsWeb()) return null;
|
|
736
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
737
|
+
if (!color) return null;
|
|
738
|
+
return {
|
|
739
|
+
"--kb-gradient-via": color,
|
|
740
|
+
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-via), var(--kb-gradient-to, transparent)`
|
|
741
|
+
};
|
|
742
|
+
},
|
|
743
|
+
to: ({ value, isArbitrary }, { colors }) => {
|
|
744
|
+
if (!getEffectiveIsWeb()) return null;
|
|
745
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
746
|
+
if (!color) return null;
|
|
747
|
+
return { "--kb-gradient-to": color };
|
|
748
|
+
},
|
|
749
|
+
// ── Tint color (native-only, for Image and icon components) ──────────────
|
|
750
|
+
tint: ({ value, isArbitrary }, { colors }) => {
|
|
751
|
+
if (getEffectiveIsWeb()) return null;
|
|
752
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
753
|
+
return color ? { tintColor: color } : null;
|
|
754
|
+
},
|
|
755
|
+
// ── Caret color (web-only) ────────────────────────────────────────────────
|
|
756
|
+
caret: ({ value, isArbitrary }, { colors }) => {
|
|
757
|
+
if (!getEffectiveIsWeb()) return null;
|
|
758
|
+
if (value === "auto" || value === "transparent") return { caretColor: value };
|
|
759
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
760
|
+
return color ? { caretColor: color } : null;
|
|
761
|
+
},
|
|
762
|
+
// ── Accent color (web-only) ───────────────────────────────────────────────
|
|
763
|
+
accent: ({ value, isArbitrary }, { colors }) => {
|
|
764
|
+
if (!getEffectiveIsWeb()) return null;
|
|
765
|
+
if (value === "auto") return { accentColor: "auto" };
|
|
766
|
+
const color = resolveColor(value, colors, isArbitrary);
|
|
767
|
+
return color ? { accentColor: color } : null;
|
|
768
|
+
}
|
|
769
|
+
};
|
|
770
|
+
|
|
771
|
+
// src/core/resolvers/spacing.ts
|
|
690
772
|
function resolveSpacing(value, negative, spacing, isArbitrary) {
|
|
691
773
|
if (isArbitrary) {
|
|
692
774
|
const resolved = getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
@@ -719,516 +801,174 @@ function resolveSizing(value, spacing, isArbitrary) {
|
|
|
719
801
|
}
|
|
720
802
|
return null;
|
|
721
803
|
}
|
|
804
|
+
function makeSpacingResolver(prop) {
|
|
805
|
+
return ({ value, negative, isArbitrary }, { spacing }) => {
|
|
806
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
807
|
+
return v !== null ? { [prop]: v } : null;
|
|
808
|
+
};
|
|
809
|
+
}
|
|
810
|
+
var PADDING_MARGIN_PROPS = {
|
|
811
|
+
p: "padding",
|
|
812
|
+
px: "paddingHorizontal",
|
|
813
|
+
py: "paddingVertical",
|
|
814
|
+
pt: "paddingTop",
|
|
815
|
+
pr: "paddingRight",
|
|
816
|
+
pb: "paddingBottom",
|
|
817
|
+
pl: "paddingLeft",
|
|
818
|
+
m: "margin",
|
|
819
|
+
mx: "marginHorizontal",
|
|
820
|
+
my: "marginVertical",
|
|
821
|
+
mt: "marginTop",
|
|
822
|
+
mr: "marginRight",
|
|
823
|
+
mb: "marginBottom",
|
|
824
|
+
ml: "marginLeft"
|
|
825
|
+
};
|
|
826
|
+
var spacingResolvers = {
|
|
827
|
+
// ── Sizing ─────────────────────────────────────────────────────────────────
|
|
828
|
+
w: ({ value, isArbitrary }, { spacing }) => {
|
|
829
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
830
|
+
return v !== null ? { width: v } : null;
|
|
831
|
+
},
|
|
832
|
+
h: ({ value, isArbitrary }, { spacing }) => {
|
|
833
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
834
|
+
return v !== null ? { height: v } : null;
|
|
835
|
+
},
|
|
836
|
+
"min-w": ({ value, isArbitrary }, { spacing }) => {
|
|
837
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
838
|
+
return v !== null ? { minWidth: v } : null;
|
|
839
|
+
},
|
|
840
|
+
"min-h": ({ value, isArbitrary }, { spacing }) => {
|
|
841
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
842
|
+
return v !== null ? { minHeight: v } : null;
|
|
843
|
+
},
|
|
844
|
+
"max-w": ({ value, isArbitrary }, { spacing }) => {
|
|
845
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
846
|
+
return v !== null ? { maxWidth: v } : null;
|
|
847
|
+
},
|
|
848
|
+
"max-h": ({ value, isArbitrary }, { spacing }) => {
|
|
849
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
850
|
+
return v !== null ? { maxHeight: v } : null;
|
|
851
|
+
},
|
|
852
|
+
// ── Size shorthand (sets width AND height in one utility) ────────────────
|
|
853
|
+
size: ({ value, isArbitrary }, { spacing }) => {
|
|
854
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
855
|
+
return v !== null ? { width: v, height: v } : null;
|
|
856
|
+
},
|
|
857
|
+
// ── Flex basis ─────────────────────────────────────────────────────────────
|
|
858
|
+
basis: ({ value, isArbitrary }, { spacing }) => {
|
|
859
|
+
const v = resolveSizing(value, spacing, isArbitrary);
|
|
860
|
+
return v !== null ? { flexBasis: v } : null;
|
|
861
|
+
},
|
|
862
|
+
// ── Gap ────────────────────────────────────────────────────────────────────
|
|
863
|
+
gap: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
864
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
865
|
+
return v !== null ? { gap: v } : null;
|
|
866
|
+
},
|
|
867
|
+
"gap-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
868
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
869
|
+
return v !== null ? { columnGap: v } : null;
|
|
870
|
+
},
|
|
871
|
+
"gap-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
872
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
873
|
+
return v !== null ? { rowGap: v } : null;
|
|
874
|
+
},
|
|
875
|
+
// ── Position ───────────────────────────────────────────────────────────────
|
|
876
|
+
top: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
877
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
878
|
+
return v !== null ? { top: v } : null;
|
|
879
|
+
},
|
|
880
|
+
right: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
881
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
882
|
+
return v !== null ? { right: v } : null;
|
|
883
|
+
},
|
|
884
|
+
bottom: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
885
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
886
|
+
return v !== null ? { bottom: v } : null;
|
|
887
|
+
},
|
|
888
|
+
left: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
889
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
890
|
+
return v !== null ? { left: v } : null;
|
|
891
|
+
},
|
|
892
|
+
inset: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
893
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
894
|
+
return v !== null ? { top: v, right: v, bottom: v, left: v } : null;
|
|
895
|
+
},
|
|
896
|
+
"inset-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
897
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
898
|
+
return v !== null ? { left: v, right: v } : null;
|
|
899
|
+
},
|
|
900
|
+
"inset-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
901
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
902
|
+
return v !== null ? { top: v, bottom: v } : null;
|
|
903
|
+
},
|
|
904
|
+
// ── Translate ──────────────────────────────────────────────────────────────
|
|
905
|
+
"translate-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
906
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
907
|
+
if (v === null) return null;
|
|
908
|
+
if (getEffectiveIsWeb()) return { transform: `translateX(${typeof v === "number" ? `${v}px` : v})` };
|
|
909
|
+
if (typeof v === "string") {
|
|
910
|
+
const n = parseFloat(v);
|
|
911
|
+
return isNaN(n) ? null : { transform: [{ translateX: n }] };
|
|
912
|
+
}
|
|
913
|
+
return { transform: [{ translateX: v }] };
|
|
914
|
+
},
|
|
915
|
+
"translate-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
916
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
917
|
+
if (v === null) return null;
|
|
918
|
+
if (getEffectiveIsWeb()) return { transform: `translateY(${typeof v === "number" ? `${v}px` : v})` };
|
|
919
|
+
if (typeof v === "string") {
|
|
920
|
+
const n = parseFloat(v);
|
|
921
|
+
return isNaN(n) ? null : { transform: [{ translateY: n }] };
|
|
922
|
+
}
|
|
923
|
+
return { transform: [{ translateY: v }] };
|
|
924
|
+
},
|
|
925
|
+
// ── Space between ─────────────────────────────────────────────────────────
|
|
926
|
+
// On web: emits __spaceX/__spaceY markers → resolver generates > * + * CSS rules.
|
|
927
|
+
// On native (RN 0.71+): uses columnGap/rowGap directly.
|
|
928
|
+
"space-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
929
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
930
|
+
if (v === null) return null;
|
|
931
|
+
if (getEffectiveIsWeb()) return { __spaceX: v };
|
|
932
|
+
return { columnGap: v };
|
|
933
|
+
},
|
|
934
|
+
"space-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
935
|
+
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
936
|
+
if (v === null) return null;
|
|
937
|
+
if (getEffectiveIsWeb()) return { __spaceY: v };
|
|
938
|
+
return { rowGap: v };
|
|
939
|
+
}
|
|
940
|
+
};
|
|
941
|
+
for (const [utility, prop] of Object.entries(PADDING_MARGIN_PROPS)) {
|
|
942
|
+
spacingResolvers[utility] = makeSpacingResolver(prop);
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// src/core/resolvers/border.ts
|
|
722
946
|
function resolveRadius(value, radii, isArbitrary) {
|
|
723
947
|
if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
724
948
|
const key = value === "" ? "DEFAULT" : value;
|
|
725
949
|
return radii[key] ?? null;
|
|
726
950
|
}
|
|
727
|
-
function
|
|
728
|
-
|
|
729
|
-
|
|
951
|
+
function makeBorderSideResolver(widthProp, colorProp) {
|
|
952
|
+
return ({ value, isArbitrary }, { colors, borderWidth }) => {
|
|
953
|
+
if (!value) return { [widthProp]: 1 };
|
|
954
|
+
if (isArbitrary) {
|
|
955
|
+
const w2 = toNativeValue(value);
|
|
956
|
+
if (typeof w2 === "number") return { [widthProp]: w2 };
|
|
957
|
+
return { [colorProp]: value };
|
|
958
|
+
}
|
|
959
|
+
const color = resolveColor(value, colors, false);
|
|
960
|
+
if (color) return { [colorProp]: color };
|
|
961
|
+
const w = borderWidth[value];
|
|
962
|
+
return w !== void 0 ? { [widthProp]: w } : null;
|
|
963
|
+
};
|
|
730
964
|
}
|
|
731
|
-
var
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
// React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
|
|
739
|
-
// a no-op normally, but is needed to re-show an element that was hidden via `hidden`.
|
|
740
|
-
// `grid`, `contents`, `flow-root` have no native equivalent and stay null there.
|
|
741
|
-
// The inline-* family (inline, inline-block, inline-flex, inline-grid) falls back
|
|
742
|
-
// to 'flex' on native instead — like plain `flex`, this is a no-op most of the
|
|
743
|
-
// time, but without it these utilities couldn't re-show a `hidden` element on
|
|
744
|
-
// native either (null → no style applied → still display:'none').
|
|
745
|
-
flex: { display: "flex" },
|
|
746
|
-
block: web ? { display: "block" } : null,
|
|
747
|
-
"inline-block": { display: web ? "inline-block" : "flex" },
|
|
748
|
-
inline: { display: web ? "inline" : "flex" },
|
|
749
|
-
grid: web ? { display: "grid" } : null,
|
|
750
|
-
grd: web ? { display: "grid" } : null,
|
|
751
|
-
"inline-flex": { display: web ? "inline-flex" : "flex" },
|
|
752
|
-
"inline-grid": { display: web ? "inline-grid" : "flex" },
|
|
753
|
-
hidden: { display: "none" },
|
|
754
|
-
contents: web ? { display: "contents" } : null,
|
|
755
|
-
"flow-root": web ? { display: "flow-root" } : null,
|
|
756
|
-
// Flex direction (both web and native)
|
|
757
|
-
"flex-row": { flexDirection: "row" },
|
|
758
|
-
"flex-col": { flexDirection: "column" },
|
|
759
|
-
"flex-row-reverse": { flexDirection: "row-reverse" },
|
|
760
|
-
"flex-col-reverse": { flexDirection: "column-reverse" },
|
|
761
|
-
// Flex wrap (both)
|
|
762
|
-
"flex-wrap": { flexWrap: "wrap" },
|
|
763
|
-
"flex-wrap-reverse": { flexWrap: "wrap-reverse" },
|
|
764
|
-
"flex-nowrap": { flexWrap: "nowrap" },
|
|
765
|
-
// Flex grow / shrink (both)
|
|
766
|
-
"flex-grow": { flexGrow: 1 },
|
|
767
|
-
"flex-grow-0": { flexGrow: 0 },
|
|
768
|
-
"flex-shrink": { flexShrink: 1 },
|
|
769
|
-
"flex-shrink-0": { flexShrink: 0 },
|
|
770
|
-
// Align items (both)
|
|
771
|
-
"items-start": { alignItems: "flex-start" },
|
|
772
|
-
"items-end": { alignItems: "flex-end" },
|
|
773
|
-
"items-center": { alignItems: "center" },
|
|
774
|
-
"items-baseline": { alignItems: "baseline" },
|
|
775
|
-
"items-stretch": { alignItems: "stretch" },
|
|
776
|
-
// Justify content (both)
|
|
777
|
-
"justify-start": { justifyContent: "flex-start" },
|
|
778
|
-
"justify-end": { justifyContent: "flex-end" },
|
|
779
|
-
"justify-center": { justifyContent: "center" },
|
|
780
|
-
"justify-between": { justifyContent: "space-between" },
|
|
781
|
-
"justify-around": { justifyContent: "space-around" },
|
|
782
|
-
"justify-evenly": { justifyContent: "space-evenly" },
|
|
783
|
-
// Align content (both)
|
|
784
|
-
"content-start": { alignContent: "flex-start" },
|
|
785
|
-
"content-end": { alignContent: "flex-end" },
|
|
786
|
-
"content-center": { alignContent: "center" },
|
|
787
|
-
"content-between": { alignContent: "space-between" },
|
|
788
|
-
"content-around": { alignContent: "space-around" },
|
|
789
|
-
"content-evenly": { alignContent: "space-evenly" },
|
|
790
|
-
"content-stretch": { alignContent: "stretch" },
|
|
791
|
-
// Align self (both)
|
|
792
|
-
"self-auto": { alignSelf: "auto" },
|
|
793
|
-
"self-start": { alignSelf: "flex-start" },
|
|
794
|
-
"self-end": { alignSelf: "flex-end" },
|
|
795
|
-
"self-center": { alignSelf: "center" },
|
|
796
|
-
"self-stretch": { alignSelf: "stretch" },
|
|
797
|
-
"self-baseline": { alignSelf: "baseline" },
|
|
798
|
-
// Text align (both)
|
|
799
|
-
"text-left": { textAlign: "left" },
|
|
800
|
-
"text-right": { textAlign: "right" },
|
|
801
|
-
"text-center": { textAlign: "center" },
|
|
802
|
-
"text-justify": { textAlign: "justify" },
|
|
803
|
-
// Font weight shortcuts (both)
|
|
804
|
-
"font-thin": { fontWeight: "100" },
|
|
805
|
-
"font-extralight": { fontWeight: "200" },
|
|
806
|
-
"font-light": { fontWeight: "300" },
|
|
807
|
-
"font-normal": { fontWeight: "400" },
|
|
808
|
-
"font-medium": { fontWeight: "500" },
|
|
809
|
-
"font-semibold": { fontWeight: "600" },
|
|
810
|
-
"font-bold": { fontWeight: "700" },
|
|
811
|
-
"font-extrabold": { fontWeight: "800" },
|
|
812
|
-
"font-black": { fontWeight: "900" },
|
|
813
|
-
// Text decoration (overline is web-only)
|
|
814
|
-
underline: { textDecorationLine: "underline" },
|
|
815
|
-
overline: web ? { textDecorationLine: "overline" } : null,
|
|
816
|
-
"line-through": { textDecorationLine: "line-through" },
|
|
817
|
-
"no-underline": { textDecorationLine: "none" },
|
|
818
|
-
// Text transform (both)
|
|
819
|
-
uppercase: { textTransform: "uppercase" },
|
|
820
|
-
lowercase: { textTransform: "lowercase" },
|
|
821
|
-
capitalize: { textTransform: "capitalize" },
|
|
822
|
-
"normal-case": { textTransform: "none" },
|
|
823
|
-
// Font style (both)
|
|
824
|
-
italic: { fontStyle: "italic" },
|
|
825
|
-
"non-italic": { fontStyle: "normal" },
|
|
826
|
-
// Position (fixed/sticky/static are web-only; RN only supports relative/absolute)
|
|
827
|
-
relative: { position: "relative" },
|
|
828
|
-
absolute: { position: "absolute" },
|
|
829
|
-
fixed: web ? { position: "fixed" } : null,
|
|
830
|
-
sticky: web ? { position: "sticky" } : null,
|
|
831
|
-
static: web ? { position: "static" } : null,
|
|
832
|
-
// Visibility (no `visibility` prop on native; use opacity instead)
|
|
833
|
-
visible: web ? { visibility: "visible" } : null,
|
|
834
|
-
invisible: web ? { visibility: "hidden" } : { opacity: 0 },
|
|
835
|
-
// Overflow (RN supports 'hidden' | 'visible' | 'scroll'; not 'auto')
|
|
836
|
-
"overflow-hidden": { overflow: "hidden" },
|
|
837
|
-
"overflow-visible": { overflow: "visible" },
|
|
838
|
-
"overflow-scroll": { overflow: "scroll" },
|
|
839
|
-
"overflow-auto": web ? { overflow: "auto" } : { overflow: "scroll" },
|
|
840
|
-
// overflowX / overflowY are web-only
|
|
841
|
-
"overflow-x-hidden": web ? { overflowX: "hidden" } : null,
|
|
842
|
-
"overflow-x-scroll": web ? { overflowX: "scroll" } : null,
|
|
843
|
-
"overflow-x-auto": web ? { overflowX: "auto" } : null,
|
|
844
|
-
"overflow-y-hidden": web ? { overflowY: "hidden" } : null,
|
|
845
|
-
"overflow-y-scroll": web ? { overflowY: "scroll" } : null,
|
|
846
|
-
"overflow-y-auto": web ? { overflowY: "auto" } : null,
|
|
847
|
-
// Object fit (web-only; use resizeMode prop on RN Image)
|
|
848
|
-
"object-contain": web ? { objectFit: "contain" } : null,
|
|
849
|
-
"object-cover": web ? { objectFit: "cover" } : null,
|
|
850
|
-
"object-fill": web ? { objectFit: "fill" } : null,
|
|
851
|
-
"object-none": web ? { objectFit: "none" } : null,
|
|
852
|
-
"object-scale-down": web ? { objectFit: "scale-down" } : null,
|
|
853
|
-
// Border style (both)
|
|
854
|
-
"border-solid": { borderStyle: "solid" },
|
|
855
|
-
"border-dashed": { borderStyle: "dashed" },
|
|
856
|
-
"border-dotted": { borderStyle: "dotted" },
|
|
857
|
-
"border-none": { borderWidth: 0 },
|
|
858
|
-
// Border sides default width (both)
|
|
859
|
-
"border-t": { borderTopWidth: 1 },
|
|
860
|
-
"border-r": { borderRightWidth: 1 },
|
|
861
|
-
"border-b": { borderBottomWidth: 1 },
|
|
862
|
-
"border-l": { borderLeftWidth: 1 },
|
|
863
|
-
// Cursor (web-only)
|
|
864
|
-
"cursor-auto": web ? { cursor: "auto" } : null,
|
|
865
|
-
"cursor-default": web ? { cursor: "default" } : null,
|
|
866
|
-
"cursor-pointer": web ? { cursor: "pointer" } : null,
|
|
867
|
-
"cursor-wait": web ? { cursor: "wait" } : null,
|
|
868
|
-
"cursor-text": web ? { cursor: "text" } : null,
|
|
869
|
-
"cursor-move": web ? { cursor: "move" } : null,
|
|
870
|
-
"cursor-not-allowed": web ? { cursor: "not-allowed" } : null,
|
|
871
|
-
// User select (web-only)
|
|
872
|
-
"select-none": web ? { userSelect: "none" } : null,
|
|
873
|
-
"select-text": web ? { userSelect: "text" } : null,
|
|
874
|
-
"select-all": web ? { userSelect: "all" } : null,
|
|
875
|
-
"select-auto": web ? { userSelect: "auto" } : null,
|
|
876
|
-
// Pointer events (both)
|
|
877
|
-
"pointer-events-none": { pointerEvents: "none" },
|
|
878
|
-
"pointer-events-auto": { pointerEvents: "auto" },
|
|
879
|
-
// Whitespace (web-only; RN Text uses numberOfLines prop instead)
|
|
880
|
-
"whitespace-normal": web ? { whiteSpace: "normal" } : null,
|
|
881
|
-
"whitespace-nowrap": web ? { whiteSpace: "nowrap" } : null,
|
|
882
|
-
"whitespace-pre": web ? { whiteSpace: "pre" } : null,
|
|
883
|
-
"whitespace-pre-wrap": web ? { whiteSpace: "pre-wrap" } : null,
|
|
884
|
-
"whitespace-pre-line": web ? { whiteSpace: "pre-line" } : null,
|
|
885
|
-
// Word break (web-only)
|
|
886
|
-
"break-normal": web ? { overflowWrap: "normal", wordBreak: "normal" } : null,
|
|
887
|
-
"break-words": web ? { overflowWrap: "break-word" } : null,
|
|
888
|
-
"break-all": web ? { wordBreak: "break-all" } : null,
|
|
889
|
-
// Misc web-only
|
|
890
|
-
truncate: web ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null,
|
|
891
|
-
"box-border": web ? { boxSizing: "border-box" } : null,
|
|
892
|
-
"box-content": web ? { boxSizing: "content-box" } : null,
|
|
893
|
-
"appearance-none": web ? { appearance: "none" } : null,
|
|
894
|
-
"outline-none": web ? { outline: "none", outlineOffset: "0" } : null,
|
|
895
|
-
outline: web ? { outline: "2px solid transparent", outlineOffset: "2px" } : null,
|
|
896
|
-
resize: web ? { resize: "both" } : null,
|
|
897
|
-
"resize-none": web ? { resize: "none" } : null,
|
|
898
|
-
"resize-y": web ? { resize: "vertical" } : null,
|
|
899
|
-
"resize-x": web ? { resize: "horizontal" } : null,
|
|
900
|
-
antialiased: web ? { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale" } : null,
|
|
901
|
-
"subpixel-antialiased": web ? { WebkitFontSmoothing: "subpixel-antialiased", MozOsxFontSmoothing: "auto" } : null,
|
|
902
|
-
"overflow-ellipsis": web ? { textOverflow: "ellipsis" } : null,
|
|
903
|
-
"sr-only": web ? {
|
|
904
|
-
position: "absolute",
|
|
905
|
-
width: 1,
|
|
906
|
-
height: 1,
|
|
907
|
-
padding: 0,
|
|
908
|
-
margin: -1,
|
|
909
|
-
overflow: "hidden",
|
|
910
|
-
clip: "rect(0,0,0,0)",
|
|
911
|
-
whiteSpace: "nowrap",
|
|
912
|
-
border: 0
|
|
913
|
-
} : null,
|
|
914
|
-
"not-sr-only": web ? {
|
|
915
|
-
position: "static",
|
|
916
|
-
width: "auto",
|
|
917
|
-
height: "auto",
|
|
918
|
-
padding: 0,
|
|
919
|
-
margin: 0,
|
|
920
|
-
overflow: "visible",
|
|
921
|
-
clip: "auto",
|
|
922
|
-
whiteSpace: "normal"
|
|
923
|
-
} : null,
|
|
924
|
-
// Lists (web-only)
|
|
925
|
-
"list-none": web ? { listStyleType: "none" } : null,
|
|
926
|
-
"list-disc": web ? { listStyleType: "disc" } : null,
|
|
927
|
-
"list-decimal": web ? { listStyleType: "decimal" } : null,
|
|
928
|
-
// Background clip (web-only)
|
|
929
|
-
"bg-clip-border": web ? { backgroundClip: "border-box" } : null,
|
|
930
|
-
"bg-clip-padding": web ? { backgroundClip: "padding-box" } : null,
|
|
931
|
-
"bg-clip-content": web ? { backgroundClip: "content-box" } : null,
|
|
932
|
-
"bg-clip-text": web ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
|
|
933
|
-
// Background image
|
|
934
|
-
"bg-none": web ? { backgroundImage: "none" } : null,
|
|
935
|
-
// Background size (web-only)
|
|
936
|
-
"bg-auto": web ? { backgroundSize: "auto" } : null,
|
|
937
|
-
"bg-cover": web ? { backgroundSize: "cover" } : null,
|
|
938
|
-
"bg-contain": web ? { backgroundSize: "contain" } : null,
|
|
939
|
-
// Background position (web-only)
|
|
940
|
-
"bg-center": web ? { backgroundPosition: "center" } : null,
|
|
941
|
-
"bg-top": web ? { backgroundPosition: "top" } : null,
|
|
942
|
-
"bg-bottom": web ? { backgroundPosition: "bottom" } : null,
|
|
943
|
-
"bg-left": web ? { backgroundPosition: "left" } : null,
|
|
944
|
-
"bg-right": web ? { backgroundPosition: "right" } : null,
|
|
945
|
-
"bg-left-top": web ? { backgroundPosition: "left top" } : null,
|
|
946
|
-
"bg-left-bottom": web ? { backgroundPosition: "left bottom" } : null,
|
|
947
|
-
"bg-right-top": web ? { backgroundPosition: "right top" } : null,
|
|
948
|
-
"bg-right-bottom": web ? { backgroundPosition: "right bottom" } : null,
|
|
949
|
-
// Background repeat (web-only)
|
|
950
|
-
"bg-repeat": web ? { backgroundRepeat: "repeat" } : null,
|
|
951
|
-
"bg-no-repeat": web ? { backgroundRepeat: "no-repeat" } : null,
|
|
952
|
-
"bg-repeat-x": web ? { backgroundRepeat: "repeat-x" } : null,
|
|
953
|
-
"bg-repeat-y": web ? { backgroundRepeat: "repeat-y" } : null,
|
|
954
|
-
"bg-repeat-round": web ? { backgroundRepeat: "round" } : null,
|
|
955
|
-
"bg-repeat-space": web ? { backgroundRepeat: "space" } : null,
|
|
956
|
-
// Background attachment (web-only)
|
|
957
|
-
"bg-fixed": web ? { backgroundAttachment: "fixed" } : null,
|
|
958
|
-
"bg-local": web ? { backgroundAttachment: "local" } : null,
|
|
959
|
-
"bg-scroll": web ? { backgroundAttachment: "scroll" } : null,
|
|
960
|
-
// Object position (web-only)
|
|
961
|
-
"object-center": web ? { objectPosition: "center" } : null,
|
|
962
|
-
"object-top": web ? { objectPosition: "top" } : null,
|
|
963
|
-
"object-bottom": web ? { objectPosition: "bottom" } : null,
|
|
964
|
-
"object-left": web ? { objectPosition: "left" } : null,
|
|
965
|
-
"object-right": web ? { objectPosition: "right" } : null,
|
|
966
|
-
"object-left-top": web ? { objectPosition: "left top" } : null,
|
|
967
|
-
"object-left-bottom": web ? { objectPosition: "left bottom" } : null,
|
|
968
|
-
"object-right-top": web ? { objectPosition: "right top" } : null,
|
|
969
|
-
"object-right-bottom": web ? { objectPosition: "right bottom" } : null,
|
|
970
|
-
// Table (web-only)
|
|
971
|
-
table: web ? { display: "table" } : null,
|
|
972
|
-
"table-auto": web ? { tableLayout: "auto" } : null,
|
|
973
|
-
"table-fixed": web ? { tableLayout: "fixed" } : null,
|
|
974
|
-
"caption-top": web ? { captionSide: "top" } : null,
|
|
975
|
-
"caption-bottom": web ? { captionSide: "bottom" } : null,
|
|
976
|
-
"border-collapse": web ? { borderCollapse: "collapse" } : null,
|
|
977
|
-
"border-separate": web ? { borderCollapse: "separate" } : null,
|
|
978
|
-
// List style position (web-only)
|
|
979
|
-
"list-inside": web ? { listStylePosition: "inside" } : null,
|
|
980
|
-
"list-outside": web ? { listStylePosition: "outside" } : null,
|
|
981
|
-
// Font variant numeric (web-only)
|
|
982
|
-
"normal-nums": web ? { fontVariantNumeric: "normal" } : null,
|
|
983
|
-
ordinal: web ? { fontVariantNumeric: "ordinal" } : null,
|
|
984
|
-
"slashed-zero": web ? { fontVariantNumeric: "slashed-zero" } : null,
|
|
985
|
-
"lining-nums": web ? { fontVariantNumeric: "lining-nums" } : null,
|
|
986
|
-
"oldstyle-nums": web ? { fontVariantNumeric: "oldstyle-nums" } : null,
|
|
987
|
-
"proportional-nums": web ? { fontVariantNumeric: "proportional-nums" } : null,
|
|
988
|
-
"tabular-nums": web ? { fontVariantNumeric: "tabular-nums" } : null,
|
|
989
|
-
"diagonal-fractions": web ? { fontVariantNumeric: "diagonal-fractions" } : null,
|
|
990
|
-
"stacked-fractions": web ? { fontVariantNumeric: "stacked-fractions" } : null,
|
|
991
|
-
// Isolation (web-only)
|
|
992
|
-
isolate: web ? { isolation: "isolate" } : null,
|
|
993
|
-
"isolation-auto": web ? { isolation: "auto" } : null,
|
|
994
|
-
// Backface visibility (both iOS and Android)
|
|
995
|
-
"backface-visible": { backfaceVisibility: "visible" },
|
|
996
|
-
"backface-hidden": { backfaceVisibility: "hidden" },
|
|
997
|
-
// CSS filters — standalone = default/full effect (web-only)
|
|
998
|
-
grayscale: web ? { "--kb-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
|
|
999
|
-
invert: web ? { "--kb-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
|
|
1000
|
-
sepia: web ? { "--kb-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
|
|
1001
|
-
// Divide none
|
|
1002
|
-
"divide-none": web ? { __divideX: 0, __divideY: 0 } : null,
|
|
1003
|
-
// Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
|
|
1004
|
-
group: web ? {} : null,
|
|
1005
|
-
peer: web ? {} : null,
|
|
1006
|
-
// Text-wrap (web-only)
|
|
1007
|
-
"text-wrap": web ? { textWrap: "wrap" } : null,
|
|
1008
|
-
"text-nowrap": web ? { textWrap: "nowrap" } : null,
|
|
1009
|
-
"text-balance": web ? { textWrap: "balance" } : null,
|
|
1010
|
-
"text-pretty": web ? { textWrap: "pretty" } : null,
|
|
1011
|
-
// Screen sizing — dvw/dvh (dynamic viewport units) instead of vw/vh: on mobile
|
|
1012
|
-
// browsers, vh/vw are pinned to the LARGEST viewport size (address bar hidden),
|
|
1013
|
-
// so `h-screen` overflows behind the address bar when it's shown. dvh/dvw track
|
|
1014
|
-
// the actual visible viewport as browser chrome shows/hides. Desktop behavior
|
|
1015
|
-
// is unchanged since there's no dynamic chrome to account for.
|
|
1016
|
-
// (vw/dvw values are web-only; vh/dvh values work cross-platform via spacing scale for h-*)
|
|
1017
|
-
"w-screen": web ? { width: "100dvw" } : null,
|
|
1018
|
-
"min-h-screen": { minHeight: "100dvh" },
|
|
1019
|
-
"max-h-screen": { maxHeight: "100dvh" },
|
|
1020
|
-
"min-w-screen": web ? { minWidth: "100dvw" } : null,
|
|
1021
|
-
"max-w-screen": web ? { maxWidth: "100dvw" } : null,
|
|
1022
|
-
// max-w named container sizes (mirrors Tailwind's container scale)
|
|
1023
|
-
"max-w-none": { maxWidth: "none" },
|
|
1024
|
-
"max-w-xs": { maxWidth: 320 },
|
|
1025
|
-
"max-w-sm": { maxWidth: 384 },
|
|
1026
|
-
"max-w-md": { maxWidth: 448 },
|
|
1027
|
-
"max-w-lg": { maxWidth: 512 },
|
|
1028
|
-
"max-w-xl": { maxWidth: 576 },
|
|
1029
|
-
"max-w-2xl": { maxWidth: 672 },
|
|
1030
|
-
"max-w-3xl": { maxWidth: 768 },
|
|
1031
|
-
"max-w-4xl": { maxWidth: 896 },
|
|
1032
|
-
"max-w-5xl": { maxWidth: 1024 },
|
|
1033
|
-
"max-w-6xl": { maxWidth: 1152 },
|
|
1034
|
-
"max-w-7xl": { maxWidth: 1280 },
|
|
1035
|
-
"max-w-prose": web ? { maxWidth: "65ch" } : null,
|
|
1036
|
-
// Extended cursors (web-only)
|
|
1037
|
-
"cursor-grab": web ? { cursor: "grab" } : null,
|
|
1038
|
-
"cursor-grabbing": web ? { cursor: "grabbing" } : null,
|
|
1039
|
-
"cursor-zoom-in": web ? { cursor: "zoom-in" } : null,
|
|
1040
|
-
"cursor-zoom-out": web ? { cursor: "zoom-out" } : null,
|
|
1041
|
-
"cursor-crosshair": web ? { cursor: "crosshair" } : null,
|
|
1042
|
-
"cursor-help": web ? { cursor: "help" } : null,
|
|
1043
|
-
"cursor-none": web ? { cursor: "none" } : null,
|
|
1044
|
-
// Overflow clip (web-only)
|
|
1045
|
-
"overflow-clip": web ? { overflow: "clip" } : null,
|
|
1046
|
-
"overflow-x-clip": web ? { overflowX: "clip" } : null,
|
|
1047
|
-
"overflow-y-clip": web ? { overflowY: "clip" } : null,
|
|
1048
|
-
// Scroll behavior (web-only)
|
|
1049
|
-
"scroll-smooth": web ? { scrollBehavior: "smooth" } : null,
|
|
1050
|
-
"scroll-auto": web ? { scrollBehavior: "auto" } : null,
|
|
1051
|
-
// Float (web-only)
|
|
1052
|
-
"float-left": web ? { float: "left" } : null,
|
|
1053
|
-
"float-right": web ? { float: "right" } : null,
|
|
1054
|
-
"float-start": web ? { float: "inline-start" } : null,
|
|
1055
|
-
"float-end": web ? { float: "inline-end" } : null,
|
|
1056
|
-
"float-none": web ? { float: "none" } : null,
|
|
1057
|
-
// Clear (web-only)
|
|
1058
|
-
"clear-left": web ? { clear: "left" } : null,
|
|
1059
|
-
"clear-right": web ? { clear: "right" } : null,
|
|
1060
|
-
"clear-both": web ? { clear: "both" } : null,
|
|
1061
|
-
"clear-start": web ? { clear: "inline-start" } : null,
|
|
1062
|
-
"clear-end": web ? { clear: "inline-end" } : null,
|
|
1063
|
-
"clear-none": web ? { clear: "none" } : null,
|
|
1064
|
-
// Vertical align (web-only)
|
|
1065
|
-
"align-baseline": web ? { verticalAlign: "baseline" } : null,
|
|
1066
|
-
"align-top": web ? { verticalAlign: "top" } : null,
|
|
1067
|
-
"align-middle": web ? { verticalAlign: "middle" } : null,
|
|
1068
|
-
"align-bottom": web ? { verticalAlign: "bottom" } : null,
|
|
1069
|
-
"align-text-top": web ? { verticalAlign: "text-top" } : null,
|
|
1070
|
-
"align-text-bottom": web ? { verticalAlign: "text-bottom" } : null,
|
|
1071
|
-
"align-sub": web ? { verticalAlign: "sub" } : null,
|
|
1072
|
-
"align-super": web ? { verticalAlign: "super" } : null,
|
|
1073
|
-
// Touch action (web-only)
|
|
1074
|
-
"touch-auto": web ? { touchAction: "auto" } : null,
|
|
1075
|
-
"touch-none": web ? { touchAction: "none" } : null,
|
|
1076
|
-
"touch-pan-x": web ? { touchAction: "pan-x" } : null,
|
|
1077
|
-
"touch-pan-y": web ? { touchAction: "pan-y" } : null,
|
|
1078
|
-
"touch-pan-left": web ? { touchAction: "pan-left" } : null,
|
|
1079
|
-
"touch-pan-right": web ? { touchAction: "pan-right" } : null,
|
|
1080
|
-
"touch-pan-up": web ? { touchAction: "pan-up" } : null,
|
|
1081
|
-
"touch-pan-down": web ? { touchAction: "pan-down" } : null,
|
|
1082
|
-
"touch-pinch-zoom": web ? { touchAction: "pinch-zoom" } : null,
|
|
1083
|
-
"touch-manipulation": web ? { touchAction: "manipulation" } : null
|
|
1084
|
-
};
|
|
1085
|
-
}
|
|
1086
|
-
function getStandalone() {
|
|
1087
|
-
if (!_standalone) _standalone = buildStandalone();
|
|
1088
|
-
return _standalone;
|
|
1089
|
-
}
|
|
1090
|
-
function makeSpacingResolver(prop) {
|
|
1091
|
-
return ({ value, negative, isArbitrary }, { spacing }) => {
|
|
1092
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
1093
|
-
return v !== null ? { [prop]: v } : null;
|
|
1094
|
-
};
|
|
1095
|
-
}
|
|
1096
|
-
var PADDING_MARGIN_PROPS = {
|
|
1097
|
-
p: "padding",
|
|
1098
|
-
px: "paddingHorizontal",
|
|
1099
|
-
py: "paddingVertical",
|
|
1100
|
-
pt: "paddingTop",
|
|
1101
|
-
pr: "paddingRight",
|
|
1102
|
-
pb: "paddingBottom",
|
|
1103
|
-
pl: "paddingLeft",
|
|
1104
|
-
m: "margin",
|
|
1105
|
-
mx: "marginHorizontal",
|
|
1106
|
-
my: "marginVertical",
|
|
1107
|
-
mt: "marginTop",
|
|
1108
|
-
mr: "marginRight",
|
|
1109
|
-
mb: "marginBottom",
|
|
1110
|
-
ml: "marginLeft"
|
|
1111
|
-
};
|
|
1112
|
-
function makeBorderSideResolver(widthProp, colorProp) {
|
|
1113
|
-
return ({ value, isArbitrary }, { colors, borderWidth }) => {
|
|
1114
|
-
if (!value) return { [widthProp]: 1 };
|
|
1115
|
-
if (isArbitrary) {
|
|
1116
|
-
const w2 = toNativeValue(value);
|
|
1117
|
-
if (typeof w2 === "number") return { [widthProp]: w2 };
|
|
1118
|
-
return { [colorProp]: value };
|
|
1119
|
-
}
|
|
1120
|
-
const color = resolveColor(value, colors, false);
|
|
1121
|
-
if (color) return { [colorProp]: color };
|
|
1122
|
-
const w = borderWidth[value];
|
|
1123
|
-
return w !== void 0 ? { [widthProp]: w } : null;
|
|
1124
|
-
};
|
|
1125
|
-
}
|
|
1126
|
-
var BORDER_SIDE_PROPS = {
|
|
1127
|
-
"border-t": ["borderTopWidth", "borderTopColor"],
|
|
1128
|
-
"border-r": ["borderRightWidth", "borderRightColor"],
|
|
1129
|
-
"border-b": ["borderBottomWidth", "borderBottomColor"],
|
|
1130
|
-
"border-l": ["borderLeftWidth", "borderLeftColor"]
|
|
1131
|
-
};
|
|
1132
|
-
function keyframeDeclToCSS(decl) {
|
|
1133
|
-
return Object.entries(decl).map(([prop, val]) => `${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${val}`).join("; ");
|
|
1134
|
-
}
|
|
1135
|
-
function buildKeyframeCSS(name, steps) {
|
|
1136
|
-
const body = Object.entries(steps).map(([selector, decl]) => `${selector} { ${keyframeDeclToCSS(decl)} }`).join(" ");
|
|
1137
|
-
return `@keyframes ${name} { ${body} }`;
|
|
1138
|
-
}
|
|
1139
|
-
var BUILTIN_ANIMATIONS = {
|
|
1140
|
-
none: { animation: "none" },
|
|
1141
|
-
spin: {
|
|
1142
|
-
animation: "kb-spin 1s linear infinite",
|
|
1143
|
-
__keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
|
|
1144
|
-
},
|
|
1145
|
-
ping: {
|
|
1146
|
-
animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
|
|
1147
|
-
__keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
|
|
1148
|
-
},
|
|
1149
|
-
pulse: {
|
|
1150
|
-
animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
|
|
1151
|
-
__keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
|
|
1152
|
-
},
|
|
1153
|
-
bounce: {
|
|
1154
|
-
animation: "kb-bounce 1s infinite",
|
|
1155
|
-
__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) } }"
|
|
1156
|
-
}
|
|
1157
|
-
};
|
|
1158
|
-
function buildAnimationValue(animation, keyframes) {
|
|
1159
|
-
const words = animation.trim().split(/\s+/);
|
|
1160
|
-
const name = words[0];
|
|
1161
|
-
if (!name) return { animation };
|
|
1162
|
-
const builtin = BUILTIN_ANIMATIONS[name];
|
|
1163
|
-
if (builtin?.__keyframe) {
|
|
1164
|
-
const kbName = builtin.animation.split(/\s+/, 1)[0];
|
|
1165
|
-
return { animation: [kbName, ...words.slice(1)].join(" "), __keyframe: builtin.__keyframe };
|
|
1166
|
-
}
|
|
1167
|
-
const steps = keyframes?.[name];
|
|
1168
|
-
return steps ? { animation, __keyframe: buildKeyframeCSS(name, steps) } : { animation };
|
|
1169
|
-
}
|
|
1170
|
-
var RESOLVERS = {
|
|
1171
|
-
// ── Background ─────────────────────────────────────────────────────────────
|
|
1172
|
-
bg: ({ value, isArbitrary }, { colors }) => {
|
|
1173
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1174
|
-
if (!color) return null;
|
|
1175
|
-
return { backgroundColor: getEffectiveIsWeb() ? withOpacityVar(color, "--bg-opacity") : color };
|
|
1176
|
-
},
|
|
1177
|
-
"bg-opacity": ({ value, isArbitrary }, _) => {
|
|
1178
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1179
|
-
const n = parseFloat(value);
|
|
1180
|
-
if (isNaN(n)) return null;
|
|
1181
|
-
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
1182
|
-
return { "--bg-opacity": v };
|
|
1183
|
-
},
|
|
1184
|
-
// ── Text ───────────────────────────────────────────────────────────────────
|
|
1185
|
-
text: ({ value, isArbitrary }, { colors, fontSize }) => {
|
|
1186
|
-
const size = resolveFontSize(value, fontSize, false);
|
|
1187
|
-
if (!isArbitrary && size !== null) return { fontSize: size };
|
|
1188
|
-
if (isArbitrary) {
|
|
1189
|
-
if (/^\d/.test(value) || /^(calc|min|max|clamp)/.test(value)) {
|
|
1190
|
-
return { fontSize: getEffectiveIsWeb() ? value : toNativeValue(value) };
|
|
1191
|
-
}
|
|
1192
|
-
return { color: getEffectiveIsWeb() ? withOpacityVar(value, "--text-opacity") : value };
|
|
1193
|
-
}
|
|
1194
|
-
const color = resolveColor(value, colors, false);
|
|
1195
|
-
if (!color) return null;
|
|
1196
|
-
return { color: getEffectiveIsWeb() ? withOpacityVar(color, "--text-opacity") : color };
|
|
1197
|
-
},
|
|
1198
|
-
"text-opacity": ({ value, isArbitrary }, _) => {
|
|
1199
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1200
|
-
const n = parseFloat(value);
|
|
1201
|
-
if (isNaN(n)) return null;
|
|
1202
|
-
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
1203
|
-
return { "--text-opacity": v };
|
|
1204
|
-
},
|
|
1205
|
-
// ── Padding & margin ───────────────────────────────────────────────────────
|
|
1206
|
-
// Generated below via makeSpacingResolver() — see PADDING_MARGIN_PROPS.
|
|
1207
|
-
// ── Sizing ─────────────────────────────────────────────────────────────────
|
|
1208
|
-
w: ({ value, isArbitrary }, { spacing }) => {
|
|
1209
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1210
|
-
return v !== null ? { width: v } : null;
|
|
1211
|
-
},
|
|
1212
|
-
h: ({ value, isArbitrary }, { spacing }) => {
|
|
1213
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1214
|
-
return v !== null ? { height: v } : null;
|
|
1215
|
-
},
|
|
1216
|
-
"min-w": ({ value, isArbitrary }, { spacing }) => {
|
|
1217
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1218
|
-
return v !== null ? { minWidth: v } : null;
|
|
1219
|
-
},
|
|
1220
|
-
"min-h": ({ value, isArbitrary }, { spacing }) => {
|
|
1221
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1222
|
-
return v !== null ? { minHeight: v } : null;
|
|
1223
|
-
},
|
|
1224
|
-
"max-w": ({ value, isArbitrary }, { spacing }) => {
|
|
1225
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1226
|
-
return v !== null ? { maxWidth: v } : null;
|
|
1227
|
-
},
|
|
1228
|
-
"max-h": ({ value, isArbitrary }, { spacing }) => {
|
|
1229
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
1230
|
-
return v !== null ? { maxHeight: v } : null;
|
|
1231
|
-
},
|
|
965
|
+
var BORDER_SIDE_PROPS = {
|
|
966
|
+
"border-t": ["borderTopWidth", "borderTopColor"],
|
|
967
|
+
"border-r": ["borderRightWidth", "borderRightColor"],
|
|
968
|
+
"border-b": ["borderBottomWidth", "borderBottomColor"],
|
|
969
|
+
"border-l": ["borderLeftWidth", "borderLeftColor"]
|
|
970
|
+
};
|
|
971
|
+
var borderResolvers = {
|
|
1232
972
|
// ── Border width ───────────────────────────────────────────────────────────
|
|
1233
973
|
border: ({ value, isArbitrary }, { colors, borderWidth, spacing }) => {
|
|
1234
974
|
if (!value) return { borderWidth: borderWidth["DEFAULT"] ?? 1 };
|
|
@@ -1285,188 +1025,128 @@ var RESOLVERS = {
|
|
|
1285
1025
|
const r = resolveRadius(value, borderRadius, isArbitrary);
|
|
1286
1026
|
return r !== null ? { borderBottomRightRadius: r } : null;
|
|
1287
1027
|
},
|
|
1288
|
-
// ──
|
|
1289
|
-
|
|
1290
|
-
if (!value) return null;
|
|
1291
|
-
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1292
|
-
const n = parseInt(value, 10);
|
|
1293
|
-
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1294
|
-
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1295
|
-
},
|
|
1296
|
-
// ── Grid template columns/rows (Tailwind-style aliases, web-only) ──────────
|
|
1297
|
-
"grid-cols": ({ value, isArbitrary }) => {
|
|
1028
|
+
// ── Outline extended (web-only) ───────────────────────────────────────────
|
|
1029
|
+
outline: ({ value, isArbitrary }, { colors }) => {
|
|
1298
1030
|
if (!getEffectiveIsWeb()) return null;
|
|
1299
|
-
if (!value) return
|
|
1300
|
-
if (
|
|
1301
|
-
if (
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1031
|
+
if (!value) return { outline: "2px solid transparent", outlineOffset: "2px" };
|
|
1032
|
+
if (value === "none") return { outline: "none", outlineOffset: "0" };
|
|
1033
|
+
if (isArbitrary) {
|
|
1034
|
+
if (/^\d/.test(value) || value.startsWith("calc(")) return { outlineWidth: value };
|
|
1035
|
+
return { outlineColor: value };
|
|
1036
|
+
}
|
|
1037
|
+
const widths = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1038
|
+
if (value in widths) return { outlineWidth: widths[value] };
|
|
1039
|
+
const color = resolveColor(value, colors, false);
|
|
1040
|
+
return color ? { outlineColor: color } : null;
|
|
1305
1041
|
},
|
|
1306
|
-
"
|
|
1042
|
+
"outline-offset": ({ value, isArbitrary }) => {
|
|
1307
1043
|
if (!getEffectiveIsWeb()) return null;
|
|
1308
|
-
if (
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
const n = parseInt(value, 10);
|
|
1312
|
-
if (isNaN(n) || n < 1) return null;
|
|
1313
|
-
return { gridTemplateRows: `repeat(${n}, minmax(0, 1fr))` };
|
|
1044
|
+
if (isArbitrary) return { outlineOffset: value };
|
|
1045
|
+
const offsets = { "0": "0px", "1": "1px", "2": "2px", "4": "4px", "8": "8px" };
|
|
1046
|
+
return offsets[value] ? { outlineOffset: offsets[value] } : null;
|
|
1314
1047
|
},
|
|
1315
|
-
// ──
|
|
1316
|
-
|
|
1048
|
+
// ── Divide (child combinator CSS, web-only) ───────────────────────────────
|
|
1049
|
+
// These return special __divide* markers that resolver.ts converts to
|
|
1050
|
+
// .cls > * + * { border-... } CSS rules. No inline style is applied.
|
|
1051
|
+
"divide-x": ({ value, isArbitrary }) => {
|
|
1317
1052
|
if (!getEffectiveIsWeb()) return null;
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
"row-dense": "row dense",
|
|
1323
|
-
"col-dense": "column dense"
|
|
1324
|
-
};
|
|
1325
|
-
const flow = flows[value];
|
|
1326
|
-
return flow ? { gridAutoFlow: flow } : null;
|
|
1053
|
+
if (value === "reverse") return null;
|
|
1054
|
+
if (!value) return { __divideX: 1 };
|
|
1055
|
+
const n = parseFloat(value);
|
|
1056
|
+
return isNaN(n) ? null : { __divideX: n };
|
|
1327
1057
|
},
|
|
1328
|
-
|
|
1329
|
-
"auto-cols": ({ value, isArbitrary }) => {
|
|
1058
|
+
"divide-y": ({ value, isArbitrary }) => {
|
|
1330
1059
|
if (!getEffectiveIsWeb()) return null;
|
|
1331
|
-
if (
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
max: "max-content",
|
|
1336
|
-
fr: "minmax(0, 1fr)"
|
|
1337
|
-
};
|
|
1338
|
-
const v = presets[value];
|
|
1339
|
-
return v ? { gridAutoColumns: v } : null;
|
|
1060
|
+
if (value === "reverse") return null;
|
|
1061
|
+
if (!value) return { __divideY: 1 };
|
|
1062
|
+
const n = parseFloat(value);
|
|
1063
|
+
return isNaN(n) ? null : { __divideY: n };
|
|
1340
1064
|
},
|
|
1341
|
-
|
|
1065
|
+
divide: ({ value, isArbitrary }, { colors }) => {
|
|
1342
1066
|
if (!getEffectiveIsWeb()) return null;
|
|
1343
|
-
if (isArbitrary) return {
|
|
1344
|
-
const
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1067
|
+
if (isArbitrary) return { __divideColor: value };
|
|
1068
|
+
const styleTokens = {
|
|
1069
|
+
solid: "solid",
|
|
1070
|
+
dashed: "dashed",
|
|
1071
|
+
dotted: "dotted",
|
|
1072
|
+
double: "double",
|
|
1073
|
+
none: "none"
|
|
1349
1074
|
};
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
// ── Grid column placement (web-only) ──────────────────────────────────────
|
|
1354
|
-
"col-span": ({ value }) => {
|
|
1355
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1356
|
-
if (value === "full") return { gridColumn: "1 / -1" };
|
|
1357
|
-
const n = parseInt(value, 10);
|
|
1358
|
-
return isNaN(n) ? null : { gridColumn: `span ${n} / span ${n}` };
|
|
1359
|
-
},
|
|
1360
|
-
"col-start": ({ value, isArbitrary }) => {
|
|
1361
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1362
|
-
if (value === "auto") return { gridColumnStart: "auto" };
|
|
1363
|
-
if (isArbitrary) return { gridColumnStart: value };
|
|
1364
|
-
const n = parseInt(value, 10);
|
|
1365
|
-
return isNaN(n) ? null : { gridColumnStart: n };
|
|
1366
|
-
},
|
|
1367
|
-
"col-end": ({ value, isArbitrary }) => {
|
|
1368
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1369
|
-
if (value === "auto") return { gridColumnEnd: "auto" };
|
|
1370
|
-
if (isArbitrary) return { gridColumnEnd: value };
|
|
1371
|
-
const n = parseInt(value, 10);
|
|
1372
|
-
return isNaN(n) ? null : { gridColumnEnd: n };
|
|
1373
|
-
},
|
|
1374
|
-
col: ({ value, isArbitrary }) => {
|
|
1375
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1376
|
-
if (!value || value === "auto") return { gridColumn: "auto" };
|
|
1377
|
-
if (isArbitrary) return { gridColumn: value };
|
|
1378
|
-
return null;
|
|
1379
|
-
},
|
|
1380
|
-
// ── Grid row placement (web-only) ─────────────────────────────────────────
|
|
1381
|
-
"row-span": ({ value }) => {
|
|
1382
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1383
|
-
if (value === "full") return { gridRow: "1 / -1" };
|
|
1384
|
-
const n = parseInt(value, 10);
|
|
1385
|
-
return isNaN(n) ? null : { gridRow: `span ${n} / span ${n}` };
|
|
1386
|
-
},
|
|
1387
|
-
"row-start": ({ value, isArbitrary }) => {
|
|
1388
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1389
|
-
if (value === "auto") return { gridRowStart: "auto" };
|
|
1390
|
-
if (isArbitrary) return { gridRowStart: value };
|
|
1391
|
-
const n = parseInt(value, 10);
|
|
1392
|
-
return isNaN(n) ? null : { gridRowStart: n };
|
|
1393
|
-
},
|
|
1394
|
-
"row-end": ({ value, isArbitrary }) => {
|
|
1395
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1396
|
-
if (value === "auto") return { gridRowEnd: "auto" };
|
|
1397
|
-
if (isArbitrary) return { gridRowEnd: value };
|
|
1398
|
-
const n = parseInt(value, 10);
|
|
1399
|
-
return isNaN(n) ? null : { gridRowEnd: n };
|
|
1075
|
+
if (value in styleTokens) return { __divideStyle: styleTokens[value] };
|
|
1076
|
+
const color = resolveColor(value, colors, false);
|
|
1077
|
+
return color ? { __divideColor: color } : null;
|
|
1400
1078
|
},
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1079
|
+
// ── Ring ───────────────────────────────────────────────────────────────────
|
|
1080
|
+
// Web: box-shadow outline ring (doesn't affect layout).
|
|
1081
|
+
// Native: React Native has no box-shadow, so this falls back to borderWidth/
|
|
1082
|
+
// borderColor — the closest visual approximation (used by other RN Tailwind-
|
|
1083
|
+
// likes for the same reason). Unlike the web ring, this DOES affect layout,
|
|
1084
|
+
// and it shares its properties with the `border` utility — combining
|
|
1085
|
+
// `border-*` and `ring-*` on the same native element means whichever class
|
|
1086
|
+
// comes later wins, since both ultimately set borderWidth/borderColor.
|
|
1087
|
+
ring: ({ value, isArbitrary }, { colors }) => {
|
|
1088
|
+
const onWeb = getEffectiveIsWeb();
|
|
1089
|
+
const DEFAULT_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
1090
|
+
const DEFAULT_WIDTH = 3;
|
|
1091
|
+
const asNative = (w, color2) => w === 0 ? { borderWidth: 0 } : { borderWidth: w, borderColor: color2 };
|
|
1092
|
+
if (!value) {
|
|
1093
|
+
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
1094
|
+
}
|
|
1095
|
+
if (value === "inset") {
|
|
1096
|
+
return onWeb ? { boxShadow: `inset 0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
1097
|
+
}
|
|
1098
|
+
const widthTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
1099
|
+
if (!isArbitrary && value in widthTokens) {
|
|
1100
|
+
const w = widthTokens[value];
|
|
1101
|
+
return onWeb ? { boxShadow: w === 0 ? "none" : `0 0 0 ${w}px ${DEFAULT_COLOR}` } : asNative(w, DEFAULT_COLOR);
|
|
1102
|
+
}
|
|
1103
|
+
if (isArbitrary) {
|
|
1104
|
+
const numMatch = /^(\d+(?:\.\d+)?)(px|rem|em|vw|vh)?$/.exec(value);
|
|
1105
|
+
if (numMatch) {
|
|
1106
|
+
const unit = numMatch[2] ?? "px";
|
|
1107
|
+
if (onWeb) return { boxShadow: `0 0 0 ${numMatch[1]}${unit} ${DEFAULT_COLOR}` };
|
|
1108
|
+
return unit === "px" ? asNative(parseFloat(numMatch[1]), DEFAULT_COLOR) : null;
|
|
1109
|
+
}
|
|
1110
|
+
return onWeb ? { boxShadow: value.replace(/_/g, " ") } : null;
|
|
1111
|
+
}
|
|
1112
|
+
const color = resolveColor(value, colors, false);
|
|
1113
|
+
if (color) {
|
|
1114
|
+
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${color}` } : asNative(DEFAULT_WIDTH, color);
|
|
1115
|
+
}
|
|
1405
1116
|
return null;
|
|
1406
1117
|
},
|
|
1407
|
-
//
|
|
1408
|
-
//
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
end: "end",
|
|
1414
|
-
center: "center",
|
|
1415
|
-
stretch: "stretch",
|
|
1416
|
-
baseline: "baseline"
|
|
1417
|
-
};
|
|
1418
|
-
return map[value] ? { placeItems: map[value] } : null;
|
|
1419
|
-
},
|
|
1420
|
-
// place-content is shorthand for align-content + justify-content on a grid container
|
|
1421
|
-
"place-content": ({ value }) => {
|
|
1422
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1423
|
-
const map = {
|
|
1424
|
-
start: "start",
|
|
1425
|
-
end: "end",
|
|
1426
|
-
center: "center",
|
|
1427
|
-
stretch: "stretch",
|
|
1428
|
-
between: "space-between",
|
|
1429
|
-
around: "space-around",
|
|
1430
|
-
evenly: "space-evenly",
|
|
1431
|
-
baseline: "baseline"
|
|
1432
|
-
};
|
|
1433
|
-
return map[value] ? { placeContent: map[value] } : null;
|
|
1434
|
-
},
|
|
1435
|
-
// justify-items controls inline-axis alignment of grid items within their cells
|
|
1436
|
-
"justify-items": ({ value }) => {
|
|
1437
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1438
|
-
const map = {
|
|
1439
|
-
start: "start",
|
|
1440
|
-
end: "end",
|
|
1441
|
-
center: "center",
|
|
1442
|
-
stretch: "stretch"
|
|
1443
|
-
};
|
|
1444
|
-
return map[value] ? { justifyItems: map[value] } : null;
|
|
1445
|
-
},
|
|
1446
|
-
// place-self is shorthand for align-self + justify-self on a grid item
|
|
1447
|
-
"place-self": ({ value }) => {
|
|
1448
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1449
|
-
const map = {
|
|
1450
|
-
auto: "auto",
|
|
1451
|
-
start: "start",
|
|
1452
|
-
end: "end",
|
|
1453
|
-
center: "center",
|
|
1454
|
-
stretch: "stretch"
|
|
1455
|
-
};
|
|
1456
|
-
return map[value] ? { placeSelf: map[value] } : null;
|
|
1457
|
-
},
|
|
1458
|
-
// justify-self controls inline-axis self-alignment of a grid item
|
|
1459
|
-
"justify-self": ({ value }) => {
|
|
1118
|
+
// Web-only, unlike `ring` above: this stacks a second box-shadow layer to
|
|
1119
|
+
// create a gap between the element and the ring. There's no native
|
|
1120
|
+
// equivalent to approximate that with (a border can't create a gap outside
|
|
1121
|
+
// its own element without an extra wrapper view), so this stays a no-op
|
|
1122
|
+
// on native rather than rendering a misleading half-translation.
|
|
1123
|
+
"ring-offset": ({ value, isArbitrary }, _theme) => {
|
|
1460
1124
|
if (!getEffectiveIsWeb()) return null;
|
|
1461
|
-
const
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1125
|
+
const DEFAULT_RING_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
1126
|
+
const DEFAULT_RING_WIDTH = 3;
|
|
1127
|
+
const offsetTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
1128
|
+
let offsetWidth;
|
|
1129
|
+
if (!isArbitrary) {
|
|
1130
|
+
offsetWidth = value in offsetTokens ? offsetTokens[value] : null;
|
|
1131
|
+
} else {
|
|
1132
|
+
offsetWidth = /^-?\d+(\.\d+)?$/.test(value) ? parseFloat(value) : value;
|
|
1133
|
+
}
|
|
1134
|
+
if (offsetWidth === null || typeof offsetWidth === "number" && isNaN(offsetWidth)) return null;
|
|
1135
|
+
const isZero = offsetWidth === 0 || offsetWidth === "0";
|
|
1136
|
+
const offsetCss = typeof offsetWidth === "number" ? `${offsetWidth}px` : offsetWidth;
|
|
1137
|
+
return {
|
|
1138
|
+
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}`
|
|
1467
1139
|
};
|
|
1468
|
-
|
|
1469
|
-
|
|
1140
|
+
}
|
|
1141
|
+
};
|
|
1142
|
+
for (const [utility, [widthProp, colorProp]] of Object.entries(BORDER_SIDE_PROPS)) {
|
|
1143
|
+
borderResolvers[utility] = makeBorderSideResolver(widthProp, colorProp);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// src/core/resolvers/filters.ts
|
|
1147
|
+
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,)";
|
|
1148
|
+
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,)";
|
|
1149
|
+
var filterResolvers = {
|
|
1470
1150
|
// ── CSS Filters (composable via CSS variables, web-only) ─────────────────
|
|
1471
1151
|
blur: ({ value, isArbitrary }) => {
|
|
1472
1152
|
if (!getEffectiveIsWeb()) return null;
|
|
@@ -1601,410 +1281,606 @@ var RESOLVERS = {
|
|
|
1601
1281
|
if (value === "none") return { backdropFilter: "none" };
|
|
1602
1282
|
return null;
|
|
1603
1283
|
},
|
|
1604
|
-
// ──
|
|
1605
|
-
"
|
|
1606
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1607
|
-
const directions = {
|
|
1608
|
-
t: "to top",
|
|
1609
|
-
tr: "to top right",
|
|
1610
|
-
r: "to right",
|
|
1611
|
-
br: "to bottom right",
|
|
1612
|
-
b: "to bottom",
|
|
1613
|
-
bl: "to bottom left",
|
|
1614
|
-
l: "to left",
|
|
1615
|
-
tl: "to top left"
|
|
1616
|
-
};
|
|
1617
|
-
const dir = directions[value];
|
|
1618
|
-
if (!dir) return null;
|
|
1619
|
-
return {
|
|
1620
|
-
backgroundImage: `linear-gradient(${dir}, var(--kb-gradient-from, transparent), var(--kb-gradient-stops, transparent))`
|
|
1621
|
-
};
|
|
1622
|
-
},
|
|
1623
|
-
from: ({ value, isArbitrary }, { colors }) => {
|
|
1624
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1625
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1626
|
-
if (!color) return null;
|
|
1627
|
-
return {
|
|
1628
|
-
"--kb-gradient-from": color,
|
|
1629
|
-
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-to, transparent)`
|
|
1630
|
-
};
|
|
1631
|
-
},
|
|
1632
|
-
via: ({ value, isArbitrary }, { colors }) => {
|
|
1633
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1634
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1635
|
-
if (!color) return null;
|
|
1636
|
-
return {
|
|
1637
|
-
"--kb-gradient-via": color,
|
|
1638
|
-
"--kb-gradient-stops": `var(--kb-gradient-from), var(--kb-gradient-via), var(--kb-gradient-to, transparent)`
|
|
1639
|
-
};
|
|
1640
|
-
},
|
|
1641
|
-
to: ({ value, isArbitrary }, { colors }) => {
|
|
1642
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1643
|
-
const color = resolveColor(value, colors, isArbitrary);
|
|
1644
|
-
if (!color) return null;
|
|
1645
|
-
return { "--kb-gradient-to": color };
|
|
1646
|
-
},
|
|
1647
|
-
// ── Transform extras (web-only) ───────────────────────────────────────────
|
|
1648
|
-
"skew-x": ({ value, negative, isArbitrary }) => {
|
|
1649
|
-
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
1650
|
-
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
1651
|
-
return getEffectiveIsWeb() ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
|
|
1652
|
-
},
|
|
1653
|
-
"skew-y": ({ value, negative, isArbitrary }) => {
|
|
1654
|
-
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
1655
|
-
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
1656
|
-
return getEffectiveIsWeb() ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
|
|
1657
|
-
},
|
|
1658
|
-
// Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
|
|
1659
|
-
transform: ({ value, isArbitrary }) => {
|
|
1660
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1661
|
-
if (isArbitrary) return { transform: value.replace(/_/g, " ") };
|
|
1662
|
-
if (value === "none") return { transform: "none" };
|
|
1663
|
-
return null;
|
|
1664
|
-
},
|
|
1665
|
-
// Transform origin
|
|
1666
|
-
origin: ({ value, isArbitrary }) => {
|
|
1284
|
+
// ── Mix / background blend mode (web-only) ───────────────────────────────
|
|
1285
|
+
"mix-blend": ({ value }) => {
|
|
1667
1286
|
if (!getEffectiveIsWeb()) return null;
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
"
|
|
1673
|
-
|
|
1674
|
-
"
|
|
1675
|
-
|
|
1676
|
-
"
|
|
1677
|
-
|
|
1678
|
-
"
|
|
1679
|
-
|
|
1680
|
-
|
|
1287
|
+
const modes = [
|
|
1288
|
+
"normal",
|
|
1289
|
+
"multiply",
|
|
1290
|
+
"screen",
|
|
1291
|
+
"overlay",
|
|
1292
|
+
"darken",
|
|
1293
|
+
"lighten",
|
|
1294
|
+
"color-dodge",
|
|
1295
|
+
"color-burn",
|
|
1296
|
+
"hard-light",
|
|
1297
|
+
"soft-light",
|
|
1298
|
+
"difference",
|
|
1299
|
+
"exclusion",
|
|
1300
|
+
"hue",
|
|
1301
|
+
"saturation",
|
|
1302
|
+
"color",
|
|
1303
|
+
"luminosity",
|
|
1304
|
+
"plus-lighter"
|
|
1305
|
+
];
|
|
1306
|
+
return modes.includes(value) ? { mixBlendMode: value } : null;
|
|
1681
1307
|
},
|
|
1682
|
-
|
|
1683
|
-
decoration: ({ value, isArbitrary }, { colors }) => {
|
|
1308
|
+
"bg-blend": ({ value }) => {
|
|
1684
1309
|
if (!getEffectiveIsWeb()) return null;
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
"
|
|
1692
|
-
"
|
|
1693
|
-
"
|
|
1694
|
-
"
|
|
1695
|
-
"
|
|
1696
|
-
"
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
wavy: "wavy"
|
|
1705
|
-
};
|
|
1706
|
-
if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
|
|
1707
|
-
const color = resolveColor(value, colors, false);
|
|
1708
|
-
return color ? { textDecorationColor: color } : null;
|
|
1310
|
+
const modes = [
|
|
1311
|
+
"normal",
|
|
1312
|
+
"multiply",
|
|
1313
|
+
"screen",
|
|
1314
|
+
"overlay",
|
|
1315
|
+
"darken",
|
|
1316
|
+
"lighten",
|
|
1317
|
+
"color-dodge",
|
|
1318
|
+
"color-burn",
|
|
1319
|
+
"hard-light",
|
|
1320
|
+
"soft-light",
|
|
1321
|
+
"difference",
|
|
1322
|
+
"exclusion",
|
|
1323
|
+
"hue",
|
|
1324
|
+
"saturation",
|
|
1325
|
+
"color",
|
|
1326
|
+
"luminosity"
|
|
1327
|
+
];
|
|
1328
|
+
return modes.includes(value) ? { backgroundBlendMode: value } : null;
|
|
1709
1329
|
},
|
|
1710
|
-
|
|
1330
|
+
// ── Will-change (web-only) ─────────────────────────────────────────────────
|
|
1331
|
+
"will-change": ({ value, isArbitrary }) => {
|
|
1711
1332
|
if (!getEffectiveIsWeb()) return null;
|
|
1712
|
-
if (isArbitrary) return {
|
|
1713
|
-
const
|
|
1333
|
+
if (isArbitrary) return { willChange: value.replace(/_/g, ", ") };
|
|
1334
|
+
const presets = {
|
|
1714
1335
|
auto: "auto",
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
"4": "4px",
|
|
1719
|
-
"8": "8px"
|
|
1336
|
+
scroll: "scroll-position",
|
|
1337
|
+
contents: "contents",
|
|
1338
|
+
transform: "transform"
|
|
1720
1339
|
};
|
|
1721
|
-
return
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1340
|
+
return presets[value] ? { willChange: presets[value] } : null;
|
|
1341
|
+
}
|
|
1342
|
+
};
|
|
1343
|
+
|
|
1344
|
+
// src/core/resolvers/layout.ts
|
|
1345
|
+
var _standalone = null;
|
|
1346
|
+
function buildStandalone() {
|
|
1347
|
+
const web = getEffectiveIsWeb();
|
|
1348
|
+
return {
|
|
1349
|
+
// Display
|
|
1350
|
+
// React Native only supports display:'flex'|'none'. Setting 'flex' explicitly is
|
|
1351
|
+
// a no-op normally, but is needed to re-show an element that was hidden via `hidden`.
|
|
1352
|
+
// `grid`, `contents`, `flow-root` have no native equivalent and stay null there.
|
|
1353
|
+
// The inline-* family (inline, inline-block, inline-flex, inline-grid) falls back
|
|
1354
|
+
// to 'flex' on native instead — like plain `flex`, this is a no-op most of the
|
|
1355
|
+
// time, but without it these utilities couldn't re-show a `hidden` element on
|
|
1356
|
+
// native either (null → no style applied → still display:'none').
|
|
1357
|
+
flex: { display: "flex" },
|
|
1358
|
+
block: web ? { display: "block" } : null,
|
|
1359
|
+
"inline-block": { display: web ? "inline-block" : "flex" },
|
|
1360
|
+
inline: { display: web ? "inline" : "flex" },
|
|
1361
|
+
grid: web ? { display: "grid" } : null,
|
|
1362
|
+
grd: web ? { display: "grid" } : null,
|
|
1363
|
+
"inline-flex": { display: web ? "inline-flex" : "flex" },
|
|
1364
|
+
"inline-grid": { display: web ? "inline-grid" : "flex" },
|
|
1365
|
+
hidden: { display: "none" },
|
|
1366
|
+
contents: web ? { display: "contents" } : null,
|
|
1367
|
+
"flow-root": web ? { display: "flow-root" } : null,
|
|
1368
|
+
// Flex direction (both web and native)
|
|
1369
|
+
"flex-row": { flexDirection: "row" },
|
|
1370
|
+
"flex-col": { flexDirection: "column" },
|
|
1371
|
+
"flex-row-reverse": { flexDirection: "row-reverse" },
|
|
1372
|
+
"flex-col-reverse": { flexDirection: "column-reverse" },
|
|
1373
|
+
// Flex wrap (both)
|
|
1374
|
+
"flex-wrap": { flexWrap: "wrap" },
|
|
1375
|
+
"flex-wrap-reverse": { flexWrap: "wrap-reverse" },
|
|
1376
|
+
"flex-nowrap": { flexWrap: "nowrap" },
|
|
1377
|
+
// Flex grow / shrink (both)
|
|
1378
|
+
"flex-grow": { flexGrow: 1 },
|
|
1379
|
+
"flex-grow-0": { flexGrow: 0 },
|
|
1380
|
+
"flex-shrink": { flexShrink: 1 },
|
|
1381
|
+
"flex-shrink-0": { flexShrink: 0 },
|
|
1382
|
+
// Align items (both)
|
|
1383
|
+
"items-start": { alignItems: "flex-start" },
|
|
1384
|
+
"items-end": { alignItems: "flex-end" },
|
|
1385
|
+
"items-center": { alignItems: "center" },
|
|
1386
|
+
"items-baseline": { alignItems: "baseline" },
|
|
1387
|
+
"items-stretch": { alignItems: "stretch" },
|
|
1388
|
+
// Justify content (both)
|
|
1389
|
+
"justify-start": { justifyContent: "flex-start" },
|
|
1390
|
+
"justify-end": { justifyContent: "flex-end" },
|
|
1391
|
+
"justify-center": { justifyContent: "center" },
|
|
1392
|
+
"justify-between": { justifyContent: "space-between" },
|
|
1393
|
+
"justify-around": { justifyContent: "space-around" },
|
|
1394
|
+
"justify-evenly": { justifyContent: "space-evenly" },
|
|
1395
|
+
// Align content (both)
|
|
1396
|
+
"content-start": { alignContent: "flex-start" },
|
|
1397
|
+
"content-end": { alignContent: "flex-end" },
|
|
1398
|
+
"content-center": { alignContent: "center" },
|
|
1399
|
+
"content-between": { alignContent: "space-between" },
|
|
1400
|
+
"content-around": { alignContent: "space-around" },
|
|
1401
|
+
"content-evenly": { alignContent: "space-evenly" },
|
|
1402
|
+
"content-stretch": { alignContent: "stretch" },
|
|
1403
|
+
// Align self (both)
|
|
1404
|
+
"self-auto": { alignSelf: "auto" },
|
|
1405
|
+
"self-start": { alignSelf: "flex-start" },
|
|
1406
|
+
"self-end": { alignSelf: "flex-end" },
|
|
1407
|
+
"self-center": { alignSelf: "center" },
|
|
1408
|
+
"self-stretch": { alignSelf: "stretch" },
|
|
1409
|
+
"self-baseline": { alignSelf: "baseline" },
|
|
1410
|
+
// Text align (both)
|
|
1411
|
+
"text-left": { textAlign: "left" },
|
|
1412
|
+
"text-right": { textAlign: "right" },
|
|
1413
|
+
"text-center": { textAlign: "center" },
|
|
1414
|
+
"text-justify": { textAlign: "justify" },
|
|
1415
|
+
// Font weight shortcuts (both)
|
|
1416
|
+
"font-thin": { fontWeight: "100" },
|
|
1417
|
+
"font-extralight": { fontWeight: "200" },
|
|
1418
|
+
"font-light": { fontWeight: "300" },
|
|
1419
|
+
"font-normal": { fontWeight: "400" },
|
|
1420
|
+
"font-medium": { fontWeight: "500" },
|
|
1421
|
+
"font-semibold": { fontWeight: "600" },
|
|
1422
|
+
"font-bold": { fontWeight: "700" },
|
|
1423
|
+
"font-extrabold": { fontWeight: "800" },
|
|
1424
|
+
"font-black": { fontWeight: "900" },
|
|
1425
|
+
// Text decoration (overline is web-only)
|
|
1426
|
+
underline: { textDecorationLine: "underline" },
|
|
1427
|
+
overline: web ? { textDecorationLine: "overline" } : null,
|
|
1428
|
+
"line-through": { textDecorationLine: "line-through" },
|
|
1429
|
+
"no-underline": { textDecorationLine: "none" },
|
|
1430
|
+
// Text transform (both)
|
|
1431
|
+
uppercase: { textTransform: "uppercase" },
|
|
1432
|
+
lowercase: { textTransform: "lowercase" },
|
|
1433
|
+
capitalize: { textTransform: "capitalize" },
|
|
1434
|
+
"normal-case": { textTransform: "none" },
|
|
1435
|
+
// Font style (both)
|
|
1436
|
+
italic: { fontStyle: "italic" },
|
|
1437
|
+
"non-italic": { fontStyle: "normal" },
|
|
1438
|
+
// Position (fixed/sticky/static are web-only; RN only supports relative/absolute)
|
|
1439
|
+
relative: { position: "relative" },
|
|
1440
|
+
absolute: { position: "absolute" },
|
|
1441
|
+
fixed: web ? { position: "fixed" } : null,
|
|
1442
|
+
sticky: web ? { position: "sticky" } : null,
|
|
1443
|
+
static: web ? { position: "static" } : null,
|
|
1444
|
+
// Visibility (no `visibility` prop on native; use opacity instead)
|
|
1445
|
+
visible: web ? { visibility: "visible" } : null,
|
|
1446
|
+
invisible: web ? { visibility: "hidden" } : { opacity: 0 },
|
|
1447
|
+
// Overflow (RN supports 'hidden' | 'visible' | 'scroll'; not 'auto')
|
|
1448
|
+
"overflow-hidden": { overflow: "hidden" },
|
|
1449
|
+
"overflow-visible": { overflow: "visible" },
|
|
1450
|
+
"overflow-scroll": { overflow: "scroll" },
|
|
1451
|
+
"overflow-auto": web ? { overflow: "auto" } : { overflow: "scroll" },
|
|
1452
|
+
// overflowX / overflowY are web-only
|
|
1453
|
+
"overflow-x-hidden": web ? { overflowX: "hidden" } : null,
|
|
1454
|
+
"overflow-x-scroll": web ? { overflowX: "scroll" } : null,
|
|
1455
|
+
"overflow-x-auto": web ? { overflowX: "auto" } : null,
|
|
1456
|
+
"overflow-y-hidden": web ? { overflowY: "hidden" } : null,
|
|
1457
|
+
"overflow-y-scroll": web ? { overflowY: "scroll" } : null,
|
|
1458
|
+
"overflow-y-auto": web ? { overflowY: "auto" } : null,
|
|
1459
|
+
// Object fit (web-only; use resizeMode prop on RN Image)
|
|
1460
|
+
"object-contain": web ? { objectFit: "contain" } : null,
|
|
1461
|
+
"object-cover": web ? { objectFit: "cover" } : null,
|
|
1462
|
+
"object-fill": web ? { objectFit: "fill" } : null,
|
|
1463
|
+
"object-none": web ? { objectFit: "none" } : null,
|
|
1464
|
+
"object-scale-down": web ? { objectFit: "scale-down" } : null,
|
|
1465
|
+
// Border style (both)
|
|
1466
|
+
"border-solid": { borderStyle: "solid" },
|
|
1467
|
+
"border-dashed": { borderStyle: "dashed" },
|
|
1468
|
+
"border-dotted": { borderStyle: "dotted" },
|
|
1469
|
+
"border-none": { borderWidth: 0 },
|
|
1470
|
+
// Border sides default width (both)
|
|
1471
|
+
"border-t": { borderTopWidth: 1 },
|
|
1472
|
+
"border-r": { borderRightWidth: 1 },
|
|
1473
|
+
"border-b": { borderBottomWidth: 1 },
|
|
1474
|
+
"border-l": { borderLeftWidth: 1 },
|
|
1475
|
+
// Cursor (web-only)
|
|
1476
|
+
"cursor-auto": web ? { cursor: "auto" } : null,
|
|
1477
|
+
"cursor-default": web ? { cursor: "default" } : null,
|
|
1478
|
+
"cursor-pointer": web ? { cursor: "pointer" } : null,
|
|
1479
|
+
"cursor-wait": web ? { cursor: "wait" } : null,
|
|
1480
|
+
"cursor-text": web ? { cursor: "text" } : null,
|
|
1481
|
+
"cursor-move": web ? { cursor: "move" } : null,
|
|
1482
|
+
"cursor-not-allowed": web ? { cursor: "not-allowed" } : null,
|
|
1483
|
+
// User select (web-only)
|
|
1484
|
+
"select-none": web ? { userSelect: "none" } : null,
|
|
1485
|
+
"select-text": web ? { userSelect: "text" } : null,
|
|
1486
|
+
"select-all": web ? { userSelect: "all" } : null,
|
|
1487
|
+
"select-auto": web ? { userSelect: "auto" } : null,
|
|
1488
|
+
// Pointer events (both)
|
|
1489
|
+
"pointer-events-none": { pointerEvents: "none" },
|
|
1490
|
+
"pointer-events-auto": { pointerEvents: "auto" },
|
|
1491
|
+
// Whitespace (web-only; RN Text uses numberOfLines prop instead)
|
|
1492
|
+
"whitespace-normal": web ? { whiteSpace: "normal" } : null,
|
|
1493
|
+
"whitespace-nowrap": web ? { whiteSpace: "nowrap" } : null,
|
|
1494
|
+
"whitespace-pre": web ? { whiteSpace: "pre" } : null,
|
|
1495
|
+
"whitespace-pre-wrap": web ? { whiteSpace: "pre-wrap" } : null,
|
|
1496
|
+
"whitespace-pre-line": web ? { whiteSpace: "pre-line" } : null,
|
|
1497
|
+
// Word break (web-only)
|
|
1498
|
+
"break-normal": web ? { overflowWrap: "normal", wordBreak: "normal" } : null,
|
|
1499
|
+
"break-words": web ? { overflowWrap: "break-word" } : null,
|
|
1500
|
+
"break-all": web ? { wordBreak: "break-all" } : null,
|
|
1501
|
+
// Misc web-only
|
|
1502
|
+
truncate: web ? { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } : null,
|
|
1503
|
+
"box-border": web ? { boxSizing: "border-box" } : null,
|
|
1504
|
+
"box-content": web ? { boxSizing: "content-box" } : null,
|
|
1505
|
+
"appearance-none": web ? { appearance: "none" } : null,
|
|
1506
|
+
"outline-none": web ? { outline: "none", outlineOffset: "0" } : null,
|
|
1507
|
+
outline: web ? { outline: "2px solid transparent", outlineOffset: "2px" } : null,
|
|
1508
|
+
resize: web ? { resize: "both" } : null,
|
|
1509
|
+
"resize-none": web ? { resize: "none" } : null,
|
|
1510
|
+
"resize-y": web ? { resize: "vertical" } : null,
|
|
1511
|
+
"resize-x": web ? { resize: "horizontal" } : null,
|
|
1512
|
+
antialiased: web ? { WebkitFontSmoothing: "antialiased", MozOsxFontSmoothing: "grayscale" } : null,
|
|
1513
|
+
"subpixel-antialiased": web ? { WebkitFontSmoothing: "subpixel-antialiased", MozOsxFontSmoothing: "auto" } : null,
|
|
1514
|
+
"overflow-ellipsis": web ? { textOverflow: "ellipsis" } : null,
|
|
1515
|
+
"sr-only": web ? {
|
|
1516
|
+
position: "absolute",
|
|
1517
|
+
width: 1,
|
|
1518
|
+
height: 1,
|
|
1519
|
+
padding: 0,
|
|
1520
|
+
margin: -1,
|
|
1521
|
+
overflow: "hidden",
|
|
1522
|
+
clip: "rect(0,0,0,0)",
|
|
1523
|
+
whiteSpace: "nowrap",
|
|
1524
|
+
border: 0
|
|
1525
|
+
} : null,
|
|
1526
|
+
"not-sr-only": web ? {
|
|
1527
|
+
position: "static",
|
|
1528
|
+
width: "auto",
|
|
1529
|
+
height: "auto",
|
|
1530
|
+
padding: 0,
|
|
1531
|
+
margin: 0,
|
|
1532
|
+
overflow: "visible",
|
|
1533
|
+
clip: "auto",
|
|
1534
|
+
whiteSpace: "normal"
|
|
1535
|
+
} : null,
|
|
1536
|
+
// Lists (web-only)
|
|
1537
|
+
"list-none": web ? { listStyleType: "none" } : null,
|
|
1538
|
+
"list-disc": web ? { listStyleType: "disc" } : null,
|
|
1539
|
+
"list-decimal": web ? { listStyleType: "decimal" } : null,
|
|
1540
|
+
// Background clip (web-only)
|
|
1541
|
+
"bg-clip-border": web ? { backgroundClip: "border-box" } : null,
|
|
1542
|
+
"bg-clip-padding": web ? { backgroundClip: "padding-box" } : null,
|
|
1543
|
+
"bg-clip-content": web ? { backgroundClip: "content-box" } : null,
|
|
1544
|
+
"bg-clip-text": web ? { backgroundClip: "text", WebkitBackgroundClip: "text" } : null,
|
|
1545
|
+
// Background image
|
|
1546
|
+
"bg-none": web ? { backgroundImage: "none" } : null,
|
|
1547
|
+
// Background size (web-only)
|
|
1548
|
+
"bg-auto": web ? { backgroundSize: "auto" } : null,
|
|
1549
|
+
"bg-cover": web ? { backgroundSize: "cover" } : null,
|
|
1550
|
+
"bg-contain": web ? { backgroundSize: "contain" } : null,
|
|
1551
|
+
// Background position (web-only)
|
|
1552
|
+
"bg-center": web ? { backgroundPosition: "center" } : null,
|
|
1553
|
+
"bg-top": web ? { backgroundPosition: "top" } : null,
|
|
1554
|
+
"bg-bottom": web ? { backgroundPosition: "bottom" } : null,
|
|
1555
|
+
"bg-left": web ? { backgroundPosition: "left" } : null,
|
|
1556
|
+
"bg-right": web ? { backgroundPosition: "right" } : null,
|
|
1557
|
+
"bg-left-top": web ? { backgroundPosition: "left top" } : null,
|
|
1558
|
+
"bg-left-bottom": web ? { backgroundPosition: "left bottom" } : null,
|
|
1559
|
+
"bg-right-top": web ? { backgroundPosition: "right top" } : null,
|
|
1560
|
+
"bg-right-bottom": web ? { backgroundPosition: "right bottom" } : null,
|
|
1561
|
+
// Background repeat (web-only)
|
|
1562
|
+
"bg-repeat": web ? { backgroundRepeat: "repeat" } : null,
|
|
1563
|
+
"bg-no-repeat": web ? { backgroundRepeat: "no-repeat" } : null,
|
|
1564
|
+
"bg-repeat-x": web ? { backgroundRepeat: "repeat-x" } : null,
|
|
1565
|
+
"bg-repeat-y": web ? { backgroundRepeat: "repeat-y" } : null,
|
|
1566
|
+
"bg-repeat-round": web ? { backgroundRepeat: "round" } : null,
|
|
1567
|
+
"bg-repeat-space": web ? { backgroundRepeat: "space" } : null,
|
|
1568
|
+
// Background attachment (web-only)
|
|
1569
|
+
"bg-fixed": web ? { backgroundAttachment: "fixed" } : null,
|
|
1570
|
+
"bg-local": web ? { backgroundAttachment: "local" } : null,
|
|
1571
|
+
"bg-scroll": web ? { backgroundAttachment: "scroll" } : null,
|
|
1572
|
+
// Object position (web-only)
|
|
1573
|
+
"object-center": web ? { objectPosition: "center" } : null,
|
|
1574
|
+
"object-top": web ? { objectPosition: "top" } : null,
|
|
1575
|
+
"object-bottom": web ? { objectPosition: "bottom" } : null,
|
|
1576
|
+
"object-left": web ? { objectPosition: "left" } : null,
|
|
1577
|
+
"object-right": web ? { objectPosition: "right" } : null,
|
|
1578
|
+
"object-left-top": web ? { objectPosition: "left top" } : null,
|
|
1579
|
+
"object-left-bottom": web ? { objectPosition: "left bottom" } : null,
|
|
1580
|
+
"object-right-top": web ? { objectPosition: "right top" } : null,
|
|
1581
|
+
"object-right-bottom": web ? { objectPosition: "right bottom" } : null,
|
|
1582
|
+
// Table (web-only)
|
|
1583
|
+
table: web ? { display: "table" } : null,
|
|
1584
|
+
"table-auto": web ? { tableLayout: "auto" } : null,
|
|
1585
|
+
"table-fixed": web ? { tableLayout: "fixed" } : null,
|
|
1586
|
+
"caption-top": web ? { captionSide: "top" } : null,
|
|
1587
|
+
"caption-bottom": web ? { captionSide: "bottom" } : null,
|
|
1588
|
+
"border-collapse": web ? { borderCollapse: "collapse" } : null,
|
|
1589
|
+
"border-separate": web ? { borderCollapse: "separate" } : null,
|
|
1590
|
+
// List style position (web-only)
|
|
1591
|
+
"list-inside": web ? { listStylePosition: "inside" } : null,
|
|
1592
|
+
"list-outside": web ? { listStylePosition: "outside" } : null,
|
|
1593
|
+
// Font variant numeric (web-only)
|
|
1594
|
+
"normal-nums": web ? { fontVariantNumeric: "normal" } : null,
|
|
1595
|
+
ordinal: web ? { fontVariantNumeric: "ordinal" } : null,
|
|
1596
|
+
"slashed-zero": web ? { fontVariantNumeric: "slashed-zero" } : null,
|
|
1597
|
+
"lining-nums": web ? { fontVariantNumeric: "lining-nums" } : null,
|
|
1598
|
+
"oldstyle-nums": web ? { fontVariantNumeric: "oldstyle-nums" } : null,
|
|
1599
|
+
"proportional-nums": web ? { fontVariantNumeric: "proportional-nums" } : null,
|
|
1600
|
+
"tabular-nums": web ? { fontVariantNumeric: "tabular-nums" } : null,
|
|
1601
|
+
"diagonal-fractions": web ? { fontVariantNumeric: "diagonal-fractions" } : null,
|
|
1602
|
+
"stacked-fractions": web ? { fontVariantNumeric: "stacked-fractions" } : null,
|
|
1603
|
+
// Isolation (web-only)
|
|
1604
|
+
isolate: web ? { isolation: "isolate" } : null,
|
|
1605
|
+
"isolation-auto": web ? { isolation: "auto" } : null,
|
|
1606
|
+
// Backface visibility (both iOS and Android)
|
|
1607
|
+
"backface-visible": { backfaceVisibility: "visible" },
|
|
1608
|
+
"backface-hidden": { backfaceVisibility: "hidden" },
|
|
1609
|
+
// CSS filters — standalone = default/full effect (web-only)
|
|
1610
|
+
grayscale: web ? { "--kb-grayscale": "grayscale(100%)", filter: FILTER_COMPOSE } : null,
|
|
1611
|
+
invert: web ? { "--kb-invert": "invert(100%)", filter: FILTER_COMPOSE } : null,
|
|
1612
|
+
sepia: web ? { "--kb-sepia": "sepia(100%)", filter: FILTER_COMPOSE } : null,
|
|
1613
|
+
// Divide none
|
|
1614
|
+
"divide-none": web ? { __divideX: 0, __divideY: 0 } : null,
|
|
1615
|
+
// Group / peer markers (no-op: no style emitted; just ensures isKnownUtility returns true)
|
|
1616
|
+
group: web ? {} : null,
|
|
1617
|
+
peer: web ? {} : null,
|
|
1618
|
+
// Text-wrap (web-only)
|
|
1619
|
+
"text-wrap": web ? { textWrap: "wrap" } : null,
|
|
1620
|
+
"text-nowrap": web ? { textWrap: "nowrap" } : null,
|
|
1621
|
+
"text-balance": web ? { textWrap: "balance" } : null,
|
|
1622
|
+
"text-pretty": web ? { textWrap: "pretty" } : null,
|
|
1623
|
+
// Screen sizing — dvw/dvh (dynamic viewport units) instead of vw/vh: on mobile
|
|
1624
|
+
// browsers, vh/vw are pinned to the LARGEST viewport size (address bar hidden),
|
|
1625
|
+
// so `h-screen` overflows behind the address bar when it's shown. dvh/dvw track
|
|
1626
|
+
// the actual visible viewport as browser chrome shows/hides. Desktop behavior
|
|
1627
|
+
// is unchanged since there's no dynamic chrome to account for.
|
|
1628
|
+
// (vw/dvw values are web-only; vh/dvh values work cross-platform via spacing scale for h-*)
|
|
1629
|
+
"w-screen": web ? { width: "100dvw" } : null,
|
|
1630
|
+
"min-h-screen": { minHeight: "100dvh" },
|
|
1631
|
+
"max-h-screen": { maxHeight: "100dvh" },
|
|
1632
|
+
"min-w-screen": web ? { minWidth: "100dvw" } : null,
|
|
1633
|
+
"max-w-screen": web ? { maxWidth: "100dvw" } : null,
|
|
1634
|
+
// max-w named container sizes (mirrors Tailwind's container scale)
|
|
1635
|
+
"max-w-none": { maxWidth: "none" },
|
|
1636
|
+
"max-w-xs": { maxWidth: 320 },
|
|
1637
|
+
"max-w-sm": { maxWidth: 384 },
|
|
1638
|
+
"max-w-md": { maxWidth: 448 },
|
|
1639
|
+
"max-w-lg": { maxWidth: 512 },
|
|
1640
|
+
"max-w-xl": { maxWidth: 576 },
|
|
1641
|
+
"max-w-2xl": { maxWidth: 672 },
|
|
1642
|
+
"max-w-3xl": { maxWidth: 768 },
|
|
1643
|
+
"max-w-4xl": { maxWidth: 896 },
|
|
1644
|
+
"max-w-5xl": { maxWidth: 1024 },
|
|
1645
|
+
"max-w-6xl": { maxWidth: 1152 },
|
|
1646
|
+
"max-w-7xl": { maxWidth: 1280 },
|
|
1647
|
+
"max-w-prose": web ? { maxWidth: "65ch" } : null,
|
|
1648
|
+
// Extended cursors (web-only)
|
|
1649
|
+
"cursor-grab": web ? { cursor: "grab" } : null,
|
|
1650
|
+
"cursor-grabbing": web ? { cursor: "grabbing" } : null,
|
|
1651
|
+
"cursor-zoom-in": web ? { cursor: "zoom-in" } : null,
|
|
1652
|
+
"cursor-zoom-out": web ? { cursor: "zoom-out" } : null,
|
|
1653
|
+
"cursor-crosshair": web ? { cursor: "crosshair" } : null,
|
|
1654
|
+
"cursor-help": web ? { cursor: "help" } : null,
|
|
1655
|
+
"cursor-none": web ? { cursor: "none" } : null,
|
|
1656
|
+
// Overflow clip (web-only)
|
|
1657
|
+
"overflow-clip": web ? { overflow: "clip" } : null,
|
|
1658
|
+
"overflow-x-clip": web ? { overflowX: "clip" } : null,
|
|
1659
|
+
"overflow-y-clip": web ? { overflowY: "clip" } : null,
|
|
1660
|
+
// Scroll behavior (web-only)
|
|
1661
|
+
"scroll-smooth": web ? { scrollBehavior: "smooth" } : null,
|
|
1662
|
+
"scroll-auto": web ? { scrollBehavior: "auto" } : null,
|
|
1663
|
+
// Float (web-only)
|
|
1664
|
+
"float-left": web ? { float: "left" } : null,
|
|
1665
|
+
"float-right": web ? { float: "right" } : null,
|
|
1666
|
+
"float-start": web ? { float: "inline-start" } : null,
|
|
1667
|
+
"float-end": web ? { float: "inline-end" } : null,
|
|
1668
|
+
"float-none": web ? { float: "none" } : null,
|
|
1669
|
+
// Clear (web-only)
|
|
1670
|
+
"clear-left": web ? { clear: "left" } : null,
|
|
1671
|
+
"clear-right": web ? { clear: "right" } : null,
|
|
1672
|
+
"clear-both": web ? { clear: "both" } : null,
|
|
1673
|
+
"clear-start": web ? { clear: "inline-start" } : null,
|
|
1674
|
+
"clear-end": web ? { clear: "inline-end" } : null,
|
|
1675
|
+
"clear-none": web ? { clear: "none" } : null,
|
|
1676
|
+
// Vertical align (web-only)
|
|
1677
|
+
"align-baseline": web ? { verticalAlign: "baseline" } : null,
|
|
1678
|
+
"align-top": web ? { verticalAlign: "top" } : null,
|
|
1679
|
+
"align-middle": web ? { verticalAlign: "middle" } : null,
|
|
1680
|
+
"align-bottom": web ? { verticalAlign: "bottom" } : null,
|
|
1681
|
+
"align-text-top": web ? { verticalAlign: "text-top" } : null,
|
|
1682
|
+
"align-text-bottom": web ? { verticalAlign: "text-bottom" } : null,
|
|
1683
|
+
"align-sub": web ? { verticalAlign: "sub" } : null,
|
|
1684
|
+
"align-super": web ? { verticalAlign: "super" } : null,
|
|
1685
|
+
// Touch action (web-only)
|
|
1686
|
+
"touch-auto": web ? { touchAction: "auto" } : null,
|
|
1687
|
+
"touch-none": web ? { touchAction: "none" } : null,
|
|
1688
|
+
"touch-pan-x": web ? { touchAction: "pan-x" } : null,
|
|
1689
|
+
"touch-pan-y": web ? { touchAction: "pan-y" } : null,
|
|
1690
|
+
"touch-pan-left": web ? { touchAction: "pan-left" } : null,
|
|
1691
|
+
"touch-pan-right": web ? { touchAction: "pan-right" } : null,
|
|
1692
|
+
"touch-pan-up": web ? { touchAction: "pan-up" } : null,
|
|
1693
|
+
"touch-pan-down": web ? { touchAction: "pan-down" } : null,
|
|
1694
|
+
"touch-pinch-zoom": web ? { touchAction: "pinch-zoom" } : null,
|
|
1695
|
+
"touch-manipulation": web ? { touchAction: "manipulation" } : null
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1698
|
+
function getStandalone() {
|
|
1699
|
+
if (!_standalone) _standalone = buildStandalone();
|
|
1700
|
+
return _standalone;
|
|
1701
|
+
}
|
|
1702
|
+
var layoutResolvers = {
|
|
1703
|
+
// ── Grid (responsive column count: grid-1 … grid-12, or arbitrary) ───────
|
|
1704
|
+
grid: ({ value, isArbitrary }) => {
|
|
1705
|
+
if (!value) return null;
|
|
1706
|
+
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1707
|
+
const n = parseInt(value, 10);
|
|
1708
|
+
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1709
|
+
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1774
1710
|
},
|
|
1775
|
-
// ──
|
|
1776
|
-
|
|
1711
|
+
// ── Grid template columns/rows (Tailwind-style aliases, web-only) ──────────
|
|
1712
|
+
"grid-cols": ({ value, isArbitrary }) => {
|
|
1777
1713
|
if (!getEffectiveIsWeb()) return null;
|
|
1778
|
-
if (
|
|
1779
|
-
if (
|
|
1714
|
+
if (!value) return null;
|
|
1715
|
+
if (isArbitrary) return { display: "grid", gridTemplateColumns: value };
|
|
1716
|
+
if (value === "none") return { display: "grid", gridTemplateColumns: "none" };
|
|
1780
1717
|
const n = parseInt(value, 10);
|
|
1781
|
-
if (
|
|
1782
|
-
|
|
1783
|
-
"3xs": "16rem",
|
|
1784
|
-
"2xs": "18rem",
|
|
1785
|
-
xs: "20rem",
|
|
1786
|
-
sm: "24rem",
|
|
1787
|
-
md: "28rem",
|
|
1788
|
-
lg: "32rem",
|
|
1789
|
-
xl: "36rem",
|
|
1790
|
-
"2xl": "42rem",
|
|
1791
|
-
"3xl": "48rem",
|
|
1792
|
-
"4xl": "56rem",
|
|
1793
|
-
"5xl": "64rem",
|
|
1794
|
-
"6xl": "72rem",
|
|
1795
|
-
"7xl": "80rem"
|
|
1796
|
-
};
|
|
1797
|
-
return widths[value] ? { columnWidth: widths[value] } : null;
|
|
1718
|
+
if (isNaN(n) || n < 1 || n > 12) return null;
|
|
1719
|
+
return { display: "grid", gridTemplateColumns: `repeat(${n}, minmax(0, 1fr))` };
|
|
1798
1720
|
},
|
|
1799
|
-
|
|
1800
|
-
"mix-blend": ({ value }) => {
|
|
1721
|
+
"grid-rows": ({ value, isArbitrary }) => {
|
|
1801
1722
|
if (!getEffectiveIsWeb()) return null;
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
"lighten",
|
|
1809
|
-
"color-dodge",
|
|
1810
|
-
"color-burn",
|
|
1811
|
-
"hard-light",
|
|
1812
|
-
"soft-light",
|
|
1813
|
-
"difference",
|
|
1814
|
-
"exclusion",
|
|
1815
|
-
"hue",
|
|
1816
|
-
"saturation",
|
|
1817
|
-
"color",
|
|
1818
|
-
"luminosity",
|
|
1819
|
-
"plus-lighter"
|
|
1820
|
-
];
|
|
1821
|
-
return modes.includes(value) ? { mixBlendMode: value } : null;
|
|
1723
|
+
if (!value) return null;
|
|
1724
|
+
if (isArbitrary) return { gridTemplateRows: value };
|
|
1725
|
+
if (value === "none") return { gridTemplateRows: "none" };
|
|
1726
|
+
const n = parseInt(value, 10);
|
|
1727
|
+
if (isNaN(n) || n < 1) return null;
|
|
1728
|
+
return { gridTemplateRows: `repeat(${n}, minmax(0, 1fr))` };
|
|
1822
1729
|
},
|
|
1823
|
-
|
|
1730
|
+
// ── Grid auto flow (web-only) ─────────────────────────────────────────────
|
|
1731
|
+
"grid-flow": ({ value }) => {
|
|
1824
1732
|
if (!getEffectiveIsWeb()) return null;
|
|
1825
|
-
const
|
|
1826
|
-
"
|
|
1827
|
-
"
|
|
1828
|
-
"
|
|
1829
|
-
"
|
|
1830
|
-
"
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
"hard-light",
|
|
1835
|
-
"soft-light",
|
|
1836
|
-
"difference",
|
|
1837
|
-
"exclusion",
|
|
1838
|
-
"hue",
|
|
1839
|
-
"saturation",
|
|
1840
|
-
"color",
|
|
1841
|
-
"luminosity"
|
|
1842
|
-
];
|
|
1843
|
-
return modes.includes(value) ? { backgroundBlendMode: value } : null;
|
|
1733
|
+
const flows = {
|
|
1734
|
+
row: "row",
|
|
1735
|
+
col: "column",
|
|
1736
|
+
dense: "dense",
|
|
1737
|
+
"row-dense": "row dense",
|
|
1738
|
+
"col-dense": "column dense"
|
|
1739
|
+
};
|
|
1740
|
+
const flow = flows[value];
|
|
1741
|
+
return flow ? { gridAutoFlow: flow } : null;
|
|
1844
1742
|
},
|
|
1845
|
-
// ──
|
|
1846
|
-
"
|
|
1743
|
+
// ── Grid auto sizing (web-only) ───────────────────────────────────────────
|
|
1744
|
+
"auto-cols": ({ value, isArbitrary }) => {
|
|
1847
1745
|
if (!getEffectiveIsWeb()) return null;
|
|
1848
|
-
if (isArbitrary) return {
|
|
1746
|
+
if (isArbitrary) return { gridAutoColumns: value };
|
|
1849
1747
|
const presets = {
|
|
1850
1748
|
auto: "auto",
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1749
|
+
min: "min-content",
|
|
1750
|
+
max: "max-content",
|
|
1751
|
+
fr: "minmax(0, 1fr)"
|
|
1854
1752
|
};
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
// ── Divide (child combinator CSS, web-only) ───────────────────────────────
|
|
1858
|
-
// These return special __divide* markers that resolver.ts converts to
|
|
1859
|
-
// .cls > * + * { border-... } CSS rules. No inline style is applied.
|
|
1860
|
-
"divide-x": ({ value, isArbitrary }) => {
|
|
1861
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1862
|
-
if (value === "reverse") return null;
|
|
1863
|
-
if (!value) return { __divideX: 1 };
|
|
1864
|
-
const n = parseFloat(value);
|
|
1865
|
-
return isNaN(n) ? null : { __divideX: n };
|
|
1866
|
-
},
|
|
1867
|
-
"divide-y": ({ value, isArbitrary }) => {
|
|
1868
|
-
if (!getEffectiveIsWeb()) return null;
|
|
1869
|
-
if (value === "reverse") return null;
|
|
1870
|
-
if (!value) return { __divideY: 1 };
|
|
1871
|
-
const n = parseFloat(value);
|
|
1872
|
-
return isNaN(n) ? null : { __divideY: n };
|
|
1753
|
+
const v = presets[value];
|
|
1754
|
+
return v ? { gridAutoColumns: v } : null;
|
|
1873
1755
|
},
|
|
1874
|
-
|
|
1756
|
+
"auto-rows": ({ value, isArbitrary }) => {
|
|
1875
1757
|
if (!getEffectiveIsWeb()) return null;
|
|
1876
|
-
if (isArbitrary) return {
|
|
1877
|
-
const
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
none: "none"
|
|
1883
|
-
};
|
|
1884
|
-
if (value in styleTokens) return { __divideStyle: styleTokens[value] };
|
|
1885
|
-
const color = resolveColor(value, colors, false);
|
|
1886
|
-
return color ? { __divideColor: color } : null;
|
|
1887
|
-
},
|
|
1888
|
-
// ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
|
|
1889
|
-
// Named presets give cross-platform shadow; arbitrary is web-only.
|
|
1890
|
-
"text-shadow": ({ value, isArbitrary }, { colors }) => {
|
|
1891
|
-
if (value === "none") {
|
|
1892
|
-
return getEffectiveIsWeb() ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
|
|
1893
|
-
}
|
|
1894
|
-
const webPresets = {
|
|
1895
|
-
"": "0 2px 4px rgba(0,0,0,0.3)",
|
|
1896
|
-
sm: "0 1px 2px rgba(0,0,0,0.3)",
|
|
1897
|
-
md: "0 4px 6px rgba(0,0,0,0.3)",
|
|
1898
|
-
lg: "0 8px 16px rgba(0,0,0,0.5)",
|
|
1899
|
-
xl: "0 16px 32px rgba(0,0,0,0.5)"
|
|
1900
|
-
};
|
|
1901
|
-
const nativePresets = {
|
|
1902
|
-
"": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
|
|
1903
|
-
sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
|
|
1904
|
-
md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
|
|
1905
|
-
lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
|
|
1906
|
-
xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
|
|
1758
|
+
if (isArbitrary) return { gridAutoRows: value };
|
|
1759
|
+
const presets = {
|
|
1760
|
+
auto: "auto",
|
|
1761
|
+
min: "min-content",
|
|
1762
|
+
max: "max-content",
|
|
1763
|
+
fr: "minmax(0, 1fr)"
|
|
1907
1764
|
};
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
return nativePresets[value] ?? null;
|
|
1911
|
-
}
|
|
1912
|
-
if (isArbitrary) {
|
|
1913
|
-
return getEffectiveIsWeb() ? { textShadow: value.replace(/_/g, " ") } : null;
|
|
1914
|
-
}
|
|
1915
|
-
const color = resolveColor(value, colors, false);
|
|
1916
|
-
if (color) {
|
|
1917
|
-
return getEffectiveIsWeb() ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
|
|
1918
|
-
}
|
|
1919
|
-
return null;
|
|
1765
|
+
const v = presets[value];
|
|
1766
|
+
return v ? { gridAutoRows: v } : null;
|
|
1920
1767
|
},
|
|
1921
|
-
// ──
|
|
1922
|
-
|
|
1923
|
-
if (
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
}
|
|
1928
|
-
if (value === "none") return getEffectiveIsWeb() ? { transform: "none" } : null;
|
|
1929
|
-
const n = parseFloat(value);
|
|
1930
|
-
if (isNaN(n)) return null;
|
|
1931
|
-
return getEffectiveIsWeb() ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
|
|
1768
|
+
// ── Grid column placement (web-only) ──────────────────────────────────────
|
|
1769
|
+
"col-span": ({ value }) => {
|
|
1770
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1771
|
+
if (value === "full") return { gridColumn: "1 / -1" };
|
|
1772
|
+
const n = parseInt(value, 10);
|
|
1773
|
+
return isNaN(n) ? null : { gridColumn: `span ${n} / span ${n}` };
|
|
1932
1774
|
},
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
if (
|
|
1936
|
-
|
|
1937
|
-
|
|
1775
|
+
"col-start": ({ value, isArbitrary }) => {
|
|
1776
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1777
|
+
if (value === "auto") return { gridColumnStart: "auto" };
|
|
1778
|
+
if (isArbitrary) return { gridColumnStart: value };
|
|
1779
|
+
const n = parseInt(value, 10);
|
|
1780
|
+
return isNaN(n) ? null : { gridColumnStart: n };
|
|
1938
1781
|
},
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1782
|
+
"col-end": ({ value, isArbitrary }) => {
|
|
1783
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1784
|
+
if (value === "auto") return { gridColumnEnd: "auto" };
|
|
1785
|
+
if (isArbitrary) return { gridColumnEnd: value };
|
|
1786
|
+
const n = parseInt(value, 10);
|
|
1787
|
+
return isNaN(n) ? null : { gridColumnEnd: n };
|
|
1943
1788
|
},
|
|
1944
|
-
|
|
1945
|
-
// Each variant injects a @keyframes rule once via the __keyframe marker.
|
|
1946
|
-
// resolver.ts detects __keyframe, injects the rule, then strips the marker
|
|
1947
|
-
// so it never reaches element inline styles.
|
|
1948
|
-
animate: ({ value, isArbitrary }, theme) => {
|
|
1789
|
+
col: ({ value, isArbitrary }) => {
|
|
1949
1790
|
if (!getEffectiveIsWeb()) return null;
|
|
1950
|
-
if (
|
|
1951
|
-
if (
|
|
1952
|
-
|
|
1953
|
-
return custom ? buildAnimationValue(custom, theme.keyframes) : null;
|
|
1791
|
+
if (!value || value === "auto") return { gridColumn: "auto" };
|
|
1792
|
+
if (isArbitrary) return { gridColumn: value };
|
|
1793
|
+
return null;
|
|
1954
1794
|
},
|
|
1955
|
-
// ──
|
|
1956
|
-
"
|
|
1795
|
+
// ── Grid row placement (web-only) ─────────────────────────────────────────
|
|
1796
|
+
"row-span": ({ value }) => {
|
|
1957
1797
|
if (!getEffectiveIsWeb()) return null;
|
|
1958
|
-
if (value === "
|
|
1798
|
+
if (value === "full") return { gridRow: "1 / -1" };
|
|
1959
1799
|
const n = parseInt(value, 10);
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1800
|
+
return isNaN(n) ? null : { gridRow: `span ${n} / span ${n}` };
|
|
1801
|
+
},
|
|
1802
|
+
"row-start": ({ value, isArbitrary }) => {
|
|
1803
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1804
|
+
if (value === "auto") return { gridRowStart: "auto" };
|
|
1805
|
+
if (isArbitrary) return { gridRowStart: value };
|
|
1806
|
+
const n = parseInt(value, 10);
|
|
1807
|
+
return isNaN(n) ? null : { gridRowStart: n };
|
|
1808
|
+
},
|
|
1809
|
+
"row-end": ({ value, isArbitrary }) => {
|
|
1810
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1811
|
+
if (value === "auto") return { gridRowEnd: "auto" };
|
|
1812
|
+
if (isArbitrary) return { gridRowEnd: value };
|
|
1813
|
+
const n = parseInt(value, 10);
|
|
1814
|
+
return isNaN(n) ? null : { gridRowEnd: n };
|
|
1815
|
+
},
|
|
1816
|
+
row: ({ value, isArbitrary }) => {
|
|
1817
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1818
|
+
if (!value || value === "auto") return { gridRow: "auto" };
|
|
1819
|
+
if (isArbitrary) return { gridRow: value };
|
|
1820
|
+
return null;
|
|
1821
|
+
},
|
|
1822
|
+
// ── Grid alignment (web-only) ──────────────────────────────────────────────
|
|
1823
|
+
// place-items is shorthand for align-items + justify-items on a grid container
|
|
1824
|
+
"place-items": ({ value }) => {
|
|
1825
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1826
|
+
const map = {
|
|
1827
|
+
start: "start",
|
|
1828
|
+
end: "end",
|
|
1829
|
+
center: "center",
|
|
1830
|
+
stretch: "stretch",
|
|
1831
|
+
baseline: "baseline"
|
|
1966
1832
|
};
|
|
1833
|
+
return map[value] ? { placeItems: map[value] } : null;
|
|
1967
1834
|
},
|
|
1968
|
-
//
|
|
1969
|
-
|
|
1835
|
+
// place-content is shorthand for align-content + justify-content on a grid container
|
|
1836
|
+
"place-content": ({ value }) => {
|
|
1970
1837
|
if (!getEffectiveIsWeb()) return null;
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1838
|
+
const map = {
|
|
1839
|
+
start: "start",
|
|
1840
|
+
end: "end",
|
|
1841
|
+
center: "center",
|
|
1842
|
+
stretch: "stretch",
|
|
1843
|
+
between: "space-between",
|
|
1844
|
+
around: "space-around",
|
|
1845
|
+
evenly: "space-evenly",
|
|
1846
|
+
baseline: "baseline"
|
|
1847
|
+
};
|
|
1848
|
+
return map[value] ? { placeContent: map[value] } : null;
|
|
1974
1849
|
},
|
|
1975
|
-
//
|
|
1976
|
-
|
|
1850
|
+
// justify-items controls inline-axis alignment of grid items within their cells
|
|
1851
|
+
"justify-items": ({ value }) => {
|
|
1977
1852
|
if (!getEffectiveIsWeb()) return null;
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1853
|
+
const map = {
|
|
1854
|
+
start: "start",
|
|
1855
|
+
end: "end",
|
|
1856
|
+
center: "center",
|
|
1857
|
+
stretch: "stretch"
|
|
1858
|
+
};
|
|
1859
|
+
return map[value] ? { justifyItems: map[value] } : null;
|
|
1981
1860
|
},
|
|
1982
|
-
//
|
|
1983
|
-
|
|
1984
|
-
// take stroke/fill as component PROPS, not style entries, so there's no
|
|
1985
|
-
// reliable way to apply a resolved color through the `style` prop there.
|
|
1986
|
-
// `stroke-{n}` sets strokeWidth (a plain number, unlike a color) — same
|
|
1987
|
-
// color-first-then-numeric-fallback disambiguation `border` uses above.
|
|
1988
|
-
stroke: ({ value, isArbitrary }, { colors }) => {
|
|
1861
|
+
// place-self is shorthand for align-self + justify-self on a grid item
|
|
1862
|
+
"place-self": ({ value }) => {
|
|
1989
1863
|
if (!getEffectiveIsWeb()) return null;
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
const n = parseFloat(value);
|
|
1999
|
-
return isNaN(n) ? null : { strokeWidth: n };
|
|
1864
|
+
const map = {
|
|
1865
|
+
auto: "auto",
|
|
1866
|
+
start: "start",
|
|
1867
|
+
end: "end",
|
|
1868
|
+
center: "center",
|
|
1869
|
+
stretch: "stretch"
|
|
1870
|
+
};
|
|
1871
|
+
return map[value] ? { placeSelf: map[value] } : null;
|
|
2000
1872
|
},
|
|
2001
|
-
|
|
1873
|
+
// justify-self controls inline-axis self-alignment of a grid item
|
|
1874
|
+
"justify-self": ({ value }) => {
|
|
2002
1875
|
if (!getEffectiveIsWeb()) return null;
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
1876
|
+
const map = {
|
|
1877
|
+
auto: "auto",
|
|
1878
|
+
start: "start",
|
|
1879
|
+
end: "end",
|
|
1880
|
+
center: "center",
|
|
1881
|
+
stretch: "stretch"
|
|
1882
|
+
};
|
|
1883
|
+
return map[value] ? { justifySelf: map[value] } : null;
|
|
2008
1884
|
},
|
|
2009
1885
|
// ── Flex ───────────────────────────────────────────────────────────────────
|
|
2010
1886
|
flex: ({ value, isArbitrary }, { flex }) => {
|
|
@@ -2025,10 +1901,6 @@ var RESOLVERS = {
|
|
|
2025
1901
|
const n = parseFloat(value);
|
|
2026
1902
|
return isNaN(n) ? null : { flex: n };
|
|
2027
1903
|
},
|
|
2028
|
-
basis: ({ value, isArbitrary }, { spacing }) => {
|
|
2029
|
-
const v = resolveSizing(value, spacing, isArbitrary);
|
|
2030
|
-
return v !== null ? { flexBasis: v } : null;
|
|
2031
|
-
},
|
|
2032
1904
|
grow: ({ value }, _) => {
|
|
2033
1905
|
if (!value) return { flexGrow: 1 };
|
|
2034
1906
|
const n = parseFloat(value);
|
|
@@ -2043,72 +1915,132 @@ var RESOLVERS = {
|
|
|
2043
1915
|
const n = parseInt(value, 10);
|
|
2044
1916
|
return isNaN(n) ? null : { order: negative ? -n : n };
|
|
2045
1917
|
},
|
|
2046
|
-
// ── Gap ────────────────────────────────────────────────────────────────────
|
|
2047
|
-
gap: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2048
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2049
|
-
return v !== null ? { gap: v } : null;
|
|
2050
|
-
},
|
|
2051
|
-
"gap-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2052
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2053
|
-
return v !== null ? { columnGap: v } : null;
|
|
2054
|
-
},
|
|
2055
|
-
"gap-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2056
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2057
|
-
return v !== null ? { rowGap: v } : null;
|
|
2058
|
-
},
|
|
2059
|
-
// ── Position ───────────────────────────────────────────────────────────────
|
|
2060
|
-
top: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2061
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2062
|
-
return v !== null ? { top: v } : null;
|
|
2063
|
-
},
|
|
2064
|
-
right: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2065
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2066
|
-
return v !== null ? { right: v } : null;
|
|
2067
|
-
},
|
|
2068
|
-
bottom: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2069
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2070
|
-
return v !== null ? { bottom: v } : null;
|
|
2071
|
-
},
|
|
2072
|
-
left: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2073
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2074
|
-
return v !== null ? { left: v } : null;
|
|
2075
|
-
},
|
|
2076
|
-
inset: ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2077
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2078
|
-
return v !== null ? { top: v, right: v, bottom: v, left: v } : null;
|
|
2079
|
-
},
|
|
2080
|
-
"inset-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2081
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2082
|
-
return v !== null ? { left: v, right: v } : null;
|
|
2083
|
-
},
|
|
2084
|
-
"inset-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2085
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2086
|
-
return v !== null ? { top: v, bottom: v } : null;
|
|
2087
|
-
},
|
|
2088
1918
|
// ── Z-index ────────────────────────────────────────────────────────────────
|
|
2089
1919
|
z: ({ value, isArbitrary }, { zIndex }) => {
|
|
2090
1920
|
if (isArbitrary) {
|
|
2091
|
-
const n2 = parseInt(value);
|
|
2092
|
-
return isNaN(n2) ? null : { zIndex: n2 };
|
|
2093
|
-
}
|
|
2094
|
-
const v = zIndex[value];
|
|
2095
|
-
if (v !== void 0) {
|
|
2096
|
-
if (v === "auto") return getEffectiveIsWeb() ? { zIndex: "auto" } : null;
|
|
2097
|
-
return { zIndex: v };
|
|
1921
|
+
const n2 = parseInt(value);
|
|
1922
|
+
return isNaN(n2) ? null : { zIndex: n2 };
|
|
1923
|
+
}
|
|
1924
|
+
const v = zIndex[value];
|
|
1925
|
+
if (v !== void 0) {
|
|
1926
|
+
if (v === "auto") return getEffectiveIsWeb() ? { zIndex: "auto" } : null;
|
|
1927
|
+
return { zIndex: v };
|
|
1928
|
+
}
|
|
1929
|
+
const n = parseInt(value);
|
|
1930
|
+
return isNaN(n) ? null : { zIndex: n };
|
|
1931
|
+
},
|
|
1932
|
+
// ── Aspect ratio ───────────────────────────────────────────────────────────
|
|
1933
|
+
aspect: ({ value, isArbitrary }) => {
|
|
1934
|
+
if (isArbitrary) return { aspectRatio: value };
|
|
1935
|
+
const presets = { auto: "auto", square: 1, video: 16 / 9 };
|
|
1936
|
+
if (!(value in presets)) return null;
|
|
1937
|
+
const v = presets[value];
|
|
1938
|
+
if (v === "auto") return getEffectiveIsWeb() ? { aspectRatio: "auto" } : null;
|
|
1939
|
+
return { aspectRatio: v };
|
|
1940
|
+
},
|
|
1941
|
+
// ── Columns (web-only) ─────────────────────────────────────────────────────
|
|
1942
|
+
columns: ({ value, isArbitrary }) => {
|
|
1943
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1944
|
+
if (isArbitrary) return { columnCount: value };
|
|
1945
|
+
if (value === "auto") return { columnCount: "auto" };
|
|
1946
|
+
const n = parseInt(value, 10);
|
|
1947
|
+
if (!isNaN(n)) return { columnCount: n };
|
|
1948
|
+
const widths = {
|
|
1949
|
+
"3xs": "16rem",
|
|
1950
|
+
"2xs": "18rem",
|
|
1951
|
+
xs: "20rem",
|
|
1952
|
+
sm: "24rem",
|
|
1953
|
+
md: "28rem",
|
|
1954
|
+
lg: "32rem",
|
|
1955
|
+
xl: "36rem",
|
|
1956
|
+
"2xl": "42rem",
|
|
1957
|
+
"3xl": "48rem",
|
|
1958
|
+
"4xl": "56rem",
|
|
1959
|
+
"5xl": "64rem",
|
|
1960
|
+
"6xl": "72rem",
|
|
1961
|
+
"7xl": "80rem"
|
|
1962
|
+
};
|
|
1963
|
+
return widths[value] ? { columnWidth: widths[value] } : null;
|
|
1964
|
+
}
|
|
1965
|
+
};
|
|
1966
|
+
|
|
1967
|
+
// src/core/resolvers/typography.ts
|
|
1968
|
+
function resolveFontSize(value, fontSizes, isArbitrary) {
|
|
1969
|
+
if (isArbitrary) return getEffectiveIsWeb() ? value : toNativeValue(value);
|
|
1970
|
+
return fontSizes[value] ?? null;
|
|
1971
|
+
}
|
|
1972
|
+
var typographyResolvers = {
|
|
1973
|
+
// ── Text ───────────────────────────────────────────────────────────────────
|
|
1974
|
+
text: ({ value, isArbitrary }, { colors, fontSize }) => {
|
|
1975
|
+
const size = resolveFontSize(value, fontSize, false);
|
|
1976
|
+
if (!isArbitrary && size !== null) return { fontSize: size };
|
|
1977
|
+
if (isArbitrary) {
|
|
1978
|
+
if (/^\d/.test(value) || /^(calc|min|max|clamp)/.test(value)) {
|
|
1979
|
+
return { fontSize: getEffectiveIsWeb() ? value : toNativeValue(value) };
|
|
1980
|
+
}
|
|
1981
|
+
return { color: getEffectiveIsWeb() ? withOpacityVar(value, "--text-opacity") : value };
|
|
2098
1982
|
}
|
|
2099
|
-
const
|
|
2100
|
-
|
|
1983
|
+
const color = resolveColor(value, colors, false);
|
|
1984
|
+
if (!color) return null;
|
|
1985
|
+
return { color: getEffectiveIsWeb() ? withOpacityVar(color, "--text-opacity") : color };
|
|
2101
1986
|
},
|
|
2102
|
-
|
|
2103
|
-
|
|
1987
|
+
"text-opacity": ({ value, isArbitrary }, _) => {
|
|
1988
|
+
if (!getEffectiveIsWeb()) return null;
|
|
1989
|
+
const n = parseFloat(value);
|
|
1990
|
+
if (isNaN(n)) return null;
|
|
1991
|
+
const v = isArbitrary ? n > 1 ? n / 100 : n : n / 100;
|
|
1992
|
+
return { "--text-opacity": v };
|
|
1993
|
+
},
|
|
1994
|
+
// ── Text decoration advanced (web-only) ───────────────────────────────────
|
|
1995
|
+
decoration: ({ value, isArbitrary }, { colors }) => {
|
|
1996
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2104
1997
|
if (isArbitrary) {
|
|
2105
|
-
|
|
2106
|
-
return
|
|
1998
|
+
if (/^\d/.test(value) || value.startsWith("calc(")) return { textDecorationThickness: value };
|
|
1999
|
+
return { textDecorationColor: value };
|
|
2107
2000
|
}
|
|
2108
|
-
const
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2001
|
+
const thickTokens = {
|
|
2002
|
+
auto: "auto",
|
|
2003
|
+
"from-font": "from-font",
|
|
2004
|
+
"0": "0px",
|
|
2005
|
+
"1": "1px",
|
|
2006
|
+
"2": "2px",
|
|
2007
|
+
"4": "4px",
|
|
2008
|
+
"8": "8px"
|
|
2009
|
+
};
|
|
2010
|
+
if (value in thickTokens) return { textDecorationThickness: thickTokens[value] };
|
|
2011
|
+
const styleTokens = {
|
|
2012
|
+
solid: "solid",
|
|
2013
|
+
dashed: "dashed",
|
|
2014
|
+
dotted: "dotted",
|
|
2015
|
+
double: "double",
|
|
2016
|
+
wavy: "wavy"
|
|
2017
|
+
};
|
|
2018
|
+
if (value in styleTokens) return { textDecorationStyle: styleTokens[value] };
|
|
2019
|
+
const color = resolveColor(value, colors, false);
|
|
2020
|
+
return color ? { textDecorationColor: color } : null;
|
|
2021
|
+
},
|
|
2022
|
+
"underline-offset": ({ value, isArbitrary }) => {
|
|
2023
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2024
|
+
if (isArbitrary) return { textUnderlineOffset: value };
|
|
2025
|
+
const offsets = {
|
|
2026
|
+
auto: "auto",
|
|
2027
|
+
"0": "0px",
|
|
2028
|
+
"1": "1px",
|
|
2029
|
+
"2": "2px",
|
|
2030
|
+
"4": "4px",
|
|
2031
|
+
"8": "8px"
|
|
2032
|
+
};
|
|
2033
|
+
return offsets[value] ? { textUnderlineOffset: offsets[value] } : null;
|
|
2034
|
+
},
|
|
2035
|
+
// ── Content (web-only — for before:/after: pseudo-elements, which don't exist on native) ──
|
|
2036
|
+
// Arbitrary value carries its own quotes from the bracket syntax (content-['*'] parses to
|
|
2037
|
+
// the literal string 'you can see it' quotes included), so it passes straight through as a
|
|
2038
|
+
// valid `content: '*'` CSS value with no extra wrapping needed.
|
|
2039
|
+
content: ({ value, isArbitrary }) => {
|
|
2040
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2041
|
+
if (isArbitrary) return { content: value };
|
|
2042
|
+
const presets = { none: "none" };
|
|
2043
|
+
return value in presets ? { content: presets[value] } : null;
|
|
2112
2044
|
},
|
|
2113
2045
|
// ── Font ───────────────────────────────────────────────────────────────────
|
|
2114
2046
|
font: ({ value, isArbitrary }, { fontFamily, fontWeight }) => {
|
|
@@ -2134,10 +2066,57 @@ var RESOLVERS = {
|
|
|
2134
2066
|
const v = letterSpacing[value];
|
|
2135
2067
|
return v !== void 0 ? { letterSpacing: v } : null;
|
|
2136
2068
|
},
|
|
2137
|
-
// ──
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
return
|
|
2069
|
+
// ── Line-clamp (web-only) ─────────────────────────────────────────────────
|
|
2070
|
+
"line-clamp": ({ value }) => {
|
|
2071
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2072
|
+
if (value === "none") return { overflow: "visible", display: "block", WebkitLineClamp: "unset" };
|
|
2073
|
+
const n = parseInt(value, 10);
|
|
2074
|
+
if (isNaN(n) || n < 1) return null;
|
|
2075
|
+
return {
|
|
2076
|
+
overflow: "hidden",
|
|
2077
|
+
display: "-webkit-box",
|
|
2078
|
+
WebkitBoxOrient: "vertical",
|
|
2079
|
+
WebkitLineClamp: n
|
|
2080
|
+
};
|
|
2081
|
+
}
|
|
2082
|
+
};
|
|
2083
|
+
|
|
2084
|
+
// src/core/resolvers/transform.ts
|
|
2085
|
+
var transformResolvers = {
|
|
2086
|
+
// ── Transform extras (web-only) ───────────────────────────────────────────
|
|
2087
|
+
"skew-x": ({ value, negative, isArbitrary }) => {
|
|
2088
|
+
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
2089
|
+
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2090
|
+
return getEffectiveIsWeb() ? { transform: `skewX(${deg})` } : { transform: [{ skewX: deg }] };
|
|
2091
|
+
},
|
|
2092
|
+
"skew-y": ({ value, negative, isArbitrary }) => {
|
|
2093
|
+
const deg = isArbitrary ? value : `${(negative ? -1 : 1) * parseFloat(value)}deg`;
|
|
2094
|
+
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2095
|
+
return getEffectiveIsWeb() ? { transform: `skewY(${deg})` } : { transform: [{ skewY: deg }] };
|
|
2096
|
+
},
|
|
2097
|
+
// Arbitrary full transform string: transform-[rotate(45deg)_scale(1.5)]
|
|
2098
|
+
transform: ({ value, isArbitrary }) => {
|
|
2099
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2100
|
+
if (isArbitrary) return { transform: value.replace(/_/g, " ") };
|
|
2101
|
+
if (value === "none") return { transform: "none" };
|
|
2102
|
+
return null;
|
|
2103
|
+
},
|
|
2104
|
+
// Transform origin
|
|
2105
|
+
origin: ({ value, isArbitrary }) => {
|
|
2106
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2107
|
+
if (isArbitrary) return { transformOrigin: value.replace(/_/g, " ") };
|
|
2108
|
+
const origins = {
|
|
2109
|
+
center: "center",
|
|
2110
|
+
top: "top",
|
|
2111
|
+
"top-right": "top right",
|
|
2112
|
+
right: "right",
|
|
2113
|
+
"bottom-right": "bottom right",
|
|
2114
|
+
bottom: "bottom",
|
|
2115
|
+
"bottom-left": "bottom left",
|
|
2116
|
+
left: "left",
|
|
2117
|
+
"top-left": "top left"
|
|
2118
|
+
};
|
|
2119
|
+
return origins[value] ? { transformOrigin: origins[value] } : null;
|
|
2141
2120
|
},
|
|
2142
2121
|
// ── Scale ──────────────────────────────────────────────────────────────────
|
|
2143
2122
|
// Non-arbitrary: scale-150 → value='150' → 150/100 = 1.5
|
|
@@ -2168,35 +2147,86 @@ var RESOLVERS = {
|
|
|
2168
2147
|
const finalDeg = negative ? -deg : deg;
|
|
2169
2148
|
return getEffectiveIsWeb() ? { transform: `rotate(${finalDeg}deg)` } : { transform: [{ rotate: `${finalDeg}deg` }] };
|
|
2170
2149
|
},
|
|
2171
|
-
// ──
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
const n = parseFloat(v);
|
|
2178
|
-
return isNaN(n) ? null : { transform: [{ translateX: n }] };
|
|
2150
|
+
// ── Perspective transform (cross-platform: iOS, Android, web) ────────────
|
|
2151
|
+
perspective: ({ value, isArbitrary }) => {
|
|
2152
|
+
if (isArbitrary) {
|
|
2153
|
+
const numPx = parseFloat(value);
|
|
2154
|
+
if (getEffectiveIsWeb()) return { transform: `perspective(${value})` };
|
|
2155
|
+
return isNaN(numPx) ? null : { transform: [{ perspective: numPx }] };
|
|
2179
2156
|
}
|
|
2180
|
-
return
|
|
2157
|
+
if (value === "none") return getEffectiveIsWeb() ? { transform: "none" } : null;
|
|
2158
|
+
const n = parseFloat(value);
|
|
2159
|
+
if (isNaN(n)) return null;
|
|
2160
|
+
return getEffectiveIsWeb() ? { transform: `perspective(${n}px)` } : { transform: [{ perspective: n }] };
|
|
2161
|
+
}
|
|
2162
|
+
};
|
|
2163
|
+
|
|
2164
|
+
// src/core/resolvers/effects.ts
|
|
2165
|
+
function keyframeDeclToCSS(decl) {
|
|
2166
|
+
return Object.entries(decl).map(([prop, val]) => `${prop.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${val}`).join("; ");
|
|
2167
|
+
}
|
|
2168
|
+
function buildKeyframeCSS(name, steps) {
|
|
2169
|
+
const body = Object.entries(steps).map(([selector, decl]) => `${selector} { ${keyframeDeclToCSS(decl)} }`).join(" ");
|
|
2170
|
+
return `@keyframes ${name} { ${body} }`;
|
|
2171
|
+
}
|
|
2172
|
+
var BUILTIN_ANIMATIONS = {
|
|
2173
|
+
none: { animation: "none" },
|
|
2174
|
+
spin: {
|
|
2175
|
+
animation: "kb-spin 1s linear infinite",
|
|
2176
|
+
__keyframe: "@keyframes kb-spin { from { transform: rotate(0deg) } to { transform: rotate(360deg) } }"
|
|
2181
2177
|
},
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2178
|
+
ping: {
|
|
2179
|
+
animation: "kb-ping 1s cubic-bezier(0,0,0.2,1) infinite",
|
|
2180
|
+
__keyframe: "@keyframes kb-ping { 75%, 100% { transform: scale(2); opacity: 0 } }"
|
|
2181
|
+
},
|
|
2182
|
+
pulse: {
|
|
2183
|
+
animation: "kb-pulse 2s cubic-bezier(0.4,0,0.6,1) infinite",
|
|
2184
|
+
__keyframe: "@keyframes kb-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .5 } }"
|
|
2185
|
+
},
|
|
2186
|
+
bounce: {
|
|
2187
|
+
animation: "kb-bounce 1s infinite",
|
|
2188
|
+
__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) } }"
|
|
2189
|
+
}
|
|
2190
|
+
};
|
|
2191
|
+
function buildAnimationValue(animation, keyframes) {
|
|
2192
|
+
const words = animation.trim().split(/\s+/);
|
|
2193
|
+
const name = words[0];
|
|
2194
|
+
if (!name) return { animation };
|
|
2195
|
+
const builtin = BUILTIN_ANIMATIONS[name];
|
|
2196
|
+
if (builtin?.__keyframe) {
|
|
2197
|
+
const kbName = builtin.animation.split(/\s+/, 1)[0];
|
|
2198
|
+
return { animation: [kbName, ...words.slice(1)].join(" "), __keyframe: builtin.__keyframe };
|
|
2199
|
+
}
|
|
2200
|
+
const steps = keyframes?.[name];
|
|
2201
|
+
return steps ? { animation, __keyframe: buildKeyframeCSS(name, steps) } : { animation };
|
|
2202
|
+
}
|
|
2203
|
+
var effectResolvers = {
|
|
2204
|
+
// ── Opacity ────────────────────────────────────────────────────────────────
|
|
2205
|
+
opacity: ({ value, isArbitrary }, { opacity }) => {
|
|
2206
|
+
if (isArbitrary) {
|
|
2207
|
+
const v2 = parseFloat(value);
|
|
2208
|
+
return isNaN(v2) ? null : { opacity: v2 > 1 ? v2 / 100 : v2 };
|
|
2189
2209
|
}
|
|
2190
|
-
|
|
2210
|
+
const v = opacity[value];
|
|
2211
|
+
if (v !== void 0) return { opacity: v };
|
|
2212
|
+
const n = parseFloat(value);
|
|
2213
|
+
return isNaN(n) ? null : { opacity: n > 1 ? n / 100 : n };
|
|
2191
2214
|
},
|
|
2192
|
-
// ──
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2215
|
+
// ── Shadow ─────────────────────────────────────────────────────────────────
|
|
2216
|
+
shadow: ({ value }, { shadow }) => {
|
|
2217
|
+
const key = value === "" ? "DEFAULT" : value;
|
|
2218
|
+
return shadow[key] ?? null;
|
|
2219
|
+
},
|
|
2220
|
+
// ── Animations (CSS keyframe animations, web-only) ────────────────────────
|
|
2221
|
+
// Each variant injects a @keyframes rule once via the __keyframe marker.
|
|
2222
|
+
// resolver.ts detects __keyframe, injects the rule, then strips the marker
|
|
2223
|
+
// so it never reaches element inline styles.
|
|
2224
|
+
animate: ({ value, isArbitrary }, theme) => {
|
|
2225
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2226
|
+
if (isArbitrary) return buildAnimationValue(value.replace(/_/g, " "), theme.keyframes);
|
|
2227
|
+
if (value in BUILTIN_ANIMATIONS) return BUILTIN_ANIMATIONS[value];
|
|
2228
|
+
const custom = theme.animation?.[value];
|
|
2229
|
+
return custom ? buildAnimationValue(custom, theme.keyframes) : null;
|
|
2200
2230
|
},
|
|
2201
2231
|
// ── Transition (web-only; use Animated API on native) ─────────────────────
|
|
2202
2232
|
transition: ({ value }) => {
|
|
@@ -2224,91 +2254,107 @@ var RESOLVERS = {
|
|
|
2224
2254
|
if (!isArbitrary && isNaN(parseFloat(value))) return null;
|
|
2225
2255
|
const ms = isArbitrary ? value : `${value}ms`;
|
|
2226
2256
|
return { transitionDelay: ms };
|
|
2257
|
+
}
|
|
2258
|
+
};
|
|
2259
|
+
|
|
2260
|
+
// src/core/resolvers/misc.ts
|
|
2261
|
+
var miscResolvers = {
|
|
2262
|
+
// ── Arbitrary CSS property (web-only): [property:value] with no utility prefix ──
|
|
2263
|
+
// e.g. [mask-type:luminance], [--my-var:10px]. parser.ts already isolates this case
|
|
2264
|
+
// as utility: '' — it's ALSO how a stray, prefix-less negative bracket ("-[10px]",
|
|
2265
|
+
// presumably a typo) parses, which is why this only fires when the arbitrary value
|
|
2266
|
+
// itself contains a "property:value" pair; anything else (no colon) still resolves
|
|
2267
|
+
// to null exactly as before this resolver existed, rather than guessing a property.
|
|
2268
|
+
//
|
|
2269
|
+
// Only the FIRST colon splits property from value — the value itself may contain
|
|
2270
|
+
// more colons (a URL's "http://…") and must stay intact: [background:url(http://x/a.png)].
|
|
2271
|
+
// camelToKebab() in resolver.ts is a no-op on an already-kebab-case (or "--"-prefixed
|
|
2272
|
+
// custom property) key, so it can be used as the style object key as-written with no
|
|
2273
|
+
// extra case conversion — it only needs to look like a plausible CSS property name.
|
|
2274
|
+
"": ({ value, isArbitrary, negative }) => {
|
|
2275
|
+
if (!getEffectiveIsWeb() || !isArbitrary || !value) return null;
|
|
2276
|
+
if (negative) return null;
|
|
2277
|
+
const colonIdx = value.indexOf(":");
|
|
2278
|
+
if (colonIdx <= 0) return null;
|
|
2279
|
+
const prop = value.slice(0, colonIdx).trim();
|
|
2280
|
+
const cssValue = value.slice(colonIdx + 1).trim();
|
|
2281
|
+
if (!cssValue || !/^(--[\w-]+|[a-zA-Z-]+)$/.test(prop)) return null;
|
|
2282
|
+
return { [prop]: cssValue };
|
|
2227
2283
|
},
|
|
2228
|
-
// ──
|
|
2229
|
-
//
|
|
2230
|
-
//
|
|
2231
|
-
//
|
|
2232
|
-
//
|
|
2233
|
-
//
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
if (!value) {
|
|
2242
|
-
return onWeb ? { boxShadow: `0 0 0 ${DEFAULT_WIDTH}px ${DEFAULT_COLOR}` } : asNative(DEFAULT_WIDTH, DEFAULT_COLOR);
|
|
2284
|
+
// ── SVG stroke/fill (web-only) ────────────────────────────────────────────
|
|
2285
|
+
// Native is intentionally excluded: react-native-svg's <Path>/<Circle>/etc.
|
|
2286
|
+
// take stroke/fill as component PROPS, not style entries, so there's no
|
|
2287
|
+
// reliable way to apply a resolved color through the `style` prop there.
|
|
2288
|
+
// `stroke-{n}` sets strokeWidth (a plain number, unlike a color) — same
|
|
2289
|
+
// color-first-then-numeric-fallback disambiguation `border` uses above.
|
|
2290
|
+
stroke: ({ value, isArbitrary }, { colors }) => {
|
|
2291
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2292
|
+
if (!value) return null;
|
|
2293
|
+
if (value === "none") return { stroke: "none" };
|
|
2294
|
+
if (isArbitrary) {
|
|
2295
|
+
const w = toNativeValue(value);
|
|
2296
|
+
return typeof w === "number" ? { strokeWidth: w } : { stroke: value };
|
|
2243
2297
|
}
|
|
2244
|
-
|
|
2245
|
-
|
|
2298
|
+
const color = resolveColor(value, colors, false);
|
|
2299
|
+
if (color) return { stroke: color };
|
|
2300
|
+
const n = parseFloat(value);
|
|
2301
|
+
return isNaN(n) ? null : { strokeWidth: n };
|
|
2302
|
+
},
|
|
2303
|
+
fill: ({ value, isArbitrary }, { colors }) => {
|
|
2304
|
+
if (!getEffectiveIsWeb()) return null;
|
|
2305
|
+
if (!value) return null;
|
|
2306
|
+
if (value === "none") return { fill: "none" };
|
|
2307
|
+
if (isArbitrary) return { fill: value };
|
|
2308
|
+
const color = resolveColor(value, colors, false);
|
|
2309
|
+
return color ? { fill: color } : null;
|
|
2310
|
+
},
|
|
2311
|
+
// ── Text shadow (cross-platform: iOS, Android, web) ─────────────────────
|
|
2312
|
+
// Named presets give cross-platform shadow; arbitrary is web-only.
|
|
2313
|
+
"text-shadow": ({ value, isArbitrary }, { colors }) => {
|
|
2314
|
+
if (value === "none") {
|
|
2315
|
+
return getEffectiveIsWeb() ? { textShadow: "none" } : { textShadowColor: "transparent", textShadowOffset: { width: 0, height: 0 }, textShadowRadius: 0 };
|
|
2246
2316
|
}
|
|
2247
|
-
const
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2317
|
+
const webPresets = {
|
|
2318
|
+
"": "0 2px 4px rgba(0,0,0,0.3)",
|
|
2319
|
+
sm: "0 1px 2px rgba(0,0,0,0.3)",
|
|
2320
|
+
md: "0 4px 6px rgba(0,0,0,0.3)",
|
|
2321
|
+
lg: "0 8px 16px rgba(0,0,0,0.5)",
|
|
2322
|
+
xl: "0 16px 32px rgba(0,0,0,0.5)"
|
|
2323
|
+
};
|
|
2324
|
+
const nativePresets = {
|
|
2325
|
+
"": { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 2 }, textShadowRadius: 4 },
|
|
2326
|
+
sm: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 1 }, textShadowRadius: 2 },
|
|
2327
|
+
md: { textShadowColor: "rgba(0,0,0,0.3)", textShadowOffset: { width: 0, height: 4 }, textShadowRadius: 6 },
|
|
2328
|
+
lg: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 8 }, textShadowRadius: 16 },
|
|
2329
|
+
xl: { textShadowColor: "rgba(0,0,0,0.5)", textShadowOffset: { width: 0, height: 16 }, textShadowRadius: 32 }
|
|
2330
|
+
};
|
|
2331
|
+
if (value in webPresets) {
|
|
2332
|
+
if (getEffectiveIsWeb()) return { textShadow: webPresets[value] };
|
|
2333
|
+
return nativePresets[value] ?? null;
|
|
2251
2334
|
}
|
|
2252
2335
|
if (isArbitrary) {
|
|
2253
|
-
|
|
2254
|
-
if (numMatch) {
|
|
2255
|
-
const unit = numMatch[2] ?? "px";
|
|
2256
|
-
if (onWeb) return { boxShadow: `0 0 0 ${numMatch[1]}${unit} ${DEFAULT_COLOR}` };
|
|
2257
|
-
return unit === "px" ? asNative(parseFloat(numMatch[1]), DEFAULT_COLOR) : null;
|
|
2258
|
-
}
|
|
2259
|
-
return onWeb ? { boxShadow: value.replace(/_/g, " ") } : null;
|
|
2336
|
+
return getEffectiveIsWeb() ? { textShadow: value.replace(/_/g, " ") } : null;
|
|
2260
2337
|
}
|
|
2261
2338
|
const color = resolveColor(value, colors, false);
|
|
2262
2339
|
if (color) {
|
|
2263
|
-
return
|
|
2340
|
+
return getEffectiveIsWeb() ? { textShadow: `0 2px 4px ${color}` } : { textShadowColor: color };
|
|
2264
2341
|
}
|
|
2265
2342
|
return null;
|
|
2266
|
-
},
|
|
2267
|
-
// Web-only, unlike `ring` above: this stacks a second box-shadow layer to
|
|
2268
|
-
// create a gap between the element and the ring. There's no native
|
|
2269
|
-
// equivalent to approximate that with (a border can't create a gap outside
|
|
2270
|
-
// its own element without an extra wrapper view), so this stays a no-op
|
|
2271
|
-
// on native rather than rendering a misleading half-translation.
|
|
2272
|
-
"ring-offset": ({ value, isArbitrary }, _theme) => {
|
|
2273
|
-
if (!getEffectiveIsWeb()) return null;
|
|
2274
|
-
const DEFAULT_RING_COLOR = "rgba(59, 130, 246, 0.5)";
|
|
2275
|
-
const DEFAULT_RING_WIDTH = 3;
|
|
2276
|
-
const offsetTokens = { "0": 0, "1": 1, "2": 2, "4": 4, "8": 8 };
|
|
2277
|
-
let offsetWidth;
|
|
2278
|
-
if (!isArbitrary) {
|
|
2279
|
-
offsetWidth = value in offsetTokens ? offsetTokens[value] : null;
|
|
2280
|
-
} else {
|
|
2281
|
-
offsetWidth = /^-?\d+(\.\d+)?$/.test(value) ? parseFloat(value) : value;
|
|
2282
|
-
}
|
|
2283
|
-
if (offsetWidth === null || typeof offsetWidth === "number" && isNaN(offsetWidth)) return null;
|
|
2284
|
-
const isZero = offsetWidth === 0 || offsetWidth === "0";
|
|
2285
|
-
const offsetCss = typeof offsetWidth === "number" ? `${offsetWidth}px` : offsetWidth;
|
|
2286
|
-
return {
|
|
2287
|
-
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}`
|
|
2288
|
-
};
|
|
2289
|
-
},
|
|
2290
|
-
// ── Space between ─────────────────────────────────────────────────────────
|
|
2291
|
-
// On web: emits __spaceX/__spaceY markers → resolver generates > * + * CSS rules.
|
|
2292
|
-
// On native (RN 0.71+): uses columnGap/rowGap directly.
|
|
2293
|
-
"space-x": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2294
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2295
|
-
if (v === null) return null;
|
|
2296
|
-
if (getEffectiveIsWeb()) return { __spaceX: v };
|
|
2297
|
-
return { columnGap: v };
|
|
2298
|
-
},
|
|
2299
|
-
"space-y": ({ value, negative, isArbitrary }, { spacing }) => {
|
|
2300
|
-
const v = resolveSpacing(value, negative, spacing, isArbitrary);
|
|
2301
|
-
if (v === null) return null;
|
|
2302
|
-
if (getEffectiveIsWeb()) return { __spaceY: v };
|
|
2303
|
-
return { rowGap: v };
|
|
2304
2343
|
}
|
|
2305
2344
|
};
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2345
|
+
|
|
2346
|
+
// src/core/utilities.ts
|
|
2347
|
+
var RESOLVERS = {
|
|
2348
|
+
...colorResolvers,
|
|
2349
|
+
...spacingResolvers,
|
|
2350
|
+
...borderResolvers,
|
|
2351
|
+
...layoutResolvers,
|
|
2352
|
+
...typographyResolvers,
|
|
2353
|
+
...filterResolvers,
|
|
2354
|
+
...transformResolvers,
|
|
2355
|
+
...effectResolvers,
|
|
2356
|
+
...miscResolvers
|
|
2357
|
+
};
|
|
2312
2358
|
var NAMED_GROUP_PEER_MARKER_RE = /^(group|peer)\/.+$/;
|
|
2313
2359
|
function resolveUtility(parsed, theme) {
|
|
2314
2360
|
if (!parsed.value) {
|
|
@@ -2356,6 +2402,47 @@ function kbachWarn(message) {
|
|
|
2356
2402
|
);
|
|
2357
2403
|
}
|
|
2358
2404
|
|
|
2405
|
+
// src/core/cache.ts
|
|
2406
|
+
var LRUCache = class {
|
|
2407
|
+
constructor(capacity = 1e4, onEvict) {
|
|
2408
|
+
this.capacity = capacity;
|
|
2409
|
+
if (capacity <= 0) throw new Error("LRUCache: capacity must be a positive integer");
|
|
2410
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
2411
|
+
this.onEvict = onEvict;
|
|
2412
|
+
}
|
|
2413
|
+
get(key) {
|
|
2414
|
+
if (!this.cache.has(key)) return void 0;
|
|
2415
|
+
const value = this.cache.get(key);
|
|
2416
|
+
this.cache.delete(key);
|
|
2417
|
+
this.cache.set(key, value);
|
|
2418
|
+
return value;
|
|
2419
|
+
}
|
|
2420
|
+
set(key, value) {
|
|
2421
|
+
if (this.cache.has(key)) {
|
|
2422
|
+
this.cache.delete(key);
|
|
2423
|
+
} else if (this.cache.size >= this.capacity) {
|
|
2424
|
+
const oldestKey = this.cache.keys().next().value;
|
|
2425
|
+
const oldestValue = this.cache.get(oldestKey);
|
|
2426
|
+
this.cache.delete(oldestKey);
|
|
2427
|
+
this.onEvict?.(oldestKey, oldestValue);
|
|
2428
|
+
}
|
|
2429
|
+
this.cache.set(key, value);
|
|
2430
|
+
return this;
|
|
2431
|
+
}
|
|
2432
|
+
has(key) {
|
|
2433
|
+
return this.cache.has(key);
|
|
2434
|
+
}
|
|
2435
|
+
delete(key) {
|
|
2436
|
+
return this.cache.delete(key);
|
|
2437
|
+
}
|
|
2438
|
+
clear() {
|
|
2439
|
+
this.cache.clear();
|
|
2440
|
+
}
|
|
2441
|
+
get size() {
|
|
2442
|
+
return this.cache.size;
|
|
2443
|
+
}
|
|
2444
|
+
};
|
|
2445
|
+
|
|
2359
2446
|
// src/core/registry.ts
|
|
2360
2447
|
var BUILTIN_MODIFIERS = {
|
|
2361
2448
|
// ── Mode ─────────────────────────────────────────────────────────────────
|
|
@@ -2442,7 +2529,7 @@ function clearPluginModifiers() {
|
|
|
2442
2529
|
_invalidate();
|
|
2443
2530
|
}
|
|
2444
2531
|
var NAMED_GROUP_PEER_RE = /^(group|peer)-(hover|focus)\/(.+)$/;
|
|
2445
|
-
var _namedModifierCache =
|
|
2532
|
+
var _namedModifierCache = new LRUCache(1e4);
|
|
2446
2533
|
function getNamedGroupPeerModifier(name) {
|
|
2447
2534
|
const cached = _namedModifierCache.get(name);
|
|
2448
2535
|
if (cached) return cached;
|
|
@@ -2613,51 +2700,10 @@ function findOuterColon(s) {
|
|
|
2613
2700
|
return -1;
|
|
2614
2701
|
}
|
|
2615
2702
|
|
|
2616
|
-
// src/core/cache.ts
|
|
2617
|
-
var LRUCache = class {
|
|
2618
|
-
constructor(capacity = 1e4, onEvict) {
|
|
2619
|
-
this.capacity = capacity;
|
|
2620
|
-
if (capacity <= 0) throw new Error("LRUCache: capacity must be a positive integer");
|
|
2621
|
-
this.cache = /* @__PURE__ */ new Map();
|
|
2622
|
-
this.onEvict = onEvict;
|
|
2623
|
-
}
|
|
2624
|
-
get(key) {
|
|
2625
|
-
if (!this.cache.has(key)) return void 0;
|
|
2626
|
-
const value = this.cache.get(key);
|
|
2627
|
-
this.cache.delete(key);
|
|
2628
|
-
this.cache.set(key, value);
|
|
2629
|
-
return value;
|
|
2630
|
-
}
|
|
2631
|
-
set(key, value) {
|
|
2632
|
-
if (this.cache.has(key)) {
|
|
2633
|
-
this.cache.delete(key);
|
|
2634
|
-
} else if (this.cache.size >= this.capacity) {
|
|
2635
|
-
const oldestKey = this.cache.keys().next().value;
|
|
2636
|
-
const oldestValue = this.cache.get(oldestKey);
|
|
2637
|
-
this.cache.delete(oldestKey);
|
|
2638
|
-
this.onEvict?.(oldestKey, oldestValue);
|
|
2639
|
-
}
|
|
2640
|
-
this.cache.set(key, value);
|
|
2641
|
-
return this;
|
|
2642
|
-
}
|
|
2643
|
-
has(key) {
|
|
2644
|
-
return this.cache.has(key);
|
|
2645
|
-
}
|
|
2646
|
-
delete(key) {
|
|
2647
|
-
return this.cache.delete(key);
|
|
2648
|
-
}
|
|
2649
|
-
clear() {
|
|
2650
|
-
this.cache.clear();
|
|
2651
|
-
}
|
|
2652
|
-
get size() {
|
|
2653
|
-
return this.cache.size;
|
|
2654
|
-
}
|
|
2655
|
-
};
|
|
2656
|
-
|
|
2657
2703
|
// src/core/resolver.ts
|
|
2658
|
-
var
|
|
2704
|
+
var _defaultFontFamily;
|
|
2659
2705
|
function setDefaultFontFamily(font) {
|
|
2660
|
-
|
|
2706
|
+
_defaultFontFamily = font;
|
|
2661
2707
|
}
|
|
2662
2708
|
var _styleEl = null;
|
|
2663
2709
|
var _ruleIndexByKey = /* @__PURE__ */ new Map();
|
|
@@ -2677,9 +2723,9 @@ function evictInjectedRule(rule) {
|
|
|
2677
2723
|
}
|
|
2678
2724
|
}
|
|
2679
2725
|
var _injectedRules = new LRUCache(5e4, evictInjectedRule);
|
|
2680
|
-
var
|
|
2726
|
+
var _runtimeCSSDisabled = false;
|
|
2681
2727
|
function isRuntimeCSSDisabled() {
|
|
2682
|
-
return
|
|
2728
|
+
return _runtimeCSSDisabled;
|
|
2683
2729
|
}
|
|
2684
2730
|
function getStyleEl() {
|
|
2685
2731
|
if (_styleEl) return _styleEl;
|
|
@@ -2902,14 +2948,7 @@ function deepMerge(base, override) {
|
|
|
2902
2948
|
}
|
|
2903
2949
|
return result;
|
|
2904
2950
|
}
|
|
2905
|
-
var
|
|
2906
|
-
function getConfigStore() {
|
|
2907
|
-
const g = globalThis;
|
|
2908
|
-
if (!g[CONFIG_KEY]) {
|
|
2909
|
-
g[CONFIG_KEY] = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
2910
|
-
}
|
|
2911
|
-
return g[CONFIG_KEY];
|
|
2912
|
-
}
|
|
2951
|
+
var configStore = { resolved: null, listeners: /* @__PURE__ */ new Set(), customVariants: {} };
|
|
2913
2952
|
function resolveOneRef(ref, colors) {
|
|
2914
2953
|
const lastDash = ref.lastIndexOf("-");
|
|
2915
2954
|
if (lastDash <= 0) return null;
|
|
@@ -2983,8 +3022,7 @@ function buildConfig(userConfig) {
|
|
|
2983
3022
|
clearPluginUtilities();
|
|
2984
3023
|
clearPluginModifiers();
|
|
2985
3024
|
}
|
|
2986
|
-
const
|
|
2987
|
-
for (const k of Object.keys(_store.customVariants)) delete _store.customVariants[k];
|
|
3025
|
+
for (const k of Object.keys(configStore.customVariants)) delete configStore.customVariants[k];
|
|
2988
3026
|
const pluginAPI = makePluginAPI(resolved.theme);
|
|
2989
3027
|
for (const plugin of resolved.plugins) {
|
|
2990
3028
|
plugin(pluginAPI);
|
|
@@ -3031,26 +3069,7 @@ function makePluginAPI(theme) {
|
|
|
3031
3069
|
}
|
|
3032
3070
|
};
|
|
3033
3071
|
}
|
|
3034
|
-
var customVariants =
|
|
3035
|
-
{},
|
|
3036
|
-
{
|
|
3037
|
-
get(_t, p) {
|
|
3038
|
-
return typeof p === "string" ? getConfigStore().customVariants[p] : void 0;
|
|
3039
|
-
},
|
|
3040
|
-
set(_t, p, v) {
|
|
3041
|
-
if (typeof p === "string") getConfigStore().customVariants[p] = v;
|
|
3042
|
-
return true;
|
|
3043
|
-
},
|
|
3044
|
-
ownKeys() {
|
|
3045
|
-
return Object.keys(getConfigStore().customVariants);
|
|
3046
|
-
},
|
|
3047
|
-
getOwnPropertyDescriptor(_t, p) {
|
|
3048
|
-
if (typeof p !== "string") return void 0;
|
|
3049
|
-
const v = getConfigStore().customVariants[p];
|
|
3050
|
-
return v !== void 0 ? { value: v, writable: true, enumerable: true, configurable: true } : void 0;
|
|
3051
|
-
}
|
|
3052
|
-
}
|
|
3053
|
-
);
|
|
3072
|
+
var customVariants = configStore.customVariants;
|
|
3054
3073
|
|
|
3055
3074
|
// src/vite-plugin.ts
|
|
3056
3075
|
var process2 = processImport;
|
|
@@ -3410,7 +3429,9 @@ function pushTokens(str, into) {
|
|
|
3410
3429
|
if (tok && !NOT_A_CLASS_NAME_RE.test(tok)) into.add(tok);
|
|
3411
3430
|
}
|
|
3412
3431
|
}
|
|
3413
|
-
|
|
3432
|
+
var MAX_SCAN_DEPTH = 10;
|
|
3433
|
+
function scanDir(dir, onFile, depth = 0) {
|
|
3434
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
3414
3435
|
let entries;
|
|
3415
3436
|
try {
|
|
3416
3437
|
entries = readdirSync(dir);
|
|
@@ -3425,7 +3446,7 @@ function scanDir(dir, onFile) {
|
|
|
3425
3446
|
const full = join(dir, entry);
|
|
3426
3447
|
try {
|
|
3427
3448
|
const st = statSync(full);
|
|
3428
|
-
if (st.isDirectory()) scanDir(full, onFile);
|
|
3449
|
+
if (st.isDirectory()) scanDir(full, onFile, depth + 1);
|
|
3429
3450
|
else if (/\.(tsx?|jsx?)$/.test(entry)) onFile(full, readFileSync(full, "utf-8"));
|
|
3430
3451
|
} catch (err) {
|
|
3431
3452
|
warn(`Can't process ${full}: ${err.message}`);
|
|
@@ -3443,7 +3464,8 @@ function scanCssFileInto(filePath, into) {
|
|
|
3443
3464
|
} catch {
|
|
3444
3465
|
}
|
|
3445
3466
|
}
|
|
3446
|
-
function scanCssSelectorsInto(dir, into) {
|
|
3467
|
+
function scanCssSelectorsInto(dir, into, depth = 0) {
|
|
3468
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
3447
3469
|
let entries;
|
|
3448
3470
|
try {
|
|
3449
3471
|
entries = readdirSync(dir);
|
|
@@ -3455,7 +3477,7 @@ function scanCssSelectorsInto(dir, into) {
|
|
|
3455
3477
|
const full = join(dir, entry);
|
|
3456
3478
|
try {
|
|
3457
3479
|
const st = statSync(full);
|
|
3458
|
-
if (st.isDirectory()) scanCssSelectorsInto(full, into);
|
|
3480
|
+
if (st.isDirectory()) scanCssSelectorsInto(full, into, depth + 1);
|
|
3459
3481
|
else if (CSS_FILE_RE.test(entry)) scanCssFileInto(full, into);
|
|
3460
3482
|
} catch {
|
|
3461
3483
|
}
|
|
@@ -3522,6 +3544,17 @@ function kbach(userConfigOrOptions) {
|
|
|
3522
3544
|
function generateCSS() {
|
|
3523
3545
|
return formatKbachCSS(buildTokenCSSView(), cfg.theme, responsiveRe);
|
|
3524
3546
|
}
|
|
3547
|
+
function syncMainCSSFile(server) {
|
|
3548
|
+
const active = /* @__PURE__ */ new Set();
|
|
3549
|
+
for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
|
|
3550
|
+
for (const tok of tokenCSS.keys()) {
|
|
3551
|
+
if (!active.has(tok)) tokenCSS.delete(tok);
|
|
3552
|
+
}
|
|
3553
|
+
if (mainCSSFile) {
|
|
3554
|
+
const changed = writeKbachToFile(mainCSSFile, generateCSS());
|
|
3555
|
+
if (changed) server.watcher.emit("change", mainCSSFile);
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3525
3558
|
return {
|
|
3526
3559
|
name: "kbach",
|
|
3527
3560
|
enforce: "pre",
|
|
@@ -3581,6 +3614,37 @@ ${code}`,
|
|
|
3581
3614
|
initialScan();
|
|
3582
3615
|
if (mainCSSFile) writeKbachToFile(mainCSSFile, generateCSS());
|
|
3583
3616
|
},
|
|
3617
|
+
// Vite's `handleHotUpdate` hook only fires for `type === "update"` (plain
|
|
3618
|
+
// file edits) — it's never called for file create/delete, which land on
|
|
3619
|
+
// the watcher's own 'add'/'unlink' events instead (confirmed against
|
|
3620
|
+
// vite's own onHMRUpdate/handleHMRUpdate: the hook loop is gated on
|
|
3621
|
+
// `type === "update"`). Without also listening on those two events here,
|
|
3622
|
+
// creating a new file with new Kbach classes never adds them to
|
|
3623
|
+
// kbach.css, and deleting a file never removes its classes, until a full
|
|
3624
|
+
// dev-server restart. configureServer gives access to the raw watcher so
|
|
3625
|
+
// both cases can share the same sync logic as a plain edit.
|
|
3626
|
+
configureServer(server) {
|
|
3627
|
+
const onAddOrUnlink = (file, isUnlink) => {
|
|
3628
|
+
if (file.includes("node_modules")) return;
|
|
3629
|
+
if (CSS_FILE_RE.test(file)) {
|
|
3630
|
+
if (!isUnlink) scanCssFileInto(file, projectCssClasses);
|
|
3631
|
+
return;
|
|
3632
|
+
}
|
|
3633
|
+
if (!/\.(tsx?|jsx?)$/.test(file)) return;
|
|
3634
|
+
if (isUnlink) {
|
|
3635
|
+
fileTokens.delete(normPath(file));
|
|
3636
|
+
} else {
|
|
3637
|
+
try {
|
|
3638
|
+
processFile(file, readFileSync(file, "utf-8"));
|
|
3639
|
+
} catch {
|
|
3640
|
+
fileTokens.delete(normPath(file));
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
syncMainCSSFile(server);
|
|
3644
|
+
};
|
|
3645
|
+
server.watcher.on("add", (file) => onAddOrUnlink(file, false));
|
|
3646
|
+
server.watcher.on("unlink", (file) => onAddOrUnlink(file, true));
|
|
3647
|
+
},
|
|
3584
3648
|
handleHotUpdate({ file, server }) {
|
|
3585
3649
|
if (file.includes("node_modules")) return;
|
|
3586
3650
|
if (CSS_FILE_RE.test(file)) {
|
|
@@ -3593,15 +3657,7 @@ ${code}`,
|
|
|
3593
3657
|
} catch {
|
|
3594
3658
|
fileTokens.delete(normPath(file));
|
|
3595
3659
|
}
|
|
3596
|
-
|
|
3597
|
-
for (const tokens of fileTokens.values()) for (const t of tokens) active.add(t);
|
|
3598
|
-
for (const tok of tokenCSS.keys()) {
|
|
3599
|
-
if (!active.has(tok)) tokenCSS.delete(tok);
|
|
3600
|
-
}
|
|
3601
|
-
if (mainCSSFile) {
|
|
3602
|
-
const changed = writeKbachToFile(mainCSSFile, generateCSS());
|
|
3603
|
-
if (changed) server.watcher.emit("change", mainCSSFile);
|
|
3604
|
-
}
|
|
3660
|
+
syncMainCSSFile(server);
|
|
3605
3661
|
}
|
|
3606
3662
|
};
|
|
3607
3663
|
}
|