Skip to content

Commit d525314

Browse files
authored
feat: react-native-safe-area-context support (#118)
1 parent 4156893 commit d525314

File tree

9 files changed

+457
-1
lines changed

9 files changed

+457
-1
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
"react-test-renderer": "^19.1.0",
204204
"release-it": "^19.0.4",
205205
"tailwindcss": "^4.1.12",
206+
"tailwindcss-safe-area": "^1.1.0",
206207
"typescript": "^5.9.2",
207208
"typescript-eslint": "^8.40.0"
208209
},

src/__tests__/vendor/tailwind/_tailwind.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export async function render(
6060
css += `@import "tailwindcss/preflight.css" layer(base);\n`;
6161
}
6262

63-
css += `@import "tailwindcss/utilities.css" layer(utilities) source(none);\n`;
63+
css += `@import "tailwindcss/utilities.css" layer(utilities) source(none);\n@import "tailwindcss-safe-area";`;
6464
}
6565

6666
css += sourceInline
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
import type { ViewProps } from "react-native";
2+
3+
import { SafeAreaProvider } from "react-native-css/components/react-native-safe-area-context";
4+
import { type Metrics } from "react-native-safe-area-context";
5+
6+
import { renderCurrentTest } from "./_tailwind";
7+
8+
const initialMetrics: Metrics = {
9+
insets: {
10+
top: 10,
11+
bottom: 10,
12+
left: 10,
13+
right: 10,
14+
},
15+
frame: {
16+
x: 0,
17+
y: 0,
18+
height: 100,
19+
width: 100,
20+
},
21+
};
22+
23+
function Wrapper({ children }: ViewProps) {
24+
return (
25+
<SafeAreaProvider initialMetrics={initialMetrics}>
26+
{children}
27+
</SafeAreaProvider>
28+
);
29+
}
30+
31+
test("m-safe", async () => {
32+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
33+
props: {
34+
style: {
35+
marginBottom: 10,
36+
marginLeft: 10,
37+
marginRight: 10,
38+
marginTop: 10,
39+
},
40+
},
41+
});
42+
});
43+
44+
test("mx-safe", async () => {
45+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
46+
props: {
47+
style: {
48+
marginLeft: 10,
49+
marginRight: 10,
50+
},
51+
},
52+
});
53+
});
54+
test("my-safe", async () => {
55+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
56+
props: {
57+
style: {
58+
marginBottom: 10,
59+
marginTop: 10,
60+
},
61+
},
62+
});
63+
});
64+
test("ms-safe", async () => {
65+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
66+
props: {
67+
style: {
68+
marginInlineStart: 10,
69+
},
70+
},
71+
});
72+
});
73+
test("me-safe", async () => {
74+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
75+
props: {
76+
style: {
77+
marginInlineEnd: 10,
78+
},
79+
},
80+
});
81+
});
82+
test("mt-safe", async () => {
83+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
84+
props: {
85+
style: {
86+
marginTop: 10,
87+
},
88+
},
89+
});
90+
});
91+
test("mr-safe", async () => {
92+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
93+
props: {
94+
style: {
95+
marginRight: 10,
96+
},
97+
},
98+
});
99+
});
100+
test("mb-safe", async () => {
101+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
102+
props: {
103+
style: {
104+
marginBottom: 10,
105+
},
106+
},
107+
});
108+
});
109+
110+
test("ml-safe", async () => {
111+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
112+
props: {
113+
style: {
114+
marginLeft: 10,
115+
},
116+
},
117+
});
118+
});
119+
120+
test("p-safe", async () => {
121+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
122+
props: {
123+
style: {
124+
paddingBottom: 10,
125+
paddingLeft: 10,
126+
paddingRight: 10,
127+
paddingTop: 10,
128+
},
129+
},
130+
});
131+
});
132+
133+
test("px-safe", async () => {
134+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
135+
props: {
136+
style: {
137+
paddingLeft: 10,
138+
paddingRight: 10,
139+
},
140+
},
141+
});
142+
});
143+
test("py-safe", async () => {
144+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
145+
props: {
146+
style: {
147+
paddingBottom: 10,
148+
paddingTop: 10,
149+
},
150+
},
151+
});
152+
});
153+
test("ps-safe", async () => {
154+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
155+
props: {
156+
style: {
157+
paddingInlineStart: 10,
158+
},
159+
},
160+
});
161+
});
162+
test("pe-safe", async () => {
163+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
164+
props: {
165+
style: {
166+
paddingInlineEnd: 10,
167+
},
168+
},
169+
});
170+
});
171+
test("pt-safe", async () => {
172+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
173+
props: {
174+
style: {
175+
paddingTop: 10,
176+
},
177+
},
178+
});
179+
});
180+
test("pr-safe", async () => {
181+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
182+
props: {
183+
style: {
184+
paddingRight: 10,
185+
},
186+
},
187+
});
188+
});
189+
test("pb-safe", async () => {
190+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
191+
props: {
192+
style: {
193+
paddingBottom: 10,
194+
},
195+
},
196+
});
197+
});
198+
test("pl-safe", async () => {
199+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
200+
props: {
201+
style: {
202+
paddingLeft: 10,
203+
},
204+
},
205+
});
206+
});
207+
208+
test("min-h-screen-safe", async () => {
209+
// calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)));
210+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
211+
props: {
212+
style: {
213+
minHeight: 1314,
214+
},
215+
},
216+
});
217+
});
218+
219+
test("max-h-screen-safe", async () => {
220+
// calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)));
221+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
222+
props: {
223+
style: {
224+
maxHeight: 1314,
225+
},
226+
},
227+
});
228+
});
229+
230+
test("h-screen-safe", async () => {
231+
// calc(100vh - (env(safe-area-inset-top) + env(safe-area-inset-bottom)));
232+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
233+
props: {
234+
style: {
235+
height: 1314,
236+
},
237+
},
238+
});
239+
});
240+
241+
test("inset-safe", async () => {
242+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
243+
props: {
244+
style: {
245+
bottom: 10,
246+
left: 10,
247+
right: 10,
248+
top: 10,
249+
},
250+
},
251+
});
252+
});
253+
test("inset-x-safe", async () => {
254+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
255+
props: {
256+
style: {
257+
left: 10,
258+
right: 10,
259+
},
260+
},
261+
});
262+
});
263+
test("inset-y-safe", async () => {
264+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
265+
props: {
266+
style: {
267+
bottom: 10,
268+
top: 10,
269+
},
270+
},
271+
});
272+
});
273+
test("start-safe", async () => {
274+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
275+
props: {
276+
style: {
277+
insetInlineStart: 10,
278+
},
279+
},
280+
});
281+
});
282+
test("end-safe", async () => {
283+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
284+
props: {
285+
style: {
286+
insetInlineEnd: 10,
287+
},
288+
},
289+
});
290+
});
291+
test("top-safe", async () => {
292+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
293+
props: {
294+
style: {
295+
top: 10,
296+
},
297+
},
298+
});
299+
});
300+
test("right-safe", async () => {
301+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
302+
props: {
303+
style: {
304+
right: 10,
305+
},
306+
},
307+
});
308+
});
309+
test("bottom-safe", async () => {
310+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
311+
props: {
312+
style: {
313+
bottom: 10,
314+
},
315+
},
316+
});
317+
});
318+
test("left-safe", async () => {
319+
expect(await renderCurrentTest({ wrapper: Wrapper })).toStrictEqual({
320+
props: {
321+
style: {
322+
left: 10,
323+
},
324+
},
325+
});
326+
});
327+
328+
test("pb-safe-offset-4", async () => {
329+
// calc(env(safe-area-inset-right) + 2rem);
330+
expect(
331+
await renderCurrentTest({
332+
wrapper: Wrapper,
333+
}),
334+
).toStrictEqual({
335+
props: {
336+
style: {
337+
paddingBottom: 24, // 10 + 14
338+
},
339+
},
340+
});
341+
});
342+
343+
test("pb-safe-or-20", async () => {
344+
// --spacing: 3.5
345+
// max(env(safe-area-inset-bottom), calc(var(--spacing) * 20));
346+
expect(
347+
await renderCurrentTest({
348+
wrapper: Wrapper,
349+
}),
350+
).toStrictEqual({
351+
props: {
352+
style: {
353+
paddingBottom: 70,
354+
},
355+
},
356+
});
357+
});

0 commit comments

Comments
 (0)