react-native-mantine 0.7.0 → 0.9.0
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 +37 -5
- package/lib/commonjs/components/Group/index.js.map +1 -1
- package/lib/commonjs/components/Radio/index.js +62 -6
- package/lib/commonjs/components/Radio/index.js.map +1 -1
- package/lib/commonjs/components/Switch/index.js +6 -2
- package/lib/commonjs/components/Switch/index.js.map +1 -1
- package/lib/commonjs/hooks/index.js +28 -0
- package/lib/commonjs/hooks/index.js.map +1 -0
- package/lib/commonjs/hooks/use-form/index.js +40 -0
- package/lib/commonjs/hooks/use-form/index.js.map +1 -0
- package/lib/commonjs/hooks/use-form/types.js +2 -0
- package/lib/commonjs/hooks/use-form/types.js.map +1 -0
- package/lib/commonjs/hooks/use-form/useForm.js +418 -0
- package/lib/commonjs/hooks/use-form/useForm.js.map +1 -0
- package/lib/commonjs/hooks/use-form/validators.js +135 -0
- package/lib/commonjs/hooks/use-form/validators.js.map +1 -0
- package/lib/commonjs/index.js +11 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/components/Group/index.js.map +1 -1
- package/lib/module/components/Radio/index.js +64 -8
- package/lib/module/components/Radio/index.js.map +1 -1
- package/lib/module/components/Switch/index.js +6 -2
- package/lib/module/components/Switch/index.js.map +1 -1
- package/lib/module/hooks/index.js +5 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/use-form/index.js +6 -0
- package/lib/module/hooks/use-form/index.js.map +1 -0
- package/lib/module/hooks/use-form/types.js +2 -0
- package/lib/module/hooks/use-form/types.js.map +1 -0
- package/lib/module/hooks/use-form/useForm.js +414 -0
- package/lib/module/hooks/use-form/useForm.js.map +1 -0
- package/lib/module/hooks/use-form/validators.js +122 -0
- package/lib/module/hooks/use-form/validators.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/components/Group/index.d.ts +1 -0
- package/lib/typescript/commonjs/src/components/Group/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/Radio/index.d.ts +22 -1
- package/lib/typescript/commonjs/src/components/Radio/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/components/Switch/index.d.ts +3 -3
- package/lib/typescript/commonjs/src/components/Switch/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/hooks/index.d.ts +3 -0
- package/lib/typescript/commonjs/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/hooks/use-form/index.d.ts +4 -0
- package/lib/typescript/commonjs/src/hooks/use-form/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/hooks/use-form/types.d.ts +119 -0
- package/lib/typescript/commonjs/src/hooks/use-form/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/hooks/use-form/useForm.d.ts +30 -0
- package/lib/typescript/commonjs/src/hooks/use-form/useForm.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/hooks/use-form/validators.d.ts +41 -0
- package/lib/typescript/commonjs/src/hooks/use-form/validators.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +1 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/components/Group/index.d.ts +1 -0
- package/lib/typescript/module/src/components/Group/index.d.ts.map +1 -1
- package/lib/typescript/module/src/components/Radio/index.d.ts +22 -1
- package/lib/typescript/module/src/components/Radio/index.d.ts.map +1 -1
- package/lib/typescript/module/src/components/Switch/index.d.ts +3 -3
- package/lib/typescript/module/src/components/Switch/index.d.ts.map +1 -1
- package/lib/typescript/module/src/hooks/index.d.ts +3 -0
- package/lib/typescript/module/src/hooks/index.d.ts.map +1 -0
- package/lib/typescript/module/src/hooks/use-form/index.d.ts +4 -0
- package/lib/typescript/module/src/hooks/use-form/index.d.ts.map +1 -0
- package/lib/typescript/module/src/hooks/use-form/types.d.ts +119 -0
- package/lib/typescript/module/src/hooks/use-form/types.d.ts.map +1 -0
- package/lib/typescript/module/src/hooks/use-form/useForm.d.ts +30 -0
- package/lib/typescript/module/src/hooks/use-form/useForm.d.ts.map +1 -0
- package/lib/typescript/module/src/hooks/use-form/validators.d.ts +41 -0
- package/lib/typescript/module/src/hooks/use-form/validators.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +1 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Group/index.tsx +1 -0
- package/src/components/Radio/index.tsx +99 -8
- package/src/components/Switch/index.tsx +10 -6
- package/src/hooks/index.ts +2 -0
- package/src/hooks/use-form/index.ts +3 -0
- package/src/hooks/use-form/types.ts +169 -0
- package/src/hooks/use-form/useForm.ts +436 -0
- package/src/hooks/use-form/validators.ts +143 -0
- package/src/index.tsx +1 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form field validation function
|
|
3
|
+
*/
|
|
4
|
+
export type FormValidator<T> = (value: T) => string | null;
|
|
5
|
+
/**
|
|
6
|
+
* Form validation rules
|
|
7
|
+
*/
|
|
8
|
+
export type FormValidationRules<Values> = {
|
|
9
|
+
[K in keyof Values]?: FormValidator<Values[K]> | FormValidator<Values[K]>[];
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Form errors
|
|
13
|
+
*/
|
|
14
|
+
export type FormErrors<Values = Record<string, any>> = Partial<Record<keyof Values, string>>;
|
|
15
|
+
/**
|
|
16
|
+
* Form touched state
|
|
17
|
+
*/
|
|
18
|
+
export type FormTouched<Values = Record<string, any>> = Partial<Record<keyof Values, boolean>>;
|
|
19
|
+
/**
|
|
20
|
+
* Form dirty state
|
|
21
|
+
*/
|
|
22
|
+
export type FormDirty<Values = Record<string, any>> = Partial<Record<keyof Values, boolean>>;
|
|
23
|
+
/**
|
|
24
|
+
* Form field status
|
|
25
|
+
*/
|
|
26
|
+
export interface FormFieldStatus {
|
|
27
|
+
hasError: boolean;
|
|
28
|
+
isTouched: boolean;
|
|
29
|
+
isDirty: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Props to be spread on input components
|
|
33
|
+
*/
|
|
34
|
+
export interface FormInputProps<T = any> {
|
|
35
|
+
value: T;
|
|
36
|
+
onChange?: (value: T) => void;
|
|
37
|
+
onChangeText?: (text: string) => void;
|
|
38
|
+
error?: string;
|
|
39
|
+
onBlur?: () => void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Form submit handler
|
|
43
|
+
*/
|
|
44
|
+
export type FormSubmitHandler<Values> = (values: Values, event?: any) => void | Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* useForm hook input parameters
|
|
47
|
+
*/
|
|
48
|
+
export interface UseFormInput<Values = Record<string, any>> {
|
|
49
|
+
/** Initial form values */
|
|
50
|
+
initialValues?: Values;
|
|
51
|
+
/** Initial form errors */
|
|
52
|
+
initialErrors?: FormErrors<Values>;
|
|
53
|
+
/** Initial touched state */
|
|
54
|
+
initialTouched?: FormTouched<Values>;
|
|
55
|
+
/** Initial dirty state */
|
|
56
|
+
initialDirty?: FormDirty<Values>;
|
|
57
|
+
/** Form validation rules */
|
|
58
|
+
validate?: FormValidationRules<Values>;
|
|
59
|
+
/** Clear input error on change */
|
|
60
|
+
clearInputErrorOnChange?: boolean;
|
|
61
|
+
/** Validate input on change */
|
|
62
|
+
validateInputOnChange?: boolean;
|
|
63
|
+
/** Validate input on blur */
|
|
64
|
+
validateInputOnBlur?: boolean;
|
|
65
|
+
/** Transform values before submit */
|
|
66
|
+
transformValues?: (values: Values) => any;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* useForm hook return type
|
|
70
|
+
*/
|
|
71
|
+
export interface UseFormReturnType<Values = Record<string, any>> {
|
|
72
|
+
/** Current form values */
|
|
73
|
+
values: Values;
|
|
74
|
+
/** Current form errors */
|
|
75
|
+
errors: FormErrors<Values>;
|
|
76
|
+
/** Current touched state */
|
|
77
|
+
touched: FormTouched<Values>;
|
|
78
|
+
/** Current dirty state */
|
|
79
|
+
dirty: FormDirty<Values>;
|
|
80
|
+
/** Set a single field value */
|
|
81
|
+
setFieldValue: <K extends keyof Values>(field: K, value: Values[K]) => void;
|
|
82
|
+
/** Set multiple values */
|
|
83
|
+
setValues: (values: Partial<Values>) => void;
|
|
84
|
+
/** Set a single field error */
|
|
85
|
+
setFieldError: <K extends keyof Values>(field: K, error: string | null) => void;
|
|
86
|
+
/** Set multiple errors */
|
|
87
|
+
setErrors: (errors: FormErrors<Values>) => void;
|
|
88
|
+
/** Clear a specific field error */
|
|
89
|
+
clearFieldError: <K extends keyof Values>(field: K) => void;
|
|
90
|
+
/** Clear all errors */
|
|
91
|
+
clearErrors: () => void;
|
|
92
|
+
/** Reset form to initial values */
|
|
93
|
+
reset: () => void;
|
|
94
|
+
/** Validate a specific field */
|
|
95
|
+
validateField: <K extends keyof Values>(field: K) => boolean;
|
|
96
|
+
/** Validate entire form */
|
|
97
|
+
validate: () => boolean;
|
|
98
|
+
/** Check if form is valid */
|
|
99
|
+
isValid: () => boolean;
|
|
100
|
+
/** Check if form is dirty */
|
|
101
|
+
isDirty: () => boolean;
|
|
102
|
+
/** Get field status */
|
|
103
|
+
getFieldStatus: <K extends keyof Values>(field: K) => FormFieldStatus;
|
|
104
|
+
/** Get props to spread on input component */
|
|
105
|
+
getInputProps: <K extends keyof Values>(field: K, options?: {
|
|
106
|
+
type?: 'input' | 'checkbox' | 'radio' | 'select';
|
|
107
|
+
withError?: boolean;
|
|
108
|
+
withFocus?: boolean;
|
|
109
|
+
}) => FormInputProps<Values[K]>;
|
|
110
|
+
/** Handle form submit */
|
|
111
|
+
onSubmit: (handleSubmit: FormSubmitHandler<Values>) => (event?: any) => void | Promise<void>;
|
|
112
|
+
/** Reset touched state */
|
|
113
|
+
resetTouched: () => void;
|
|
114
|
+
/** Reset dirty state */
|
|
115
|
+
resetDirty: () => void;
|
|
116
|
+
/** Mark field as touched */
|
|
117
|
+
setFieldTouched: <K extends keyof Values>(field: K, touched?: boolean) => void;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/hooks/use-form/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { UseFormInput, UseFormReturnType } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Form state management hook for React Native
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```tsx
|
|
7
|
+
* const form = useForm({
|
|
8
|
+
* initialValues: {
|
|
9
|
+
* email: '',
|
|
10
|
+
* password: '',
|
|
11
|
+
* },
|
|
12
|
+
* validate: {
|
|
13
|
+
* email: isEmail('Invalid email'),
|
|
14
|
+
* password: minLength(6, 'Password must be at least 6 characters'),
|
|
15
|
+
* },
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* return (
|
|
19
|
+
* <View>
|
|
20
|
+
* <TextInput {...form.getInputProps('email')} />
|
|
21
|
+
* <TextInput {...form.getInputProps('password')} />
|
|
22
|
+
* <Button onPress={form.onSubmit((values) => console.log(values))}>
|
|
23
|
+
* Submit
|
|
24
|
+
* </Button>
|
|
25
|
+
* </View>
|
|
26
|
+
* );
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function useForm<Values extends Record<string, any> = Record<string, any>>({ initialValues, initialErrors, initialTouched, initialDirty, validate: validationRules, clearInputErrorOnChange, validateInputOnChange, validateInputOnBlur, transformValues, }?: UseFormInput<Values>): UseFormReturnType<Values>;
|
|
30
|
+
//# sourceMappingURL=useForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useForm.d.ts","sourceRoot":"","sources":["../../../../../../src/hooks/use-form/useForm.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAQV,YAAY,EACZ,iBAAiB,EAClB,MAAM,SAAS,CAAC;AA4DjB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,OAAO,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAChF,aAA4B,EAC5B,aAAkB,EAClB,cAAmB,EACnB,YAAiB,EACjB,QAAQ,EAAE,eAAe,EACzB,uBAA8B,EAC9B,qBAA6B,EAC7B,mBAA2B,EAC3B,eAA4C,GAC7C,GAAE,YAAY,CAAC,MAAM,CAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAuUvD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { FormValidator } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in validators
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Validates that a value is not empty
|
|
7
|
+
*/
|
|
8
|
+
export declare const isNotEmpty: (message?: string) => FormValidator<any>;
|
|
9
|
+
/**
|
|
10
|
+
* Validates minimum length
|
|
11
|
+
*/
|
|
12
|
+
export declare const minLength: (min: number, message?: string) => FormValidator<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Validates maximum length
|
|
15
|
+
*/
|
|
16
|
+
export declare const maxLength: (max: number, message?: string) => FormValidator<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Validates that value matches a pattern
|
|
19
|
+
*/
|
|
20
|
+
export declare const matches: (pattern: RegExp, message?: string) => FormValidator<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Validates email format
|
|
23
|
+
*/
|
|
24
|
+
export declare const isEmail: (message?: string) => FormValidator<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Validates minimum value
|
|
27
|
+
*/
|
|
28
|
+
export declare const min: (minValue: number, message?: string) => FormValidator<number>;
|
|
29
|
+
/**
|
|
30
|
+
* Validates maximum value
|
|
31
|
+
*/
|
|
32
|
+
export declare const max: (maxValue: number, message?: string) => FormValidator<number>;
|
|
33
|
+
/**
|
|
34
|
+
* Validates that value is in a range
|
|
35
|
+
*/
|
|
36
|
+
export declare const inRange: (minValue: number, maxValue: number, message?: string) => FormValidator<number>;
|
|
37
|
+
/**
|
|
38
|
+
* Validates that value is in a list
|
|
39
|
+
*/
|
|
40
|
+
export declare const isInArray: <T>(array: T[], message?: string) => FormValidator<T>;
|
|
41
|
+
//# sourceMappingURL=validators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../../../../src/hooks/use-form/validators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C;;GAEG;AAEH;;GAEG;AACH,eAAO,MAAM,UAAU,GAAI,gBAAkC,KAAG,aAAa,CAAC,GAAG,CAahF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,GACpB,KAAK,MAAM,EACX,UAAU,MAAM,KACf,aAAa,CAAC,MAAM,CAQtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,GACpB,KAAK,MAAM,EACX,UAAU,MAAM,KACf,aAAa,CAAC,MAAM,CAQtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,GAClB,SAAS,MAAM,EACf,gBAA0B,KACzB,aAAa,CAAC,MAAM,CAQtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,GAAI,gBAAyB,KAAG,aAAa,CAAC,MAAM,CAGvE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,GAAG,GACd,UAAU,MAAM,EAChB,UAAU,MAAM,KACf,aAAa,CAAC,MAAM,CAQtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,GAAG,GACd,UAAU,MAAM,EAChB,UAAU,MAAM,KACf,aAAa,CAAC,MAAM,CAQtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,OAAO,GAClB,UAAU,MAAM,EAChB,UAAU,MAAM,EAChB,UAAU,MAAM,KACf,aAAa,CAAC,MAAM,CAQtB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,EACzB,OAAO,CAAC,EAAE,EACV,gBAAyB,KACxB,aAAa,CAAC,CAAC,CAOjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,mBAAmB,eAAe,CAAC;AACnC,mBAAmB,eAAe,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,mBAAmB,eAAe,CAAC;AACnC,mBAAmB,eAAe,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { forwardRef, useEffect, useRef } from 'react';
|
|
2
|
-
import { Pressable, Animated } from 'react-native';
|
|
1
|
+
import React, { forwardRef, useEffect, useRef, createContext, useContext } from 'react';
|
|
2
|
+
import { Pressable, Animated, View } from 'react-native';
|
|
3
3
|
import { BoxView } from '../BoxView';
|
|
4
4
|
import { Text } from '../Text';
|
|
5
5
|
import type { DefaultProps, MantineColor, MantineSize } from '../../theme/types';
|
|
@@ -36,6 +36,44 @@ export interface RadioProps extends DefaultProps {
|
|
|
36
36
|
wrapperStyle?: any;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
export interface RadioGroupProps {
|
|
40
|
+
/** Current selected value */
|
|
41
|
+
value?: string;
|
|
42
|
+
|
|
43
|
+
/** Called when value changes */
|
|
44
|
+
onChange?: (value: string) => void;
|
|
45
|
+
|
|
46
|
+
/** Radio group children */
|
|
47
|
+
children: React.ReactNode;
|
|
48
|
+
|
|
49
|
+
/** Radio group name for accessibility */
|
|
50
|
+
name?: string;
|
|
51
|
+
|
|
52
|
+
/** Radio size for all children */
|
|
53
|
+
size?: MantineSize;
|
|
54
|
+
|
|
55
|
+
/** Radio color for all children */
|
|
56
|
+
color?: MantineColor;
|
|
57
|
+
|
|
58
|
+
/** Wrapper style */
|
|
59
|
+
style?: any;
|
|
60
|
+
|
|
61
|
+
/** Spacing between radio buttons */
|
|
62
|
+
spacing?: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
interface RadioGroupContextValue {
|
|
66
|
+
value?: string;
|
|
67
|
+
onChange?: (value: string) => void;
|
|
68
|
+
size?: MantineSize;
|
|
69
|
+
color?: MantineColor;
|
|
70
|
+
name?: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const RadioGroupContext = createContext<RadioGroupContextValue | undefined>(undefined);
|
|
74
|
+
|
|
75
|
+
const useRadioGroupContext = () => useContext(RadioGroupContext);
|
|
76
|
+
|
|
39
77
|
const sizes = {
|
|
40
78
|
xs: rem(14),
|
|
41
79
|
sm: rem(18),
|
|
@@ -103,20 +141,28 @@ const defaultProps: Partial<RadioProps> = {
|
|
|
103
141
|
disabled: false,
|
|
104
142
|
};
|
|
105
143
|
|
|
106
|
-
|
|
144
|
+
const RadioComponent = forwardRef<any, RadioProps>((props, ref) => {
|
|
145
|
+
const groupContext = useRadioGroupContext();
|
|
146
|
+
|
|
107
147
|
const {
|
|
108
148
|
label,
|
|
109
|
-
size,
|
|
110
|
-
color,
|
|
149
|
+
size: propSize,
|
|
150
|
+
color: propColor,
|
|
111
151
|
value,
|
|
112
|
-
checked,
|
|
113
|
-
onChange,
|
|
152
|
+
checked: propChecked,
|
|
153
|
+
onChange: propOnChange,
|
|
114
154
|
disabled,
|
|
115
155
|
style,
|
|
116
156
|
wrapperStyle,
|
|
117
157
|
...others
|
|
118
158
|
} = useComponentDefaultProps('Radio', defaultProps, props);
|
|
119
159
|
|
|
160
|
+
// Use group context if available, otherwise use props
|
|
161
|
+
const size = propSize || groupContext?.size || defaultProps.size;
|
|
162
|
+
const color = propColor || groupContext?.color || defaultProps.color;
|
|
163
|
+
const checked = groupContext ? groupContext.value === value : propChecked;
|
|
164
|
+
const onChange = groupContext?.onChange || propOnChange;
|
|
165
|
+
|
|
120
166
|
const { styles, sx } = useStyles({ size, color, disabled }, { name: 'Radio' }) as any;
|
|
121
167
|
|
|
122
168
|
const scaleAnim = useRef(new Animated.Value(checked ? 1 : 0)).current;
|
|
@@ -158,6 +204,7 @@ export const Radio = forwardRef<any, RadioProps>((props, ref) => {
|
|
|
158
204
|
style={sx(styles.root, wrapperStyle)}
|
|
159
205
|
accessibilityRole="radio"
|
|
160
206
|
accessibilityState={{ checked }}
|
|
207
|
+
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
|
|
161
208
|
{...others}
|
|
162
209
|
>
|
|
163
210
|
{radioContent}
|
|
@@ -166,4 +213,48 @@ export const Radio = forwardRef<any, RadioProps>((props, ref) => {
|
|
|
166
213
|
);
|
|
167
214
|
});
|
|
168
215
|
|
|
169
|
-
|
|
216
|
+
RadioComponent.displayName = 'Radio';
|
|
217
|
+
|
|
218
|
+
const RadioGroup = forwardRef<View, RadioGroupProps>((props, ref) => {
|
|
219
|
+
const {
|
|
220
|
+
value,
|
|
221
|
+
onChange,
|
|
222
|
+
children,
|
|
223
|
+
name,
|
|
224
|
+
size,
|
|
225
|
+
color,
|
|
226
|
+
style,
|
|
227
|
+
spacing = 12,
|
|
228
|
+
} = props;
|
|
229
|
+
|
|
230
|
+
const contextValue: RadioGroupContextValue = {
|
|
231
|
+
value,
|
|
232
|
+
onChange,
|
|
233
|
+
size,
|
|
234
|
+
color,
|
|
235
|
+
name,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
return (
|
|
239
|
+
<RadioGroupContext.Provider value={contextValue}>
|
|
240
|
+
<View ref={ref} style={style}>
|
|
241
|
+
{React.Children.map(children, (child, index) => {
|
|
242
|
+
if (!React.isValidElement(child)) {
|
|
243
|
+
return child;
|
|
244
|
+
}
|
|
245
|
+
return (
|
|
246
|
+
<View key={index} style={{ marginBottom: index < React.Children.count(children) - 1 ? spacing : 0 }}>
|
|
247
|
+
{child}
|
|
248
|
+
</View>
|
|
249
|
+
);
|
|
250
|
+
})}
|
|
251
|
+
</View>
|
|
252
|
+
</RadioGroupContext.Provider>
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
RadioGroup.displayName = 'RadioGroup';
|
|
257
|
+
|
|
258
|
+
export const Radio = Object.assign(RadioComponent, {
|
|
259
|
+
Group: RadioGroup,
|
|
260
|
+
});
|
|
@@ -19,15 +19,15 @@ export interface SwitchProps extends DefaultProps {
|
|
|
19
19
|
/** Label position */
|
|
20
20
|
labelPosition?: 'left' | 'right';
|
|
21
21
|
|
|
22
|
-
/** Checked state */
|
|
22
|
+
/** Checked state (controlled component) */
|
|
23
23
|
checked?: boolean;
|
|
24
24
|
|
|
25
|
-
/** Default checked state */
|
|
26
|
-
defaultChecked?: boolean;
|
|
27
|
-
|
|
28
25
|
/** Called when switch state changes */
|
|
29
26
|
onChange?: (value: boolean) => void;
|
|
30
27
|
|
|
28
|
+
/** Disabled state */
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
|
|
31
31
|
/** Additional styles */
|
|
32
32
|
style?: any;
|
|
33
33
|
|
|
@@ -78,7 +78,7 @@ const defaultProps: Partial<SwitchProps> = {
|
|
|
78
78
|
size: 'md',
|
|
79
79
|
color: 'blue',
|
|
80
80
|
labelPosition: 'right',
|
|
81
|
-
|
|
81
|
+
disabled: false,
|
|
82
82
|
};
|
|
83
83
|
|
|
84
84
|
export const Switch = forwardRef<any, SwitchProps>((props, ref) => {
|
|
@@ -89,6 +89,7 @@ export const Switch = forwardRef<any, SwitchProps>((props, ref) => {
|
|
|
89
89
|
labelPosition,
|
|
90
90
|
checked,
|
|
91
91
|
onChange,
|
|
92
|
+
disabled,
|
|
92
93
|
style,
|
|
93
94
|
wrapperStyle,
|
|
94
95
|
} = useComponentDefaultProps('Switch', defaultProps, props);
|
|
@@ -97,7 +98,9 @@ export const Switch = forwardRef<any, SwitchProps>((props, ref) => {
|
|
|
97
98
|
const { styles, sx } = useStyles({ labelPosition, size }, { name: 'Switch' }) as any;
|
|
98
99
|
|
|
99
100
|
const handleChange = (value: boolean) => {
|
|
100
|
-
|
|
101
|
+
if (!disabled) {
|
|
102
|
+
onChange?.(value);
|
|
103
|
+
}
|
|
101
104
|
};
|
|
102
105
|
|
|
103
106
|
const colorKey = color || theme.primaryColor;
|
|
@@ -126,6 +129,7 @@ export const Switch = forwardRef<any, SwitchProps>((props, ref) => {
|
|
|
126
129
|
trackColor={trackColor}
|
|
127
130
|
thumbColor={thumbColor}
|
|
128
131
|
ios_backgroundColor={trackColor.false}
|
|
132
|
+
disabled={disabled}
|
|
129
133
|
style={sx(styles.switch, style)}
|
|
130
134
|
/>
|
|
131
135
|
);
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form field validation function
|
|
3
|
+
*/
|
|
4
|
+
export type FormValidator<T> = (value: T) => string | null;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Form validation rules
|
|
8
|
+
*/
|
|
9
|
+
export type FormValidationRules<Values> = {
|
|
10
|
+
[K in keyof Values]?: FormValidator<Values[K]> | FormValidator<Values[K]>[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Form errors
|
|
15
|
+
*/
|
|
16
|
+
export type FormErrors<Values = Record<string, any>> = Partial<
|
|
17
|
+
Record<keyof Values, string>
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Form touched state
|
|
22
|
+
*/
|
|
23
|
+
export type FormTouched<Values = Record<string, any>> = Partial<
|
|
24
|
+
Record<keyof Values, boolean>
|
|
25
|
+
>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Form dirty state
|
|
29
|
+
*/
|
|
30
|
+
export type FormDirty<Values = Record<string, any>> = Partial<
|
|
31
|
+
Record<keyof Values, boolean>
|
|
32
|
+
>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Form field status
|
|
36
|
+
*/
|
|
37
|
+
export interface FormFieldStatus {
|
|
38
|
+
hasError: boolean;
|
|
39
|
+
isTouched: boolean;
|
|
40
|
+
isDirty: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Props to be spread on input components
|
|
45
|
+
*/
|
|
46
|
+
export interface FormInputProps<T = any> {
|
|
47
|
+
value: T;
|
|
48
|
+
onChange?: (value: T) => void;
|
|
49
|
+
onChangeText?: (text: string) => void;
|
|
50
|
+
error?: string;
|
|
51
|
+
onBlur?: () => void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Form submit handler
|
|
56
|
+
*/
|
|
57
|
+
export type FormSubmitHandler<Values> = (
|
|
58
|
+
values: Values,
|
|
59
|
+
event?: any
|
|
60
|
+
) => void | Promise<void>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* useForm hook input parameters
|
|
64
|
+
*/
|
|
65
|
+
export interface UseFormInput<Values = Record<string, any>> {
|
|
66
|
+
/** Initial form values */
|
|
67
|
+
initialValues?: Values;
|
|
68
|
+
|
|
69
|
+
/** Initial form errors */
|
|
70
|
+
initialErrors?: FormErrors<Values>;
|
|
71
|
+
|
|
72
|
+
/** Initial touched state */
|
|
73
|
+
initialTouched?: FormTouched<Values>;
|
|
74
|
+
|
|
75
|
+
/** Initial dirty state */
|
|
76
|
+
initialDirty?: FormDirty<Values>;
|
|
77
|
+
|
|
78
|
+
/** Form validation rules */
|
|
79
|
+
validate?: FormValidationRules<Values>;
|
|
80
|
+
|
|
81
|
+
/** Clear input error on change */
|
|
82
|
+
clearInputErrorOnChange?: boolean;
|
|
83
|
+
|
|
84
|
+
/** Validate input on change */
|
|
85
|
+
validateInputOnChange?: boolean;
|
|
86
|
+
|
|
87
|
+
/** Validate input on blur */
|
|
88
|
+
validateInputOnBlur?: boolean;
|
|
89
|
+
|
|
90
|
+
/** Transform values before submit */
|
|
91
|
+
transformValues?: (values: Values) => any;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* useForm hook return type
|
|
96
|
+
*/
|
|
97
|
+
export interface UseFormReturnType<Values = Record<string, any>> {
|
|
98
|
+
/** Current form values */
|
|
99
|
+
values: Values;
|
|
100
|
+
|
|
101
|
+
/** Current form errors */
|
|
102
|
+
errors: FormErrors<Values>;
|
|
103
|
+
|
|
104
|
+
/** Current touched state */
|
|
105
|
+
touched: FormTouched<Values>;
|
|
106
|
+
|
|
107
|
+
/** Current dirty state */
|
|
108
|
+
dirty: FormDirty<Values>;
|
|
109
|
+
|
|
110
|
+
/** Set a single field value */
|
|
111
|
+
setFieldValue: <K extends keyof Values>(field: K, value: Values[K]) => void;
|
|
112
|
+
|
|
113
|
+
/** Set multiple values */
|
|
114
|
+
setValues: (values: Partial<Values>) => void;
|
|
115
|
+
|
|
116
|
+
/** Set a single field error */
|
|
117
|
+
setFieldError: <K extends keyof Values>(field: K, error: string | null) => void;
|
|
118
|
+
|
|
119
|
+
/** Set multiple errors */
|
|
120
|
+
setErrors: (errors: FormErrors<Values>) => void;
|
|
121
|
+
|
|
122
|
+
/** Clear a specific field error */
|
|
123
|
+
clearFieldError: <K extends keyof Values>(field: K) => void;
|
|
124
|
+
|
|
125
|
+
/** Clear all errors */
|
|
126
|
+
clearErrors: () => void;
|
|
127
|
+
|
|
128
|
+
/** Reset form to initial values */
|
|
129
|
+
reset: () => void;
|
|
130
|
+
|
|
131
|
+
/** Validate a specific field */
|
|
132
|
+
validateField: <K extends keyof Values>(field: K) => boolean;
|
|
133
|
+
|
|
134
|
+
/** Validate entire form */
|
|
135
|
+
validate: () => boolean;
|
|
136
|
+
|
|
137
|
+
/** Check if form is valid */
|
|
138
|
+
isValid: () => boolean;
|
|
139
|
+
|
|
140
|
+
/** Check if form is dirty */
|
|
141
|
+
isDirty: () => boolean;
|
|
142
|
+
|
|
143
|
+
/** Get field status */
|
|
144
|
+
getFieldStatus: <K extends keyof Values>(field: K) => FormFieldStatus;
|
|
145
|
+
|
|
146
|
+
/** Get props to spread on input component */
|
|
147
|
+
getInputProps: <K extends keyof Values>(
|
|
148
|
+
field: K,
|
|
149
|
+
options?: {
|
|
150
|
+
type?: 'input' | 'checkbox' | 'radio' | 'select';
|
|
151
|
+
withError?: boolean;
|
|
152
|
+
withFocus?: boolean;
|
|
153
|
+
}
|
|
154
|
+
) => FormInputProps<Values[K]>;
|
|
155
|
+
|
|
156
|
+
/** Handle form submit */
|
|
157
|
+
onSubmit: (
|
|
158
|
+
handleSubmit: FormSubmitHandler<Values>
|
|
159
|
+
) => (event?: any) => void | Promise<void>;
|
|
160
|
+
|
|
161
|
+
/** Reset touched state */
|
|
162
|
+
resetTouched: () => void;
|
|
163
|
+
|
|
164
|
+
/** Reset dirty state */
|
|
165
|
+
resetDirty: () => void;
|
|
166
|
+
|
|
167
|
+
/** Mark field as touched */
|
|
168
|
+
setFieldTouched: <K extends keyof Values>(field: K, touched?: boolean) => void;
|
|
169
|
+
}
|