@webority-technologies/mobile 0.0.23 → 0.0.25

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 (171) hide show
  1. package/lib/commonjs/components/Accordion/Accordion.js +5 -5
  2. package/lib/commonjs/components/AnimatePresence/AnimatePresence.js +69 -0
  3. package/lib/commonjs/components/AnimatePresence/index.js +13 -0
  4. package/lib/commonjs/components/AppBar/AppBar.js +9 -6
  5. package/lib/commonjs/components/Autocomplete/Autocomplete.js +204 -0
  6. package/lib/commonjs/components/Autocomplete/index.js +13 -0
  7. package/lib/commonjs/components/Banner/Banner.js +12 -2
  8. package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +1 -1
  9. package/lib/commonjs/components/Card/Card.js +3 -3
  10. package/lib/commonjs/components/Checkbox/Checkbox.js +3 -2
  11. package/lib/commonjs/components/Chip/Chip.js +4 -2
  12. package/lib/commonjs/components/Confetti/Confetti.js +170 -0
  13. package/lib/commonjs/components/Confetti/index.js +13 -0
  14. package/lib/commonjs/components/DatePicker/DatePicker.js +23 -18
  15. package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +11 -9
  16. package/lib/commonjs/components/Dialog/Dialog.js +4 -2
  17. package/lib/commonjs/components/Drawer/Drawer.js +4 -2
  18. package/lib/commonjs/components/FieldBase/FieldBase.js +0 -2
  19. package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +10 -8
  20. package/lib/commonjs/components/IconButton/IconButton.js +176 -0
  21. package/lib/commonjs/components/IconButton/index.js +13 -0
  22. package/lib/commonjs/components/ImageGallery/ImageGallery.js +17 -15
  23. package/lib/commonjs/components/ListItem/ListItem.js +4 -3
  24. package/lib/commonjs/components/Modal/Modal.js +4 -4
  25. package/lib/commonjs/components/NumberInput/NumberInput.js +7 -5
  26. package/lib/commonjs/components/OTPInput/OTPInput.js +7 -7
  27. package/lib/commonjs/components/ProgressBar/ProgressBar.js +32 -4
  28. package/lib/commonjs/components/Radio/Radio.js +2 -3
  29. package/lib/commonjs/components/Rating/Rating.js +4 -3
  30. package/lib/commonjs/components/SearchBar/SearchBar.js +7 -4
  31. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +4 -3
  32. package/lib/commonjs/components/Select/Select.js +7 -4
  33. package/lib/commonjs/components/SlideToConfirm/SlideToConfirm.js +224 -0
  34. package/lib/commonjs/components/SlideToConfirm/index.js +13 -0
  35. package/lib/commonjs/components/Slider/Slider.js +228 -228
  36. package/lib/commonjs/components/Stepper/Stepper.js +6 -5
  37. package/lib/commonjs/components/Swipeable/Swipeable.js +8 -9
  38. package/lib/commonjs/components/Tabs/Tabs.js +4 -3
  39. package/lib/commonjs/components/TimePicker/TimePicker.js +14 -9
  40. package/lib/commonjs/components/index.js +149 -114
  41. package/lib/commonjs/hooks/usePressAnimation.js +0 -1
  42. package/lib/commonjs/utils/hapticUtils.js +11 -1
  43. package/lib/commonjs/utils/index.js +6 -0
  44. package/lib/module/components/Accordion/Accordion.js +6 -6
  45. package/lib/module/components/AnimatePresence/AnimatePresence.js +63 -0
  46. package/lib/module/components/AnimatePresence/index.js +4 -0
  47. package/lib/module/components/AppBar/AppBar.js +10 -7
  48. package/lib/module/components/Autocomplete/Autocomplete.js +199 -0
  49. package/lib/module/components/Autocomplete/index.js +4 -0
  50. package/lib/module/components/Banner/Banner.js +12 -2
  51. package/lib/module/components/BottomNavigation/BottomNavigation.js +1 -1
  52. package/lib/module/components/Card/Card.js +4 -4
  53. package/lib/module/components/Checkbox/Checkbox.js +4 -3
  54. package/lib/module/components/Chip/Chip.js +5 -3
  55. package/lib/module/components/Confetti/Confetti.js +166 -0
  56. package/lib/module/components/Confetti/index.js +4 -0
  57. package/lib/module/components/DatePicker/DatePicker.js +24 -19
  58. package/lib/module/components/DateRangePicker/DateRangePicker.js +12 -10
  59. package/lib/module/components/Dialog/Dialog.js +5 -3
  60. package/lib/module/components/Drawer/Drawer.js +5 -3
  61. package/lib/module/components/FieldBase/FieldBase.js +0 -2
  62. package/lib/module/components/FloatingActionButton/FloatingActionButton.js +11 -9
  63. package/lib/module/components/IconButton/IconButton.js +172 -0
  64. package/lib/module/components/IconButton/index.js +4 -0
  65. package/lib/module/components/ImageGallery/ImageGallery.js +18 -16
  66. package/lib/module/components/ListItem/ListItem.js +5 -4
  67. package/lib/module/components/Modal/Modal.js +5 -5
  68. package/lib/module/components/NumberInput/NumberInput.js +8 -6
  69. package/lib/module/components/OTPInput/OTPInput.js +8 -8
  70. package/lib/module/components/ProgressBar/ProgressBar.js +33 -5
  71. package/lib/module/components/Radio/Radio.js +3 -4
  72. package/lib/module/components/Rating/Rating.js +5 -4
  73. package/lib/module/components/SearchBar/SearchBar.js +8 -5
  74. package/lib/module/components/SegmentedControl/SegmentedControl.js +5 -4
  75. package/lib/module/components/Select/Select.js +8 -5
  76. package/lib/module/components/SlideToConfirm/SlideToConfirm.js +220 -0
  77. package/lib/module/components/SlideToConfirm/index.js +4 -0
  78. package/lib/module/components/Slider/Slider.js +231 -231
  79. package/lib/module/components/Stepper/Stepper.js +7 -6
  80. package/lib/module/components/Swipeable/Swipeable.js +9 -10
  81. package/lib/module/components/Tabs/Tabs.js +5 -4
  82. package/lib/module/components/TimePicker/TimePicker.js +15 -10
  83. package/lib/module/components/index.js +5 -0
  84. package/lib/module/hooks/usePressAnimation.js +0 -1
  85. package/lib/module/utils/hapticUtils.js +9 -0
  86. package/lib/module/utils/index.js +1 -1
  87. package/lib/typescript/commonjs/components/Accordion/Accordion.d.ts +3 -0
  88. package/lib/typescript/commonjs/components/AnimatePresence/AnimatePresence.d.ts +30 -0
  89. package/lib/typescript/commonjs/components/AnimatePresence/index.d.ts +3 -0
  90. package/lib/typescript/commonjs/components/AppBar/AppBar.d.ts +6 -0
  91. package/lib/typescript/commonjs/components/Autocomplete/Autocomplete.d.ts +53 -0
  92. package/lib/typescript/commonjs/components/Autocomplete/index.d.ts +3 -0
  93. package/lib/typescript/commonjs/components/Banner/Banner.d.ts +3 -0
  94. package/lib/typescript/commonjs/components/Card/Card.d.ts +3 -0
  95. package/lib/typescript/commonjs/components/Checkbox/Checkbox.d.ts +1 -0
  96. package/lib/typescript/commonjs/components/Chip/Chip.d.ts +3 -0
  97. package/lib/typescript/commonjs/components/Confetti/Confetti.d.ts +41 -0
  98. package/lib/typescript/commonjs/components/Confetti/index.d.ts +3 -0
  99. package/lib/typescript/commonjs/components/DatePicker/DatePicker.d.ts +3 -0
  100. package/lib/typescript/commonjs/components/DateRangePicker/DateRangePicker.d.ts +6 -0
  101. package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +3 -0
  102. package/lib/typescript/commonjs/components/Drawer/Drawer.d.ts +3 -0
  103. package/lib/typescript/commonjs/components/FloatingActionButton/FloatingActionButton.d.ts +5 -0
  104. package/lib/typescript/commonjs/components/IconButton/IconButton.d.ts +34 -0
  105. package/lib/typescript/commonjs/components/IconButton/index.d.ts +3 -0
  106. package/lib/typescript/commonjs/components/ImageGallery/ImageGallery.d.ts +6 -0
  107. package/lib/typescript/commonjs/components/ListItem/ListItem.d.ts +3 -0
  108. package/lib/typescript/commonjs/components/Modal/Modal.d.ts +6 -0
  109. package/lib/typescript/commonjs/components/NumberInput/NumberInput.d.ts +3 -0
  110. package/lib/typescript/commonjs/components/OTPInput/OTPInput.d.ts +6 -0
  111. package/lib/typescript/commonjs/components/ProgressBar/ProgressBar.d.ts +12 -0
  112. package/lib/typescript/commonjs/components/ProgressBar/index.d.ts +1 -1
  113. package/lib/typescript/commonjs/components/Rating/Rating.d.ts +6 -0
  114. package/lib/typescript/commonjs/components/SearchBar/SearchBar.d.ts +3 -0
  115. package/lib/typescript/commonjs/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  116. package/lib/typescript/commonjs/components/Select/Select.d.ts +6 -0
  117. package/lib/typescript/commonjs/components/SlideToConfirm/SlideToConfirm.d.ts +34 -0
  118. package/lib/typescript/commonjs/components/SlideToConfirm/index.d.ts +3 -0
  119. package/lib/typescript/commonjs/components/Slider/Slider.d.ts +3 -0
  120. package/lib/typescript/commonjs/components/Stepper/Stepper.d.ts +6 -0
  121. package/lib/typescript/commonjs/components/Swipeable/Swipeable.d.ts +3 -0
  122. package/lib/typescript/commonjs/components/Tabs/Tabs.d.ts +3 -0
  123. package/lib/typescript/commonjs/components/TimePicker/TimePicker.d.ts +3 -0
  124. package/lib/typescript/commonjs/components/index.d.ts +11 -1
  125. package/lib/typescript/commonjs/hooks/usePressAnimation.d.ts +1 -2
  126. package/lib/typescript/commonjs/theme/types.d.ts +2 -67
  127. package/lib/typescript/commonjs/utils/hapticUtils.d.ts +8 -0
  128. package/lib/typescript/commonjs/utils/index.d.ts +1 -1
  129. package/lib/typescript/module/components/Accordion/Accordion.d.ts +3 -0
  130. package/lib/typescript/module/components/AnimatePresence/AnimatePresence.d.ts +30 -0
  131. package/lib/typescript/module/components/AnimatePresence/index.d.ts +3 -0
  132. package/lib/typescript/module/components/AppBar/AppBar.d.ts +6 -0
  133. package/lib/typescript/module/components/Autocomplete/Autocomplete.d.ts +53 -0
  134. package/lib/typescript/module/components/Autocomplete/index.d.ts +3 -0
  135. package/lib/typescript/module/components/Banner/Banner.d.ts +3 -0
  136. package/lib/typescript/module/components/Card/Card.d.ts +3 -0
  137. package/lib/typescript/module/components/Checkbox/Checkbox.d.ts +1 -0
  138. package/lib/typescript/module/components/Chip/Chip.d.ts +3 -0
  139. package/lib/typescript/module/components/Confetti/Confetti.d.ts +41 -0
  140. package/lib/typescript/module/components/Confetti/index.d.ts +3 -0
  141. package/lib/typescript/module/components/DatePicker/DatePicker.d.ts +3 -0
  142. package/lib/typescript/module/components/DateRangePicker/DateRangePicker.d.ts +6 -0
  143. package/lib/typescript/module/components/Dialog/Dialog.d.ts +3 -0
  144. package/lib/typescript/module/components/Drawer/Drawer.d.ts +3 -0
  145. package/lib/typescript/module/components/FloatingActionButton/FloatingActionButton.d.ts +5 -0
  146. package/lib/typescript/module/components/IconButton/IconButton.d.ts +34 -0
  147. package/lib/typescript/module/components/IconButton/index.d.ts +3 -0
  148. package/lib/typescript/module/components/ImageGallery/ImageGallery.d.ts +6 -0
  149. package/lib/typescript/module/components/ListItem/ListItem.d.ts +3 -0
  150. package/lib/typescript/module/components/Modal/Modal.d.ts +6 -0
  151. package/lib/typescript/module/components/NumberInput/NumberInput.d.ts +3 -0
  152. package/lib/typescript/module/components/OTPInput/OTPInput.d.ts +6 -0
  153. package/lib/typescript/module/components/ProgressBar/ProgressBar.d.ts +12 -0
  154. package/lib/typescript/module/components/ProgressBar/index.d.ts +1 -1
  155. package/lib/typescript/module/components/Rating/Rating.d.ts +6 -0
  156. package/lib/typescript/module/components/SearchBar/SearchBar.d.ts +3 -0
  157. package/lib/typescript/module/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  158. package/lib/typescript/module/components/Select/Select.d.ts +6 -0
  159. package/lib/typescript/module/components/SlideToConfirm/SlideToConfirm.d.ts +34 -0
  160. package/lib/typescript/module/components/SlideToConfirm/index.d.ts +3 -0
  161. package/lib/typescript/module/components/Slider/Slider.d.ts +3 -0
  162. package/lib/typescript/module/components/Stepper/Stepper.d.ts +6 -0
  163. package/lib/typescript/module/components/Swipeable/Swipeable.d.ts +3 -0
  164. package/lib/typescript/module/components/Tabs/Tabs.d.ts +3 -0
  165. package/lib/typescript/module/components/TimePicker/TimePicker.d.ts +3 -0
  166. package/lib/typescript/module/components/index.d.ts +11 -1
  167. package/lib/typescript/module/hooks/usePressAnimation.d.ts +1 -2
  168. package/lib/typescript/module/theme/types.d.ts +2 -67
  169. package/lib/typescript/module/utils/hapticUtils.d.ts +8 -0
  170. package/lib/typescript/module/utils/index.d.ts +1 -1
  171. package/package.json +1 -1
@@ -3,7 +3,7 @@
3
3
  import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { Animated, Easing, LayoutAnimation, Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import { useTheme, createAnimatedValue } from "../../theme/index.js";
6
- import { triggerHaptic } from "../../utils/hapticUtils.js";
6
+ import { resolveHaptic, triggerHaptic } from "../../utils/hapticUtils.js";
7
7
  import { Skeleton } from "../Skeleton/index.js";
8
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  const AccordionGroupContext = /*#__PURE__*/createContext(null);
@@ -90,7 +90,8 @@ const Accordion = props => {
90
90
  contentWrapperStyle,
91
91
  containerStyle,
92
92
  testID,
93
- loading = false
93
+ loading = false,
94
+ haptic
94
95
  } = props;
95
96
  const theme = useTheme();
96
97
  const styles = useMemo(() => buildStyles(theme), [theme]);
@@ -137,9 +138,8 @@ const Accordion = props => {
137
138
  }, [measuredHeight]);
138
139
  const handlePress = useCallback(() => {
139
140
  if (disabled) return;
140
- if (theme.components.accordion?.pressHaptic ?? false) {
141
- triggerHaptic('selection');
142
- }
141
+ const h = resolveHaptic(haptic, 'selection');
142
+ if (h) triggerHaptic(h);
143
143
  if (group && id) {
144
144
  group.toggle(id);
145
145
  onChange?.(!expanded);
@@ -147,7 +147,7 @@ const Accordion = props => {
147
147
  }
148
148
  if (!isControlled) setInternalExpanded(!expanded);
149
149
  onChange?.(!expanded);
150
- }, [disabled, group, id, expanded, isControlled, onChange, theme.components.accordion]);
150
+ }, [disabled, group, id, expanded, isControlled, onChange, haptic]);
151
151
  const rotate = rotateAnim.interpolate({
152
152
  inputRange: [0, 1],
153
153
  outputRange: ['0deg', '180deg']
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import Animated, { FadeIn, FadeInDown, FadeInUp, FadeOut, FadeOutDown, FadeOutUp, ZoomIn, ZoomOut } from 'react-native-reanimated';
5
+ import { useTheme } from "../../theme/index.js";
6
+ import { useReducedMotion } from "../../hooks/index.js";
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ /**
9
+ * Animates a single child in on mount and out on unmount. Thin, theme-aware
10
+ * wrapper over Reanimated's `entering`/`exiting` — Reanimated keeps the view
11
+ * alive to play the exit, so the parent only toggles a condition. Honors the OS
12
+ * Reduce Motion setting (renders instantly when reduced).
13
+ *
14
+ * For animating items inside a list, use Reanimated's `itemLayoutAnimation`
15
+ * on `Animated.FlatList` instead — this wrapper targets single conditional nodes.
16
+ */
17
+ const AnimatePresence = ({
18
+ children,
19
+ preset = 'fade',
20
+ duration,
21
+ style,
22
+ testID
23
+ }) => {
24
+ const theme = useTheme();
25
+ const reduceMotion = useReducedMotion();
26
+ const visible = children !== null && children !== undefined && children !== false;
27
+ if (!visible) return null;
28
+ const dur = duration ?? theme.motion.duration.normal;
29
+ let entering;
30
+ let exiting;
31
+ if (!reduceMotion) {
32
+ switch (preset) {
33
+ case 'scale':
34
+ entering = ZoomIn.duration(dur);
35
+ exiting = ZoomOut.duration(dur);
36
+ break;
37
+ case 'slide-up':
38
+ entering = FadeInUp.duration(dur);
39
+ exiting = FadeOutDown.duration(dur);
40
+ break;
41
+ case 'slide-down':
42
+ entering = FadeInDown.duration(dur);
43
+ exiting = FadeOutUp.duration(dur);
44
+ break;
45
+ case 'fade':
46
+ default:
47
+ entering = FadeIn.duration(dur);
48
+ exiting = FadeOut.duration(dur);
49
+ break;
50
+ }
51
+ }
52
+ return /*#__PURE__*/_jsx(Animated.View, {
53
+ entering: entering,
54
+ exiting: exiting,
55
+ style: style,
56
+ testID: testID,
57
+ children: children
58
+ });
59
+ };
60
+ AnimatePresence.displayName = 'AnimatePresence';
61
+ export { AnimatePresence };
62
+ export default AnimatePresence;
63
+ //# sourceMappingURL=AnimatePresence.js.map
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { AnimatePresence } from "./AnimatePresence.js";
4
+ //# sourceMappingURL=index.js.map
@@ -5,7 +5,7 @@ import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
6
  import { useTheme } from "../../theme/index.js";
7
7
  import { usePressAnimation } from "../../hooks/usePressAnimation.js";
8
- import { triggerHaptic } from "../../utils/hapticUtils.js";
8
+ import { triggerHaptic, resolveHaptic } from "../../utils/hapticUtils.js";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  const variantSize = (theme, variant) => {
11
11
  switch (variant) {
@@ -36,7 +36,8 @@ const variantSize = (theme, variant) => {
36
36
  const ActionButton = ({
37
37
  action,
38
38
  side,
39
- badgeStyle
39
+ badgeStyle,
40
+ haptic
40
41
  }) => {
41
42
  const theme = useTheme();
42
43
  const {
@@ -48,9 +49,8 @@ const ActionButton = ({
48
49
  });
49
50
  const styles = useMemo(() => buildActionStyles(theme), [theme]);
50
51
  const onPress = () => {
51
- if (theme.components.appBar?.pressHaptic ?? false) {
52
- triggerHaptic('selection');
53
- }
52
+ const h = resolveHaptic(haptic, 'selection');
53
+ if (h) triggerHaptic(h);
54
54
  action.onPress();
55
55
  };
56
56
  const badgeValue = action.badge;
@@ -108,6 +108,7 @@ const AppBar = /*#__PURE__*/forwardRef((props, ref) => {
108
108
  titleStyle,
109
109
  subtitleStyle,
110
110
  badgeStyle,
111
+ haptic,
111
112
  testID
112
113
  } = props;
113
114
  const theme = useTheme();
@@ -225,7 +226,8 @@ const AppBar = /*#__PURE__*/forwardRef((props, ref) => {
225
226
  style: styles.sideSlot,
226
227
  children: leftAction ? /*#__PURE__*/_jsx(ActionButton, {
227
228
  action: leftAction,
228
- side: "left"
229
+ side: "left",
230
+ haptic: haptic
229
231
  }) : null
230
232
  }), /*#__PURE__*/_jsx(View, {
231
233
  style: [styles.center, titleAlignment === 'center' ? styles.centerAligned : styles.centerLeft],
@@ -235,7 +237,8 @@ const AppBar = /*#__PURE__*/forwardRef((props, ref) => {
235
237
  children: rightActions?.map((action, index) => /*#__PURE__*/_jsx(ActionButton, {
236
238
  action: action,
237
239
  side: "right",
238
- badgeStyle: badgeStyle
240
+ badgeStyle: badgeStyle,
241
+ haptic: haptic
239
242
  }, `appbar-right-${index}`))
240
243
  })]
241
244
  })]
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+
3
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
4
+ import { Keyboard, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
5
+ import { useTheme } from "../../theme/index.js";
6
+ import { resolveHaptic, triggerHaptic } from "../../utils/index.js";
7
+ import { useControllableState } from "../../hooks/index.js";
8
+ import { Input } from "../Input/index.js";
9
+ import { Spinner } from "../Spinner/index.js";
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ const defaultGetLabel = o => typeof o === 'string' ? o : String(o);
12
+ function Autocomplete(props) {
13
+ const {
14
+ options,
15
+ value,
16
+ defaultValue,
17
+ onChangeText,
18
+ onSelect,
19
+ getOptionLabel,
20
+ getOptionKey,
21
+ filter,
22
+ minChars = 1,
23
+ maxResults = 8,
24
+ emptyText = 'No matches',
25
+ loading = false,
26
+ filterMode = 'client',
27
+ loadingText = 'Searching…',
28
+ placeholder,
29
+ label,
30
+ error,
31
+ helperText,
32
+ disabled = false,
33
+ size = 'md',
34
+ variant,
35
+ haptic,
36
+ style,
37
+ listStyle,
38
+ optionTextStyle,
39
+ testID
40
+ } = props;
41
+ const theme = useTheme();
42
+ const styles = useMemo(() => buildStyles(theme), [theme]);
43
+ const [text, setText] = useControllableState({
44
+ value,
45
+ defaultValue: defaultValue ?? '',
46
+ onChange: onChangeText
47
+ });
48
+ const [focused, setFocused] = useState(false);
49
+ const [fieldHeight, setFieldHeight] = useState(0);
50
+ const blurTimer = useRef(null);
51
+ const labelOf = useCallback(o => getOptionLabel ? getOptionLabel(o) : defaultGetLabel(o), [getOptionLabel]);
52
+ const filtered = useMemo(() => {
53
+ // Server-side search: trust the provided options, don't re-filter them away.
54
+ if (filterMode === 'none') return options.slice(0, maxResults);
55
+ const q = text.trim();
56
+ if (q.length < minChars) return [];
57
+ const lower = q.toLowerCase();
58
+ const match = filter ? o => filter(o, q) : o => labelOf(o).toLowerCase().includes(lower);
59
+ return options.filter(match).slice(0, maxResults);
60
+ }, [options, text, minChars, maxResults, filter, labelOf, filterMode]);
61
+ const showList = focused && (loading || text.trim().length >= minChars);
62
+ const handleSelect = useCallback(o => {
63
+ const h = resolveHaptic(haptic, 'selection');
64
+ if (h) triggerHaptic(h);
65
+ if (blurTimer.current) clearTimeout(blurTimer.current);
66
+ setText(labelOf(o));
67
+ setFocused(false);
68
+ Keyboard.dismiss();
69
+ onSelect(o);
70
+ }, [haptic, setText, labelOf, onSelect]);
71
+ React.useEffect(() => () => {
72
+ if (blurTimer.current) clearTimeout(blurTimer.current);
73
+ }, []);
74
+ const onFieldLayout = useCallback(e => {
75
+ setFieldHeight(e.nativeEvent.layout.height);
76
+ }, []);
77
+ return /*#__PURE__*/_jsxs(View, {
78
+ style: [styles.container, style],
79
+ testID: testID,
80
+ children: [/*#__PURE__*/_jsx(View, {
81
+ onLayout: onFieldLayout,
82
+ children: /*#__PURE__*/_jsx(Input, {
83
+ value: text,
84
+ onChangeText: setText,
85
+ onFocus: () => {
86
+ if (blurTimer.current) clearTimeout(blurTimer.current);
87
+ setFocused(true);
88
+ },
89
+ onBlur: () => {
90
+ blurTimer.current = setTimeout(() => setFocused(false), 120);
91
+ },
92
+ placeholder: placeholder,
93
+ label: label,
94
+ error: error,
95
+ helperText: helperText,
96
+ editable: !disabled,
97
+ size: size,
98
+ variant: variant,
99
+ autoCorrect: false,
100
+ autoCapitalize: "none"
101
+ })
102
+ }), showList ? /*#__PURE__*/_jsx(View, {
103
+ style: [styles.list, {
104
+ top: fieldHeight,
105
+ backgroundColor: theme.colors.background.elevated,
106
+ borderColor: theme.colors.border.primary,
107
+ borderRadius: theme.radius.md,
108
+ ...theme.shadows.lg
109
+ }, listStyle],
110
+ children: loading ? /*#__PURE__*/_jsxs(View, {
111
+ style: styles.loadingRow,
112
+ children: [/*#__PURE__*/_jsx(Spinner, {
113
+ size: "sm"
114
+ }), /*#__PURE__*/_jsx(Text, {
115
+ style: [styles.loadingText, {
116
+ color: theme.colors.text.secondary,
117
+ fontSize: theme.typography.fontSize.sm
118
+ }],
119
+ children: loadingText
120
+ })]
121
+ }) : filtered.length === 0 ? /*#__PURE__*/_jsx(Text, {
122
+ style: [styles.empty, {
123
+ color: theme.colors.text.tertiary,
124
+ fontSize: theme.typography.fontSize.sm
125
+ }],
126
+ children: emptyText
127
+ }) : /*#__PURE__*/_jsx(ScrollView, {
128
+ keyboardShouldPersistTaps: "handled",
129
+ style: styles.scroll,
130
+ children: filtered.map((o, i) => /*#__PURE__*/_jsx(Pressable, {
131
+ onPress: () => handleSelect(o),
132
+ android_ripple: {
133
+ color: theme.colors.surface.pressed
134
+ },
135
+ style: ({
136
+ pressed
137
+ }) => [styles.option, {
138
+ paddingHorizontal: theme.spacing.md,
139
+ paddingVertical: theme.spacing.sm,
140
+ backgroundColor: pressed ? theme.colors.surface.pressed : 'transparent'
141
+ }],
142
+ accessibilityRole: "button",
143
+ accessibilityLabel: labelOf(o),
144
+ children: /*#__PURE__*/_jsx(Text, {
145
+ style: [styles.optionText, {
146
+ color: theme.colors.text.primary,
147
+ fontSize: theme.typography.fontSize.base
148
+ }, optionTextStyle],
149
+ numberOfLines: 1,
150
+ children: labelOf(o)
151
+ })
152
+ }, getOptionKey ? getOptionKey(o) : `${labelOf(o)}-${i}`))
153
+ })
154
+ }) : null]
155
+ });
156
+ }
157
+ Autocomplete.displayName = 'Autocomplete';
158
+ const buildStyles = theme => StyleSheet.create({
159
+ container: {
160
+ width: '100%',
161
+ position: 'relative',
162
+ zIndex: 10
163
+ },
164
+ list: {
165
+ position: 'absolute',
166
+ left: 0,
167
+ right: 0,
168
+ borderWidth: StyleSheet.hairlineWidth,
169
+ overflow: 'hidden',
170
+ zIndex: 20,
171
+ maxHeight: 240
172
+ },
173
+ scroll: {
174
+ maxHeight: 240
175
+ },
176
+ option: {
177
+ width: '100%'
178
+ },
179
+ optionText: {
180
+ includeFontPadding: false
181
+ },
182
+ empty: {
183
+ padding: theme.spacing.md,
184
+ textAlign: 'center',
185
+ includeFontPadding: false
186
+ },
187
+ loadingRow: {
188
+ flexDirection: 'row',
189
+ alignItems: 'center',
190
+ gap: theme.spacing.sm,
191
+ padding: theme.spacing.md
192
+ },
193
+ loadingText: {
194
+ includeFontPadding: false
195
+ }
196
+ });
197
+ export { Autocomplete };
198
+ export default Autocomplete;
199
+ //# sourceMappingURL=Autocomplete.js.map
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { Autocomplete } from "./Autocomplete.js";
4
+ //# sourceMappingURL=index.js.map
@@ -3,6 +3,7 @@
3
3
  import React, { forwardRef, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import { useTheme, createAnimatedValue } from "../../theme/index.js";
6
+ import { resolveHaptic, triggerHaptic } from "../../utils/hapticUtils.js";
6
7
  import { Skeleton, SkeletonText } from "../Skeleton/index.js";
7
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
9
  const Banner = /*#__PURE__*/forwardRef((props, ref) => {
@@ -14,6 +15,7 @@ const Banner = /*#__PURE__*/forwardRef((props, ref) => {
14
15
  actions,
15
16
  dismissible = false,
16
17
  onDismiss,
18
+ haptic,
17
19
  visible = true,
18
20
  animateMount = true,
19
21
  loading = false,
@@ -143,7 +145,11 @@ const Banner = /*#__PURE__*/forwardRef((props, ref) => {
143
145
  }), dismissible ? /*#__PURE__*/_jsx(Pressable, {
144
146
  accessibilityRole: "button",
145
147
  accessibilityLabel: "Dismiss banner",
146
- onPress: onDismiss,
148
+ onPress: () => {
149
+ const h = resolveHaptic(haptic, 'selection');
150
+ if (h) triggerHaptic(h);
151
+ onDismiss?.();
152
+ },
147
153
  hitSlop: 8,
148
154
  style: ({
149
155
  pressed
@@ -168,7 +174,11 @@ const Banner = /*#__PURE__*/forwardRef((props, ref) => {
168
174
  return /*#__PURE__*/_jsx(Pressable, {
169
175
  accessibilityRole: "button",
170
176
  accessibilityLabel: action.label,
171
- onPress: action.onPress,
177
+ onPress: () => {
178
+ const h = resolveHaptic(haptic, 'selection');
179
+ if (h) triggerHaptic(h);
180
+ action.onPress();
181
+ },
172
182
  style: ({
173
183
  pressed
174
184
  }) => [styles.actionBtn, {
@@ -154,7 +154,7 @@ const BottomNavigation = /*#__PURE__*/forwardRef((props, ref) => {
154
154
  translateX: indicatorTranslateX
155
155
  }]
156
156
  }, indicatorStyle]
157
- }) : null, tabs.map((tab, index) => {
157
+ }) : null, tabs.map(tab => {
158
158
  const isActive = tab.key === activeTab;
159
159
  const color = isActive ? theme.colors.primary : theme.colors.text.tertiary;
160
160
  const renderIcon = isActive && tab.activeIcon ? tab.activeIcon : tab.icon;
@@ -4,7 +4,7 @@ import React, { forwardRef, useMemo } from 'react';
4
4
  import { Animated, Image, Pressable, StyleSheet, View } from 'react-native';
5
5
  import { Gradient, useTheme } from "../../theme/index.js";
6
6
  import { usePressAnimation } from "../../hooks/usePressAnimation.js";
7
- import { triggerHaptic } from "../../utils/hapticUtils.js";
7
+ import { resolveHaptic, triggerHaptic } from "../../utils/hapticUtils.js";
8
8
  import { Skeleton, SkeletonText } from "../Skeleton/index.js";
9
9
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  const paddingMap = {
@@ -31,6 +31,7 @@ const Card = /*#__PURE__*/forwardRef((props, ref) => {
31
31
  loading = false,
32
32
  gradient,
33
33
  onPress,
34
+ haptic,
34
35
  accessibilityLabel,
35
36
  accessibilityHint,
36
37
  accessibilityRole,
@@ -150,9 +151,8 @@ const Card = /*#__PURE__*/forwardRef((props, ref) => {
150
151
  let rendered;
151
152
  if (isInteractive) {
152
153
  const handlePress = event => {
153
- if (theme.components.card?.pressHaptic ?? false) {
154
- triggerHaptic('selection');
155
- }
154
+ const h = resolveHaptic(haptic, 'selection');
155
+ if (h) triggerHaptic(h);
156
156
  onPress?.(event);
157
157
  };
158
158
  rendered = /*#__PURE__*/_jsx(Animated.View, {
@@ -4,7 +4,7 @@ import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
4
4
  import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import { useTheme, createAnimatedValue } from "../../theme/index.js";
6
6
  import { useControllableState } from "../../hooks/index.js";
7
- import { triggerHaptic } from "../../utils/hapticUtils.js";
7
+ import { triggerHaptic, resolveHaptic } from "../../utils/hapticUtils.js";
8
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  const sizeMap = {
10
10
  sm: 16,
@@ -35,7 +35,7 @@ const Checkbox = /*#__PURE__*/forwardRef((props, ref) => {
35
35
  size = 'md',
36
36
  tone = 'primary',
37
37
  accessibilityLabel,
38
- haptic = 'selection',
38
+ haptic,
39
39
  style,
40
40
  boxStyle,
41
41
  checkIconStyle,
@@ -75,7 +75,8 @@ const Checkbox = /*#__PURE__*/forwardRef((props, ref) => {
75
75
  });
76
76
  const handlePress = event => {
77
77
  if (disabled) return;
78
- if (haptic !== false && theme.components.checkbox?.pressHaptic) triggerHaptic(haptic);
78
+ const h = resolveHaptic(haptic, 'selection');
79
+ if (h) triggerHaptic(h);
79
80
  setCurrent(!current);
80
81
  rest.onPressOut?.(event);
81
82
  };
@@ -4,7 +4,7 @@ import React, { forwardRef, useMemo } from 'react';
4
4
  import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import { fontFor, useTheme } from "../../theme/index.js";
6
6
  import { usePressAnimation } from "../../hooks/usePressAnimation.js";
7
- import { triggerHaptic } from "../../utils/hapticUtils.js";
7
+ import { resolveHaptic, triggerHaptic } from "../../utils/hapticUtils.js";
8
8
  import { Skeleton } from "../Skeleton/index.js";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  const toneFor = (theme, tone) => {
@@ -99,6 +99,7 @@ const Chip = /*#__PURE__*/forwardRef((props, ref) => {
99
99
  disabled = false,
100
100
  loading = false,
101
101
  accessibilityLabel,
102
+ haptic,
102
103
  style,
103
104
  textStyle,
104
105
  containerStyle,
@@ -145,12 +146,13 @@ const Chip = /*#__PURE__*/forwardRef((props, ref) => {
145
146
  const borderWidth = isFilled ? 0 : theme.colors.border.width;
146
147
  const handlePress = () => {
147
148
  if (!isPressable) return;
148
- if (theme.components.chip?.pressHaptic) triggerHaptic('selection');
149
+ const h = resolveHaptic(haptic, 'selection');
150
+ if (h) triggerHaptic(h);
149
151
  onPress?.();
150
152
  };
151
153
  const handleClose = () => {
152
154
  if (disabled) return;
153
- if (theme.components.chip?.closeHaptic) triggerHaptic('impactLight');
155
+ if (haptic !== false) triggerHaptic('impactLight');
154
156
  onClose?.();
155
157
  };
156
158
  const a11yLabel = accessibilityLabel ?? label;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+
3
+ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react';
4
+ import { StyleSheet, View, useWindowDimensions } from 'react-native';
5
+ import Animated, { Easing, cancelAnimation, runOnJS, useAnimatedStyle, useSharedValue, withRepeat, withTiming } from 'react-native-reanimated';
6
+ import { useTheme } from "../../theme/index.js";
7
+ import { useReducedMotion } from "../../hooks/index.js";
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ const TAU = Math.PI * 2;
10
+ const rand = (min, max) => min + Math.random() * (max - min);
11
+ const buildPieces = (count, colors, mode, baseSize) => Array.from({
12
+ length: count
13
+ }, (_, i) => {
14
+ const isCannon = mode === 'cannon';
15
+ return {
16
+ color: colors[i % colors.length] ?? colors[0],
17
+ size: baseSize * rand(0.6, 1.4),
18
+ isCircle: Math.random() < 0.35,
19
+ baseXFrac: isCannon ? 0.5 : Math.random(),
20
+ vxFrac: isCannon ? rand(-0.7, 0.7) : rand(-0.15, 0.15),
21
+ vy0Frac: isCannon ? rand(-1.5, -1.0) : rand(0, 0.15),
22
+ rotations: rand(1, 5),
23
+ rotateDir: Math.random() < 0.5 ? 1 : -1,
24
+ swayAmp: rand(8, 28),
25
+ swayFreq: rand(1, 3),
26
+ flutterFreq: rand(2, 5)
27
+ };
28
+ });
29
+ const ConfettiPiece = ({
30
+ piece,
31
+ progress,
32
+ width,
33
+ height,
34
+ originX,
35
+ originY,
36
+ mode,
37
+ fadeOut
38
+ }) => {
39
+ const animStyle = useAnimatedStyle(() => {
40
+ const t = progress.value;
41
+ const startX = mode === 'cannon' ? originX : piece.baseXFrac * width;
42
+ const startY = mode === 'cannon' ? originY : -piece.size * 2;
43
+ const gravity = height * (mode === 'cannon' ? 1.8 : 1.5);
44
+ const x = startX + piece.vxFrac * width * t + Math.sin(t * piece.swayFreq * TAU) * piece.swayAmp;
45
+ const y = startY + piece.vy0Frac * height * t + gravity * t * t;
46
+ const rotate = piece.rotateDir * piece.rotations * 360 * t;
47
+ // Paper-flutter: oscillate scaleX so pieces read as thin spinning paper.
48
+ const flutter = 0.35 + 0.65 * Math.abs(Math.cos(t * piece.flutterFreq * TAU));
49
+ const opacity = fadeOut ? Math.max(0, 1 - Math.max(0, t - 0.8) / 0.2) : 1;
50
+ return {
51
+ opacity,
52
+ transform: [{
53
+ translateX: x
54
+ }, {
55
+ translateY: y
56
+ }, {
57
+ rotate: `${rotate}deg`
58
+ }, {
59
+ scaleX: flutter
60
+ }]
61
+ };
62
+ });
63
+ return /*#__PURE__*/_jsx(Animated.View, {
64
+ style: [{
65
+ position: 'absolute',
66
+ width: piece.size,
67
+ height: piece.isCircle ? piece.size : piece.size * 0.5,
68
+ borderRadius: piece.isCircle ? piece.size / 2 : 1,
69
+ backgroundColor: piece.color
70
+ }, animStyle]
71
+ });
72
+ };
73
+ const Confetti = /*#__PURE__*/forwardRef(({
74
+ count = 80,
75
+ colors,
76
+ mode = 'rain',
77
+ origin,
78
+ duration = 2800,
79
+ fadeOut = true,
80
+ autoStart = false,
81
+ recycle = false,
82
+ size = 10,
83
+ onComplete,
84
+ style,
85
+ testID
86
+ }, ref) => {
87
+ const theme = useTheme();
88
+ const reduceMotion = useReducedMotion();
89
+ const window = useWindowDimensions();
90
+ const [layout, setLayout] = useState({
91
+ width: window.width,
92
+ height: window.height
93
+ });
94
+ const [active, setActive] = useState(false);
95
+ const [pieces, setPieces] = useState([]);
96
+ const palette = useMemo(() => colors ?? [theme.colors.primary, theme.colors.secondary, theme.colors.success, theme.colors.warning, theme.colors.error, theme.colors.info], [colors, theme.colors]);
97
+ const progress = useSharedValue(0);
98
+ const finish = useCallback(() => {
99
+ setActive(false);
100
+ onComplete?.();
101
+ }, [onComplete]);
102
+ const start = useCallback(() => {
103
+ if (reduceMotion) {
104
+ onComplete?.();
105
+ return;
106
+ }
107
+ cancelAnimation(progress);
108
+ progress.value = 0;
109
+ setPieces(buildPieces(count, palette, mode, size));
110
+ setActive(true);
111
+ const tween = withTiming(1, {
112
+ duration,
113
+ easing: Easing.linear
114
+ }, finished => {
115
+ 'worklet';
116
+
117
+ if (finished && !recycle) runOnJS(finish)();
118
+ });
119
+ progress.value = recycle ? withRepeat(tween, -1, false) : tween;
120
+ }, [reduceMotion, progress, duration, recycle, finish, onComplete, count, palette, mode, size]);
121
+ const stop = useCallback(() => {
122
+ cancelAnimation(progress);
123
+ setActive(false);
124
+ }, [progress]);
125
+ useImperativeHandle(ref, () => ({
126
+ start,
127
+ stop
128
+ }), [start, stop]);
129
+ useEffect(() => {
130
+ if (autoStart) start();
131
+ return () => cancelAnimation(progress);
132
+ // eslint-disable-next-line react-hooks/exhaustive-deps
133
+ }, []);
134
+ const onLayout = useCallback(e => {
135
+ const {
136
+ width,
137
+ height
138
+ } = e.nativeEvent.layout;
139
+ if (width > 0 && height > 0) setLayout({
140
+ width,
141
+ height
142
+ });
143
+ }, []);
144
+ const originX = origin?.x ?? layout.width / 2;
145
+ const originY = origin?.y ?? layout.height;
146
+ return /*#__PURE__*/_jsx(View, {
147
+ style: [StyleSheet.absoluteFill, style],
148
+ pointerEvents: "none",
149
+ onLayout: onLayout,
150
+ testID: testID,
151
+ children: active ? pieces.map((piece, i) => /*#__PURE__*/_jsx(ConfettiPiece, {
152
+ piece: piece,
153
+ progress: progress,
154
+ width: layout.width,
155
+ height: layout.height,
156
+ originX: originX,
157
+ originY: originY,
158
+ mode: mode,
159
+ fadeOut: fadeOut
160
+ }, i)) : null
161
+ });
162
+ });
163
+ Confetti.displayName = 'Confetti';
164
+ export { Confetti };
165
+ export default Confetti;
166
+ //# sourceMappingURL=Confetti.js.map
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { Confetti } from "./Confetti.js";
4
+ //# sourceMappingURL=index.js.map