UNPKG

zmp-ui

Version:

Zalo Mini App framework

242 lines 7.65 kB
import clsx from "clsx"; import React, { useMemo, useRef } from "react"; import Text from "../text"; import { clamp } from "../../utils/clamp"; import { getPosition } from "../../utils/get-position"; import { getPrefixCls } from "../../utils/class"; import useMergedState from "../../hooks/useMergedState"; import Track from "./Track"; import { getChangeValue } from "../../utils/get-change-value"; import Thumb from "./Thumb"; var Slider = function Slider(props) { var rawValue = props.value, defaultValue = props.defaultValue, name = props.name, label = props.label, showValue = props.showValue, renderValue = props.renderValue, prefix = props.prefix, suffix = props.suffix, _props$min = props.min, min = _props$min === void 0 ? 0 : _props$min, _props$max = props.max, max = _props$max === void 0 ? 100 : _props$max, _props$step = props.step, step = _props$step === void 0 ? 1 : _props$step, _props$minRange = props.minRange, minRange = _props$minRange === void 0 ? 1 : _props$minRange, _props$marks = props.marks, marks = _props$marks === void 0 ? false : _props$marks, onChange = props.onChange; var prefixCls = getPrefixCls("slider"); var _useMergedState = useMergedState(defaultValue || 0, { value: rawValue }), value = _useMergedState[0], setValue = _useMergedState[1]; var valueRender = useMemo(function () { if (!showValue) return null; if (renderValue) { return renderValue(value); } return Array.isArray(value) ? value.join(" - ") : value; }, [value, showValue, renderValue]); var _useMemo = useMemo(function () { if (!Array.isArray(value)) { return { offset: 0, position: getPosition({ min: min, max: max, value: value || 0 }) }; } var start = getPosition({ min: min, max: max, value: value[0] }); var end = getPosition({ min: min, max: max, value: value[1] }); return { offset: start, position: end - start }; }, [value, min, max]), offset = _useMemo.offset, position = _useMemo.position; var markList = useMemo(function () { if (!marks) return undefined; if (marks !== true) return marks.map(function (mark) { return getPosition({ min: min, max: max, value: mark }); }); var stepCount = (max - min) / step; var list = []; for (var i = 0; i <= stepCount; i += 1) { var markValue = min + i * step; var markPosition = getPosition({ min: min, max: max, value: markValue }); list.push(markPosition); } return list; }, [marks, min, max, step]); var isSliding = useRef(false); var frame = useRef(0); var trackRef = useRef(null); var thumbIndex = useRef(0); var handleChange = function handleChange(_ref) { var x = _ref.x; var nextValue = getChangeValue({ value: x, min: min, max: max, step: step }); if (!Array.isArray(value)) { setValue(nextValue); onChange == null || onChange(nextValue); } else { var start = value[0], end = value[1]; if (thumbIndex.current === 0) { var endValue = clamp(end - nextValue < minRange ? nextValue + step : end, min, max); if (endValue - nextValue < minRange) return; var newValue = [nextValue, endValue]; setValue(newValue); onChange == null || onChange(newValue); } else { var startValue = clamp(nextValue - start < minRange ? nextValue - step : start, min, max); if (nextValue - startValue < minRange) return; var cloneValue = [startValue, nextValue]; setValue(cloneValue); onChange == null || onChange(cloneValue); } } }; var handleMove = function handleMove(_ref2, checkNearest) { var x = _ref2.x; cancelAnimationFrame(frame.current); frame.current = requestAnimationFrame(function () { if (trackRef.current) { var rect = trackRef.current.getBoundingClientRect(); if (rect.width && rect.height) { var tempX = clamp((x - rect.left) / rect.width, 0, 1); if (checkNearest) { if (Array.isArray(value)) { var start = value[0], end = value[1]; var middle = (start + end) / 2; var nextValue = getChangeValue({ value: tempX, min: min, max: max, step: step }); thumbIndex.current = nextValue < middle ? 0 : 1; } else { thumbIndex.current = 0; } } handleChange({ x: tempX }); } } }); }; var handleMouseDown = function handleMouseDown(event) { isSliding.current = true; handleMove({ x: event.clientX, y: event.clientY }, true); }; var handleMouseMove = function handleMouseMove(e) { if (isSliding.current) { handleMove({ x: e.clientX, y: e.clientY }); } }; var handleMouseUp = function handleMouseUp() { isSliding.current = false; }; var handleTouchStart = function handleTouchStart(event) { isSliding.current = true; handleMove({ x: event.touches[0].clientX, y: event.touches[0].clientY }, true); }; var handleTouchMove = function handleTouchMove(e) { if (e.cancelable) e.preventDefault(); isSliding.current = true; handleMove({ x: e.touches[0].clientX, y: e.touches[0].clientY }); }; var handleTouchEnd = function handleTouchEnd() { isSliding.current = false; }; return /*#__PURE__*/React.createElement("div", { className: clsx(prefixCls + "-wrapper") }, (label || showValue) && /*#__PURE__*/React.createElement("div", { className: clsx(prefixCls + "-header") }, /*#__PURE__*/React.createElement(Text, { className: clsx(prefixCls + "-label") }, label), /*#__PURE__*/React.createElement(Text, { size: "small", bold: true, className: clsx(prefixCls + "-value") }, valueRender)), /*#__PURE__*/React.createElement("div", { className: clsx(prefixCls + "-content") }, prefix && /*#__PURE__*/React.createElement("div", { className: clsx(prefixCls + "-prefix") }, prefix), /*#__PURE__*/React.createElement("div", { role: "presentation", className: clsx(prefixCls + "-handler"), onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, onMouseUp: handleMouseUp, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd }, /*#__PURE__*/React.createElement(Track, { ref: trackRef, width: position, offset: offset, marks: markList }, Array.isArray(value) && /*#__PURE__*/React.createElement(Thumb, { position: offset }), /*#__PURE__*/React.createElement(Thumb, { position: offset + position }))), suffix && /*#__PURE__*/React.createElement("div", { className: clsx(prefixCls + "-suffix") }, suffix)), Array.isArray(value) ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("input", { type: "hidden", name: name ? name + "_from" : undefined, value: value[0] }), /*#__PURE__*/React.createElement("input", { type: "hidden", name: name ? name + "_to" : undefined, value: value[1] })) : /*#__PURE__*/React.createElement("input", { type: "hidden", name: name, value: value })); }; export default Slider;