react-native-global-datetimepicker
Version:
react native multi culture datetime picker
185 lines • 8.14 kB
JavaScript
import React, { useEffect, useRef } from 'react';
import { toPersianNumber } from '../../Utilities';
import useDateTimePicker from '../../Hooks/useDateTimePicker';
import { Animated, Text, View } from 'react-native';
import { PickerMode } from '../../Providers/DateTimePickerProvider';
export default function Clock() {
const { theme, pickerMode, setHour, setPickerMode, setMinute, selectedDate, persianNumber, } = useDateTimePicker();
const isHourMode = pickerMode === PickerMode.Hour;
const value = isHourMode
? selectedDate.getHours()
: selectedDate.getMinutes();
const isPM = selectedDate.getHours() >= 12;
const textSize = 30;
const itemCount = 12;
const clockPadding = 5;
const clockSize = 285 - 20;
const angleMode = (angle) => {
return ((angle % 360) + 360) % 360;
};
const angleToValue = (angle) => {
const angleDiff = 360 / itemCount;
const value = angleMode(angle + 720 / itemCount) / angleDiff + 1;
if (isHourMode) {
if (isPM) {
return (value % 12) + 12;
}
else {
return value % 12;
}
}
else {
return (value * 5) % 60;
}
};
const valueToAngle = (value) => {
const angleDiff = 360 / itemCount;
return angleMode((value / (isHourMode ? 1 : 5) - (isPM && isHourMode ? 12 : 0)) *
angleDiff -
90);
};
const onChangeValue = (animated, resultAngle) => {
if (((lastRotation.current % 360) + 360) % 360 ===
((resultAngle % 360) + 360) % 360) {
return;
}
lastRotation.current = resultAngle;
if (animated)
Animated.timing(rotationAnim, {
duration: 200,
useNativeDriver: true,
toValue: resultAngle,
}).start();
else
rotationAnim.setValue(resultAngle);
};
const lastRotation = useRef(value);
const lastHour = useRef(selectedDate.getHours());
const lastTouch = useRef(selectedDate.getHours());
const rotationAnim = useRef(new Animated.Value(valueToAngle(value))).current;
useEffect(() => {
onChangeValue(true, valueToAngle(value));
}, [pickerMode, value]);
const onRelease = (e) => {
if (e.timeStamp - lastTouch.current > 250) {
lastHour.current = selectedDate.getHours();
return;
}
const x = e.nativeEvent.locationX - clockSize / 2;
const y = clockSize / 2 - e.nativeEvent.locationY;
const angle = (Math.atan2(y, x) * 180) / Math.PI;
const angleDiff = isHourMode ? 360 / itemCount : 360 / 60;
const result = Math.round(angle / angleDiff) * -angleDiff;
const resultValue = angleToValue(result);
if (isHourMode && resultValue == lastHour.current) {
setPickerMode(PickerMode.Minute);
}
lastHour.current = selectedDate.getHours();
};
const onTouch = (isStart, e) => {
if (isStart) {
lastTouch.current = e.timeStamp;
}
const x = e.nativeEvent.locationX - clockSize / 2;
const y = clockSize / 2 - e.nativeEvent.locationY;
const angle = (Math.atan2(y, x) * 180) / Math.PI;
const angleDiff = isHourMode ? 360 / itemCount : 360 / 60;
const result = Math.round(angle / angleDiff) * -angleDiff;
const resultValue = angleToValue(result);
if (isHourMode) {
setHour(resultValue);
}
else {
setMinute(resultValue);
}
onChangeValue(isStart, result);
};
return (React.createElement(View, { style: { flex: 1, justifyContent: 'center' } },
React.createElement(View, { style: {
width: clockSize,
height: clockSize,
position: 'relative',
borderRadius: clockSize,
backgroundColor: theme.ClockBackground,
} },
React.createElement(View, { style: {
width: '100%',
height: '100%',
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
} }, [...Array(itemCount)].map((_, i) => {
let a = (360 / itemCount) * i - 720 / itemCount;
let b = (-360 / itemCount) * i + 720 / itemCount;
const lable = (i + 1) * (isHourMode ? 1 : 5) + (isPM && isHourMode ? 12 : 0);
return (React.createElement(View, { key: i + itemCount * (value + itemCount * (isHourMode ? 1 : 2)), style: {
position: 'absolute',
transform: [
{ rotate: a + 'deg' },
{ translateX: (clockSize - textSize) / 2 - clockPadding },
],
} },
React.createElement(View, { style: {
padding: 3,
borderRadius: 50,
backgroundColor: value / (isHourMode ? 1 : 5) -
(isPM && isHourMode ? 12 : 0) ==
(i + 1) % 12
? theme.ClockPointer
: undefined,
} },
React.createElement(Text, { style: {
fontSize: 18,
width: textSize,
height: textSize,
fontWeight: 'bold',
textAlign: 'center',
textAlignVertical: 'center',
color: value / (isHourMode ? 1 : 5) -
(isPM && isHourMode ? 12 : 0) ==
(i + 1) % 12
? theme.SelectedClockForeground
: theme.ClockForeground,
transform: [{ rotate: b + 'deg' }],
} }, persianNumber ? toPersianNumber(`${lable}`) : lable))));
})),
React.createElement(View, { onResponderRelease: onRelease, onStartShouldSetResponder: () => true, onResponderStart: onTouch.bind(null, true), onResponderMove: onTouch.bind(null, false), style: {
zIndex: 10,
width: '100%',
height: '100%',
position: 'absolute',
} }),
React.createElement(Animated.View, { style: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
transform: [
{
rotate: rotationAnim.interpolate({
inputRange: [-180, 0, 180],
outputRange: ['-180deg', '0deg', '180deg'],
}),
},
{ translateX: -4 },
{ translateY: -4 },
],
} },
React.createElement(View, null,
React.createElement(View, { style: {
width: 8,
zIndex: 1,
height: 8,
borderRadius: 4,
position: 'absolute',
backgroundColor: theme.ClockPointer,
} }),
React.createElement(View, { style: {
height: 4,
borderRadius: 4,
position: 'absolute',
width: clockSize * 0.37,
backgroundColor: theme.ClockPointer,
transform: [{ translateX: 4 }, { translateY: 2 }],
} }))))));
}
//# sourceMappingURL=index.js.map