@webority-technologies/mobile 0.0.15 → 0.0.20
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 +60 -19
- package/lib/commonjs/components/AppBar/AppBar.js +29 -20
- package/lib/commonjs/components/Avatar/Avatar.js +38 -8
- package/lib/commonjs/components/Badge/Badge.js +66 -4
- package/lib/commonjs/components/Banner/Banner.js +146 -66
- package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +37 -15
- package/lib/commonjs/components/BottomSheet/BottomSheet.js +78 -53
- package/lib/commonjs/components/Button/Button.js +12 -5
- package/lib/commonjs/components/Card/Card.js +106 -16
- package/lib/commonjs/components/Carousel/Carousel.js +66 -12
- package/lib/commonjs/components/Checkbox/Checkbox.js +11 -7
- package/lib/commonjs/components/Chip/Chip.js +44 -12
- package/lib/commonjs/components/DatePicker/DatePicker.js +185 -76
- package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +133 -59
- package/lib/commonjs/components/Dialog/Dialog.js +16 -10
- package/lib/commonjs/components/Drawer/Drawer.js +13 -10
- package/lib/commonjs/components/FieldBase/FieldBase.js +306 -0
- package/lib/commonjs/components/FieldBase/index.js +32 -0
- package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +69 -44
- package/lib/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
- package/lib/commonjs/components/FormField/FormField.js +3 -2
- package/lib/commonjs/components/ImageGallery/ImageGallery.js +132 -44
- package/lib/commonjs/components/Input/Input.js +144 -181
- package/lib/commonjs/components/ListItem/ListItem.js +90 -11
- package/lib/commonjs/components/Modal/Modal.js +55 -27
- package/lib/commonjs/components/NumberInput/NumberInput.js +60 -106
- package/lib/commonjs/components/OTPInput/OTPInput.js +65 -58
- package/lib/commonjs/components/PickerTrigger/PickerTrigger.js +185 -0
- package/lib/commonjs/components/{AppIcon → PickerTrigger}/index.js +4 -4
- package/lib/commonjs/components/ProgressBar/ProgressBar.js +19 -11
- package/lib/commonjs/components/Radio/Radio.js +11 -6
- package/lib/commonjs/components/Rating/Rating.js +85 -19
- package/lib/commonjs/components/SearchBar/SearchBar.js +84 -107
- package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +22 -11
- package/lib/commonjs/components/Select/Select.js +62 -91
- package/lib/commonjs/components/Skeleton/Skeleton.js +131 -174
- package/lib/commonjs/components/Skeleton/SkeletonClock.js +117 -0
- package/lib/commonjs/components/Skeleton/SkeletonContent.js +164 -81
- package/lib/commonjs/components/Skeleton/SkeletonProvider.js +72 -10
- package/lib/commonjs/components/Skeleton/index.js +17 -16
- package/lib/commonjs/components/Slider/Slider.js +44 -25
- package/lib/commonjs/components/Stepper/Stepper.js +199 -29
- package/lib/commonjs/components/Swipeable/Swipeable.js +36 -19
- package/lib/commonjs/components/Switch/Switch.js +9 -2
- package/lib/commonjs/components/Tabs/Tabs.js +84 -21
- package/lib/commonjs/components/TimePicker/TimePicker.js +123 -45
- package/lib/commonjs/components/Toast/Toast.js +27 -16
- package/lib/commonjs/components/Tooltip/Tooltip.js +56 -32
- package/lib/commonjs/components/index.js +37 -37
- package/lib/commonjs/theme/tokens.js +55 -7
- package/lib/module/components/Accordion/Accordion.js +61 -20
- package/lib/module/components/AppBar/AppBar.js +29 -20
- package/lib/module/components/Avatar/Avatar.js +39 -9
- package/lib/module/components/Badge/Badge.js +67 -5
- package/lib/module/components/Banner/Banner.js +147 -67
- package/lib/module/components/BottomNavigation/BottomNavigation.js +37 -15
- package/lib/module/components/BottomSheet/BottomSheet.js +80 -55
- package/lib/module/components/Button/Button.js +12 -5
- package/lib/module/components/Card/Card.js +107 -17
- package/lib/module/components/Carousel/Carousel.js +67 -13
- package/lib/module/components/Checkbox/Checkbox.js +11 -7
- package/lib/module/components/Chip/Chip.js +45 -13
- package/lib/module/components/DatePicker/DatePicker.js +185 -76
- package/lib/module/components/DateRangePicker/DateRangePicker.js +134 -60
- package/lib/module/components/Dialog/Dialog.js +16 -10
- package/lib/module/components/Drawer/Drawer.js +13 -10
- package/lib/module/components/FieldBase/FieldBase.js +297 -0
- package/lib/module/components/FieldBase/index.js +4 -0
- package/lib/module/components/FloatingActionButton/FloatingActionButton.js +69 -44
- package/lib/module/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
- package/lib/module/components/FormField/FormField.js +3 -2
- package/lib/module/components/ImageGallery/ImageGallery.js +128 -40
- package/lib/module/components/Input/Input.js +144 -179
- package/lib/module/components/ListItem/ListItem.js +91 -12
- package/lib/module/components/Modal/Modal.js +55 -27
- package/lib/module/components/NumberInput/NumberInput.js +60 -106
- package/lib/module/components/OTPInput/OTPInput.js +65 -58
- package/lib/module/components/PickerTrigger/PickerTrigger.js +181 -0
- package/lib/module/components/PickerTrigger/index.js +4 -0
- package/lib/module/components/ProgressBar/ProgressBar.js +19 -11
- package/lib/module/components/Radio/Radio.js +11 -6
- package/lib/module/components/Rating/Rating.js +86 -20
- package/lib/module/components/SearchBar/SearchBar.js +84 -107
- package/lib/module/components/SegmentedControl/SegmentedControl.js +22 -11
- package/lib/module/components/Select/Select.js +62 -91
- package/lib/module/components/Skeleton/Skeleton.js +135 -175
- package/lib/module/components/Skeleton/SkeletonClock.js +110 -0
- package/lib/module/components/Skeleton/SkeletonContent.js +167 -84
- package/lib/module/components/Skeleton/SkeletonProvider.js +71 -10
- package/lib/module/components/Skeleton/index.js +3 -2
- package/lib/module/components/Slider/Slider.js +44 -25
- package/lib/module/components/Stepper/Stepper.js +201 -31
- package/lib/module/components/Swipeable/Swipeable.js +36 -19
- package/lib/module/components/Switch/Switch.js +9 -2
- package/lib/module/components/Tabs/Tabs.js +84 -21
- package/lib/module/components/TimePicker/TimePicker.js +123 -45
- package/lib/module/components/Toast/Toast.js +27 -16
- package/lib/module/components/Tooltip/Tooltip.js +56 -32
- package/lib/module/components/index.js +2 -2
- package/lib/module/theme/tokens.js +55 -7
- package/lib/typescript/commonjs/components/Accordion/Accordion.d.ts +10 -5
- package/lib/typescript/commonjs/components/AppBar/AppBar.d.ts +8 -0
- package/lib/typescript/commonjs/components/Avatar/Avatar.d.ts +12 -6
- package/lib/typescript/commonjs/components/Badge/Badge.d.ts +7 -6
- package/lib/typescript/commonjs/components/Banner/Banner.d.ts +17 -6
- package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +7 -0
- package/lib/typescript/commonjs/components/Card/Card.d.ts +17 -6
- package/lib/typescript/commonjs/components/Carousel/Carousel.d.ts +7 -6
- package/lib/typescript/commonjs/components/Checkbox/Checkbox.d.ts +9 -1
- package/lib/typescript/commonjs/components/Chip/Chip.d.ts +13 -6
- package/lib/typescript/commonjs/components/DatePicker/DatePicker.d.ts +38 -3
- package/lib/typescript/commonjs/components/DateRangePicker/DateRangePicker.d.ts +36 -3
- package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +13 -1
- package/lib/typescript/commonjs/components/FieldBase/FieldBase.d.ts +141 -0
- package/lib/typescript/commonjs/components/FieldBase/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
- package/lib/typescript/commonjs/components/FloatingActionButton/index.d.ts +1 -1
- package/lib/typescript/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
- package/lib/typescript/commonjs/components/FormField/FormField.d.ts +7 -0
- package/lib/typescript/commonjs/components/ImageGallery/ImageGallery.d.ts +6 -4
- package/lib/typescript/commonjs/components/Input/Input.d.ts +6 -0
- package/lib/typescript/commonjs/components/ListItem/ListItem.d.ts +13 -6
- package/lib/typescript/commonjs/components/NumberInput/NumberInput.d.ts +3 -0
- package/lib/typescript/commonjs/components/PickerTrigger/PickerTrigger.d.ts +57 -0
- package/lib/typescript/commonjs/components/PickerTrigger/index.d.ts +3 -0
- package/lib/typescript/commonjs/components/ProgressBar/ProgressBar.d.ts +2 -0
- package/lib/typescript/commonjs/components/Radio/Radio.d.ts +3 -0
- package/lib/typescript/commonjs/components/Rating/Rating.d.ts +9 -6
- package/lib/typescript/commonjs/components/SegmentedControl/SegmentedControl.d.ts +3 -0
- package/lib/typescript/commonjs/components/Skeleton/Skeleton.d.ts +49 -20
- package/lib/typescript/commonjs/components/Skeleton/SkeletonClock.d.ts +60 -0
- package/lib/typescript/commonjs/components/Skeleton/SkeletonContent.d.ts +80 -19
- package/lib/typescript/commonjs/components/Skeleton/SkeletonProvider.d.ts +39 -5
- package/lib/typescript/commonjs/components/Skeleton/index.d.ts +6 -4
- package/lib/typescript/commonjs/components/Slider/Slider.d.ts +12 -1
- package/lib/typescript/commonjs/components/Stepper/Stepper.d.ts +18 -6
- package/lib/typescript/commonjs/components/Swipeable/Swipeable.d.ts +2 -0
- package/lib/typescript/commonjs/components/Switch/Switch.d.ts +1 -0
- package/lib/typescript/commonjs/components/Tabs/Tabs.d.ts +26 -2
- package/lib/typescript/commonjs/components/TimePicker/TimePicker.d.ts +36 -3
- package/lib/typescript/commonjs/components/Toast/Toast.d.ts +8 -0
- package/lib/typescript/commonjs/components/Tooltip/Tooltip.d.ts +7 -1
- package/lib/typescript/commonjs/components/index.d.ts +5 -5
- package/lib/typescript/commonjs/index.d.ts +1 -1
- package/lib/typescript/commonjs/theme/index.d.ts +1 -1
- package/lib/typescript/commonjs/theme/types.d.ts +553 -11
- package/lib/typescript/module/components/Accordion/Accordion.d.ts +10 -5
- package/lib/typescript/module/components/AppBar/AppBar.d.ts +8 -0
- package/lib/typescript/module/components/Avatar/Avatar.d.ts +12 -6
- package/lib/typescript/module/components/Badge/Badge.d.ts +7 -6
- package/lib/typescript/module/components/Banner/Banner.d.ts +17 -6
- package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +7 -0
- package/lib/typescript/module/components/Card/Card.d.ts +17 -6
- package/lib/typescript/module/components/Carousel/Carousel.d.ts +7 -6
- package/lib/typescript/module/components/Checkbox/Checkbox.d.ts +9 -1
- package/lib/typescript/module/components/Chip/Chip.d.ts +13 -6
- package/lib/typescript/module/components/DatePicker/DatePicker.d.ts +38 -3
- package/lib/typescript/module/components/DateRangePicker/DateRangePicker.d.ts +36 -3
- package/lib/typescript/module/components/Dialog/Dialog.d.ts +13 -1
- package/lib/typescript/module/components/FieldBase/FieldBase.d.ts +141 -0
- package/lib/typescript/module/components/FieldBase/index.d.ts +3 -0
- package/lib/typescript/module/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
- package/lib/typescript/module/components/FloatingActionButton/index.d.ts +1 -1
- package/lib/typescript/module/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
- package/lib/typescript/module/components/FormField/FormField.d.ts +7 -0
- package/lib/typescript/module/components/ImageGallery/ImageGallery.d.ts +6 -4
- package/lib/typescript/module/components/Input/Input.d.ts +6 -0
- package/lib/typescript/module/components/ListItem/ListItem.d.ts +13 -6
- package/lib/typescript/module/components/NumberInput/NumberInput.d.ts +3 -0
- package/lib/typescript/module/components/PickerTrigger/PickerTrigger.d.ts +57 -0
- package/lib/typescript/module/components/PickerTrigger/index.d.ts +3 -0
- package/lib/typescript/module/components/ProgressBar/ProgressBar.d.ts +2 -0
- package/lib/typescript/module/components/Radio/Radio.d.ts +3 -0
- package/lib/typescript/module/components/Rating/Rating.d.ts +9 -6
- package/lib/typescript/module/components/SegmentedControl/SegmentedControl.d.ts +3 -0
- package/lib/typescript/module/components/Skeleton/Skeleton.d.ts +49 -20
- package/lib/typescript/module/components/Skeleton/SkeletonClock.d.ts +60 -0
- package/lib/typescript/module/components/Skeleton/SkeletonContent.d.ts +80 -19
- package/lib/typescript/module/components/Skeleton/SkeletonProvider.d.ts +39 -5
- package/lib/typescript/module/components/Skeleton/index.d.ts +6 -4
- package/lib/typescript/module/components/Slider/Slider.d.ts +12 -1
- package/lib/typescript/module/components/Stepper/Stepper.d.ts +18 -6
- package/lib/typescript/module/components/Swipeable/Swipeable.d.ts +2 -0
- package/lib/typescript/module/components/Switch/Switch.d.ts +1 -0
- package/lib/typescript/module/components/Tabs/Tabs.d.ts +26 -2
- package/lib/typescript/module/components/TimePicker/TimePicker.d.ts +36 -3
- package/lib/typescript/module/components/Toast/Toast.d.ts +8 -0
- package/lib/typescript/module/components/Tooltip/Tooltip.d.ts +7 -1
- package/lib/typescript/module/components/index.d.ts +5 -5
- package/lib/typescript/module/index.d.ts +1 -1
- package/lib/typescript/module/theme/index.d.ts +1 -1
- package/lib/typescript/module/theme/types.d.ts +553 -11
- package/package.json +2 -6
- package/lib/commonjs/components/AppIcon/AppIcon.js +0 -120
- package/lib/commonjs/types/vector-icons.d.js +0 -2
- package/lib/module/components/AppIcon/AppIcon.js +0 -111
- package/lib/module/components/AppIcon/index.js +0 -4
- package/lib/module/types/vector-icons.d.js +0 -2
- package/lib/typescript/commonjs/components/AppIcon/AppIcon.d.ts +0 -20
- package/lib/typescript/commonjs/components/AppIcon/index.d.ts +0 -3
- package/lib/typescript/module/components/AppIcon/AppIcon.d.ts +0 -20
- package/lib/typescript/module/components/AppIcon/index.d.ts +0 -3
|
@@ -25,12 +25,28 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
25
25
|
scrollable = false,
|
|
26
26
|
align = 'left',
|
|
27
27
|
style,
|
|
28
|
+
containerStyle,
|
|
28
29
|
tabStyle,
|
|
30
|
+
tabLabelStyle,
|
|
31
|
+
tabIconStyle,
|
|
32
|
+
tabBadgeStyle,
|
|
33
|
+
dividerStyle,
|
|
34
|
+
indicatorStyle,
|
|
35
|
+
progress,
|
|
29
36
|
accessibilityLabel,
|
|
30
37
|
testID
|
|
31
38
|
} = props;
|
|
32
39
|
const theme = useTheme();
|
|
33
40
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
41
|
+
const tabsTokens = theme.components.tabs;
|
|
42
|
+
const tabPaddingHorizontal = tabsTokens?.tabPaddingHorizontal ?? theme.spacing.lg;
|
|
43
|
+
const tabPaddingVertical = tabsTokens?.tabPaddingVertical ?? theme.spacing.md;
|
|
44
|
+
const tabIconSpacing = tabsTokens?.tabIconSpacing ?? 6;
|
|
45
|
+
const underlineHeight = tabsTokens?.underlineHeight ?? 2;
|
|
46
|
+
const pillInset = tabsTokens?.pillInset ?? 4;
|
|
47
|
+
const disabledOpacity = tabsTokens?.disabledOpacity ?? 0.45;
|
|
48
|
+
const badgeGap = tabsTokens?.badgeGap ?? 6;
|
|
49
|
+
const hapticOnPress = tabsTokens?.hapticOnPress ?? false;
|
|
34
50
|
|
|
35
51
|
// Per-tab measured layouts (key → {x, width}).
|
|
36
52
|
const [layouts, setLayouts] = useState({});
|
|
@@ -38,9 +54,33 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
38
54
|
const indicatorWidth = useRef(createAnimatedValue(0)).current;
|
|
39
55
|
const activeLayout = layouts[activeKey];
|
|
40
56
|
|
|
57
|
+
// Progress-driven mode: when the caller supplies a fractional-index signal
|
|
58
|
+
// and every tab has reported its layout, the indicator's translateX/width
|
|
59
|
+
// are interpolated from that signal — the press-spring is suppressed so the
|
|
60
|
+
// two drivers don't fight for the same view.
|
|
61
|
+
const allMeasured = tabs.every(t => layouts[t.key] !== undefined);
|
|
62
|
+
const useProgress = progress !== undefined && allMeasured && tabs.length > 1;
|
|
63
|
+
const progressTranslateX = useMemo(() => {
|
|
64
|
+
if (!useProgress || !progress) return null;
|
|
65
|
+
return progress.interpolate({
|
|
66
|
+
inputRange: tabs.map((_, i) => i),
|
|
67
|
+
outputRange: tabs.map(t => layouts[t.key].x),
|
|
68
|
+
extrapolate: 'clamp'
|
|
69
|
+
});
|
|
70
|
+
}, [useProgress, progress, tabs, layouts]);
|
|
71
|
+
const progressWidth = useMemo(() => {
|
|
72
|
+
if (!useProgress || !progress) return null;
|
|
73
|
+
return progress.interpolate({
|
|
74
|
+
inputRange: tabs.map((_, i) => i),
|
|
75
|
+
outputRange: tabs.map(t => layouts[t.key].width),
|
|
76
|
+
extrapolate: 'clamp'
|
|
77
|
+
});
|
|
78
|
+
}, [useProgress, progress, tabs, layouts]);
|
|
79
|
+
|
|
41
80
|
// Animate indicator whenever activeKey or its layout changes.
|
|
42
81
|
useEffect(() => {
|
|
43
82
|
if (!activeLayout) return;
|
|
83
|
+
if (useProgress) return;
|
|
44
84
|
const spring = theme.motion.spring.snappy;
|
|
45
85
|
Animated.parallel([
|
|
46
86
|
// Both must use the JS driver: width can't run on native, and mixing
|
|
@@ -59,7 +99,7 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
59
99
|
mass: spring.mass,
|
|
60
100
|
useNativeDriver: false
|
|
61
101
|
})]).start();
|
|
62
|
-
}, [activeLayout, activeKey, indicatorTranslateX, indicatorWidth, theme.motion.spring.snappy]);
|
|
102
|
+
}, [activeLayout, activeKey, indicatorTranslateX, indicatorWidth, theme.motion.spring.snappy, useProgress]);
|
|
63
103
|
const handleLayout = useCallback(key => e => {
|
|
64
104
|
const {
|
|
65
105
|
x,
|
|
@@ -80,22 +120,27 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
80
120
|
const handlePress = useCallback(tab => {
|
|
81
121
|
if (tab.disabled) return;
|
|
82
122
|
if (tab.key === activeKey) return;
|
|
83
|
-
triggerHaptic('selection');
|
|
123
|
+
if (hapticOnPress) triggerHaptic('selection');
|
|
84
124
|
onChange(tab.key);
|
|
85
|
-
}, [activeKey, onChange]);
|
|
125
|
+
}, [activeKey, onChange, hapticOnPress]);
|
|
86
126
|
const indicatorIsPill = variant === 'pills';
|
|
87
127
|
|
|
88
128
|
// Indicator visual.
|
|
89
129
|
const indicator = /*#__PURE__*/_jsx(Animated.View, {
|
|
90
130
|
pointerEvents: "none",
|
|
91
|
-
style: [indicatorIsPill ? styles.indicatorPill : styles.indicatorUnderline, {
|
|
92
|
-
|
|
131
|
+
style: [indicatorIsPill ? styles.indicatorPill : styles.indicatorUnderline, indicatorIsPill ? {
|
|
132
|
+
top: pillInset,
|
|
133
|
+
bottom: pillInset
|
|
134
|
+
} : {
|
|
135
|
+
height: underlineHeight
|
|
136
|
+
}, {
|
|
137
|
+
width: progressWidth ?? indicatorWidth,
|
|
93
138
|
transform: [{
|
|
94
|
-
translateX: indicatorTranslateX
|
|
139
|
+
translateX: progressTranslateX ?? indicatorTranslateX
|
|
95
140
|
}],
|
|
96
141
|
backgroundColor: indicatorIsPill ? theme.colors.primaryMuted : theme.colors.primary,
|
|
97
142
|
borderRadius: indicatorIsPill ? theme.radius.full : 0
|
|
98
|
-
}]
|
|
143
|
+
}, indicatorStyle]
|
|
99
144
|
});
|
|
100
145
|
const renderTabs = () => tabs.map(tab => {
|
|
101
146
|
const isActive = tab.key === activeKey;
|
|
@@ -117,23 +162,41 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
117
162
|
style: ({
|
|
118
163
|
pressed
|
|
119
164
|
}) => [styles.tab, scrollable ? null : styles.tabFlex, {
|
|
120
|
-
paddingHorizontal:
|
|
121
|
-
paddingVertical:
|
|
122
|
-
opacity: isDisabled ?
|
|
165
|
+
paddingHorizontal: tabPaddingHorizontal,
|
|
166
|
+
paddingVertical: tabPaddingVertical,
|
|
167
|
+
opacity: isDisabled ? disabledOpacity : 1,
|
|
123
168
|
backgroundColor: pressed ? theme.colors.surface.pressed : 'transparent'
|
|
124
169
|
}, tabStyle],
|
|
125
170
|
children: [tab.icon ? /*#__PURE__*/_jsx(View, {
|
|
126
|
-
style: styles.tabIcon,
|
|
171
|
+
style: [styles.tabIcon, {
|
|
172
|
+
marginRight: tabIconSpacing
|
|
173
|
+
}, tabIconStyle],
|
|
127
174
|
children: tab.icon
|
|
128
175
|
}) : null, /*#__PURE__*/_jsx(Text, {
|
|
129
176
|
style: [styles.tabLabel, {
|
|
130
177
|
color: isActive ? theme.colors.primary : theme.colors.text.tertiary,
|
|
131
178
|
fontSize: theme.typography.fontSize.base,
|
|
132
179
|
fontWeight: isActive ? theme.typography.fontWeight.semibold : theme.typography.fontWeight.medium
|
|
133
|
-
}],
|
|
180
|
+
}, tabLabelStyle],
|
|
134
181
|
numberOfLines: 1,
|
|
135
182
|
children: tab.label
|
|
136
|
-
})
|
|
183
|
+
}), tab.badge !== undefined && tab.badge !== null ? /*#__PURE__*/_jsx(View, {
|
|
184
|
+
style: [styles.tabBadge, {
|
|
185
|
+
marginLeft: badgeGap,
|
|
186
|
+
backgroundColor: theme.colors.primaryMuted,
|
|
187
|
+
borderRadius: theme.radius.full,
|
|
188
|
+
paddingHorizontal: theme.spacing.xs
|
|
189
|
+
}, tabBadgeStyle],
|
|
190
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
191
|
+
style: {
|
|
192
|
+
color: theme.colors.primary,
|
|
193
|
+
fontSize: theme.typography.fontSize.xs,
|
|
194
|
+
fontWeight: theme.typography.fontWeight.semibold
|
|
195
|
+
},
|
|
196
|
+
numberOfLines: 1,
|
|
197
|
+
children: String(tab.badge)
|
|
198
|
+
})
|
|
199
|
+
}) : null]
|
|
137
200
|
}, tab.key);
|
|
138
201
|
});
|
|
139
202
|
const baseRowStyle = {
|
|
@@ -147,7 +210,7 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
147
210
|
style: [styles.container, {
|
|
148
211
|
borderBottomColor: theme.colors.border.secondary,
|
|
149
212
|
borderBottomWidth: variant === 'underline' ? StyleSheet.hairlineWidth : 0
|
|
150
|
-
}, style],
|
|
213
|
+
}, variant === 'underline' ? dividerStyle : null, style, containerStyle],
|
|
151
214
|
accessibilityRole: "tablist",
|
|
152
215
|
accessibilityLabel: accessibilityLabel,
|
|
153
216
|
testID: testID,
|
|
@@ -177,23 +240,23 @@ const buildStyles = _theme => StyleSheet.create({
|
|
|
177
240
|
tabFlex: {
|
|
178
241
|
flex: 1
|
|
179
242
|
},
|
|
180
|
-
tabIcon: {
|
|
181
|
-
marginRight: 6
|
|
182
|
-
},
|
|
243
|
+
tabIcon: {},
|
|
183
244
|
tabLabel: {
|
|
184
245
|
includeFontPadding: false
|
|
185
246
|
},
|
|
247
|
+
tabBadge: {
|
|
248
|
+
minWidth: 18,
|
|
249
|
+
alignItems: 'center',
|
|
250
|
+
justifyContent: 'center'
|
|
251
|
+
},
|
|
186
252
|
indicatorUnderline: {
|
|
187
253
|
position: 'absolute',
|
|
188
254
|
left: 0,
|
|
189
|
-
bottom: 0
|
|
190
|
-
height: 2
|
|
255
|
+
bottom: 0
|
|
191
256
|
},
|
|
192
257
|
indicatorPill: {
|
|
193
258
|
position: 'absolute',
|
|
194
259
|
left: 0,
|
|
195
|
-
top: 4,
|
|
196
|
-
bottom: 4,
|
|
197
260
|
zIndex: -1
|
|
198
261
|
}
|
|
199
262
|
});
|
|
@@ -2,9 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { AccessibilityInfo, Animated, Easing, FlatList, Modal, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
5
6
|
import { useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
|
|
6
7
|
import { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
7
8
|
import Button from "../Button/Button.js";
|
|
9
|
+
import { PickerTrigger } from "../PickerTrigger/PickerTrigger.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* TimePicker supports two modes:
|
|
13
|
+
*
|
|
14
|
+
* 1. Controlled-modal mode — pass `visible`, `onSelect`, `onClose`. The
|
|
15
|
+
* component renders only the modal sheet and the caller owns open/close
|
|
16
|
+
* state plus its own trigger UI.
|
|
17
|
+
* 2. Trigger mode — omit `visible`. The component renders a PickerTrigger
|
|
18
|
+
* field (label / value / placeholder / chevron / clear / helper / error)
|
|
19
|
+
* and manages its own modal open state. `onSelect` is still called on
|
|
20
|
+
* confirm.
|
|
21
|
+
*/
|
|
8
22
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
9
23
|
const ITEM_HEIGHT = 40;
|
|
10
24
|
const VISIBLE_ITEMS = 5;
|
|
@@ -78,6 +92,8 @@ const Wheel = ({
|
|
|
78
92
|
});
|
|
79
93
|
}
|
|
80
94
|
}, [selectedIndex, scrollY]);
|
|
95
|
+
const hapticEnabled = theme.components.timePicker?.haptic ?? false;
|
|
96
|
+
const hapticDebounceMs = theme.components.timePicker?.hapticDebounceMs ?? HAPTIC_DEBOUNCE_MS;
|
|
81
97
|
const onScroll = useMemo(() => Animated.event([{
|
|
82
98
|
nativeEvent: {
|
|
83
99
|
contentOffset: {
|
|
@@ -91,14 +107,14 @@ const Wheel = ({
|
|
|
91
107
|
const idx = Math.round(y / ITEM_HEIGHT);
|
|
92
108
|
if (idx !== lastIndexRef.current && idx >= 0 && idx < data.length) {
|
|
93
109
|
const now = Date.now();
|
|
94
|
-
if (now - lastHapticAtRef.current >=
|
|
110
|
+
if (hapticEnabled && now - lastHapticAtRef.current >= hapticDebounceMs) {
|
|
95
111
|
triggerHaptic('selection');
|
|
96
112
|
lastHapticAtRef.current = now;
|
|
97
113
|
}
|
|
98
114
|
lastIndexRef.current = idx;
|
|
99
115
|
}
|
|
100
116
|
}
|
|
101
|
-
}), [scrollY, data.length]);
|
|
117
|
+
}), [scrollY, data.length, hapticEnabled, hapticDebounceMs]);
|
|
102
118
|
const onMomentumScrollEnd = useCallback(event => {
|
|
103
119
|
const y = event.nativeEvent.contentOffset.y;
|
|
104
120
|
const idx = Math.max(0, Math.min(data.length - 1, Math.round(y / ITEM_HEIGHT)));
|
|
@@ -197,21 +213,48 @@ const Wheel = ({
|
|
|
197
213
|
})]
|
|
198
214
|
});
|
|
199
215
|
};
|
|
200
|
-
const TimePicker =
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
216
|
+
const TimePicker = props => {
|
|
217
|
+
const {
|
|
218
|
+
visible,
|
|
219
|
+
value,
|
|
220
|
+
onSelect,
|
|
221
|
+
onClose,
|
|
222
|
+
format = '12h',
|
|
223
|
+
minuteStep = 1,
|
|
224
|
+
title = 'Select Time',
|
|
225
|
+
confirmLabel = 'Confirm',
|
|
226
|
+
cancelLabel = 'Cancel',
|
|
227
|
+
testID,
|
|
228
|
+
style,
|
|
229
|
+
containerStyle,
|
|
230
|
+
headerLabelStyle,
|
|
231
|
+
footerButtonStyle,
|
|
232
|
+
label,
|
|
233
|
+
placeholder,
|
|
234
|
+
helperText,
|
|
235
|
+
error,
|
|
236
|
+
required,
|
|
237
|
+
disabled,
|
|
238
|
+
size,
|
|
239
|
+
variant,
|
|
240
|
+
clearable,
|
|
241
|
+
onClear,
|
|
242
|
+
formatValue,
|
|
243
|
+
triggerStyle
|
|
244
|
+
} = props;
|
|
245
|
+
const isControlled = props.visible !== undefined;
|
|
246
|
+
const [internalOpen, setInternalOpen] = useState(false);
|
|
247
|
+
const open = isControlled ? visible : internalOpen;
|
|
213
248
|
const theme = useTheme();
|
|
249
|
+
const insets = useSafeAreaInsets();
|
|
214
250
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
251
|
+
const handleCloseModal = useCallback(() => {
|
|
252
|
+
if (isControlled) {
|
|
253
|
+
onClose?.();
|
|
254
|
+
} else {
|
|
255
|
+
setInternalOpen(false);
|
|
256
|
+
}
|
|
257
|
+
}, [isControlled, onClose]);
|
|
215
258
|
const hours = useMemo(() => format === '24h' ? range(0, 23) : range(1, 12), [format]);
|
|
216
259
|
const minutes = useMemo(() => range(0, 59, minuteStep), [minuteStep]);
|
|
217
260
|
const periods = useMemo(() => ['AM', 'PM'], []);
|
|
@@ -240,9 +283,9 @@ const TimePicker = ({
|
|
|
240
283
|
});
|
|
241
284
|
const [periodIndex, setPeriodIndex] = useState(() => initial.period === 'PM' ? 1 : 0);
|
|
242
285
|
|
|
243
|
-
// Re-sync on
|
|
286
|
+
// Re-sync on open toggle / value change / format / step.
|
|
244
287
|
useEffect(() => {
|
|
245
|
-
if (!
|
|
288
|
+
if (!open) return;
|
|
246
289
|
const h24 = value && Number.isFinite(value.hour) ? value.hour : new Date().getHours();
|
|
247
290
|
const m = value && Number.isFinite(value.minute) ? value.minute : new Date().getMinutes();
|
|
248
291
|
const stepped = clampMinuteToStep(m, minuteStep);
|
|
@@ -255,18 +298,20 @@ const TimePicker = ({
|
|
|
255
298
|
const mIdx = minutes.indexOf(stepped);
|
|
256
299
|
setMinuteIndex(mIdx >= 0 ? mIdx : 0);
|
|
257
300
|
setPeriodIndex(period === 'PM' ? 1 : 0);
|
|
258
|
-
}, [
|
|
301
|
+
}, [open, value, format, minuteStep, hours, minutes]);
|
|
259
302
|
|
|
260
303
|
// Sheet animations.
|
|
261
304
|
const opacity = useRef(createAnimatedValue(0)).current;
|
|
262
305
|
const translateY = useRef(createAnimatedValue(40)).current;
|
|
263
306
|
useEffect(() => {
|
|
264
|
-
if (
|
|
265
|
-
Animated.parallel([
|
|
307
|
+
if (open) {
|
|
308
|
+
Animated.parallel([
|
|
309
|
+
// Backdrop opacity uses JS driver — see Modal.tsx for the Fabric reason.
|
|
310
|
+
Animated.timing(opacity, {
|
|
266
311
|
toValue: 1,
|
|
267
312
|
duration: theme.motion.duration.normal,
|
|
268
313
|
easing: Easing.out(Easing.cubic),
|
|
269
|
-
useNativeDriver:
|
|
314
|
+
useNativeDriver: false
|
|
270
315
|
}), Animated.spring(translateY, {
|
|
271
316
|
toValue: 0,
|
|
272
317
|
damping: theme.motion.spring.snappy.damping,
|
|
@@ -275,10 +320,10 @@ const TimePicker = ({
|
|
|
275
320
|
useNativeDriver: true
|
|
276
321
|
})]).start();
|
|
277
322
|
} else {
|
|
278
|
-
|
|
323
|
+
opacity.setValue(0);
|
|
279
324
|
setNativeValue(translateY, 40);
|
|
280
325
|
}
|
|
281
|
-
}, [
|
|
326
|
+
}, [open, opacity, translateY, theme.motion]);
|
|
282
327
|
const announce = useCallback(msg => {
|
|
283
328
|
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
284
329
|
AccessibilityInfo.announceForAccessibility(msg);
|
|
@@ -297,21 +342,21 @@ const TimePicker = ({
|
|
|
297
342
|
announce(periods[idx] ?? '');
|
|
298
343
|
}, [periods, announce]);
|
|
299
344
|
const handleCancel = useCallback(() => {
|
|
300
|
-
triggerHaptic('selection');
|
|
301
|
-
|
|
302
|
-
}, [
|
|
345
|
+
if (theme.components.timePicker?.haptic) triggerHaptic('selection');
|
|
346
|
+
handleCloseModal();
|
|
347
|
+
}, [handleCloseModal, theme.components.timePicker]);
|
|
303
348
|
const handleConfirm = useCallback(() => {
|
|
304
349
|
const displayHour = hours[hourIndex] ?? 0;
|
|
305
350
|
const period = periods[periodIndex] ?? 'AM';
|
|
306
351
|
const hour24 = to24h(displayHour, period, format);
|
|
307
352
|
const minute = minutes[minuteIndex] ?? 0;
|
|
308
|
-
triggerHaptic('notificationSuccess');
|
|
309
|
-
onSelect({
|
|
353
|
+
if (theme.components.timePicker?.haptic) triggerHaptic('notificationSuccess');
|
|
354
|
+
onSelect?.({
|
|
310
355
|
hour: hour24,
|
|
311
356
|
minute
|
|
312
357
|
});
|
|
313
|
-
|
|
314
|
-
}, [hours, hourIndex, periods, periodIndex, minutes, minuteIndex, format, onSelect,
|
|
358
|
+
handleCloseModal();
|
|
359
|
+
}, [hours, hourIndex, periods, periodIndex, minutes, minuteIndex, format, onSelect, handleCloseModal, theme.components.timePicker]);
|
|
315
360
|
const summary = useMemo(() => {
|
|
316
361
|
const displayHour = hours[hourIndex] ?? 0;
|
|
317
362
|
const minute = minutes[minuteIndex] ?? 0;
|
|
@@ -322,28 +367,43 @@ const TimePicker = ({
|
|
|
322
367
|
const formatHourItem = useCallback(item => pad2(Number(item)), []);
|
|
323
368
|
const formatMinuteItem = useCallback(item => pad2(Number(item)), []);
|
|
324
369
|
const formatPeriodItem = useCallback(item => String(item), []);
|
|
325
|
-
|
|
326
|
-
|
|
370
|
+
const defaultFormatValue = useCallback(t => {
|
|
371
|
+
if (format === '24h') return `${pad2(t.hour)}:${pad2(t.minute)}`;
|
|
372
|
+
const {
|
|
373
|
+
displayHour,
|
|
374
|
+
period
|
|
375
|
+
} = from24h(t.hour, '12h');
|
|
376
|
+
return `${displayHour}:${pad2(t.minute)} ${period}`;
|
|
377
|
+
}, [format]);
|
|
378
|
+
const triggerValue = !isControlled && value && Number.isFinite(value.hour) && Number.isFinite(value.minute) ? (formatValue ?? defaultFormatValue)(value) : undefined;
|
|
379
|
+
const modal = /*#__PURE__*/_jsx(Modal, {
|
|
380
|
+
visible: open,
|
|
327
381
|
transparent: true,
|
|
328
|
-
statusBarTranslucent: true
|
|
382
|
+
statusBarTranslucent: true
|
|
383
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
384
|
+
// @ts-ignore — Android-only RN 0.71+; iOS ignores it.
|
|
385
|
+
,
|
|
386
|
+
navigationBarTranslucent: true,
|
|
329
387
|
animationType: "none",
|
|
330
|
-
onRequestClose:
|
|
388
|
+
onRequestClose: handleCloseModal,
|
|
331
389
|
testID: testID,
|
|
332
|
-
children: /*#__PURE__*/_jsxs(
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
390
|
+
children: /*#__PURE__*/_jsxs(View
|
|
391
|
+
// Plain View + collapsable={false} — see Modal.tsx backdrop comment.
|
|
392
|
+
, {
|
|
393
|
+
collapsable: false,
|
|
394
|
+
style: styles.backdrop,
|
|
336
395
|
children: [/*#__PURE__*/_jsx(Pressable, {
|
|
337
396
|
style: StyleSheet.absoluteFill,
|
|
338
|
-
onPress:
|
|
397
|
+
onPress: handleCloseModal,
|
|
339
398
|
accessibilityLabel: "Close time picker",
|
|
340
399
|
accessibilityRole: "button"
|
|
341
400
|
}), /*#__PURE__*/_jsxs(Animated.View, {
|
|
342
401
|
style: [styles.sheet, {
|
|
402
|
+
paddingBottom: insets.bottom + theme.spacing.xl,
|
|
343
403
|
transform: [{
|
|
344
404
|
translateY
|
|
345
405
|
}]
|
|
346
|
-
}, style],
|
|
406
|
+
}, style, containerStyle],
|
|
347
407
|
accessibilityViewIsModal: true,
|
|
348
408
|
accessible: true,
|
|
349
409
|
accessibilityRole: "none",
|
|
@@ -351,7 +411,7 @@ const TimePicker = ({
|
|
|
351
411
|
children: [/*#__PURE__*/_jsx(View, {
|
|
352
412
|
style: styles.handle
|
|
353
413
|
}), /*#__PURE__*/_jsx(Text, {
|
|
354
|
-
style: styles.title,
|
|
414
|
+
style: [styles.title, headerLabelStyle],
|
|
355
415
|
accessibilityRole: "header",
|
|
356
416
|
children: title
|
|
357
417
|
}), /*#__PURE__*/_jsx(View, {
|
|
@@ -414,7 +474,7 @@ const TimePicker = ({
|
|
|
414
474
|
variant: "ghost",
|
|
415
475
|
tone: "neutral",
|
|
416
476
|
onPress: handleCancel,
|
|
417
|
-
style: styles.footerBtn,
|
|
477
|
+
style: [styles.footerBtn, footerButtonStyle],
|
|
418
478
|
accessibilityHint: "Dismiss without changes",
|
|
419
479
|
testID: "time-picker-cancel"
|
|
420
480
|
}), /*#__PURE__*/_jsx(Button, {
|
|
@@ -423,7 +483,7 @@ const TimePicker = ({
|
|
|
423
483
|
tone: "primary",
|
|
424
484
|
haptic: false,
|
|
425
485
|
onPress: handleConfirm,
|
|
426
|
-
style: styles.footerBtn,
|
|
486
|
+
style: [styles.footerBtn, footerButtonStyle],
|
|
427
487
|
accessibilityHint: "Confirm selected time",
|
|
428
488
|
testID: "time-picker-confirm"
|
|
429
489
|
})]
|
|
@@ -431,6 +491,24 @@ const TimePicker = ({
|
|
|
431
491
|
})]
|
|
432
492
|
})
|
|
433
493
|
});
|
|
494
|
+
if (isControlled) return modal;
|
|
495
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
496
|
+
children: [/*#__PURE__*/_jsx(PickerTrigger, {
|
|
497
|
+
label: label,
|
|
498
|
+
placeholder: placeholder,
|
|
499
|
+
helperText: helperText,
|
|
500
|
+
error: error,
|
|
501
|
+
required: required,
|
|
502
|
+
disabled: disabled,
|
|
503
|
+
size: size,
|
|
504
|
+
variant: variant,
|
|
505
|
+
clearable: clearable,
|
|
506
|
+
onClear: onClear,
|
|
507
|
+
value: triggerValue,
|
|
508
|
+
onPress: () => setInternalOpen(true),
|
|
509
|
+
triggerStyle: triggerStyle
|
|
510
|
+
}), modal]
|
|
511
|
+
});
|
|
434
512
|
};
|
|
435
513
|
const styles = StyleSheet.create({
|
|
436
514
|
wheelColumn: {
|
|
@@ -475,8 +553,8 @@ const buildStyles = theme => {
|
|
|
475
553
|
},
|
|
476
554
|
handle: {
|
|
477
555
|
alignSelf: 'center',
|
|
478
|
-
width: 36,
|
|
479
|
-
height: 4,
|
|
556
|
+
width: theme.components.timePicker?.handleWidth ?? 36,
|
|
557
|
+
height: theme.components.timePicker?.handleHeight ?? 4,
|
|
480
558
|
borderRadius: theme.radius.full,
|
|
481
559
|
backgroundColor: theme.colors.border.secondary,
|
|
482
560
|
marginBottom: theme.spacing.sm
|
|
@@ -4,10 +4,11 @@ import React, { useEffect, useMemo, useRef } from 'react';
|
|
|
4
4
|
import { Animated, PanResponder, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
5
|
import { fontFor, useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
|
|
6
6
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
7
|
+
const DEFAULT_SWIPE_DISMISS_THRESHOLD = 80;
|
|
8
|
+
const DEFAULT_SWIPE_VELOCITY_THRESHOLD = 0.5;
|
|
9
|
+
const DEFAULT_STACK_OFFSET = 8;
|
|
10
|
+
const DEFAULT_STACK_SCALE_STEP = 0.04;
|
|
11
|
+
const DEFAULT_AUTO_DISMISS_MS = 3000;
|
|
11
12
|
const Toast = ({
|
|
12
13
|
toast,
|
|
13
14
|
index,
|
|
@@ -23,6 +24,16 @@ const Toast = ({
|
|
|
23
24
|
const iconCircleBorderRadius = toastTokens?.iconCircleBorderRadius ?? 14;
|
|
24
25
|
const iconGlyphFontSize = toastTokens?.iconGlyphFontSize ?? 16;
|
|
25
26
|
const tintBarWidth = toastTokens?.tintBarWidth ?? 4;
|
|
27
|
+
const swipeDismissThreshold = toastTokens?.swipeDismissThreshold ?? DEFAULT_SWIPE_DISMISS_THRESHOLD;
|
|
28
|
+
const swipeVelocityThreshold = toastTokens?.swipeVelocityThreshold ?? DEFAULT_SWIPE_VELOCITY_THRESHOLD;
|
|
29
|
+
const stackOffset = toastTokens?.stackOffset ?? DEFAULT_STACK_OFFSET;
|
|
30
|
+
const stackScaleStep = toastTokens?.stackScaleStep ?? DEFAULT_STACK_SCALE_STEP;
|
|
31
|
+
const stackMinScale = toastTokens?.stackMinScale ?? 0.9;
|
|
32
|
+
const defaultDurationMs = toastTokens?.defaultDurationMs ?? DEFAULT_AUTO_DISMISS_MS;
|
|
33
|
+
const enableSwipeDismiss = toastTokens?.enableSwipeDismiss ?? true;
|
|
34
|
+
const enterSpringDamping = toastTokens?.enterSpringDamping ?? 18;
|
|
35
|
+
const enterSpringStiffness = toastTokens?.enterSpringStiffness ?? 180;
|
|
36
|
+
const enterSpringMass = toastTokens?.enterSpringMass ?? 1;
|
|
26
37
|
const enterFrom = position === 'top' ? -120 : 120;
|
|
27
38
|
const translateY = useRef(createAnimatedValue(enterFrom)).current;
|
|
28
39
|
const translateX = useRef(createAnimatedValue(0)).current;
|
|
@@ -48,16 +59,16 @@ const Toast = ({
|
|
|
48
59
|
useEffect(() => {
|
|
49
60
|
Animated.parallel([Animated.spring(translateY, {
|
|
50
61
|
toValue: 0,
|
|
51
|
-
damping:
|
|
52
|
-
stiffness:
|
|
53
|
-
mass:
|
|
62
|
+
damping: enterSpringDamping,
|
|
63
|
+
stiffness: enterSpringStiffness,
|
|
64
|
+
mass: enterSpringMass,
|
|
54
65
|
useNativeDriver: true
|
|
55
66
|
}), Animated.timing(opacity, {
|
|
56
67
|
toValue: 1,
|
|
57
68
|
duration: theme.motion.duration.fast,
|
|
58
69
|
useNativeDriver: true
|
|
59
70
|
})]).start();
|
|
60
|
-
const duration = toast.duration ??
|
|
71
|
+
const duration = toast.duration ?? defaultDurationMs;
|
|
61
72
|
if (duration > 0) {
|
|
62
73
|
const timer = setTimeout(() => dismiss(true), duration);
|
|
63
74
|
return () => clearTimeout(timer);
|
|
@@ -73,7 +84,7 @@ const Toast = ({
|
|
|
73
84
|
setNativeValue(opacity, fade);
|
|
74
85
|
},
|
|
75
86
|
onPanResponderRelease: (_evt, gesture) => {
|
|
76
|
-
if (Math.abs(gesture.dx) >
|
|
87
|
+
if (Math.abs(gesture.dx) > swipeDismissThreshold || Math.abs(gesture.vx) > swipeVelocityThreshold) {
|
|
77
88
|
const direction = gesture.dx >= 0 ? 1 : -1;
|
|
78
89
|
Animated.parallel([Animated.timing(translateX, {
|
|
79
90
|
toValue: direction * 500,
|
|
@@ -100,8 +111,8 @@ const Toast = ({
|
|
|
100
111
|
}),
|
|
101
112
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
102
113
|
[]);
|
|
103
|
-
const stackTranslate = position === 'top' ? index *
|
|
104
|
-
const stackScale = Math.max(1 - index *
|
|
114
|
+
const stackTranslate = position === 'top' ? index * stackOffset : -index * stackOffset;
|
|
115
|
+
const stackScale = Math.max(1 - index * stackScaleStep, stackMinScale);
|
|
105
116
|
const handleActionPress = () => {
|
|
106
117
|
toast.action?.onPress();
|
|
107
118
|
dismiss(true);
|
|
@@ -116,7 +127,7 @@ const Toast = ({
|
|
|
116
127
|
height: iconCircleSize,
|
|
117
128
|
borderRadius: iconCircleBorderRadius,
|
|
118
129
|
backgroundColor: tint + '22'
|
|
119
|
-
}],
|
|
130
|
+
}, toast.iconCircleStyle],
|
|
120
131
|
children: /*#__PURE__*/_jsx(Text, {
|
|
121
132
|
style: [styles.iconGlyph, {
|
|
122
133
|
color: tint,
|
|
@@ -129,7 +140,7 @@ const Toast = ({
|
|
|
129
140
|
};
|
|
130
141
|
const a11yLabel = toast.description ? `${toast.message}. ${toast.description}` : toast.message;
|
|
131
142
|
return /*#__PURE__*/_jsxs(Animated.View, {
|
|
132
|
-
...panResponder.panHandlers,
|
|
143
|
+
...(enableSwipeDismiss ? panResponder.panHandlers : {}),
|
|
133
144
|
accessibilityRole: "alert",
|
|
134
145
|
accessibilityLiveRegion: "assertive",
|
|
135
146
|
accessibilityLabel: a11yLabel,
|
|
@@ -147,7 +158,7 @@ const Toast = ({
|
|
|
147
158
|
}, {
|
|
148
159
|
scale: stackScale
|
|
149
160
|
}]
|
|
150
|
-
}, toast.style],
|
|
161
|
+
}, toast.style, toast.containerStyle],
|
|
151
162
|
children: [/*#__PURE__*/_jsx(View, {
|
|
152
163
|
style: [styles.tintBar, {
|
|
153
164
|
width: tintBarWidth,
|
|
@@ -162,7 +173,7 @@ const Toast = ({
|
|
|
162
173
|
color: theme.colors.text.primary,
|
|
163
174
|
fontSize: theme.typography.fontSize.base,
|
|
164
175
|
...fontFor(theme, 'semibold')
|
|
165
|
-
}, toast.textStyle],
|
|
176
|
+
}, toast.textStyle, toast.messageStyle],
|
|
166
177
|
numberOfLines: 2,
|
|
167
178
|
children: toast.message
|
|
168
179
|
}), toast.description ? /*#__PURE__*/_jsx(Text, {
|
|
@@ -181,7 +192,7 @@ const Toast = ({
|
|
|
181
192
|
pressed
|
|
182
193
|
}) => [styles.actionBtn, {
|
|
183
194
|
backgroundColor: pressed ? theme.colors.surface.pressed : 'transparent'
|
|
184
|
-
}],
|
|
195
|
+
}, toast.actionButtonStyle],
|
|
185
196
|
children: /*#__PURE__*/_jsx(Text, {
|
|
186
197
|
style: {
|
|
187
198
|
color: tint,
|