Skip to content

Commit 94bc55c

Browse files
authored
Merge pull request #12 from jpudysz/feature/typings
feat: improve typings
2 parents 75a2495 + 8dfeab9 commit 94bc55c

File tree

12 files changed

+336
-97
lines changed

12 files changed

+336
-97
lines changed

example/src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React from 'react'
22
import { UnistylesTheme } from 'react-native-unistyles'
3-
import { ExampleScreen } from './ExampleScreen'
3+
import * as Examples from './examples'
44
import { theme } from './styles'
55

66
export const App: React.FunctionComponent = () => (
77
<UnistylesTheme theme={theme}>
8-
<ExampleScreen />
8+
<Examples.Extreme />
99
</UnistylesTheme>
1010
)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react'
2+
import { Text, View } from 'react-native'
3+
import { createStyles, useStyles } from '../styles'
4+
5+
// Use breakpoints for some values
6+
export const Breakpoints: React.FunctionComponent = () => {
7+
const { styles } = useStyles(stylesheet)
8+
9+
return (
10+
<View style={styles.dynamicContainer}>
11+
<Text>
12+
Breakpoint demo, resize me :)
13+
</Text>
14+
<Text>
15+
Row or column?
16+
</Text>
17+
</View>
18+
)
19+
}
20+
21+
const stylesheet = createStyles(theme => ({
22+
dynamicContainer: {
23+
flex: 1,
24+
justifyContent: 'center',
25+
alignItems: 'center',
26+
flexDirection: {
27+
// hints for breakpoints are available here
28+
xs: 'row',
29+
md: 'column'
30+
},
31+
backgroundColor: theme.colors.sky
32+
}
33+
}))

example/src/examples/Extreme.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
import { Text, View } from 'react-native'
3+
import { createStyles, useStyles } from '../styles'
4+
5+
// Edge cases
6+
export const Extreme: React.FunctionComponent = () => {
7+
const { styles } = useStyles(stylesheet)
8+
9+
return (
10+
<View style={styles.dynamicContainer(1)}>
11+
<Text style={styles.text}>
12+
Edge cases
13+
</Text>
14+
</View>
15+
)
16+
}
17+
18+
const stylesheet = createStyles(theme => ({
19+
// dynamic function with hints
20+
dynamicContainer: (flex: number) => ({
21+
flex,
22+
justifyContent: 'center',
23+
alignItems: 'center',
24+
backgroundColor: {
25+
xs: theme.colors.oak,
26+
md: theme.colors.sky
27+
}
28+
}),
29+
text: {
30+
height: 100,
31+
shadowOpacity: {
32+
xs: 20
33+
},
34+
transform: [
35+
{
36+
scale: 2
37+
},
38+
{
39+
translateX: {
40+
sm: 10,
41+
md: 20
42+
}
43+
}
44+
]
45+
}
46+
}))
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from 'react'
2+
import { Text, View } from 'react-native'
3+
import { createStyles, useStyles } from '../styles'
4+
5+
// Media queries
6+
export const MediaQueries: React.FunctionComponent = () => {
7+
const { styles } = useStyles(stylesheet)
8+
9+
return (
10+
<View style={styles.dynamicContainer}>
11+
<Text>
12+
Media queries, resize me :)
13+
</Text>
14+
<Text>
15+
Row of column
16+
</Text>
17+
</View>
18+
)
19+
}
20+
21+
const stylesheet = createStyles(theme => ({
22+
dynamicContainer: {
23+
flex: 1,
24+
justifyContent: 'center',
25+
alignItems: 'center',
26+
flexDirection: {
27+
xs: 'row',
28+
// mixed queries
29+
':w[400]': 'column'
30+
},
31+
backgroundColor: {
32+
':w[, 300]:h[100]': theme.colors.oak,
33+
':w[301]': theme.colors.barbie
34+
}
35+
}
36+
}))

example/src/examples/Minimal.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react'
2+
import { Text, View, StyleSheet } from 'react-native'
3+
import { useStyles } from '../styles'
4+
5+
// Compatibility between StyleSheet.create and useStyles
6+
// access theme from useStyles
7+
export const Minimal: React.FunctionComponent = () => {
8+
const { styles, theme } = useStyles(stylesheet)
9+
10+
return (
11+
<View style={styles.container}>
12+
<Text>
13+
I'm just a minimal example with {theme.colors.barbie} color
14+
</Text>
15+
</View>
16+
)
17+
}
18+
19+
const stylesheet = StyleSheet.create({
20+
container: {
21+
flex: 1,
22+
justifyContent: 'center',
23+
alignItems: 'center'
24+
}
25+
})
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React from 'react'
2+
import { Text, View } from 'react-native'
3+
import { createStyles, useStyles } from '../styles'
4+
5+
// createStyles with StyleSheet.create compatible Object
6+
export const MinimalWithCreateStyles: React.FunctionComponent = () => {
7+
const { styles } = useStyles(stylesheet)
8+
9+
return (
10+
<View style={styles.container}>
11+
<Text style={styles.text}>
12+
I'm just a minimal example with createStyles
13+
</Text>
14+
</View>
15+
)
16+
}
17+
18+
const stylesheet = createStyles({
19+
container: {
20+
flex: 1,
21+
justifyContent: 'center',
22+
alignItems: 'center',
23+
alignContent: 'space-between',
24+
resizeMode: 'contain'
25+
},
26+
text: {
27+
borderWidth: 1,
28+
borderColor: 'purple',
29+
padding: 20,
30+
flex: {
31+
xs: 2,
32+
md: 1
33+
}
34+
}
35+
})
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import React from 'react'
22
import { Text, View } from 'react-native'
3-
import { createStyles, useStyles } from './styles'
3+
import { createStyles, useStyles } from '../styles'
44

5-
export const ExampleScreen: React.FunctionComponent = () => {
5+
// Injected theme to createStyles
6+
export const Theme: React.FunctionComponent = () => {
67
const { styles } = useStyles(stylesheet)
78

89
return (
910
<View style={styles.container}>
1011
<Text>
11-
Resize me :)
12+
Theme example
1213
</Text>
1314
</View>
1415
)
@@ -19,10 +20,6 @@ const stylesheet = createStyles(theme => ({
1920
flex: 1,
2021
justifyContent: 'center',
2122
alignItems: 'center',
22-
backgroundColor: {
23-
sm: theme.colors.oak,
24-
md: theme.colors.aloes,
25-
':w[800]': theme.colors.fog
26-
}
23+
backgroundColor: theme.colors.oak
2724
}
2825
}))

example/src/examples/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export { Minimal } from './Minimal'
2+
export { MinimalWithCreateStyles } from './MinimalWithCreateStyles'
3+
export { Theme } from './Theme'
4+
export { Breakpoints } from './Breakpoints'
5+
export { MediaQueries } from './MediaQueries'
6+
export { Extreme } from './Extreme'

src/createUnistyles.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ import { getBreakpointFromScreenWidth, proxifyFunction, parseStyle, sortAndValid
55
import { useDimensions } from './hooks'
66

77
export const createUnistyles = <B extends Record<string, number>, T = {}>(breakpoints: B) => {
8-
const sortedBreakpoints = sortAndValidateBreakpoints(breakpoints) as B
8+
const sortedBreakpoints = sortAndValidateBreakpoints(breakpoints)
99

1010
return {
11-
createStyles: <S extends CustomNamedStyles<S, B>>(styles: S | CreateStylesFactory<S, T>) => styles as S,
11+
createStyles: <S extends CustomNamedStyles<S, B>, X>(styles: S | CustomNamedStyles<S, B> | X | ((theme: T) => X | CustomNamedStyles<X, B>)): S | X => {
12+
if (typeof styles === 'function') {
13+
return styles as X
14+
}
15+
16+
return styles as S
17+
},
1218
useStyles: <ST extends CustomNamedStyles<ST, B>>(stylesheet?: ST | CreateStylesFactory<ST, T>) => {
1319
const theme = useContext(UnistylesContext) as T
1420
const dimensions = useDimensions()

src/types.ts

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,80 @@
1-
import type { ImageStyle, TextStyle, TransformsStyle, ViewStyle } from 'react-native'
2-
import type { CSSProperties } from 'react'
1+
import type { ImageStyle, TextStyle, ViewStyle } from 'react-native'
2+
import type {
3+
MatrixTransform,
4+
PerpectiveTransform,
5+
RotateTransform,
6+
RotateXTransform,
7+
RotateYTransform,
8+
RotateZTransform,
9+
ScaleTransform,
10+
ScaleXTransform,
11+
ScaleYTransform,
12+
SkewXTransform,
13+
SkewYTransform,
14+
TranslateXTransform,
15+
TranslateYTransform
16+
} from 'react-native/Libraries/StyleSheet/StyleSheetTypes'
317

418
export type ScreenSize = {
519
width: number,
620
height: number
721
}
822

9-
export type CreateStylesFactory<T, Theme> = (theme: Theme) => T
23+
export type CreateStylesFactory<ST, Theme> = (theme: Theme) => ST
1024

1125
type StyleProperty<T, B extends Record<string, number>> = {
12-
[key in keyof T]?: {
13-
[innerKey in keyof B]?: T[key]
26+
[K in keyof T]: {
27+
[innerKey in keyof B]?: T[K]
1428
} | {
15-
[innerKey in `:w${string}` | `:h${string}`]?: T[key]
16-
} | T[key]
29+
[innerKey in string]?: T[K]
30+
} | T[K]
1731
}
1832

19-
export type CustomNamedStyles<T, B extends Record<string, number>> = {
20-
[P in keyof T]:
21-
| ViewStyle
22-
| TextStyle
23-
| ImageStyle
24-
| TransformsStyle
25-
| CSSProperties
26-
| StyleProperty<ViewStyle, B>
27-
| StyleProperty<ImageStyle, B>
28-
| StyleProperty<TextStyle, B>
29-
| (
30-
(...args: Array<never>) => ViewStyle | TextStyle | ImageStyle | TransformsStyle | CSSProperties | StyleProperty<ViewStyle, B> | StyleProperty<ImageStyle, B> | StyleProperty<TextStyle, B>
31-
)
33+
type ShadowOffsetProps<B extends Record<string, number>> = {
34+
shadowOffset: {
35+
width: number | {
36+
[innerKey in keyof B]?: number
37+
},
38+
height: number | {
39+
[innerKey in keyof B]?: number
40+
}
41+
}
42+
}
43+
44+
type TransformStyles<B extends Record<string, number>> =
45+
PerpectiveTransform | StyleProperty<PerpectiveTransform, B>
46+
| RotateTransform | StyleProperty<RotateTransform, B>
47+
| RotateXTransform | StyleProperty<RotateXTransform, B>
48+
| RotateYTransform | StyleProperty<RotateYTransform, B>
49+
| RotateZTransform | StyleProperty<RotateZTransform, B>
50+
| ScaleTransform | StyleProperty<ScaleTransform, B>
51+
| ScaleXTransform | StyleProperty<ScaleXTransform, B>
52+
| ScaleYTransform | StyleProperty<ScaleYTransform, B>
53+
| TranslateXTransform | StyleProperty<TranslateXTransform, B>
54+
| TranslateYTransform | StyleProperty<TranslateYTransform, B>
55+
| SkewXTransform | StyleProperty<SkewXTransform, B>
56+
| SkewYTransform | StyleProperty<SkewYTransform, B>
57+
| MatrixTransform | StyleProperty<MatrixTransform, B>
58+
59+
type TransformProps<B extends Record<string, number>> = {
60+
transform: Array<TransformStyles<B>>
3261
}
3362

63+
type UnistyleView = Omit<Omit<ViewStyle, 'shadowOffset'>, 'transform'>
64+
type UnistyleText = Omit<Omit<TextStyle, 'shadowOffset'>, 'transform'>
65+
type UnistyleImage = Omit<Omit<ImageStyle, 'shadowOffset'>, 'transform'>
66+
67+
export type StaticStyles<B extends Record<string, number>> =
68+
| (UnistyleView | StyleProperty<UnistyleView, B>)
69+
| (UnistyleText | StyleProperty<UnistyleText, B>)
70+
| (UnistyleImage | StyleProperty<UnistyleImage, B>)
71+
& TransformProps<B> & ShadowOffsetProps<B>
72+
73+
export type CustomNamedStyles<T, B extends Record<string, number>> = {
74+
[K in keyof T]: T[K] extends (...args: infer A) => unknown
75+
? (...args: A) => StaticStyles<B>
76+
: StaticStyles<B>
77+
}
3478
export type ExtractBreakpoints<T, B extends Record<string, number>> = T extends Partial<Record<keyof B & string, infer V>>
3579
? V
3680
: T extends (...args: infer A) => infer R

0 commit comments

Comments
 (0)