@idealyst/components 1.2.106 → 1.2.108

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.
Files changed (47) hide show
  1. package/package.json +4 -4
  2. package/src/Dialog/Dialog.native.tsx +1 -1
  3. package/src/Form/Form.native.tsx +38 -0
  4. package/src/Form/Form.styles.tsx +14 -0
  5. package/src/Form/Form.web.tsx +50 -0
  6. package/src/Form/FormContext.ts +12 -0
  7. package/src/Form/fields/FormCheckbox.tsx +27 -0
  8. package/src/Form/fields/FormField.tsx +11 -0
  9. package/src/Form/fields/FormRadioGroup.tsx +24 -0
  10. package/src/Form/fields/FormSelect.tsx +27 -0
  11. package/src/Form/fields/FormSlider.tsx +26 -0
  12. package/src/Form/fields/FormSwitch.tsx +26 -0
  13. package/src/Form/fields/FormTextArea.tsx +27 -0
  14. package/src/Form/fields/FormTextInput.tsx +55 -0
  15. package/src/Form/index.native.ts +35 -0
  16. package/src/Form/index.ts +35 -0
  17. package/src/Form/index.web.ts +35 -0
  18. package/src/Form/types.ts +105 -0
  19. package/src/Form/useForm.ts +279 -0
  20. package/src/Form/useFormField.ts +21 -0
  21. package/src/Popover/Popover.native.tsx +1 -1
  22. package/src/RadioButton/RadioButton.styles.tsx +28 -0
  23. package/src/RadioButton/RadioGroup.native.tsx +28 -3
  24. package/src/RadioButton/RadioGroup.web.tsx +37 -1
  25. package/src/RadioButton/types.ts +16 -0
  26. package/src/Screen/Screen.native.tsx +12 -3
  27. package/src/Select/Select.native.tsx +10 -6
  28. package/src/Select/Select.styles.tsx +8 -8
  29. package/src/Select/Select.web.tsx +11 -7
  30. package/src/Select/types.ts +4 -2
  31. package/src/Slider/Slider.native.tsx +122 -0
  32. package/src/Slider/Slider.styles.tsx +48 -11
  33. package/src/Slider/Slider.web.tsx +54 -5
  34. package/src/Slider/types.ts +15 -0
  35. package/src/Switch/Switch.native.tsx +48 -20
  36. package/src/Switch/Switch.styles.tsx +28 -0
  37. package/src/Switch/Switch.web.tsx +55 -16
  38. package/src/Switch/types.ts +10 -0
  39. package/src/TextInput/TextInput.native.tsx +123 -40
  40. package/src/TextInput/TextInput.styles.tsx +47 -9
  41. package/src/TextInput/TextInput.web.tsx +163 -51
  42. package/src/TextInput/types.ts +16 -1
  43. package/src/hooks/useSmartPosition.native.ts +1 -1
  44. package/src/index.native.ts +19 -0
  45. package/src/index.ts +19 -0
  46. package/src/internal/BoundedModalContent.native.tsx +1 -1
  47. package/src/internal/SafeAreaDebugOverlay.native.tsx +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idealyst/components",
3
- "version": "1.2.106",
3
+ "version": "1.2.108",
4
4
  "description": "Shared component library for React and React Native",
5
5
  "documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/components#readme",
6
6
  "readme": "README.md",
@@ -56,7 +56,7 @@
56
56
  "publish:npm": "npm publish"
57
57
  },
58
58
  "peerDependencies": {
59
- "@idealyst/theme": "^1.2.106",
59
+ "@idealyst/theme": "^1.2.108",
60
60
  "@mdi/js": ">=7.0.0",
61
61
  "@mdi/react": ">=1.0.0",
62
62
  "@react-native-vector-icons/common": ">=12.0.0",
@@ -107,8 +107,8 @@
107
107
  },
108
108
  "devDependencies": {
109
109
  "@idealyst/blur": "^1.2.40",
110
- "@idealyst/theme": "^1.2.106",
111
- "@idealyst/tooling": "^1.2.106",
110
+ "@idealyst/theme": "^1.2.108",
111
+ "@idealyst/tooling": "^1.2.108",
112
112
  "@mdi/react": "^1.6.1",
113
113
  "@types/react": "^19.1.0",
114
114
  "react": "^19.1.0",
@@ -1,7 +1,7 @@
1
1
  import { useEffect, forwardRef, useMemo, useState } from 'react';
2
2
  import { Modal, View, Text, TouchableOpacity, TouchableWithoutFeedback, BackHandler, Platform, Keyboard, useWindowDimensions } from 'react-native';
3
3
  import Animated, { useSharedValue, useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated';
4
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
+ import { useSafeAreaInsets } from '@idealyst/theme';
5
5
  import { DialogProps } from './types';
6
6
  import { dialogStyles } from './Dialog.styles';
7
7
  import { getNativeInteractiveAccessibilityProps } from '../utils/accessibility';
@@ -0,0 +1,38 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { View } from 'react-native';
3
+ import { formStyles } from './Form.styles';
4
+ import { FormContext } from './FormContext';
5
+ import type { FormProps } from './types';
6
+ import type { IdealystElement } from '../utils/refTypes';
7
+
8
+ /**
9
+ * Form component for managing form state and validation.
10
+ * Wraps children in a context provider and renders a View on native.
11
+ */
12
+ const Form = forwardRef<IdealystElement, FormProps>(({
13
+ form,
14
+ children,
15
+ style,
16
+ testID,
17
+ id,
18
+ }, ref) => {
19
+ return (
20
+ <FormContext.Provider value={{ form }}>
21
+ <View
22
+ ref={ref as any}
23
+ nativeID={id}
24
+ style={[
25
+ formStyles.container,
26
+ style as any,
27
+ ]}
28
+ testID={testID}
29
+ >
30
+ {children}
31
+ </View>
32
+ </FormContext.Provider>
33
+ );
34
+ });
35
+
36
+ Form.displayName = 'Form';
37
+
38
+ export default Form;
@@ -0,0 +1,14 @@
1
+ import { StyleSheet } from 'react-native-unistyles';
2
+ import { defineStyle, ThemeStyleWrapper } from '@idealyst/theme';
3
+ import type { Theme as BaseTheme } from '@idealyst/theme';
4
+
5
+ void StyleSheet;
6
+ type Theme = ThemeStyleWrapper<BaseTheme>;
7
+
8
+ export const formStyles = defineStyle('Form', (_theme: Theme) => ({
9
+ container: {
10
+ display: 'flex' as const,
11
+ flexDirection: 'column' as const,
12
+ width: '100%',
13
+ },
14
+ }));
@@ -0,0 +1,50 @@
1
+ import React, { forwardRef, useCallback } from 'react';
2
+ import { getWebProps } from 'react-native-unistyles/web';
3
+ import { formStyles } from './Form.styles';
4
+ import { FormContext } from './FormContext';
5
+ import useMergeRefs from '../hooks/useMergeRefs';
6
+ import type { FormProps } from './types';
7
+ import type { IdealystElement } from '../utils/refTypes';
8
+
9
+ /**
10
+ * Form component for managing form state and validation.
11
+ * Wraps children in a context provider and renders a semantic <form> element on web.
12
+ */
13
+ const Form = forwardRef<IdealystElement, FormProps>(({
14
+ form,
15
+ children,
16
+ style,
17
+ testID,
18
+ id,
19
+ }, ref) => {
20
+ const handleSubmit = useCallback((e: React.FormEvent) => {
21
+ e.preventDefault();
22
+ form.handleSubmit();
23
+ }, [form]);
24
+
25
+ const containerProps = getWebProps([
26
+ formStyles.container,
27
+ style as any,
28
+ ]);
29
+
30
+ const mergedRef = useMergeRefs(ref, containerProps.ref);
31
+
32
+ return (
33
+ <FormContext.Provider value={{ form }}>
34
+ <form
35
+ {...containerProps}
36
+ ref={mergedRef}
37
+ onSubmit={handleSubmit}
38
+ noValidate
39
+ id={id}
40
+ data-testid={testID}
41
+ >
42
+ {children}
43
+ </form>
44
+ </FormContext.Provider>
45
+ );
46
+ });
47
+
48
+ Form.displayName = 'Form';
49
+
50
+ export default Form;
@@ -0,0 +1,12 @@
1
+ import { createContext, useContext } from 'react';
2
+ import type { FormContextValue } from './types';
3
+
4
+ export const FormContext = createContext<FormContextValue | null>(null);
5
+
6
+ export function useFormContext(): FormContextValue {
7
+ const ctx = useContext(FormContext);
8
+ if (!ctx) {
9
+ throw new Error('useFormContext must be used within a <Form> component');
10
+ }
11
+ return ctx;
12
+ }
@@ -0,0 +1,27 @@
1
+ import React, { forwardRef } from 'react';
2
+ import Checkbox from '../../Checkbox';
3
+ import { useFormField } from '../useFormField';
4
+ import type { FormCheckboxProps } from '../types';
5
+ import type { IdealystElement } from '../../utils/refTypes';
6
+
7
+ const FormCheckbox = forwardRef<IdealystElement, FormCheckboxProps>(({
8
+ name,
9
+ disabled: localDisabled,
10
+ ...rest
11
+ }, ref) => {
12
+ const field = useFormField(name);
13
+
14
+ return (
15
+ <Checkbox
16
+ ref={ref}
17
+ checked={Boolean(field.value)}
18
+ onChange={(checked: boolean) => field.onChange(checked)}
19
+ error={field.error}
20
+ disabled={field.disabled || localDisabled}
21
+ {...rest}
22
+ />
23
+ );
24
+ });
25
+
26
+ FormCheckbox.displayName = 'Form.Checkbox';
27
+ export default FormCheckbox;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { useFormField } from '../useFormField';
3
+ import type { FormFieldProps } from '../types';
4
+
5
+ const FormField: React.FC<FormFieldProps> = ({ name, children }) => {
6
+ const field = useFormField(name);
7
+ return <>{children(field)}</>;
8
+ };
9
+
10
+ FormField.displayName = 'Form.Field';
11
+ export default FormField;
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import { RadioGroup } from '../../RadioButton';
3
+ import { useFormField } from '../useFormField';
4
+ import type { FormRadioGroupProps } from '../types';
5
+
6
+ const FormRadioGroup: React.FC<FormRadioGroupProps> = ({
7
+ name,
8
+ disabled: localDisabled,
9
+ ...rest
10
+ }) => {
11
+ const field = useFormField(name);
12
+
13
+ return (
14
+ <RadioGroup
15
+ value={(field.value as string) ?? ''}
16
+ onValueChange={(value) => field.onChange(value)}
17
+ disabled={field.disabled || localDisabled}
18
+ {...rest}
19
+ />
20
+ );
21
+ };
22
+
23
+ FormRadioGroup.displayName = 'Form.RadioGroup';
24
+ export default FormRadioGroup;
@@ -0,0 +1,27 @@
1
+ import React, { forwardRef } from 'react';
2
+ import Select from '../../Select';
3
+ import { useFormField } from '../useFormField';
4
+ import type { FormSelectProps } from '../types';
5
+ import type { IdealystElement } from '../../utils/refTypes';
6
+
7
+ const FormSelect = forwardRef<IdealystElement, FormSelectProps>(({
8
+ name,
9
+ disabled: localDisabled,
10
+ ...rest
11
+ }, ref) => {
12
+ const field = useFormField(name);
13
+
14
+ return (
15
+ <Select
16
+ ref={ref}
17
+ value={(field.value as string) ?? ''}
18
+ onChange={(value) => field.onChange(value)}
19
+ error={Boolean(field.error)}
20
+ disabled={field.disabled || localDisabled}
21
+ {...rest}
22
+ />
23
+ );
24
+ });
25
+
26
+ FormSelect.displayName = 'Form.Select';
27
+ export default FormSelect;
@@ -0,0 +1,26 @@
1
+ import React, { forwardRef } from 'react';
2
+ import Slider from '../../Slider';
3
+ import { useFormField } from '../useFormField';
4
+ import type { FormSliderProps } from '../types';
5
+ import type { IdealystElement } from '../../utils/refTypes';
6
+
7
+ const FormSlider = forwardRef<IdealystElement, FormSliderProps>(({
8
+ name,
9
+ disabled: localDisabled,
10
+ ...rest
11
+ }, ref) => {
12
+ const field = useFormField(name);
13
+
14
+ return (
15
+ <Slider
16
+ ref={ref}
17
+ value={(field.value as number) ?? 0}
18
+ onChange={(value: number) => field.onChange(value)}
19
+ disabled={field.disabled || localDisabled}
20
+ {...rest}
21
+ />
22
+ );
23
+ });
24
+
25
+ FormSlider.displayName = 'Form.Slider';
26
+ export default FormSlider;
@@ -0,0 +1,26 @@
1
+ import React, { forwardRef } from 'react';
2
+ import Switch from '../../Switch';
3
+ import { useFormField } from '../useFormField';
4
+ import type { FormSwitchProps } from '../types';
5
+ import type { IdealystElement } from '../../utils/refTypes';
6
+
7
+ const FormSwitch = forwardRef<IdealystElement, FormSwitchProps>(({
8
+ name,
9
+ disabled: localDisabled,
10
+ ...rest
11
+ }, ref) => {
12
+ const field = useFormField(name);
13
+
14
+ return (
15
+ <Switch
16
+ ref={ref}
17
+ checked={Boolean(field.value)}
18
+ onChange={(checked: boolean) => field.onChange(checked)}
19
+ disabled={field.disabled || localDisabled}
20
+ {...rest}
21
+ />
22
+ );
23
+ });
24
+
25
+ FormSwitch.displayName = 'Form.Switch';
26
+ export default FormSwitch;
@@ -0,0 +1,27 @@
1
+ import React, { forwardRef } from 'react';
2
+ import TextArea from '../../TextArea';
3
+ import { useFormField } from '../useFormField';
4
+ import type { FormTextAreaProps } from '../types';
5
+ import type { IdealystElement } from '../../utils/refTypes';
6
+
7
+ const FormTextArea = forwardRef<IdealystElement, FormTextAreaProps>(({
8
+ name,
9
+ disabled: localDisabled,
10
+ ...rest
11
+ }, ref) => {
12
+ const field = useFormField(name);
13
+
14
+ return (
15
+ <TextArea
16
+ ref={ref}
17
+ value={(field.value as string) ?? ''}
18
+ onChange={(text) => field.onChange(text)}
19
+ error={field.error}
20
+ disabled={field.disabled || localDisabled}
21
+ {...rest}
22
+ />
23
+ );
24
+ });
25
+
26
+ FormTextArea.displayName = 'Form.TextArea';
27
+ export default FormTextArea;
@@ -0,0 +1,55 @@
1
+ import React, { forwardRef, useRef, useEffect } from 'react';
2
+ import TextInput from '../../TextInput';
3
+ import { useFormField } from '../useFormField';
4
+ import { useFormContext } from '../FormContext';
5
+ import useMergeRefs from '../../hooks/useMergeRefs';
6
+ import type { FormTextInputProps } from '../types';
7
+ import type { IdealystElement } from '../../utils/refTypes';
8
+
9
+ const FormTextInput = forwardRef<IdealystElement, FormTextInputProps>(({
10
+ name,
11
+ tabOrder,
12
+ disabled: localDisabled,
13
+ onSubmitEditing: userOnSubmitEditing,
14
+ returnKeyType: userReturnKeyType,
15
+ ...rest
16
+ }, ref) => {
17
+ const { form } = useFormContext();
18
+ const field = useFormField(name);
19
+ const inputRef = useRef<any>(null);
20
+ const mergedRef = useMergeRefs(ref, inputRef);
21
+
22
+ useEffect(() => {
23
+ form.registerField(name, inputRef, tabOrder);
24
+ return () => form.unregisterField(name);
25
+ }, [name, tabOrder, form]);
26
+
27
+ const isLast = form.isLastTextField(name);
28
+
29
+ const handleSubmitEditing = () => {
30
+ if (userOnSubmitEditing) {
31
+ userOnSubmitEditing();
32
+ } else if (isLast) {
33
+ form.handleSubmit();
34
+ } else {
35
+ form.focusNextField(name);
36
+ }
37
+ };
38
+
39
+ return (
40
+ <TextInput
41
+ ref={mergedRef}
42
+ value={(field.value as string) ?? ''}
43
+ onChangeText={(text) => field.onChange(text)}
44
+ onBlur={field.onBlur}
45
+ error={field.error}
46
+ disabled={field.disabled || localDisabled}
47
+ returnKeyType={userReturnKeyType ?? (isLast ? 'done' : 'next')}
48
+ onSubmitEditing={handleSubmitEditing}
49
+ {...rest}
50
+ />
51
+ );
52
+ });
53
+
54
+ FormTextInput.displayName = 'Form.TextInput';
55
+ export default FormTextInput;
@@ -0,0 +1,35 @@
1
+ import FormComponent from './Form.native';
2
+ import FormTextInput from './fields/FormTextInput';
3
+ import FormTextArea from './fields/FormTextArea';
4
+ import FormSelect from './fields/FormSelect';
5
+ import FormCheckbox from './fields/FormCheckbox';
6
+ import FormRadioGroup from './fields/FormRadioGroup';
7
+ import FormSwitch from './fields/FormSwitch';
8
+ import FormSlider from './fields/FormSlider';
9
+ import FormField from './fields/FormField';
10
+
11
+ type FormType = typeof FormComponent & {
12
+ TextInput: typeof FormTextInput;
13
+ TextArea: typeof FormTextArea;
14
+ Select: typeof FormSelect;
15
+ Checkbox: typeof FormCheckbox;
16
+ RadioGroup: typeof FormRadioGroup;
17
+ Switch: typeof FormSwitch;
18
+ Slider: typeof FormSlider;
19
+ Field: typeof FormField;
20
+ };
21
+
22
+ const Form = FormComponent as FormType;
23
+ Form.TextInput = FormTextInput;
24
+ Form.TextArea = FormTextArea;
25
+ Form.Select = FormSelect;
26
+ Form.Checkbox = FormCheckbox;
27
+ Form.RadioGroup = FormRadioGroup;
28
+ Form.Switch = FormSwitch;
29
+ Form.Slider = FormSlider;
30
+ Form.Field = FormField;
31
+
32
+ export default Form;
33
+ export { Form };
34
+ export { useForm } from './useForm';
35
+ export * from './types';
@@ -0,0 +1,35 @@
1
+ import FormComponent from './Form.web';
2
+ import FormTextInput from './fields/FormTextInput';
3
+ import FormTextArea from './fields/FormTextArea';
4
+ import FormSelect from './fields/FormSelect';
5
+ import FormCheckbox from './fields/FormCheckbox';
6
+ import FormRadioGroup from './fields/FormRadioGroup';
7
+ import FormSwitch from './fields/FormSwitch';
8
+ import FormSlider from './fields/FormSlider';
9
+ import FormField from './fields/FormField';
10
+
11
+ type FormType = typeof FormComponent & {
12
+ TextInput: typeof FormTextInput;
13
+ TextArea: typeof FormTextArea;
14
+ Select: typeof FormSelect;
15
+ Checkbox: typeof FormCheckbox;
16
+ RadioGroup: typeof FormRadioGroup;
17
+ Switch: typeof FormSwitch;
18
+ Slider: typeof FormSlider;
19
+ Field: typeof FormField;
20
+ };
21
+
22
+ const Form = FormComponent as FormType;
23
+ Form.TextInput = FormTextInput;
24
+ Form.TextArea = FormTextArea;
25
+ Form.Select = FormSelect;
26
+ Form.Checkbox = FormCheckbox;
27
+ Form.RadioGroup = FormRadioGroup;
28
+ Form.Switch = FormSwitch;
29
+ Form.Slider = FormSlider;
30
+ Form.Field = FormField;
31
+
32
+ export default Form;
33
+ export { Form };
34
+ export { useForm } from './useForm';
35
+ export * from './types';
@@ -0,0 +1,35 @@
1
+ import FormComponent from './Form.web';
2
+ import FormTextInput from './fields/FormTextInput';
3
+ import FormTextArea from './fields/FormTextArea';
4
+ import FormSelect from './fields/FormSelect';
5
+ import FormCheckbox from './fields/FormCheckbox';
6
+ import FormRadioGroup from './fields/FormRadioGroup';
7
+ import FormSwitch from './fields/FormSwitch';
8
+ import FormSlider from './fields/FormSlider';
9
+ import FormField from './fields/FormField';
10
+
11
+ type FormType = typeof FormComponent & {
12
+ TextInput: typeof FormTextInput;
13
+ TextArea: typeof FormTextArea;
14
+ Select: typeof FormSelect;
15
+ Checkbox: typeof FormCheckbox;
16
+ RadioGroup: typeof FormRadioGroup;
17
+ Switch: typeof FormSwitch;
18
+ Slider: typeof FormSlider;
19
+ Field: typeof FormField;
20
+ };
21
+
22
+ const Form = FormComponent as FormType;
23
+ Form.TextInput = FormTextInput;
24
+ Form.TextArea = FormTextArea;
25
+ Form.Select = FormSelect;
26
+ Form.Checkbox = FormCheckbox;
27
+ Form.RadioGroup = FormRadioGroup;
28
+ Form.Switch = FormSwitch;
29
+ Form.Slider = FormSlider;
30
+ Form.Field = FormField;
31
+
32
+ export default Form;
33
+ export { Form };
34
+ export { useForm } from './useForm';
35
+ export * from './types';
@@ -0,0 +1,105 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { StyleProp, ViewStyle } from 'react-native';
3
+ import type { TextInputProps } from '../TextInput/types';
4
+ import type { TextAreaProps } from '../TextArea/types';
5
+ import type { SelectProps } from '../Select/types';
6
+ import type { CheckboxProps } from '../Checkbox/types';
7
+ import type { RadioGroupProps } from '../RadioButton/types';
8
+ import type { SwitchProps } from '../Switch/types';
9
+ import type { SliderProps } from '../Slider/types';
10
+
11
+ export type FieldValue = string | number | boolean | undefined;
12
+ export type FormValues = Record<string, FieldValue>;
13
+ export type FormErrors<T extends FormValues = FormValues> = Partial<Record<keyof T, string>>;
14
+
15
+ export type ValidateFunction<T extends FormValues = FormValues> = (
16
+ values: T
17
+ ) => FormErrors<T> | undefined | void;
18
+
19
+ export interface UseFormOptions<T extends FormValues = FormValues> {
20
+ initialValues: T;
21
+ validate?: ValidateFunction<T>;
22
+ validateOn?: 'onBlur' | 'onChange' | 'onSubmit';
23
+ onSubmit: (values: T) => void | Promise<void>;
24
+ disabled?: boolean;
25
+ }
26
+
27
+ export interface UseFormReturn<T extends FormValues = FormValues> {
28
+ values: T;
29
+ errors: FormErrors<T>;
30
+ touched: Partial<Record<keyof T, boolean>>;
31
+ isSubmitting: boolean;
32
+ isDirty: boolean;
33
+ isValid: boolean;
34
+ submitCount: number;
35
+ disabled: boolean;
36
+
37
+ getValue: (name: keyof T) => T[keyof T];
38
+ setValue: (name: keyof T, value: T[keyof T]) => void;
39
+ setTouched: (name: keyof T) => void;
40
+ getError: (name: keyof T) => string | undefined;
41
+ setError: (name: keyof T, error: string | undefined) => void;
42
+
43
+ handleSubmit: () => void | Promise<void>;
44
+ reset: (nextValues?: Partial<T>) => void;
45
+
46
+ registerField: (name: keyof T, ref: React.RefObject<any>, order?: number) => void;
47
+ unregisterField: (name: keyof T) => void;
48
+ focusNextField: (currentName: keyof T) => void;
49
+ isLastTextField: (name: keyof T) => boolean;
50
+ }
51
+
52
+ export interface FormContextValue<T extends FormValues = FormValues> {
53
+ form: UseFormReturn<T>;
54
+ }
55
+
56
+ export interface FieldRenderProps {
57
+ value: FieldValue;
58
+ onChange: (value: FieldValue) => void;
59
+ onBlur: () => void;
60
+ error: string | undefined;
61
+ touched: boolean;
62
+ dirty: boolean;
63
+ disabled: boolean;
64
+ name: string;
65
+ }
66
+
67
+ export interface FormProps {
68
+ form: UseFormReturn<any>;
69
+ children: ReactNode;
70
+ style?: StyleProp<ViewStyle>;
71
+ testID?: string;
72
+ id?: string;
73
+ }
74
+
75
+ // Form field wrapper props - Omit the props that Form wires automatically
76
+ export interface FormFieldBaseProps {
77
+ name: string;
78
+ }
79
+
80
+ export interface FormTextInputProps extends FormFieldBaseProps,
81
+ Omit<TextInputProps, 'value' | 'onChangeText' | 'onBlur' | 'error' | 'hasError'> {
82
+ tabOrder?: number;
83
+ }
84
+
85
+ export interface FormTextAreaProps extends FormFieldBaseProps,
86
+ Omit<TextAreaProps, 'value' | 'onChange' | 'error'> {}
87
+
88
+ export interface FormSelectProps extends FormFieldBaseProps,
89
+ Omit<SelectProps, 'value' | 'onChange' | 'error'> {}
90
+
91
+ export interface FormCheckboxProps extends FormFieldBaseProps,
92
+ Omit<CheckboxProps, 'checked' | 'onChange' | 'error'> {}
93
+
94
+ export interface FormRadioGroupProps extends FormFieldBaseProps,
95
+ Omit<RadioGroupProps, 'value' | 'onValueChange' | 'error'> {}
96
+
97
+ export interface FormSwitchProps extends FormFieldBaseProps,
98
+ Omit<SwitchProps, 'checked' | 'onChange' | 'error'> {}
99
+
100
+ export interface FormSliderProps extends FormFieldBaseProps,
101
+ Omit<SliderProps, 'value' | 'onChange' | 'error'> {}
102
+
103
+ export interface FormFieldProps extends FormFieldBaseProps {
104
+ children: (field: FieldRenderProps) => ReactNode;
105
+ }