UNPKG

react-native-lucy-radial-slider

Version:

React Native component to select or highlight a specific value from a range of values

98 lines 6.46 kB
import React, { useEffect, useState } from 'react'; import Svg, { Path, Defs, LinearGradient, Stop, Circle, } from 'react-native-svg'; import { View, Platform, StyleSheet } from 'react-native'; import { styles } from './styles'; import { Colors } from '../../theme'; import { useSliderAnimation, useRadialSlider } from './hooks'; import { defaultProps } from './SliderDefaultProps'; import ButtonContent from './ButtonContent'; import TailText from './TailText'; import LineContent from './LineContent'; const RadialSlider = (props) => { const [isStart, setIsStart] = useState(false); const [iconPosition, setIconPosition] = useState(''); const { step, radius, sliderWidth, sliderTrackColor, linearGradient, strokeColor, thumbRadius, thumbBorderColor, thumbColor, thumbBorderWidth, style, markerLineSize, disabled, contentStyle, buttonContainerStyle, min, max, isHideSlider, isHideTailText, isHideButtons, isHideLines, isHideStroke, isHideThumb, leftIconStyle, rightIconStyle, stroke, children, } = props; const { panResponder, value, setValue, curPoint, currentRadian, prevValue } = useSliderAnimation(props); const { svgSize, containerRef, startPoint, endPoint, startRadian, radianValue, isRadialCircleVariant, centerValue, } = useRadialSlider(props); useEffect(() => { var _a; //check max value length const maxLength = (_a = max === null || max === void 0 ? void 0 : max.toString()) === null || _a === void 0 ? void 0 : _a.length; const timerId = setTimeout(handleValue, maxLength > 2 ? 10 : 100); return () => clearTimeout(timerId); }); const handleValue = () => { if (iconPosition === 'up' && max > value) { isStart && onPressButtons('up'); } else if (iconPosition === 'down' && min < value) { isStart && onPressButtons('down'); } }; const leftButtonStyle = StyleSheet.flatten([ leftIconStyle, (disabled || min === value) && { opacity: 0.5, }, ]); const rightButtonStyle = StyleSheet.flatten([ rightIconStyle, (disabled || max === value) && { opacity: 0.5, }, ]); const onLayout = () => { const ref = containerRef.current; if (ref) { ref.measure((_x, _y, _width, _height) => { }); } }; const onPressButtons = (type) => { if (type === 'up' && max > value) { setValue((prevState) => { const calculatedValue = prevState + step; const roundedValue = parseFloat(calculatedValue.toFixed(1)); return roundedValue; }); } else if (type === 'down' && min < value) { setValue((prevState) => { const calculatedValue = prevState - step; const roundedValue = parseFloat(calculatedValue.toFixed(1)); prevValue.current = roundedValue; return roundedValue; }); } }; const circleXPosition = isRadialCircleVariant ? centerValue < value ? -7 : 4 : 0; const strokeLinecap = isRadialCircleVariant ? 'square' : 'round'; return (React.createElement(View, { onLayout: onLayout, ref: containerRef, style: [styles.container, style, { width: svgSize, height: svgSize }], testID: "slider-view" }, React.createElement(Svg, { width: svgSize + markerLineSize / 2 - (Platform.OS === 'web' ? 20 : 0), height: svgSize + markerLineSize / 2, viewBox: `-${markerLineSize / 2} -${markerLineSize / 2} ${svgSize + markerLineSize} ${svgSize + markerLineSize}`, preserveAspectRatio: "none" }, React.createElement(Defs, null, React.createElement(LinearGradient, { x1: "0%", y1: "100%", x2: "100%", y2: "0%", id: "gradient" }, linearGradient.map((item, index) => (React.createElement(Stop, { key: index, offset: item.offset, stopColor: item.color }))))), !isRadialCircleVariant && !isHideTailText && React.createElement(TailText, { ...props }), !isHideLines && React.createElement(LineContent, { ...props, value: value }), !isHideSlider && (React.createElement(React.Fragment, null, React.createElement(Path, { strokeWidth: sliderWidth, stroke: sliderTrackColor, fill: "none", strokeLinecap: strokeLinecap, d: `M${startPoint.x},${startPoint.y} A ${radius},${radius},0,${startRadian - radianValue >= Math.PI ? '1' : '0'},1,${endPoint.x},${endPoint.y}` }), !isHideStroke && (React.createElement(Path, { strokeWidth: sliderWidth, stroke: `${linearGradient.length > 0 ? 'url(#gradient)' : strokeColor}`, fill: "none", strokeLinecap: strokeLinecap, d: `M${startPoint.x},${startPoint.y} A ${radius},${radius},0,${startRadian - currentRadian >= Math.PI ? '1' : '0'},1,${curPoint.x},${curPoint.y}` })), !isHideThumb && (React.createElement(Circle, { cx: curPoint.x + circleXPosition, cy: curPoint.y, r: thumbRadius, fill: thumbColor || thumbBorderColor, stroke: thumbBorderColor, strokeWidth: thumbBorderWidth, ...panResponder.panHandlers }))))), React.createElement(View, { style: [styles.content, contentStyle], pointerEvents: "box-none" }, children, !isRadialCircleVariant && !isHideButtons && (React.createElement(View, { style: [styles.buttonsWrapper, buttonContainerStyle] }, React.createElement(View, { style: styles.center }, React.createElement(ButtonContent, { onPress: () => onPressButtons('down'), onLongPress: () => { setIsStart(true); setIconPosition('down'); }, onPressOut: () => setIsStart(false), buttonType: "left-btn", style: leftButtonStyle, disabled: disabled || min === value, stroke: stroke !== null && stroke !== void 0 ? stroke : Colors.blue }), React.createElement(ButtonContent, { disabled: disabled || max === value, onPress: () => onPressButtons('up'), onLongPress: () => { setIsStart(true); setIconPosition('up'); }, onPressOut: () => setIsStart(false), style: rightButtonStyle, buttonType: "right-btn", stroke: stroke !== null && stroke !== void 0 ? stroke : Colors.blue }))))))); }; RadialSlider.defaultProps = defaultProps; export default RadialSlider; //# sourceMappingURL=RadialSlider.js.map