@webority-technologies/mobile 0.0.15 → 0.0.21

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 (202) hide show
  1. package/lib/commonjs/components/Accordion/Accordion.js +60 -19
  2. package/lib/commonjs/components/AppBar/AppBar.js +29 -20
  3. package/lib/commonjs/components/Avatar/Avatar.js +38 -8
  4. package/lib/commonjs/components/Badge/Badge.js +66 -4
  5. package/lib/commonjs/components/Banner/Banner.js +146 -66
  6. package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +37 -15
  7. package/lib/commonjs/components/BottomSheet/BottomSheet.js +78 -53
  8. package/lib/commonjs/components/Button/Button.js +12 -5
  9. package/lib/commonjs/components/Card/Card.js +106 -16
  10. package/lib/commonjs/components/Carousel/Carousel.js +66 -12
  11. package/lib/commonjs/components/Checkbox/Checkbox.js +11 -7
  12. package/lib/commonjs/components/Chip/Chip.js +44 -12
  13. package/lib/commonjs/components/DatePicker/DatePicker.js +185 -76
  14. package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +133 -59
  15. package/lib/commonjs/components/Dialog/Dialog.js +16 -10
  16. package/lib/commonjs/components/Drawer/Drawer.js +13 -10
  17. package/lib/commonjs/components/FieldBase/FieldBase.js +494 -0
  18. package/lib/commonjs/components/FieldBase/index.js +32 -0
  19. package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +69 -44
  20. package/lib/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
  21. package/lib/commonjs/components/FormField/FormField.js +3 -2
  22. package/lib/commonjs/components/ImageGallery/ImageGallery.js +132 -44
  23. package/lib/commonjs/components/Input/Input.js +144 -181
  24. package/lib/commonjs/components/ListItem/ListItem.js +90 -11
  25. package/lib/commonjs/components/Modal/Modal.js +55 -27
  26. package/lib/commonjs/components/NumberInput/NumberInput.js +60 -106
  27. package/lib/commonjs/components/OTPInput/OTPInput.js +65 -58
  28. package/lib/commonjs/components/PickerTrigger/PickerTrigger.js +185 -0
  29. package/lib/commonjs/components/{AppIcon → PickerTrigger}/index.js +4 -4
  30. package/lib/commonjs/components/ProgressBar/ProgressBar.js +19 -11
  31. package/lib/commonjs/components/Radio/Radio.js +11 -6
  32. package/lib/commonjs/components/Rating/Rating.js +85 -19
  33. package/lib/commonjs/components/SearchBar/SearchBar.js +90 -107
  34. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +22 -11
  35. package/lib/commonjs/components/Select/Select.js +62 -91
  36. package/lib/commonjs/components/Skeleton/Skeleton.js +131 -174
  37. package/lib/commonjs/components/Skeleton/SkeletonClock.js +117 -0
  38. package/lib/commonjs/components/Skeleton/SkeletonContent.js +164 -81
  39. package/lib/commonjs/components/Skeleton/SkeletonProvider.js +72 -10
  40. package/lib/commonjs/components/Skeleton/index.js +17 -16
  41. package/lib/commonjs/components/Slider/Slider.js +44 -25
  42. package/lib/commonjs/components/Stepper/Stepper.js +199 -29
  43. package/lib/commonjs/components/Swipeable/Swipeable.js +36 -19
  44. package/lib/commonjs/components/Switch/Switch.js +9 -2
  45. package/lib/commonjs/components/Tabs/Tabs.js +84 -21
  46. package/lib/commonjs/components/TimePicker/TimePicker.js +123 -45
  47. package/lib/commonjs/components/Toast/Toast.js +27 -16
  48. package/lib/commonjs/components/Tooltip/Tooltip.js +56 -32
  49. package/lib/commonjs/components/index.js +37 -37
  50. package/lib/commonjs/theme/tokens.js +55 -7
  51. package/lib/module/components/Accordion/Accordion.js +61 -20
  52. package/lib/module/components/AppBar/AppBar.js +29 -20
  53. package/lib/module/components/Avatar/Avatar.js +39 -9
  54. package/lib/module/components/Badge/Badge.js +67 -5
  55. package/lib/module/components/Banner/Banner.js +147 -67
  56. package/lib/module/components/BottomNavigation/BottomNavigation.js +37 -15
  57. package/lib/module/components/BottomSheet/BottomSheet.js +80 -55
  58. package/lib/module/components/Button/Button.js +12 -5
  59. package/lib/module/components/Card/Card.js +107 -17
  60. package/lib/module/components/Carousel/Carousel.js +67 -13
  61. package/lib/module/components/Checkbox/Checkbox.js +11 -7
  62. package/lib/module/components/Chip/Chip.js +45 -13
  63. package/lib/module/components/DatePicker/DatePicker.js +185 -76
  64. package/lib/module/components/DateRangePicker/DateRangePicker.js +134 -60
  65. package/lib/module/components/Dialog/Dialog.js +16 -10
  66. package/lib/module/components/Drawer/Drawer.js +13 -10
  67. package/lib/module/components/FieldBase/FieldBase.js +485 -0
  68. package/lib/module/components/FieldBase/index.js +4 -0
  69. package/lib/module/components/FloatingActionButton/FloatingActionButton.js +69 -44
  70. package/lib/module/components/ForceUpdateDialog/ForceUpdateDialog.js +8 -2
  71. package/lib/module/components/FormField/FormField.js +3 -2
  72. package/lib/module/components/ImageGallery/ImageGallery.js +128 -40
  73. package/lib/module/components/Input/Input.js +144 -179
  74. package/lib/module/components/ListItem/ListItem.js +91 -12
  75. package/lib/module/components/Modal/Modal.js +55 -27
  76. package/lib/module/components/NumberInput/NumberInput.js +60 -106
  77. package/lib/module/components/OTPInput/OTPInput.js +65 -58
  78. package/lib/module/components/PickerTrigger/PickerTrigger.js +181 -0
  79. package/lib/module/components/PickerTrigger/index.js +4 -0
  80. package/lib/module/components/ProgressBar/ProgressBar.js +19 -11
  81. package/lib/module/components/Radio/Radio.js +11 -6
  82. package/lib/module/components/Rating/Rating.js +86 -20
  83. package/lib/module/components/SearchBar/SearchBar.js +90 -107
  84. package/lib/module/components/SegmentedControl/SegmentedControl.js +22 -11
  85. package/lib/module/components/Select/Select.js +62 -91
  86. package/lib/module/components/Skeleton/Skeleton.js +135 -175
  87. package/lib/module/components/Skeleton/SkeletonClock.js +110 -0
  88. package/lib/module/components/Skeleton/SkeletonContent.js +167 -84
  89. package/lib/module/components/Skeleton/SkeletonProvider.js +71 -10
  90. package/lib/module/components/Skeleton/index.js +3 -2
  91. package/lib/module/components/Slider/Slider.js +44 -25
  92. package/lib/module/components/Stepper/Stepper.js +201 -31
  93. package/lib/module/components/Swipeable/Swipeable.js +36 -19
  94. package/lib/module/components/Switch/Switch.js +9 -2
  95. package/lib/module/components/Tabs/Tabs.js +84 -21
  96. package/lib/module/components/TimePicker/TimePicker.js +123 -45
  97. package/lib/module/components/Toast/Toast.js +27 -16
  98. package/lib/module/components/Tooltip/Tooltip.js +56 -32
  99. package/lib/module/components/index.js +2 -2
  100. package/lib/module/theme/tokens.js +55 -7
  101. package/lib/typescript/commonjs/components/Accordion/Accordion.d.ts +10 -5
  102. package/lib/typescript/commonjs/components/AppBar/AppBar.d.ts +8 -0
  103. package/lib/typescript/commonjs/components/Avatar/Avatar.d.ts +12 -6
  104. package/lib/typescript/commonjs/components/Badge/Badge.d.ts +7 -6
  105. package/lib/typescript/commonjs/components/Banner/Banner.d.ts +17 -6
  106. package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +7 -0
  107. package/lib/typescript/commonjs/components/Card/Card.d.ts +17 -6
  108. package/lib/typescript/commonjs/components/Carousel/Carousel.d.ts +7 -6
  109. package/lib/typescript/commonjs/components/Checkbox/Checkbox.d.ts +9 -1
  110. package/lib/typescript/commonjs/components/Chip/Chip.d.ts +13 -6
  111. package/lib/typescript/commonjs/components/DatePicker/DatePicker.d.ts +38 -3
  112. package/lib/typescript/commonjs/components/DateRangePicker/DateRangePicker.d.ts +36 -3
  113. package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +13 -1
  114. package/lib/typescript/commonjs/components/FieldBase/FieldBase.d.ts +172 -0
  115. package/lib/typescript/commonjs/components/FieldBase/index.d.ts +3 -0
  116. package/lib/typescript/commonjs/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
  117. package/lib/typescript/commonjs/components/FloatingActionButton/index.d.ts +1 -1
  118. package/lib/typescript/commonjs/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
  119. package/lib/typescript/commonjs/components/FormField/FormField.d.ts +7 -0
  120. package/lib/typescript/commonjs/components/ImageGallery/ImageGallery.d.ts +6 -4
  121. package/lib/typescript/commonjs/components/Input/Input.d.ts +7 -1
  122. package/lib/typescript/commonjs/components/ListItem/ListItem.d.ts +13 -6
  123. package/lib/typescript/commonjs/components/NumberInput/NumberInput.d.ts +3 -0
  124. package/lib/typescript/commonjs/components/PickerTrigger/PickerTrigger.d.ts +57 -0
  125. package/lib/typescript/commonjs/components/PickerTrigger/index.d.ts +3 -0
  126. package/lib/typescript/commonjs/components/ProgressBar/ProgressBar.d.ts +2 -0
  127. package/lib/typescript/commonjs/components/Radio/Radio.d.ts +3 -0
  128. package/lib/typescript/commonjs/components/Rating/Rating.d.ts +9 -6
  129. package/lib/typescript/commonjs/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  130. package/lib/typescript/commonjs/components/Skeleton/Skeleton.d.ts +49 -20
  131. package/lib/typescript/commonjs/components/Skeleton/SkeletonClock.d.ts +60 -0
  132. package/lib/typescript/commonjs/components/Skeleton/SkeletonContent.d.ts +80 -19
  133. package/lib/typescript/commonjs/components/Skeleton/SkeletonProvider.d.ts +39 -5
  134. package/lib/typescript/commonjs/components/Skeleton/index.d.ts +6 -4
  135. package/lib/typescript/commonjs/components/Slider/Slider.d.ts +12 -1
  136. package/lib/typescript/commonjs/components/Stepper/Stepper.d.ts +18 -6
  137. package/lib/typescript/commonjs/components/Swipeable/Swipeable.d.ts +2 -0
  138. package/lib/typescript/commonjs/components/Switch/Switch.d.ts +1 -0
  139. package/lib/typescript/commonjs/components/Tabs/Tabs.d.ts +26 -2
  140. package/lib/typescript/commonjs/components/TimePicker/TimePicker.d.ts +36 -3
  141. package/lib/typescript/commonjs/components/Toast/Toast.d.ts +8 -0
  142. package/lib/typescript/commonjs/components/Tooltip/Tooltip.d.ts +7 -1
  143. package/lib/typescript/commonjs/components/index.d.ts +5 -5
  144. package/lib/typescript/commonjs/index.d.ts +1 -1
  145. package/lib/typescript/commonjs/theme/index.d.ts +1 -1
  146. package/lib/typescript/commonjs/theme/types.d.ts +578 -12
  147. package/lib/typescript/module/components/Accordion/Accordion.d.ts +10 -5
  148. package/lib/typescript/module/components/AppBar/AppBar.d.ts +8 -0
  149. package/lib/typescript/module/components/Avatar/Avatar.d.ts +12 -6
  150. package/lib/typescript/module/components/Badge/Badge.d.ts +7 -6
  151. package/lib/typescript/module/components/Banner/Banner.d.ts +17 -6
  152. package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +7 -0
  153. package/lib/typescript/module/components/Card/Card.d.ts +17 -6
  154. package/lib/typescript/module/components/Carousel/Carousel.d.ts +7 -6
  155. package/lib/typescript/module/components/Checkbox/Checkbox.d.ts +9 -1
  156. package/lib/typescript/module/components/Chip/Chip.d.ts +13 -6
  157. package/lib/typescript/module/components/DatePicker/DatePicker.d.ts +38 -3
  158. package/lib/typescript/module/components/DateRangePicker/DateRangePicker.d.ts +36 -3
  159. package/lib/typescript/module/components/Dialog/Dialog.d.ts +13 -1
  160. package/lib/typescript/module/components/FieldBase/FieldBase.d.ts +172 -0
  161. package/lib/typescript/module/components/FieldBase/index.d.ts +3 -0
  162. package/lib/typescript/module/components/FloatingActionButton/FloatingActionButton.d.ts +8 -6
  163. package/lib/typescript/module/components/FloatingActionButton/index.d.ts +1 -1
  164. package/lib/typescript/module/components/ForceUpdateDialog/ForceUpdateDialog.d.ts +7 -0
  165. package/lib/typescript/module/components/FormField/FormField.d.ts +7 -0
  166. package/lib/typescript/module/components/ImageGallery/ImageGallery.d.ts +6 -4
  167. package/lib/typescript/module/components/Input/Input.d.ts +7 -1
  168. package/lib/typescript/module/components/ListItem/ListItem.d.ts +13 -6
  169. package/lib/typescript/module/components/NumberInput/NumberInput.d.ts +3 -0
  170. package/lib/typescript/module/components/PickerTrigger/PickerTrigger.d.ts +57 -0
  171. package/lib/typescript/module/components/PickerTrigger/index.d.ts +3 -0
  172. package/lib/typescript/module/components/ProgressBar/ProgressBar.d.ts +2 -0
  173. package/lib/typescript/module/components/Radio/Radio.d.ts +3 -0
  174. package/lib/typescript/module/components/Rating/Rating.d.ts +9 -6
  175. package/lib/typescript/module/components/SegmentedControl/SegmentedControl.d.ts +3 -0
  176. package/lib/typescript/module/components/Skeleton/Skeleton.d.ts +49 -20
  177. package/lib/typescript/module/components/Skeleton/SkeletonClock.d.ts +60 -0
  178. package/lib/typescript/module/components/Skeleton/SkeletonContent.d.ts +80 -19
  179. package/lib/typescript/module/components/Skeleton/SkeletonProvider.d.ts +39 -5
  180. package/lib/typescript/module/components/Skeleton/index.d.ts +6 -4
  181. package/lib/typescript/module/components/Slider/Slider.d.ts +12 -1
  182. package/lib/typescript/module/components/Stepper/Stepper.d.ts +18 -6
  183. package/lib/typescript/module/components/Swipeable/Swipeable.d.ts +2 -0
  184. package/lib/typescript/module/components/Switch/Switch.d.ts +1 -0
  185. package/lib/typescript/module/components/Tabs/Tabs.d.ts +26 -2
  186. package/lib/typescript/module/components/TimePicker/TimePicker.d.ts +36 -3
  187. package/lib/typescript/module/components/Toast/Toast.d.ts +8 -0
  188. package/lib/typescript/module/components/Tooltip/Tooltip.d.ts +7 -1
  189. package/lib/typescript/module/components/index.d.ts +5 -5
  190. package/lib/typescript/module/index.d.ts +1 -1
  191. package/lib/typescript/module/theme/index.d.ts +1 -1
  192. package/lib/typescript/module/theme/types.d.ts +578 -12
  193. package/package.json +2 -6
  194. package/lib/commonjs/components/AppIcon/AppIcon.js +0 -120
  195. package/lib/commonjs/types/vector-icons.d.js +0 -2
  196. package/lib/module/components/AppIcon/AppIcon.js +0 -111
  197. package/lib/module/components/AppIcon/index.js +0 -4
  198. package/lib/module/types/vector-icons.d.js +0 -2
  199. package/lib/typescript/commonjs/components/AppIcon/AppIcon.d.ts +0 -20
  200. package/lib/typescript/commonjs/components/AppIcon/index.d.ts +0 -3
  201. package/lib/typescript/module/components/AppIcon/AppIcon.d.ts +0 -20
  202. package/lib/typescript/module/components/AppIcon/index.d.ts +0 -3
@@ -10,9 +10,12 @@ var _reactNativeSafeAreaContext = require("react-native-safe-area-context");
10
10
  var _index = require("../../theme/index.js");
11
11
  var _usePressAnimation = require("../../hooks/usePressAnimation.js");
12
12
  var _hapticUtils = require("../../utils/hapticUtils.js");
13
- var _index2 = require("../AppIcon/index.js");
14
13
  var _jsxRuntime = require("react/jsx-runtime");
15
14
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
15
+ // Local shape mirror — see types.ts FloatingActionButtonTokens for the canonical
16
+ // definition. Declared here so the component can read tokens before types.ts is
17
+ // regenerated; will collapse to a direct import once that lands.
18
+
16
19
  const sizeMap = {
17
20
  sm: {
18
21
  diameter: 40,
@@ -52,9 +55,6 @@ const toneForeground = (theme, tone) => {
52
55
  if (tone === 'neutral') return theme.colors.text.primary;
53
56
  return theme.colors.text.inverse;
54
57
  };
55
- const isIconConfig = value => {
56
- return typeof value === 'object' && value !== null && ! /*#__PURE__*/_react.default.isValidElement(value) && typeof value.name === 'string';
57
- };
58
58
  const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
59
59
  const {
60
60
  icon,
@@ -70,6 +70,8 @@ const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _re
70
70
  accessibilityLabel,
71
71
  accessibilityHint,
72
72
  style,
73
+ containerStyle,
74
+ labelStyle,
73
75
  testID
74
76
  } = props;
75
77
  const theme = (0, _index.useTheme)();
@@ -83,6 +85,10 @@ const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _re
83
85
  } = (0, _usePressAnimation.usePressAnimation)({
84
86
  enabled: !disabled
85
87
  });
88
+ const fabTokens = theme.components.floatingActionButton;
89
+ const edgeOffset = fabTokens?.edgeOffset ?? 24;
90
+ const defaultBottomOffset = fabTokens?.bottomOffset ?? 24;
91
+ const pressHaptic = fabTokens?.pressHaptic ?? false;
86
92
  const hideAnim = (0, _react.useRef)((0, _index.createAnimatedValue)(0)).current;
87
93
  (0, _react.useEffect)(() => {
88
94
  if (!hideOnScroll) {
@@ -98,7 +104,7 @@ const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _re
98
104
  }, [hideOnScroll, isScrolling, hideAnim, theme.motion.duration.normal, theme.motion.easing.standard]);
99
105
  const hideTranslateY = hideAnim.interpolate({
100
106
  inputRange: [0, 1],
101
- outputRange: [0, sizeStyles.diameter + (bottomOffset ?? 24) + insets.bottom + 24]
107
+ outputRange: [0, sizeStyles.diameter + (bottomOffset ?? defaultBottomOffset) + insets.bottom + edgeOffset]
102
108
  });
103
109
  const hideOpacity = hideAnim.interpolate({
104
110
  inputRange: [0, 1],
@@ -106,27 +112,22 @@ const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _re
106
112
  });
107
113
  const handlePress = _event => {
108
114
  if (disabled) return;
109
- (0, _hapticUtils.triggerHaptic)('impactLight');
115
+ if (pressHaptic) (0, _hapticUtils.triggerHaptic)('impactLight');
110
116
  onPress();
111
117
  };
112
- const renderedIcon = isIconConfig(icon) ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.AppIcon, {
113
- name: icon.name,
114
- family: icon.family ?? 'feather',
115
- size: sizeStyles.iconSize,
116
- color: toneForeground(theme, tone)
117
- }) : icon;
118
+ const renderedIcon = icon;
118
119
  const isExtended = typeof label === 'string' && label.length > 0;
119
120
  const backgroundColor = disabled ? theme.colors.surface.disabled : toneBackground(theme, tone);
120
121
  const foregroundColor = disabled ? theme.colors.text.disabled : toneForeground(theme, tone);
121
122
  const positionStyle = (0, _react.useMemo)(() => {
122
123
  if (!position) return null;
123
- const bottom = (bottomOffset ?? 24) + insets.bottom;
124
+ const bottom = (bottomOffset ?? defaultBottomOffset) + insets.bottom;
124
125
  switch (position) {
125
126
  case 'bottomLeft':
126
127
  return {
127
128
  position: 'absolute',
128
129
  bottom,
129
- left: 24
130
+ left: edgeOffset
130
131
  };
131
132
  case 'bottomCenter':
132
133
  return {
@@ -139,10 +140,10 @@ const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _re
139
140
  return {
140
141
  position: 'absolute',
141
142
  bottom,
142
- right: 24
143
+ right: edgeOffset
143
144
  };
144
145
  }
145
- }, [position, bottomOffset, insets.bottom]);
146
+ }, [position, bottomOffset, insets.bottom, defaultBottomOffset, edgeOffset]);
146
147
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Animated.View, {
147
148
  style: [positionStyle, {
148
149
  transform: [{
@@ -151,7 +152,7 @@ const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _re
151
152
  scale
152
153
  }],
153
154
  opacity: hideOpacity
154
- }, style],
155
+ }, containerStyle, style],
155
156
  pointerEvents: hideOnScroll && isScrolling ? 'none' : 'auto',
156
157
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Pressable, {
157
158
  ref: ref,
@@ -188,7 +189,7 @@ const FloatingActionButton = exports.FloatingActionButton = /*#__PURE__*/(0, _re
188
189
  fontSize: sizeStyles.fontSize,
189
190
  fontWeight: theme.typography.fontWeight.semibold,
190
191
  marginLeft: theme.spacing.sm
191
- }],
192
+ }, labelStyle],
192
193
  numberOfLines: 1,
193
194
  children: label
194
195
  }) : null]
@@ -214,8 +215,6 @@ const buildStyles = _theme => _reactNative.StyleSheet.create({
214
215
  // so they remain smooth during JS thread work.
215
216
  // =====================================================================
216
217
 
217
- const SECONDARY_GAP = 16;
218
- const STAGGER_MS = 50;
219
218
  const FloatingActionButtonGroup = props => {
220
219
  const {
221
220
  primaryIcon,
@@ -228,28 +227,54 @@ const FloatingActionButtonGroup = props => {
228
227
  bottomOffset,
229
228
  size = 'md',
230
229
  accessibilityLabel = 'Quick actions',
230
+ containerStyle,
231
+ secondaryActionStyle,
232
+ labelPillStyle,
233
+ labelStyle,
231
234
  testID
232
235
  } = props;
233
236
  const theme = (0, _index.useTheme)();
234
237
  const insets = (0, _reactNativeSafeAreaContext.useSafeAreaInsets)();
235
238
  const sizeStyles = sizeMap[size];
236
239
  const styles = (0, _react.useMemo)(() => buildGroupStyles(theme), [theme]);
240
+ const fabTokens = theme.components.floatingActionButton;
241
+ const edgeOffset = fabTokens?.edgeOffset ?? 24;
242
+ const defaultBottomOffset = fabTokens?.bottomOffset ?? 24;
243
+ const secondaryGap = fabTokens?.secondaryGap ?? 16;
244
+ const staggerMs = fabTokens?.staggerMs ?? 50;
245
+ const pressHaptic = fabTokens?.pressHaptic ?? false;
237
246
  const isControlled = typeof controlledOpen === 'boolean';
238
247
  const [internalOpen, setInternalOpen] = (0, _react.useState)(defaultOpen);
239
248
  const isOpen = isControlled ? controlledOpen : internalOpen;
240
249
 
241
250
  // Animation drivers
242
251
  const progress = (0, _react.useRef)((0, _index.createAnimatedValue)(isOpen ? 1 : 0)).current;
252
+ // Stable refs for per-item Animated.Values. Reconciled inside useEffect — never
253
+ // mutated during render — so re-renders don't recreate Animated.Value instances
254
+ // (previous implementation leaked one Animated.Value per re-render when the
255
+ // actions array length changed).
243
256
  const itemAnims = (0, _react.useRef)([]);
244
-
245
- // Resize per-item anim array if action count changes
246
- if (itemAnims.current.length !== actions.length) {
247
- const next = [];
248
- for (let i = 0; i < actions.length; i += 1) {
249
- next.push(itemAnims.current[i] ?? new _reactNative.Animated.Value(isOpen ? 1 : 0));
257
+ // Bump this when the underlying refs array is re-shaped so downstream effects
258
+ // and mapping reads see the new length.
259
+ const [itemAnimsVersion, setItemAnimsVersion] = (0, _react.useState)(0);
260
+ (0, _react.useEffect)(() => {
261
+ const current = itemAnims.current;
262
+ if (current.length === actions.length) return;
263
+ if (current.length < actions.length) {
264
+ const next = current.slice();
265
+ for (let i = current.length; i < actions.length; i += 1) {
266
+ next.push(new _reactNative.Animated.Value(isOpen ? 1 : 0));
267
+ }
268
+ itemAnims.current = next;
269
+ } else {
270
+ // Drop stale refs when actions array shrinks.
271
+ itemAnims.current = current.slice(0, actions.length);
250
272
  }
251
- itemAnims.current = next;
252
- }
273
+ setItemAnimsVersion(v => v + 1);
274
+ // isOpen intentionally not in deps — only used to seed brand-new values; the
275
+ // open/close effect below will animate them to the correct target anyway.
276
+ // eslint-disable-next-line react-hooks/exhaustive-deps
277
+ }, [actions.length]);
253
278
  (0, _react.useEffect)(() => {
254
279
  _reactNative.Animated.timing(progress, {
255
280
  toValue: isOpen ? 1 : 0,
@@ -265,34 +290,34 @@ const FloatingActionButtonGroup = props => {
265
290
  }));
266
291
  // Reverse stagger order on close so items closest to primary collapse last
267
292
  const ordered = isOpen ? animations : [...animations].reverse();
268
- _reactNative.Animated.stagger(STAGGER_MS, ordered).start();
269
- }, [isOpen, progress, theme.motion.duration.normal, theme.motion.easing.standard, actions.length]);
293
+ _reactNative.Animated.stagger(staggerMs, ordered).start();
294
+ }, [isOpen, progress, theme.motion.duration.normal, theme.motion.easing.standard, actions.length, itemAnimsVersion, staggerMs]);
270
295
  const setOpen = (0, _react.useCallback)(next => {
271
- (0, _hapticUtils.triggerHaptic)('impactLight');
296
+ if (pressHaptic) (0, _hapticUtils.triggerHaptic)('impactLight');
272
297
  if (!isControlled) setInternalOpen(next);
273
298
  onOpenChange?.(next);
274
- }, [isControlled, onOpenChange]);
299
+ }, [isControlled, onOpenChange, pressHaptic]);
275
300
  const handlePrimaryPress = (0, _react.useCallback)(() => {
276
301
  setOpen(!isOpen);
277
302
  }, [isOpen, setOpen]);
278
303
  const handleActionPress = (0, _react.useCallback)(action => {
279
- (0, _hapticUtils.triggerHaptic)('selection');
304
+ if (pressHaptic) (0, _hapticUtils.triggerHaptic)('selection');
280
305
  action.onPress();
281
306
  // Close after action runs
282
307
  if (!isControlled) setInternalOpen(false);
283
308
  onOpenChange?.(false);
284
- }, [isControlled, onOpenChange]);
309
+ }, [isControlled, onOpenChange, pressHaptic]);
285
310
  const handleBackdropPress = (0, _react.useCallback)(() => {
286
311
  if (isOpen) setOpen(false);
287
312
  }, [isOpen, setOpen]);
288
313
  const positionStyle = (0, _react.useMemo)(() => {
289
- const bottom = (bottomOffset ?? 24) + insets.bottom;
314
+ const bottom = (bottomOffset ?? defaultBottomOffset) + insets.bottom;
290
315
  switch (position) {
291
316
  case 'bottomLeft':
292
317
  return {
293
318
  position: 'absolute',
294
319
  bottom,
295
- left: 24,
320
+ left: edgeOffset,
296
321
  alignItems: 'flex-start'
297
322
  };
298
323
  case 'bottomCenter':
@@ -307,14 +332,14 @@ const FloatingActionButtonGroup = props => {
307
332
  return {
308
333
  position: 'absolute',
309
334
  bottom,
310
- right: 24,
335
+ right: edgeOffset,
311
336
  alignItems: 'flex-end'
312
337
  };
313
338
  }
314
- }, [position, bottomOffset, insets.bottom]);
339
+ }, [position, bottomOffset, insets.bottom, defaultBottomOffset, edgeOffset]);
315
340
 
316
341
  // Vertical slot offset per index: secondary at index i sits (diameter + gap) * (i + 1) above primary
317
- const slotOffset = index => -((sizeStyles.diameter + SECONDARY_GAP) * (index + 1));
342
+ const slotOffset = index => -((sizeStyles.diameter + secondaryGap) * (index + 1));
318
343
  const backdropOpacity = progress.interpolate({
319
344
  inputRange: [0, 1],
320
345
  outputRange: [0, 0.4]
@@ -338,7 +363,7 @@ const FloatingActionButtonGroup = props => {
338
363
  testID: testID ? `${testID}-backdrop` : undefined
339
364
  })
340
365
  }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
341
- style: positionStyle,
366
+ style: [positionStyle, containerStyle],
342
367
  accessibilityRole: 'menu',
343
368
  testID: testID,
344
369
  children: [actions.map((action, index) => {
@@ -374,13 +399,13 @@ const FloatingActionButtonGroup = props => {
374
399
  paddingVertical: theme.spacing.xs,
375
400
  borderRadius: theme.radius.sm,
376
401
  marginRight: theme.spacing.sm
377
- }],
402
+ }, labelPillStyle],
378
403
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
379
- style: {
404
+ style: [{
380
405
  color: theme.colors.text.primary,
381
406
  fontSize: theme.typography.fontSize.sm,
382
407
  fontWeight: theme.typography.fontWeight.medium
383
- },
408
+ }, labelStyle],
384
409
  numberOfLines: 1,
385
410
  children: action.label
386
411
  })
@@ -397,7 +422,7 @@ const FloatingActionButtonGroup = props => {
397
422
  height: secondaryDiameter,
398
423
  borderRadius: secondaryDiameter / 2,
399
424
  backgroundColor: itemBackground
400
- }],
425
+ }, secondaryActionStyle],
401
426
  testID: testID ? `${testID}-action-${action.key}` : undefined,
402
427
  children: /*#__PURE__*/_react.default.isValidElement(action.icon) ? action.icon : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
403
428
  style: {
@@ -32,7 +32,10 @@ const ForceUpdateDialog = ({
32
32
  title = 'Update available',
33
33
  message = 'A new version of the app is available. Please update to continue using the latest features and security improvements.',
34
34
  updateLabel = 'Update now',
35
- laterLabel = 'Later'
35
+ laterLabel = 'Later',
36
+ containerStyle,
37
+ titleStyle,
38
+ messageStyle
36
39
  }) => {
37
40
  const [updating, setUpdating] = (0, _react.useState)(false);
38
41
  const handleUpdate = (0, _react.useCallback)(() => {
@@ -73,7 +76,10 @@ const ForceUpdateDialog = ({
73
76
  message: message,
74
77
  variant: "info",
75
78
  actions: actions,
76
- dismissOnAction: false
79
+ dismissOnAction: false,
80
+ containerStyle: containerStyle,
81
+ titleStyle: titleStyle,
82
+ messageStyle: messageStyle
77
83
  });
78
84
  };
79
85
  exports.ForceUpdateDialog = ForceUpdateDialog;
@@ -21,6 +21,7 @@ const FormField = exports.FormField = /*#__PURE__*/(0, _react.forwardRef)((props
21
21
  helperStyle,
22
22
  errorStyle,
23
23
  containerStyle,
24
+ inputContainerStyle: inputContainerStyleProp,
24
25
  accessibilityLabel,
25
26
  testID
26
27
  } = props;
@@ -61,12 +62,12 @@ const FormField = exports.FormField = /*#__PURE__*/(0, _react.forwardRef)((props
61
62
  testID: testID,
62
63
  children: [layout === 'inline' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
63
64
  children: [labelNode, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
64
- style: inputContainerStyle,
65
+ style: [inputContainerStyle, inputContainerStyleProp],
65
66
  children: children
66
67
  })]
67
68
  }) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
68
69
  children: [labelNode, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
69
- style: inputContainerStyle,
70
+ style: [inputContainerStyle, inputContainerStyleProp],
70
71
  children: children
71
72
  })]
72
73
  }), showHelper ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
@@ -9,10 +9,9 @@ var _reactNative = require("react-native");
9
9
  var _reactNativeGestureHandler = require("react-native-gesture-handler");
10
10
  var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
11
11
  var _index = require("../Carousel/index.js");
12
- var _index2 = require("../AppIcon/index.js");
13
- var _index3 = require("../Skeleton/index.js");
14
- var _index4 = require("../../theme/index.js");
15
- var _index5 = require("../../utils/index.js");
12
+ var _index2 = require("../Skeleton/index.js");
13
+ var _index3 = require("../../theme/index.js");
14
+ var _index4 = require("../../utils/index.js");
16
15
  var _jsxRuntime = require("react/jsx-runtime");
17
16
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
18
17
  /**
@@ -34,9 +33,11 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
34
33
  * />
35
34
  */
36
35
 
37
- const MAX_SCALE = 4;
38
- const MIN_SCALE = 1;
39
- const DOUBLE_TAP_SCALE = 2;
36
+ // Local shape mirror — see types.ts ImageGalleryTokens for the canonical definition.
37
+
38
+ const MAX_SCALE_FALLBACK = 4;
39
+ const MIN_SCALE_FALLBACK = 1;
40
+ const DOUBLE_TAP_SCALE_FALLBACK = 2;
40
41
  const SPRING_CONFIG = {
41
42
  damping: 18,
42
43
  stiffness: 220,
@@ -55,8 +56,10 @@ const ImageGallery = ({
55
56
  containerStyle,
56
57
  testID
57
58
  }) => {
58
- const theme = (0, _index4.useTheme)();
59
+ const theme = (0, _index3.useTheme)();
59
60
  const styles = (0, _react.useMemo)(() => buildStyles(theme), [theme]);
61
+ const galleryTokens = theme.components.imageGallery;
62
+ const pressHaptic = galleryTokens?.pressHaptic ?? false;
60
63
  const [currentIndex, setCurrentIndex] = (0, _react.useState)(clamp(initialIndex, 0, Math.max(0, images.length - 1)));
61
64
  const [lightboxOpen, setLightboxOpen] = (0, _react.useState)(false);
62
65
  const handleIndexChange = (0, _react.useCallback)(idx => {
@@ -65,13 +68,13 @@ const ImageGallery = ({
65
68
  }, [onIndexChange]);
66
69
  const openLightbox = (0, _react.useCallback)(() => {
67
70
  if (!enableLightbox) return;
68
- (0, _index5.triggerHaptic)('selection');
71
+ if (pressHaptic) (0, _index4.triggerHaptic)('selection');
69
72
  setLightboxOpen(true);
70
- }, [enableLightbox]);
73
+ }, [enableLightbox, pressHaptic]);
71
74
  const closeLightbox = (0, _react.useCallback)(() => {
72
- (0, _index5.triggerHaptic)('selection');
75
+ if (pressHaptic) (0, _index4.triggerHaptic)('selection');
73
76
  setLightboxOpen(false);
74
- }, []);
77
+ }, [pressHaptic]);
75
78
  const renderImage = (0, _react.useCallback)((image, idx) => {
76
79
  const a11y = image.alt ?? `Image ${idx + 1} of ${images.length}`;
77
80
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
@@ -124,14 +127,17 @@ const ImageGallery = ({
124
127
  enablePinchZoom: enablePinchZoom,
125
128
  showCounter: showCounter,
126
129
  onClose: closeLightbox,
127
- onIndexChange: handleIndexChange
130
+ onIndexChange: handleIndexChange,
131
+ pressHaptic: pressHaptic
128
132
  }) : null]
129
133
  });
130
134
  if (loading) {
131
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_index3.SkeletonContent, {
132
- loading: true,
133
- mode: "auto",
134
- children: rendered
135
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(ImageGallerySkeleton, {
136
+ images: images,
137
+ showThumbnails: showThumbnails,
138
+ showCounter: showCounter,
139
+ containerStyle: containerStyle,
140
+ testID: testID
135
141
  });
136
142
  }
137
143
  return rendered;
@@ -139,6 +145,69 @@ const ImageGallery = ({
139
145
  exports.ImageGallery = ImageGallery;
140
146
  ImageGallery.displayName = 'ImageGallery';
141
147
 
148
+ /**
149
+ * Placeholder shape for `<ImageGallery>`. Hero image block + optional
150
+ * counter pill + thumbnail strip. Heights are tuned to match the live
151
+ * component's defaults so the gallery doesn't reflow when ready.
152
+ */
153
+ const ImageGallerySkeleton = ({
154
+ images,
155
+ showThumbnails = true,
156
+ showCounter = true,
157
+ containerStyle,
158
+ testID
159
+ }) => {
160
+ const thumbCount = Math.min(images?.length || 4, 6);
161
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
162
+ style: [{
163
+ width: '100%'
164
+ }, containerStyle],
165
+ testID: testID,
166
+ accessibilityRole: "progressbar",
167
+ accessibilityState: {
168
+ busy: true
169
+ },
170
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
171
+ style: {
172
+ position: 'relative'
173
+ },
174
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.Skeleton, {
175
+ width: "100%",
176
+ height: 280,
177
+ radius: "lg"
178
+ }), showCounter ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
179
+ style: {
180
+ position: 'absolute',
181
+ top: 12,
182
+ right: 12
183
+ },
184
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.Skeleton, {
185
+ width: 44,
186
+ height: 22,
187
+ radius: "full"
188
+ })
189
+ }) : null]
190
+ }), showThumbnails ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
191
+ style: {
192
+ flexDirection: 'row',
193
+ marginTop: 12
194
+ },
195
+ children: Array.from({
196
+ length: thumbCount
197
+ }).map((_, i) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.Skeleton, {
198
+ width: 64,
199
+ height: 64,
200
+ radius: "md",
201
+ style: {
202
+ marginRight: 8
203
+ }
204
+ }, `sk-thumb-${i}`))
205
+ }) : null]
206
+ });
207
+ };
208
+ ImageGallerySkeleton.displayName = 'ImageGallerySkeleton';
209
+ ImageGallery.Skeleton = ImageGallerySkeleton;
210
+
142
211
  // ───────── Lightbox ─────────
143
212
 
144
213
  const Lightbox = ({
@@ -148,26 +217,35 @@ const Lightbox = ({
148
217
  enablePinchZoom,
149
218
  showCounter,
150
219
  onClose,
151
- onIndexChange
220
+ onIndexChange,
221
+ pressHaptic
152
222
  }) => {
153
- const theme = (0, _index4.useTheme)();
223
+ const theme = (0, _index3.useTheme)();
154
224
  const styles = (0, _react.useMemo)(() => buildLightboxStyles(theme), [theme]);
225
+ const galleryTokens = theme.components.imageGallery;
226
+ const maxScale = galleryTokens?.maxScale ?? MAX_SCALE_FALLBACK;
227
+ const minScale = galleryTokens?.minScale ?? MIN_SCALE_FALLBACK;
228
+ const doubleTapScale = galleryTokens?.doubleTapScale ?? DOUBLE_TAP_SCALE_FALLBACK;
155
229
  const carouselRef = (0, _react.useRef)(null);
156
230
  const [activeIndex, setActiveIndex] = (0, _react.useState)(initialIndex);
157
231
  const handleSwipe = (0, _react.useCallback)(idx => {
158
232
  if (idx !== activeIndex) {
159
- (0, _index5.triggerHaptic)('selection');
233
+ if (pressHaptic) (0, _index4.triggerHaptic)('selection');
160
234
  setActiveIndex(idx);
161
235
  onIndexChange(idx);
162
236
  }
163
- }, [activeIndex, onIndexChange]);
237
+ }, [activeIndex, onIndexChange, pressHaptic]);
164
238
  const renderItem = (0, _react.useCallback)((image, idx) => /*#__PURE__*/(0, _jsxRuntime.jsx)(ZoomableImage, {
165
239
  image: image,
166
240
  index: idx,
167
241
  total: images.length,
168
242
  active: idx === activeIndex,
169
- enabled: enablePinchZoom
170
- }), [activeIndex, enablePinchZoom, images.length]);
243
+ enabled: enablePinchZoom,
244
+ maxScale: maxScale,
245
+ minScale: minScale,
246
+ doubleTapScale: doubleTapScale,
247
+ pressHaptic: pressHaptic
248
+ }), [activeIndex, enablePinchZoom, images.length, maxScale, minScale, doubleTapScale, pressHaptic]);
171
249
  const caption = images[activeIndex]?.caption;
172
250
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Modal, {
173
251
  visible: visible,
@@ -203,11 +281,15 @@ const Lightbox = ({
203
281
  accessibilityLabel: "Close gallery",
204
282
  style: styles.closeButton,
205
283
  hitSlop: 12,
206
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index2.AppIcon, {
207
- name: "x",
208
- family: "feather",
209
- size: "lg",
284
+ children: theme.icons?.close ? theme.icons.close({
285
+ size: 24,
210
286
  color: theme.colors.text.inverse
287
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
288
+ style: {
289
+ fontSize: 24,
290
+ color: theme.colors.text.inverse
291
+ },
292
+ children: "\xD7"
211
293
  })
212
294
  }), caption ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
213
295
  style: styles.captionWrap,
@@ -230,7 +312,11 @@ const ZoomableImage = ({
230
312
  index,
231
313
  total,
232
314
  active,
233
- enabled
315
+ enabled,
316
+ maxScale,
317
+ minScale,
318
+ doubleTapScale,
319
+ pressHaptic
234
320
  }) => {
235
321
  const screen = _reactNative.Dimensions.get('window');
236
322
  const scale = (0, _reactNativeReanimated.useSharedValue)(1);
@@ -265,7 +351,9 @@ const ZoomableImage = ({
265
351
  savedTranslateY.value = 0;
266
352
  }
267
353
  }, [active, scale, translateX, translateY, savedScale, savedTranslateX, savedTranslateY]);
268
- const triggerImpact = (0, _react.useCallback)(() => (0, _index5.triggerHaptic)('impactLight'), []);
354
+ const triggerImpact = (0, _react.useCallback)(() => {
355
+ if (pressHaptic) (0, _index4.triggerHaptic)('impactLight');
356
+ }, [pressHaptic]);
269
357
  const pinch = (0, _react.useMemo)(() => _reactNativeGestureHandler.Gesture.Pinch().enabled(enabled).onStart(() => {
270
358
  'worklet';
271
359
 
@@ -274,33 +362,33 @@ const ZoomableImage = ({
274
362
  'worklet';
275
363
 
276
364
  const next = savedScale.value * e.scale;
277
- // Clamp 1..MAX_SCALE on the UI thread so pinch feels rubbery at limits.
278
- if (next < MIN_SCALE) {
279
- scale.value = MIN_SCALE + (next - MIN_SCALE) * 0.3;
280
- } else if (next > MAX_SCALE) {
281
- scale.value = MAX_SCALE + (next - MAX_SCALE) * 0.2;
365
+ // Clamp minScale..maxScale on the UI thread so pinch feels rubbery at limits.
366
+ if (next < minScale) {
367
+ scale.value = minScale + (next - minScale) * 0.3;
368
+ } else if (next > maxScale) {
369
+ scale.value = maxScale + (next - maxScale) * 0.2;
282
370
  } else {
283
371
  scale.value = next;
284
372
  }
285
373
  }).onEnd(() => {
286
374
  'worklet';
287
375
 
288
- if (scale.value < MIN_SCALE) {
289
- scale.value = (0, _reactNativeReanimated.withSpring)(MIN_SCALE, SPRING_CONFIG);
376
+ if (scale.value < minScale) {
377
+ scale.value = (0, _reactNativeReanimated.withSpring)(minScale, SPRING_CONFIG);
290
378
  translateX.value = (0, _reactNativeReanimated.withSpring)(0, SPRING_CONFIG);
291
379
  translateY.value = (0, _reactNativeReanimated.withSpring)(0, SPRING_CONFIG);
292
- savedScale.value = MIN_SCALE;
380
+ savedScale.value = minScale;
293
381
  savedTranslateX.value = 0;
294
382
  savedTranslateY.value = 0;
295
383
  return;
296
384
  }
297
- if (scale.value > MAX_SCALE) {
298
- scale.value = (0, _reactNativeReanimated.withSpring)(MAX_SCALE, SPRING_CONFIG);
299
- savedScale.value = MAX_SCALE;
385
+ if (scale.value > maxScale) {
386
+ scale.value = (0, _reactNativeReanimated.withSpring)(maxScale, SPRING_CONFIG);
387
+ savedScale.value = maxScale;
300
388
  return;
301
389
  }
302
390
  savedScale.value = scale.value;
303
- }), [enabled, scale, savedScale, translateX, translateY, savedTranslateX, savedTranslateY]);
391
+ }), [enabled, scale, savedScale, translateX, translateY, savedTranslateX, savedTranslateY, minScale, maxScale]);
304
392
 
305
393
  // Pan only engages when zoomed in — otherwise the parent Carousel owns horizontal swipe.
306
394
  const pan = (0, _react.useMemo)(() => _reactNativeGestureHandler.Gesture.Pan().minPointers(1).maxPointers(1).onStart(() => {
@@ -332,10 +420,10 @@ const ZoomableImage = ({
332
420
  savedTranslateX.value = 0;
333
421
  savedTranslateY.value = 0;
334
422
  } else {
335
- scale.value = (0, _reactNativeReanimated.withSpring)(DOUBLE_TAP_SCALE, SPRING_CONFIG);
336
- savedScale.value = DOUBLE_TAP_SCALE;
423
+ scale.value = (0, _reactNativeReanimated.withSpring)(doubleTapScale, SPRING_CONFIG);
424
+ savedScale.value = doubleTapScale;
337
425
  }
338
- }), [scale, savedScale, translateX, translateY, savedTranslateX, savedTranslateY, triggerImpact]);
426
+ }), [scale, savedScale, translateX, translateY, savedTranslateX, savedTranslateY, triggerImpact, doubleTapScale]);
339
427
 
340
428
  // Race the gestures so they coordinate cleanly: a tap won't be misread as a tiny pan,
341
429
  // and pan won't fire when the user actually starts a pinch.