Skip to content

Commit bec0751

Browse files
authored
Merge pull request #14 from MOCHI-inc-JAPAN/upmain
Upmain
2 parents 613fd2a + b40cb92 commit bec0751

7 files changed

Lines changed: 250 additions & 63 deletions

File tree

example/src/PerfTest.tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { useMemo } from 'react';
2+
import { Stack } from './components';
3+
import { styled } from './styles';
4+
5+
let measured = false;
6+
7+
export default function PerfTest() {
8+
const start = useMemo(() => new Date(), []);
9+
10+
return (
11+
<Wrapper
12+
onLayout={() => {
13+
if (!measured) {
14+
measured = true;
15+
console.log(
16+
`Time taken: ${new Date().getTime() - start.getTime()} ms`
17+
);
18+
}
19+
}}
20+
>
21+
<Content>
22+
<Stack axis="y" space="4">
23+
{Array.from({ length: 1000 }).map((_, i) => (
24+
<Box key={i}>
25+
<BoxText>{i + 1}</BoxText>
26+
</Box>
27+
))}
28+
</Stack>
29+
</Content>
30+
</Wrapper>
31+
);
32+
}
33+
34+
const Wrapper = styled('SafeAreaView', {
35+
flex: 1,
36+
backgroundColor: '$background',
37+
});
38+
39+
const Content = styled('ScrollView', {
40+
flex: 1,
41+
}).attrs((p) => ({
42+
contentContainerStyle: {
43+
padding: p.theme.space[2],
44+
},
45+
}));
46+
47+
const Box = styled('View', {
48+
minHeight: 100,
49+
backgroundColor: '$primaryMuted',
50+
flexCenter: 'row',
51+
borderRadius: '$md',
52+
});
53+
54+
const BoxText = styled('Text', {
55+
color: '$primaryText',
56+
});

example/src/type-test.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { styled, css } from './styles';
2+
3+
const View = styled('View', {});
4+
5+
const csstest = css({
6+
fontSize: 16,
7+
});
8+
9+
export const Test = <View css={csstest} />;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "stitches-native",
33
"description": "The modern CSS-in-JS library for React Native",
4-
"version": "0.3.1",
4+
"version": "0.4.0",
55
"license": "MIT",
66
"author": "Teemu Taskula",
77
"repository": "https://github.com/Temzasse/stitches-native",

src/internals/index.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,19 +92,28 @@ export function createStitches(config = {}) {
9292

9393
const styles = _styles;
9494

95-
const styleSheets = utils.createStyleSheets({
96-
styles,
97-
config,
98-
themes,
99-
variants,
100-
compoundVariants,
101-
});
95+
const styleSheets = {};
10296

10397
let attrsFn;
10498

10599
let Comp = forwardRef((props, ref) => {
106100
const theme = useThemeInternal();
107-
const styleSheet = styleSheets[theme.definition.__ID__];
101+
102+
const styleSheet = useMemo(() => {
103+
const _styleSheet = styleSheets[theme.definition.__ID__];
104+
if (_styleSheet) {
105+
return _styleSheet;
106+
}
107+
styleSheets[theme.definition.__ID__] = utils.createStyleSheet({
108+
styles,
109+
config,
110+
theme,
111+
variants,
112+
compoundVariants,
113+
});
114+
return styleSheets[theme.definition.__ID__];
115+
}, [theme]);
116+
108117
const { width: windowWidth } = useWindowDimensions();
109118

110119
let variantStyles = [];

src/internals/utils.js

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -192,58 +192,50 @@ export function processStyles({ styles, theme, config }) {
192192
}, {});
193193
}
194194

195-
export function createStyleSheets({
196-
themes,
195+
export function createStyleSheet({
196+
theme,
197197
styles,
198198
config,
199199
variants,
200200
compoundVariants,
201201
}) {
202-
const styleSheets = themes.reduce((styleSheetAcc, theme) => {
203-
styleSheetAcc[theme.definition.__ID__] = StyleSheet.create({
204-
base: styles
205-
? processStyles({ styles, config, theme: theme.values })
206-
: {},
207-
// Variant styles
208-
...Object.entries(variants).reduce(
209-
(variantsAcc, [vartiantProp, variantValues]) => {
210-
Object.entries(variantValues).forEach(
211-
([variantName, variantStyles]) => {
212-
// Eg. `color_primary` or `size_small`
213-
const key = `${vartiantProp}_${variantName}`;
214-
215-
variantsAcc[key] = processStyles({
216-
styles: variantStyles,
217-
config,
218-
theme: theme.values,
219-
});
220-
}
221-
);
222-
return variantsAcc;
223-
},
224-
{}
225-
),
226-
// Compound variant styles
227-
...compoundVariants.reduce((compoundAcc, compoundVariant) => {
228-
const { css, ...compounds } = compoundVariant;
229-
const compoundEntries = Object.entries(compounds);
230-
231-
if (compoundEntries.length > 1) {
232-
const key = getCompoundKey(compoundEntries);
233-
234-
compoundAcc[key] = processStyles({
235-
styles: css || {},
236-
config,
237-
theme: theme.values,
238-
});
239-
}
240-
241-
return compoundAcc;
242-
}, {}),
243-
});
244-
245-
return styleSheetAcc;
246-
}, {});
202+
return StyleSheet.create({
203+
base: styles ? processStyles({ styles, config, theme: theme.values }) : {},
204+
// Variant styles
205+
...Object.entries(variants).reduce(
206+
(variantsAcc, [variantProp, variantValues]) => {
207+
Object.entries(variantValues).forEach(
208+
([variantName, variantStyles]) => {
209+
// Eg. `color_primary` or `size_small`
210+
const key = `${variantProp}_${variantName}`;
211+
212+
variantsAcc[key] = processStyles({
213+
styles: variantStyles,
214+
config,
215+
theme: theme.values,
216+
});
217+
}
218+
);
219+
return variantsAcc;
220+
},
221+
{}
222+
),
223+
// Compound variant styles
224+
...compoundVariants.reduce((compoundAcc, compoundVariant) => {
225+
const { css, ...compounds } = compoundVariant;
226+
const compoundEntries = Object.entries(compounds);
227+
228+
if (compoundEntries.length > 1) {
229+
const key = getCompoundKey(compoundEntries);
230+
231+
compoundAcc[key] = processStyles({
232+
styles: css || {},
233+
config,
234+
theme: theme.values,
235+
});
236+
}
247237

248-
return styleSheets;
238+
return compoundAcc;
239+
}, {}),
240+
});
249241
}

src/tests/index.test.tsx

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,130 @@ describe('Basic', () => {
2626
width: 100,
2727
});
2828
});
29+
30+
it('Functionality of styled() should not trigger recompute when a runtime theme is not used', () => {
31+
const { styled, createTheme } = createStitches({
32+
theme: {
33+
sizes: { demoWidth: 100 },
34+
},
35+
});
36+
37+
const Comp = styled('View', {
38+
backgroundColor: 'red',
39+
height: 100,
40+
width: '$demoWidth',
41+
});
42+
43+
render(<Comp />);
44+
45+
createTheme({ sizes: { demoWidth: 10 } });
46+
47+
const { toJSON } = render(<Comp />);
48+
49+
const result = toJSON();
50+
51+
expect(result?.type).toEqual('View');
52+
expect(result?.props.style[0]).toMatchObject({
53+
backgroundColor: 'red',
54+
height: 100,
55+
width: 100,
56+
});
57+
});
58+
});
59+
60+
describe('Runtime', () => {
61+
it('Functionality of ThemeProvider', () => {
62+
const { styled, createTheme, ThemeProvider } = createStitches({
63+
theme: {
64+
sizes: { demoWidth: 100 },
65+
},
66+
});
67+
68+
const Comp = styled('View', {
69+
backgroundColor: 'red',
70+
height: 100,
71+
width: '$demoWidth',
72+
});
73+
74+
const newTheme = createTheme({ sizes: { demoWidth: 30 } });
75+
76+
const { toJSON } = render(
77+
<ThemeProvider theme={newTheme}>
78+
<Comp />
79+
</ThemeProvider>
80+
);
81+
82+
const result = toJSON();
83+
84+
expect(result?.type).toEqual('View');
85+
expect(result?.props.style[0]).toMatchObject({
86+
backgroundColor: 'red',
87+
height: 100,
88+
width: 30,
89+
});
90+
});
91+
92+
it('Functionality of ThemeProvider should use new theme when a runtime theme is added', () => {
93+
const { styled, createTheme, ThemeProvider } = createStitches({
94+
theme: {
95+
sizes: { demoWidth: 100 },
96+
},
97+
});
98+
99+
const Comp = styled('View', {
100+
backgroundColor: 'red',
101+
height: 100,
102+
width: '$demoWidth',
103+
});
104+
105+
const newTheme = createTheme({ sizes: { demoWidth: 10 } });
106+
107+
const { toJSON } = render(
108+
<ThemeProvider theme={newTheme}>
109+
<Comp />
110+
</ThemeProvider>
111+
);
112+
113+
const result = toJSON();
114+
115+
expect(result?.type).toEqual('View');
116+
expect(result?.props.style[0]).toMatchObject({
117+
backgroundColor: 'red',
118+
height: 100,
119+
width: 10,
120+
});
121+
});
122+
123+
it('Functionality of ThemeProvider should trigger recompute when a runtime theme is added', () => {
124+
const { styled, createTheme, ThemeProvider } = createStitches({
125+
theme: {
126+
sizes: { demoWidth: 100 },
127+
},
128+
});
129+
130+
const Comp = styled('View', {
131+
backgroundColor: 'red',
132+
height: 100,
133+
width: '$demoWidth',
134+
});
135+
136+
render(<Comp />);
137+
138+
const newTheme = createTheme({ sizes: { demoWidth: 10 } });
139+
140+
const { toJSON } = render(
141+
<ThemeProvider theme={newTheme}>
142+
<Comp />
143+
</ThemeProvider>
144+
);
145+
146+
const result = toJSON();
147+
148+
expect(result?.type).toEqual('View');
149+
expect(result?.props.style[0]).toMatchObject({
150+
backgroundColor: 'red',
151+
height: 100,
152+
width: 10,
153+
});
154+
});
29155
});

src/types/stitches.d.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,7 @@ export default interface Stitches<
124124
: unknown;
125125
};
126126
}
127-
): StyledComponent.CssComponent<
128-
StyledComponent.StyledComponentType<Composers>,
129-
StyledComponent.StyledComponentProps<Composers>,
130-
Media,
131-
CSS
132-
>;
127+
): CSS;
133128
}; // TODO: `variants` inside `css` break TS...
134129
styled: {
135130
<

0 commit comments

Comments
 (0)