Skip to content

Commit 64d6a52

Browse files
authored
feat: add basic pseudo element selectors (#103)
1 parent cf115c3 commit 64d6a52

File tree

10 files changed

+385
-118
lines changed

10 files changed

+385
-118
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import { fireEvent, screen } from "@testing-library/react-native";
2+
3+
import { Switch, TextInput, View } from "../../../components";
4+
import { render } from "./_tailwind";
5+
6+
const testID = "component";
7+
8+
test("hover", async () => {
9+
await render(<TextInput testID={testID} className="hover:text-white" />);
10+
11+
const component = screen.getByTestId(testID);
12+
13+
expect(component).toHaveStyle(undefined);
14+
15+
fireEvent(component, "hoverIn");
16+
expect(component).toHaveStyle({ color: "#fff" });
17+
18+
fireEvent(component, "hoverOut");
19+
expect(component).toHaveStyle(undefined);
20+
});
21+
22+
test("focus", async () => {
23+
await render(<TextInput testID={testID} className="focus:text-white" />);
24+
25+
const component = screen.getByTestId(testID);
26+
27+
expect(component).toHaveStyle(undefined);
28+
29+
fireEvent(component, "focus");
30+
expect(component).toHaveStyle({ color: "#fff" });
31+
32+
fireEvent(component, "blur");
33+
expect(component).toHaveStyle(undefined);
34+
});
35+
36+
test("active", async () => {
37+
await render(<TextInput testID={testID} className="active:text-white" />);
38+
39+
const component = screen.getByTestId(testID);
40+
41+
expect(component).toHaveStyle(undefined);
42+
43+
fireEvent(component, "pressIn");
44+
expect(component).toHaveStyle({ color: "#fff" });
45+
46+
fireEvent(component, "pressOut");
47+
expect(component).toHaveStyle(undefined);
48+
});
49+
50+
test("mixed", async () => {
51+
await render(
52+
<TextInput testID={testID} className="active:hover:focus:text-white" />,
53+
);
54+
55+
const component = screen.getByTestId(testID);
56+
expect(component).toHaveStyle(undefined);
57+
58+
fireEvent(component, "pressIn");
59+
expect(component).toHaveStyle(undefined);
60+
61+
fireEvent(component, "hoverIn");
62+
expect(component).toHaveStyle(undefined);
63+
64+
fireEvent(component, "focus");
65+
expect(component).toHaveStyle({ color: "#fff" });
66+
});
67+
68+
test("selection", async () => {
69+
await render(<TextInput testID={testID} className="selection:text-black" />);
70+
71+
const component = screen.getByTestId(testID);
72+
expect(component.props).toEqual({
73+
testID,
74+
selectionColor: "#000",
75+
children: undefined,
76+
style: {},
77+
});
78+
});
79+
80+
test("ltr:", async () => {
81+
await render(<View testID={testID} className="ltr:text-black" />);
82+
83+
const component = screen.getByTestId(testID);
84+
expect(component).toHaveStyle({
85+
color: "#000",
86+
});
87+
});
88+
89+
test("placeholder", async () => {
90+
await render(
91+
<TextInput testID={testID} className="placeholder:text-black" />,
92+
);
93+
94+
const component = screen.getByTestId(testID);
95+
expect(component.props).toEqual({
96+
testID,
97+
placeholderTextColor: "#000",
98+
children: undefined,
99+
style: {},
100+
});
101+
});
102+
103+
test("disabled", async () => {
104+
const { rerender } = await render(
105+
<Switch testID={testID} className="disabled:bg-black" />,
106+
);
107+
108+
const component = screen.getByTestId(testID);
109+
expect(component.props).toEqual(
110+
expect.objectContaining({
111+
testID,
112+
style: {
113+
height: 31,
114+
width: 51,
115+
},
116+
}),
117+
);
118+
119+
rerender(<Switch testID={testID} disabled className="disabled:bg-black" />);
120+
121+
expect(component.props).toEqual(
122+
expect.objectContaining({
123+
testID,
124+
style: [
125+
{
126+
height: 31,
127+
width: 51,
128+
},
129+
{
130+
backgroundColor: "#000",
131+
},
132+
],
133+
}),
134+
);
135+
136+
rerender(
137+
<Switch testID={testID} disabled={false} className="disabled:bg-black" />,
138+
);
139+
140+
expect(component.props).toEqual(
141+
expect.objectContaining({
142+
testID,
143+
style: {
144+
height: 31,
145+
width: 51,
146+
},
147+
}),
148+
);
149+
});

src/compiler/attributes.test.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/compiler/compiler.types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export type MediaCondition =
177177
// Comparison
178178
| [
179179
MediaFeatureComparison,
180-
MediaFeatureNameFor_MediaFeatureId | MediaFeatureNameFor_MediaFeatureId,
180+
MediaFeatureNameFor_MediaFeatureId | "dir",
181181
StyleDescriptor,
182182
]
183183
// [Start, End]

src/compiler/pseudo-elements.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { isStyleFunction } from "../runtime/utils";
2+
import type { StyleDeclaration, StyleRule } from "./compiler.types";
3+
4+
export function modifyRuleForSelection(rule: StyleRule): StyleRule | undefined {
5+
if (!rule.d) {
6+
return;
7+
}
8+
9+
rule.d = rule.d.flatMap((declaration): StyleDeclaration[] => {
10+
return modifyStyleDeclaration(declaration, "color", "selectionColor");
11+
});
12+
13+
return rule;
14+
}
15+
16+
export function modifyRuleForPlaceholder(
17+
rule: StyleRule,
18+
): StyleRule | undefined {
19+
if (!rule.d) {
20+
return;
21+
}
22+
23+
rule.d = rule.d.flatMap((declaration): StyleDeclaration[] => {
24+
return modifyStyleDeclaration(declaration, "color", "placeholderTextColor");
25+
});
26+
27+
return rule;
28+
}
29+
30+
function modifyStyleDeclaration(
31+
declaration: StyleDeclaration,
32+
from: string,
33+
to: string,
34+
): StyleDeclaration[] {
35+
if (Array.isArray(declaration)) {
36+
if (isStyleFunction(declaration) && declaration[2] === from) {
37+
declaration = [...declaration] as StyleDeclaration;
38+
declaration[2] = [to];
39+
return [declaration];
40+
} else if (declaration[1] === from) {
41+
declaration = [...declaration] as StyleDeclaration;
42+
declaration[1] = [to];
43+
return [declaration];
44+
}
45+
} else if (typeof declaration === "object") {
46+
const { color: selectionColor, ...rest } = declaration;
47+
48+
if (selectionColor) {
49+
return [rest, [selectionColor, [to]]] as StyleDeclaration[];
50+
}
51+
}
52+
53+
return [declaration];
54+
}

0 commit comments

Comments
 (0)