Skip to content

Commit fadc623

Browse files
authored
fix: transform shorthands (#94)
1 parent 04068d6 commit fadc623

25 files changed

+292
-189
lines changed

src/__tests__/vendor/tailwind.test.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ test("transition", () => {
8787
["default-transition-duration", [[150]]],
8888
[
8989
"default-transition-timing-function",
90-
[[[{}, "cubic-bezier", [0.4, 0, 0.2, 1]]]],
90+
[[[{}, "cubicBezier", [0.4, 0, 0.2, 1]]]],
9191
],
9292
],
9393
});
@@ -117,7 +117,7 @@ test("box-shadow", () => {
117117
[
118118
[
119119
{},
120-
"@boxShadow",
120+
"boxShadow",
121121
[
122122
[{}, "var", "tw-inset-shadow", 1],
123123
[{}, "var", "tw-inset-ring-shadow", 1],
@@ -268,7 +268,7 @@ test("filter", () => {
268268
"tw-drop-shadow-size",
269269
[
270270
{},
271-
"drop-shadow",
271+
"dropShadow",
272272
[
273273
0,
274274
3,
@@ -279,7 +279,7 @@ test("filter", () => {
279279
],
280280
[
281281
"tw-drop-shadow",
282-
[{}, "drop-shadow", [{}, "var", "drop-shadow-md", 1]],
282+
[{}, "dropShadow", [{}, "var", "drop-shadow-md", 1]],
283283
],
284284
],
285285
},

src/compiler/declarations.ts

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,16 @@ const propertyRename: Record<string, string> = {
6262
"background-image": "experimental_backgroundImage",
6363
};
6464

65+
// TODO: We need a better way to handle this
6566
const unparsedRuntimeParsing = new Set([
6667
"animation",
68+
"border",
69+
"box-shadow",
6770
"text-shadow",
6871
"transform",
69-
"box-shadow",
70-
"border",
72+
"scale",
73+
"rotate",
74+
"translate",
7175
]);
7276

7377
const parsers: {
@@ -666,22 +670,22 @@ function parseTransform(
666670
) {
667671
builder.addDescriptor("transform", [
668672
{},
669-
"@transform",
673+
"transform",
670674
value.flatMap((t): StyleDescriptor[] => {
671675
switch (t.type) {
672676
case "perspective":
673-
return [[{}, "@perspective", parseLength(t.value, builder)]];
677+
return [[{}, "perspective", parseLength(t.value, builder)]];
674678
case "translate":
675679
return [
676680
[
677681
{},
678-
"@translateX",
682+
"translateX",
679683
parseLengthOrCoercePercentageToRuntime(t.value[0], builder),
680684
],
681685
[
682686
[
683687
{},
684-
"@translateY",
688+
"translateY",
685689
parseLengthOrCoercePercentageToRuntime(t.value[1], builder),
686690
],
687691
],
@@ -690,30 +694,30 @@ function parseTransform(
690694
return [
691695
[
692696
{},
693-
"@translateX",
697+
"translateX",
694698
parseLengthOrCoercePercentageToRuntime(t.value, builder),
695699
],
696700
];
697701
case "translateY":
698702
return [
699703
[
700704
{},
701-
"@translateY",
705+
"translateY",
702706
parseLengthOrCoercePercentageToRuntime(t.value, builder),
703707
],
704708
];
705709
case "rotate":
706-
return [[{}, "@rotate", parseAngle(t.value, builder)]];
710+
return [[{}, "rotate", parseAngle(t.value, builder)]];
707711
case "rotateX":
708-
return [[{}, "@rotateX", parseAngle(t.value, builder)]];
712+
return [[{}, "rotateX", parseAngle(t.value, builder)]];
709713
case "rotateY":
710-
return [[{}, "@rotateY", parseAngle(t.value, builder)]];
714+
return [[{}, "rotateY", parseAngle(t.value, builder)]];
711715
case "rotateZ":
712-
return [[{}, "@rotateZ", parseAngle(t.value, builder)]];
716+
return [[{}, "rotateZ", parseAngle(t.value, builder)]];
713717
case "scale":
714718
return [
715-
[{}, "@scaleX", parseLength(t.value[0], builder)],
716-
[{}, "@scaleY", parseLength(t.value[1], builder)],
719+
[{}, "scaleX", parseLength(t.value[0], builder)],
720+
[{}, "scaleY", parseLength(t.value[1], builder)],
717721
];
718722
case "scaleX":
719723
return [[{}, "scaleX", parseLength(t.value, builder)]];
@@ -915,18 +919,9 @@ export function parseUnparsedDeclaration(
915919
const args = parseUnparsed(declaration.value.value, builder, property);
916920

917921
if (property === "animation") {
918-
builder.addDescriptor("animation", [
919-
{},
920-
`@${toRNProperty(property)}`,
921-
args,
922-
]);
922+
builder.addDescriptor("animation", [{}, property, args]);
923923
} else {
924-
builder.addDescriptor(property, [
925-
{},
926-
`@${toRNProperty(property)}`,
927-
args,
928-
1,
929-
]);
924+
builder.addDescriptor(property, [{}, toRNProperty(property), args, 1]);
930925
}
931926
} else {
932927
const value = parseUnparsed(declaration.value.value, builder, property);
@@ -1040,7 +1035,7 @@ export function unparsedFunction(
10401035
): StyleFunction {
10411036
return [
10421037
{},
1043-
token.value.name,
1038+
toRNProperty(token.value.name),
10441039
reduceParseUnparsed(token.value.arguments, builder, property, allowAuto),
10451040
];
10461041
}
@@ -1129,7 +1124,6 @@ export function parseUnparsed(
11291124
case "scaleY":
11301125
case "translateX":
11311126
case "translateY":
1132-
tokenOrValue.value.name = `@${tokenOrValue.value.name}`;
11331127
return unparsedFunction(tokenOrValue, builder, property, allowAuto);
11341128
case "blur":
11351129
case "brightness":
@@ -2959,7 +2953,7 @@ function parseGradient(
29592953
case "linear": {
29602954
return [
29612955
{},
2962-
"@linear-gradient",
2956+
"linear-gradient",
29632957
[
29642958
parseLineDirection(gradient.direction, builder),
29652959
...gradient.items.map((item) => parseGradientItem(item, builder)),
@@ -3036,6 +3030,16 @@ function parseFilter(
30363030
[value.type]: parseAngle(value.value, builder),
30373031
} as unknown as StyleDescriptor;
30383032
case "drop-shadow":
3033+
return [
3034+
{},
3035+
toRNProperty(value.type),
3036+
[
3037+
parseLength(value.value.xOffset, builder),
3038+
parseLength(value.value.yOffset, builder),
3039+
parseLength(value.value.blur, builder),
3040+
parseColor(value.value.color, builder),
3041+
],
3042+
] as unknown as StyleDescriptor;
30393043
case "url":
30403044
return;
30413045
}

src/compiler/keyframes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function parseEasingFunction(
3030
case "cubic-bezier":
3131
return [
3232
{},
33-
"cubic-bezier",
33+
"cubicBezier",
3434
[value.x1, value.y1, value.x2, value.y2],
3535
] as const;
3636
case "steps":

src/compiler/stylesheet.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,10 @@ export class StylesheetBuilder {
342342
const [delayed, usesVariables] = postProcessStyleFunction(value);
343343

344344
rule.d ??= [];
345-
if (value[1] === "@animation") {
345+
if (
346+
value[1].startsWith("animation") ||
347+
value[1].startsWith("transition")
348+
) {
346349
rule.a ??= true;
347350
}
348351

src/jest/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ export function registerCSS(
3434
css: string,
3535
options: CompilerOptions & { debug?: boolean } = {},
3636
) {
37-
const { debug } = options;
37+
const { debug = debugDefault } = options;
3838
const compiled = compileWithAutoDebug(css, options);
39+
3940
if (debug) {
4041
console.log(
4142
`Compiled:\n---\n${inspect(

src/runtime/native/__tests__/transform.test.tsx

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,61 @@ import { render } from "@testing-library/react-native";
22
import { View } from "react-native-css/components/View";
33
import { registerCSS, testID } from "react-native-css/jest";
44

5-
test("translate", () => {
6-
registerCSS(`.my-class { translate: 10%; }`);
7-
const component = render(
8-
<View testID={testID} className="my-class" />,
9-
).getByTestId(testID);
10-
11-
expect(component.props.style).toStrictEqual({
12-
transform: [{ translateX: "10%" }, { translateY: 0 }],
5+
describe("translate", () => {
6+
test("parsed", () => {
7+
registerCSS(`.my-class { translate: 10%; }`);
8+
const component = render(
9+
<View testID={testID} className="my-class" />,
10+
).getByTestId(testID);
11+
12+
expect(component.props.style).toStrictEqual({
13+
transform: [{ translateX: "10%" }, { translateY: 0 }],
14+
});
15+
});
16+
17+
test("unparsed", () => {
18+
registerCSS(`
19+
:root {
20+
--translate-x: 2;
21+
--translate-y: 3;
22+
}
23+
.my-class { translate: var(--translate-x) var(--translate-y); }`);
24+
const component = render(
25+
<View testID={testID} className="my-class" />,
26+
).getByTestId(testID);
27+
28+
expect(component.props.style).toStrictEqual({
29+
transform: [{ translateX: 2 }, { translateY: 3 }],
30+
});
31+
});
32+
});
33+
34+
describe("scale", () => {
35+
test("parsed", () => {
36+
registerCSS(`.my-class { scale: 2 3; }`);
37+
const component = render(
38+
<View testID={testID} className="my-class" />,
39+
).getByTestId(testID);
40+
41+
expect(component.props.style).toStrictEqual({
42+
transform: [{ scaleX: 2 }, { scaleY: 3 }],
43+
});
44+
});
45+
46+
test("unparsed", () => {
47+
registerCSS(`
48+
:root {
49+
--scale-x: 2;
50+
--scale-y: 3;
51+
}
52+
.my-class { scale: var(--scale-x) var(--scale-y); }`);
53+
const component = render(
54+
<View testID={testID} className="my-class" />,
55+
).getByTestId(testID);
56+
57+
expect(component.props.style).toStrictEqual({
58+
transform: [{ scaleX: 2 }, { scaleY: 3 }],
59+
});
1360
});
1461
});
1562

@@ -77,4 +124,16 @@ describe("transform", () => {
77124
transform: [{ translateX: "20%" }],
78125
});
79126
});
127+
128+
test("multiple", () => {
129+
registerCSS(`.my-class { transform: translateX(10%) scaleX(2); }`);
130+
131+
const component = render(
132+
<View testID={testID} className="my-class" />,
133+
).getByTestId(testID);
134+
135+
expect(component.props.style).toStrictEqual({
136+
transform: [{ translateX: "10%" }, { scaleX: 2 }],
137+
});
138+
});
80139
});

src/runtime/native/react/useNativeCss.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import {
2020
type Getter,
2121
type VariableContextValue,
2222
} from "../reactivity";
23+
import { animatedComponentFamily } from "../reanimated";
2324
import { getStyledProps, stylesFamily } from "../styles";
24-
import { animatedComponentFamily } from "../styles/animation";
2525
import { updateRules } from "./rules";
2626

2727
export type Config = {

src/runtime/native/reanimated.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { ComponentType } from "react";
2+
3+
import { weakFamily } from "./reactivity";
4+
5+
export const animatedComponentFamily = weakFamily(
6+
(component: ComponentType) => {
7+
if (
8+
"displayName" in component &&
9+
component.displayName?.startsWith("Animated.")
10+
) {
11+
return component;
12+
}
13+
14+
const createAnimatedComponent =
15+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-member-access
16+
require("react-native-reanimated").createAnimatedComponent as (
17+
component: ComponentType,
18+
) => ComponentType;
19+
20+
return createAnimatedComponent(component);
21+
},
22+
);

src/runtime/native/styles/calculate-props.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type {
44
StyleDeclaration,
55
StyleRule,
66
} from "../../../compiler";
7-
import { applyValue, Specificity as S } from "../../utils";
7+
import { applyValue, getDeepPath, Specificity as S } from "../../utils";
88
import type { RenderGuard } from "../conditions/guards";
99
import {
1010
VAR_SYMBOL,
@@ -147,9 +147,10 @@ export function applyDeclarations(
147147
* mutate the props object and not create a new one
148148
*/
149149
const originalValue = value;
150-
value = {};
150+
// This needs to be a object with the [prop] so we can discover in transform arrays
151+
value = { [prop]: true };
151152
delayedStyles.push(() => {
152-
if (target[prop] === value) {
153+
if (getDeepPath(target, prop) === value) {
153154
delete target[prop];
154155
value = resolveValue(originalValue, get, {
155156
inlineVariables,

src/runtime/native/styles/defaults.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable */
22
export const transformKeys = new Set([
3+
"translate",
34
"translateX",
45
"translateY",
56
"scale",

0 commit comments

Comments
 (0)