diff --git a/src/__tests__/compiler/@prop.test.tsx b/src/__tests__/compiler/@prop.test.tsx
index 89ba59f7..63f8793e 100644
--- a/src/__tests__/compiler/@prop.test.tsx
+++ b/src/__tests__/compiler/@prop.test.tsx
@@ -61,15 +61,13 @@ test("@prop target unparsed", () => {
"my-class",
[
{
- d: [[[{}, "var", "color-black", 1], ["test"], 1]],
- dv: 1,
- s: [2, 1],
- v: [["__rn-css-current-color", [{}, "var", "color-black", 1]]],
+ d: [["#000", ["test"]]],
+ s: [1, 1],
+ v: [["__rn-css-color", "#000"]],
},
],
],
],
- vr: [["color-black", [["#000"]]]],
});
render();
diff --git a/src/__tests__/compiler/compiler.test.tsx b/src/__tests__/compiler/compiler.test.tsx
index 0623c8d3..5e5775b5 100644
--- a/src/__tests__/compiler/compiler.test.tsx
+++ b/src/__tests__/compiler/compiler.test.tsx
@@ -27,12 +27,17 @@ test("hello world", () => {
});
test("reads global CSS variables", () => {
- const compiled = compile(`
+ const compiled = compile(
+ `
@layer theme {
:root, :host {
--color-red-500: oklch(63.7% 0.237 25.331);
}
-}`);
+}`,
+ {
+ inlineVariables: false,
+ },
+ );
expect(compiled.stylesheet()).toStrictEqual({
vr: [["color-red-500", [["#fb2c36"]]]],
@@ -236,11 +241,16 @@ test.skip("animations", () => {
});
test("breaks apart comma separated variables", () => {
- const compiled = compile(`
+ const compiled = compile(
+ `
:root {
--test: blue, green;
}
- `);
+ `,
+ {
+ inlineVariables: false,
+ },
+ );
expect(compiled.stylesheet()).toStrictEqual({
vr: [["test", [[["blue", "green"]]]]],
diff --git a/src/__tests__/native/box-shadow.test.tsx b/src/__tests__/native/box-shadow.test.tsx
index 6d62135a..48a387a4 100644
--- a/src/__tests__/native/box-shadow.test.tsx
+++ b/src/__tests__/native/box-shadow.test.tsx
@@ -49,7 +49,7 @@ test("shadow values - multiple nested variables", () => {
boxShadow: [
{
blurRadius: 0,
- color: "red",
+ color: "#f00",
offsetX: 0,
offsetY: 20,
spreadDistance: 0,
@@ -57,35 +57,35 @@ test("shadow values - multiple nested variables", () => {
{
blurRadius: 0,
- color: "green",
+ color: "#008000",
offsetX: 0,
offsetY: 30,
spreadDistance: 0,
},
{
blurRadius: 0,
- color: "purple",
+ color: "#800080",
offsetX: 0,
offsetY: 40,
spreadDistance: 0,
},
{
blurRadius: 0,
- color: "yellow",
+ color: "#ff0",
offsetX: 0,
offsetY: 50,
spreadDistance: 0,
},
{
blurRadius: 0,
- color: "orange",
+ color: "#ffa500",
offsetX: 0,
offsetY: 60,
spreadDistance: 0,
},
{
blurRadius: 0,
- color: "gray",
+ color: "#808080",
offsetX: 0,
offsetY: 70,
spreadDistance: 0,
diff --git a/src/__tests__/native/calc.test.tsx b/src/__tests__/native/calc.test.tsx
index 30cd63b3..b26cfbad 100644
--- a/src/__tests__/native/calc.test.tsx
+++ b/src/__tests__/native/calc.test.tsx
@@ -139,7 +139,6 @@ test("calc(var(--variable) + 20%)", () => {
expect(component.type).toBe("View");
expect(component.props).toStrictEqual({
children: undefined,
- style: {},
testID,
});
});
@@ -159,7 +158,6 @@ test("calc(var(--percent) + 20px)", () => {
expect(component.type).toBe("View");
expect(component.props).toStrictEqual({
children: undefined,
- style: {},
testID,
});
});
@@ -185,7 +183,7 @@ test("calc & colors", () => {
expect(component.props).toStrictEqual({
children: undefined,
style: {
- backgroundColor: "hsl(120, 90%, 80%)",
+ backgroundColor: "#9efa9e",
},
testID,
});
diff --git a/src/__tests__/native/colors.test.tsx b/src/__tests__/native/colors.test.tsx
index 384379b0..6a8c7255 100644
--- a/src/__tests__/native/colors.test.tsx
+++ b/src/__tests__/native/colors.test.tsx
@@ -45,7 +45,7 @@ describe("hsl", () => {
expect(component.type).toBe("View");
expect(component.props).toStrictEqual({
children: undefined,
- style: { color: "hsl(0, 84.2%, 60.2%)" },
+ style: { color: "#ef4444" },
testID,
});
});
@@ -62,7 +62,7 @@ describe("hsl", () => {
expect(component.type).toBe("View");
expect(component.props).toStrictEqual({
children: undefined,
- style: { color: "hsl(0, 84.2%, 60.2%)" },
+ style: { color: "#ef4444" },
testID,
});
});
@@ -113,7 +113,7 @@ describe("hsla", () => {
expect(component.type).toBe("View");
expect(component.props).toStrictEqual({
children: undefined,
- style: { color: "hsla(0, 84.2%, 60.2%, 60%)" },
+ style: { color: "#ef444499" },
testID,
});
});
@@ -130,7 +130,7 @@ describe("hsla", () => {
expect(component.type).toBe("View");
expect(component.props).toStrictEqual({
children: undefined,
- style: { color: "hsla(0, 84.2%, 60.2%, 60%)" },
+ style: { color: "#ef444499" },
testID,
});
});
@@ -160,7 +160,7 @@ describe("currentcolor", () => {
expect(component.type).toBe("View");
expect(component.props).toStrictEqual({
children: undefined,
- style: { color: "red", backgroundColor: "red" },
+ style: { color: "#f00", backgroundColor: "#f00" },
testID,
});
});
diff --git a/src/__tests__/native/text-shadow.test.ios.tsx b/src/__tests__/native/text-shadow.test.ios.tsx
index 8b45ea72..07281ee7 100644
--- a/src/__tests__/native/text-shadow.test.ios.tsx
+++ b/src/__tests__/native/text-shadow.test.ios.tsx
@@ -5,13 +5,18 @@ import { registerCSS, testID } from "react-native-css/jest";
describe("text-shadow", () => {
test(" ", () => {
registerCSS(
- `.my-class { --my-var: 10px 10px; text-shadow: var(--my-var); }`,
+ `.my-class {
+ --my-var: 10px 10px;
+ text-shadow: var(--my-var);
+ }`,
);
render();
expect(screen.getByTestId(testID).props.style).toStrictEqual({
- textShadowColor: "black",
+ textShadowColor: {
+ semantic: ["label", "labelColor"],
+ },
textShadowOffset: {
height: 10,
width: 10,
@@ -28,7 +33,7 @@ describe("text-shadow", () => {
render();
expect(screen.getByTestId(testID).props.style).toStrictEqual({
- textShadowColor: "red",
+ textShadowColor: "#f00",
textShadowOffset: {
height: 10,
width: 10,
@@ -45,7 +50,7 @@ describe("text-shadow", () => {
render();
expect(screen.getByTestId(testID).props.style).toStrictEqual({
- textShadowColor: "red",
+ textShadowColor: "#f00",
textShadowOffset: {
height: 10,
width: 10,
diff --git a/src/__tests__/native/transform.test.tsx b/src/__tests__/native/transform.test.tsx
index 6ec3c08b..b7a08fca 100644
--- a/src/__tests__/native/transform.test.tsx
+++ b/src/__tests__/native/transform.test.tsx
@@ -56,7 +56,7 @@ describe("scale", () => {
).getByTestId(testID);
expect(component.props.style).toStrictEqual({
- transform: [{ scale: "2%" }],
+ transform: [{ scaleX: "2%" }, { scaleY: "2%" }],
});
});
diff --git a/src/__tests__/native/variables.test.tsx b/src/__tests__/native/variables.test.tsx
index dbdf150b..48971465 100644
--- a/src/__tests__/native/variables.test.tsx
+++ b/src/__tests__/native/variables.test.tsx
@@ -20,7 +20,7 @@ test("inline variable", () => {
});
});
-test("combined inline variable", () => {
+test("combined inline variables", () => {
registerCSS(`
.my-class-1 { width: var(--my-var); }
.my-class-2 { --my-var: 10px; }
@@ -142,7 +142,7 @@ test(":root variables", () => {
,
).getByTestId(testID);
- expect(component.props.style).toStrictEqual({ color: "red" });
+ expect(component.props.style).toStrictEqual({ color: "#f00" });
});
test("can apply and set new variables", () => {
@@ -166,13 +166,13 @@ test("can apply and set new variables", () => {
);
expect(screen.getByTestId(testIDs.one).props.style).toStrictEqual({
- color: "red",
+ color: "#f00",
});
expect(screen.getByTestId(testIDs.two).props.style).toStrictEqual({
- color: "red",
+ color: "#f00",
});
expect(screen.getByTestId(testIDs.three).props.style).toStrictEqual({
- color: "green",
+ color: "#008000",
});
});
@@ -199,7 +199,7 @@ test("variables will be inherited", () => {
);
expect(screen.getByTestId(testIDs.three).props.style).toStrictEqual({
- color: "green",
+ color: "#008000",
});
});
@@ -212,7 +212,7 @@ test("useUnsafeVariable", () => {
render();
const component = screen.getByTestId(testID);
- expect(component.props.style).toStrictEqual({ color: "red" });
+ expect(component.props.style).toStrictEqual({ color: "#f00" });
});
test("ratio values", () => {
@@ -224,7 +224,7 @@ test("ratio values", () => {
render();
const component = screen.getByTestId(testID);
- expect(component.props.style).toStrictEqual({ aspectRatio: "16 / 9" });
+ expect(component.props.style).toStrictEqual({ aspectRatio: "16/9" });
});
test("VariableContextProvider", () => {
@@ -269,5 +269,5 @@ test("variable overriding with classes", () => {
);
const component = screen.getByTestId(testID);
- expect(component.props.style).toStrictEqual({ color: "red" });
+ expect(component.props.style).toStrictEqual({ color: "#f00" });
});
diff --git a/src/__tests__/vendor/tailwind.test.tsx b/src/__tests__/vendor/tailwind.test.tsx
deleted file mode 100644
index 446fd662..00000000
--- a/src/__tests__/vendor/tailwind.test.tsx
+++ /dev/null
@@ -1,414 +0,0 @@
-import { render, screen } from "@testing-library/react-native";
-import { View } from "react-native-css/components/View";
-import { registerCSS, testID } from "react-native-css/jest";
-
-/**
- * Tailwind CSS utilities
- *
- * These tests are designed to ensure that complex Tailwind CSS utilities are compiled correctly.
- * For the full Tailwind CSS test suite, see the Nativewind repository.
- */
-
-test("transition", () => {
- const compiled = registerCSS(`
-:root, :host {
- --default-transition-duration: 150ms;
- --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
-}
-
-.transition {
- transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events;
- transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
- transition-duration: var(--tw-duration, var(--default-transition-duration));
-}
- `);
-
- expect(compiled.stylesheet()).toStrictEqual({
- s: [
- [
- "transition",
- [
- {
- a: true,
- d: [
- {
- transitionProperty: [
- "color",
- "backgroundColor",
- "borderColor",
- "outlineColor",
- "textDecorationColor",
- "fill",
- "stroke",
- "opacity",
- "boxShadow",
- "transform",
- "translate",
- "scale",
- "rotate",
- "filter",
- "display",
- "pointerEvents",
- ],
- },
- [
- [
- {},
- "var",
- [
- "tw-ease",
- [{}, "var", "default-transition-timing-function", 1],
- ],
- 1,
- ],
- "transitionTimingFunction",
- 1,
- ],
- [
- [
- {},
- "var",
- [
- "tw-duration",
- [{}, "var", "default-transition-duration", 1],
- ],
- 1,
- ],
- "transitionDuration",
- 1,
- ],
- ],
- dv: 1,
- s: [2, 1],
- },
- ],
- ],
- ],
- vr: [
- ["default-transition-duration", [[150]]],
- [
- "default-transition-timing-function",
- [[[{}, "cubicBezier", [0.4, 0, 0.2, 1]]]],
- ],
- ],
- });
-});
-
-test("box-shadow", () => {
- const compiled = registerCSS(`
-.shadow-xl {
- --tw-shadow: 0 20px 25px -5px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 8px 10px -6px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
-}
-.shadow-red-500 {
- --tw-shadow-color: oklch(63.7% 0.237 25.331);
- @supports (color: color-mix(in lab, red, red)) {
- --tw-shadow-color: color-mix(in oklab, var(--color-red-500) var(--tw-shadow-alpha), transparent);
- }
-}
- `);
-
- expect(compiled.stylesheet()).toStrictEqual({
- s: [
- [
- "shadow-xl",
- [
- {
- d: [
- [
- [
- {},
- "boxShadow",
- [
- [{}, "var", "tw-inset-shadow", 1],
- [{}, "var", "tw-inset-ring-shadow", 1],
- [{}, "var", "tw-ring-offset-shadow", 1],
- [{}, "var", "tw-ring-shadow", 1],
- [{}, "var", "tw-shadow", 1],
- ],
- 1,
- ],
- "boxShadow",
- 1,
- ],
- ],
- dv: 1,
- s: [1, 1],
- v: [
- [
- "tw-shadow",
- [
- [
- 0,
- 20,
- 25,
- -5,
- [{}, "var", ["tw-shadow-color", "#0000001a"], 1],
- ],
- [
- 0,
- 8,
- 10,
- -6,
- [{}, "var", ["tw-shadow-color", "#0000001a"], 1],
- ],
- ],
- ],
- ],
- },
- ],
- ],
- [
- "shadow-red-500",
- [
- {
- s: [2, 1],
- v: [["tw-shadow-color", "#fb2c36"]],
- },
- ],
- ],
- ],
- });
-
- render();
- const component = screen.getByTestId(testID);
-
- expect(component.type).toBe("View");
- expect(component.props).toStrictEqual({
- children: undefined,
- style: {
- boxShadow: [
- {
- blurRadius: 25,
- color: "#fb2c36",
- offsetX: 0,
- offsetY: 20,
- spreadDistance: -5,
- },
- {
- blurRadius: 10,
- color: "#fb2c36",
- offsetX: 0,
- offsetY: 8,
- spreadDistance: -6,
- },
- ],
- },
- testID,
- });
-});
-
-test("filter", () => {
- const compiled = registerCSS(`
-:root, :host {
- --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12);
-}
-
-.brightness-50 {
- --tw-brightness: brightness(50%);
- filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
-}
-
-.drop-shadow-md {
- --tw-drop-shadow-size: drop-shadow(0 3px 3px var(--tw-drop-shadow-color, rgb(0 0 0 / 0.12)));
- --tw-drop-shadow: drop-shadow(var(--drop-shadow-md));
- filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
-}
- `);
-
- expect(compiled.stylesheet()).toStrictEqual({
- s: [
- [
- "brightness-50",
- [
- {
- d: [
- [
- [
- [{}, "var", "tw-blur", 1],
- [{}, "var", "tw-brightness", 1],
- [{}, "var", "tw-contrast", 1],
- [{}, "var", "tw-grayscale", 1],
- [{}, "var", "tw-hue-rotate", 1],
- [{}, "var", "tw-invert", 1],
- [{}, "var", "tw-saturate", 1],
- [{}, "var", "tw-sepia", 1],
- [{}, "var", "tw-drop-shadow", 1],
- ],
- "filter",
- ],
- ],
- s: [2, 1],
- v: [["tw-brightness", [{}, "brightness", "50%"]]],
- },
- ],
- ],
- [
- "drop-shadow-md",
- [
- {
- d: [
- [
- [
- [{}, "var", "tw-blur", 1],
- [{}, "var", "tw-brightness", 1],
- [{}, "var", "tw-contrast", 1],
- [{}, "var", "tw-grayscale", 1],
- [{}, "var", "tw-hue-rotate", 1],
- [{}, "var", "tw-invert", 1],
- [{}, "var", "tw-saturate", 1],
- [{}, "var", "tw-sepia", 1],
- [{}, "var", "tw-drop-shadow", 1],
- ],
- "filter",
- ],
- ],
- s: [3, 1],
- v: [
- [
- "tw-drop-shadow-size",
- [
- {},
- "dropShadow",
- [
- 0,
- 3,
- 3,
- [{}, "var", ["tw-drop-shadow-color", "#0000001f"], 1],
- ],
- ],
- ],
- [
- "tw-drop-shadow",
- [{}, "dropShadow", [{}, "var", "drop-shadow-md", 1]],
- ],
- ],
- },
- ],
- ],
- ],
- vr: [["drop-shadow-md", [[[0, 3, 3, "#0000001f"]]]]],
- });
-
- render();
- const component = screen.getByTestId(testID);
-
- expect(component.type).toBe("View");
- expect(component.props).toStrictEqual({
- children: undefined,
- style: {
- filter: [
- { brightness: "50%" },
- {
- dropShadow: {
- blurRadius: 3,
- color: "#0000001f",
- offsetX: 0,
- offsetY: 3,
- },
- },
- ],
- },
- testID,
- });
-});
-
-test("line-clamp", () => {
- const compiled = registerCSS(`
- .my-class {
- overflow: hidden;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- -webkit-line-clamp: 1
- }
- `);
-
- expect(compiled.stylesheet()).toStrictEqual({
- s: [
- [
- "my-class",
- [
- {
- d: [
- [1, ["numberOfLines"]],
- {
- overflow: "hidden",
- },
- ],
- s: [1, 1],
- },
- ],
- ],
- ],
- });
-
- render();
- const component = screen.getByTestId(testID);
-
- expect(component.props).toStrictEqual({
- children: undefined,
- numberOfLines: 1,
- style: {
- overflow: "hidden",
- },
- testID,
- });
-});
-
-test("blur-xl", () => {
- const compiled = registerCSS(`
- @layer theme {
- :root, :host {
- --blur-xs: 4px;
- }
- }
- @layer utilities {
- .blur-xs {
- --tw-blur: blur(var(--blur-xs));
- filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
- }
- }
- `);
-
- expect(compiled.stylesheet()).toStrictEqual({
- s: [
- [
- "blur-xs",
- [
- {
- d: [
- [
- [
- [{}, "var", "tw-blur", 1],
- [{}, "var", "tw-brightness", 1],
- [{}, "var", "tw-contrast", 1],
- [{}, "var", "tw-grayscale", 1],
- [{}, "var", "tw-hue-rotate", 1],
- [{}, "var", "tw-invert", 1],
- [{}, "var", "tw-saturate", 1],
- [{}, "var", "tw-sepia", 1],
- [{}, "var", "tw-drop-shadow", 1],
- ],
- "filter",
- ],
- ],
- s: [2, 1],
- v: [["tw-blur", [{}, "blur", [{}, "var", "blur-xs", 1]]]],
- },
- ],
- ],
- ],
- vr: [["blur-xs", [[4]]]],
- });
-
- render();
- const component = screen.getByTestId(testID);
-
- expect(component.props).toStrictEqual({
- children: undefined,
- style: {
- filter: [{ blur: 4 }],
- },
- testID,
- });
-});
diff --git a/src/__tests__/vendor/tailwind/_tailwind.tsx b/src/__tests__/vendor/tailwind/_tailwind.tsx
index 6f5cd5a6..bff42224 100644
--- a/src/__tests__/vendor/tailwind/_tailwind.tsx
+++ b/src/__tests__/vendor/tailwind/_tailwind.tsx
@@ -1,7 +1,5 @@
import type { PropsWithChildren, ReactElement } from "react";
-import { inspect } from "node:util";
-
import tailwind from "@tailwindcss/postcss";
import {
screen,
@@ -88,16 +86,6 @@ export async function render(
const compiled = registerCSS(output, { debug: Boolean(debug) });
- if (debug) {
- console.log(
- inspect(compiled.stylesheet(), {
- colors: true,
- compact: false,
- depth: null,
- }),
- );
- }
-
return Object.assign(
{},
tlRender(component, {
diff --git a/src/__tests__/vendor/tailwind/flexbox-grid.test.tsx b/src/__tests__/vendor/tailwind/flexbox-grid.test.tsx
index b73d6648..cc825129 100644
--- a/src/__tests__/vendor/tailwind/flexbox-grid.test.tsx
+++ b/src/__tests__/vendor/tailwind/flexbox-grid.test.tsx
@@ -402,7 +402,7 @@ describe("Flexbox & Grid - Gap", () => {
});
test("gap-px", async () => {
expect(await renderCurrentTest()).toStrictEqual({
- props: { style: { columnGap: 1, rowGap: 1 } },
+ props: { style: { gap: 1 } },
});
});
test("gap-x-1", async () => {
diff --git a/src/__tests__/vendor/tailwind/interactivity.test.tsx b/src/__tests__/vendor/tailwind/interactivity.test.tsx
index e4a99fe3..dd2082f6 100644
--- a/src/__tests__/vendor/tailwind/interactivity.test.tsx
+++ b/src/__tests__/vendor/tailwind/interactivity.test.tsx
@@ -60,7 +60,12 @@ describe("Interactivity - Caret Color", () => {
});
test("caret-current", async () => {
expect(await renderCurrentTest()).toStrictEqual({
- props: { style: {} },
+ props: {
+ cursorColor: {
+ semantic: ["label", "labelColor"],
+ },
+ style: {},
+ },
});
});
test("caret-white", async () => {
diff --git a/src/__tests__/vendor/tailwind/layout.test.tsx b/src/__tests__/vendor/tailwind/layout.test.tsx
index 99948b3b..e38a1cec 100644
--- a/src/__tests__/vendor/tailwind/layout.test.tsx
+++ b/src/__tests__/vendor/tailwind/layout.test.tsx
@@ -8,7 +8,7 @@ describe("Layout - Aspect Ratio", () => {
});
test("aspect-video", async () => {
expect(await renderCurrentTest()).toStrictEqual({
- props: { style: { aspectRatio: "16 / 9" } },
+ props: { style: { aspectRatio: "16/9" } },
});
});
test("aspect-[4/3]", async () => {
diff --git a/src/__tests__/vendor/tailwind/transform.test.ts b/src/__tests__/vendor/tailwind/transform.test.ts
index b2198afb..a056663f 100644
--- a/src/__tests__/vendor/tailwind/transform.test.ts
+++ b/src/__tests__/vendor/tailwind/transform.test.ts
@@ -95,7 +95,7 @@ describe("Transforms - Translate", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateX: 0 }],
+ transform: [{ translateX: 0 }, { translateY: 0 }],
},
},
});
@@ -104,7 +104,7 @@ describe("Transforms - Translate", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateY: 0 }],
+ transform: [{ translateX: 0 }, { translateY: 0 }],
},
},
});
@@ -113,7 +113,7 @@ describe("Transforms - Translate", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateX: 1 }],
+ transform: [{ translateX: 1 }, { translateY: 0 }],
},
},
});
@@ -122,7 +122,7 @@ describe("Transforms - Translate", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateY: 1 }],
+ transform: [{ translateX: 0 }, { translateY: 1 }],
},
},
});
@@ -131,7 +131,7 @@ describe("Transforms - Translate", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateX: 3.5 }],
+ transform: [{ translateX: 3.5 }, { translateY: 0 }],
},
},
});
@@ -140,7 +140,7 @@ describe("Transforms - Translate", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateY: 3.5 }],
+ transform: [{ translateX: 0 }, { translateY: 3.5 }],
},
},
});
@@ -150,7 +150,9 @@ describe("Transforms - Translate", () => {
describe("Transforms - Translate (%)", () => {
test("translate-x-1/2", async () => {
expect(await renderCurrentTest()).toStrictEqual({
- props: { style: { transform: [{ translateX: "50%" }] } },
+ props: {
+ style: { transform: [{ translateX: "50%" }, { translateY: 0 }] },
+ },
});
});
@@ -158,7 +160,7 @@ describe("Transforms - Translate (%)", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateY: "50%" }],
+ transform: [{ translateX: 0 }, { translateY: "50%" }],
},
},
});
@@ -167,7 +169,7 @@ describe("Transforms - Translate (%)", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateX: "100%" }],
+ transform: [{ translateX: "100%" }, { translateY: 0 }],
},
},
});
@@ -176,7 +178,7 @@ describe("Transforms - Translate (%)", () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
style: {
- transform: [{ translateY: "100%" }],
+ transform: [{ translateX: 0 }, { translateY: "100%" }],
},
},
});
@@ -234,6 +236,7 @@ describe("Transforms - Mixed", () => {
transform: [
{ skewY: "1deg" },
{ translateX: 3.5 },
+ { translateY: 0 },
{ rotateZ: "90deg" },
],
},
diff --git a/src/__tests__/vendor/tailwind/typography.test.tsx b/src/__tests__/vendor/tailwind/typography.test.tsx
index 5986d5b4..00d184b7 100644
--- a/src/__tests__/vendor/tailwind/typography.test.tsx
+++ b/src/__tests__/vendor/tailwind/typography.test.tsx
@@ -313,7 +313,11 @@ describe("Typography - Text Color", () => {
test("text-current", async () => {
expect(await renderCurrentTest()).toStrictEqual({
props: {
- style: {},
+ style: {
+ color: {
+ semantic: ["label", "labelColor"],
+ },
+ },
},
});
});
diff --git a/src/compiler/compiler.ts b/src/compiler/compiler.ts
index 52018dc1..f403ea6d 100644
--- a/src/compiler/compiler.ts
+++ b/src/compiler/compiler.ts
@@ -14,9 +14,14 @@ import {
} from "lightningcss";
import { maybeMutateReactNativeOptions, parsePropAtRule } from "./atRules";
-import type { CompilerOptions, ContainerQuery } from "./compiler.types";
+import type {
+ CompilerOptions,
+ ContainerQuery,
+ UniqueVarInfo,
+} from "./compiler.types";
import { parseContainerCondition } from "./container-query";
import { parseDeclaration, round } from "./declarations";
+import { inlineVariables } from "./inline-variables";
import { extractKeyFrames } from "./keyframes";
import { parseMediaQuery } from "./media-query";
import { StylesheetBuilder } from "./stylesheet";
@@ -64,22 +69,54 @@ export function compile(code: Buffer | string, options: CompilerOptions = {}) {
*
* Due to the above issue, we run lightningcss twice
*/
+
+ const vars = new Map();
+
+ const firstPassVisitor: Visitor = {};
+
+ if (options.inlineRem !== false) {
+ firstPassVisitor.Length = (length) => {
+ if (length.unit !== "rem" || options.inlineRem === false) {
+ return length;
+ }
+
+ return {
+ unit: "px",
+ value: round(length.value * (options.inlineRem ?? 14)),
+ };
+ };
+ }
+
+ if (options.inlineVariables !== false) {
+ const exclusionList: string[] = options.inlineVariables?.exclude ?? [];
+
+ firstPassVisitor.Declaration = (decl) => {
+ if (
+ decl.property === "custom" &&
+ decl.value.name.startsWith("--") &&
+ !exclusionList.includes(decl.value.name)
+ ) {
+ const entry = vars.get(decl.value.name) ?? {
+ count: 0,
+ value: [
+ ...decl.value.value,
+ { type: "token", value: { type: "white-space", value: " " } },
+ ],
+ };
+ entry.count++;
+ vars.set(decl.value.name, entry);
+ }
+ };
+ firstPassVisitor.StyleSheetExit = (sheet) => {
+ return inlineVariables(sheet, vars);
+ };
+ }
+
const { code: firstPass } = lightningcss({
code: typeof code === "string" ? new TextEncoder().encode(code) : code,
include: Features.DoublePositionGradients | Features.ColorFunction,
exclude: Features.VendorPrefixes,
- visitor: {
- Length(length) {
- if (length.unit !== "rem" || options.inlineRem === false) {
- return length;
- }
-
- return {
- unit: "px",
- value: round(length.value * (options.inlineRem ?? 14)),
- };
- },
- },
+ visitor: firstPassVisitor,
filename: options.filename ?? "style.css",
projectRoot: options.projectRoot ?? process.cwd(),
});
diff --git a/src/compiler/compiler.types.ts b/src/compiler/compiler.types.ts
index 9f71729d..f1cecb41 100644
--- a/src/compiler/compiler.types.ts
+++ b/src/compiler/compiler.types.ts
@@ -1,6 +1,9 @@
/* eslint-disable */
import type { Debugger } from "debug";
-import type { MediaFeatureNameFor_MediaFeatureId } from "lightningcss";
+import type {
+ MediaFeatureNameFor_MediaFeatureId,
+ TokenOrValue,
+} from "lightningcss";
import { VAR_SYMBOL } from "../runtime/native/reactivity";
@@ -8,6 +11,7 @@ export interface CompilerOptions {
filename?: string;
projectRoot?: string;
inlineRem?: number | false;
+ inlineVariables?: false | InlineVariableOptions;
selectorPrefix?: string;
stylesheetOrder?: number;
features?: FeatureFlagRecord;
@@ -16,6 +20,10 @@ export interface CompilerOptions {
colorPrecision?: number;
}
+export interface InlineVariableOptions {
+ exclude?: `--${string}`[];
+}
+
/**
* A `react-native-css` StyleSheet
*/
@@ -151,6 +159,12 @@ export type InlineVariable = {
[key: string]: unknown | undefined;
};
+export type UniqueVarInfo = {
+ count: number;
+ value: TokenOrValue[] | undefined;
+ flat?: true;
+};
+
/****************************** Animations ******************************/
export type Animation = [string, AnimationKeyframes[]];
diff --git a/src/compiler/declarations.ts b/src/compiler/declarations.ts
index 47540aac..2e20bd9a 100644
--- a/src/compiler/declarations.ts
+++ b/src/compiler/declarations.ts
@@ -36,6 +36,7 @@ import type {
UnresolvedColor,
} from "lightningcss";
+import { isStyleFunction } from "../runtime/utils";
import type {
StyleDescriptor,
StyleFunction,
@@ -369,35 +370,26 @@ function parseBorderColor(
>,
builder: StylesheetBuilder,
) {
- switch (declaration.property) {
- case "border-color":
- builder.addShorthand("border-color", {
- "border-top-color": parseColor(declaration.value.top, builder),
- "border-bottom-color": parseColor(declaration.value.bottom, builder),
- "border-left-color": parseColor(declaration.value.left, builder),
- "border-right-color": parseColor(declaration.value.right, builder),
- });
- break;
- case "border-block-color":
- builder.addDescriptor(
- "border-top-color",
- parseColor(declaration.value.start, builder),
- );
- builder.addDescriptor(
- "border-bottom-color",
- parseColor(declaration.value.end, builder),
- );
- break;
- case "border-inline-color":
- builder.addDescriptor(
- "border-left-color",
- parseColor(declaration.value.start, builder),
- );
- builder.addDescriptor(
- "border-right-color",
- parseColor(declaration.value.end, builder),
- );
- break;
+ if (declaration.property === "border-color") {
+ builder.addShorthand("border-color", {
+ "border-top-color": parseColor(declaration.value.top, builder),
+ "border-bottom-color": parseColor(declaration.value.bottom, builder),
+ "border-left-color": parseColor(declaration.value.left, builder),
+ "border-right-color": parseColor(declaration.value.right, builder),
+ });
+ } else {
+ const start = parseColor(declaration.value.start, builder);
+ const end = parseColor(declaration.value.end, builder);
+
+ if (start === end) {
+ builder.addDescriptor(declaration.property, start);
+ } else if (declaration.property === "border-block-color") {
+ builder.addDescriptor("border-top-color", start);
+ builder.addDescriptor("border-bottom-color", end);
+ } else {
+ builder.addDescriptor("border-left-color", start);
+ builder.addDescriptor("border-right-color", end);
+ }
}
}
@@ -859,17 +851,8 @@ function parseLetterSpacing(
if (value.type === "normal") {
return;
}
- const descriptor = parseLength(value.value, builder);
- if (
- Array.isArray(descriptor) &&
- descriptor[1] === "em" &&
- typeof descriptor[2] === "number"
- ) {
- return descriptor[2];
- }
-
- return descriptor;
+ return parseLength(value.value, builder);
}
function parseTextDecoration(
@@ -966,7 +949,13 @@ export function parseUnparsedDeclaration(
}
if (property === "color") {
- builder.addDescriptor("--__rn-css-current-color", value);
+ if (
+ !isStyleFunction(value) ||
+ value[1] !== "var" ||
+ value[2] !== "-css-color"
+ ) {
+ builder.addDescriptor("--__rn-css-color", value);
+ }
}
}
}
@@ -1125,7 +1114,7 @@ export function parseUnparsed(
} else if (tokenOrValue === "false") {
return false;
} else if (tokenOrValue === "currentcolor") {
- return [{}, "var", "__rn-css-current-color"] as const;
+ return [{}, "var", "__rn-css-color"] as const;
} else {
return tokenOrValue;
}
@@ -1143,8 +1132,16 @@ export function parseUnparsed(
allowAuto,
);
if (!args) return;
- if (Array.isArray(args) && args.length === 1) return args[0];
- return args;
+ if (Array.isArray(args) && args.length === 1) {
+ return args[0];
+ } else if (
+ (property === "filter" || property === "transform") &&
+ isStyleFunction(args)
+ ) {
+ return [args];
+ } else {
+ return args;
+ }
}
switch (tokenOrValue.type) {
@@ -1255,7 +1252,7 @@ export function parseUnparsed(
builder.addWarning("value", value);
return;
} else if (value === "currentcolor") {
- return [{}, "var", "__rn-css-current-color"] as const;
+ return [{}, "var", "__rn-css-color"] as const;
}
if (value === "true") {
@@ -1579,10 +1576,15 @@ export function parseFontColorDeclaration(
) {
parseColorDeclaration(declaration, builder);
- builder.addDescriptor(
- "--__rn-css-color",
- parseColor(declaration.value, builder),
- );
+ if (
+ typeof declaration.value !== "object" ||
+ declaration.value.type !== "currentcolor"
+ ) {
+ builder.addDescriptor(
+ "--__rn-css-color",
+ parseColor(declaration.value, builder),
+ );
+ }
}
export function parseColorDeclaration(
@@ -1609,7 +1611,7 @@ export function parseColor(cssColor: CssColor, builder: StylesheetBuilder) {
switch (cssColor.type) {
case "currentcolor":
- return [{}, "var", "__rn-css-current-color"] as const;
+ return [{}, "var", "__rn-css-color"] as const;
case "light-dark": {
const extraRule: StyleRule = {
s: [],
@@ -1952,7 +1954,7 @@ export function parseFontWeight(
switch (fontWeight.type) {
case "absolute":
if (fontWeight.value.type === "weight") {
- return fontWeight.value.value.toString();
+ return fontWeight.value.value;
} else {
return fontWeight.value.type;
}
@@ -1982,11 +1984,11 @@ export function parseTextShadow(
parseColor(textShadow.color, builder),
);
builder.addDescriptor(
- "textShadowOffset.width",
+ "*.textShadowOffset.width",
parseLength(textShadow.xOffset, builder),
);
builder.addDescriptor(
- "textShadowOffset.height",
+ "*.textShadowOffset.height",
parseLength(textShadow.yOffset, builder),
);
builder.addDescriptor(
@@ -2324,24 +2326,22 @@ export function parseGap(
builder: StylesheetBuilder,
) {
if ("column" in declaration.value) {
- builder.addDescriptor(
- "row-gap",
- parseGapValue(declaration.value.row, builder),
- );
- builder.addDescriptor(
- "column-gap",
- parseGapValue(declaration.value.column, builder),
- );
+ const row = parseGapValue(declaration.value.row, builder);
+ const column = parseGapValue(declaration.value.column, builder);
- return;
- } else {
- if (declaration.value.type === "normal") {
- builder.addWarning("value", declaration.value.type);
- return;
+ if (row !== column) {
+ builder.addDescriptor("row-gap", row);
+ builder.addDescriptor("column-gap", column);
+ } else {
+ builder.addDescriptor("gap", row);
}
-
+ } else if (declaration.value.type === "normal") {
+ builder.addWarning("value", declaration.value.type);
+ } else {
return parseLength(declaration.value.value, builder);
}
+
+ return;
}
function parseGapValue(
@@ -2374,27 +2374,27 @@ export function parseBoxShadow(
) {
for (const [index, shadow] of value.entries()) {
builder.addDescriptor(
- `boxShadow.[${index}].color`,
+ `*.boxShadow.[${index}].color`,
parseColor(shadow.color, builder),
);
builder.addDescriptor(
- `boxShadow.[${index}].offsetX`,
+ `*.boxShadow.[${index}].offsetX`,
parseLength(shadow.xOffset, builder),
);
builder.addDescriptor(
- `boxShadow.[${index}].offsetY`,
+ `*.boxShadow.[${index}].offsetY`,
parseLength(shadow.yOffset, builder),
);
builder.addDescriptor(
- `boxShadow.[${index}].blurRadius`,
+ `*.boxShadow.[${index}].blurRadius`,
parseLength(shadow.blur, builder),
);
builder.addDescriptor(
- `boxShadow.[${index}].spreadDistance`,
+ `*.boxShadow.[${index}].spreadDistance`,
parseLength(shadow.spread, builder),
);
builder.addDescriptor(
- `boxShadow.[${index}].inset`,
+ `*.boxShadow.[${index}].inset`,
shadow.inset ? true : undefined,
);
}
diff --git a/src/compiler/inline-variables.ts b/src/compiler/inline-variables.ts
new file mode 100644
index 00000000..609760c1
--- /dev/null
+++ b/src/compiler/inline-variables.ts
@@ -0,0 +1,209 @@
+import type {
+ Declaration,
+ DeclarationBlock,
+ StyleSheet,
+ TokenOrValue,
+} from "lightningcss";
+
+import type { UniqueVarInfo } from "./compiler.types";
+
+export function inlineVariables(
+ stylesheet: StyleSheet,
+ vars: Map,
+) {
+ for (const [name, info] of [...vars]) {
+ if (info.count !== 1) {
+ vars.delete(name);
+ } else {
+ flattenVar(name, vars);
+ }
+ }
+
+ stylesheet.rules = stylesheet.rules.map(function checkRule(rule) {
+ switch (rule.type) {
+ case "custom":
+ case "font-face":
+ case "font-palette-values":
+ case "font-feature-values":
+ case "namespace":
+ case "layer-statement":
+ case "property":
+ case "view-transition":
+ case "ignored":
+ case "unknown":
+ case "import":
+ case "page":
+ case "counter-style":
+ case "moz-document":
+ case "nesting":
+ case "viewport":
+ case "custom-media":
+ case "scope":
+ case "starting-style":
+ return rule;
+
+ case "media":
+ rule.value.rules = rule.value.rules.map((rule) => checkRule(rule));
+ return rule;
+ case "keyframes":
+ rule.value.keyframes = rule.value.keyframes.map((keyframe) => {
+ keyframe.declarations =
+ replaceDeclarationBlock(keyframe.declarations, vars) ??
+ keyframe.declarations;
+
+ return keyframe;
+ });
+ return rule;
+ case "style":
+ rule.value.declarations = replaceDeclarationBlock(
+ rule.value.declarations,
+ vars,
+ );
+
+ rule.value.rules = rule.value.rules?.flatMap((rule) => checkRule(rule));
+
+ return rule;
+ case "nested-declarations":
+ rule.value.declarations =
+ replaceDeclarationBlock(rule.value.declarations, vars) ?? {};
+ return rule;
+ case "supports":
+ rule.value.rules = rule.value.rules.flatMap((rule) => checkRule(rule));
+ return rule;
+ case "layer-block":
+ rule.value.rules = rule.value.rules.flatMap((rule) => checkRule(rule));
+ return rule;
+ case "container":
+ rule.value.rules = rule.value.rules.flatMap((rule) => checkRule(rule));
+ return rule;
+ }
+ });
+
+ return stylesheet;
+}
+
+function replaceDeclarationBlock(
+ block: DeclarationBlock | undefined,
+ vars: Map,
+) {
+ if (!block) return;
+
+ block.declarations = block.declarations
+ ?.map((decl) => {
+ return replaceDeclaration(decl, vars);
+ })
+ .filter((d) => !!d);
+
+ block.importantDeclarations = block.importantDeclarations
+ ?.map((decl) => {
+ return replaceDeclaration(decl, vars);
+ })
+ .filter((d) => !!d);
+
+ return block;
+}
+
+function replaceDeclaration(
+ declaration: Declaration,
+ vars: Map,
+) {
+ if (
+ declaration.property !== "unparsed" &&
+ declaration.property !== "custom"
+ ) {
+ return declaration;
+ }
+
+ if (declaration.property === "custom" && vars.has(declaration.value.name)) {
+ return;
+ }
+
+ declaration.value.value = declaration.value.value.flatMap((part) => {
+ return flattenPart(part, vars);
+ });
+
+ return declaration;
+}
+
+function flattenPart(
+ part: TokenOrValue,
+ vars: Map,
+): TokenOrValue | TokenOrValue[] {
+ if (part.type === "var") {
+ const varInfo = vars.get(part.value.name.ident);
+
+ if (!varInfo) {
+ part.value.fallback = part.value.fallback?.flatMap((arg) => {
+ return flattenPart(arg, vars);
+ });
+
+ return part;
+ } else if (varInfo.value === undefined) {
+ const fallback = part.value.fallback?.flatMap((arg) => {
+ return flattenPart(arg, vars);
+ });
+
+ return fallback ?? [];
+ }
+
+ return varInfo.value;
+ } else if (part.type === "function") {
+ part.value.arguments = part.value.arguments.flatMap((arg) => {
+ return flattenPart(arg, vars);
+ });
+ }
+
+ return part;
+}
+
+function flattenVar(
+ name: string,
+ vars: Map,
+ seen = new Set(),
+) {
+ if (seen.has(name)) {
+ vars.delete(name);
+ }
+
+ seen.add(name);
+
+ let varInfo = vars.get(name);
+
+ if (!varInfo || varInfo.flat) {
+ return;
+ }
+
+ let varInfoValue = varInfo.value?.flatMap((part) => {
+ if (part.type === "var") {
+ const name = part.value.name.ident;
+
+ flattenVar(name, vars, seen);
+
+ const nestedVarInfo = vars.get(part.value.name.ident);
+ if (nestedVarInfo?.value) {
+ return nestedVarInfo.value;
+ }
+ }
+ return flattenPart(part, vars);
+ });
+
+ // If the variable is shorthand for "initial", substitute it for undefined
+ if (
+ varInfoValue?.length === 2 &&
+ varInfoValue[0]?.type === "token" &&
+ varInfoValue[0].value.type === "ident" &&
+ varInfoValue[0].value.value === "initial" &&
+ varInfoValue[1]?.type === "token" &&
+ varInfoValue[1].value.type === "white-space"
+ ) {
+ varInfoValue = undefined;
+ }
+
+ varInfo = {
+ count: 1,
+ flat: true,
+ value: varInfoValue,
+ };
+
+ vars.set(name, varInfo);
+}
diff --git a/src/compiler/stylesheet.ts b/src/compiler/stylesheet.ts
index a23514a8..8d8d51ef 100644
--- a/src/compiler/stylesheet.ts
+++ b/src/compiler/stylesheet.ts
@@ -391,6 +391,10 @@ export class StylesheetBuilder {
let propPath: string | string[] | undefined =
this.mapping[rawProperty] ?? this.mapping[property] ?? this.mapping["*"];
+ if (typeof property === "string" && property.includes(".")) {
+ propPath = property.split(".");
+ }
+
if (Array.isArray(propPath)) {
const [first, second] = propPath;
diff --git a/src/jest/index.ts b/src/jest/index.ts
index fd57173b..26beaf6e 100644
--- a/src/jest/index.ts
+++ b/src/jest/index.ts
@@ -59,12 +59,12 @@ export function compileWithAutoDebug(
{
debug = debugDefault,
...options
- }: CompilerOptions & { debug?: boolean } = {},
+ }: CompilerOptions & { debug?: boolean | "verbose" } = {},
) {
const logger = debug
? (text: string) => {
// Just log the rules
- if (text.startsWith("[")) {
+ if (text.startsWith("[") && debug === "verbose") {
console.log(`Rules:\n---\n${text}`);
}
}
diff --git a/src/runtime/native/styles/calculate-props.ts b/src/runtime/native/styles/calculate-props.ts
index c8f53a8f..a24bd77e 100644
--- a/src/runtime/native/styles/calculate-props.ts
+++ b/src/runtime/native/styles/calculate-props.ts
@@ -115,7 +115,7 @@ export function applyDeclarations(
// Dynamic styles
let value: any = declaration[0];
let propPath = declaration[1];
- let prop: string;
+ let prop: string | number;
if (Array.isArray(propPath)) {
const [first, ...rest] = propPath;
@@ -132,7 +132,21 @@ export function applyDeclarations(
target = topLevelTarget[first];
}
+ let previousProp: string | number = first;
+ let previousTarget = topLevelTarget;
+
for (prop of rest) {
+ if (prop.startsWith("[") && prop.endsWith("]")) {
+ prop = Number(prop.slice(1, -1));
+
+ if (!Array.isArray(previousTarget[previousProp])) {
+ previousTarget[previousProp] = [];
+ target = previousTarget[previousProp];
+ }
+ }
+ previousTarget = target;
+ previousProp = prop;
+
target[prop] ??= {};
target = target[prop];
}
diff --git a/src/runtime/native/styles/shorthands/box-shadow.ts b/src/runtime/native/styles/shorthands/box-shadow.ts
index fa6c4691..f3f814bb 100644
--- a/src/runtime/native/styles/shorthands/box-shadow.ts
+++ b/src/runtime/native/styles/shorthands/box-shadow.ts
@@ -10,32 +10,11 @@ const blurRadius = ["blurRadius", "number"] as const;
const spreadDistance = ["spreadDistance", "number"] as const;
// const inset = ["inset", "string"] as const;
-function deepFlattenToArrayOfStyleDescriptors(
- arr: StyleDescriptor[],
-): StyleDescriptor[] {
- const result: StyleDescriptor[] = [];
- const stack = [arr];
- while (stack.length > 0) {
- const current = stack.pop();
- if (Array.isArray(current)) {
- if (current.length > 0 && Array.isArray(current[0])) {
- for (let i = current.length - 1; i >= 0; i--) {
- const elem = current[i];
- if (isStyleDescriptorArray(elem)) stack.push(elem);
- }
- } else {
- result.push(current);
- }
- }
- }
- return result;
-}
-
const handler = shorthandHandler(
[
+ [offsetX, offsetY, blurRadius, spreadDistance],
[offsetX, offsetY, blurRadius, spreadDistance, color],
[color, offsetX, offsetY],
- [color, offsetX, offsetY, blurRadius],
[color, offsetX, offsetY, blurRadius, spreadDistance],
[offsetX, offsetY, color],
[offsetX, offsetY, blurRadius, color],
@@ -55,10 +34,11 @@ export const boxShadow: StyleFunctionResolver = (
if (!isStyleDescriptorArray(args)) {
return args;
} else {
- return deepFlattenToArrayOfStyleDescriptors(args)
+ return args
+ .flatMap(flattenShadowDescriptor)
.map((shadows) => {
if (shadows === undefined) {
- return [];
+ return;
} else {
return omitTransparentShadows(
handler(resolveValue, shadows, get, options),
@@ -69,6 +49,16 @@ export const boxShadow: StyleFunctionResolver = (
}
};
+function flattenShadowDescriptor(arg: StyleDescriptor): StyleDescriptor[] {
+ if (isStyleDescriptorArray(arg) && isStyleDescriptorArray(arg[0])) {
+ return arg.map((arg) => {
+ return flattenShadowDescriptor(arg);
+ });
+ }
+
+ return [arg];
+}
+
function omitTransparentShadows(style: unknown) {
if (typeof style === "object" && style && "color" in style) {
if (style.color === "#0000" || style.color === "transparent") {
diff --git a/src/style-collection/root.ts b/src/style-collection/root.ts
index 67f28f7c..3c59dd77 100644
--- a/src/style-collection/root.ts
+++ b/src/style-collection/root.ts
@@ -1,3 +1,5 @@
+import { Platform, PlatformColor } from "react-native";
+
import type { StyleDescriptor, VariableValue } from "react-native-css/compiler";
import { testMediaQuery } from "../runtime/native/conditions/media-query";
@@ -35,3 +37,12 @@ export const rootVariables = rootVariableFamily();
export const universalVariables = rootVariableFamily();
rootVariables("__rn-css-rem").set([[14]]);
+// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
+rootVariables("__rn-css-color").set([
+ [
+ Platform.OS === "ios"
+ ? PlatformColor("label", "labelColor")
+ : PlatformColor("?attr/textColorPrimary", "SystemBaseHighColor"),
+ ],
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+] as any);