UNPKG

react-native-modern-elements

Version:

A modern, customizable UI component library for React Native

313 lines (312 loc) 15.2 kB
import React, { memo, useRef, useState } from "react"; import { PanResponder, StyleSheet, Text, View } from "react-native"; import TrackThumlable from "../helper/TrackThumlable"; import Wheel from "../helper/Wheel"; import formatPrice from "../helper/formatPrice"; const RangeSlider = ({ sliderWidth, min, max, step = 10, mode = "range", // default = 2 thumbs onValueChange, thumbStyle = "one", // default = one thumb thumbValue = "parcentage", // default = percentage // ==== New STYLE PROPS ==== TrackthumbLabelBackgroundColor = "#3F4CF6", TrackHeight = 8, defaultTrackColor = "#DFEAFB", trickBorderRadious = 50, // default = 50 textColor = "white", fontSize = 10, // default = 12 priceSymbols = "$", defaultLeftPercent, // default = 15% defaultRightPercent, // default = 80% formatPrices = false, }) => { const [minVal, setMinVal] = useState(Math.round(min + (max - min) * (defaultLeftPercent !== null && defaultLeftPercent !== void 0 ? defaultLeftPercent : 0)) // default 0% ); const [maxVal, setMaxVal] = useState(Math.round(min + (max - min) * (defaultRightPercent !== null && defaultRightPercent !== void 0 ? defaultRightPercent : 1)) // default 100% ); // const minPos = useRef(0); // const maxPos = useRef(sliderWidth); // Initialize thumb positions in pixels const minPos = useRef((defaultLeftPercent !== null && defaultLeftPercent !== void 0 ? defaultLeftPercent : 0) * sliderWidth); const maxPos = useRef((defaultRightPercent !== null && defaultRightPercent !== void 0 ? defaultRightPercent : 1) * sliderWidth); const gapPixels = ((step * 1) / (max - min)) * sliderWidth; // === Range Mode - Left Thumb === const minPan = PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderMove: (_, gesture) => { let newPos = minPos.current + gesture.dx; newPos = Math.max(0, Math.min(newPos, maxPos.current - gapPixels)); minPos.current = newPos; const val = Math.round((newPos / sliderWidth) * (max - min) + min); setMinVal(val); onValueChange({ min: val, max: maxVal }); }, }); // === Range Mode - Right Thumb === const maxPan = PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderMove: (_, gesture) => { let newPos = maxPos.current + gesture.dx; newPos = Math.min(sliderWidth, Math.max(newPos, minPos.current + gapPixels)); maxPos.current = newPos; const val = Math.round((newPos / sliderWidth) * (max - min) + min); setMaxVal(val); onValueChange({ min: minVal, max: val }); }, }); // === Single Thumb Mode === const singlePos = useRef((defaultLeftPercent !== null && defaultLeftPercent !== void 0 ? defaultLeftPercent : 0) * sliderWidth); const [singleVal, setSingleVal] = useState(Math.round(min + (max - min) * (defaultLeftPercent !== null && defaultLeftPercent !== void 0 ? defaultLeftPercent : 0))); const singlePan = PanResponder.create({ onStartShouldSetPanResponder: () => true, onPanResponderMove: (_, gesture) => { let newPos = singlePos.current + gesture.dx; newPos = Math.max(0, Math.min(newPos, sliderWidth)); singlePos.current = newPos; const val = Math.round((newPos / sliderWidth) * (max - min) + min); setSingleVal(val); // ✅ always return object, no TypeScript error onValueChange({ min, max: val }); }, }); return (React.createElement(View, { style: [styles.sliderContainer, { width: sliderWidth }] }, React.createElement(View, { style: [ { height: TrackHeight, backgroundColor: defaultTrackColor, borderRadius: trickBorderRadious, }, styles.track, ] }), mode === "range" && (React.createElement(View, { style: [ { backgroundColor: TrackthumbLabelBackgroundColor, height: TrackHeight, borderRadius: trickBorderRadious, }, styles.selectedTrack, { left: ((minVal - min) / (max - min)) * sliderWidth, width: ((maxVal - minVal) / (max - min)) * sliderWidth, }, ] })), mode === "single" && (React.createElement(View, { style: [ { backgroundColor: TrackthumbLabelBackgroundColor, height: TrackHeight, borderRadius: trickBorderRadious, }, styles.selectedTrack, { width: ((singleVal - min) / (max - min)) * sliderWidth, }, ] })), mode === "range" && (React.createElement(View, Object.assign({ style: [ { borderColor: TrackthumbLabelBackgroundColor }, thumbStyle === "one" ? styles.thumb : thumbStyle === "two" ? styles.thumbs : thumbStyle === "three" ? styles.thumb : thumbStyle === "four" ? styles.thumb : thumbStyle === "five" && styles.thumb, { left: ((minVal - min) / (max - min)) * sliderWidth - 10 }, ] }, minPan.panHandlers), React.createElement(TrackThumlable, null), thumbStyle === "one" ? (React.createElement(React.Fragment, null, React.createElement(Text, { style: [ { backgroundColor: TrackthumbLabelBackgroundColor, color: textColor, fontSize: fontSize, }, styles.thumbLabel, ] }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(minVal) : minVal}` : `${Math.round(((minVal - min) / (max - min)) * 100)}%`), React.createElement(Wheel, null))) : thumbStyle === "two" ? (React.createElement(Text, { style: { color: textColor, fontSize: fontSize } }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(minVal) : minVal}` : `${Math.round(((minVal - min) / (max - min)) * 100)}%`)) : thumbStyle === "three" ? null : thumbStyle === "four" ? (React.createElement(Text, { style: [ styles === null || styles === void 0 ? void 0 : styles.thumbLabelss, { color: textColor, fontSize: fontSize }, ] }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(minVal) : minVal}` : `${Math.round(((minVal - min) / (max - min)) * 100)}%`)) : (thumbStyle === "five" && (React.createElement(Text, { style: [ styles === null || styles === void 0 ? void 0 : styles.thumbLabelss5, { color: textColor, fontSize: fontSize }, ] }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(minVal) : minVal}` : `${Math.round(((minVal - min) / (max - min)) * 100)}%`))))), mode === "range" && (React.createElement(View, Object.assign({ style: [ { borderColor: TrackthumbLabelBackgroundColor }, thumbStyle === "one" ? styles.thumb : thumbStyle === "two" ? styles.thumbs : thumbStyle === "three" ? styles.thumb : thumbStyle === "four" ? styles.thumb : thumbStyle === "five" && styles.thumb, , { left: ((maxVal - min) / (max - min)) * sliderWidth - 10 }, ] }, maxPan.panHandlers), React.createElement(TrackThumlable, null), thumbStyle === "one" ? (React.createElement(React.Fragment, null, React.createElement(Text, { style: [ { backgroundColor: TrackthumbLabelBackgroundColor, color: textColor, fontSize: fontSize, }, , styles.thumbLabelRight, ] }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(maxVal) : maxVal}` : `${Math.round(((maxVal - min) / (max - min)) * 100)}%`), React.createElement(Wheel, null))) : thumbStyle === "two" ? (React.createElement(Text, { style: { color: textColor, fontSize: fontSize } }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(maxVal) : maxVal}` : `${Math.round(((maxVal - min) / (max - min)) * 100)}%`)) : thumbStyle === "three" ? null : thumbStyle === "four" ? (React.createElement(Text, { style: [ styles === null || styles === void 0 ? void 0 : styles.thumbLabelss, { color: textColor, fontSize: fontSize }, ] }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(maxVal) : maxVal}` : `${Math.round(((maxVal - min) / (max - min)) * 100)}%`)) : (thumbStyle === "five" && (React.createElement(Text, { style: [ styles === null || styles === void 0 ? void 0 : styles.thumbLabelss5, { color: textColor, fontSize: fontSize }, ] }, thumbValue === "Value" ? `${priceSymbols}${formatPrices === true ? formatPrice(maxVal) : maxVal}` : `${Math.round(((maxVal - min) / (max - min)) * 100)}%`))))), mode === "single" && (React.createElement(View, Object.assign({ style: [ { borderColor: TrackthumbLabelBackgroundColor }, thumbStyle === "one" ? styles.thumb : thumbStyle === "two" ? styles.thumbs : thumbStyle === "three" ? styles.thumb : thumbStyle === "four" ? styles.thumb : thumbStyle === "five" && styles.thumb, { left: ((singleVal - min) / (max - min)) * sliderWidth - 10 }, ] }, singlePan.panHandlers), React.createElement(TrackThumlable, null), thumbStyle === "one" ? (React.createElement(React.Fragment, null, React.createElement(Text, { style: [ { backgroundColor: TrackthumbLabelBackgroundColor, color: textColor, fontSize: fontSize, }, styles.thumbLabel, ] }, thumbValue === "Value" ? ` ${priceSymbols}${formatPrices === true ? formatPrice(singleVal) : singleVal}` : `${Math.round(((singleVal - min) / (max - min)) * 100)}%`), React.createElement(Wheel, null))) : thumbStyle === "two" ? (React.createElement(Text, { style: { color: textColor, fontSize } }, thumbValue === "Value" ? ` ${priceSymbols}${formatPrices === true ? formatPrice(singleVal) : singleVal}` : `${Math.round(((singleVal - min) / (max - min)) * 100)}%`)) : thumbStyle === "three" ? null : thumbStyle === "four" ? (React.createElement(Text, { style: [ styles === null || styles === void 0 ? void 0 : styles.thumbLabelss, { color: textColor, fontSize: fontSize }, ] }, thumbValue === "Value" ? ` ${priceSymbols}${formatPrices === true ? formatPrice(singleVal) : singleVal}` : `${Math.round(((singleVal - min) / (max - min)) * 100)}%`)) : (thumbStyle === "five" && (React.createElement(Text, { style: [ styles === null || styles === void 0 ? void 0 : styles.thumbLabelss5, { color: textColor, fontSize: fontSize }, ] }, thumbValue === "Value" ? ` ${priceSymbols}${formatPrices === true ? formatPrice(singleVal) : singleVal}` : `${Math.round(((singleVal - min) / (max - min)) * 100)}%`))))))); }; export default memo(RangeSlider); const styles = StyleSheet.create({ sliderContainer: { height: 50, justifyContent: "center" }, track: {}, selectedTrack: { position: "absolute", // top: 20, left: 0, }, thumb: { position: "absolute", width: 20, height: 20, backgroundColor: "white", borderWidth: 3, // borderColor: "#3F4CF6", borderRadius: 10, justifyContent: "center", alignItems: "center", top: 10, }, thumbLabel: { position: "absolute", top: -30, width: 40, height: 22, textAlign: "center", fontWeight: "bold", borderTopRightRadius: 50, borderTopLeftRadius: 10, borderBottomRightRadius: 10, overflow: "hidden", }, thumbLabel2: { position: "absolute", top: -40, width: 50, height: 120, borderWidth: 1, textAlign: "center", fontWeight: "bold", borderTopRightRadius: 50, borderTopLeftRadius: 10, borderBottomRightRadius: 10, overflow: "hidden", }, thumbLabelRight: { position: "absolute", top: -30, width: 41, height: 24, flexDirection: "column", textAlign: "center", fontWeight: "500", borderTopRightRadius: 10, borderTopLeftRadius: 50, borderBottomLeftRadius: 10, overflow: "hidden", }, thumbs: { position: "absolute", width: 36, height: 36, backgroundColor: "white", borderWidth: 3, // borderColor: "#3F4CF6", borderRadius: 50, justifyContent: "center", alignItems: "center", top: 2.5, }, thumbLabelss: { position: "absolute", top: -30, fontSize: 12, color: "black", width: 100, height: 25, textAlign: "center", fontWeight: "bold", borderTopRightRadius: 50, borderTopLeftRadius: 10, borderBottomRightRadius: 10, overflow: "hidden", }, thumbLabelss5: { position: "absolute", top: 30, fontSize: 12, color: "black", width: 100, height: 25, textAlign: "center", fontWeight: "bold", borderTopRightRadius: 50, borderTopLeftRadius: 10, borderBottomRightRadius: 10, overflow: "hidden", }, });