-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.ts
109 lines (92 loc) · 2.55 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import {
StyleSheet,
useColorScheme,
type ViewStyle,
type TextStyle,
type ImageStyle,
} from 'react-native'
type DarkModed<TStyles> = {
[P in keyof TStyles]: TStyles[P] | DarkModeValue<TStyles[P]>
}
type DarkModeStyleDefinition =
| DarkModed<ViewStyle>
| DarkModed<TextStyle>
| DarkModed<ImageStyle>
type StandardStyleDefinition = ViewStyle | TextStyle | ImageStyle
type DarkModeNamedStyles<T> = {
[P in keyof T]: DarkModeStyleDefinition
}
type StandardStyleSheetParams<T> =
| StyleSheet.NamedStyles<T>
| StyleSheet.NamedStyles<any>
type DarkModeStyleSheetParams<T> =
| DarkModeNamedStyles<T>
| DarkModeNamedStyles<any>
export class DarkModeValue<TValue> {
readonly light: TValue
readonly dark: TValue
constructor(light: TValue, dark: TValue) {
this.light = light
this.dark = dark
}
}
export type DarkModeStyleSheet<T> = {
light: StandardStyleSheetParams<T>
dark: StandardStyleSheetParams<T>
}
export function useIsDarkMode(): boolean {
return useColorScheme() === 'dark'
}
export function useDarkModeValue<T>(value: DarkModeValue<T>): T {
return useIsDarkMode() ? value.dark : value.light
}
export function useDarkModeSwitch<TValue>(
valueLight: TValue,
valueDark: TValue,
): TValue {
return useIsDarkMode() ? valueDark : valueLight
}
export function useDarkModeStyleSheet<TDefinition>(
styles: DarkModeStyleSheet<TDefinition>,
): StandardStyleSheetParams<TDefinition> {
const isDarkMode = useIsDarkMode()
return isDarkMode ? styles.dark : styles.light
}
function createStyle(
values: DarkModeStyleDefinition,
isDarkMode: boolean,
): StandardStyleDefinition {
return Object.entries(values).reduce((result, [property, value]) => {
if (value instanceof DarkModeValue) {
result[property] = isDarkMode ? value.dark : value.light
} else {
result[property] = value
}
return result
}, {} as Record<string, any>)
}
export function createStyleSheet<T extends DarkModeStyleSheetParams<T>>(
styles: T | DarkModeStyleSheetParams<T>,
): DarkModeStyleSheet<T> {
const { light, dark } = Object.entries(styles).reduce(
(sheets, [styleName, values]) => {
sheets.light[styleName as keyof typeof sheets.light] = createStyle(
values,
false,
)
sheets.dark[styleName as keyof typeof sheets.dark] = createStyle(
values,
true,
)
return sheets
},
{
light: {} as StandardStyleSheetParams<T>,
dark: {} as StandardStyleSheetParams<T>,
},
)
return {
dark: StyleSheet.create(dark),
light: StyleSheet.create(light),
}
}