@webority-technologies/mobile 0.0.12 → 0.0.14

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 (47) hide show
  1. package/lib/commonjs/components/Badge/Badge.js +1 -1
  2. package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +11 -3
  3. package/lib/commonjs/components/BottomSheet/BottomSheet.js +45 -6
  4. package/lib/commonjs/components/DatePicker/DatePicker.js +18 -12
  5. package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +14 -9
  6. package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +1 -1
  7. package/lib/commonjs/components/Input/Input.js +1 -1
  8. package/lib/commonjs/components/Modal/Modal.js +4 -4
  9. package/lib/commonjs/components/OTPInput/OTPInput.js +29 -9
  10. package/lib/commonjs/components/ProgressBar/ProgressBar.js +1 -1
  11. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +23 -28
  12. package/lib/commonjs/components/Skeleton/Skeleton.js +1 -1
  13. package/lib/commonjs/components/Slider/Slider.js +11 -11
  14. package/lib/commonjs/components/Stepper/Stepper.js +10 -4
  15. package/lib/commonjs/components/Tabs/Tabs.js +7 -5
  16. package/lib/commonjs/components/TimePicker/TimePicker.js +3 -3
  17. package/lib/commonjs/components/Toast/Toast.js +2 -2
  18. package/lib/commonjs/theme/animatedValue.js +20 -1
  19. package/lib/commonjs/theme/index.js +8 -1
  20. package/lib/module/components/Badge/Badge.js +2 -2
  21. package/lib/module/components/BottomNavigation/BottomNavigation.js +11 -3
  22. package/lib/module/components/BottomSheet/BottomSheet.js +47 -8
  23. package/lib/module/components/DatePicker/DatePicker.js +19 -13
  24. package/lib/module/components/DateRangePicker/DateRangePicker.js +15 -10
  25. package/lib/module/components/FloatingActionButton/FloatingActionButton.js +2 -2
  26. package/lib/module/components/Input/Input.js +2 -2
  27. package/lib/module/components/Modal/Modal.js +5 -5
  28. package/lib/module/components/OTPInput/OTPInput.js +30 -10
  29. package/lib/module/components/ProgressBar/ProgressBar.js +2 -2
  30. package/lib/module/components/SegmentedControl/SegmentedControl.js +24 -29
  31. package/lib/module/components/Skeleton/Skeleton.js +2 -2
  32. package/lib/module/components/Slider/Slider.js +12 -12
  33. package/lib/module/components/Stepper/Stepper.js +10 -4
  34. package/lib/module/components/Tabs/Tabs.js +7 -5
  35. package/lib/module/components/TimePicker/TimePicker.js +4 -4
  36. package/lib/module/components/Toast/Toast.js +3 -3
  37. package/lib/module/theme/animatedValue.js +18 -0
  38. package/lib/module/theme/index.js +1 -1
  39. package/lib/typescript/commonjs/components/BottomNavigation/BottomNavigation.d.ts +7 -0
  40. package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +10 -0
  41. package/lib/typescript/commonjs/theme/animatedValue.d.ts +11 -0
  42. package/lib/typescript/commonjs/theme/index.d.ts +1 -1
  43. package/lib/typescript/module/components/BottomNavigation/BottomNavigation.d.ts +7 -0
  44. package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +10 -0
  45. package/lib/typescript/module/theme/animatedValue.d.ts +11 -0
  46. package/lib/typescript/module/theme/index.d.ts +1 -1
  47. package/package.json +1 -1
@@ -8,7 +8,7 @@
8
8
  * fully accessible (radiogroup / radio roles + selected state).
9
9
  */
10
10
 
11
- import React, { forwardRef, useCallback, useEffect, useMemo, useRef } from 'react';
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
14
  import { triggerHaptic } from "../../utils/index.js";
@@ -45,44 +45,39 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
45
45
  const styles = useMemo(() => buildStyles(theme), [theme]);
46
46
  const sizeStyles = sizeMap[size];
47
47
 
48
- // Total track width measured from onLayout; thumb width = trackWidth / segments.length.
49
- const trackWidthRef = useRef(0);
48
+ // Track width is measured from onLayout. Thumb width is a regular number (not
49
+ // animated) `width` cannot be driven by the native animated module, and mixing
50
+ // a JS-driven width with a native-driven translateX inside `Animated.parallel`
51
+ // sends the parallel composite into the native driver and JS setValue/timing
52
+ // calls on the same value then throw "moved to native". Keep width as state and
53
+ // only animate translateX via the native driver.
54
+ const [trackWidth, setTrackWidth] = useState(0);
50
55
  const thumbTranslateX = useRef(createAnimatedValue(0)).current;
51
- const thumbWidth = useRef(createAnimatedValue(0)).current;
52
56
  const activeIndex = Math.max(0, segments.findIndex(s => s.value === value));
53
- const animateThumb = useCallback((index, totalWidth) => {
54
- if (totalWidth <= 0 || segments.length === 0) return;
55
- const segWidth = (totalWidth - TRACK_PADDING * 2) / segments.length;
57
+ const segmentWidth = trackWidth > 0 ? (trackWidth - TRACK_PADDING * 2) / Math.max(segments.length, 1) : 0;
58
+ const animateThumb = useCallback((index, segWidth) => {
59
+ if (segWidth <= 0) return;
56
60
  const targetX = TRACK_PADDING + segWidth * index;
57
61
  const spring = theme.motion.spring.snappy;
58
- Animated.parallel([Animated.spring(thumbTranslateX, {
62
+ Animated.spring(thumbTranslateX, {
59
63
  toValue: targetX,
60
64
  damping: spring.damping,
61
65
  stiffness: spring.stiffness,
62
66
  mass: spring.mass,
63
67
  useNativeDriver: true
64
- }), Animated.spring(thumbWidth, {
65
- toValue: segWidth,
66
- damping: spring.damping,
67
- stiffness: spring.stiffness,
68
- mass: spring.mass,
69
- useNativeDriver: false
70
- })]).start();
71
- }, [segments.length, theme.motion.spring.snappy, thumbTranslateX, thumbWidth]);
68
+ }).start();
69
+ }, [theme.motion.spring.snappy, thumbTranslateX]);
72
70
  useEffect(() => {
73
- if (trackWidthRef.current > 0) {
74
- animateThumb(activeIndex, trackWidthRef.current);
71
+ if (segmentWidth > 0) {
72
+ animateThumb(activeIndex, segmentWidth);
75
73
  }
76
- }, [activeIndex, animateThumb]);
74
+ }, [activeIndex, segmentWidth, animateThumb]);
77
75
  const handleTrackLayout = useCallback(e => {
78
76
  const width = e.nativeEvent.layout.width;
79
- if (width === trackWidthRef.current) return;
80
- trackWidthRef.current = width;
81
- // Initial-position the thumb without animation jitter — set then animate to active.
82
- const segWidth = (width - TRACK_PADDING * 2) / Math.max(segments.length, 1);
83
- thumbWidth.setValue(segWidth);
84
- thumbTranslateX.setValue(TRACK_PADDING + segWidth * activeIndex);
85
- }, [activeIndex, segments.length, thumbTranslateX, thumbWidth]);
77
+ if (width !== trackWidth) {
78
+ setTrackWidth(width);
79
+ }
80
+ }, [trackWidth]);
86
81
  const handlePress = useCallback(segment => {
87
82
  if (disabled) return;
88
83
  if (segment.value === value) return;
@@ -105,10 +100,10 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
105
100
  alignSelf: fullWidth ? 'stretch' : 'flex-start'
106
101
  }, style],
107
102
  onLayout: handleTrackLayout,
108
- children: [/*#__PURE__*/_jsx(Animated.View, {
103
+ children: [segmentWidth > 0 ? /*#__PURE__*/_jsx(Animated.View, {
109
104
  pointerEvents: "none",
110
105
  style: [styles.thumb, {
111
- width: thumbWidth,
106
+ width: segmentWidth,
112
107
  height: sizeStyles.height - TRACK_PADDING * 2,
113
108
  borderRadius: theme.radius.sm,
114
109
  backgroundColor: thumbBg,
@@ -117,7 +112,7 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
117
112
  }],
118
113
  ...theme.shadows.sm
119
114
  }]
120
- }), segments.map(segment => {
115
+ }) : null, segments.map(segment => {
121
116
  const isActive = segment.value === value;
122
117
  return /*#__PURE__*/_jsxs(Pressable, {
123
118
  onPress: () => handlePress(segment),
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { Animated, Easing, StyleSheet, View } from 'react-native';
5
- import { useTheme, createAnimatedValue } from "../../theme/index.js";
5
+ import { useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
6
6
  import { Responsive } from "../../utils/index.js";
7
7
  import { useSkeletonDefaults } from "./SkeletonProvider.js";
8
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -50,7 +50,7 @@ const Skeleton = ({
50
50
  const progress = useRef(createAnimatedValue(0)).current;
51
51
  const [containerWidth, setContainerWidth] = useState(0);
52
52
  useEffect(() => {
53
- progress.setValue(0);
53
+ setNativeValue(progress, 0);
54
54
  const duration = resolvedVariant === 'pulse' ? PULSE_DURATION : SPEED_DURATION[resolvedSpeed];
55
55
  const animation = resolvedVariant === 'pulse' ? Animated.loop(Animated.sequence([Animated.timing(progress, {
56
56
  toValue: 1,
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { Animated, Easing, PanResponder, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
5
- import { useTheme, createAnimatedValue } from "../../theme/index.js";
5
+ import { useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
6
6
  import { triggerHaptic } from "../../utils/index.js";
7
7
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
8
  const SIZE_MAP = {
@@ -105,14 +105,14 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
105
105
  highRef.current = hi;
106
106
  lastReportedLow.current = lo;
107
107
  lastReportedHigh.current = hi;
108
- lowX.setValue(valueToPx(lo, trackWidth));
109
- highX.setValue(valueToPx(hi, trackWidth));
108
+ setNativeValue(lowX, valueToPx(lo, trackWidth));
109
+ setNativeValue(highX, valueToPx(hi, trackWidth));
110
110
  } else {
111
111
  const v = props.value;
112
112
  lowRef.current = v;
113
113
  highRef.current = v;
114
114
  lastReportedLow.current = v;
115
- lowX.setValue(valueToPx(v, trackWidth));
115
+ setNativeValue(lowX, valueToPx(v, trackWidth));
116
116
  }
117
117
  // We intentionally listen to props.value across both shapes via JSON; ESLint is fine.
118
118
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -125,10 +125,10 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
125
125
  const [v0, v1] = props.value;
126
126
  const lo = Math.min(v0, v1);
127
127
  const hi = Math.max(v0, v1);
128
- lowX.setValue(valueToPx(lo, w));
129
- highX.setValue(valueToPx(hi, w));
128
+ setNativeValue(lowX, valueToPx(lo, w));
129
+ setNativeValue(highX, valueToPx(hi, w));
130
130
  } else {
131
- lowX.setValue(valueToPx(props.value, w));
131
+ setNativeValue(lowX, valueToPx(props.value, w));
132
132
  }
133
133
  },
134
134
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -179,7 +179,7 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
179
179
  lastReportedLow.current = nextValue;
180
180
  }
181
181
  lowRef.current = nextValue;
182
- lowX.setValue(valueToPx(nextValue, trackWidth));
182
+ setNativeValue(lowX, valueToPx(nextValue, trackWidth));
183
183
  fireChange(nextValue, highRef.current);
184
184
  } else {
185
185
  if (isRange && nextValue < lowRef.current) nextValue = lowRef.current;
@@ -188,7 +188,7 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
188
188
  lastReportedHigh.current = nextValue;
189
189
  }
190
190
  highRef.current = nextValue;
191
- highX.setValue(valueToPx(nextValue, trackWidth));
191
+ setNativeValue(highX, valueToPx(nextValue, trackWidth));
192
192
  fireChange(lowRef.current, nextValue);
193
193
  }
194
194
  },
@@ -218,7 +218,7 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
218
218
  toValue: valueToPx(next, trackWidth),
219
219
  duration: theme.motion.duration.fast,
220
220
  easing: Easing.out(Easing.cubic),
221
- useNativeDriver: false
221
+ useNativeDriver: true
222
222
  }).start();
223
223
  fireChange(next, next);
224
224
  }
@@ -233,7 +233,7 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
233
233
  if (nextLow !== lowRef.current) {
234
234
  lowRef.current = nextLow;
235
235
  lastReportedLow.current = nextLow;
236
- lowX.setValue(valueToPx(nextLow, trackWidth));
236
+ setNativeValue(lowX, valueToPx(nextLow, trackWidth));
237
237
  triggerHaptic('selection');
238
238
  fireChange(nextLow, highRef.current);
239
239
  }
@@ -242,7 +242,7 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
242
242
  if (next !== lowRef.current) {
243
243
  lowRef.current = next;
244
244
  lastReportedLow.current = next;
245
- lowX.setValue(valueToPx(next, trackWidth));
245
+ setNativeValue(lowX, valueToPx(next, trackWidth));
246
246
  triggerHaptic('selection');
247
247
  fireChange(next, next);
248
248
  }
@@ -23,6 +23,7 @@ const StepCircle = ({
23
23
  status,
24
24
  toneColor,
25
25
  upcomingColor,
26
+ upcomingFillColor,
26
27
  textOnColor,
27
28
  upcomingTextColor,
28
29
  interactive,
@@ -65,7 +66,7 @@ const StepCircle = ({
65
66
  loop.start();
66
67
  return () => loop.stop();
67
68
  }, [isActive, pulseScale, pulseOpacity]);
68
- const bgColor = status === 'upcoming' ? 'transparent' : toneColor;
69
+ const bgColor = status === 'upcoming' ? upcomingFillColor : toneColor;
69
70
  const borderColor = status === 'upcoming' ? upcomingColor : toneColor;
70
71
  const textColor = status === 'upcoming' ? upcomingTextColor : textOnColor;
71
72
  const isComplete = status === 'complete';
@@ -169,6 +170,7 @@ const Stepper = /*#__PURE__*/forwardRef((props, ref) => {
169
170
  const styles = useMemo(() => buildStyles(theme), [theme]);
170
171
  const toneColor = toneColorFor(theme, tone);
171
172
  const upcomingColor = theme.colors.border.primary;
173
+ const upcomingFillColor = theme.colors.background.primary;
172
174
  const upcomingTextColor = theme.colors.text.secondary;
173
175
  const textOnColor = theme.colors.text.inverse;
174
176
  const interactive = typeof onStepPress === 'function';
@@ -198,11 +200,15 @@ const Stepper = /*#__PURE__*/forwardRef((props, ref) => {
198
200
  outputRange: ['0%', '100%']
199
201
  });
200
202
  const a11yLabel = accessibilityLabel ?? `Progress: step ${activeStep + 1} of ${total}`;
203
+ const halfStepPct = total > 0 ? `${50 / total}%` : `0%`;
201
204
  const renderHorizontal = () => /*#__PURE__*/_jsxs(View, {
202
205
  style: styles.hRow,
203
206
  children: [/*#__PURE__*/_jsxs(View, {
204
207
  pointerEvents: "none",
205
- style: styles.hConnectorContainer,
208
+ style: [styles.hConnectorContainer, {
209
+ left: halfStepPct,
210
+ right: halfStepPct
211
+ }],
206
212
  children: [/*#__PURE__*/_jsx(View, {
207
213
  style: [styles.hConnectorTrack, {
208
214
  backgroundColor: upcomingColor
@@ -223,6 +229,7 @@ const Stepper = /*#__PURE__*/forwardRef((props, ref) => {
223
229
  status: status,
224
230
  toneColor: toneColor,
225
231
  upcomingColor: upcomingColor,
232
+ upcomingFillColor: upcomingFillColor,
226
233
  onPressColor: toneColor,
227
234
  textOnColor: textOnColor,
228
235
  upcomingTextColor: upcomingTextColor,
@@ -255,6 +262,7 @@ const Stepper = /*#__PURE__*/forwardRef((props, ref) => {
255
262
  status: status,
256
263
  toneColor: toneColor,
257
264
  upcomingColor: upcomingColor,
265
+ upcomingFillColor: upcomingFillColor,
258
266
  onPressColor: toneColor,
259
267
  textOnColor: textOnColor,
260
268
  upcomingTextColor: upcomingTextColor,
@@ -333,8 +341,6 @@ const buildStyles = theme => StyleSheet.create({
333
341
  hConnectorContainer: {
334
342
  position: 'absolute',
335
343
  top: CIRCLE_SIZE / 2 - 1,
336
- left: CIRCLE_SIZE / 2,
337
- right: CIRCLE_SIZE / 2,
338
344
  height: 2,
339
345
  flexDirection: 'row',
340
346
  alignItems: 'center'
@@ -42,15 +42,17 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
42
42
  useEffect(() => {
43
43
  if (!activeLayout) return;
44
44
  const spring = theme.motion.spring.snappy;
45
- Animated.parallel([Animated.spring(indicatorTranslateX, {
45
+ Animated.parallel([
46
+ // Both must use the JS driver: width can't run on native, and mixing
47
+ // drivers on the same view (transform native + width JS) trips RN's
48
+ // "node already moved to native" guard under the new architecture.
49
+ Animated.spring(indicatorTranslateX, {
46
50
  toValue: activeLayout.x,
47
51
  damping: spring.damping,
48
52
  stiffness: spring.stiffness,
49
53
  mass: spring.mass,
50
- useNativeDriver: true
51
- }),
52
- // width is a layout prop — must run on JS thread (useNativeDriver: false).
53
- Animated.spring(indicatorWidth, {
54
+ useNativeDriver: false
55
+ }), Animated.spring(indicatorWidth, {
54
56
  toValue: activeLayout.width,
55
57
  damping: spring.damping,
56
58
  stiffness: spring.stiffness,
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { AccessibilityInfo, Animated, Easing, FlatList, Modal, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
5
- import { useTheme, createAnimatedValue } from "../../theme/index.js";
5
+ import { useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
6
6
  import { triggerHaptic } from "../../utils/hapticUtils.js";
7
7
  import Button from "../Button/Button.js";
8
8
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
@@ -68,7 +68,7 @@ const Wheel = ({
68
68
  if (lastIndexRef.current !== selectedIndex) {
69
69
  lastIndexRef.current = selectedIndex;
70
70
  const offset = selectedIndex * ITEM_HEIGHT;
71
- scrollY.setValue(offset);
71
+ setNativeValue(scrollY, offset);
72
72
  // Defer to next frame so FlatList has measured.
73
73
  requestAnimationFrame(() => {
74
74
  listRef.current?.scrollToOffset({
@@ -275,8 +275,8 @@ const TimePicker = ({
275
275
  useNativeDriver: true
276
276
  })]).start();
277
277
  } else {
278
- opacity.setValue(0);
279
- translateY.setValue(40);
278
+ setNativeValue(opacity, 0);
279
+ setNativeValue(translateY, 40);
280
280
  }
281
281
  }, [visible, opacity, translateY, theme.motion]);
282
282
  const announce = useCallback(msg => {
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useEffect, useMemo, useRef } from 'react';
4
4
  import { Animated, PanResponder, Pressable, StyleSheet, Text, View } from 'react-native';
5
- import { fontFor, useTheme, createAnimatedValue } from "../../theme/index.js";
5
+ import { fontFor, useTheme, createAnimatedValue, setNativeValue } from "../../theme/index.js";
6
6
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
7
  const SWIPE_DISMISS_THRESHOLD = 80;
8
8
  const SWIPE_VELOCITY_THRESHOLD = 0.5;
@@ -68,9 +68,9 @@ const Toast = ({
68
68
  const panResponder = useMemo(() => PanResponder.create({
69
69
  onMoveShouldSetPanResponder: (_evt, gesture) => Math.abs(gesture.dx) > Math.abs(gesture.dy) && Math.abs(gesture.dx) > 6,
70
70
  onPanResponderMove: (_evt, gesture) => {
71
- translateX.setValue(gesture.dx);
71
+ setNativeValue(translateX, gesture.dx);
72
72
  const fade = 1 - Math.min(Math.abs(gesture.dx) / 200, 1) * 0.7;
73
- opacity.setValue(fade);
73
+ setNativeValue(opacity, fade);
74
74
  },
75
75
  onPanResponderRelease: (_evt, gesture) => {
76
76
  if (Math.abs(gesture.dx) > SWIPE_DISMISS_THRESHOLD || Math.abs(gesture.vx) > SWIPE_VELOCITY_THRESHOLD) {
@@ -21,4 +21,22 @@ import { Animated } from 'react-native';
21
21
  * Use everywhere the library would otherwise call `new Animated.Value(...)`.
22
22
  */
23
23
  export const createAnimatedValue = (initial, config) => Object.seal(new Animated.Value(initial, config));
24
+
25
+ /**
26
+ * Set an `Animated.Value` to a target without going through JS.
27
+ *
28
+ * Once a value has been driven by `useNativeDriver: true`, the underlying
29
+ * native node owns it — calling `value.setValue(x)` from JS throws
30
+ * "Attempting to run JS driven animation on animated node that has been moved to native".
31
+ * Use this helper for any value that is *also* used in a native-driven
32
+ * `Animated.timing/spring`. A zero-duration native timing routes the update
33
+ * through the same driver and stays valid across re-mounts and re-runs.
34
+ */
35
+ export const setNativeValue = (value, to) => {
36
+ Animated.timing(value, {
37
+ toValue: to,
38
+ duration: 0,
39
+ useNativeDriver: true
40
+ }).start();
41
+ };
24
42
  //# sourceMappingURL=animatedValue.js.map
@@ -46,6 +46,6 @@ export { ThemeProvider, useTheme, useThemeMode } from "./ThemeContext.js";
46
46
  export { lightTheme, darkTheme } from "./tokens.js";
47
47
  export { mergeTheme } from "./merge.js";
48
48
  export { fontFor } from "./textStyle.js";
49
- export { createAnimatedValue } from "./animatedValue.js";
49
+ export { createAnimatedValue, setNativeValue } from "./animatedValue.js";
50
50
  export { Gradient, isGradientAvailable } from "./Gradient.js";
51
51
  //# sourceMappingURL=index.js.map
@@ -3,6 +3,7 @@ import { View } from 'react-native';
3
3
  import type { StyleProp, TextStyle, ViewStyle } from 'react-native';
4
4
  import type { HapticType } from '../../utils';
5
5
  export type BottomNavigationVariant = 'pill' | 'underline';
6
+ export type BottomNavigationIndicatorPosition = 'top' | 'bottom';
6
7
  export type TabBadge = number | string | boolean | null;
7
8
  export interface TabIconProps {
8
9
  color: string;
@@ -23,6 +24,12 @@ export interface BottomNavigationProps {
23
24
  haptic?: HapticType | false;
24
25
  showLabels?: boolean;
25
26
  variant?: BottomNavigationVariant;
27
+ /**
28
+ * Where the active-tab line sits, for variants that draw a line
29
+ * (currently `underline`). Default `'bottom'` preserves the legacy look;
30
+ * `'top'` flips the line to sit just above the tab row.
31
+ */
32
+ indicatorPosition?: BottomNavigationIndicatorPosition;
26
33
  style?: StyleProp<ViewStyle>;
27
34
  indicatorStyle?: StyleProp<ViewStyle>;
28
35
  labelStyle?: StyleProp<TextStyle>;
@@ -20,6 +20,7 @@ import React from 'react';
20
20
  import type { StyleProp, ViewStyle } from 'react-native';
21
21
  export type SnapPoint = number | `${number}%`;
22
22
  export type KeyboardBehavior = 'none' | 'shift';
23
+ export type BottomSheetMode = 'modal' | 'inline';
23
24
  export interface BottomSheetProps {
24
25
  snapPoints: SnapPoint[];
25
26
  index?: number;
@@ -37,6 +38,15 @@ export interface BottomSheetProps {
37
38
  * sheet itself.
38
39
  */
39
40
  keyboardBehavior?: KeyboardBehavior;
41
+ /**
42
+ * How the sheet is mounted in the view tree.
43
+ * - `'modal'` (default): rendered inside a native `<Modal>` so the backdrop
44
+ * covers the entire screen (status bar, headers, tab bars) — the standard
45
+ * bottom-sheet UX.
46
+ * - `'inline'`: rendered as an `absoluteFill` overlay inside the parent
47
+ * component. Useful when embedding a sheet within a bounded area.
48
+ */
49
+ mode?: BottomSheetMode;
40
50
  handleIndicatorStyle?: StyleProp<ViewStyle>;
41
51
  containerStyle?: StyleProp<ViewStyle>;
42
52
  children?: React.ReactNode;
@@ -18,4 +18,15 @@ import { Animated } from 'react-native';
18
18
  * Use everywhere the library would otherwise call `new Animated.Value(...)`.
19
19
  */
20
20
  export declare const createAnimatedValue: (initial: number, config?: ConstructorParameters<typeof Animated.Value>[1]) => Animated.Value;
21
+ /**
22
+ * Set an `Animated.Value` to a target without going through JS.
23
+ *
24
+ * Once a value has been driven by `useNativeDriver: true`, the underlying
25
+ * native node owns it — calling `value.setValue(x)` from JS throws
26
+ * "Attempting to run JS driven animation on animated node that has been moved to native".
27
+ * Use this helper for any value that is *also* used in a native-driven
28
+ * `Animated.timing/spring`. A zero-duration native timing routes the update
29
+ * through the same driver and stays valid across re-mounts and re-runs.
30
+ */
31
+ export declare const setNativeValue: (value: Animated.Value, to: number) => void;
21
32
  //# sourceMappingURL=animatedValue.d.ts.map
@@ -11,7 +11,7 @@ export { lightTheme, darkTheme } from './tokens';
11
11
  export { mergeTheme } from './merge';
12
12
  export { fontFor } from './textStyle';
13
13
  export type { FontWeightKey } from './textStyle';
14
- export { createAnimatedValue } from './animatedValue';
14
+ export { createAnimatedValue, setNativeValue } from './animatedValue';
15
15
  export { Gradient, isGradientAvailable } from './Gradient';
16
16
  export type { GradientProps } from './Gradient';
17
17
  export type { ColorMode, ColorPalette, GradientDefinition, GradientScale, RadiusScale, ShadowDefinition, ShadowScale, SpacingScale, Theme, ThemeOverrides, TypographyScale, MotionScale, DeepPartial } from './types';
@@ -3,6 +3,7 @@ import { View } from 'react-native';
3
3
  import type { StyleProp, TextStyle, ViewStyle } from 'react-native';
4
4
  import type { HapticType } from '../../utils';
5
5
  export type BottomNavigationVariant = 'pill' | 'underline';
6
+ export type BottomNavigationIndicatorPosition = 'top' | 'bottom';
6
7
  export type TabBadge = number | string | boolean | null;
7
8
  export interface TabIconProps {
8
9
  color: string;
@@ -23,6 +24,12 @@ export interface BottomNavigationProps {
23
24
  haptic?: HapticType | false;
24
25
  showLabels?: boolean;
25
26
  variant?: BottomNavigationVariant;
27
+ /**
28
+ * Where the active-tab line sits, for variants that draw a line
29
+ * (currently `underline`). Default `'bottom'` preserves the legacy look;
30
+ * `'top'` flips the line to sit just above the tab row.
31
+ */
32
+ indicatorPosition?: BottomNavigationIndicatorPosition;
26
33
  style?: StyleProp<ViewStyle>;
27
34
  indicatorStyle?: StyleProp<ViewStyle>;
28
35
  labelStyle?: StyleProp<TextStyle>;
@@ -20,6 +20,7 @@ import React from 'react';
20
20
  import type { StyleProp, ViewStyle } from 'react-native';
21
21
  export type SnapPoint = number | `${number}%`;
22
22
  export type KeyboardBehavior = 'none' | 'shift';
23
+ export type BottomSheetMode = 'modal' | 'inline';
23
24
  export interface BottomSheetProps {
24
25
  snapPoints: SnapPoint[];
25
26
  index?: number;
@@ -37,6 +38,15 @@ export interface BottomSheetProps {
37
38
  * sheet itself.
38
39
  */
39
40
  keyboardBehavior?: KeyboardBehavior;
41
+ /**
42
+ * How the sheet is mounted in the view tree.
43
+ * - `'modal'` (default): rendered inside a native `<Modal>` so the backdrop
44
+ * covers the entire screen (status bar, headers, tab bars) — the standard
45
+ * bottom-sheet UX.
46
+ * - `'inline'`: rendered as an `absoluteFill` overlay inside the parent
47
+ * component. Useful when embedding a sheet within a bounded area.
48
+ */
49
+ mode?: BottomSheetMode;
40
50
  handleIndicatorStyle?: StyleProp<ViewStyle>;
41
51
  containerStyle?: StyleProp<ViewStyle>;
42
52
  children?: React.ReactNode;
@@ -18,4 +18,15 @@ import { Animated } from 'react-native';
18
18
  * Use everywhere the library would otherwise call `new Animated.Value(...)`.
19
19
  */
20
20
  export declare const createAnimatedValue: (initial: number, config?: ConstructorParameters<typeof Animated.Value>[1]) => Animated.Value;
21
+ /**
22
+ * Set an `Animated.Value` to a target without going through JS.
23
+ *
24
+ * Once a value has been driven by `useNativeDriver: true`, the underlying
25
+ * native node owns it — calling `value.setValue(x)` from JS throws
26
+ * "Attempting to run JS driven animation on animated node that has been moved to native".
27
+ * Use this helper for any value that is *also* used in a native-driven
28
+ * `Animated.timing/spring`. A zero-duration native timing routes the update
29
+ * through the same driver and stays valid across re-mounts and re-runs.
30
+ */
31
+ export declare const setNativeValue: (value: Animated.Value, to: number) => void;
21
32
  //# sourceMappingURL=animatedValue.d.ts.map
@@ -11,7 +11,7 @@ export { lightTheme, darkTheme } from './tokens';
11
11
  export { mergeTheme } from './merge';
12
12
  export { fontFor } from './textStyle';
13
13
  export type { FontWeightKey } from './textStyle';
14
- export { createAnimatedValue } from './animatedValue';
14
+ export { createAnimatedValue, setNativeValue } from './animatedValue';
15
15
  export { Gradient, isGradientAvailable } from './Gradient';
16
16
  export type { GradientProps } from './Gradient';
17
17
  export type { ColorMode, ColorPalette, GradientDefinition, GradientScale, RadiusScale, ShadowDefinition, ShadowScale, SpacingScale, Theme, ThemeOverrides, TypographyScale, MotionScale, DeepPartial } from './types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority-technologies/mobile",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "description": "Beautiful, animated, accessible React Native components plus API/auth/logging/network/storage utilities for Webority projects.",
5
5
  "keywords": [
6
6
  "react-native",