@webority-technologies/mobile 0.0.23 → 0.0.24

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 (125) 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/Banner/Banner.js +12 -2
  6. package/lib/commonjs/components/Card/Card.js +3 -3
  7. package/lib/commonjs/components/Checkbox/Checkbox.js +3 -2
  8. package/lib/commonjs/components/Chip/Chip.js +4 -2
  9. package/lib/commonjs/components/DatePicker/DatePicker.js +23 -18
  10. package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +11 -9
  11. package/lib/commonjs/components/Dialog/Dialog.js +4 -2
  12. package/lib/commonjs/components/Drawer/Drawer.js +4 -2
  13. package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +10 -8
  14. package/lib/commonjs/components/ImageGallery/ImageGallery.js +17 -15
  15. package/lib/commonjs/components/ListItem/ListItem.js +4 -3
  16. package/lib/commonjs/components/Modal/Modal.js +4 -3
  17. package/lib/commonjs/components/NumberInput/NumberInput.js +7 -5
  18. package/lib/commonjs/components/OTPInput/OTPInput.js +7 -7
  19. package/lib/commonjs/components/Radio/Radio.js +2 -3
  20. package/lib/commonjs/components/Rating/Rating.js +4 -3
  21. package/lib/commonjs/components/SearchBar/SearchBar.js +7 -4
  22. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +4 -3
  23. package/lib/commonjs/components/Select/Select.js +7 -4
  24. package/lib/commonjs/components/Slider/Slider.js +228 -228
  25. package/lib/commonjs/components/Stepper/Stepper.js +6 -5
  26. package/lib/commonjs/components/Swipeable/Swipeable.js +8 -9
  27. package/lib/commonjs/components/Tabs/Tabs.js +4 -3
  28. package/lib/commonjs/components/TimePicker/TimePicker.js +14 -9
  29. package/lib/commonjs/components/index.js +121 -114
  30. package/lib/commonjs/utils/hapticUtils.js +11 -1
  31. package/lib/commonjs/utils/index.js +6 -0
  32. package/lib/module/components/Accordion/Accordion.js +6 -6
  33. package/lib/module/components/AnimatePresence/AnimatePresence.js +63 -0
  34. package/lib/module/components/AnimatePresence/index.js +4 -0
  35. package/lib/module/components/AppBar/AppBar.js +10 -7
  36. package/lib/module/components/Banner/Banner.js +12 -2
  37. package/lib/module/components/Card/Card.js +4 -4
  38. package/lib/module/components/Checkbox/Checkbox.js +4 -3
  39. package/lib/module/components/Chip/Chip.js +5 -3
  40. package/lib/module/components/DatePicker/DatePicker.js +24 -19
  41. package/lib/module/components/DateRangePicker/DateRangePicker.js +12 -10
  42. package/lib/module/components/Dialog/Dialog.js +5 -3
  43. package/lib/module/components/Drawer/Drawer.js +5 -3
  44. package/lib/module/components/FloatingActionButton/FloatingActionButton.js +11 -9
  45. package/lib/module/components/ImageGallery/ImageGallery.js +18 -16
  46. package/lib/module/components/ListItem/ListItem.js +5 -4
  47. package/lib/module/components/Modal/Modal.js +5 -4
  48. package/lib/module/components/NumberInput/NumberInput.js +8 -6
  49. package/lib/module/components/OTPInput/OTPInput.js +8 -8
  50. package/lib/module/components/Radio/Radio.js +3 -4
  51. package/lib/module/components/Rating/Rating.js +5 -4
  52. package/lib/module/components/SearchBar/SearchBar.js +8 -5
  53. package/lib/module/components/SegmentedControl/SegmentedControl.js +5 -4
  54. package/lib/module/components/Select/Select.js +8 -5
  55. package/lib/module/components/Slider/Slider.js +231 -231
  56. package/lib/module/components/Stepper/Stepper.js +7 -6
  57. package/lib/module/components/Swipeable/Swipeable.js +9 -10
  58. package/lib/module/components/Tabs/Tabs.js +5 -4
  59. package/lib/module/components/TimePicker/TimePicker.js +15 -10
  60. package/lib/module/components/index.js +1 -0
  61. package/lib/module/utils/hapticUtils.js +9 -0
  62. package/lib/module/utils/index.js +1 -1
  63. package/lib/typescript/commonjs/components/Accordion/Accordion.d.ts +3 -0
  64. package/lib/typescript/commonjs/components/AnimatePresence/AnimatePresence.d.ts +30 -0
  65. package/lib/typescript/commonjs/components/AnimatePresence/index.d.ts +3 -0
  66. package/lib/typescript/commonjs/components/AppBar/AppBar.d.ts +6 -0
  67. package/lib/typescript/commonjs/components/Banner/Banner.d.ts +3 -0
  68. package/lib/typescript/commonjs/components/Card/Card.d.ts +3 -0
  69. package/lib/typescript/commonjs/components/Checkbox/Checkbox.d.ts +1 -0
  70. package/lib/typescript/commonjs/components/Chip/Chip.d.ts +3 -0
  71. package/lib/typescript/commonjs/components/DatePicker/DatePicker.d.ts +3 -0
  72. package/lib/typescript/commonjs/components/DateRangePicker/DateRangePicker.d.ts +6 -0
  73. package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +3 -0
  74. package/lib/typescript/commonjs/components/Drawer/Drawer.d.ts +3 -0
  75. package/lib/typescript/commonjs/components/FloatingActionButton/FloatingActionButton.d.ts +5 -0
  76. package/lib/typescript/commonjs/components/ImageGallery/ImageGallery.d.ts +6 -0
  77. package/lib/typescript/commonjs/components/ListItem/ListItem.d.ts +3 -0
  78. package/lib/typescript/commonjs/components/Modal/Modal.d.ts +6 -0
  79. package/lib/typescript/commonjs/components/NumberInput/NumberInput.d.ts +3 -0
  80. package/lib/typescript/commonjs/components/OTPInput/OTPInput.d.ts +6 -0
  81. package/lib/typescript/commonjs/components/Rating/Rating.d.ts +6 -0
  82. package/lib/typescript/commonjs/components/SearchBar/SearchBar.d.ts +3 -0
  83. package/lib/typescript/commonjs/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  84. package/lib/typescript/commonjs/components/Select/Select.d.ts +6 -0
  85. package/lib/typescript/commonjs/components/Slider/Slider.d.ts +3 -0
  86. package/lib/typescript/commonjs/components/Stepper/Stepper.d.ts +6 -0
  87. package/lib/typescript/commonjs/components/Swipeable/Swipeable.d.ts +3 -0
  88. package/lib/typescript/commonjs/components/Tabs/Tabs.d.ts +3 -0
  89. package/lib/typescript/commonjs/components/TimePicker/TimePicker.d.ts +3 -0
  90. package/lib/typescript/commonjs/components/index.d.ts +2 -0
  91. package/lib/typescript/commonjs/theme/types.d.ts +2 -67
  92. package/lib/typescript/commonjs/utils/hapticUtils.d.ts +8 -0
  93. package/lib/typescript/commonjs/utils/index.d.ts +1 -1
  94. package/lib/typescript/module/components/Accordion/Accordion.d.ts +3 -0
  95. package/lib/typescript/module/components/AnimatePresence/AnimatePresence.d.ts +30 -0
  96. package/lib/typescript/module/components/AnimatePresence/index.d.ts +3 -0
  97. package/lib/typescript/module/components/AppBar/AppBar.d.ts +6 -0
  98. package/lib/typescript/module/components/Banner/Banner.d.ts +3 -0
  99. package/lib/typescript/module/components/Card/Card.d.ts +3 -0
  100. package/lib/typescript/module/components/Checkbox/Checkbox.d.ts +1 -0
  101. package/lib/typescript/module/components/Chip/Chip.d.ts +3 -0
  102. package/lib/typescript/module/components/DatePicker/DatePicker.d.ts +3 -0
  103. package/lib/typescript/module/components/DateRangePicker/DateRangePicker.d.ts +6 -0
  104. package/lib/typescript/module/components/Dialog/Dialog.d.ts +3 -0
  105. package/lib/typescript/module/components/Drawer/Drawer.d.ts +3 -0
  106. package/lib/typescript/module/components/FloatingActionButton/FloatingActionButton.d.ts +5 -0
  107. package/lib/typescript/module/components/ImageGallery/ImageGallery.d.ts +6 -0
  108. package/lib/typescript/module/components/ListItem/ListItem.d.ts +3 -0
  109. package/lib/typescript/module/components/Modal/Modal.d.ts +6 -0
  110. package/lib/typescript/module/components/NumberInput/NumberInput.d.ts +3 -0
  111. package/lib/typescript/module/components/OTPInput/OTPInput.d.ts +6 -0
  112. package/lib/typescript/module/components/Rating/Rating.d.ts +6 -0
  113. package/lib/typescript/module/components/SearchBar/SearchBar.d.ts +3 -0
  114. package/lib/typescript/module/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  115. package/lib/typescript/module/components/Select/Select.d.ts +6 -0
  116. package/lib/typescript/module/components/Slider/Slider.d.ts +3 -0
  117. package/lib/typescript/module/components/Stepper/Stepper.d.ts +6 -0
  118. package/lib/typescript/module/components/Swipeable/Swipeable.d.ts +3 -0
  119. package/lib/typescript/module/components/Tabs/Tabs.d.ts +3 -0
  120. package/lib/typescript/module/components/TimePicker/TimePicker.d.ts +3 -0
  121. package/lib/typescript/module/components/index.d.ts +2 -0
  122. package/lib/typescript/module/theme/types.d.ts +2 -67
  123. package/lib/typescript/module/utils/hapticUtils.d.ts +8 -0
  124. package/lib/typescript/module/utils/index.d.ts +1 -1
  125. package/package.json +1 -1
@@ -26,7 +26,7 @@ import Animated, { runOnJS, useAnimatedStyle, useSharedValue, withSpring, withTi
26
26
  import { Carousel } from "../Carousel/index.js";
27
27
  import { Skeleton } from "../Skeleton/index.js";
28
28
  import { useTheme } from "../../theme/index.js";
29
- import { triggerHaptic } from "../../utils/index.js";
29
+ import { resolveHaptic, triggerHaptic } from "../../utils/index.js";
30
30
 
31
31
  // Local shape mirror — see types.ts ImageGalleryTokens for the canonical definition.
32
32
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -46,6 +46,7 @@ const ImageGallery = ({
46
46
  enableLightbox = true,
47
47
  enablePinchZoom = true,
48
48
  onIndexChange,
49
+ haptic,
49
50
  loading = false,
50
51
  accessibilityLabel,
51
52
  containerStyle,
@@ -53,8 +54,6 @@ const ImageGallery = ({
53
54
  }) => {
54
55
  const theme = useTheme();
55
56
  const styles = useMemo(() => buildStyles(theme), [theme]);
56
- const galleryTokens = theme.components.imageGallery;
57
- const pressHaptic = galleryTokens?.pressHaptic ?? false;
58
57
  const [currentIndex, setCurrentIndex] = useState(clamp(initialIndex, 0, Math.max(0, images.length - 1)));
59
58
  const [lightboxOpen, setLightboxOpen] = useState(false);
60
59
  const handleIndexChange = useCallback(idx => {
@@ -63,13 +62,15 @@ const ImageGallery = ({
63
62
  }, [onIndexChange]);
64
63
  const openLightbox = useCallback(() => {
65
64
  if (!enableLightbox) return;
66
- if (pressHaptic) triggerHaptic('selection');
65
+ const h = resolveHaptic(haptic, 'selection');
66
+ if (h) triggerHaptic(h);
67
67
  setLightboxOpen(true);
68
- }, [enableLightbox, pressHaptic]);
68
+ }, [enableLightbox, haptic]);
69
69
  const closeLightbox = useCallback(() => {
70
- if (pressHaptic) triggerHaptic('selection');
70
+ const h = resolveHaptic(haptic, 'selection');
71
+ if (h) triggerHaptic(h);
71
72
  setLightboxOpen(false);
72
- }, [pressHaptic]);
73
+ }, [haptic]);
73
74
  const renderImage = useCallback((image, idx) => {
74
75
  const a11y = image.alt ?? `Image ${idx + 1} of ${images.length}`;
75
76
  return /*#__PURE__*/_jsx(Pressable, {
@@ -123,7 +124,7 @@ const ImageGallery = ({
123
124
  showCounter: showCounter,
124
125
  onClose: closeLightbox,
125
126
  onIndexChange: handleIndexChange,
126
- pressHaptic: pressHaptic
127
+ haptic: haptic
127
128
  }) : null]
128
129
  });
129
130
  if (loading) {
@@ -212,7 +213,7 @@ const Lightbox = ({
212
213
  showCounter,
213
214
  onClose,
214
215
  onIndexChange,
215
- pressHaptic
216
+ haptic
216
217
  }) => {
217
218
  const theme = useTheme();
218
219
  const styles = useMemo(() => buildLightboxStyles(theme), [theme]);
@@ -224,11 +225,12 @@ const Lightbox = ({
224
225
  const [activeIndex, setActiveIndex] = useState(initialIndex);
225
226
  const handleSwipe = useCallback(idx => {
226
227
  if (idx !== activeIndex) {
227
- if (pressHaptic) triggerHaptic('selection');
228
+ const h = resolveHaptic(haptic, 'selection');
229
+ if (h) triggerHaptic(h);
228
230
  setActiveIndex(idx);
229
231
  onIndexChange(idx);
230
232
  }
231
- }, [activeIndex, onIndexChange, pressHaptic]);
233
+ }, [activeIndex, onIndexChange, haptic]);
232
234
  const renderItem = useCallback((image, idx) => /*#__PURE__*/_jsx(ZoomableImage, {
233
235
  image: image,
234
236
  index: idx,
@@ -238,8 +240,8 @@ const Lightbox = ({
238
240
  maxScale: maxScale,
239
241
  minScale: minScale,
240
242
  doubleTapScale: doubleTapScale,
241
- pressHaptic: pressHaptic
242
- }), [activeIndex, enablePinchZoom, images.length, maxScale, minScale, doubleTapScale, pressHaptic]);
243
+ haptic: haptic
244
+ }), [activeIndex, enablePinchZoom, images.length, maxScale, minScale, doubleTapScale, haptic]);
243
245
  const caption = images[activeIndex]?.caption;
244
246
  return /*#__PURE__*/_jsx(RNModal, {
245
247
  visible: visible,
@@ -310,7 +312,7 @@ const ZoomableImage = ({
310
312
  maxScale,
311
313
  minScale,
312
314
  doubleTapScale,
313
- pressHaptic
315
+ haptic
314
316
  }) => {
315
317
  const screen = Dimensions.get('window');
316
318
  const scale = useSharedValue(1);
@@ -346,8 +348,8 @@ const ZoomableImage = ({
346
348
  }
347
349
  }, [active, scale, translateX, translateY, savedScale, savedTranslateX, savedTranslateY]);
348
350
  const triggerImpact = useCallback(() => {
349
- if (pressHaptic) triggerHaptic('impactLight');
350
- }, [pressHaptic]);
351
+ if (haptic !== false) triggerHaptic('impactLight');
352
+ }, [haptic]);
351
353
  const pinch = useMemo(() => Gesture.Pinch().enabled(enabled).onStart(() => {
352
354
  'worklet';
353
355
 
@@ -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 { Swipeable } from "../Swipeable/index.js";
9
9
  import { Skeleton } from "../Skeleton/index.js";
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -64,6 +64,7 @@ const ListItem = /*#__PURE__*/forwardRef((props, ref) => {
64
64
  left,
65
65
  right,
66
66
  onPress,
67
+ haptic,
67
68
  selected = false,
68
69
  disabled = false,
69
70
  size = 'md',
@@ -83,7 +84,6 @@ const ListItem = /*#__PURE__*/forwardRef((props, ref) => {
83
84
  testID
84
85
  } = props;
85
86
  const theme = useTheme();
86
- const pressHaptic = theme.components.listItem?.pressHaptic ?? false;
87
87
  const sz = useMemo(() => sizeFor(theme, size), [theme, size]);
88
88
  const styles = useMemo(() => buildStyles(theme), [theme]);
89
89
  const isInteractive = !!onPress && !disabled;
@@ -96,7 +96,8 @@ const ListItem = /*#__PURE__*/forwardRef((props, ref) => {
96
96
  });
97
97
  const handlePress = event => {
98
98
  if (!isInteractive) return;
99
- if (pressHaptic) triggerHaptic('selection');
99
+ const h = resolveHaptic(haptic, 'selection');
100
+ if (h) triggerHaptic(h);
100
101
  onPress?.(event);
101
102
  };
102
103
  const a11yLabel = accessibilityLabel ?? title;
@@ -291,7 +292,7 @@ const buildStyles = theme => StyleSheet.create({
291
292
  backgroundColor: theme.colors.surface.pressed
292
293
  },
293
294
  disabled: {
294
- opacity: 0.6
295
+ opacity: 0.55
295
296
  },
296
297
  leftSlot: {
297
298
  marginRight: theme.spacing.md,
@@ -4,7 +4,7 @@ import React, { forwardRef, useCallback, useEffect, useMemo, useRef } from 'reac
4
4
  import { AccessibilityInfo, Animated, Dimensions, findNodeHandle, Modal as RNModal, Pressable, StyleSheet, View } from 'react-native';
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
6
  import { useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
7
- import { triggerHaptic } from "../../utils/hapticUtils.js";
7
+ import { triggerHaptic, resolveHaptic } from "../../utils/hapticUtils.js";
8
8
 
9
9
  // Local shape mirror — see types.ts ModalTokens for the canonical definition.
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -22,6 +22,7 @@ const Modal = /*#__PURE__*/forwardRef((props, ref) => {
22
22
  contentStyle,
23
23
  backdropStyle,
24
24
  restoreFocusRef,
25
+ haptic,
25
26
  testID
26
27
  } = props;
27
28
  const theme = useTheme();
@@ -30,7 +31,6 @@ const Modal = /*#__PURE__*/forwardRef((props, ref) => {
30
31
  const screenHeight = Dimensions.get('window').height;
31
32
  const modalTokens = theme.components.modal;
32
33
  const scaleStartValue = modalTokens?.scaleStartValue ?? 0.9;
33
- const backdropHaptic = modalTokens?.backdropHaptic ?? false;
34
34
  const backdropAnim = useRef(createAnimatedValue(0)).current;
35
35
  const scaleAnim = useRef(createAnimatedValue(scaleStartValue)).current;
36
36
  const opacityAnim = useRef(createAnimatedValue(0)).current;
@@ -126,9 +126,10 @@ const Modal = /*#__PURE__*/forwardRef((props, ref) => {
126
126
  }, [visible, duration, restoreFocusRef]);
127
127
  const handleBackdropPress = useCallback(() => {
128
128
  if (!backdropPressClose) return;
129
- if (backdropHaptic) triggerHaptic('selection');
129
+ const h = resolveHaptic(haptic, 'selection');
130
+ if (h) triggerHaptic(h);
130
131
  onRequestClose();
131
- }, [backdropPressClose, onRequestClose, backdropHaptic]);
132
+ }, [backdropPressClose, onRequestClose, haptic]);
132
133
  const handleHardwareBack = useCallback(() => {
133
134
  if (hardwareBackPress) {
134
135
  onRequestClose();
@@ -4,7 +4,7 @@ import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState }
4
4
  import { Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
5
5
  import { useControllableState } from "../../hooks/index.js";
6
6
  import { useTheme } from "../../theme/index.js";
7
- import { triggerHaptic } from "../../utils/index.js";
7
+ import { resolveHaptic, triggerHaptic } from "../../utils/index.js";
8
8
  import { FieldBase, resolveFieldSize, resolveFieldTextStyle } from "../FieldBase/FieldBase.js";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  const DEFAULT_LONG_PRESS_DELAY = 500;
@@ -58,6 +58,7 @@ const NumberInput = /*#__PURE__*/forwardRef((props, ref) => {
58
58
  size = 'md',
59
59
  variant = 'inline',
60
60
  unit,
61
+ haptic,
61
62
  accessibilityLabel,
62
63
  style,
63
64
  containerStyle,
@@ -81,7 +82,6 @@ const NumberInput = /*#__PURE__*/forwardRef((props, ref) => {
81
82
  const styles = useMemo(() => buildStyles(theme), [theme]);
82
83
  const longPressDelay = theme.components.numberInput?.longPressDelayMs ?? DEFAULT_LONG_PRESS_DELAY;
83
84
  const longPressInterval = theme.components.numberInput?.longPressIntervalMs ?? DEFAULT_LONG_PRESS_INTERVAL;
84
- const pressHaptic = theme.components.numberInput?.pressHaptic ?? false;
85
85
  const inputRef = useRef(null);
86
86
  const [draft, setDraft] = useState(formatValue(current, allowDecimal, precision));
87
87
  const [editing, setEditing] = useState(false);
@@ -116,14 +116,16 @@ const NumberInput = /*#__PURE__*/forwardRef((props, ref) => {
116
116
  }, [allowDecimal, max, min, setCurrent, precision, current]);
117
117
  const decrement = useCallback(() => {
118
118
  if (!interactive || atMin) return;
119
- if (pressHaptic) triggerHaptic('impactLight');
119
+ const h = resolveHaptic(haptic, 'selection');
120
+ if (h) triggerHaptic(h);
120
121
  setExternal(current - step);
121
- }, [atMin, interactive, pressHaptic, setExternal, step, current]);
122
+ }, [atMin, interactive, haptic, setExternal, step, current]);
122
123
  const increment = useCallback(() => {
123
124
  if (!interactive || atMax) return;
124
- if (pressHaptic) triggerHaptic('impactLight');
125
+ const h = resolveHaptic(haptic, 'selection');
126
+ if (h) triggerHaptic(h);
125
127
  setExternal(current + step);
126
- }, [atMax, interactive, pressHaptic, setExternal, step, current]);
128
+ }, [atMax, interactive, haptic, setExternal, step, current]);
127
129
  React.useImperativeHandle(ref, () => ({
128
130
  focus: () => inputRef.current?.focus(),
129
131
  blur: () => inputRef.current?.blur(),
@@ -4,7 +4,7 @@ import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo
4
4
  import { Animated, Easing, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
5
5
  import { fontFor, useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
6
6
  import { useReducedMotion, useControllableState } from "../../hooks/index.js";
7
- import { triggerHaptic } from "../../utils/index.js";
7
+ import { triggerHaptic, resolveHaptic } from "../../utils/index.js";
8
8
  import { FieldBase } from "../FieldBase/FieldBase.js";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  const sizeMap = {
@@ -47,6 +47,7 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
47
47
  error,
48
48
  size = 'md',
49
49
  secure = false,
50
+ haptic,
50
51
  accessibilityLabel,
51
52
  style,
52
53
  cellStyle,
@@ -89,8 +90,6 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
89
90
  const previousFocusedIndexRef = useRef(-1);
90
91
  const shakeOnError = theme.components.otpInput?.shakeOnError ?? false;
91
92
  const reduceMotion = useReducedMotion();
92
- const errorHaptic = theme.components.otpInput?.errorHaptic ?? false;
93
- const selectionHaptic = theme.components.otpInput?.selectionHaptic ?? false;
94
93
  const hasError = Boolean(error);
95
94
  const errorMessage = typeof error === 'string' ? error : undefined;
96
95
 
@@ -100,7 +99,7 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
100
99
  const isFirstRun = previousErrorRef.current === null;
101
100
  let anim;
102
101
  if (!isFirstRun && hasError && !previousErrorRef.current) {
103
- if (errorHaptic) triggerHaptic('notificationError');
102
+ if (haptic !== false) triggerHaptic('notificationError');
104
103
  if (shakeOnError && !reduceMotion) {
105
104
  setNativeValue(shake, 0);
106
105
  anim = Animated.sequence([Animated.timing(shake, {
@@ -129,7 +128,7 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
129
128
  }
130
129
  previousErrorRef.current = hasError;
131
130
  return () => anim?.stop();
132
- }, [hasError, shake, shakeOnError, errorHaptic]);
131
+ }, [hasError, shake, shakeOnError, haptic]);
133
132
 
134
133
  // Animate underline opacity for the focused cell. Skip on first mount
135
134
  // (no prior focus state) — values are already at 0 and there's nothing to animate.
@@ -225,8 +224,9 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
225
224
  const next = chars.join('').slice(0, length);
226
225
  const previousLength = current.length;
227
226
  updateValue(next);
228
- if (next.length !== previousLength && selectionHaptic) {
229
- triggerHaptic('selection');
227
+ if (next.length !== previousLength) {
228
+ const h = resolveHaptic(haptic, 'selection');
229
+ if (h) triggerHaptic(h);
230
230
  }
231
231
 
232
232
  // Move focus to the next empty cell or last cell.
@@ -236,7 +236,7 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
236
236
  } else {
237
237
  focusCell(nextFocus);
238
238
  }
239
- }, [cells, focusCell, keyboardType, length, selectionHaptic, updateValue, current]);
239
+ }, [cells, focusCell, keyboardType, length, haptic, updateValue, current]);
240
240
  const handleKeyPress = useCallback((index, e) => {
241
241
  const key = e.nativeEvent.key;
242
242
  if (key !== 'Backspace') return;
@@ -3,7 +3,7 @@
3
3
  import React, { createContext, forwardRef, useContext, 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
- import { triggerHaptic } from "../../utils/hapticUtils.js";
6
+ import { triggerHaptic, resolveHaptic } from "../../utils/hapticUtils.js";
7
7
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  export const RadioGroupContext = /*#__PURE__*/createContext(null);
9
9
  export const useRadioGroup = () => useContext(RadioGroupContext);
@@ -64,8 +64,6 @@ const Radio = /*#__PURE__*/forwardRef((props, ref) => {
64
64
  const inner = sizeOverrides?.inner ?? sizeMap[size].inner;
65
65
  const radioBorderWidth = theme.colors.border.width;
66
66
  const radioLabelGap = theme.components.radio?.labelGap ?? 10;
67
- const pressHapticEnabled = theme.components.radio?.pressHaptic ?? false;
68
- const resolvedHaptic = haptic === undefined ? pressHapticEnabled ? 'selection' : false : haptic;
69
67
  const progress = useRef(createAnimatedValue(selected ? 1 : 0)).current;
70
68
  useEffect(() => {
71
69
  const anim = Animated.spring(progress, {
@@ -84,7 +82,8 @@ const Radio = /*#__PURE__*/forwardRef((props, ref) => {
84
82
  });
85
83
  const handlePress = event => {
86
84
  if (disabled) return;
87
- if (resolvedHaptic !== false) triggerHaptic(resolvedHaptic);
85
+ const h = resolveHaptic(haptic, 'selection');
86
+ if (h) triggerHaptic(h);
88
87
  if (ctx) {
89
88
  ctx.onChange(value);
90
89
  } else {
@@ -3,7 +3,7 @@
3
3
  import React, { forwardRef, useCallback, useMemo, useRef } from 'react';
4
4
  import { Animated, Easing, Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import { useTheme } 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 sizePxMap = {
@@ -80,6 +80,7 @@ const Rating = /*#__PURE__*/forwardRef((props, ref) => {
80
80
  tone = 'warning',
81
81
  label,
82
82
  loading = false,
83
+ haptic,
83
84
  accessibilityLabel,
84
85
  style,
85
86
  containerStyle,
@@ -116,7 +117,6 @@ const Rating = /*#__PURE__*/forwardRef((props, ref) => {
116
117
  }, [max]);
117
118
  const pulseOnPress = theme.components.rating?.pulseOnPress ?? false;
118
119
  const pulseScale = theme.components.rating?.pulseScale ?? 1.2;
119
- const pressHapticEnabled = theme.components.rating?.pressHaptic ?? false;
120
120
  const pulse = useCallback(idx => {
121
121
  const v = scaleRefs[idx];
122
122
  if (!v) return;
@@ -136,10 +136,11 @@ const Rating = /*#__PURE__*/forwardRef((props, ref) => {
136
136
  const commit = useCallback((next, animatedIndex) => {
137
137
  if (!interactive || !onChange) return;
138
138
  const cleaned = clampToStep(next, max, step);
139
- if (pressHapticEnabled) triggerHaptic('selection');
139
+ const h = resolveHaptic(haptic, 'selection');
140
+ if (h) triggerHaptic(h);
140
141
  if (pulseOnPress && typeof animatedIndex === 'number') pulse(animatedIndex);
141
142
  onChange(cleaned);
142
- }, [interactive, onChange, max, step, pulse, pressHapticEnabled, pulseOnPress]);
143
+ }, [interactive, onChange, max, step, pulse, haptic, pulseOnPress]);
143
144
  const handleStarPress = useCallback(index => e => {
144
145
  if (!interactive) return;
145
146
  const w = starWidthRef.current || starSize;
@@ -3,7 +3,7 @@
3
3
  import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { Animated, Easing, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
5
5
  import { fontFor, useTheme, createAnimatedValue } from "../../theme/index.js";
6
- import { triggerHaptic } from "../../utils/hapticUtils.js";
6
+ import { resolveHaptic, triggerHaptic } from "../../utils/hapticUtils.js";
7
7
  import { useDebounce } from "../../hooks/useDebounce.js";
8
8
  import { FieldBase, resolveFieldSize, resolveFieldTextStyle, resolveVariantColors } from "../FieldBase/FieldBase.js";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -24,6 +24,7 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
24
24
  size = 'md',
25
25
  variant: variantProp,
26
26
  cancelLabel = 'Cancel',
27
+ haptic,
27
28
  style,
28
29
  accessibilityLabel,
29
30
  testID,
@@ -92,16 +93,18 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
92
93
  onChangeText(text);
93
94
  }, [debounceMs, onChangeText]);
94
95
  const handleClear = useCallback(() => {
95
- triggerHaptic('selection');
96
+ const h = resolveHaptic(haptic, 'selection');
97
+ if (h) triggerHaptic(h);
96
98
  if (debounceMs !== undefined) {
97
99
  setInternalValue('');
98
100
  lastSentRef.current = '';
99
101
  }
100
102
  onChangeText('');
101
103
  onClear?.();
102
- }, [debounceMs, onChangeText, onClear]);
104
+ }, [haptic, debounceMs, onChangeText, onClear]);
103
105
  const handleCancel = useCallback(() => {
104
- triggerHaptic('selection');
106
+ const h = resolveHaptic(haptic, 'selection');
107
+ if (h) triggerHaptic(h);
105
108
  if (debounceMs !== undefined) {
106
109
  setInternalValue('');
107
110
  lastSentRef.current = '';
@@ -109,7 +112,7 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
109
112
  onChangeText('');
110
113
  setIsFocused(false);
111
114
  onCancel?.();
112
- }, [debounceMs, onChangeText, onCancel]);
115
+ }, [haptic, debounceMs, onChangeText, onCancel]);
113
116
  const handleSubmit = useCallback(() => {
114
117
  onSubmit?.(debounceMs !== undefined ? internalValue : value);
115
118
  }, [onSubmit, debounceMs, internalValue, value]);
@@ -11,7 +11,7 @@
11
11
  import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
12
12
  import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
13
13
  import { useTheme, createAnimatedValue } from "../../theme/index.js";
14
- import { triggerHaptic } from "../../utils/index.js";
14
+ import { triggerHaptic, resolveHaptic } from "../../utils/index.js";
15
15
  import { useControllableState } from "../../hooks/index.js";
16
16
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
17
  const sizeMap = {
@@ -37,6 +37,7 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
37
37
  fullWidth = true,
38
38
  disabled = false,
39
39
  tone = 'primary',
40
+ haptic,
40
41
  accessibilityLabel,
41
42
  style,
42
43
  containerStyle,
@@ -61,7 +62,6 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
61
62
  paddingHorizontal: segTheme?.[size]?.paddingHorizontal ?? baseSize.paddingHorizontal
62
63
  };
63
64
  const trackPadding = segTheme?.trackPadding ?? TRACK_PADDING;
64
- const changeHapticEnabled = segTheme?.changeHaptic ?? false;
65
65
 
66
66
  // Track width is measured from onLayout. Thumb width is a regular number (not
67
67
  // animated) — `width` cannot be driven by the native animated module, and mixing
@@ -102,9 +102,10 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
102
102
  const handlePress = useCallback(segment => {
103
103
  if (disabled) return;
104
104
  if (segment.value === current) return;
105
- if (changeHapticEnabled) triggerHaptic('selection');
105
+ const h = resolveHaptic(haptic, 'selection');
106
+ if (h) triggerHaptic(h);
106
107
  setCurrent(segment.value);
107
- }, [disabled, setCurrent, current, changeHapticEnabled]);
108
+ }, [disabled, setCurrent, current, haptic]);
108
109
  const thumbBg = tone === 'primary' ? theme.colors.background.elevated : theme.colors.background.elevated;
109
110
  const activeTextColor = tone === 'primary' ? theme.colors.text.primary : theme.colors.text.primary;
110
111
  return /*#__PURE__*/_jsxs(View, {
@@ -12,7 +12,7 @@ import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState }
12
12
  import { Animated, Dimensions, Easing, FlatList, Modal, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
13
13
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
14
14
  import { useTheme, createAnimatedValue } from "../../theme/index.js";
15
- import { triggerHaptic } from "../../utils/index.js";
15
+ import { resolveHaptic, triggerHaptic } from "../../utils/index.js";
16
16
  import { FieldBase, resolveFieldSize, resolveFieldTextStyle, resolveVariantColors } from "../FieldBase/FieldBase.js";
17
17
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
18
  // `unknown` here keeps the forwardRef signature non-generic — consumers who
@@ -27,6 +27,7 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
27
27
  getOptionDescription,
28
28
  placeholder,
29
29
  searchable = false,
30
+ haptic,
30
31
  label,
31
32
  error,
32
33
  disabled = false,
@@ -114,9 +115,10 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
114
115
  }, [searchable, query, options, labelOf, descriptionOf]);
115
116
  const handleOpen = useCallback(() => {
116
117
  if (disabled) return;
117
- triggerHaptic('selection');
118
+ const h = resolveHaptic(haptic, 'selection');
119
+ if (h) triggerHaptic(h);
118
120
  setOpen(true);
119
- }, [disabled]);
121
+ }, [disabled, haptic]);
120
122
  const handleClose = useCallback(() => {
121
123
  setOpen(false);
122
124
  setQuery('');
@@ -124,7 +126,8 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
124
126
  const handleSelect = useCallback(option => {
125
127
  if (disabledOf(option)) return;
126
128
  const optValue = valueOf(option);
127
- triggerHaptic('selection');
129
+ const h = resolveHaptic(haptic, 'selection');
130
+ if (h) triggerHaptic(h);
128
131
  if (multi) {
129
132
  const current = props.value ?? [];
130
133
  const next = current.includes(optValue) ? current.filter(v => v !== optValue) : [...current, optValue];
@@ -133,7 +136,7 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
133
136
  }
134
137
  props.onChange(optValue);
135
138
  handleClose();
136
- }, [multi, props, handleClose, disabledOf, valueOf]);
139
+ }, [multi, props, handleClose, disabledOf, valueOf, haptic]);
137
140
 
138
141
  // Trigger label / placeholder text.
139
142
  const triggerText = selectedOptions.length === 0 ? placeholder ?? 'Select…' : selectedOptions.map(o => labelOf(o)).join(', ');