@herca/rn-kit 0.1.68 → 0.1.70
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/module/DatePicker/TimePicker.js +26 -46
- package/lib/module/DatePicker/TimePicker.js.map +1 -1
- package/lib/module/DatePicker/partials/AnimatedItem.js +52 -0
- package/lib/module/DatePicker/partials/AnimatedItem.js.map +1 -0
- package/lib/module/Input/InputFile.js +76 -275
- package/lib/module/Input/InputFile.js.map +1 -1
- package/lib/module/Input/README_INPUT_FILE.md +144 -23
- package/lib/module/Input/TextArea.js +5 -2
- package/lib/module/Input/TextArea.js.map +1 -1
- package/lib/module/Input/partials/InputFile/CardTrigger.js +77 -0
- package/lib/module/Input/partials/InputFile/CardTrigger.js.map +1 -0
- package/lib/module/Input/partials/InputFile/CardTriggerSmall.js +86 -0
- package/lib/module/Input/partials/InputFile/CardTriggerSmall.js.map +1 -0
- package/lib/module/Input/partials/InputFile/ItemPicker.js +43 -0
- package/lib/module/Input/partials/InputFile/ItemPicker.js.map +1 -0
- package/lib/module/Input/partials/InputFile/ItemPreview.js +149 -0
- package/lib/module/Input/partials/InputFile/ItemPreview.js.map +1 -0
- package/lib/module/Input/partials/InputFile/ModalDelete.js +76 -0
- package/lib/module/Input/partials/InputFile/ModalDelete.js.map +1 -0
- package/lib/module/Input/partials/InputFile/ModalPicker.js +72 -0
- package/lib/module/Input/partials/InputFile/ModalPicker.js.map +1 -0
- package/lib/module/LabelForm/LabelForm.js +3 -1
- package/lib/module/LabelForm/LabelForm.js.map +1 -1
- package/lib/module/Step/Step.js +1 -1
- package/lib/module/Step/StepItem.js +14 -6
- package/lib/module/Step/StepItem.js.map +1 -1
- package/lib/module/Ui/Center.js.map +1 -1
- package/lib/module/styles/layouting.js +3 -0
- package/lib/module/styles/layouting.js.map +1 -1
- package/lib/typescript/src/DatePicker/TimePicker.d.ts +4 -1
- package/lib/typescript/src/DatePicker/TimePicker.d.ts.map +1 -1
- package/lib/typescript/src/DatePicker/partials/AnimatedItem.d.ts +11 -0
- package/lib/typescript/src/DatePicker/partials/AnimatedItem.d.ts.map +1 -0
- package/lib/typescript/src/Input/InputFile.d.ts +17 -4
- package/lib/typescript/src/Input/InputFile.d.ts.map +1 -1
- package/lib/typescript/src/Input/TextArea.d.ts +1 -1
- package/lib/typescript/src/Input/TextArea.d.ts.map +1 -1
- package/lib/typescript/src/Input/partials/InputFile/CardTrigger.d.ts +11 -0
- package/lib/typescript/src/Input/partials/InputFile/CardTrigger.d.ts.map +1 -0
- package/lib/typescript/src/Input/partials/InputFile/CardTriggerSmall.d.ts +12 -0
- package/lib/typescript/src/Input/partials/InputFile/CardTriggerSmall.d.ts.map +1 -0
- package/lib/typescript/src/Input/partials/InputFile/ItemPicker.d.ts +10 -0
- package/lib/typescript/src/Input/partials/InputFile/ItemPicker.d.ts.map +1 -0
- package/lib/typescript/src/Input/partials/InputFile/ItemPreview.d.ts +11 -0
- package/lib/typescript/src/Input/partials/InputFile/ItemPreview.d.ts.map +1 -0
- package/lib/typescript/src/Input/partials/InputFile/ModalDelete.d.ts +12 -0
- package/lib/typescript/src/Input/partials/InputFile/ModalDelete.d.ts.map +1 -0
- package/lib/typescript/src/Input/partials/InputFile/ModalPicker.d.ts +18 -0
- package/lib/typescript/src/Input/partials/InputFile/ModalPicker.d.ts.map +1 -0
- package/lib/typescript/src/LabelForm/LabelForm.d.ts +2 -1
- package/lib/typescript/src/LabelForm/LabelForm.d.ts.map +1 -1
- package/lib/typescript/src/Step/StepItem.d.ts.map +1 -1
- package/lib/typescript/src/Ui/Center.d.ts +2 -2
- package/lib/typescript/src/Ui/Center.d.ts.map +1 -1
- package/lib/typescript/src/styles/layouting.d.ts +3 -0
- package/lib/typescript/src/styles/layouting.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/DatePicker/TimePicker.tsx +37 -74
- package/src/DatePicker/partials/AnimatedItem.tsx +62 -0
- package/src/Input/InputFile.tsx +148 -296
- package/src/Input/README_INPUT_FILE.md +144 -23
- package/src/Input/TextArea.tsx +3 -0
- package/src/Input/partials/InputFile/CardTrigger.tsx +87 -0
- package/src/Input/partials/InputFile/CardTriggerSmall.tsx +120 -0
- package/src/Input/partials/InputFile/ItemPicker.tsx +46 -0
- package/src/Input/partials/InputFile/ItemPreview.tsx +182 -0
- package/src/Input/partials/InputFile/ModalDelete.tsx +84 -0
- package/src/Input/partials/InputFile/ModalPicker.tsx +86 -0
- package/src/LabelForm/LabelForm.tsx +7 -2
- package/src/Step/Step.tsx +1 -1
- package/src/Step/StepItem.tsx +15 -3
- package/src/Ui/Center.tsx +2 -2
- package/src/styles/layouting.ts +1 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import BottomSheet from '../../../BottomSheet/BottomSheet';
|
|
2
|
+
interface Props extends React.ComponentProps<typeof BottomSheet> {
|
|
3
|
+
title: string;
|
|
4
|
+
descripition: string;
|
|
5
|
+
confirm: string;
|
|
6
|
+
onConfirm: () => void;
|
|
7
|
+
cancel: string;
|
|
8
|
+
onCnacel: () => void;
|
|
9
|
+
}
|
|
10
|
+
export default function ModalDelete({ title, descripition, confirm, cancel, onCnacel, onConfirm, ...props }: Props): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=ModalDelete.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModalDelete.d.ts","sourceRoot":"","sources":["../../../../../../src/Input/partials/InputFile/ModalDelete.tsx"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAM3D,UAAU,KAAM,SAAQ,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,KAAK,EACL,YAAY,EACZ,OAAO,EACP,MAAM,EACN,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,2CAkCP"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import BottomSheet from '../../../BottomSheet/BottomSheet';
|
|
2
|
+
import type { IconNameProps } from '../../../Icon';
|
|
3
|
+
interface FilePicker {
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
onPress: () => void;
|
|
7
|
+
icon: IconNameProps;
|
|
8
|
+
}
|
|
9
|
+
interface Props extends React.ComponentProps<typeof BottomSheet> {
|
|
10
|
+
title: string;
|
|
11
|
+
description: string;
|
|
12
|
+
camera: FilePicker;
|
|
13
|
+
gallery: FilePicker;
|
|
14
|
+
document: FilePicker;
|
|
15
|
+
}
|
|
16
|
+
export default function ModalPicker({ title, description, camera, gallery, document, ...props }: Props): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=ModalPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModalPicker.d.ts","sourceRoot":"","sources":["../../../../../../src/Input/partials/InputFile/ModalPicker.tsx"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAO3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,UAAU,KAAM,SAAQ,KAAK,CAAC,cAAc,CAAC,OAAO,WAAW,CAAC;IAC9D,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,UAAU,CAAC;IACpB,QAAQ,EAAE,UAAU,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,KAAK,EACL,WAAW,EACX,MAAM,EACN,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,KAAK,2CA4CP"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
interface Props {
|
|
2
2
|
title: string;
|
|
3
3
|
required?: boolean;
|
|
4
|
+
color?: string;
|
|
4
5
|
}
|
|
5
|
-
export default function LabelForm({ title, required }: Props): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export default function LabelForm({ title, required, color, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
6
7
|
export {};
|
|
7
8
|
//# sourceMappingURL=LabelForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LabelForm.d.ts","sourceRoot":"","sources":["../../../../src/LabelForm/LabelForm.tsx"],"names":[],"mappings":"AAIA,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"LabelForm.d.ts","sourceRoot":"","sources":["../../../../src/LabelForm/LabelForm.tsx"],"names":[],"mappings":"AAIA,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,KAAK,EACL,QAAQ,EACR,KAAuB,GACxB,EAAE,KAAK,2CAaP"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StepItem.d.ts","sourceRoot":"","sources":["../../../../src/Step/StepItem.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"StepItem.d.ts","sourceRoot":"","sources":["../../../../src/Step/StepItem.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAG5C,QAAA,MAAM,QAAQ,GAAI,sEAQf,aAAa,4CAuCf,CAAC;AAsCF,eAAe,QAAQ,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { type ViewStyle } from 'react-native';
|
|
1
|
+
import { type ViewStyle, type StyleProp } from 'react-native';
|
|
2
2
|
interface CenterProps {
|
|
3
3
|
children: React.ReactNode;
|
|
4
4
|
size?: number;
|
|
5
|
-
style?: ViewStyle
|
|
5
|
+
style?: StyleProp<ViewStyle>;
|
|
6
6
|
}
|
|
7
7
|
declare const Center: ({ children, style }: CenterProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
export default Center;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Center.d.ts","sourceRoot":"","sources":["../../../../src/Ui/Center.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"Center.d.ts","sourceRoot":"","sources":["../../../../src/Ui/Center.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAEhF,UAAU,WAAW;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAED,QAAA,MAAM,MAAM,GAAI,qBAAqB,WAAW,4CAE/C,CAAC;AASF,eAAe,MAAM,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layouting.d.ts","sourceRoot":"","sources":["../../../../src/styles/layouting.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS
|
|
1
|
+
{"version":3,"file":"layouting.d.ts","sourceRoot":"","sources":["../../../../src/styles/layouting.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCrB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
|
-
View,
|
|
4
|
-
StyleSheet,
|
|
5
|
-
Text,
|
|
6
|
-
Dimensions,
|
|
7
3
|
Animated,
|
|
8
|
-
|
|
4
|
+
Dimensions,
|
|
9
5
|
type NativeScrollEvent,
|
|
6
|
+
type NativeSyntheticEvent,
|
|
10
7
|
ScrollView,
|
|
8
|
+
StyleSheet,
|
|
9
|
+
View,
|
|
11
10
|
} from 'react-native';
|
|
12
11
|
import BottomSheet from '../BottomSheet/BottomSheet';
|
|
13
12
|
import Button from '../Button/Button';
|
|
14
|
-
import Typography from '../Typography/Typography';
|
|
15
13
|
import Color from '../Color/Color';
|
|
14
|
+
import Typography from '../Typography/Typography';
|
|
15
|
+
import AnimatedItem from './partials/AnimatedItem';
|
|
16
16
|
|
|
17
17
|
const ITEM_HEIGHT = 40;
|
|
18
18
|
const SCREEN_WIDTH = Dimensions.get('window').width;
|
|
@@ -24,6 +24,9 @@ interface TimePickerProps {
|
|
|
24
24
|
isOpen: boolean;
|
|
25
25
|
onClose?: () => void;
|
|
26
26
|
onChange?: (value: { hour: number; minute: number }) => void;
|
|
27
|
+
title?: string;
|
|
28
|
+
confirmLabel?: string;
|
|
29
|
+
cancelLabel?: string;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
const generateItems = (max: number) => Array.from({ length: max }, (_, i) => i);
|
|
@@ -35,6 +38,9 @@ export default function TimePickerWheel({
|
|
|
35
38
|
isOpen,
|
|
36
39
|
onClose,
|
|
37
40
|
onChange,
|
|
41
|
+
title = 'Pilih Waktu',
|
|
42
|
+
cancelLabel = 'Batal',
|
|
43
|
+
confirmLabel = 'Pilih',
|
|
38
44
|
}: TimePickerProps) {
|
|
39
45
|
const [selectedHour, setSelectedHour] = useState<number>(0);
|
|
40
46
|
const [selectedMinute, setSelectedMinute] = useState<number>(0);
|
|
@@ -69,13 +75,9 @@ export default function TimePickerWheel({
|
|
|
69
75
|
scrollToIndex(minuteRef, CENTER_INDEX_MINUTE);
|
|
70
76
|
}, 100);
|
|
71
77
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
selectedHour,
|
|
76
|
-
CENTER_INDEX_HOUR,
|
|
77
|
-
CENTER_INDEX_MINUTE,
|
|
78
|
-
]);
|
|
78
|
+
|
|
79
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
80
|
+
}, [isOpen]);
|
|
79
81
|
|
|
80
82
|
const scrollToIndex = (
|
|
81
83
|
ref: React.RefObject<ScrollView | null>,
|
|
@@ -116,47 +118,6 @@ export default function TimePickerWheel({
|
|
|
116
118
|
onClose?.();
|
|
117
119
|
};
|
|
118
120
|
|
|
119
|
-
const renderAnimatedItem = (
|
|
120
|
-
value: number,
|
|
121
|
-
type: 'hour' | 'minute',
|
|
122
|
-
index: number,
|
|
123
|
-
scrollY: Animated.Value
|
|
124
|
-
) => {
|
|
125
|
-
const normalizedValue =
|
|
126
|
-
type === 'hour' ? ((value % 24) + 24) % 24 : ((value % 60) + 60) % 60;
|
|
127
|
-
|
|
128
|
-
const inputRange = [
|
|
129
|
-
(index - 2) * ITEM_HEIGHT,
|
|
130
|
-
(index - 1) * ITEM_HEIGHT,
|
|
131
|
-
index * ITEM_HEIGHT,
|
|
132
|
-
(index + 1) * ITEM_HEIGHT,
|
|
133
|
-
(index + 2) * ITEM_HEIGHT,
|
|
134
|
-
];
|
|
135
|
-
|
|
136
|
-
const scale = scrollY.interpolate({
|
|
137
|
-
inputRange,
|
|
138
|
-
outputRange: [0.7, 0.85, 1, 0.85, 0.7],
|
|
139
|
-
extrapolate: 'clamp',
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const opacity = scrollY.interpolate({
|
|
143
|
-
inputRange,
|
|
144
|
-
outputRange: [0.3, 0.6, 1, 0.6, 0.3],
|
|
145
|
-
extrapolate: 'clamp',
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
return (
|
|
149
|
-
<Animated.View
|
|
150
|
-
key={`${type}-${index}`}
|
|
151
|
-
style={[styles.item, { transform: [{ scale }], opacity }]}
|
|
152
|
-
>
|
|
153
|
-
<Text style={styles.itemText}>
|
|
154
|
-
{normalizedValue.toString().padStart(2, '0')}
|
|
155
|
-
</Text>
|
|
156
|
-
</Animated.View>
|
|
157
|
-
);
|
|
158
|
-
};
|
|
159
|
-
|
|
160
121
|
return (
|
|
161
122
|
<BottomSheet
|
|
162
123
|
isOpen={isOpen}
|
|
@@ -165,7 +126,7 @@ export default function TimePickerWheel({
|
|
|
165
126
|
<View style={styles.footer}>
|
|
166
127
|
<View style={styles.flex1}>
|
|
167
128
|
<Button
|
|
168
|
-
title=
|
|
129
|
+
title={cancelLabel}
|
|
169
130
|
variant="tertiary"
|
|
170
131
|
onPress={onClose}
|
|
171
132
|
color="primary"
|
|
@@ -174,7 +135,7 @@ export default function TimePickerWheel({
|
|
|
174
135
|
</View>
|
|
175
136
|
<View style={styles.flex1}>
|
|
176
137
|
<Button
|
|
177
|
-
title=
|
|
138
|
+
title={confirmLabel}
|
|
178
139
|
onPress={handleSubmit}
|
|
179
140
|
color="primary"
|
|
180
141
|
size="medium"
|
|
@@ -190,7 +151,7 @@ export default function TimePickerWheel({
|
|
|
190
151
|
center
|
|
191
152
|
style={styles.hintTime}
|
|
192
153
|
>
|
|
193
|
-
|
|
154
|
+
{title}
|
|
194
155
|
</Typography>
|
|
195
156
|
|
|
196
157
|
<View style={styles.container}>
|
|
@@ -214,9 +175,15 @@ export default function TimePickerWheel({
|
|
|
214
175
|
scrollEventThrottle={16}
|
|
215
176
|
contentContainerStyle={styles.scrollContent}
|
|
216
177
|
>
|
|
217
|
-
{hours.map((h, i) =>
|
|
218
|
-
|
|
219
|
-
|
|
178
|
+
{hours.map((h, i) => (
|
|
179
|
+
<AnimatedItem
|
|
180
|
+
key={i}
|
|
181
|
+
index={i}
|
|
182
|
+
value={h}
|
|
183
|
+
type="hour"
|
|
184
|
+
scrollY={hourScrollY}
|
|
185
|
+
/>
|
|
186
|
+
))}
|
|
220
187
|
</Animated.ScrollView>
|
|
221
188
|
</View>
|
|
222
189
|
|
|
@@ -234,9 +201,15 @@ export default function TimePickerWheel({
|
|
|
234
201
|
scrollEventThrottle={16}
|
|
235
202
|
contentContainerStyle={styles.scrollContent}
|
|
236
203
|
>
|
|
237
|
-
{minutes.map((m, i) =>
|
|
238
|
-
|
|
239
|
-
|
|
204
|
+
{minutes.map((m, i) => (
|
|
205
|
+
<AnimatedItem
|
|
206
|
+
key={i}
|
|
207
|
+
index={i}
|
|
208
|
+
value={m}
|
|
209
|
+
type="minute"
|
|
210
|
+
scrollY={minuteScrollY}
|
|
211
|
+
/>
|
|
212
|
+
))}
|
|
240
213
|
</Animated.ScrollView>
|
|
241
214
|
</View>
|
|
242
215
|
</View>
|
|
@@ -270,16 +243,6 @@ const styles = StyleSheet.create({
|
|
|
270
243
|
height: ITEM_HEIGHT * VISIBLE_ITEMS,
|
|
271
244
|
overflow: 'hidden',
|
|
272
245
|
},
|
|
273
|
-
item: {
|
|
274
|
-
height: ITEM_HEIGHT,
|
|
275
|
-
justifyContent: 'center',
|
|
276
|
-
alignItems: 'center',
|
|
277
|
-
},
|
|
278
|
-
itemText: {
|
|
279
|
-
fontSize: 22,
|
|
280
|
-
color: Color.gray[900],
|
|
281
|
-
fontWeight: '600',
|
|
282
|
-
},
|
|
283
246
|
highlightOverlay: {
|
|
284
247
|
position: 'absolute',
|
|
285
248
|
zIndex: -1,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Animated, StyleSheet, Text } from 'react-native';
|
|
3
|
+
import Color from '../../Color/Color';
|
|
4
|
+
|
|
5
|
+
interface AnimatedItemProps {
|
|
6
|
+
value: number;
|
|
7
|
+
scrollY: Animated.Value;
|
|
8
|
+
index: number;
|
|
9
|
+
type: 'hour' | 'minute';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const ITEM_HEIGHT = 40;
|
|
13
|
+
|
|
14
|
+
const AnimatedItem = React.memo(
|
|
15
|
+
({ value, scrollY, index, type }: AnimatedItemProps) => {
|
|
16
|
+
const normalizedValue =
|
|
17
|
+
type === 'hour' ? ((value % 24) + 24) % 24 : ((value % 60) + 60) % 60;
|
|
18
|
+
|
|
19
|
+
const inputRange = [
|
|
20
|
+
(index - 2) * ITEM_HEIGHT,
|
|
21
|
+
(index - 1) * ITEM_HEIGHT,
|
|
22
|
+
index * ITEM_HEIGHT,
|
|
23
|
+
(index + 1) * ITEM_HEIGHT,
|
|
24
|
+
(index + 2) * ITEM_HEIGHT,
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const scale = scrollY.interpolate({
|
|
28
|
+
inputRange,
|
|
29
|
+
outputRange: [0.7, 0.85, 1, 0.85, 0.7],
|
|
30
|
+
extrapolate: 'clamp',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const opacity = scrollY.interpolate({
|
|
34
|
+
inputRange,
|
|
35
|
+
outputRange: [0.3, 0.6, 1, 0.6, 0.3],
|
|
36
|
+
extrapolate: 'clamp',
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<Animated.View style={[styles.item, { transform: [{ scale }], opacity }]}>
|
|
41
|
+
<Text style={styles.itemText}>
|
|
42
|
+
{normalizedValue.toString().padStart(2, '0')}
|
|
43
|
+
</Text>
|
|
44
|
+
</Animated.View>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const styles = StyleSheet.create({
|
|
50
|
+
itemText: {
|
|
51
|
+
fontSize: 22,
|
|
52
|
+
color: Color.gray[900],
|
|
53
|
+
fontWeight: '600',
|
|
54
|
+
},
|
|
55
|
+
item: {
|
|
56
|
+
height: ITEM_HEIGHT,
|
|
57
|
+
justifyContent: 'center',
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export default AnimatedItem;
|