@webority-technologies/mobile 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/components/Accordion/Accordion.js +3 -3
- package/lib/commonjs/components/Avatar/Avatar.js +1 -1
- package/lib/commonjs/components/Badge/Badge.js +24 -14
- package/lib/commonjs/components/Banner/Banner.js +2 -2
- package/lib/commonjs/components/BottomNavigation/BottomNavigation.js +1 -1
- package/lib/commonjs/components/BottomSheet/BottomSheet.js +39 -5
- package/lib/commonjs/components/Button/Button.js +25 -6
- package/lib/commonjs/components/Card/Card.js +13 -1
- package/lib/commonjs/components/Carousel/Carousel.js +2 -2
- package/lib/commonjs/components/Checkbox/Checkbox.js +6 -4
- package/lib/commonjs/components/Chip/Chip.js +12 -3
- package/lib/commonjs/components/DatePicker/DatePicker.js +8 -8
- package/lib/commonjs/components/DateRangePicker/DateRangePicker.js +4 -4
- package/lib/commonjs/components/Dialog/Dialog.js +15 -8
- package/lib/commonjs/components/EmptyState/EmptyState.js +32 -26
- package/lib/commonjs/components/FloatingActionButton/FloatingActionButton.js +2 -2
- package/lib/commonjs/components/FormField/FormField.js +4 -4
- package/lib/commonjs/components/Input/Input.js +18 -10
- package/lib/commonjs/components/ListItem/ListItem.js +33 -27
- package/lib/commonjs/components/Modal/Modal.js +4 -4
- package/lib/commonjs/components/OTPInput/OTPInput.js +7 -4
- package/lib/commonjs/components/ProgressBar/ProgressBar.js +2 -2
- package/lib/commonjs/components/Radio/Radio.js +8 -7
- package/lib/commonjs/components/SearchBar/SearchBar.js +10 -6
- package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +2 -2
- package/lib/commonjs/components/Select/Select.js +3 -3
- package/lib/commonjs/components/Skeleton/Skeleton.js +1 -1
- package/lib/commonjs/components/Slider/Slider.js +6 -6
- package/lib/commonjs/components/Spinner/Spinner.js +2 -2
- package/lib/commonjs/components/Stepper/Stepper.js +3 -3
- package/lib/commonjs/components/Switch/Switch.js +33 -4
- package/lib/commonjs/components/Tabs/Tabs.js +2 -2
- package/lib/commonjs/components/TimePicker/TimePicker.js +3 -3
- package/lib/commonjs/components/Toast/Toast.js +19 -14
- package/lib/commonjs/components/Tooltip/Tooltip.js +2 -2
- package/lib/commonjs/theme/Gradient.js +57 -0
- package/lib/commonjs/theme/animatedValue.js +28 -0
- package/lib/commonjs/theme/index.js +27 -0
- package/lib/commonjs/theme/textStyle.js +37 -0
- package/lib/commonjs/theme/tokens.js +260 -2
- package/lib/module/components/Accordion/Accordion.js +4 -4
- package/lib/module/components/Avatar/Avatar.js +2 -2
- package/lib/module/components/Badge/Badge.js +25 -15
- package/lib/module/components/Banner/Banner.js +3 -3
- package/lib/module/components/BottomNavigation/BottomNavigation.js +2 -2
- package/lib/module/components/BottomSheet/BottomSheet.js +40 -6
- package/lib/module/components/Button/Button.js +26 -7
- package/lib/module/components/Card/Card.js +14 -2
- package/lib/module/components/Carousel/Carousel.js +3 -3
- package/lib/module/components/Checkbox/Checkbox.js +7 -5
- package/lib/module/components/Chip/Chip.js +13 -4
- package/lib/module/components/DatePicker/DatePicker.js +9 -9
- package/lib/module/components/DateRangePicker/DateRangePicker.js +5 -5
- package/lib/module/components/Dialog/Dialog.js +16 -9
- package/lib/module/components/EmptyState/EmptyState.js +33 -27
- package/lib/module/components/FloatingActionButton/FloatingActionButton.js +3 -3
- package/lib/module/components/FormField/FormField.js +5 -5
- package/lib/module/components/Input/Input.js +19 -11
- package/lib/module/components/ListItem/ListItem.js +34 -28
- package/lib/module/components/Modal/Modal.js +5 -5
- package/lib/module/components/OTPInput/OTPInput.js +8 -5
- package/lib/module/components/ProgressBar/ProgressBar.js +3 -3
- package/lib/module/components/Radio/Radio.js +9 -8
- package/lib/module/components/SearchBar/SearchBar.js +11 -7
- package/lib/module/components/SegmentedControl/SegmentedControl.js +3 -3
- package/lib/module/components/Select/Select.js +4 -4
- package/lib/module/components/Skeleton/Skeleton.js +2 -2
- package/lib/module/components/Slider/Slider.js +7 -7
- package/lib/module/components/Spinner/Spinner.js +3 -3
- package/lib/module/components/Stepper/Stepper.js +4 -4
- package/lib/module/components/Switch/Switch.js +34 -5
- package/lib/module/components/Tabs/Tabs.js +3 -3
- package/lib/module/components/TimePicker/TimePicker.js +4 -4
- package/lib/module/components/Toast/Toast.js +20 -15
- package/lib/module/components/Tooltip/Tooltip.js +3 -3
- package/lib/module/theme/Gradient.js +50 -0
- package/lib/module/theme/animatedValue.js +24 -0
- package/lib/module/theme/index.js +3 -0
- package/lib/module/theme/textStyle.js +32 -0
- package/lib/module/theme/tokens.js +260 -2
- package/lib/typescript/commonjs/components/BottomSheet/BottomSheet.d.ts +10 -0
- package/lib/typescript/commonjs/components/Button/Button.d.ts +8 -0
- package/lib/typescript/commonjs/components/Card/Card.d.ts +8 -0
- package/lib/typescript/commonjs/components/Dialog/Dialog.d.ts +5 -0
- package/lib/typescript/commonjs/components/Input/Input.d.ts +12 -0
- package/lib/typescript/commonjs/components/Switch/Switch.d.ts +5 -0
- package/lib/typescript/commonjs/components/Toast/Toast.d.ts +5 -0
- package/lib/typescript/commonjs/theme/Gradient.d.ts +11 -0
- package/lib/typescript/commonjs/theme/animatedValue.d.ts +21 -0
- package/lib/typescript/commonjs/theme/index.d.ts +6 -1
- package/lib/typescript/commonjs/theme/textStyle.d.ts +18 -0
- package/lib/typescript/commonjs/theme/types.d.ts +178 -0
- package/lib/typescript/module/components/BottomSheet/BottomSheet.d.ts +10 -0
- package/lib/typescript/module/components/Button/Button.d.ts +8 -0
- package/lib/typescript/module/components/Card/Card.d.ts +8 -0
- package/lib/typescript/module/components/Dialog/Dialog.d.ts +5 -0
- package/lib/typescript/module/components/Input/Input.d.ts +12 -0
- package/lib/typescript/module/components/Switch/Switch.d.ts +5 -0
- package/lib/typescript/module/components/Toast/Toast.d.ts +5 -0
- package/lib/typescript/module/theme/Gradient.d.ts +11 -0
- package/lib/typescript/module/theme/animatedValue.d.ts +21 -0
- package/lib/typescript/module/theme/index.d.ts +6 -1
- package/lib/typescript/module/theme/textStyle.d.ts +18 -0
- package/lib/typescript/module/theme/types.d.ts +178 -0
- package/package.json +5 -1
|
@@ -5,7 +5,7 @@ import { Animated, Easing, Pressable, StyleSheet, Text, TextInput, View } from '
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
6
6
|
// @ts-ignore - react-native-vector-icons ships no bundled types in this version
|
|
7
7
|
import Feather from 'react-native-vector-icons/Feather';
|
|
8
|
-
import { useTheme } from "../../theme/index.js";
|
|
8
|
+
import { createAnimatedValue, fontFor, useTheme } from "../../theme/index.js";
|
|
9
9
|
import { triggerHaptic } from "../../utils/index.js";
|
|
10
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
11
|
const sizeMap = {
|
|
@@ -55,6 +55,8 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
55
55
|
variant = 'outlined',
|
|
56
56
|
required = false,
|
|
57
57
|
maxLength,
|
|
58
|
+
format,
|
|
59
|
+
parse,
|
|
58
60
|
style,
|
|
59
61
|
inputStyle,
|
|
60
62
|
labelStyle,
|
|
@@ -67,7 +69,10 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
67
69
|
} = props;
|
|
68
70
|
const theme = useTheme();
|
|
69
71
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
70
|
-
const sizeStyles =
|
|
72
|
+
const sizeStyles = {
|
|
73
|
+
...sizeMap[size],
|
|
74
|
+
...(theme.components.input?.[size] ?? {})
|
|
75
|
+
};
|
|
71
76
|
const [isFocused, setIsFocused] = useState(false);
|
|
72
77
|
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
|
|
73
78
|
const hasValue = typeof value === 'string' && value.length > 0;
|
|
@@ -77,11 +82,11 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
77
82
|
const showFloatingLabel = Boolean(label) && !multiline;
|
|
78
83
|
|
|
79
84
|
// Animations
|
|
80
|
-
const focusAnim = useRef(
|
|
81
|
-
const errorAnim = useRef(
|
|
82
|
-
const labelAnim = useRef(
|
|
83
|
-
const shakeAnim = useRef(
|
|
84
|
-
const messageAnim = useRef(
|
|
85
|
+
const focusAnim = useRef(createAnimatedValue(0)).current;
|
|
86
|
+
const errorAnim = useRef(createAnimatedValue(0)).current;
|
|
87
|
+
const labelAnim = useRef(createAnimatedValue(shouldFloat ? 1 : 0)).current;
|
|
88
|
+
const shakeAnim = useRef(createAnimatedValue(0)).current;
|
|
89
|
+
const messageAnim = useRef(createAnimatedValue(hasError || helperText ? 1 : 0)).current;
|
|
85
90
|
|
|
86
91
|
// Focus border animation
|
|
87
92
|
useEffect(() => {
|
|
@@ -217,7 +222,7 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
217
222
|
style: [styles.staticLabel, {
|
|
218
223
|
color: hasError ? theme.colors.error : isFocused ? theme.colors.border.focus : theme.colors.text.secondary,
|
|
219
224
|
fontSize: theme.typography.fontSize.sm,
|
|
220
|
-
|
|
225
|
+
...fontFor(theme, 'medium'),
|
|
221
226
|
marginBottom: theme.spacing.xxs
|
|
222
227
|
}, labelStyle],
|
|
223
228
|
children: [label, required ? /*#__PURE__*/_jsx(Text, {
|
|
@@ -251,7 +256,7 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
251
256
|
left: leftPad,
|
|
252
257
|
color: labelColor,
|
|
253
258
|
fontSize: sizeStyles.fontSize,
|
|
254
|
-
|
|
259
|
+
...fontFor(theme, 'medium'),
|
|
255
260
|
backgroundColor: shouldFloat && variant === 'outlined' ? theme.colors.background.primary : 'transparent',
|
|
256
261
|
paddingHorizontal: shouldFloat && variant === 'outlined' ? 4 : 0,
|
|
257
262
|
transform: [{
|
|
@@ -277,8 +282,11 @@ const Input = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
277
282
|
}, inputStyle],
|
|
278
283
|
placeholder: showFloatingLabel && !shouldFloat ? undefined : placeholder,
|
|
279
284
|
placeholderTextColor: placeholderTextColor,
|
|
280
|
-
value: value,
|
|
281
|
-
onChangeText:
|
|
285
|
+
value: format && value != null ? format(value) : value,
|
|
286
|
+
onChangeText: text => {
|
|
287
|
+
if (!onChangeText) return;
|
|
288
|
+
onChangeText(parse ? parse(text) : text);
|
|
289
|
+
},
|
|
282
290
|
onFocus: handleFocus,
|
|
283
291
|
onBlur: handleBlur,
|
|
284
292
|
editable: isEditable,
|
|
@@ -2,38 +2,44 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useMemo } from 'react';
|
|
4
4
|
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { fontFor, useTheme } from "../../theme/index.js";
|
|
6
6
|
import { usePressAnimation } from "../../hooks/usePressAnimation.js";
|
|
7
7
|
import { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
8
8
|
import { Swipeable } from "../Swipeable/index.js";
|
|
9
9
|
import { SkeletonContent } from "../Skeleton/index.js";
|
|
10
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
paddingVertical: theme.spacing.md,
|
|
31
|
-
titleSize: theme.typography.fontSize.base,
|
|
32
|
-
subtitleSize: theme.typography.fontSize.sm,
|
|
33
|
-
minHeight: 56
|
|
34
|
-
};
|
|
11
|
+
const SIZE_FALLBACK = {
|
|
12
|
+
sm: {
|
|
13
|
+
paddingVertical: 'sm',
|
|
14
|
+
titleFontSize: 'sm',
|
|
15
|
+
subtitleFontSize: 'xs',
|
|
16
|
+
minHeight: 44
|
|
17
|
+
},
|
|
18
|
+
md: {
|
|
19
|
+
paddingVertical: 'md',
|
|
20
|
+
titleFontSize: 'base',
|
|
21
|
+
subtitleFontSize: 'sm',
|
|
22
|
+
minHeight: 56
|
|
23
|
+
},
|
|
24
|
+
lg: {
|
|
25
|
+
paddingVertical: 'lg',
|
|
26
|
+
titleFontSize: 'lg',
|
|
27
|
+
subtitleFontSize: 'sm',
|
|
28
|
+
minHeight: 72
|
|
35
29
|
}
|
|
36
30
|
};
|
|
31
|
+
const sizeFor = (theme, size) => {
|
|
32
|
+
const tokens = {
|
|
33
|
+
...SIZE_FALLBACK[size],
|
|
34
|
+
...(theme.components.listItem?.[size] ?? {})
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
paddingVertical: theme.spacing[tokens.paddingVertical],
|
|
38
|
+
titleSize: theme.typography.fontSize[tokens.titleFontSize],
|
|
39
|
+
subtitleSize: theme.typography.fontSize[tokens.subtitleFontSize],
|
|
40
|
+
minHeight: tokens.minHeight
|
|
41
|
+
};
|
|
42
|
+
};
|
|
37
43
|
const Chevron = ({
|
|
38
44
|
color
|
|
39
45
|
}) => /*#__PURE__*/_jsx(Text, {
|
|
@@ -101,7 +107,7 @@ const ListItem = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
101
107
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
102
108
|
style: [styles.title, {
|
|
103
109
|
fontSize: sz.titleSize,
|
|
104
|
-
|
|
110
|
+
...fontFor(theme, 'medium'),
|
|
105
111
|
color: disabled ? theme.colors.text.disabled : theme.colors.text.primary
|
|
106
112
|
}],
|
|
107
113
|
numberOfLines: 1,
|
|
@@ -232,11 +238,11 @@ const buildStyles = theme => StyleSheet.create({
|
|
|
232
238
|
},
|
|
233
239
|
subtitle: {
|
|
234
240
|
marginTop: 2,
|
|
235
|
-
|
|
241
|
+
...fontFor(theme, 'normal')
|
|
236
242
|
},
|
|
237
243
|
description: {
|
|
238
244
|
marginTop: 2,
|
|
239
|
-
|
|
245
|
+
...fontFor(theme, 'normal')
|
|
240
246
|
}
|
|
241
247
|
});
|
|
242
248
|
export { ListItem };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { AccessibilityInfo, Animated, Dimensions, findNodeHandle, Modal as RNModal, Pressable, StyleSheet, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
6
|
import { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
7
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
8
|
const Modal = /*#__PURE__*/forwardRef((props, ref) => {
|
|
@@ -24,10 +24,10 @@ const Modal = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
24
24
|
const theme = useTheme();
|
|
25
25
|
const duration = animationDuration ?? theme.motion.duration.normal;
|
|
26
26
|
const screenHeight = Dimensions.get('window').height;
|
|
27
|
-
const backdropAnim = useRef(
|
|
28
|
-
const scaleAnim = useRef(
|
|
29
|
-
const opacityAnim = useRef(
|
|
30
|
-
const translateYAnim = useRef(
|
|
27
|
+
const backdropAnim = useRef(createAnimatedValue(0)).current;
|
|
28
|
+
const scaleAnim = useRef(createAnimatedValue(0.9)).current;
|
|
29
|
+
const opacityAnim = useRef(createAnimatedValue(0)).current;
|
|
30
|
+
const translateYAnim = useRef(createAnimatedValue(screenHeight)).current;
|
|
31
31
|
const containerRef = useRef(null);
|
|
32
32
|
const wasVisibleRef = useRef(false);
|
|
33
33
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { Animated, Easing, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { fontFor, useTheme, createAnimatedValue } 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 sizeMap = {
|
|
@@ -52,11 +52,14 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
52
52
|
} = props;
|
|
53
53
|
const theme = useTheme();
|
|
54
54
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
55
|
-
const sizeStyles =
|
|
55
|
+
const sizeStyles = {
|
|
56
|
+
...sizeMap[size],
|
|
57
|
+
...(theme.components.otpInput?.[size] ?? {})
|
|
58
|
+
};
|
|
56
59
|
const inputsRef = useRef([]);
|
|
57
60
|
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
58
61
|
const previousErrorRef = useRef(null);
|
|
59
|
-
const shake = useRef(
|
|
62
|
+
const shake = useRef(createAnimatedValue(0)).current;
|
|
60
63
|
const underlines = useRef(Array.from({
|
|
61
64
|
length
|
|
62
65
|
}, () => new Animated.Value(0))).current;
|
|
@@ -297,7 +300,7 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
297
300
|
style: [styles.input, {
|
|
298
301
|
fontSize: sizeStyles.fontSize,
|
|
299
302
|
color: theme.colors.text.primary,
|
|
300
|
-
|
|
303
|
+
...fontFor(theme, 'semibold')
|
|
301
304
|
}, textStyle]
|
|
302
305
|
}), secure && isFilled ? /*#__PURE__*/_jsx(View, {
|
|
303
306
|
pointerEvents: "none",
|
|
@@ -306,7 +309,7 @@ const OTPInput = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
306
309
|
style: [{
|
|
307
310
|
fontSize: sizeStyles.fontSize,
|
|
308
311
|
color: theme.colors.text.primary,
|
|
309
|
-
|
|
312
|
+
...fontFor(theme, 'semibold')
|
|
310
313
|
}, textStyle],
|
|
311
314
|
children: display
|
|
312
315
|
})
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { Animated, Easing, StyleSheet, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
const toneColor = (theme, tone) => {
|
|
8
8
|
switch (tone) {
|
|
@@ -40,8 +40,8 @@ const ProgressBar = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
40
40
|
} = props;
|
|
41
41
|
const isIndeterminate = indeterminateProp ?? typeof progress !== 'number';
|
|
42
42
|
const clamped = clampProgress(progress);
|
|
43
|
-
const fillAnim = useRef(
|
|
44
|
-
const loopAnim = useRef(
|
|
43
|
+
const fillAnim = useRef(createAnimatedValue(clamped)).current;
|
|
44
|
+
const loopAnim = useRef(createAnimatedValue(0)).current;
|
|
45
45
|
const widthRef = useRef(0);
|
|
46
46
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
47
47
|
const resolvedRadius = radius ?? theme.radius.full;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { createContext, forwardRef, useContext, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
6
|
import { triggerHaptic } 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);
|
|
@@ -56,11 +56,12 @@ const Radio = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
56
56
|
const selected = ctx ? ctx.selectedValue === value : !!selectedProp;
|
|
57
57
|
const disabled = ctx ? ctx.disabled || disabledProp : disabledProp;
|
|
58
58
|
const fillColor = toneColor(theme, tone);
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const
|
|
59
|
+
const sizeOverrides = theme.components.radio?.[size];
|
|
60
|
+
const outer = sizeOverrides?.outer ?? sizeMap[size].outer;
|
|
61
|
+
const inner = sizeOverrides?.inner ?? sizeMap[size].inner;
|
|
62
|
+
const radioBorderWidth = theme.components.radio?.borderWidth ?? 1.5;
|
|
63
|
+
const radioLabelGap = theme.components.radio?.labelGap ?? 10;
|
|
64
|
+
const progress = useRef(createAnimatedValue(selected ? 1 : 0)).current;
|
|
64
65
|
useEffect(() => {
|
|
65
66
|
Animated.spring(progress, {
|
|
66
67
|
toValue: selected ? 1 : 0,
|
|
@@ -108,6 +109,7 @@ const Radio = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
108
109
|
style: [styles.outer, {
|
|
109
110
|
width: outer,
|
|
110
111
|
height: outer,
|
|
112
|
+
borderWidth: radioBorderWidth,
|
|
111
113
|
borderRadius: outer / 2,
|
|
112
114
|
borderColor
|
|
113
115
|
}, circleStyle],
|
|
@@ -125,6 +127,7 @@ const Radio = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
125
127
|
})
|
|
126
128
|
}), label ? /*#__PURE__*/_jsx(Text, {
|
|
127
129
|
style: [styles.label, {
|
|
130
|
+
marginLeft: radioLabelGap,
|
|
128
131
|
color: disabled ? theme.colors.text.disabled : theme.colors.text.primary,
|
|
129
132
|
fontSize: theme.typography.fontSize.base
|
|
130
133
|
}],
|
|
@@ -140,13 +143,11 @@ const buildStyles = _theme => StyleSheet.create({
|
|
|
140
143
|
alignItems: 'center'
|
|
141
144
|
},
|
|
142
145
|
outer: {
|
|
143
|
-
borderWidth: 1.5,
|
|
144
146
|
alignItems: 'center',
|
|
145
147
|
justifyContent: 'center'
|
|
146
148
|
},
|
|
147
149
|
inner: {},
|
|
148
150
|
label: {
|
|
149
|
-
marginLeft: 10,
|
|
150
151
|
flexShrink: 1
|
|
151
152
|
}
|
|
152
153
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
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
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { fontFor, useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
6
|
import { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
7
7
|
import { useDebounce } from "../../hooks/useDebounce.js";
|
|
8
8
|
import { AppIcon } from "../AppIcon/index.js";
|
|
@@ -53,12 +53,16 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
53
53
|
...rest
|
|
54
54
|
} = props;
|
|
55
55
|
const theme = useTheme();
|
|
56
|
-
const sizeStyles =
|
|
56
|
+
const sizeStyles = {
|
|
57
|
+
...sizeMap[size],
|
|
58
|
+
...(theme.components.searchBar?.[size] ?? {})
|
|
59
|
+
};
|
|
60
|
+
const cancelWidth = theme.components.searchBar?.cancelButtonWidth ?? CANCEL_WIDTH;
|
|
57
61
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
58
62
|
const [isFocused, setIsFocused] = useState(false);
|
|
59
63
|
const [internalValue, setInternalValue] = useState(value);
|
|
60
64
|
const debouncedValue = useDebounce(internalValue, debounceMs ?? 0);
|
|
61
|
-
const cancelAnim = useRef(
|
|
65
|
+
const cancelAnim = useRef(createAnimatedValue(0)).current;
|
|
62
66
|
|
|
63
67
|
// Keep internal value in sync with controlled value when debouncing.
|
|
64
68
|
useEffect(() => {
|
|
@@ -122,7 +126,7 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
122
126
|
// Container shrinks left to make room for cancel button on right.
|
|
123
127
|
const cancelTranslateX = cancelAnim.interpolate({
|
|
124
128
|
inputRange: [0, 1],
|
|
125
|
-
outputRange: [
|
|
129
|
+
outputRange: [cancelWidth, 0]
|
|
126
130
|
});
|
|
127
131
|
const cancelOpacity = cancelAnim;
|
|
128
132
|
return /*#__PURE__*/_jsxs(View, {
|
|
@@ -139,7 +143,7 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
139
143
|
opacity: disabled ? 0.55 : 1,
|
|
140
144
|
marginRight: cancelAnim.interpolate({
|
|
141
145
|
inputRange: [0, 1],
|
|
142
|
-
outputRange: [0,
|
|
146
|
+
outputRange: [0, cancelWidth + theme.spacing.sm]
|
|
143
147
|
})
|
|
144
148
|
}],
|
|
145
149
|
accessibilityRole: "search",
|
|
@@ -194,7 +198,7 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
194
198
|
}), showCancel ? /*#__PURE__*/_jsx(Animated.View, {
|
|
195
199
|
pointerEvents: showCancelButton ? 'auto' : 'none',
|
|
196
200
|
style: [styles.cancelWrap, {
|
|
197
|
-
width:
|
|
201
|
+
width: cancelWidth,
|
|
198
202
|
transform: [{
|
|
199
203
|
translateX: cancelTranslateX
|
|
200
204
|
}],
|
|
@@ -210,7 +214,7 @@ const SearchBar = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
210
214
|
style: [styles.cancelText, {
|
|
211
215
|
color: theme.colors.primary,
|
|
212
216
|
fontSize: sizeStyles.fontSize,
|
|
213
|
-
|
|
217
|
+
...fontFor(theme, 'medium')
|
|
214
218
|
}],
|
|
215
219
|
numberOfLines: 1,
|
|
216
220
|
children: cancelLabel
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import React, { forwardRef, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
12
12
|
import { Animated, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
13
|
-
import { useTheme } from "../../theme/index.js";
|
|
13
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
14
14
|
import { triggerHaptic } from "../../utils/index.js";
|
|
15
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
16
|
const sizeMap = {
|
|
@@ -47,8 +47,8 @@ const SegmentedControl = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
47
47
|
|
|
48
48
|
// Total track width — measured from onLayout; thumb width = trackWidth / segments.length.
|
|
49
49
|
const trackWidthRef = useRef(0);
|
|
50
|
-
const thumbTranslateX = useRef(
|
|
51
|
-
const thumbWidth = useRef(
|
|
50
|
+
const thumbTranslateX = useRef(createAnimatedValue(0)).current;
|
|
51
|
+
const thumbWidth = useRef(createAnimatedValue(0)).current;
|
|
52
52
|
const activeIndex = Math.max(0, segments.findIndex(s => s.value === value));
|
|
53
53
|
const animateThumb = useCallback((index, totalWidth) => {
|
|
54
54
|
if (totalWidth <= 0 || segments.length === 0) return;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
12
12
|
import { Animated, Dimensions, Easing, FlatList, Modal, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';
|
|
13
|
-
import { useTheme } from "../../theme/index.js";
|
|
13
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
14
14
|
import { triggerHaptic } from "../../utils/index.js";
|
|
15
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
16
|
const sizeMap = {
|
|
@@ -64,8 +64,8 @@ const Select = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
64
64
|
const sheetMaxHeight = Math.round(screenHeight * 0.7);
|
|
65
65
|
|
|
66
66
|
// Animations: backdrop fade + sheet slide-up.
|
|
67
|
-
const backdropAnim = useRef(
|
|
68
|
-
const sheetAnim = useRef(
|
|
67
|
+
const backdropAnim = useRef(createAnimatedValue(0)).current;
|
|
68
|
+
const sheetAnim = useRef(createAnimatedValue(sheetMaxHeight)).current;
|
|
69
69
|
useEffect(() => {
|
|
70
70
|
if (open) {
|
|
71
71
|
Animated.parallel([Animated.timing(backdropAnim, {
|
|
@@ -390,7 +390,7 @@ const Chevron = ({
|
|
|
390
390
|
size,
|
|
391
391
|
open
|
|
392
392
|
}) => {
|
|
393
|
-
const rotate = useRef(
|
|
393
|
+
const rotate = useRef(createAnimatedValue(open ? 1 : 0)).current;
|
|
394
394
|
useEffect(() => {
|
|
395
395
|
Animated.timing(rotate, {
|
|
396
396
|
toValue: open ? 1 : 0,
|
|
@@ -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 } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } 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";
|
|
@@ -47,7 +47,7 @@ const Skeleton = ({
|
|
|
47
47
|
const borderRadius = resolveRadius(theme, resolvedRadiusToken);
|
|
48
48
|
const resolvedWidth = resolveWidth(width);
|
|
49
49
|
const resolvedHeight = Responsive.size(height);
|
|
50
|
-
const progress = useRef(
|
|
50
|
+
const progress = useRef(createAnimatedValue(0)).current;
|
|
51
51
|
const [containerWidth, setContainerWidth] = useState(0);
|
|
52
52
|
useEffect(() => {
|
|
53
53
|
progress.setValue(0);
|
|
@@ -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 } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } 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 = {
|
|
@@ -65,16 +65,16 @@ const Slider = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
65
65
|
const lastReportedHigh = useRef(highRef.current);
|
|
66
66
|
|
|
67
67
|
// Animated x positions (px) for thumbs.
|
|
68
|
-
const lowX = useRef(
|
|
69
|
-
const highX = useRef(
|
|
68
|
+
const lowX = useRef(createAnimatedValue(0)).current;
|
|
69
|
+
const highX = useRef(createAnimatedValue(0)).current;
|
|
70
70
|
|
|
71
71
|
// Press / drag scale animations.
|
|
72
|
-
const lowScale = useRef(
|
|
73
|
-
const highScale = useRef(
|
|
72
|
+
const lowScale = useRef(createAnimatedValue(1)).current;
|
|
73
|
+
const highScale = useRef(createAnimatedValue(1)).current;
|
|
74
74
|
|
|
75
75
|
// Label opacity per thumb.
|
|
76
|
-
const lowLabelOpacity = useRef(
|
|
77
|
-
const highLabelOpacity = useRef(
|
|
76
|
+
const lowLabelOpacity = useRef(createAnimatedValue(0)).current;
|
|
77
|
+
const highLabelOpacity = useRef(createAnimatedValue(0)).current;
|
|
78
78
|
|
|
79
79
|
// Track which thumb is actively dragging (to anchor gesture math).
|
|
80
80
|
const dragOffsetRef = useRef(0);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { ActivityIndicator, Animated, Easing, StyleSheet, Text, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
6
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
7
|
const sizeMap = {
|
|
8
8
|
small: 20,
|
|
@@ -18,7 +18,7 @@ const Dot = ({
|
|
|
18
18
|
delay,
|
|
19
19
|
duration
|
|
20
20
|
}) => {
|
|
21
|
-
const scale = useRef(
|
|
21
|
+
const scale = useRef(createAnimatedValue(1)).current;
|
|
22
22
|
useEffect(() => {
|
|
23
23
|
const animation = Animated.loop(Animated.sequence([Animated.delay(delay), Animated.timing(scale, {
|
|
24
24
|
toValue: 1.4,
|
|
@@ -61,7 +61,7 @@ const Spinner = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
61
61
|
testID
|
|
62
62
|
} = props;
|
|
63
63
|
const theme = useTheme();
|
|
64
|
-
const fade = useRef(
|
|
64
|
+
const fade = useRef(createAnimatedValue(0)).current;
|
|
65
65
|
useEffect(() => {
|
|
66
66
|
Animated.timing(fade, {
|
|
67
67
|
toValue: 1,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { Animated, Easing, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
6
|
import { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
7
7
|
import { SkeletonContent } from "../Skeleton/index.js";
|
|
8
8
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -30,8 +30,8 @@ const StepCircle = ({
|
|
|
30
30
|
onPress
|
|
31
31
|
}) => {
|
|
32
32
|
const isActive = status === 'active';
|
|
33
|
-
const pulseScale = useRef(
|
|
34
|
-
const pulseOpacity = useRef(
|
|
33
|
+
const pulseScale = useRef(createAnimatedValue(1)).current;
|
|
34
|
+
const pulseOpacity = useRef(createAnimatedValue(0.5)).current;
|
|
35
35
|
useEffect(() => {
|
|
36
36
|
if (!isActive) {
|
|
37
37
|
pulseScale.setValue(1);
|
|
@@ -176,7 +176,7 @@ const Stepper = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
176
176
|
|
|
177
177
|
// Connector progress: animates as activeStep changes.
|
|
178
178
|
const initialProgress = total <= 1 ? 0 : activeStep / (total - 1);
|
|
179
|
-
const progress = useRef(
|
|
179
|
+
const progress = useRef(createAnimatedValue(initialProgress)).current;
|
|
180
180
|
const lastTargetRef = useRef(initialProgress);
|
|
181
181
|
useEffect(() => {
|
|
182
182
|
const target = total <= 1 ? 0 : activeStep / (total - 1);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { forwardRef, useEffect, useMemo, useRef } from 'react';
|
|
4
4
|
import { Animated, Easing, Pressable, StyleSheet, Text, View } from 'react-native';
|
|
5
|
-
import { useTheme } from "../../theme/index.js";
|
|
5
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
6
6
|
import { triggerHaptic } from "../../utils/hapticUtils.js";
|
|
7
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
8
|
const sizeMap = {
|
|
@@ -48,6 +48,7 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
48
48
|
label,
|
|
49
49
|
accessibilityLabel,
|
|
50
50
|
haptic = 'selection',
|
|
51
|
+
bounce = false,
|
|
51
52
|
style,
|
|
52
53
|
trackStyle,
|
|
53
54
|
thumbStyle,
|
|
@@ -55,11 +56,15 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
55
56
|
...rest
|
|
56
57
|
} = props;
|
|
57
58
|
const theme = useTheme();
|
|
58
|
-
const sizeStyles =
|
|
59
|
+
const sizeStyles = {
|
|
60
|
+
...sizeMap[size],
|
|
61
|
+
...(theme.components.switch?.[size] ?? {})
|
|
62
|
+
};
|
|
63
|
+
const switchThumbColor = theme.components.switch?.thumbColor ?? '#FFFFFF';
|
|
59
64
|
const styles = useMemo(() => buildStyles(theme), [theme]);
|
|
60
65
|
const offTrackColor = theme.mode === 'dark' ? theme.colors.secondary : theme.colors.surface.disabled;
|
|
61
66
|
const onTrackColor = toneColor(theme, tone);
|
|
62
|
-
const progress = useRef(
|
|
67
|
+
const progress = useRef(createAnimatedValue(value ? 1 : 0)).current;
|
|
63
68
|
useEffect(() => {
|
|
64
69
|
Animated.spring(progress, {
|
|
65
70
|
toValue: value ? 1 : 0,
|
|
@@ -69,7 +74,7 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
69
74
|
useNativeDriver: true
|
|
70
75
|
}).start();
|
|
71
76
|
}, [value, progress, theme.motion.spring.snappy]);
|
|
72
|
-
const trackBgAnim = useRef(
|
|
77
|
+
const trackBgAnim = useRef(createAnimatedValue(value ? 1 : 0)).current;
|
|
73
78
|
useEffect(() => {
|
|
74
79
|
Animated.timing(trackBgAnim, {
|
|
75
80
|
toValue: value ? 1 : 0,
|
|
@@ -88,6 +93,28 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
88
93
|
inputRange: [0, 1],
|
|
89
94
|
outputRange: [offTrackColor, onTrackColor]
|
|
90
95
|
});
|
|
96
|
+
const bounceScale = useRef(createAnimatedValue(1)).current;
|
|
97
|
+
const isFirstRender = useRef(true);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (!bounce) return;
|
|
100
|
+
if (isFirstRender.current) {
|
|
101
|
+
isFirstRender.current = false;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
Animated.sequence([Animated.spring(bounceScale, {
|
|
105
|
+
toValue: 1.15,
|
|
106
|
+
damping: 10,
|
|
107
|
+
stiffness: 220,
|
|
108
|
+
mass: 1,
|
|
109
|
+
useNativeDriver: true
|
|
110
|
+
}), Animated.spring(bounceScale, {
|
|
111
|
+
toValue: 1,
|
|
112
|
+
damping: 14,
|
|
113
|
+
stiffness: 240,
|
|
114
|
+
mass: 1,
|
|
115
|
+
useNativeDriver: true
|
|
116
|
+
})]).start();
|
|
117
|
+
}, [value, bounce, bounceScale]);
|
|
91
118
|
const handlePress = event => {
|
|
92
119
|
if (disabled) return;
|
|
93
120
|
if (haptic !== false) triggerHaptic(haptic);
|
|
@@ -122,11 +149,14 @@ const Switch = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
122
149
|
}, trackStyle],
|
|
123
150
|
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
124
151
|
style: [styles.thumb, theme.shadows.sm, {
|
|
152
|
+
backgroundColor: switchThumbColor,
|
|
125
153
|
width: sizeStyles.thumbSize,
|
|
126
154
|
height: sizeStyles.thumbSize,
|
|
127
155
|
borderRadius: sizeStyles.thumbSize / 2,
|
|
128
156
|
transform: [{
|
|
129
157
|
translateX
|
|
158
|
+
}, {
|
|
159
|
+
scale: bounceScale
|
|
130
160
|
}]
|
|
131
161
|
}, thumbStyle]
|
|
132
162
|
})
|
|
@@ -155,7 +185,6 @@ const buildStyles = _theme => StyleSheet.create({
|
|
|
155
185
|
justifyContent: 'center'
|
|
156
186
|
},
|
|
157
187
|
thumb: {
|
|
158
|
-
backgroundColor: '#FFFFFF',
|
|
159
188
|
position: 'absolute',
|
|
160
189
|
top: 2
|
|
161
190
|
},
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import React, { forwardRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
15
15
|
import { Animated, Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
|
|
16
|
-
import { useTheme } from "../../theme/index.js";
|
|
16
|
+
import { useTheme, createAnimatedValue } from "../../theme/index.js";
|
|
17
17
|
import { triggerHaptic } from "../../utils/index.js";
|
|
18
18
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
19
|
const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
@@ -34,8 +34,8 @@ const Tabs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
34
34
|
|
|
35
35
|
// Per-tab measured layouts (key → {x, width}).
|
|
36
36
|
const [layouts, setLayouts] = useState({});
|
|
37
|
-
const indicatorTranslateX = useRef(
|
|
38
|
-
const indicatorWidth = useRef(
|
|
37
|
+
const indicatorTranslateX = useRef(createAnimatedValue(0)).current;
|
|
38
|
+
const indicatorWidth = useRef(createAnimatedValue(0)).current;
|
|
39
39
|
const activeLayout = layouts[activeKey];
|
|
40
40
|
|
|
41
41
|
// Animate indicator whenever activeKey or its layout changes.
|