@oxyhq/services 5.7.5 → 5.8.1
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/README.md +76 -76
- package/lib/commonjs/core/index.js +177 -102
- package/lib/commonjs/core/index.js.map +1 -1
- package/lib/commonjs/index.js +88 -29
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/node/createAuth.js +585 -7
- package/lib/commonjs/node/createAuth.js.map +1 -1
- package/lib/commonjs/node/index.js +38 -1
- package/lib/commonjs/node/index.js.map +1 -1
- package/lib/commonjs/ui/components/Avatar.js +15 -6
- package/lib/commonjs/ui/components/Avatar.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedItem.js +58 -13
- package/lib/commonjs/ui/components/GroupedItem.js.map +1 -1
- package/lib/commonjs/ui/components/GroupedSection.js +7 -1
- package/lib/commonjs/ui/components/GroupedSection.js.map +1 -1
- package/lib/commonjs/ui/components/Header.js +322 -0
- package/lib/commonjs/ui/components/Header.js.map +1 -0
- package/lib/commonjs/ui/components/OxyProvider.js +23 -7
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/index.js +7 -0
- package/lib/commonjs/ui/components/index.js.map +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js +1 -1
- package/lib/commonjs/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/commonjs/ui/components/internal/TextField.js +606 -546
- package/lib/commonjs/ui/components/internal/TextField.js.map +1 -1
- package/lib/commonjs/ui/components/internal/TextField.md +436 -0
- package/lib/commonjs/ui/context/OxyContext.js +122 -78
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionSocket.js +5 -2
- package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/commonjs/ui/navigation/OxyRouter.js +1 -1
- package/lib/commonjs/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountCenterScreen.js +6 -6
- package/lib/commonjs/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountManagementDemo.js +3 -3
- package/lib/commonjs/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js +241 -598
- package/lib/commonjs/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js +1151 -406
- package/lib/commonjs/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +135 -237
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/AppInfoScreen.js +246 -463
- package/lib/commonjs/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/FeedbackScreen.js +3 -3
- package/lib/commonjs/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js +808 -650
- package/lib/commonjs/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js +51 -72
- package/lib/commonjs/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SessionManagementScreen.js +11 -29
- package/lib/commonjs/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignInScreen.js +30 -303
- package/lib/commonjs/ui/screens/SignInScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/SignUpScreen.js +4 -4
- package/lib/commonjs/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js +19 -31
- package/lib/commonjs/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js +7 -10
- package/lib/commonjs/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js +11 -5
- package/lib/commonjs/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
- package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js +11 -4
- package/lib/commonjs/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
- package/lib/commonjs/ui/stores/authStore.js +12 -0
- package/lib/commonjs/ui/stores/authStore.js.map +1 -1
- package/lib/commonjs/ui/styles/authStyles.js +337 -0
- package/lib/commonjs/ui/styles/authStyles.js.map +1 -0
- package/lib/commonjs/ui/styles/index.js +11 -0
- package/lib/commonjs/ui/styles/index.js.map +1 -1
- package/lib/module/core/index.js +177 -41
- package/lib/module/core/index.js.map +1 -1
- package/lib/module/index.js +26 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/node/createAuth.js +584 -7
- package/lib/module/node/createAuth.js.map +1 -1
- package/lib/module/node/index.js +7 -1
- package/lib/module/node/index.js.map +1 -1
- package/lib/module/ui/components/Avatar.js +15 -6
- package/lib/module/ui/components/Avatar.js.map +1 -1
- package/lib/module/ui/components/GroupedItem.js +59 -14
- package/lib/module/ui/components/GroupedItem.js.map +1 -1
- package/lib/module/ui/components/GroupedSection.js +7 -1
- package/lib/module/ui/components/GroupedSection.js.map +1 -1
- package/lib/module/ui/components/Header.js +317 -0
- package/lib/module/ui/components/Header.js.map +1 -0
- package/lib/module/ui/components/OxyProvider.js +25 -9
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/index.js +1 -0
- package/lib/module/ui/components/index.js.map +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js +1 -1
- package/lib/module/ui/components/internal/GroupedPillButtons.js.map +1 -1
- package/lib/module/ui/components/internal/TextField.js +607 -547
- package/lib/module/ui/components/internal/TextField.js.map +1 -1
- package/lib/module/ui/components/internal/TextField.md +436 -0
- package/lib/module/ui/context/OxyContext.js +121 -77
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/useSessionSocket.js +5 -2
- package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
- package/lib/module/ui/navigation/OxyRouter.js +1 -1
- package/lib/module/ui/navigation/OxyRouter.js.map +1 -1
- package/lib/module/ui/screens/AccountCenterScreen.js +6 -6
- package/lib/module/ui/screens/AccountCenterScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountManagementDemo.js +3 -3
- package/lib/module/ui/screens/AccountManagementDemo.js.map +1 -1
- package/lib/module/ui/screens/AccountOverviewScreen.js +242 -597
- package/lib/module/ui/screens/AccountOverviewScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSettingsScreen.js +1152 -407
- package/lib/module/ui/screens/AccountSettingsScreen.js.map +1 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +135 -237
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +1 -1
- package/lib/module/ui/screens/AppInfoScreen.js +248 -465
- package/lib/module/ui/screens/AppInfoScreen.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js +3 -3
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/PaymentGatewayScreen.js +809 -651
- package/lib/module/ui/screens/PaymentGatewayScreen.js.map +1 -1
- package/lib/module/ui/screens/RecoverAccountScreen.js +53 -74
- package/lib/module/ui/screens/RecoverAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/SessionManagementScreen.js +11 -29
- package/lib/module/ui/screens/SessionManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/SignInScreen.js +32 -305
- package/lib/module/ui/screens/SignInScreen.js.map +1 -1
- package/lib/module/ui/screens/SignUpScreen.js +5 -5
- package/lib/module/ui/screens/SignUpScreen.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInPasswordStep.js +19 -31
- package/lib/module/ui/screens/internal/SignInPasswordStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignInUsernameStep.js +7 -10
- package/lib/module/ui/screens/internal/SignInUsernameStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignUpIdentityStep.js +11 -5
- package/lib/module/ui/screens/internal/SignUpIdentityStep.js.map +1 -1
- package/lib/module/ui/screens/internal/SignUpSecurityStep.js +11 -4
- package/lib/module/ui/screens/internal/SignUpSecurityStep.js.map +1 -1
- package/lib/module/ui/stores/authStore.js +12 -0
- package/lib/module/ui/stores/authStore.js.map +1 -1
- package/lib/module/ui/styles/authStyles.js +332 -0
- package/lib/module/ui/styles/authStyles.js.map +1 -0
- package/lib/module/ui/styles/index.js +1 -0
- package/lib/module/ui/styles/index.js.map +1 -1
- package/lib/typescript/core/index.d.ts +68 -24
- package/lib/typescript/core/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +13 -3
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/node/createAuth.d.ts +112 -0
- package/lib/typescript/node/createAuth.d.ts.map +1 -1
- package/lib/typescript/node/index.d.ts +2 -0
- package/lib/typescript/node/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/Avatar.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedItem.d.ts +6 -0
- package/lib/typescript/ui/components/GroupedItem.d.ts.map +1 -1
- package/lib/typescript/ui/components/GroupedSection.d.ts +6 -0
- package/lib/typescript/ui/components/GroupedSection.d.ts.map +1 -1
- package/lib/typescript/ui/components/Header.d.ts +22 -0
- package/lib/typescript/ui/components/Header.d.ts.map +1 -0
- package/lib/typescript/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/ui/components/index.d.ts +1 -0
- package/lib/typescript/ui/components/index.d.ts.map +1 -1
- package/lib/typescript/ui/components/internal/TextField.d.ts +31 -16
- package/lib/typescript/ui/components/internal/TextField.d.ts.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts +5 -2
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
- package/lib/typescript/ui/navigation/types.d.ts +9 -2
- package/lib/typescript/ui/navigation/types.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountOverviewScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSettingsScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AccountSwitcherScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/AppInfoScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/PaymentGatewayScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts +5 -1
- package/lib/typescript/ui/screens/RecoverAccountScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SessionManagementScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/SignInScreen.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts +1 -1
- package/lib/typescript/ui/screens/internal/SignInPasswordStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts +0 -1
- package/lib/typescript/ui/screens/internal/SignInUsernameStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignUpIdentityStep.d.ts.map +1 -1
- package/lib/typescript/ui/screens/internal/SignUpSecurityStep.d.ts.map +1 -1
- package/lib/typescript/ui/stores/authStore.d.ts.map +1 -1
- package/lib/typescript/ui/styles/authStyles.d.ts +326 -0
- package/lib/typescript/ui/styles/authStyles.d.ts.map +1 -0
- package/lib/typescript/ui/styles/index.d.ts +1 -0
- package/lib/typescript/ui/styles/index.d.ts.map +1 -1
- package/package.json +1 -4
- package/src/core/index.ts +195 -41
- package/src/index.ts +72 -4
- package/src/node/createAuth.ts +623 -7
- package/src/node/index.ts +19 -1
- package/src/ui/components/Avatar.tsx +11 -5
- package/src/ui/components/GroupedItem.tsx +57 -9
- package/src/ui/components/GroupedSection.tsx +12 -0
- package/src/ui/components/Header.tsx +364 -0
- package/src/ui/components/OxyProvider.tsx +31 -15
- package/src/ui/components/index.ts +1 -0
- package/src/ui/components/internal/GroupedPillButtons.tsx +1 -1
- package/src/ui/components/internal/TextField.md +436 -0
- package/src/ui/components/internal/TextField.tsx +720 -620
- package/src/ui/context/OxyContext.tsx +150 -63
- package/src/ui/hooks/useSessionSocket.ts +5 -2
- package/src/ui/navigation/OxyRouter.tsx +1 -1
- package/src/ui/navigation/types.ts +10 -2
- package/src/ui/screens/AccountCenterScreen.tsx +5 -5
- package/src/ui/screens/AccountManagementDemo.tsx +9 -9
- package/src/ui/screens/AccountOverviewScreen.tsx +265 -414
- package/src/ui/screens/AccountSettingsScreen.tsx +1165 -403
- package/src/ui/screens/AccountSwitcherScreen.tsx +158 -202
- package/src/ui/screens/AppInfoScreen.tsx +270 -497
- package/src/ui/screens/FeedbackScreen.tsx +3 -3
- package/src/ui/screens/PaymentGatewayScreen.tsx +668 -365
- package/src/ui/screens/ProfileScreen.tsx +5 -5
- package/src/ui/screens/RecoverAccountScreen.tsx +46 -74
- package/src/ui/screens/SessionManagementScreen.tsx +14 -22
- package/src/ui/screens/SignInScreen.tsx +27 -294
- package/src/ui/screens/SignUpScreen.tsx +5 -5
- package/src/ui/screens/internal/SignInPasswordStep.tsx +11 -22
- package/src/ui/screens/internal/SignInUsernameStep.tsx +3 -10
- package/src/ui/screens/internal/SignUpIdentityStep.tsx +2 -5
- package/src/ui/screens/internal/SignUpSecurityStep.tsx +3 -4
- package/src/ui/stores/authStore.ts +12 -0
- package/src/ui/styles/authStyles.ts +352 -0
- package/src/ui/styles/index.ts +1 -0
- package/lib/commonjs/core/auth-manager.js +0 -440
- package/lib/commonjs/core/auth-manager.js.map +0 -1
- package/lib/commonjs/core/use-auth.js +0 -244
- package/lib/commonjs/core/use-auth.js.map +0 -1
- package/lib/module/core/auth-manager.js +0 -432
- package/lib/module/core/auth-manager.js.map +0 -1
- package/lib/module/core/use-auth.js +0 -235
- package/lib/module/core/use-auth.js.map +0 -1
- package/lib/typescript/core/auth-manager.d.ts +0 -136
- package/lib/typescript/core/auth-manager.d.ts.map +0 -1
- package/lib/typescript/core/use-auth.d.ts +0 -79
- package/lib/typescript/core/use-auth.d.ts.map +0 -1
- package/src/__tests__/middleware.test.ts +0 -105
- package/src/__tests__/setup.ts +0 -10
- package/src/__tests__/zero-config-auth.test.ts +0 -607
- package/src/core/auth-manager.ts +0 -500
- package/src/core/use-auth.tsx +0 -245
|
@@ -30,6 +30,7 @@ const OxyProvider: React.FC<OxyProviderProps> = (props) => {
|
|
|
30
30
|
onAuthStateChange,
|
|
31
31
|
storageKeyPrefix,
|
|
32
32
|
showInternalToaster = true,
|
|
33
|
+
baseURL, // Add support for baseURL
|
|
33
34
|
...bottomSheetProps
|
|
34
35
|
} = props;
|
|
35
36
|
|
|
@@ -41,6 +42,7 @@ const OxyProvider: React.FC<OxyProviderProps> = (props) => {
|
|
|
41
42
|
return (
|
|
42
43
|
<OxyContextProvider
|
|
43
44
|
oxyServices={oxyServices}
|
|
45
|
+
baseURL={baseURL}
|
|
44
46
|
storageKeyPrefix={storageKeyPrefix}
|
|
45
47
|
onAuthStateChange={onAuthStateChange}
|
|
46
48
|
>
|
|
@@ -53,6 +55,7 @@ const OxyProvider: React.FC<OxyProviderProps> = (props) => {
|
|
|
53
55
|
return (
|
|
54
56
|
<OxyContextProvider
|
|
55
57
|
oxyServices={oxyServices}
|
|
58
|
+
baseURL={baseURL}
|
|
56
59
|
storageKeyPrefix={storageKeyPrefix}
|
|
57
60
|
onAuthStateChange={onAuthStateChange}
|
|
58
61
|
bottomSheetRef={internalBottomSheetRef}
|
|
@@ -85,7 +88,7 @@ const OxyProvider: React.FC<OxyProviderProps> = (props) => {
|
|
|
85
88
|
* and reimplemented using BottomSheetModal for better Android compatibility
|
|
86
89
|
*/
|
|
87
90
|
const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
88
|
-
oxyServices,
|
|
91
|
+
oxyServices: providedOxyServices,
|
|
89
92
|
initialScreen = 'SignIn',
|
|
90
93
|
onClose,
|
|
91
94
|
onAuthenticated,
|
|
@@ -95,6 +98,13 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
95
98
|
autoPresent = false,
|
|
96
99
|
showInternalToaster = true,
|
|
97
100
|
}) => {
|
|
101
|
+
// Helper function to determine if native driver should be used
|
|
102
|
+
const shouldUseNativeDriver = () => {
|
|
103
|
+
return Platform.OS === 'ios';
|
|
104
|
+
};
|
|
105
|
+
// Get oxyServices from context if not provided as prop
|
|
106
|
+
const contextOxy = useOxy();
|
|
107
|
+
const oxyServices = providedOxyServices || contextOxy?.oxyServices;
|
|
98
108
|
// Use the internal ref (which is passed as a prop from OxyProvider)
|
|
99
109
|
const modalRef = useRef<BottomSheetModalRef>(null);
|
|
100
110
|
const navigationRef = useRef<((screen: string, props?: Record<string, any>) => void) | null>(null);
|
|
@@ -168,13 +178,13 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
168
178
|
Animated.timing(fadeAnim, {
|
|
169
179
|
toValue: 1,
|
|
170
180
|
duration: 300,
|
|
171
|
-
useNativeDriver:
|
|
181
|
+
useNativeDriver: shouldUseNativeDriver(),
|
|
172
182
|
}),
|
|
173
183
|
Animated.spring(slideAnim, {
|
|
174
184
|
toValue: 0,
|
|
175
185
|
friction: 8,
|
|
176
186
|
tension: 40,
|
|
177
|
-
useNativeDriver:
|
|
187
|
+
useNativeDriver: shouldUseNativeDriver(),
|
|
178
188
|
}),
|
|
179
189
|
]).start();
|
|
180
190
|
};
|
|
@@ -186,13 +196,13 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
186
196
|
Animated.timing(fadeAnim, {
|
|
187
197
|
toValue: 1,
|
|
188
198
|
duration: 300,
|
|
189
|
-
useNativeDriver:
|
|
199
|
+
useNativeDriver: shouldUseNativeDriver(),
|
|
190
200
|
}),
|
|
191
201
|
Animated.spring(slideAnim, {
|
|
192
202
|
toValue: 0,
|
|
193
203
|
friction: 8,
|
|
194
204
|
tension: 40,
|
|
195
|
-
useNativeDriver:
|
|
205
|
+
useNativeDriver: shouldUseNativeDriver(),
|
|
196
206
|
}),
|
|
197
207
|
]).start();
|
|
198
208
|
}, 100);
|
|
@@ -204,7 +214,7 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
204
214
|
Animated.timing(fadeAnim, {
|
|
205
215
|
toValue: 0,
|
|
206
216
|
duration: Platform.OS === 'android' ? 100 : 200,
|
|
207
|
-
useNativeDriver:
|
|
217
|
+
useNativeDriver: shouldUseNativeDriver(),
|
|
208
218
|
}).start(() => {
|
|
209
219
|
modalRef.current?.dismiss();
|
|
210
220
|
if (onClose) {
|
|
@@ -304,15 +314,21 @@ const OxyBottomSheet: React.FC<OxyProviderProps> = ({
|
|
|
304
314
|
{ opacity: fadeAnim, transform: [{ translateY: slideAnim }] }
|
|
305
315
|
]}
|
|
306
316
|
>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
{oxyServices ? (
|
|
318
|
+
<OxyRouter
|
|
319
|
+
oxyServices={oxyServices}
|
|
320
|
+
initialScreen={initialScreen}
|
|
321
|
+
onClose={handleClose}
|
|
322
|
+
onAuthenticated={handleAuthenticated}
|
|
323
|
+
theme={theme}
|
|
324
|
+
navigationRef={navigationRef}
|
|
325
|
+
containerWidth={800} // static, since dynamic sizing is used
|
|
326
|
+
/>
|
|
327
|
+
) : (
|
|
328
|
+
<View style={styles.errorContainer}>
|
|
329
|
+
<Text>OxyServices not available</Text>
|
|
330
|
+
</View>
|
|
331
|
+
)}
|
|
316
332
|
</Animated.View>
|
|
317
333
|
</View>
|
|
318
334
|
</BottomSheetScrollView>
|
|
@@ -5,6 +5,7 @@ export { default as SectionTitle } from './SectionTitle';
|
|
|
5
5
|
export { default as GroupedItem } from './GroupedItem';
|
|
6
6
|
export { default as GroupedSection } from './GroupedSection';
|
|
7
7
|
export { default as QuickActions } from './QuickActions';
|
|
8
|
+
export { default as Header } from './Header';
|
|
8
9
|
|
|
9
10
|
// Re-export existing components
|
|
10
11
|
export { default as Avatar } from './Avatar';
|
|
@@ -247,7 +247,7 @@ const GroupedPillButtons: React.FC<GroupedPillButtonsProps> = ({
|
|
|
247
247
|
const styles = StyleSheet.create({
|
|
248
248
|
container: {
|
|
249
249
|
flexDirection: 'row',
|
|
250
|
-
justifyContent: '
|
|
250
|
+
justifyContent: 'flex-end',
|
|
251
251
|
marginTop: 16,
|
|
252
252
|
marginBottom: 8,
|
|
253
253
|
width: '100%',
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# TextField Component
|
|
2
|
+
|
|
3
|
+
A comprehensive, production-ready text input component with advanced features, validation, and accessibility support.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### ✨ Core Features
|
|
8
|
+
- **Floating Labels**: Animated labels that float above the input when focused or filled
|
|
9
|
+
- **Material Design**: Follows Material Design principles with outlined and filled variants
|
|
10
|
+
- **Cross-Platform**: Optimized for both React Native and Web platforms
|
|
11
|
+
- **Accessibility**: Full accessibility support with proper labels, hints, and roles
|
|
12
|
+
- **Customizable**: Extensive theming and styling options
|
|
13
|
+
|
|
14
|
+
### 🎯 Advanced Features
|
|
15
|
+
- **Input Masking**: Built-in masks for phone numbers, credit cards, and currency
|
|
16
|
+
- **Password Strength**: Real-time password strength indicator
|
|
17
|
+
- **Character Counting**: Optional character count display
|
|
18
|
+
- **Debounced Validation**: Configurable debounced validation with loading states
|
|
19
|
+
- **Clear Button**: Optional clear button for easy input clearing
|
|
20
|
+
- **Custom Components**: Support for custom left and right components
|
|
21
|
+
- **Disabled State**: Full disabled state support
|
|
22
|
+
- **Helper Text**: Optional helper text below inputs
|
|
23
|
+
- **Validation States**: Error, success, and loading states with visual indicators
|
|
24
|
+
|
|
25
|
+
### 🔧 Technical Features
|
|
26
|
+
- **TypeScript**: Full TypeScript support with comprehensive type definitions
|
|
27
|
+
- **Performance**: Optimized with proper memoization and debouncing
|
|
28
|
+
- **Ref Forwarding**: Proper ref forwarding for focus management
|
|
29
|
+
- **Event Handling**: Comprehensive event handling with proper cleanup
|
|
30
|
+
- **State Management**: Robust internal state management
|
|
31
|
+
|
|
32
|
+
## Props
|
|
33
|
+
|
|
34
|
+
### Basic Props
|
|
35
|
+
| Prop | Type | Default | Description |
|
|
36
|
+
|------|------|---------|-------------|
|
|
37
|
+
| `label` | `string` | - | The label text for the input |
|
|
38
|
+
| `icon` | `string` | - | Ionicons icon name |
|
|
39
|
+
| `iconColor` | `string` | - | Custom icon color |
|
|
40
|
+
| `error` | `string` | - | Error message to display |
|
|
41
|
+
| `success` | `boolean` | `false` | Whether to show success state |
|
|
42
|
+
| `loading` | `boolean` | `false` | Whether to show loading state |
|
|
43
|
+
| `variant` | `'outlined' \| 'filled'` | `'outlined'` | Input variant style |
|
|
44
|
+
| `disabled` | `boolean` | `false` | Whether the input is disabled |
|
|
45
|
+
|
|
46
|
+
### Enhanced Features
|
|
47
|
+
| Prop | Type | Default | Description |
|
|
48
|
+
|------|------|---------|-------------|
|
|
49
|
+
| `helperText` | `string` | - | Helper text displayed below input |
|
|
50
|
+
| `maxLength` | `number` | - | Maximum character limit |
|
|
51
|
+
| `showCharacterCount` | `boolean` | `false` | Show character count |
|
|
52
|
+
| `inputMask` | `'phone' \| 'creditCard' \| 'currency' \| 'custom'` | - | Input masking type |
|
|
53
|
+
| `customMask` | `(value: string) => string` | - | Custom masking function |
|
|
54
|
+
| `formatValue` | `(value: string) => string` | - | Custom value formatting |
|
|
55
|
+
| `validateOnChange` | `boolean` | `false` | Enable real-time validation |
|
|
56
|
+
| `debounceMs` | `number` | `300` | Debounce delay for validation |
|
|
57
|
+
| `passwordStrength` | `boolean` | `false` | Show password strength indicator |
|
|
58
|
+
| `clearable` | `boolean` | `false` | Show clear button |
|
|
59
|
+
|
|
60
|
+
### Accessibility Props
|
|
61
|
+
| Prop | Type | Default | Description |
|
|
62
|
+
|------|------|---------|-------------|
|
|
63
|
+
| `accessibilityLabel` | `string` | - | Accessibility label |
|
|
64
|
+
| `accessibilityHint` | `string` | - | Accessibility hint |
|
|
65
|
+
| `accessibilityRole` | `string` | `'text'` | Accessibility role |
|
|
66
|
+
|
|
67
|
+
### Advanced Props
|
|
68
|
+
| Prop | Type | Default | Description |
|
|
69
|
+
|------|------|---------|-------------|
|
|
70
|
+
| `onValidationChange` | `(isValid: boolean, value: string) => void` | - | Validation change callback |
|
|
71
|
+
| `onClear` | `() => void` | - | Clear button callback |
|
|
72
|
+
| `autoFocus` | `boolean` | `false` | Auto focus on mount |
|
|
73
|
+
| `returnKeyType` | `'done' \| 'go' \| 'next' \| 'search' \| 'send'` | - | Return key type |
|
|
74
|
+
| `blurOnSubmit` | `boolean` | - | Blur on submit |
|
|
75
|
+
| `keyboardType` | `KeyboardTypeOptions` | - | Keyboard type |
|
|
76
|
+
|
|
77
|
+
### Styling Props
|
|
78
|
+
| Prop | Type | Default | Description |
|
|
79
|
+
|------|------|---------|-------------|
|
|
80
|
+
| `colors` | `object` | - | Color theme object |
|
|
81
|
+
| `containerStyle` | `StyleProp<ViewStyle>` | - | Container style |
|
|
82
|
+
| `inputStyle` | `StyleProp<TextStyle>` | - | Input style |
|
|
83
|
+
| `labelStyle` | `StyleProp<TextStyle>` | - | Label style |
|
|
84
|
+
| `errorStyle` | `StyleProp<ViewStyle>` | - | Error container style |
|
|
85
|
+
|
|
86
|
+
### Component Props
|
|
87
|
+
| Prop | Type | Default | Description |
|
|
88
|
+
|------|------|---------|-------------|
|
|
89
|
+
| `leftComponent` | `ReactNode` | - | Custom left component |
|
|
90
|
+
| `rightComponent` | `ReactNode` | - | Custom right component |
|
|
91
|
+
|
|
92
|
+
## Color Theme Object
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
interface ColorTheme {
|
|
96
|
+
primary: string; // Primary color for focus states
|
|
97
|
+
secondaryText: string; // Secondary text color
|
|
98
|
+
text: string; // Main text color
|
|
99
|
+
error: string; // Error color
|
|
100
|
+
success: string; // Success color
|
|
101
|
+
border: string; // Border color
|
|
102
|
+
inputBackground: string; // Input background color
|
|
103
|
+
disabled: string; // Disabled text color
|
|
104
|
+
disabledBackground: string; // Disabled background color
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Usage Examples
|
|
109
|
+
|
|
110
|
+
### Basic Usage
|
|
111
|
+
```tsx
|
|
112
|
+
import TextField from './TextField';
|
|
113
|
+
|
|
114
|
+
<TextField
|
|
115
|
+
label="Username"
|
|
116
|
+
value={username}
|
|
117
|
+
onChangeText={setUsername}
|
|
118
|
+
colors={colors}
|
|
119
|
+
/>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### With Icon and Validation
|
|
123
|
+
```tsx
|
|
124
|
+
<TextField
|
|
125
|
+
label="Email"
|
|
126
|
+
icon="mail-outline"
|
|
127
|
+
value={email}
|
|
128
|
+
onChangeText={setEmail}
|
|
129
|
+
error={emailError}
|
|
130
|
+
success={isEmailValid}
|
|
131
|
+
colors={colors}
|
|
132
|
+
variant="filled"
|
|
133
|
+
/>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Password with Strength Indicator
|
|
137
|
+
```tsx
|
|
138
|
+
<TextField
|
|
139
|
+
label="Password"
|
|
140
|
+
icon="lock-closed-outline"
|
|
141
|
+
value={password}
|
|
142
|
+
onChangeText={setPassword}
|
|
143
|
+
secureTextEntry={true}
|
|
144
|
+
passwordStrength={true}
|
|
145
|
+
colors={colors}
|
|
146
|
+
helperText="Enter a strong password"
|
|
147
|
+
/>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Phone Number with Mask
|
|
151
|
+
```tsx
|
|
152
|
+
<TextField
|
|
153
|
+
label="Phone Number"
|
|
154
|
+
icon="call-outline"
|
|
155
|
+
value={phone}
|
|
156
|
+
onChangeText={setPhone}
|
|
157
|
+
inputMask="phone"
|
|
158
|
+
keyboardType="phone-pad"
|
|
159
|
+
colors={colors}
|
|
160
|
+
/>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Credit Card with Character Count
|
|
164
|
+
```tsx
|
|
165
|
+
<TextField
|
|
166
|
+
label="Credit Card"
|
|
167
|
+
icon="card-outline"
|
|
168
|
+
value={creditCard}
|
|
169
|
+
onChangeText={setCreditCard}
|
|
170
|
+
inputMask="creditCard"
|
|
171
|
+
keyboardType="numeric"
|
|
172
|
+
maxLength={19}
|
|
173
|
+
showCharacterCount={true}
|
|
174
|
+
colors={colors}
|
|
175
|
+
/>
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Real-time Validation
|
|
179
|
+
```tsx
|
|
180
|
+
<TextField
|
|
181
|
+
label="Username"
|
|
182
|
+
icon="person-outline"
|
|
183
|
+
value={username}
|
|
184
|
+
onChangeText={setUsername}
|
|
185
|
+
error={usernameError}
|
|
186
|
+
success={isUsernameValid}
|
|
187
|
+
loading={isValidating}
|
|
188
|
+
validateOnChange={true}
|
|
189
|
+
debounceMs={500}
|
|
190
|
+
onValidationChange={(isValid, value) => {
|
|
191
|
+
// Handle validation result
|
|
192
|
+
}}
|
|
193
|
+
colors={colors}
|
|
194
|
+
/>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Disabled State
|
|
198
|
+
```tsx
|
|
199
|
+
<TextField
|
|
200
|
+
label="Disabled Field"
|
|
201
|
+
value="This field is disabled"
|
|
202
|
+
onChangeText={() => {}}
|
|
203
|
+
disabled={true}
|
|
204
|
+
colors={colors}
|
|
205
|
+
helperText="This field cannot be edited"
|
|
206
|
+
/>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Custom Right Component
|
|
210
|
+
```tsx
|
|
211
|
+
<TextField
|
|
212
|
+
label="With Custom Button"
|
|
213
|
+
icon="add-circle-outline"
|
|
214
|
+
value={value}
|
|
215
|
+
onChangeText={setValue}
|
|
216
|
+
colors={colors}
|
|
217
|
+
rightComponent={
|
|
218
|
+
<TouchableOpacity
|
|
219
|
+
style={styles.customButton}
|
|
220
|
+
onPress={handleCustomAction}
|
|
221
|
+
>
|
|
222
|
+
<Text style={styles.customButtonText}>Add</Text>
|
|
223
|
+
</TouchableOpacity>
|
|
224
|
+
}
|
|
225
|
+
/>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Multiline Input
|
|
229
|
+
```tsx
|
|
230
|
+
<TextField
|
|
231
|
+
label="Bio"
|
|
232
|
+
icon="document-text-outline"
|
|
233
|
+
value={bio}
|
|
234
|
+
onChangeText={setBio}
|
|
235
|
+
multiline={true}
|
|
236
|
+
numberOfLines={4}
|
|
237
|
+
maxLength={500}
|
|
238
|
+
showCharacterCount={true}
|
|
239
|
+
colors={colors}
|
|
240
|
+
helperText="Tell us about yourself"
|
|
241
|
+
/>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Input Masks
|
|
245
|
+
|
|
246
|
+
### Built-in Masks
|
|
247
|
+
|
|
248
|
+
#### Phone Number
|
|
249
|
+
```tsx
|
|
250
|
+
inputMask="phone"
|
|
251
|
+
// Input: 1234567890
|
|
252
|
+
// Output: (123) 456-7890
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
#### Credit Card
|
|
256
|
+
```tsx
|
|
257
|
+
inputMask="creditCard"
|
|
258
|
+
// Input: 1234567890123456
|
|
259
|
+
// Output: 1234 5678 9012 3456
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Currency
|
|
263
|
+
```tsx
|
|
264
|
+
inputMask="currency"
|
|
265
|
+
// Input: 123.45
|
|
266
|
+
// Output: $123.45
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Custom Mask
|
|
270
|
+
```tsx
|
|
271
|
+
const customMask = (value: string) => {
|
|
272
|
+
// Your custom formatting logic
|
|
273
|
+
return formattedValue;
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
<TextField
|
|
277
|
+
inputMask="custom"
|
|
278
|
+
customMask={customMask}
|
|
279
|
+
// ... other props
|
|
280
|
+
/>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Password Strength
|
|
284
|
+
|
|
285
|
+
The password strength indicator provides real-time feedback on password strength:
|
|
286
|
+
|
|
287
|
+
- **Weak (0-25%)**: Red
|
|
288
|
+
- **Fair (26-50%)**: Orange
|
|
289
|
+
- **Good (51-75%)**: Blue
|
|
290
|
+
- **Strong (76-100%)**: Green
|
|
291
|
+
|
|
292
|
+
```tsx
|
|
293
|
+
<TextField
|
|
294
|
+
label="Password"
|
|
295
|
+
secureTextEntry={true}
|
|
296
|
+
passwordStrength={true}
|
|
297
|
+
// ... other props
|
|
298
|
+
/>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Validation
|
|
302
|
+
|
|
303
|
+
### Real-time Validation
|
|
304
|
+
```tsx
|
|
305
|
+
const [emailError, setEmailError] = useState('');
|
|
306
|
+
const [isEmailValid, setIsEmailValid] = useState(false);
|
|
307
|
+
|
|
308
|
+
<TextField
|
|
309
|
+
label="Email"
|
|
310
|
+
value={email}
|
|
311
|
+
onChangeText={setEmail}
|
|
312
|
+
error={emailError}
|
|
313
|
+
success={isEmailValid}
|
|
314
|
+
validateOnChange={true}
|
|
315
|
+
debounceMs={500}
|
|
316
|
+
onValidationChange={(isValid, value) => {
|
|
317
|
+
if (isValid) {
|
|
318
|
+
setIsEmailValid(true);
|
|
319
|
+
setEmailError('');
|
|
320
|
+
} else {
|
|
321
|
+
setIsEmailValid(false);
|
|
322
|
+
setEmailError('Please enter a valid email address');
|
|
323
|
+
}
|
|
324
|
+
}}
|
|
325
|
+
/>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Accessibility
|
|
329
|
+
|
|
330
|
+
The component includes comprehensive accessibility support:
|
|
331
|
+
|
|
332
|
+
- Proper accessibility labels and hints
|
|
333
|
+
- Keyboard navigation support
|
|
334
|
+
- Screen reader compatibility
|
|
335
|
+
- Focus management
|
|
336
|
+
- Disabled state handling
|
|
337
|
+
|
|
338
|
+
```tsx
|
|
339
|
+
<TextField
|
|
340
|
+
label="Username"
|
|
341
|
+
accessibilityLabel="Enter your username"
|
|
342
|
+
accessibilityHint="Username must be at least 3 characters long"
|
|
343
|
+
accessibilityRole="text"
|
|
344
|
+
// ... other props
|
|
345
|
+
/>
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
## Focus Management
|
|
349
|
+
|
|
350
|
+
```tsx
|
|
351
|
+
const inputRef = useRef<TextInput>(null);
|
|
352
|
+
|
|
353
|
+
<TextField
|
|
354
|
+
ref={inputRef}
|
|
355
|
+
label="Username"
|
|
356
|
+
// ... other props
|
|
357
|
+
/>
|
|
358
|
+
|
|
359
|
+
// Focus the input
|
|
360
|
+
inputRef.current?.focus();
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## Styling
|
|
364
|
+
|
|
365
|
+
### Custom Colors
|
|
366
|
+
```tsx
|
|
367
|
+
const colors = {
|
|
368
|
+
primary: '#d169e5',
|
|
369
|
+
secondaryText: '#666666',
|
|
370
|
+
text: '#000000',
|
|
371
|
+
error: '#D32F2F',
|
|
372
|
+
success: '#2E7D32',
|
|
373
|
+
border: '#E0E0E0',
|
|
374
|
+
inputBackground: '#F5F5F5',
|
|
375
|
+
disabled: '#E0E0E0',
|
|
376
|
+
disabledBackground: '#F5F5F5',
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
<TextField
|
|
380
|
+
colors={colors}
|
|
381
|
+
// ... other props
|
|
382
|
+
/>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Custom Styles
|
|
386
|
+
```tsx
|
|
387
|
+
<TextField
|
|
388
|
+
containerStyle={{ marginBottom: 20 }}
|
|
389
|
+
inputStyle={{ fontSize: 18 }}
|
|
390
|
+
labelStyle={{ fontWeight: 'bold' }}
|
|
391
|
+
errorStyle={{ backgroundColor: '#ffebee' }}
|
|
392
|
+
// ... other props
|
|
393
|
+
/>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## Best Practices
|
|
397
|
+
|
|
398
|
+
1. **Always provide labels** for accessibility
|
|
399
|
+
2. **Use appropriate keyboard types** for different input types
|
|
400
|
+
3. **Implement proper validation** with user-friendly error messages
|
|
401
|
+
4. **Use debouncing** for real-time validation to avoid performance issues
|
|
402
|
+
5. **Provide helper text** for complex inputs
|
|
403
|
+
6. **Handle disabled states** appropriately
|
|
404
|
+
7. **Use consistent color themes** across your app
|
|
405
|
+
8. **Test accessibility** with screen readers
|
|
406
|
+
|
|
407
|
+
## Performance Considerations
|
|
408
|
+
|
|
409
|
+
- The component uses `useCallback` and `useMemo` for performance optimization
|
|
410
|
+
- Debouncing is built-in for validation to prevent excessive re-renders
|
|
411
|
+
- Proper cleanup of timers and animations
|
|
412
|
+
- Efficient state management to minimize re-renders
|
|
413
|
+
|
|
414
|
+
## Browser Support
|
|
415
|
+
|
|
416
|
+
- React Native: All supported platforms
|
|
417
|
+
- Web: Modern browsers with React Native Web support
|
|
418
|
+
- Mobile: iOS and Android with proper keyboard handling
|
|
419
|
+
|
|
420
|
+
## Dependencies
|
|
421
|
+
|
|
422
|
+
- React Native
|
|
423
|
+
- @expo/vector-icons (for icons)
|
|
424
|
+
- react-native-svg (for border rendering)
|
|
425
|
+
|
|
426
|
+
## Migration from Previous Version
|
|
427
|
+
|
|
428
|
+
The improved TextField component is mostly backward compatible. Key changes:
|
|
429
|
+
|
|
430
|
+
1. **New props**: Added many new features while maintaining existing API
|
|
431
|
+
2. **Better TypeScript**: Improved type definitions
|
|
432
|
+
3. **Enhanced accessibility**: Better accessibility support
|
|
433
|
+
4. **Performance improvements**: Optimized rendering and state management
|
|
434
|
+
5. **Removed web-specific code**: Unified implementation for all platforms
|
|
435
|
+
|
|
436
|
+
Existing code should continue to work with minimal changes.
|