@webority-technologies/mobile 0.0.21 → 0.0.23
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/Accordion/Accordion.js +4 -2
- package/lib/commonjs/components/Avatar/Avatar.js +4 -2
- package/lib/commonjs/components/Badge/Badge.js +5 -5
- package/lib/commonjs/components/Banner/Banner.js +8 -4
- package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +6 -4
- package/lib/commonjs/components/BottomSheet/BottomSheet.js +69 -13
- package/lib/commonjs/components/BottomSheet/index.js +6 -0
- package/lib/commonjs/components/Box/Box.js +162 -0
- package/lib/commonjs/components/Box/index.js +37 -0
- package/lib/commonjs/components/Button/Button.js +7 -7
- package/lib/commonjs/components/Carousel/Carousel.js +4 -2
- package/lib/commonjs/components/Checkbox/Checkbox.js +14 -5
- package/lib/commonjs/components/DatePicker/DatePicker.js +9 -7
- package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +5 -2
- package/lib/commonjs/components/Dialog/Dialog.js +2 -2
- package/lib/commonjs/components/FieldBase/FieldBase.js +8 -4
- package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +13 -5
- package/lib/commonjs/components/FormField/FormField.js +61 -25
- package/lib/commonjs/components/Input/Input.js +41 -29
- package/lib/commonjs/components/KeyboardAwareScrollView/KeyboardAwareScrollView.js +102 -0
- package/lib/commonjs/components/KeyboardAwareScrollView/index.js +13 -0
- package/lib/commonjs/components/KeyboardToolbar/KeyboardToolbar.js +130 -0
- package/lib/commonjs/components/KeyboardToolbar/index.js +13 -0
- package/lib/commonjs/components/Modal/Modal.js +17 -6
- package/lib/commonjs/components/NumberInput/NumberInput.js +35 -28
- package/lib/commonjs/components/OTPInput/OTPInput.js +33 -18
- package/lib/commonjs/components/Radio/Radio.js +7 -5
- package/lib/commonjs/components/Radio/RadioGroup.js +10 -3
- package/lib/commonjs/components/SearchBar/SearchBar.js +4 -2
- package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +20 -10
- package/lib/commonjs/components/Select/Select.js +33 -32
- package/lib/commonjs/components/Skeleton/SkeletonContent.js +5 -2
- package/lib/commonjs/components/Slider/Slider.js +42 -26
- package/lib/commonjs/components/Spinner/Spinner.js +5 -5
- package/lib/commonjs/components/Switch/Switch.js +29 -16
- package/lib/commonjs/components/Tabs/Tabs.js +4 -2
- package/lib/commonjs/components/Text/Text.js +142 -0
- package/lib/commonjs/components/Text/index.js +13 -0
- package/lib/commonjs/components/TimePicker/TimePicker.js +10 -7
- package/lib/commonjs/components/Toast/Toast.js +22 -10
- package/lib/commonjs/components/Tooltip/Tooltip.js +6 -2
- package/lib/commonjs/components/index.js +141 -89
- package/lib/commonjs/form/FormContext.js +40 -0
- package/lib/commonjs/form/index.js +68 -0
- package/lib/commonjs/form/path.js +79 -0
- package/lib/commonjs/form/rules.js +67 -0
- package/lib/commonjs/form/types.js +2 -0
- package/lib/commonjs/form/useField.js +54 -0
- package/lib/commonjs/form/useForm.js +316 -0
- package/lib/commonjs/hooks/index.js +14 -0
- package/lib/commonjs/hooks/useControllableState.js +30 -0
- package/lib/commonjs/hooks/useReducedMotion.js +31 -0
- package/lib/commonjs/index.js +96 -11
- package/lib/commonjs/theme/ThemeContext.js +30 -2
- package/lib/commonjs/theme/tokens.js +12 -0
- package/lib/module/components/Accordion/Accordion.js +4 -2
- package/lib/module/components/Avatar/Avatar.js +4 -2
- package/lib/module/components/Badge/Badge.js +5 -5
- package/lib/module/components/Banner/Banner.js +8 -4
- package/lib/module/components/BottomNavigation/BottomNavigation.js +6 -4
- package/lib/module/components/BottomSheet/BottomSheet.js +68 -13
- package/lib/module/components/BottomSheet/index.js +1 -1
- package/lib/module/components/Box/Box.js +156 -0
- package/lib/module/components/Box/index.js +4 -0
- package/lib/module/components/Button/Button.js +7 -7
- package/lib/module/components/Carousel/Carousel.js +4 -2
- package/lib/module/components/Checkbox/Checkbox.js +14 -5
- package/lib/module/components/DatePicker/DatePicker.js +9 -7
- package/lib/module/components/DateRangePicker/DateRangePicker.js +5 -2
- package/lib/module/components/Dialog/Dialog.js +2 -2
- package/lib/module/components/FieldBase/FieldBase.js +8 -4
- package/lib/module/components/FloatingActionButton/FloatingActionButton.js +13 -5
- package/lib/module/components/FormField/FormField.js +62 -26
- package/lib/module/components/Input/Input.js +41 -29
- package/lib/module/components/KeyboardAwareScrollView/KeyboardAwareScrollView.js +98 -0
- package/lib/module/components/KeyboardAwareScrollView/index.js +4 -0
- package/lib/module/components/KeyboardToolbar/KeyboardToolbar.js +125 -0
- package/lib/module/components/KeyboardToolbar/index.js +4 -0
- package/lib/module/components/Modal/Modal.js +17 -6
- package/lib/module/components/NumberInput/NumberInput.js +30 -23
- package/lib/module/components/OTPInput/OTPInput.js +30 -15
- package/lib/module/components/Radio/Radio.js +7 -5
- package/lib/module/components/Radio/RadioGroup.js +10 -3
- package/lib/module/components/SearchBar/SearchBar.js +4 -2
- package/lib/module/components/SegmentedControl/SegmentedControl.js +20 -10
- package/lib/module/components/Select/Select.js +33 -32
- package/lib/module/components/Skeleton/SkeletonContent.js +5 -2
- package/lib/module/components/Slider/Slider.js +42 -26
- package/lib/module/components/Spinner/Spinner.js +5 -5
- package/lib/module/components/Switch/Switch.js +29 -16
- package/lib/module/components/Tabs/Tabs.js +4 -2
- package/lib/module/components/Text/Text.js +138 -0
- package/lib/module/components/Text/index.js +4 -0
- package/lib/module/components/TimePicker/TimePicker.js +10 -7
- package/lib/module/components/Toast/Toast.js +22 -10
- package/lib/module/components/Tooltip/Tooltip.js +6 -2
- package/lib/module/components/index.js +5 -1
- package/lib/module/form/FormContext.js +32 -0
- package/lib/module/form/index.js +12 -0
- package/lib/module/form/path.js +72 -0
- package/lib/module/form/rules.js +52 -0
- package/lib/module/form/types.js +2 -0
- package/lib/module/form/useField.js +49 -0
- package/lib/module/form/useForm.js +312 -0
- package/lib/module/hooks/index.js +2 -0
- package/lib/module/hooks/useControllableState.js +26 -0
- package/lib/module/hooks/useReducedMotion.js +27 -0
- package/lib/module/index.js +3 -1
- package/lib/module/theme/ThemeContext.js +30 -2
- package/lib/module/theme/tokens.js +12 -0
- package/lib/typescript/commonjs/components/BottomNavigation/BottomNavigation.d.ts +1 -1
- package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +41 -0
- package/lib/typescript/commonjs/components/BottomSheet/index.d.ts +2 -2
- package/lib/typescript/commonjs/components/Box/Box.d.ts +60 -0
- package/lib/typescript/commonjs/components/Box/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/Button/Button.d.ts +1 -1
- package/lib/typescript/commonjs/components/Checkbox/Checkbox.d.ts +3 -2
- package/lib/typescript/commonjs/components/DatePicker/DatePicker.d.ts +3 -3
- package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +2 -2
- package/lib/typescript/commonjs/components/FormField/FormField.d.ts +13 -2
- package/lib/typescript/commonjs/components/KeyboardAwareScrollView/KeyboardAwareScrollView.d.ts +20 -0
- package/lib/typescript/commonjs/components/KeyboardAwareScrollView/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/KeyboardToolbar/KeyboardToolbar.d.ts +29 -0
- package/lib/typescript/commonjs/components/KeyboardToolbar/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/NumberInput/NumberInput.d.ts +3 -2
- package/lib/typescript/commonjs/components/OTPInput/OTPInput.d.ts +3 -2
- package/lib/typescript/commonjs/components/Radio/Radio.d.ts +2 -2
- package/lib/typescript/commonjs/components/Radio/RadioGroup.d.ts +3 -2
- package/lib/typescript/commonjs/components/SegmentedControl/SegmentedControl.d.ts +3 -2
- package/lib/typescript/commonjs/components/Slider/Slider.d.ts +6 -4
- package/lib/typescript/commonjs/components/Spinner/Spinner.d.ts +1 -1
- package/lib/typescript/commonjs/components/Switch/Switch.d.ts +3 -2
- package/lib/typescript/commonjs/components/Text/Text.d.ts +25 -0
- package/lib/typescript/commonjs/components/Text/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/TimePicker/TimePicker.d.ts +3 -3
- package/lib/typescript/commonjs/components/index.d.ts +10 -2
- package/lib/typescript/commonjs/form/FormContext.d.ts +17 -0
- package/lib/typescript/commonjs/form/index.d.ts +9 -0
- package/lib/typescript/commonjs/form/path.d.ts +10 -0
- package/lib/typescript/commonjs/form/rules.d.ts +31 -0
- package/lib/typescript/commonjs/form/types.d.ts +94 -0
- package/lib/typescript/commonjs/form/useField.d.ts +27 -0
- package/lib/typescript/commonjs/form/useForm.d.ts +10 -0
- package/lib/typescript/commonjs/hooks/index.d.ts +3 -0
- package/lib/typescript/commonjs/hooks/useControllableState.d.ts +17 -0
- package/lib/typescript/commonjs/hooks/useReducedMotion.d.ts +8 -0
- package/lib/typescript/commonjs/index.d.ts +4 -2
- package/lib/typescript/commonjs/theme/types.d.ts +15 -0
- package/lib/typescript/module/components/BottomNavigation/BottomNavigation.d.ts +1 -1
- package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +41 -0
- package/lib/typescript/module/components/BottomSheet/index.d.ts +2 -2
- package/lib/typescript/module/components/Box/Box.d.ts +60 -0
- package/lib/typescript/module/components/Box/index.d.ts +3 -0
- package/lib/typescript/module/components/Button/Button.d.ts +1 -1
- package/lib/typescript/module/components/Checkbox/Checkbox.d.ts +3 -2
- package/lib/typescript/module/components/DatePicker/DatePicker.d.ts +3 -3
- package/lib/typescript/module/components/Dialog/Dialog.d.ts +2 -2
- package/lib/typescript/module/components/FormField/FormField.d.ts +13 -2
- package/lib/typescript/module/components/KeyboardAwareScrollView/KeyboardAwareScrollView.d.ts +20 -0
- package/lib/typescript/module/components/KeyboardAwareScrollView/index.d.ts +3 -0
- package/lib/typescript/module/components/KeyboardToolbar/KeyboardToolbar.d.ts +29 -0
- package/lib/typescript/module/components/KeyboardToolbar/index.d.ts +3 -0
- package/lib/typescript/module/components/NumberInput/NumberInput.d.ts +3 -2
- package/lib/typescript/module/components/OTPInput/OTPInput.d.ts +3 -2
- package/lib/typescript/module/components/Radio/Radio.d.ts +2 -2
- package/lib/typescript/module/components/Radio/RadioGroup.d.ts +3 -2
- package/lib/typescript/module/components/SegmentedControl/SegmentedControl.d.ts +3 -2
- package/lib/typescript/module/components/Slider/Slider.d.ts +6 -4
- package/lib/typescript/module/components/Spinner/Spinner.d.ts +1 -1
- package/lib/typescript/module/components/Switch/Switch.d.ts +3 -2
- package/lib/typescript/module/components/Text/Text.d.ts +25 -0
- package/lib/typescript/module/components/Text/index.d.ts +3 -0
- package/lib/typescript/module/components/TimePicker/TimePicker.d.ts +3 -3
- package/lib/typescript/module/components/index.d.ts +10 -2
- package/lib/typescript/module/form/FormContext.d.ts +17 -0
- package/lib/typescript/module/form/index.d.ts +9 -0
- package/lib/typescript/module/form/path.d.ts +10 -0
- package/lib/typescript/module/form/rules.d.ts +31 -0
- package/lib/typescript/module/form/types.d.ts +94 -0
- package/lib/typescript/module/form/useField.d.ts +27 -0
- package/lib/typescript/module/form/useForm.d.ts +10 -0
- package/lib/typescript/module/hooks/index.d.ts +3 -0
- package/lib/typescript/module/hooks/useControllableState.d.ts +17 -0
- package/lib/typescript/module/hooks/useReducedMotion.d.ts +8 -0
- package/lib/typescript/module/index.d.ts +4 -2
- package/lib/typescript/module/theme/types.d.ts +15 -0
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { Animated, Easing, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
5
|
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
|
+
import { useControllableState } from "../../hooks/index.js";
|
|
6
7
|
import { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
7
8
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
9
|
const sizeMap = {
|
|
@@ -41,7 +42,8 @@ const toneColor = (theme, tone) => {
|
|
|
41
42
|
const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
42
43
|
const {
|
|
43
44
|
value,
|
|
44
|
-
|
|
45
|
+
defaultValue,
|
|
46
|
+
onChange,
|
|
45
47
|
disabled = false,
|
|
46
48
|
size = 'md',
|
|
47
49
|
tone = 'primary',
|
|
@@ -56,6 +58,11 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
56
58
|
testID,
|
|
57
59
|
...rest
|
|
58
60
|
} = props;
|
|
61
|
+
const [current, setCurrent] = useControllableState({
|
|
62
|
+
value,
|
|
63
|
+
defaultValue: defaultValue ?? false,
|
|
64
|
+
onChange
|
|
65
|
+
});
|
|
59
66
|
const theme = useTheme();
|
|
60
67
|
const sizeStyles = {
|
|
61
68
|
...sizeMap[size],
|
|
@@ -65,25 +72,29 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
65
72
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
66
73
|
const offTrackColor = theme.mode === 'dark' ? theme.colors.secondary : theme.colors.surface.disabled;
|
|
67
74
|
const onTrackColor = toneColor(theme, tone);
|
|
68
|
-
const progress = useRef(createAnimatedValue(
|
|
75
|
+
const progress = useRef(createAnimatedValue(current ? 1 : 0)).current;
|
|
69
76
|
useEffect(() => {
|
|
70
|
-
Animated.spring(progress, {
|
|
71
|
-
toValue:
|
|
77
|
+
const anim = Animated.spring(progress, {
|
|
78
|
+
toValue: current ? 1 : 0,
|
|
72
79
|
damping: theme.motion.spring.snappy.damping,
|
|
73
80
|
stiffness: theme.motion.spring.snappy.stiffness,
|
|
74
81
|
mass: theme.motion.spring.snappy.mass,
|
|
75
82
|
useNativeDriver: true
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
});
|
|
84
|
+
anim.start();
|
|
85
|
+
return () => anim.stop();
|
|
86
|
+
}, [current, progress, theme.motion.spring.snappy]);
|
|
87
|
+
const trackBgAnim = useRef(createAnimatedValue(current ? 1 : 0)).current;
|
|
79
88
|
useEffect(() => {
|
|
80
|
-
Animated.timing(trackBgAnim, {
|
|
81
|
-
toValue:
|
|
89
|
+
const anim = Animated.timing(trackBgAnim, {
|
|
90
|
+
toValue: current ? 1 : 0,
|
|
82
91
|
duration: theme.motion.duration.fast,
|
|
83
92
|
easing: Easing.out(Easing.ease),
|
|
84
93
|
useNativeDriver: false
|
|
85
|
-
})
|
|
86
|
-
|
|
94
|
+
});
|
|
95
|
+
anim.start();
|
|
96
|
+
return () => anim.stop();
|
|
97
|
+
}, [current, trackBgAnim, theme.motion.duration.fast]);
|
|
87
98
|
const offX = sizeStyles.padding;
|
|
88
99
|
const onX = sizeStyles.trackWidth - sizeStyles.thumbSize - sizeStyles.padding;
|
|
89
100
|
const translateX = progress.interpolate({
|
|
@@ -102,7 +113,7 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
102
113
|
isFirstRender.current = false;
|
|
103
114
|
return;
|
|
104
115
|
}
|
|
105
|
-
Animated.sequence([Animated.spring(bounceScale, {
|
|
116
|
+
const anim = Animated.sequence([Animated.spring(bounceScale, {
|
|
106
117
|
toValue: 1.15,
|
|
107
118
|
damping: 10,
|
|
108
119
|
stiffness: 220,
|
|
@@ -114,12 +125,14 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
114
125
|
stiffness: 240,
|
|
115
126
|
mass: 1,
|
|
116
127
|
useNativeDriver: true
|
|
117
|
-
})])
|
|
118
|
-
|
|
128
|
+
})]);
|
|
129
|
+
anim.start();
|
|
130
|
+
return () => anim.stop();
|
|
131
|
+
}, [current, bounce, bounceScale]);
|
|
119
132
|
const handlePress = event => {
|
|
120
133
|
if (disabled) return;
|
|
121
134
|
if (haptic !== false) triggerHaptic(haptic);
|
|
122
|
-
|
|
135
|
+
setCurrent(!current);
|
|
123
136
|
rest.onPressOut?.(event);
|
|
124
137
|
};
|
|
125
138
|
const accessibleLabel = accessibilityLabel ?? label;
|
|
@@ -130,7 +143,7 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
130
143
|
accessibilityRole: "switch",
|
|
131
144
|
accessibilityLabel: accessibleLabel,
|
|
132
145
|
accessibilityState: {
|
|
133
|
-
checked:
|
|
146
|
+
checked: current,
|
|
134
147
|
disabled
|
|
135
148
|
},
|
|
136
149
|
testID: testID,
|
|
@@ -82,7 +82,7 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
82
82
|
if (!activeLayout) return;
|
|
83
83
|
if (useProgress) return;
|
|
84
84
|
const spring = theme.motion.spring.snappy;
|
|
85
|
-
Animated.parallel([
|
|
85
|
+
const anim = Animated.parallel([
|
|
86
86
|
// Both must use the JS driver: width can't run on native, and mixing
|
|
87
87
|
// drivers on the same view (transform native + width JS) trips RN's
|
|
88
88
|
// "node already moved to native" guard under the new architecture.
|
|
@@ -98,7 +98,9 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
98
98
|
stiffness: spring.stiffness,
|
|
99
99
|
mass: spring.mass,
|
|
100
100
|
useNativeDriver: false
|
|
101
|
-
})])
|
|
101
|
+
})]);
|
|
102
|
+
anim.start();
|
|
103
|
+
return () => anim.stop();
|
|
102
104
|
}, [activeLayout, activeKey, indicatorTranslateX, indicatorWidth, theme.motion.spring.snappy, useProgress]);
|
|
103
105
|
const handleLayout = useCallback(key => e => {
|
|
104
106
|
const {
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { forwardRef, useMemo } from 'react';
|
|
4
|
+
import { Text as RNText } from 'react-native';
|
|
5
|
+
import { fontFor, useTheme } from "../../theme/index.js";
|
|
6
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
const VARIANTS = {
|
|
8
|
+
display: {
|
|
9
|
+
size: '4xl',
|
|
10
|
+
weight: 'bold',
|
|
11
|
+
line: 'tight',
|
|
12
|
+
color: 'primary',
|
|
13
|
+
heading: true
|
|
14
|
+
},
|
|
15
|
+
h1: {
|
|
16
|
+
size: '3xl',
|
|
17
|
+
weight: 'bold',
|
|
18
|
+
line: 'tight',
|
|
19
|
+
color: 'primary',
|
|
20
|
+
heading: true
|
|
21
|
+
},
|
|
22
|
+
h2: {
|
|
23
|
+
size: '2xl',
|
|
24
|
+
weight: 'semibold',
|
|
25
|
+
line: 'tight',
|
|
26
|
+
color: 'primary',
|
|
27
|
+
heading: true
|
|
28
|
+
},
|
|
29
|
+
h3: {
|
|
30
|
+
size: 'xl',
|
|
31
|
+
weight: 'semibold',
|
|
32
|
+
line: 'tight',
|
|
33
|
+
color: 'primary',
|
|
34
|
+
heading: true
|
|
35
|
+
},
|
|
36
|
+
title: {
|
|
37
|
+
size: 'lg',
|
|
38
|
+
weight: 'semibold',
|
|
39
|
+
line: 'normal',
|
|
40
|
+
color: 'primary'
|
|
41
|
+
},
|
|
42
|
+
body: {
|
|
43
|
+
size: 'base',
|
|
44
|
+
weight: 'normal',
|
|
45
|
+
line: 'normal',
|
|
46
|
+
color: 'primary'
|
|
47
|
+
},
|
|
48
|
+
bodySmall: {
|
|
49
|
+
size: 'sm',
|
|
50
|
+
weight: 'normal',
|
|
51
|
+
line: 'normal',
|
|
52
|
+
color: 'secondary'
|
|
53
|
+
},
|
|
54
|
+
caption: {
|
|
55
|
+
size: 'xs',
|
|
56
|
+
weight: 'normal',
|
|
57
|
+
line: 'normal',
|
|
58
|
+
color: 'tertiary'
|
|
59
|
+
},
|
|
60
|
+
label: {
|
|
61
|
+
size: 'sm',
|
|
62
|
+
weight: 'medium',
|
|
63
|
+
line: 'normal',
|
|
64
|
+
color: 'secondary'
|
|
65
|
+
},
|
|
66
|
+
overline: {
|
|
67
|
+
size: 'xs',
|
|
68
|
+
weight: 'semibold',
|
|
69
|
+
line: 'normal',
|
|
70
|
+
color: 'secondary',
|
|
71
|
+
uppercase: true,
|
|
72
|
+
letterSpacing: 'wide'
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const TEXT_ROLES = {
|
|
76
|
+
primary: true,
|
|
77
|
+
secondary: true,
|
|
78
|
+
tertiary: true,
|
|
79
|
+
inverse: true,
|
|
80
|
+
disabled: true,
|
|
81
|
+
link: true
|
|
82
|
+
};
|
|
83
|
+
const SEMANTIC = {
|
|
84
|
+
success: true,
|
|
85
|
+
warning: true,
|
|
86
|
+
error: true,
|
|
87
|
+
info: true
|
|
88
|
+
};
|
|
89
|
+
const resolveColor = (theme, color) => {
|
|
90
|
+
// Text roles win over the same-named brand colour ('primary' -> text.primary),
|
|
91
|
+
// which is the intent the vast majority of the time for text.
|
|
92
|
+
if (TEXT_ROLES[color]) return theme.colors.text[color];
|
|
93
|
+
if (SEMANTIC[color]) return theme.colors[color];
|
|
94
|
+
return color; // raw colour string
|
|
95
|
+
};
|
|
96
|
+
const Text = /*#__PURE__*/forwardRef((props, ref) => {
|
|
97
|
+
const {
|
|
98
|
+
variant = 'body',
|
|
99
|
+
color,
|
|
100
|
+
weight,
|
|
101
|
+
size,
|
|
102
|
+
align,
|
|
103
|
+
italic,
|
|
104
|
+
underline,
|
|
105
|
+
style,
|
|
106
|
+
children,
|
|
107
|
+
...rest
|
|
108
|
+
} = props;
|
|
109
|
+
const theme = useTheme();
|
|
110
|
+
const textStyle = useMemo(() => {
|
|
111
|
+
const spec = VARIANTS[variant];
|
|
112
|
+
const fontSize = typeof size === 'number' ? size : theme.typography.fontSize[size ?? spec.size];
|
|
113
|
+
const lineHeight = Math.round(fontSize * theme.typography.lineHeight[spec.line]);
|
|
114
|
+
return {
|
|
115
|
+
fontSize,
|
|
116
|
+
lineHeight,
|
|
117
|
+
color: resolveColor(theme, color ?? spec.color),
|
|
118
|
+
textAlign: align,
|
|
119
|
+
textTransform: spec.uppercase ? 'uppercase' : undefined,
|
|
120
|
+
letterSpacing: spec.letterSpacing ? theme.typography.letterSpacing[spec.letterSpacing] : undefined,
|
|
121
|
+
fontStyle: italic ? 'italic' : undefined,
|
|
122
|
+
textDecorationLine: underline ? 'underline' : undefined,
|
|
123
|
+
...fontFor(theme, weight ?? spec.weight)
|
|
124
|
+
};
|
|
125
|
+
}, [theme, variant, color, weight, size, align, italic, underline]);
|
|
126
|
+
const heading = VARIANTS[variant].heading;
|
|
127
|
+
return /*#__PURE__*/_jsx(RNText, {
|
|
128
|
+
ref: ref,
|
|
129
|
+
style: [textStyle, style],
|
|
130
|
+
accessibilityRole: heading ? 'header' : rest.accessibilityRole,
|
|
131
|
+
...rest,
|
|
132
|
+
children: children
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
Text.displayName = 'Text';
|
|
136
|
+
export { Text };
|
|
137
|
+
export default Text;
|
|
138
|
+
//# sourceMappingURL=Text.js.map
|
|
@@ -11,12 +11,12 @@ import { PickerTrigger } from "../PickerTrigger/PickerTrigger.js";
|
|
|
11
11
|
/**
|
|
12
12
|
* TimePicker supports two modes:
|
|
13
13
|
*
|
|
14
|
-
* 1. Controlled-modal mode — pass `visible`, `
|
|
14
|
+
* 1. Controlled-modal mode — pass `visible`, `onChange`, `onClose`. The
|
|
15
15
|
* component renders only the modal sheet and the caller owns open/close
|
|
16
16
|
* state plus its own trigger UI.
|
|
17
17
|
* 2. Trigger mode — omit `visible`. The component renders a PickerTrigger
|
|
18
18
|
* field (label / value / placeholder / chevron / clear / helper / error)
|
|
19
|
-
* and manages its own modal open state. `
|
|
19
|
+
* and manages its own modal open state. `onChange` is still called on
|
|
20
20
|
* confirm.
|
|
21
21
|
*/
|
|
22
22
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
@@ -217,7 +217,7 @@ const TimePicker = props => {
|
|
|
217
217
|
const {
|
|
218
218
|
visible,
|
|
219
219
|
value,
|
|
220
|
-
|
|
220
|
+
onChange,
|
|
221
221
|
onClose,
|
|
222
222
|
format = '12h',
|
|
223
223
|
minuteStep = 1,
|
|
@@ -304,8 +304,9 @@ const TimePicker = props => {
|
|
|
304
304
|
const opacity = useRef(createAnimatedValue(0)).current;
|
|
305
305
|
const translateY = useRef(createAnimatedValue(40)).current;
|
|
306
306
|
useEffect(() => {
|
|
307
|
+
let anim;
|
|
307
308
|
if (open) {
|
|
308
|
-
Animated.parallel([
|
|
309
|
+
anim = Animated.parallel([
|
|
309
310
|
// Backdrop opacity uses JS driver — see Modal.tsx for the Fabric reason.
|
|
310
311
|
Animated.timing(opacity, {
|
|
311
312
|
toValue: 1,
|
|
@@ -318,11 +319,13 @@ const TimePicker = props => {
|
|
|
318
319
|
stiffness: theme.motion.spring.snappy.stiffness,
|
|
319
320
|
mass: theme.motion.spring.snappy.mass,
|
|
320
321
|
useNativeDriver: true
|
|
321
|
-
})])
|
|
322
|
+
})]);
|
|
323
|
+
anim.start();
|
|
322
324
|
} else {
|
|
323
325
|
opacity.setValue(0);
|
|
324
326
|
setNativeValue(translateY, 40);
|
|
325
327
|
}
|
|
328
|
+
return () => anim?.stop();
|
|
326
329
|
}, [open, opacity, translateY, theme.motion]);
|
|
327
330
|
const announce = useCallback(msg => {
|
|
328
331
|
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
@@ -351,12 +354,12 @@ const TimePicker = props => {
|
|
|
351
354
|
const hour24 = to24h(displayHour, period, format);
|
|
352
355
|
const minute = minutes[minuteIndex] ?? 0;
|
|
353
356
|
if (theme.components.timePicker?.haptic) triggerHaptic('notificationSuccess');
|
|
354
|
-
|
|
357
|
+
onChange?.({
|
|
355
358
|
hour: hour24,
|
|
356
359
|
minute
|
|
357
360
|
});
|
|
358
361
|
handleCloseModal();
|
|
359
|
-
}, [hours, hourIndex, periods, periodIndex, minutes, minuteIndex, format,
|
|
362
|
+
}, [hours, hourIndex, periods, periodIndex, minutes, minuteIndex, format, onChange, handleCloseModal, theme.components.timePicker]);
|
|
360
363
|
const summary = useMemo(() => {
|
|
361
364
|
const displayHour = hours[hourIndex] ?? 0;
|
|
362
365
|
const minute = minutes[minuteIndex] ?? 0;
|
|
@@ -39,6 +39,18 @@ const Toast = ({
|
|
|
39
39
|
const translateX = useRef(createAnimatedValue(0)).current;
|
|
40
40
|
const opacity = useRef(createAnimatedValue(0)).current;
|
|
41
41
|
const dismissedRef = useRef(false);
|
|
42
|
+
const stackTranslate = position === 'top' ? index * stackOffset : -index * stackOffset;
|
|
43
|
+
const stackScale = Math.max(1 - index * stackScaleStep, stackMinScale);
|
|
44
|
+
|
|
45
|
+
// The stack offset rides on its own value so the enter spring (translateY)
|
|
46
|
+
// and the layout offset compose once instead of rebuilding a fresh
|
|
47
|
+
// `new Animated.Value` + `Animated.add` node on every render. setNativeValue
|
|
48
|
+
// keeps it in sync after the node has moved to the native driver.
|
|
49
|
+
const stackTranslateY = useRef(createAnimatedValue(stackTranslate)).current;
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
setNativeValue(stackTranslateY, stackTranslate);
|
|
52
|
+
}, [stackTranslate, stackTranslateY]);
|
|
53
|
+
const composedTranslateY = useMemo(() => Animated.add(translateY, stackTranslateY), [translateY, stackTranslateY]);
|
|
42
54
|
const dismiss = (animateOut = true) => {
|
|
43
55
|
if (dismissedRef.current) return;
|
|
44
56
|
dismissedRef.current = true;
|
|
@@ -57,7 +69,7 @@ const Toast = ({
|
|
|
57
69
|
}
|
|
58
70
|
};
|
|
59
71
|
useEffect(() => {
|
|
60
|
-
Animated.parallel([Animated.spring(translateY, {
|
|
72
|
+
const enter = Animated.parallel([Animated.spring(translateY, {
|
|
61
73
|
toValue: 0,
|
|
62
74
|
damping: enterSpringDamping,
|
|
63
75
|
stiffness: enterSpringStiffness,
|
|
@@ -67,13 +79,17 @@ const Toast = ({
|
|
|
67
79
|
toValue: 1,
|
|
68
80
|
duration: theme.motion.duration.fast,
|
|
69
81
|
useNativeDriver: true
|
|
70
|
-
})])
|
|
82
|
+
})]);
|
|
83
|
+
enter.start();
|
|
71
84
|
const duration = toast.duration ?? defaultDurationMs;
|
|
72
85
|
if (duration > 0) {
|
|
73
86
|
const timer = setTimeout(() => dismiss(true), duration);
|
|
74
|
-
return () =>
|
|
87
|
+
return () => {
|
|
88
|
+
enter.stop();
|
|
89
|
+
clearTimeout(timer);
|
|
90
|
+
};
|
|
75
91
|
}
|
|
76
|
-
return
|
|
92
|
+
return () => enter.stop();
|
|
77
93
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
78
94
|
}, []);
|
|
79
95
|
const panResponder = useMemo(() => PanResponder.create({
|
|
@@ -108,11 +124,7 @@ const Toast = ({
|
|
|
108
124
|
})]).start();
|
|
109
125
|
}
|
|
110
126
|
}
|
|
111
|
-
}),
|
|
112
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
113
|
-
[]);
|
|
114
|
-
const stackTranslate = position === 'top' ? index * stackOffset : -index * stackOffset;
|
|
115
|
-
const stackScale = Math.max(1 - index * stackScaleStep, stackMinScale);
|
|
127
|
+
}), [translateX, opacity, swipeDismissThreshold, swipeVelocityThreshold, theme.motion.duration.fast, onDismiss, toast.id]);
|
|
116
128
|
const handleActionPress = () => {
|
|
117
129
|
toast.action?.onPress();
|
|
118
130
|
dismiss(true);
|
|
@@ -152,7 +164,7 @@ const Toast = ({
|
|
|
152
164
|
shadowColor: theme.shadows.md.shadowColor,
|
|
153
165
|
opacity,
|
|
154
166
|
transform: [{
|
|
155
|
-
translateY:
|
|
167
|
+
translateY: composedTranslateY
|
|
156
168
|
}, {
|
|
157
169
|
translateX
|
|
158
170
|
}, {
|
|
@@ -102,6 +102,7 @@ const Tooltip = props => {
|
|
|
102
102
|
}
|
|
103
103
|
};
|
|
104
104
|
}
|
|
105
|
+
let anim;
|
|
105
106
|
if (visible) {
|
|
106
107
|
measureAnchor();
|
|
107
108
|
const enterAnims = [Animated.timing(opacity, {
|
|
@@ -118,7 +119,8 @@ const Tooltip = props => {
|
|
|
118
119
|
useNativeDriver: true
|
|
119
120
|
}));
|
|
120
121
|
}
|
|
121
|
-
Animated.parallel(enterAnims)
|
|
122
|
+
anim = Animated.parallel(enterAnims);
|
|
123
|
+
anim.start();
|
|
122
124
|
if (trigger === 'press') {
|
|
123
125
|
if (autoHideTimer.current) clearTimeout(autoHideTimer.current);
|
|
124
126
|
autoHideTimer.current = setTimeout(() => {
|
|
@@ -138,13 +140,15 @@ const Tooltip = props => {
|
|
|
138
140
|
useNativeDriver: true
|
|
139
141
|
}));
|
|
140
142
|
}
|
|
141
|
-
Animated.parallel(exitAnims)
|
|
143
|
+
anim = Animated.parallel(exitAnims);
|
|
144
|
+
anim.start();
|
|
142
145
|
if (autoHideTimer.current) {
|
|
143
146
|
clearTimeout(autoHideTimer.current);
|
|
144
147
|
autoHideTimer.current = null;
|
|
145
148
|
}
|
|
146
149
|
}
|
|
147
150
|
return () => {
|
|
151
|
+
anim?.stop();
|
|
148
152
|
if (autoHideTimer.current) {
|
|
149
153
|
clearTimeout(autoHideTimer.current);
|
|
150
154
|
autoHideTimer.current = null;
|
|
@@ -5,8 +5,12 @@ export { Avatar, AvatarGroup } from "./Avatar/index.js";
|
|
|
5
5
|
export { Badge } from "./Badge/index.js";
|
|
6
6
|
export { Banner } from "./Banner/index.js";
|
|
7
7
|
export { BottomNavigation } from "./BottomNavigation/index.js";
|
|
8
|
-
export { BottomSheet } from "./BottomSheet/index.js";
|
|
8
|
+
export { BottomSheet, useBottomSheet } from "./BottomSheet/index.js";
|
|
9
9
|
export { Button } from "./Button/index.js";
|
|
10
|
+
export { Box, Stack, Row, Spacer } from "./Box/index.js";
|
|
11
|
+
export { Text } from "./Text/index.js";
|
|
12
|
+
export { KeyboardAwareScrollView } from "./KeyboardAwareScrollView/index.js";
|
|
13
|
+
export { KeyboardToolbar } from "./KeyboardToolbar/index.js";
|
|
10
14
|
export { Card } from "./Card/index.js";
|
|
11
15
|
export { Carousel } from "./Carousel/index.js";
|
|
12
16
|
export { Checkbox } from "./Checkbox/index.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { createContext, useContext } from 'react';
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
const FormContext = /*#__PURE__*/createContext(null);
|
|
6
|
+
/**
|
|
7
|
+
* Provides a {@link useForm} instance to descendants so `<FormField name>`,
|
|
8
|
+
* {@link useField} and {@link useFieldArray} can bind by name.
|
|
9
|
+
*/
|
|
10
|
+
export const Form = ({
|
|
11
|
+
form,
|
|
12
|
+
children
|
|
13
|
+
}) => /*#__PURE__*/_jsx(FormContext.Provider, {
|
|
14
|
+
value: form,
|
|
15
|
+
children: children
|
|
16
|
+
});
|
|
17
|
+
Form.displayName = 'Form';
|
|
18
|
+
|
|
19
|
+
/** Read the surrounding form. Throws if there is no `<Form>` ancestor. */
|
|
20
|
+
export function useFormContext() {
|
|
21
|
+
const ctx = useContext(FormContext);
|
|
22
|
+
if (!ctx) {
|
|
23
|
+
throw new Error('useFormContext / useField / <FormField name> must be rendered inside a <Form> from @webority-technologies/mobile.');
|
|
24
|
+
}
|
|
25
|
+
return ctx;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Read the surrounding form, or null when there is no `<Form>` ancestor. */
|
|
29
|
+
export function useOptionalFormContext() {
|
|
30
|
+
return useContext(FormContext);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=FormContext.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
export { useForm } from "./useForm.js";
|
|
4
|
+
export { useField, useFieldArray } from "./useField.js";
|
|
5
|
+
export { Form, useFormContext, useOptionalFormContext } from "./FormContext.js";
|
|
6
|
+
export { getPath, setPath, deletePath } from "./path.js";
|
|
7
|
+
|
|
8
|
+
// Validation rule presets (the dependency-free Yup replacement):
|
|
9
|
+
// import { rules } from '@webority-technologies/mobile';
|
|
10
|
+
// validate: { email: [rules.required(), rules.email()] }
|
|
11
|
+
export * as rules from "./rules.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Immutable get/set/delete for dot- and bracket-notation field paths
|
|
5
|
+
* ("address.city", "phones[0]", "items[2].qty"). Lets a single flat `name`
|
|
6
|
+
* string address nested values and array items, so the form engine can treat
|
|
7
|
+
* every field uniformly regardless of how deep it lives in the value tree.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const tokenize = path => {
|
|
11
|
+
const tokens = [];
|
|
12
|
+
const re = /[^.[\]]+/g;
|
|
13
|
+
let m;
|
|
14
|
+
while ((m = re.exec(path)) !== null) {
|
|
15
|
+
const raw = m[0];
|
|
16
|
+
tokens.push(/^\d+$/.test(raw) ? Number(raw) : raw);
|
|
17
|
+
}
|
|
18
|
+
return tokens;
|
|
19
|
+
};
|
|
20
|
+
export const getPath = (obj, path) => {
|
|
21
|
+
const tokens = tokenize(path);
|
|
22
|
+
let cur = obj;
|
|
23
|
+
for (const t of tokens) {
|
|
24
|
+
if (cur == null || typeof cur !== 'object') return undefined;
|
|
25
|
+
cur = cur[t];
|
|
26
|
+
}
|
|
27
|
+
return cur;
|
|
28
|
+
};
|
|
29
|
+
export const setPath = (obj, path, value) => {
|
|
30
|
+
const tokens = tokenize(path);
|
|
31
|
+
if (tokens.length === 0) return obj;
|
|
32
|
+
const root = Array.isArray(obj) ? [...obj] : {
|
|
33
|
+
...obj
|
|
34
|
+
};
|
|
35
|
+
let cur = root;
|
|
36
|
+
for (let i = 0; i < tokens.length - 1; i++) {
|
|
37
|
+
const t = tokens[i];
|
|
38
|
+
const next = tokens[i + 1];
|
|
39
|
+
const child = cur[t];
|
|
40
|
+
// Clone the existing branch so we never mutate the previous value tree;
|
|
41
|
+
// create the right container shape when the branch is missing.
|
|
42
|
+
const cloned = child != null && typeof child === 'object' ? Array.isArray(child) ? [...child] : {
|
|
43
|
+
...child
|
|
44
|
+
} : typeof next === 'number' ? [] : {};
|
|
45
|
+
cur[t] = cloned;
|
|
46
|
+
cur = cloned;
|
|
47
|
+
}
|
|
48
|
+
cur[tokens[tokens.length - 1]] = value;
|
|
49
|
+
return root;
|
|
50
|
+
};
|
|
51
|
+
export const deletePath = (obj, path) => {
|
|
52
|
+
const tokens = tokenize(path);
|
|
53
|
+
if (tokens.length === 0) return obj;
|
|
54
|
+
const root = Array.isArray(obj) ? [...obj] : {
|
|
55
|
+
...obj
|
|
56
|
+
};
|
|
57
|
+
let cur = root;
|
|
58
|
+
for (let i = 0; i < tokens.length - 1; i++) {
|
|
59
|
+
const t = tokens[i];
|
|
60
|
+
const child = cur[t];
|
|
61
|
+
if (child == null || typeof child !== 'object') return root;
|
|
62
|
+
const cloned = Array.isArray(child) ? [...child] : {
|
|
63
|
+
...child
|
|
64
|
+
};
|
|
65
|
+
cur[t] = cloned;
|
|
66
|
+
cur = cloned;
|
|
67
|
+
}
|
|
68
|
+
const last = tokens[tokens.length - 1];
|
|
69
|
+
if (Array.isArray(cur) && typeof last === 'number') cur.splice(last, 1);else delete cur[last];
|
|
70
|
+
return root;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validation rule presets — the dependency-free replacement for Yup chains.
|
|
5
|
+
* Each factory returns a {@link ValidationRule}. Rules built on the project's
|
|
6
|
+
* `validators` module skip empty values (so `required()` owns emptiness and you
|
|
7
|
+
* don't get duplicate errors), and accept an optional custom message.
|
|
8
|
+
*/
|
|
9
|
+
import { isEmail, isIndianMobile, isPhone, isUrl, isNumeric, isInteger, isAlphanumeric, isStrongPassword, isIndianPincode, isPan, isGstin, isAadhaar, isIfsc } from "../validators/index.js";
|
|
10
|
+
import { getPath } from "./path.js";
|
|
11
|
+
const isEmptyValue = v => v == null || v === '' || Array.isArray(v) && v.length === 0;
|
|
12
|
+
const fromPredicate = (predicate, defaultMsg) => message => value => isEmptyValue(value) || predicate(value) ? undefined : message ?? defaultMsg;
|
|
13
|
+
export const required = (message = 'This field is required') => value => {
|
|
14
|
+
// A required boolean (e.g. "accept terms" checkbox) must be true.
|
|
15
|
+
if (typeof value === 'boolean') return value ? undefined : message;
|
|
16
|
+
return isEmptyValue(value) ? message : undefined;
|
|
17
|
+
};
|
|
18
|
+
export const email = fromPredicate(isEmail, 'Enter a valid email');
|
|
19
|
+
export const mobile = fromPredicate(isIndianMobile, 'Enter a valid mobile number');
|
|
20
|
+
export const phone = fromPredicate(isPhone, 'Enter a valid phone number');
|
|
21
|
+
export const url = fromPredicate(isUrl, 'Enter a valid URL');
|
|
22
|
+
export const numeric = fromPredicate(isNumeric, 'Enter a valid number');
|
|
23
|
+
export const integer = fromPredicate(isInteger, 'Enter a whole number');
|
|
24
|
+
export const alphanumeric = fromPredicate(isAlphanumeric, 'Use letters and numbers only');
|
|
25
|
+
export const pincode = fromPredicate(isIndianPincode, 'Enter a valid 6-digit PIN code');
|
|
26
|
+
export const pan = fromPredicate(isPan, 'Enter a valid PAN');
|
|
27
|
+
export const gstin = fromPredicate(isGstin, 'Enter a valid GSTIN');
|
|
28
|
+
export const aadhaar = fromPredicate(isAadhaar, 'Enter a valid Aadhaar number');
|
|
29
|
+
export const ifsc = fromPredicate(isIfsc, 'Enter a valid IFSC code');
|
|
30
|
+
export const minLength = (length, message) => value => isEmptyValue(value) || String(value).length >= length ? undefined : message ?? `Must be at least ${length} characters`;
|
|
31
|
+
export const maxLength = (length, message) => value => value == null || String(value).length <= length ? undefined : message ?? `Must be at most ${length} characters`;
|
|
32
|
+
export const min = (n, message) => value => isEmptyValue(value) || Number(value) >= n ? undefined : message ?? `Must be at least ${n}`;
|
|
33
|
+
export const max = (n, message) => value => isEmptyValue(value) || Number(value) <= n ? undefined : message ?? `Must be at most ${n}`;
|
|
34
|
+
export const pattern = (regex, message = 'Invalid format') => value => isEmptyValue(value) || regex.test(String(value)) ? undefined : message;
|
|
35
|
+
export const oneOf = (allowed, message = 'Invalid selection') => value => isEmptyValue(value) || allowed.includes(value) ? undefined : message;
|
|
36
|
+
|
|
37
|
+
/** Cross-field equality (e.g. confirm-password). `otherField` is a field path. */
|
|
38
|
+
export const matches = (otherField, message = 'Values do not match') => (value, allValues) => value === getPath(allValues, otherField) ? undefined : message;
|
|
39
|
+
export const strongPassword = (rules, message = 'Password is too weak') => value => isEmptyValue(value) || isStrongPassword(value, rules) ? undefined : message;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Wrap any custom check. Return `true` (valid), `false` (invalid → default
|
|
43
|
+
* message), or a string (invalid → that message). Async is supported — return
|
|
44
|
+
* a Promise of the same.
|
|
45
|
+
*/
|
|
46
|
+
export const custom = (fn, message = 'Invalid value') => async (value, allValues) => {
|
|
47
|
+
const result = await fn(value, allValues);
|
|
48
|
+
if (result === true) return undefined;
|
|
49
|
+
if (result === false) return message;
|
|
50
|
+
return result;
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=rules.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { getPath } from "./path.js";
|
|
4
|
+
import { useFormContext } from "./FormContext.js";
|
|
5
|
+
/**
|
|
6
|
+
* Bind a single field by name. Returns everything an input needs; pick the
|
|
7
|
+
* handler your control uses:
|
|
8
|
+
* const email = useField('email');
|
|
9
|
+
* <Input value={email.value} onChangeText={email.onChangeText} onBlur={email.onBlur} error={email.error} />
|
|
10
|
+
* <Select value={country.value} onChange={country.onChange} error={country.error} />
|
|
11
|
+
* <Switch value={!!agree.value} onChange={agree.onChange} />
|
|
12
|
+
*/
|
|
13
|
+
export function useField(name) {
|
|
14
|
+
const form = useFormContext();
|
|
15
|
+
return form.getFieldProps(name);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Manage a repeating list field (phone numbers, line items, etc.) by name.
|
|
19
|
+
* Each helper writes the whole array back through the form so validation and
|
|
20
|
+
* dirty-tracking stay correct.
|
|
21
|
+
*/
|
|
22
|
+
export function useFieldArray(name) {
|
|
23
|
+
const form = useFormContext();
|
|
24
|
+
const fields = getPath(form.values, name) ?? [];
|
|
25
|
+
const set = next => form.setFieldValue(name, next);
|
|
26
|
+
return {
|
|
27
|
+
fields,
|
|
28
|
+
length: fields.length,
|
|
29
|
+
push: item => set([...fields, item]),
|
|
30
|
+
remove: index => set(fields.filter((_, i) => i !== index)),
|
|
31
|
+
insert: (index, item) => {
|
|
32
|
+
const copy = [...fields];
|
|
33
|
+
copy.splice(index, 0, item);
|
|
34
|
+
set(copy);
|
|
35
|
+
},
|
|
36
|
+
move: (from, to) => {
|
|
37
|
+
const copy = [...fields];
|
|
38
|
+
const [moved] = copy.splice(from, 1);
|
|
39
|
+
copy.splice(to, 0, moved);
|
|
40
|
+
set(copy);
|
|
41
|
+
},
|
|
42
|
+
replace: (index, item) => {
|
|
43
|
+
const copy = [...fields];
|
|
44
|
+
copy[index] = item;
|
|
45
|
+
set(copy);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=useField.js.map
|