@utilitywarehouse/hearth-react-native 0.23.0 → 0.25.0

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 (107) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-lint.log +13 -13
  3. package/CHANGELOG.md +77 -0
  4. package/build/components/DatePicker/DatePickerCalendar.js +4 -9
  5. package/build/components/Modal/Modal.js +5 -4
  6. package/build/components/Modal/Modal.props.d.ts +10 -4
  7. package/build/components/ProgressBar/ProgressBar.d.ts +6 -0
  8. package/build/components/ProgressBar/ProgressBar.js +35 -0
  9. package/build/components/ProgressBar/ProgressBar.props.d.ts +60 -0
  10. package/build/components/ProgressBar/ProgressBar.props.js +1 -0
  11. package/build/components/ProgressBar/ProgressBarCircular.d.ts +6 -0
  12. package/build/components/ProgressBar/ProgressBarCircular.js +115 -0
  13. package/build/components/ProgressBar/ProgressBarLinear.d.ts +6 -0
  14. package/build/components/ProgressBar/ProgressBarLinear.js +79 -0
  15. package/build/components/ProgressBar/index.d.ts +2 -0
  16. package/build/components/ProgressBar/index.js +1 -0
  17. package/build/components/TimePicker/TimePicker.d.ts +6 -0
  18. package/build/components/TimePicker/TimePicker.js +78 -0
  19. package/build/components/TimePicker/TimePicker.props.d.ts +45 -0
  20. package/build/components/TimePicker/TimePicker.props.js +1 -0
  21. package/build/components/TimePicker/TimePickerView.d.ts +12 -0
  22. package/build/components/TimePicker/TimePickerView.js +130 -0
  23. package/build/components/TimePicker/TimePickerWheel.d.ts +8 -0
  24. package/build/components/TimePicker/TimePickerWheel.js +78 -0
  25. package/build/components/{DatePicker/time-picker/wheel-web.d.ts → TimePicker/TimePickerWheel.web.d.ts} +4 -4
  26. package/build/components/TimePicker/TimePickerWheel.web.js +122 -0
  27. package/build/components/TimePicker/index.d.ts +6 -0
  28. package/build/components/TimePicker/index.js +3 -0
  29. package/build/components/TimePickerInput/TimePickerInput.d.ts +6 -0
  30. package/build/components/TimePickerInput/TimePickerInput.js +127 -0
  31. package/build/components/TimePickerInput/TimePickerInput.props.d.ts +52 -0
  32. package/build/components/TimePickerInput/TimePickerInput.props.js +1 -0
  33. package/build/components/TimePickerInput/TimePickerInputDoneButton.d.ts +8 -0
  34. package/build/components/TimePickerInput/TimePickerInputDoneButton.js +19 -0
  35. package/build/components/TimePickerInput/TimePickerInputDoneButton.web.d.ts +5 -0
  36. package/build/components/TimePickerInput/TimePickerInputDoneButton.web.js +5 -0
  37. package/build/components/TimePickerInput/index.d.ts +2 -0
  38. package/build/components/TimePickerInput/index.js +1 -0
  39. package/build/components/index.d.ts +3 -0
  40. package/build/components/index.js +3 -0
  41. package/docs/components/AllComponents.web.tsx +36 -0
  42. package/package.json +2 -1
  43. package/src/components/DatePicker/DatePickerCalendar.tsx +30 -13
  44. package/src/components/Modal/Modal.props.ts +13 -4
  45. package/src/components/Modal/Modal.stories.tsx +1 -1
  46. package/src/components/Modal/Modal.tsx +28 -11
  47. package/src/components/ProgressBar/ProgressBar.docs.mdx +90 -0
  48. package/src/components/ProgressBar/ProgressBar.figma.tsx +79 -0
  49. package/src/components/ProgressBar/ProgressBar.props.ts +60 -0
  50. package/src/components/ProgressBar/ProgressBar.stories.tsx +117 -0
  51. package/src/components/ProgressBar/ProgressBar.tsx +74 -0
  52. package/src/components/ProgressBar/ProgressBarCircular.tsx +181 -0
  53. package/src/components/ProgressBar/ProgressBarLinear.tsx +127 -0
  54. package/src/components/ProgressBar/index.ts +7 -0
  55. package/src/components/TimePicker/TimePicker.docs.mdx +84 -0
  56. package/src/components/TimePicker/TimePicker.figma.tsx +29 -0
  57. package/src/components/TimePicker/TimePicker.props.ts +45 -0
  58. package/src/components/TimePicker/TimePicker.stories.tsx +85 -0
  59. package/src/components/TimePicker/TimePicker.tsx +150 -0
  60. package/src/components/TimePicker/TimePickerView.tsx +216 -0
  61. package/src/components/TimePicker/TimePickerWheel.tsx +154 -0
  62. package/src/components/TimePicker/TimePickerWheel.web.tsx +217 -0
  63. package/src/components/TimePicker/index.ts +8 -0
  64. package/src/components/TimePickerInput/TimePickerInput.docs.mdx +135 -0
  65. package/src/components/TimePickerInput/TimePickerInput.figma.tsx +34 -0
  66. package/src/components/TimePickerInput/TimePickerInput.props.ts +55 -0
  67. package/src/components/TimePickerInput/TimePickerInput.stories.tsx +175 -0
  68. package/src/components/TimePickerInput/TimePickerInput.tsx +283 -0
  69. package/src/components/TimePickerInput/TimePickerInputDoneButton.tsx +42 -0
  70. package/src/components/TimePickerInput/TimePickerInputDoneButton.web.tsx +7 -0
  71. package/src/components/TimePickerInput/index.ts +2 -0
  72. package/src/components/index.ts +3 -0
  73. package/build/components/DatePicker/TimePicker.d.ts +0 -3
  74. package/build/components/DatePicker/TimePicker.js +0 -84
  75. package/build/components/DatePicker/time-picker/animated-math.d.ts +0 -4
  76. package/build/components/DatePicker/time-picker/animated-math.js +0 -19
  77. package/build/components/DatePicker/time-picker/period-native.d.ts +0 -6
  78. package/build/components/DatePicker/time-picker/period-native.js +0 -17
  79. package/build/components/DatePicker/time-picker/period-picker.d.ts +0 -6
  80. package/build/components/DatePicker/time-picker/period-picker.js +0 -10
  81. package/build/components/DatePicker/time-picker/period-web.d.ts +0 -6
  82. package/build/components/DatePicker/time-picker/period-web.js +0 -21
  83. package/build/components/DatePicker/time-picker/wheel-native.d.ts +0 -8
  84. package/build/components/DatePicker/time-picker/wheel-native.js +0 -19
  85. package/build/components/DatePicker/time-picker/wheel-picker/index.d.ts +0 -2
  86. package/build/components/DatePicker/time-picker/wheel-picker/index.js +0 -2
  87. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.d.ts +0 -16
  88. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.js +0 -97
  89. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.d.ts +0 -21
  90. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.js +0 -88
  91. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.d.ts +0 -23
  92. package/build/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.js +0 -21
  93. package/build/components/DatePicker/time-picker/wheel-web.js +0 -146
  94. package/build/components/DatePicker/time-picker/wheel.d.ts +0 -8
  95. package/build/components/DatePicker/time-picker/wheel.js +0 -10
  96. package/src/components/DatePicker/TimePicker.tsx +0 -141
  97. package/src/components/DatePicker/time-picker/animated-math.ts +0 -33
  98. package/src/components/DatePicker/time-picker/period-native.tsx +0 -34
  99. package/src/components/DatePicker/time-picker/period-picker.tsx +0 -16
  100. package/src/components/DatePicker/time-picker/period-web.tsx +0 -36
  101. package/src/components/DatePicker/time-picker/wheel-native.tsx +0 -37
  102. package/src/components/DatePicker/time-picker/wheel-picker/index.ts +0 -3
  103. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker-item.tsx +0 -132
  104. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.style.ts +0 -22
  105. package/src/components/DatePicker/time-picker/wheel-picker/wheel-picker.tsx +0 -200
  106. package/src/components/DatePicker/time-picker/wheel-web.tsx +0 -180
  107. package/src/components/DatePicker/time-picker/wheel.tsx +0 -18
@@ -1,37 +0,0 @@
1
- import { memo } from 'react';
2
- import { Platform } from 'react-native';
3
- import { StyleSheet } from 'react-native-unistyles';
4
- import { PickerOption } from '../DatePicker.props';
5
- import WheelPicker from './wheel-picker';
6
-
7
- interface WheelProps {
8
- value: number | string;
9
- setValue?: (value: any) => void;
10
- items: PickerOption[];
11
- }
12
-
13
- const WheelNative = ({ value, setValue = () => {}, items }: WheelProps) => {
14
- return (
15
- <WheelPicker
16
- value={value}
17
- options={items}
18
- onChange={setValue}
19
- containerStyle={styles.container}
20
- itemHeight={44}
21
- decelerationRate="fast"
22
- />
23
- );
24
- };
25
-
26
- const styles = StyleSheet.create({
27
- container: {
28
- display: 'flex',
29
- ...Platform.select({
30
- web: {
31
- userSelect: 'none',
32
- },
33
- }),
34
- },
35
- });
36
-
37
- export default memo(WheelNative);
@@ -1,3 +0,0 @@
1
- import WheelPicker from './wheel-picker';
2
-
3
- export default WheelPicker;
@@ -1,132 +0,0 @@
1
- import React from 'react';
2
- import { Animated, StyleProp, ViewStyle } from 'react-native';
3
- import { BodyText } from '../../../BodyText';
4
- import { PickerOption } from '../../DatePicker.props';
5
- import styles from './wheel-picker.style';
6
-
7
- interface ItemProps {
8
- style: StyleProp<ViewStyle>;
9
- option: PickerOption | null;
10
- height: number;
11
- index: number;
12
- currentScrollIndex: Animated.AnimatedAddition<number>;
13
- visibleRest: number;
14
- rotationFunction: (x: number) => number;
15
- opacityFunction: (x: number) => number;
16
- scaleFunction: (x: number) => number;
17
- }
18
-
19
- const WheelPickerItem: React.FC<ItemProps> = ({
20
- style,
21
- height,
22
- option,
23
- index,
24
- visibleRest,
25
- currentScrollIndex,
26
- opacityFunction,
27
- rotationFunction,
28
- scaleFunction,
29
- }) => {
30
- const relativeScrollIndex = Animated.subtract(index, currentScrollIndex);
31
-
32
- const translateY = relativeScrollIndex.interpolate({
33
- inputRange: (() => {
34
- const range = [0];
35
- for (let i = 1; i <= visibleRest + 1; i++) {
36
- range.unshift(-i);
37
- range.push(i);
38
- }
39
- return range;
40
- })(),
41
- outputRange: (() => {
42
- const range = [0];
43
- for (let i = 1; i <= visibleRest + 1; i++) {
44
- let y = (height / 2) * (1 - Math.sin(Math.PI / 2 - rotationFunction(i)));
45
- for (let j = 1; j < i; j++) {
46
- y += height * (1 - Math.sin(Math.PI / 2 - rotationFunction(j)));
47
- }
48
- range.unshift(y);
49
- range.push(-y);
50
- }
51
- return range;
52
- })(),
53
- });
54
-
55
- const opacity = relativeScrollIndex.interpolate({
56
- inputRange: (() => {
57
- const range = [0];
58
- for (let i = 1; i <= visibleRest + 1; i++) {
59
- range.unshift(-i);
60
- range.push(i);
61
- }
62
- return range;
63
- })(),
64
- outputRange: (() => {
65
- const range = [1];
66
- for (let x = 1; x <= visibleRest + 1; x++) {
67
- const y = opacityFunction(x);
68
- range.unshift(y);
69
- range.push(y);
70
- }
71
- return range;
72
- })(),
73
- });
74
-
75
- const scale = relativeScrollIndex.interpolate({
76
- inputRange: (() => {
77
- const range = [0];
78
- for (let i = 1; i <= visibleRest + 1; i++) {
79
- range.unshift(-i);
80
- range.push(i);
81
- }
82
- return range;
83
- })(),
84
- outputRange: (() => {
85
- const range = [1.0];
86
- for (let x = 1; x <= visibleRest + 1; x++) {
87
- const y = scaleFunction(x);
88
- range.unshift(y);
89
- range.push(y);
90
- }
91
- return range;
92
- })(),
93
- });
94
-
95
- const rotateX = relativeScrollIndex.interpolate({
96
- inputRange: (() => {
97
- const range = [0];
98
- for (let i = 1; i <= visibleRest + 1; i++) {
99
- range.unshift(-i);
100
- range.push(i);
101
- }
102
- return range;
103
- })(),
104
- outputRange: (() => {
105
- const range = ['0deg'];
106
- for (let x = 1; x <= visibleRest + 1; x++) {
107
- const y = rotationFunction(x);
108
- range.unshift(`${y}deg`);
109
- range.push(`${y}deg`);
110
- }
111
- return range;
112
- })(),
113
- });
114
-
115
- return (
116
- <Animated.View
117
- style={[
118
- styles.option,
119
- style,
120
- {
121
- height,
122
- opacity,
123
- transform: [{ translateY }, { rotateX }, { scale }],
124
- },
125
- ]}
126
- >
127
- <BodyText>{option?.text}</BodyText>
128
- </Animated.View>
129
- );
130
- };
131
-
132
- export default React.memo(WheelPickerItem);
@@ -1,22 +0,0 @@
1
- import { StyleSheet } from 'react-native-unistyles';
2
-
3
- export default StyleSheet.create({
4
- container: {
5
- position: 'relative',
6
- },
7
- selectedIndicator: {
8
- position: 'absolute',
9
- width: '100%',
10
- top: '50%',
11
- },
12
- scrollView: {
13
- overflow: 'hidden',
14
- flex: 1,
15
- },
16
- option: {
17
- alignItems: 'center',
18
- justifyContent: 'center',
19
- paddingHorizontal: 16,
20
- zIndex: 100,
21
- },
22
- });
@@ -1,200 +0,0 @@
1
- import React, { memo, useEffect, useMemo, useRef, useState } from 'react';
2
- import {
3
- Animated,
4
- FlatList,
5
- FlatListProps,
6
- NativeScrollEvent,
7
- NativeSyntheticEvent,
8
- Platform,
9
- StyleProp,
10
- View,
11
- ViewProps,
12
- ViewStyle,
13
- } from 'react-native';
14
- import { PickerOption } from '../../DatePicker.props';
15
- import WheelPickerItem from './wheel-picker-item';
16
- import styles from './wheel-picker.style';
17
-
18
- interface Props {
19
- value: number | string;
20
- options: PickerOption[];
21
- onChange: (index: number | string) => void;
22
- selectedIndicatorStyle?: StyleProp<ViewStyle>;
23
- itemStyle?: ViewStyle;
24
- itemHeight?: number;
25
- containerStyle?: ViewStyle;
26
- containerProps?: Omit<ViewProps, 'style'>;
27
- scaleFunction?: (x: number) => number;
28
- rotationFunction?: (x: number) => number;
29
- opacityFunction?: (x: number) => number;
30
- visibleRest?: number;
31
- decelerationRate?: 'normal' | 'fast' | number;
32
- flatListProps?: Omit<FlatListProps<PickerOption | null>, 'data' | 'renderItem'>;
33
- }
34
-
35
- const WheelPicker: React.FC<Props> = ({
36
- value,
37
- options,
38
- onChange,
39
- selectedIndicatorStyle = {},
40
- containerStyle = {},
41
- itemStyle = {},
42
- itemHeight = 40,
43
- scaleFunction = (x: number) => 1.0 ** x,
44
- rotationFunction = (x: number) => 1 - Math.pow(1 / 2, x),
45
- opacityFunction = (x: number) => Math.pow(1 / 3, x),
46
- visibleRest = 2,
47
- decelerationRate = 'normal',
48
- containerProps = {},
49
- flatListProps = {},
50
- }) => {
51
- const momentumStarted = useRef(false);
52
- const selectedIndex = options.findIndex(item => item.value === value);
53
-
54
- const flatListRef = useRef<FlatList<PickerOption | null>>(null);
55
- const [scrollY] = useState(new Animated.Value(selectedIndex * itemHeight));
56
-
57
- const containerHeight = (1 + visibleRest * 2) * itemHeight;
58
- const paddedOptions = useMemo(() => {
59
- const array: (PickerOption | null)[] = [...options];
60
- for (let i = 0; i < visibleRest; i++) {
61
- array.unshift(null);
62
- array.push(null);
63
- }
64
- return array;
65
- }, [options, visibleRest]);
66
-
67
- const offsets = useMemo(
68
- () => [...Array(paddedOptions.length)].map((_, i) => i * itemHeight),
69
- [paddedOptions, itemHeight]
70
- );
71
-
72
- const currentScrollIndex = useMemo(
73
- () => Animated.add(Animated.divide(scrollY, itemHeight), visibleRest),
74
- [visibleRest, scrollY, itemHeight]
75
- );
76
-
77
- const handleScrollEnd = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
78
- const offsetY = Math.min(
79
- itemHeight * (options.length - 1),
80
- Math.max(event.nativeEvent.contentOffset.y, 0)
81
- );
82
-
83
- let index = Math.floor(offsetY / itemHeight);
84
- const remainder = offsetY % itemHeight;
85
- if (remainder > itemHeight / 2) {
86
- index++;
87
- }
88
-
89
- if (index !== selectedIndex) {
90
- onChange(options[index]?.value || 0);
91
- }
92
- };
93
-
94
- const handleMomentumScrollBegin = () => {
95
- momentumStarted.current = true;
96
- };
97
-
98
- const handleMomentumScrollEnd = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
99
- momentumStarted.current = false;
100
- handleScrollEnd(event);
101
- };
102
-
103
- const handleScrollEndDrag = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
104
- // Capture the offset value immediately
105
- const offsetY = event.nativeEvent.contentOffset?.y;
106
-
107
- // We'll start a short timer to see if momentum scroll begins
108
- setTimeout(() => {
109
- // If momentum scroll hasn't started within the timeout,
110
- // then it was a slow scroll that won't trigger momentum
111
- if (!momentumStarted.current && offsetY !== undefined) {
112
- // Create a synthetic event with just the data we need
113
- const syntheticEvent = {
114
- nativeEvent: {
115
- contentOffset: { y: offsetY },
116
- },
117
- };
118
- handleScrollEnd(syntheticEvent as any);
119
- }
120
- }, 50);
121
- };
122
-
123
- useEffect(() => {
124
- if (selectedIndex < 0 || selectedIndex >= options.length) {
125
- throw new Error(
126
- `Selected index ${selectedIndex} is out of bounds [0, ${options.length - 1}]`
127
- );
128
- }
129
- }, [selectedIndex, options]);
130
-
131
- /**
132
- * If selectedIndex is changed from outside (not via onChange) we need to scroll to the specified index.
133
- * This ensures that what the user sees as selected in the picker always corresponds to the value state.
134
- */
135
- useEffect(() => {
136
- flatListRef.current?.scrollToIndex({
137
- index: selectedIndex,
138
- animated: Platform.OS === 'ios',
139
- });
140
- }, [selectedIndex, itemHeight]);
141
-
142
- return (
143
- <View
144
- style={[styles.container, { height: containerHeight }, containerStyle]}
145
- {...containerProps}
146
- >
147
- <View
148
- style={[
149
- styles.selectedIndicator,
150
- selectedIndicatorStyle,
151
- {
152
- transform: [{ translateY: -itemHeight / 2 }],
153
- height: itemHeight,
154
- },
155
- ]}
156
- />
157
- <Animated.FlatList<PickerOption | null>
158
- {...flatListProps}
159
- ref={flatListRef}
160
- nestedScrollEnabled
161
- style={styles.scrollView}
162
- showsVerticalScrollIndicator={false}
163
- onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: scrollY } } }], {
164
- useNativeDriver: true,
165
- })}
166
- onScrollEndDrag={handleScrollEndDrag}
167
- onMomentumScrollBegin={handleMomentumScrollBegin}
168
- onMomentumScrollEnd={handleMomentumScrollEnd}
169
- snapToOffsets={offsets}
170
- decelerationRate={decelerationRate}
171
- initialScrollIndex={selectedIndex}
172
- getItemLayout={(_, index) => ({
173
- length: itemHeight,
174
- offset: itemHeight * index,
175
- index,
176
- })}
177
- data={paddedOptions}
178
- keyExtractor={(item, index) =>
179
- item ? `${item.value}-${item.text}-${index}` : `null-${index}`
180
- }
181
- renderItem={({ item: option, index }) => (
182
- <WheelPickerItem
183
- key={`option-${index}`}
184
- index={index}
185
- option={option}
186
- style={itemStyle}
187
- height={itemHeight}
188
- currentScrollIndex={currentScrollIndex}
189
- scaleFunction={scaleFunction}
190
- rotationFunction={rotationFunction}
191
- opacityFunction={opacityFunction}
192
- visibleRest={visibleRest}
193
- />
194
- )}
195
- />
196
- </View>
197
- );
198
- };
199
-
200
- export default memo(WheelPicker);
@@ -1,180 +0,0 @@
1
- import { memo, useMemo, useRef } from 'react';
2
- import { Animated, PanResponder, Platform, View } from 'react-native';
3
- import { StyleSheet } from 'react-native-unistyles';
4
- import { isEqual } from '../../../utils';
5
- import { BodyText } from '../../BodyText';
6
- import { PickerOption } from '../DatePicker.props';
7
- import { CONTAINER_HEIGHT } from '../enums';
8
- import { sin } from './animated-math';
9
-
10
- interface WheelProps {
11
- value: number | string;
12
- setValue?: (value: any) => void;
13
- items: PickerOption[];
14
- }
15
-
16
- const ITEM_HEIGHT = 44;
17
-
18
- const WheelWeb = ({ value, setValue = () => {}, items }: WheelProps) => {
19
- const displayCount = 5;
20
- const translateY = useRef(new Animated.Value(0)).current;
21
- const renderCount = displayCount * 2 < items.length ? displayCount * 8 : displayCount * 2 - 1;
22
- const circular = items.length >= displayCount;
23
- const height = 140;
24
- const radius = height / 2;
25
-
26
- const valueIndex = useMemo(() => {
27
- return Math.max(
28
- 0,
29
- items.findIndex(item => item.value === value)
30
- );
31
- }, [items, value]);
32
-
33
- const panResponder = useMemo(() => {
34
- return PanResponder.create({
35
- onMoveShouldSetPanResponder: () => true,
36
- onStartShouldSetPanResponderCapture: () => true,
37
- onPanResponderGrant: () => {
38
- translateY.setValue(0);
39
- },
40
- onPanResponderMove: (evt, gestureState) => {
41
- translateY.setValue(gestureState.dy);
42
- evt.stopPropagation();
43
- },
44
- onPanResponderRelease: (_, gestureState) => {
45
- translateY.extractOffset();
46
- let newValueIndex =
47
- valueIndex - Math.round(gestureState.dy / ((radius * 2) / displayCount));
48
- if (circular) {
49
- newValueIndex = (newValueIndex + items.length) % items.length;
50
- } else {
51
- if (newValueIndex < 0) {
52
- newValueIndex = 0;
53
- } else if (newValueIndex >= items.length) {
54
- newValueIndex = items.length - 1;
55
- }
56
- }
57
- const newValue = items[newValueIndex];
58
- if (newValue?.value === value) {
59
- translateY.setOffset(0);
60
- translateY.setValue(0);
61
- } else if (newValue?.value) {
62
- setValue(newValue.value);
63
- } else if (items[0]?.value) {
64
- setValue(items[0].value);
65
- }
66
- },
67
- });
68
- }, [circular, displayCount, radius, setValue, value, valueIndex, items, translateY]);
69
-
70
- const displayValues = useMemo(() => {
71
- const centerIndex = Math.floor(renderCount / 2);
72
-
73
- return Array.from({ length: renderCount }, (_, index) => {
74
- let targetIndex = valueIndex + index - centerIndex;
75
- if (circular) {
76
- targetIndex = ((targetIndex % items.length) + items.length) % items.length;
77
- } else {
78
- targetIndex = Math.max(0, Math.min(targetIndex, items.length - 1));
79
- }
80
- return items[targetIndex] || items[0];
81
- });
82
- }, [renderCount, valueIndex, items, circular]);
83
-
84
- const animatedAngles = useMemo(() => {
85
- //translateY.setValue(0);
86
- translateY.setOffset(0);
87
- const currentIndex = displayValues.findIndex(item => item?.value === value);
88
- return displayValues && displayValues.length > 0
89
- ? displayValues.map((_, index) =>
90
- translateY
91
- .interpolate({
92
- inputRange: [-radius, radius],
93
- outputRange: [
94
- -radius + ((radius * 2) / displayCount) * (index - currentIndex),
95
- radius + ((radius * 2) / displayCount) * (index - currentIndex),
96
- ],
97
- extrapolate: 'extend',
98
- })
99
- .interpolate({
100
- inputRange: [-radius, radius],
101
- outputRange: [-Math.PI / 2, Math.PI / 2],
102
- extrapolate: 'clamp',
103
- })
104
- )
105
- : [];
106
- }, [displayValues, radius, value, displayCount, translateY]);
107
-
108
- return (
109
- <View style={[styles.container]} {...panResponder.panHandlers}>
110
- <View
111
- style={[
112
- styles.selectedIndicator,
113
- {
114
- transform: [{ translateY: -ITEM_HEIGHT / 2 }],
115
- height: ITEM_HEIGHT,
116
- },
117
- ]}
118
- />
119
- {displayValues?.map((displayValue, index) => {
120
- const animatedAngle = animatedAngles[index];
121
- return (
122
- <Animated.View
123
- key={`${displayValue?.text}-${index}`}
124
- style={{
125
- position: 'absolute',
126
- height: ITEM_HEIGHT - 10,
127
- transform: animatedAngle
128
- ? [
129
- {
130
- translateY: Animated.multiply(radius, sin(animatedAngle)),
131
- },
132
- {
133
- rotateX: animatedAngle.interpolate({
134
- inputRange: [-Math.PI / 2, Math.PI / 2],
135
- outputRange: ['-89deg', '89deg'],
136
- extrapolate: 'clamp',
137
- }),
138
- },
139
- ]
140
- : [],
141
- opacity: displayValue?.value !== value ? 0.3 : 1,
142
- }}
143
- >
144
- <BodyText>{displayValue?.text}</BodyText>
145
- </Animated.View>
146
- );
147
- })}
148
- </View>
149
- );
150
- };
151
-
152
- const styles = StyleSheet.create({
153
- container: {
154
- minWidth: 30,
155
- overflow: 'hidden',
156
- alignItems: 'center',
157
- justifyContent: 'center',
158
- height: CONTAINER_HEIGHT / 2,
159
- ...Platform.select({
160
- web: {
161
- cursor: 'pointer',
162
- userSelect: 'none',
163
- },
164
- }),
165
- },
166
- selectedIndicator: {
167
- position: 'absolute',
168
- width: '100%',
169
- top: '50%',
170
- },
171
- });
172
-
173
- const customComparator = (prev: Readonly<WheelProps>, next: Readonly<WheelProps>) => {
174
- const areEqual =
175
- prev.value === next.value && prev.setValue === next.setValue && isEqual(prev.items, next.items);
176
-
177
- return areEqual;
178
- };
179
-
180
- export default memo(WheelWeb, customComparator);
@@ -1,18 +0,0 @@
1
- import { memo } from 'react';
2
- import { Platform } from 'react-native';
3
- import { PickerOption } from '../DatePicker.props';
4
- import WheelNative from './wheel-native';
5
- import WheelWeb from './wheel-web';
6
-
7
- type WheelProps = {
8
- value: number | string;
9
- setValue?: (value: any) => void;
10
- items: PickerOption[];
11
- };
12
-
13
- const Wheel = (props: WheelProps) => {
14
- const Component = Platform.OS === 'web' ? WheelWeb : WheelNative;
15
- return <Component {...props} />;
16
- };
17
-
18
- export default memo(Wheel);