@chem-po/react-native 0.0.35 → 0.0.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/button/DeleteButton.js +84 -43
- package/lib/commonjs/components/button/DeleteButton.js.map +1 -1
- package/lib/commonjs/components/button/LoadingButton.js +31 -19
- package/lib/commonjs/components/button/LoadingButton.js.map +1 -1
- package/lib/commonjs/components/theme/colorMode/DarkModeToggle.js +2 -2
- package/lib/commonjs/contexts/root.js +12 -6
- package/lib/commonjs/contexts/root.js.map +1 -1
- package/lib/commonjs/hooks/useThemeState.js +23 -4
- package/lib/commonjs/hooks/useThemeState.js.map +1 -1
- package/lib/module/components/button/DeleteButton.js +87 -46
- package/lib/module/components/button/DeleteButton.js.map +1 -1
- package/lib/module/components/button/LoadingButton.js +32 -20
- package/lib/module/components/button/LoadingButton.js.map +1 -1
- package/lib/module/components/theme/colorMode/DarkModeToggle.js +2 -2
- package/lib/module/contexts/root.js +12 -6
- package/lib/module/contexts/root.js.map +1 -1
- package/lib/module/hooks/useThemeState.js +23 -5
- package/lib/module/hooks/useThemeState.js.map +1 -1
- package/lib/typescript/components/button/DeleteButton.d.ts +8 -1
- package/lib/typescript/components/button/DeleteButton.d.ts.map +1 -1
- package/lib/typescript/components/button/LoadingButton.d.ts +2 -0
- package/lib/typescript/components/button/LoadingButton.d.ts.map +1 -1
- package/lib/typescript/contexts/root.d.ts +5 -2
- package/lib/typescript/contexts/root.d.ts.map +1 -1
- package/lib/typescript/hooks/useThemeState.d.ts +2 -1
- package/lib/typescript/hooks/useThemeState.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/components/button/DeleteButton.tsx +111 -40
- package/src/components/button/LoadingButton.tsx +41 -19
- package/src/components/theme/colorMode/DarkModeToggle.tsx +2 -2
- package/src/contexts/root.tsx +30 -14
- package/src/hooks/useThemeState.ts +31 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoadingButton.d.ts","sourceRoot":"","sources":["../../../../src/components/button/LoadingButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,EAAE,EAAE,SAAS,EAAqD,MAAM,OAAO,CAAA;AAC3F,OAAO,EAGL,SAAS,EAGT,SAAS,EAET,SAAS,EACV,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;IAC5C,QAAQ,EAAE,SAAS,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAC5B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IACnC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;QACnD,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;IACD,QAAQ,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"LoadingButton.d.ts","sourceRoot":"","sources":["../../../../src/components/button/LoadingButton.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,KAAK,EAAE,EAAE,SAAS,EAAqD,MAAM,OAAO,CAAA;AAC3F,OAAO,EAGL,SAAS,EAGT,SAAS,EAET,SAAS,EACV,MAAM,cAAc,CAAA;AAGrB,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;IAC5C,QAAQ,EAAE,SAAS,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAC5B,YAAY,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IACnC,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAA;IAC7B,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;QACnD,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;IACD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAA;CAClD;AAED,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAsHtD,CAAA"}
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { BackendAdapterInterface, ColorMode, Theme } from '@chem-po/core';
|
|
2
2
|
import { ChempoProps } from '@chem-po/react';
|
|
3
|
-
import React, { PropsWithChildren } from 'react';
|
|
3
|
+
import React, { FC, PropsWithChildren } from 'react';
|
|
4
4
|
import { MD3Type, MD3TypescaleKey } from 'react-native-paper/lib/typescript/types';
|
|
5
5
|
export type FontConfig = Partial<Record<MD3TypescaleKey, Partial<MD3Type>>>;
|
|
6
|
+
export type MiddlewareProvider = FC<PropsWithChildren>;
|
|
6
7
|
export interface ChempoNativeProviderProps<BackendAdapter extends BackendAdapterInterface> extends PropsWithChildren<Pick<ChempoProps<BackendAdapter>, 'backendAdapter' | 'assets'>> {
|
|
7
8
|
theme?: Theme;
|
|
8
9
|
fonts?: FontConfig;
|
|
9
10
|
initialColorMode?: ColorMode;
|
|
11
|
+
colorModeProp?: string;
|
|
12
|
+
middlewareProvider?: MiddlewareProvider;
|
|
10
13
|
}
|
|
11
|
-
export declare const ChempoNativeProvider: <BackendAdapter extends BackendAdapterInterface>({ theme: themeProp, initialColorMode, children, fonts, ...props }: ChempoNativeProviderProps<BackendAdapter>) => React.JSX.Element;
|
|
14
|
+
export declare const ChempoNativeProvider: <BackendAdapter extends BackendAdapterInterface>({ theme: themeProp, initialColorMode, children, fonts, colorModeProp, middlewareProvider: Middleware, ...props }: ChempoNativeProviderProps<BackendAdapter>) => React.JSX.Element;
|
|
12
15
|
//# sourceMappingURL=root.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../src/contexts/root.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,WAAW,EAA4B,MAAM,gBAAgB,CAAA;AACtE,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAW,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../../src/contexts/root.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AACzE,OAAO,EAAE,WAAW,EAA4B,MAAM,gBAAgB,CAAA;AACtE,OAAO,KAAK,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAW,MAAM,OAAO,CAAA;AAK7D,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAA;AAQlF,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AAC3E,MAAM,MAAM,kBAAkB,GAAG,EAAE,CAAC,iBAAiB,CAAC,CAAA;AACtD,MAAM,WAAW,yBAAyB,CAAC,cAAc,SAAS,uBAAuB,CACvF,SAAQ,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,gBAAgB,GAAG,QAAQ,CAAC,CAAC;IACzF,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;CACxC;AA4FD,eAAO,MAAM,oBAAoB,GAAI,cAAc,SAAS,uBAAuB,EAAE,kHAQlF,yBAAyB,CAAC,cAAc,CAAC,sBA0B3C,CAAA"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ColorMode, Theme } from '@chem-po/core';
|
|
2
2
|
import { ThemeProps } from '@chem-po/react';
|
|
3
3
|
export interface UseThemeProps {
|
|
4
|
-
|
|
4
|
+
colorModeProp?: string;
|
|
5
5
|
theme?: Theme;
|
|
6
|
+
initialColorMode?: ColorMode;
|
|
6
7
|
}
|
|
7
8
|
export declare const useThemeState: (props?: UseThemeProps) => ThemeProps;
|
|
8
9
|
//# sourceMappingURL=useThemeState.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useThemeState.d.ts","sourceRoot":"","sources":["../../../src/hooks/useThemeState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"useThemeState.d.ts","sourceRoot":"","sources":["../../../src/hooks/useThemeState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAI3C,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;IAEb,gBAAgB,CAAC,EAAE,SAAS,CAAA;CAC7B;AAED,eAAO,MAAM,aAAa,GAAI,QAAQ,aAAa,eA8BlD,CAAA"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@chem-po/react-native",
|
|
3
3
|
"author": "Elan Canfield",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.37",
|
|
6
6
|
"main": "lib/commonjs/index.js",
|
|
7
7
|
"types": "lib/typescript/index.d.ts",
|
|
8
8
|
"source": "src/index.ts",
|
|
@@ -46,14 +46,15 @@
|
|
|
46
46
|
"react-native": "0.79.5",
|
|
47
47
|
"react-native-element-dropdown": "^2.12.4",
|
|
48
48
|
"react-native-gesture-handler": "~2.24.0",
|
|
49
|
+
"react-native-safe-area-context": "5.4.0",
|
|
49
50
|
"react-native-reanimated": "~3.17.4",
|
|
50
51
|
"react-native-notifier": "^2.0.0",
|
|
51
52
|
"react-native-paper": "^5.14.3",
|
|
52
53
|
"react-native-paper-dates": "^0.22.42",
|
|
53
54
|
"react-native-svg": "15.11.2",
|
|
54
55
|
"zustand": "^4.3.3",
|
|
55
|
-
"@chem-po/
|
|
56
|
-
"@chem-po/
|
|
56
|
+
"@chem-po/core": "0.0.37",
|
|
57
|
+
"@chem-po/react": "0.0.37"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@babel/core": "^7.26.0",
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { useToast } from '@chem-po/react'
|
|
1
|
+
import { useBackgroundColor, useColorModeValue, useToast } from '@chem-po/react'
|
|
2
2
|
import { Ionicons } from '@expo/vector-icons'
|
|
3
|
-
import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react'
|
|
4
|
-
import { ActivityIndicator, Animated,
|
|
3
|
+
import React, { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
4
|
+
import { ActivityIndicator, Animated, StyleSheet, Text, View, ViewStyle } from 'react-native'
|
|
5
5
|
import { Pressable } from 'react-native-gesture-handler'
|
|
6
|
+
import { Modal, Portal } from 'react-native-paper'
|
|
6
7
|
import { Txt } from '../text/Txt'
|
|
7
8
|
|
|
8
9
|
const defaultAlertBodyText = "Are you sure? You can't undo this action afterwards."
|
|
@@ -15,42 +16,48 @@ export const DeleteConfirmAlert = ({
|
|
|
15
16
|
actionName = 'Delete',
|
|
16
17
|
actionLoading,
|
|
17
18
|
itemName,
|
|
19
|
+
color,
|
|
20
|
+
cancelText = 'CANCEL',
|
|
18
21
|
}: {
|
|
19
22
|
confirmActive: boolean
|
|
20
23
|
onCancel: () => void
|
|
21
24
|
onConfirm: () => void
|
|
22
25
|
body?: string | ReactNode
|
|
23
26
|
actionLoading?: boolean
|
|
27
|
+
color: string
|
|
24
28
|
actionName?: string
|
|
29
|
+
cancelText?: string
|
|
25
30
|
itemName: string
|
|
26
31
|
}) => {
|
|
32
|
+
const backgroundColor = useBackgroundColor(100)
|
|
27
33
|
return (
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
onRequestClose={onCancel}
|
|
32
|
-
animationType="fade">
|
|
33
|
-
<View style={styles.overlay}>
|
|
34
|
-
<View style={styles.alertContainer}>
|
|
34
|
+
<Portal>
|
|
35
|
+
<Modal style={styles.modal} visible={confirmActive} onDismiss={onCancel}>
|
|
36
|
+
<View style={[styles.alertContainer, { backgroundColor }]}>
|
|
35
37
|
<Txt style={styles.alertTitle}>
|
|
36
38
|
{actionName} {itemName}?
|
|
37
39
|
</Txt>
|
|
38
40
|
{typeof body === 'string' ? <Txt style={styles.alertBody}>{body}</Txt> : body}
|
|
39
41
|
<View style={styles.buttonContainer}>
|
|
40
42
|
<Pressable style={styles.cancelButton} onPress={onCancel}>
|
|
41
|
-
<Txt style={styles.cancelText}>
|
|
43
|
+
<Txt style={styles.cancelText}>{cancelText}</Txt>
|
|
42
44
|
</Pressable>
|
|
43
|
-
<Pressable
|
|
45
|
+
<Pressable
|
|
46
|
+
style={[styles.confirmButton, { backgroundColor: color }]}
|
|
47
|
+
onPress={onConfirm}
|
|
48
|
+
disabled={actionLoading}>
|
|
44
49
|
{actionLoading ? (
|
|
45
50
|
<ActivityIndicator color="#fff" />
|
|
46
51
|
) : (
|
|
47
|
-
<Txt style={[styles.buttonText, styles.confirmButtonText]}>
|
|
52
|
+
<Txt style={[styles.buttonText, styles.confirmButtonText]}>
|
|
53
|
+
{actionName.toUpperCase()}
|
|
54
|
+
</Txt>
|
|
48
55
|
)}
|
|
49
56
|
</Pressable>
|
|
50
57
|
</View>
|
|
51
58
|
</View>
|
|
52
|
-
</
|
|
53
|
-
</
|
|
59
|
+
</Modal>
|
|
60
|
+
</Portal>
|
|
54
61
|
)
|
|
55
62
|
}
|
|
56
63
|
|
|
@@ -62,7 +69,23 @@ export const DeleteButton: React.FC<{
|
|
|
62
69
|
text?: string
|
|
63
70
|
alertBody?: string | ReactNode
|
|
64
71
|
style?: ViewStyle
|
|
65
|
-
|
|
72
|
+
color?: string
|
|
73
|
+
variant?: 'outline' | 'solid'
|
|
74
|
+
iconSize?: number
|
|
75
|
+
iconProps?: React.ComponentProps<typeof Ionicons>
|
|
76
|
+
}> = ({
|
|
77
|
+
onDelete,
|
|
78
|
+
itemName,
|
|
79
|
+
noConfirm,
|
|
80
|
+
alertBody,
|
|
81
|
+
text,
|
|
82
|
+
actionName = 'Delete',
|
|
83
|
+
style,
|
|
84
|
+
color: colorProp,
|
|
85
|
+
variant = 'outline',
|
|
86
|
+
iconSize = 18,
|
|
87
|
+
iconProps,
|
|
88
|
+
}) => {
|
|
66
89
|
const { showError } = useToast()
|
|
67
90
|
const [deleteLoading, setDeleteLoading] = useState(false)
|
|
68
91
|
const [confirmActive, setConfirmActive] = useState(false)
|
|
@@ -70,6 +93,10 @@ export const DeleteButton: React.FC<{
|
|
|
70
93
|
const isMounted = useRef(true)
|
|
71
94
|
const contentOpacity = useRef(new Animated.Value(1)).current
|
|
72
95
|
const loaderOpacity = useRef(new Animated.Value(0)).current
|
|
96
|
+
const defaultColor = useColorModeValue('#dd2222', '#ff7777')
|
|
97
|
+
const color = colorProp ?? defaultColor
|
|
98
|
+
|
|
99
|
+
const textColor = useMemo(() => (variant === 'solid' ? 'white' : color), [variant, color])
|
|
73
100
|
|
|
74
101
|
useEffect(() => {
|
|
75
102
|
isMounted.current = true
|
|
@@ -122,7 +149,15 @@ export const DeleteButton: React.FC<{
|
|
|
122
149
|
<>
|
|
123
150
|
{text ? (
|
|
124
151
|
<Pressable
|
|
125
|
-
style={[
|
|
152
|
+
style={[
|
|
153
|
+
styles.button,
|
|
154
|
+
{
|
|
155
|
+
borderColor: color,
|
|
156
|
+
backgroundColor: variant === 'solid' ? color : 'transparent',
|
|
157
|
+
borderWidth: variant === 'outline' ? 1 : 0,
|
|
158
|
+
},
|
|
159
|
+
style,
|
|
160
|
+
]}
|
|
126
161
|
onPress={() => {
|
|
127
162
|
if (noConfirm) handleDelete()
|
|
128
163
|
else setConfirmActive(true)
|
|
@@ -130,30 +165,55 @@ export const DeleteButton: React.FC<{
|
|
|
130
165
|
disabled={deleteLoading}>
|
|
131
166
|
<View style={styles.buttonContent}>
|
|
132
167
|
<Animated.View style={[styles.contentContainer, { opacity: contentOpacity }]}>
|
|
133
|
-
<Ionicons
|
|
134
|
-
|
|
168
|
+
<Ionicons
|
|
169
|
+
name="trash"
|
|
170
|
+
size={iconSize}
|
|
171
|
+
color={textColor}
|
|
172
|
+
{...iconProps}
|
|
173
|
+
style={[variant === 'solid' ? styles.shadow : {}, iconProps?.style]}
|
|
174
|
+
/>
|
|
175
|
+
<Text
|
|
176
|
+
style={[
|
|
177
|
+
styles.buttonText,
|
|
178
|
+
{ color: textColor },
|
|
179
|
+
variant === 'solid' ? styles.shadow : undefined,
|
|
180
|
+
]}>
|
|
181
|
+
{text}
|
|
182
|
+
</Text>
|
|
135
183
|
</Animated.View>
|
|
136
|
-
|
|
137
184
|
<Animated.View style={[styles.loaderContainer, { opacity: loaderOpacity }]}>
|
|
138
|
-
<ActivityIndicator color=
|
|
185
|
+
<ActivityIndicator color={textColor} size="small" />
|
|
139
186
|
</Animated.View>
|
|
140
187
|
</View>
|
|
141
188
|
</Pressable>
|
|
142
189
|
) : (
|
|
143
190
|
<Pressable
|
|
144
|
-
style={[
|
|
191
|
+
style={[
|
|
192
|
+
styles.iconButton,
|
|
193
|
+
{
|
|
194
|
+
borderColor: color,
|
|
195
|
+
borderWidth: variant === 'outline' ? 1 : 0,
|
|
196
|
+
backgroundColor: variant === 'solid' ? color : 'transparent',
|
|
197
|
+
},
|
|
198
|
+
style,
|
|
199
|
+
]}
|
|
145
200
|
onPress={() => {
|
|
146
201
|
if (noConfirm) handleDelete()
|
|
147
202
|
else setConfirmActive(true)
|
|
148
203
|
}}
|
|
149
204
|
disabled={deleteLoading}>
|
|
150
|
-
<View style={styles.
|
|
205
|
+
<View style={styles.iconButtonContent}>
|
|
151
206
|
<Animated.View style={[styles.contentContainer, { opacity: contentOpacity }]}>
|
|
152
|
-
<Ionicons
|
|
207
|
+
<Ionicons
|
|
208
|
+
name="trash"
|
|
209
|
+
size={iconSize}
|
|
210
|
+
color={textColor}
|
|
211
|
+
{...iconProps}
|
|
212
|
+
style={[variant === 'solid' ? styles.shadow : {}, iconProps?.style]}
|
|
213
|
+
/>
|
|
153
214
|
</Animated.View>
|
|
154
|
-
|
|
155
215
|
<Animated.View style={[styles.loaderContainer, { opacity: loaderOpacity }]}>
|
|
156
|
-
<ActivityIndicator color=
|
|
216
|
+
<ActivityIndicator color={textColor} size="small" />
|
|
157
217
|
</Animated.View>
|
|
158
218
|
</View>
|
|
159
219
|
</Pressable>
|
|
@@ -169,6 +229,7 @@ export const DeleteButton: React.FC<{
|
|
|
169
229
|
actionName={actionName}
|
|
170
230
|
body={alertBody}
|
|
171
231
|
itemName={itemName}
|
|
232
|
+
color={color}
|
|
172
233
|
/>
|
|
173
234
|
)}
|
|
174
235
|
</>
|
|
@@ -176,18 +237,16 @@ export const DeleteButton: React.FC<{
|
|
|
176
237
|
}
|
|
177
238
|
|
|
178
239
|
const styles = StyleSheet.create({
|
|
179
|
-
overlay: {
|
|
180
|
-
flex: 1,
|
|
181
|
-
justifyContent: 'center',
|
|
182
|
-
alignItems: 'center',
|
|
183
|
-
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
184
|
-
},
|
|
185
240
|
alertContainer: {
|
|
186
|
-
width: '80%',
|
|
187
|
-
maxWidth: 400,
|
|
188
241
|
backgroundColor: 'white',
|
|
189
242
|
borderRadius: 10,
|
|
190
243
|
padding: 20,
|
|
244
|
+
maxWidth: 300,
|
|
245
|
+
alignItems: 'center',
|
|
246
|
+
},
|
|
247
|
+
modal: {
|
|
248
|
+
flex: 1,
|
|
249
|
+
justifyContent: 'center',
|
|
191
250
|
alignItems: 'center',
|
|
192
251
|
},
|
|
193
252
|
alertTitle: {
|
|
@@ -198,6 +257,7 @@ const styles = StyleSheet.create({
|
|
|
198
257
|
alertBody: {
|
|
199
258
|
fontSize: 16,
|
|
200
259
|
marginBottom: 20,
|
|
260
|
+
textAlign: 'center',
|
|
201
261
|
},
|
|
202
262
|
buttonContainer: {
|
|
203
263
|
flexDirection: 'row',
|
|
@@ -226,7 +286,6 @@ const styles = StyleSheet.create({
|
|
|
226
286
|
alignItems: 'center',
|
|
227
287
|
},
|
|
228
288
|
buttonText: {
|
|
229
|
-
color: 'red',
|
|
230
289
|
fontWeight: 'bold',
|
|
231
290
|
},
|
|
232
291
|
confirmButtonText: {
|
|
@@ -238,14 +297,11 @@ const styles = StyleSheet.create({
|
|
|
238
297
|
button: {
|
|
239
298
|
flexDirection: 'row',
|
|
240
299
|
alignItems: 'center',
|
|
241
|
-
|
|
242
|
-
backgroundColor: 'transparent',
|
|
300
|
+
borderRadius: 4,
|
|
243
301
|
},
|
|
244
302
|
buttonContent: {
|
|
245
303
|
flexDirection: 'row',
|
|
246
304
|
gap: 3,
|
|
247
|
-
borderWidth: 1,
|
|
248
|
-
borderColor: 'red',
|
|
249
305
|
paddingHorizontal: 13,
|
|
250
306
|
paddingVertical: 5,
|
|
251
307
|
borderRadius: 4,
|
|
@@ -265,9 +321,24 @@ const styles = StyleSheet.create({
|
|
|
265
321
|
alignItems: 'center',
|
|
266
322
|
justifyContent: 'center',
|
|
267
323
|
},
|
|
324
|
+
shadow: {
|
|
325
|
+
textShadowColor: 'rgba(0, 0, 0, 0.3)',
|
|
326
|
+
textShadowOffset: { width: 1, height: 1 },
|
|
327
|
+
textShadowRadius: 4,
|
|
328
|
+
},
|
|
268
329
|
iconButton: {
|
|
269
|
-
padding: 10,
|
|
270
330
|
backgroundColor: 'transparent',
|
|
331
|
+
borderRadius: 4,
|
|
332
|
+
width: 32,
|
|
333
|
+
height: 32,
|
|
334
|
+
alignItems: 'center',
|
|
335
|
+
justifyContent: 'center',
|
|
336
|
+
},
|
|
337
|
+
iconButtonContent: {
|
|
338
|
+
flexDirection: 'row',
|
|
339
|
+
alignItems: 'center',
|
|
340
|
+
justifyContent: 'center',
|
|
341
|
+
gap: 3,
|
|
271
342
|
},
|
|
272
343
|
loading: {
|
|
273
344
|
position: 'absolute',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useTextColor, useToast } from '@chem-po/react'
|
|
2
2
|
import { Ionicons } from '@expo/vector-icons'
|
|
3
3
|
import React, { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
4
4
|
import {
|
|
@@ -20,11 +20,13 @@ export interface LoadingButtonProps {
|
|
|
20
20
|
contentStyle?: StyleProp<ViewStyle>
|
|
21
21
|
textStyle?: StyleProp<TextStyle>
|
|
22
22
|
color?: string
|
|
23
|
+
variant?: 'outline' | 'solid'
|
|
23
24
|
icon?: {
|
|
24
25
|
name: React.ComponentProps<typeof Ionicons>['name']
|
|
25
26
|
size?: number
|
|
26
27
|
}
|
|
27
28
|
disabled?: boolean
|
|
29
|
+
iconProps?: React.ComponentProps<typeof Ionicons>
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export const LoadingButton: React.FC<LoadingButtonProps> = ({
|
|
@@ -34,8 +36,10 @@ export const LoadingButton: React.FC<LoadingButtonProps> = ({
|
|
|
34
36
|
contentStyle,
|
|
35
37
|
textStyle,
|
|
36
38
|
color: colorProp,
|
|
39
|
+
variant = 'outline',
|
|
37
40
|
icon,
|
|
38
41
|
disabled = false,
|
|
42
|
+
iconProps,
|
|
39
43
|
}) => {
|
|
40
44
|
const [loading, setLoading] = useState(false)
|
|
41
45
|
const isMounted = useRef(true)
|
|
@@ -89,12 +93,21 @@ export const LoadingButton: React.FC<LoadingButtonProps> = ({
|
|
|
89
93
|
|
|
90
94
|
const fallbackColor = useTextColor()
|
|
91
95
|
const color = useMemo(() => colorProp ?? fallbackColor, [colorProp, fallbackColor])
|
|
92
|
-
const
|
|
96
|
+
const textColor = useMemo(() => (variant === 'solid' ? 'white' : color), [variant, color])
|
|
97
|
+
const backgroundColor = useMemo(
|
|
98
|
+
() => (variant === 'solid' ? color : 'transparent'),
|
|
99
|
+
[variant, color],
|
|
100
|
+
)
|
|
93
101
|
return (
|
|
94
102
|
<Pressable
|
|
95
103
|
style={[
|
|
96
104
|
styles.button,
|
|
97
|
-
{
|
|
105
|
+
{
|
|
106
|
+
opacity: disabled ? 0.6 : 1,
|
|
107
|
+
borderColor: color,
|
|
108
|
+
borderWidth: variant === 'outline' ? 1 : 0,
|
|
109
|
+
backgroundColor,
|
|
110
|
+
},
|
|
98
111
|
style,
|
|
99
112
|
]}
|
|
100
113
|
onPress={() => {
|
|
@@ -102,17 +115,25 @@ export const LoadingButton: React.FC<LoadingButtonProps> = ({
|
|
|
102
115
|
}}
|
|
103
116
|
disabled={loading || disabled}>
|
|
104
117
|
<View
|
|
105
|
-
style={[
|
|
106
|
-
styles.buttonContent,
|
|
107
|
-
{ borderColor: disabled ? '#ccc' : borderColor },
|
|
108
|
-
contentStyle,
|
|
109
|
-
]}>
|
|
118
|
+
style={[styles.buttonContent, { borderColor: disabled ? '#ccc' : color }, contentStyle]}>
|
|
110
119
|
<Animated.View style={[styles.contentContainer, { opacity: contentOpacity }]}>
|
|
111
120
|
{icon && (
|
|
112
|
-
<Ionicons
|
|
121
|
+
<Ionicons
|
|
122
|
+
name={icon.name}
|
|
123
|
+
size={icon.size ?? 20}
|
|
124
|
+
color={textColor}
|
|
125
|
+
{...iconProps}
|
|
126
|
+
style={[variant === 'solid' ? styles.shadow : {}, iconProps?.style]}
|
|
127
|
+
/>
|
|
113
128
|
)}
|
|
114
129
|
{typeof children === 'string' ? (
|
|
115
|
-
<Text
|
|
130
|
+
<Text
|
|
131
|
+
style={[
|
|
132
|
+
styles.buttonText,
|
|
133
|
+
{ color: textColor },
|
|
134
|
+
variant === 'solid' ? styles.shadow : {},
|
|
135
|
+
textStyle,
|
|
136
|
+
]}>
|
|
116
137
|
{children}
|
|
117
138
|
</Text>
|
|
118
139
|
) : (
|
|
@@ -121,7 +142,7 @@ export const LoadingButton: React.FC<LoadingButtonProps> = ({
|
|
|
121
142
|
</Animated.View>
|
|
122
143
|
|
|
123
144
|
<Animated.View style={[styles.loaderContainer, { opacity: loaderOpacity }]}>
|
|
124
|
-
<ActivityIndicator color={
|
|
145
|
+
<ActivityIndicator color={textColor} size="small" />
|
|
125
146
|
</Animated.View>
|
|
126
147
|
</View>
|
|
127
148
|
</Pressable>
|
|
@@ -133,24 +154,20 @@ const styles = StyleSheet.create({
|
|
|
133
154
|
flexDirection: 'row',
|
|
134
155
|
alignItems: 'center',
|
|
135
156
|
backgroundColor: 'transparent',
|
|
157
|
+
borderRadius: 4,
|
|
158
|
+
paddingHorizontal: 12,
|
|
159
|
+
paddingVertical: 6,
|
|
136
160
|
},
|
|
137
161
|
buttonContent: {
|
|
138
|
-
flexDirection: 'row',
|
|
139
|
-
gap: 8,
|
|
140
|
-
borderWidth: 1,
|
|
141
|
-
paddingHorizontal: 16,
|
|
142
|
-
paddingVertical: 8,
|
|
143
|
-
borderRadius: 4,
|
|
144
162
|
alignItems: 'center',
|
|
145
163
|
justifyContent: 'center',
|
|
146
|
-
minHeight: 40,
|
|
147
164
|
position: 'relative',
|
|
148
165
|
},
|
|
149
166
|
contentContainer: {
|
|
150
167
|
flexDirection: 'row',
|
|
151
168
|
alignItems: 'center',
|
|
152
169
|
justifyContent: 'center',
|
|
153
|
-
gap:
|
|
170
|
+
gap: 4,
|
|
154
171
|
},
|
|
155
172
|
loaderContainer: {
|
|
156
173
|
...StyleSheet.absoluteFillObject,
|
|
@@ -160,4 +177,9 @@ const styles = StyleSheet.create({
|
|
|
160
177
|
buttonText: {
|
|
161
178
|
fontWeight: 'bold',
|
|
162
179
|
},
|
|
180
|
+
shadow: {
|
|
181
|
+
textShadowColor: 'rgba(0, 0, 0, 0.3)',
|
|
182
|
+
textShadowOffset: { width: 1, height: 1 },
|
|
183
|
+
textShadowRadius: 4,
|
|
184
|
+
},
|
|
163
185
|
})
|
package/src/contexts/root.tsx
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import { BackendAdapterInterface, ColorMode, Theme } from '@chem-po/core'
|
|
2
2
|
import { ChempoProps, ChempoProvider, useTheme } from '@chem-po/react'
|
|
3
|
-
import React, { PropsWithChildren, useMemo } from 'react'
|
|
3
|
+
import React, { FC, PropsWithChildren, useMemo } from 'react'
|
|
4
|
+
import { GestureHandlerRootView } from 'react-native-gesture-handler'
|
|
4
5
|
import { NotifierWrapper } from 'react-native-notifier'
|
|
5
6
|
import { configureFonts, PaperProvider, Props as PaperProviderProps } from 'react-native-paper'
|
|
6
7
|
import { en, registerTranslation } from 'react-native-paper-dates'
|
|
7
8
|
import { MD3Type, MD3TypescaleKey } from 'react-native-paper/lib/typescript/types'
|
|
9
|
+
import { SafeAreaProvider } from 'react-native-safe-area-context'
|
|
8
10
|
import { nativeToast } from '../constants/toast'
|
|
9
|
-
import { useThemeState } from '../hooks/useThemeState'
|
|
11
|
+
import { UseThemeProps, useThemeState } from '../hooks/useThemeState'
|
|
10
12
|
import { initializeScreen } from '../store/useScreen'
|
|
11
13
|
|
|
12
14
|
registerTranslation('en', en)
|
|
13
15
|
|
|
14
16
|
export type FontConfig = Partial<Record<MD3TypescaleKey, Partial<MD3Type>>>
|
|
17
|
+
export type MiddlewareProvider = FC<PropsWithChildren>
|
|
15
18
|
export interface ChempoNativeProviderProps<BackendAdapter extends BackendAdapterInterface>
|
|
16
19
|
extends PropsWithChildren<Pick<ChempoProps<BackendAdapter>, 'backendAdapter' | 'assets'>> {
|
|
17
20
|
theme?: Theme
|
|
18
21
|
fonts?: FontConfig
|
|
19
22
|
initialColorMode?: ColorMode
|
|
23
|
+
colorModeProp?: string
|
|
24
|
+
middlewareProvider?: MiddlewareProvider
|
|
20
25
|
}
|
|
21
26
|
const createPaperTheme = (
|
|
22
27
|
theme: Theme,
|
|
@@ -114,22 +119,33 @@ export const ChempoNativeProvider = <BackendAdapter extends BackendAdapterInterf
|
|
|
114
119
|
initialColorMode,
|
|
115
120
|
children,
|
|
116
121
|
fonts,
|
|
122
|
+
colorModeProp,
|
|
123
|
+
middlewareProvider: Middleware,
|
|
117
124
|
...props
|
|
118
125
|
}: ChempoNativeProviderProps<BackendAdapter>) => {
|
|
119
|
-
const useThemeProps = useMemo(
|
|
120
|
-
() => ({ theme: themeProp, initialColorMode }),
|
|
121
|
-
[themeProp, initialColorMode],
|
|
126
|
+
const useThemeProps = useMemo<UseThemeProps>(
|
|
127
|
+
() => ({ theme: themeProp, initialColorMode, colorModeProp }),
|
|
128
|
+
[themeProp, initialColorMode, colorModeProp],
|
|
122
129
|
)
|
|
123
130
|
const theme = useThemeState(useThemeProps)
|
|
131
|
+
|
|
132
|
+
const body = (
|
|
133
|
+
<ChempoPaperProvider fonts={fonts}>
|
|
134
|
+
<NotifierWrapper>{children}</NotifierWrapper>
|
|
135
|
+
</ChempoPaperProvider>
|
|
136
|
+
)
|
|
137
|
+
|
|
124
138
|
return (
|
|
125
|
-
<
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
<ChempoProvider
|
|
140
|
+
toast={nativeToast}
|
|
141
|
+
theme={theme}
|
|
142
|
+
initializeScreen={initializeScreen}
|
|
143
|
+
{...props}>
|
|
144
|
+
<SafeAreaProvider>
|
|
145
|
+
<GestureHandlerRootView>
|
|
146
|
+
{Middleware ? <Middleware>{body}</Middleware> : body}
|
|
147
|
+
</GestureHandlerRootView>
|
|
148
|
+
</SafeAreaProvider>
|
|
149
|
+
</ChempoProvider>
|
|
134
150
|
)
|
|
135
151
|
}
|
|
@@ -1,18 +1,43 @@
|
|
|
1
1
|
import { ColorMode, Theme } from '@chem-po/core'
|
|
2
2
|
import { ThemeProps } from '@chem-po/react'
|
|
3
|
-
import
|
|
3
|
+
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
4
|
+
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
4
5
|
|
|
5
6
|
export interface UseThemeProps {
|
|
6
|
-
|
|
7
|
+
colorModeProp?: string
|
|
7
8
|
theme?: Theme
|
|
9
|
+
// deprecated - using AsyncStorage instead
|
|
10
|
+
initialColorMode?: ColorMode
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
export const useThemeState = (props?: UseThemeProps) => {
|
|
11
|
-
const { initialColorMode, theme } = props ?? {}
|
|
12
|
-
const [
|
|
14
|
+
const { initialColorMode, theme, colorModeProp = 'chempoColorMode' } = props ?? {}
|
|
15
|
+
const [initialized, setInitialized] = useState(false)
|
|
16
|
+
|
|
17
|
+
const [colorMode, setColorModeState] = useState<ColorMode>(initialColorMode ?? 'light')
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
if (initialized) return
|
|
21
|
+
|
|
22
|
+
const initialize = async () => {
|
|
23
|
+
const storedColorMode = await AsyncStorage.getItem(colorModeProp)
|
|
24
|
+
if (storedColorMode) setColorModeState(storedColorMode as ColorMode)
|
|
25
|
+
else AsyncStorage.setItem(colorModeProp, initialColorMode ?? 'light')
|
|
26
|
+
setInitialized(true)
|
|
27
|
+
}
|
|
28
|
+
initialize()
|
|
29
|
+
}, [initialized, colorModeProp, initialColorMode])
|
|
30
|
+
|
|
31
|
+
const setColorMode = useCallback(
|
|
32
|
+
(colorMode: ColorMode) => {
|
|
33
|
+
setColorModeState(colorMode)
|
|
34
|
+
AsyncStorage.setItem(colorModeProp, colorMode)
|
|
35
|
+
},
|
|
36
|
+
[colorModeProp],
|
|
37
|
+
)
|
|
13
38
|
|
|
14
39
|
return useMemo<ThemeProps>(
|
|
15
|
-
() => ({ colorMode, setColorMode, theme }),
|
|
16
|
-
[colorMode, setColorMode, theme],
|
|
40
|
+
() => ({ colorMode, setColorMode, theme, colorModeProp, initialized }),
|
|
41
|
+
[colorMode, setColorMode, theme, colorModeProp, initialized],
|
|
17
42
|
)
|
|
18
43
|
}
|