UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

491 lines (490 loc) 18 kB
import { _ as _define_property } from "@swc/helpers/_/_define_property"; import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import classNames from "classnames"; import { useTouch } from "../../hooks/use-touch"; import { getRect } from "../../utils/get-rect"; import { ComponentDefaults } from "../../utils/typings"; import { usePropsValue } from "../../hooks/use-props-value"; import { useRtl } from "../configprovider"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { range: false, min: 0, max: 100, step: 1, vertical: false, marks: {} }); var classPrefix = 'nut-range'; var verticalClassPrefix = "".concat(classPrefix, "-vertical"); var isSameValue = function(newValue, oldValue) { return JSON.stringify(newValue) === JSON.stringify(oldValue); }; var handleOverlap = function(value) { if (value[0] > value[1]) { return value.slice(0).reverse(); } return value; }; export var Range = function(props) { var rtl = useRtl(); var _$_object_spread = _object_spread({}, defaultProps, props), className = _$_object_spread.className, style = _$_object_spread.style, range = _$_object_spread.range, disabled = _$_object_spread.disabled, button = _$_object_spread.button, vertical = _$_object_spread.vertical, marks = _$_object_spread.marks, minDescription = _$_object_spread.minDescription, maxDescription = _$_object_spread.maxDescription, currentDescription = _$_object_spread.currentDescription, min = _$_object_spread.min, max = _$_object_spread.max, step = _$_object_spread.step, value = _$_object_spread.value, defaultValue = _$_object_spread.defaultValue, onChange = _$_object_spread.onChange, onStart = _$_object_spread.onStart, onEnd = _$_object_spread.onEnd; var rtlClassPrefix = useMemo(function() { return "rtl-".concat(vertical ? verticalClassPrefix : classPrefix); }, [ vertical ]); var _useState = _sliced_to_array(useState(0), 2), buttonIndex = _useState[0], setButtonIndex = _useState[1]; var _useState1 = _sliced_to_array(useState('start'), 2), dragStatus = _useState1[0], setDragStatus = _useState1[1]; var touch = useTouch(); var root = useRef(null); var _useState2 = _sliced_to_array(useState([]), 2), marksList = _useState2[0], setMarksList = _useState2[1]; var _useState3 = _sliced_to_array(useState(0), 2), startValue = _useState3[0], setStartValue = _useState3[1]; var scope = useMemo(function() { if (max < min || max === min) { console.log('max 的值需要大于 min的值'); } return max - min; }, [ max, min ]); var handleChange = function(value) { onChange && onChange(value); }; var _usePropsValue = _sliced_to_array(usePropsValue({ value: value, defaultValue: defaultValue, finalValue: 0, onChange: handleChange }), 2), current = _usePropsValue[0], setCurrent = _usePropsValue[1]; var _useState4 = _sliced_to_array(useState(function() { return value || defaultValue || 0; }), 2), exactValue = _useState4[0], setExactValue = _useState4[1]; var marksRef = useRef({}); useEffect(function() { if (marks) { if (Array.isArray(marks)) { var list = marks.sort(function(a, b) { return a.value - b.value; }).filter(function(point) { return point.value >= min && point.value <= max; }); setMarksList(list.map(function(mark) { return mark.value; })); list.forEach(function(mark) { marksRef.current[mark.value] = mark.label !== undefined ? mark.label : mark.value; }); } else { var marksKeys = Object.keys(marks); var list1 = marksKeys.map(parseFloat).sort(function(a, b) { return a - b; }).filter(function(point) { return point >= min && point <= max; }); setMarksList(list1); } } }, [ marks, max, min ]); var _obj; var classes = classNames(classPrefix, (_obj = {}, _define_property(_obj, "".concat(classPrefix, "-disabled"), disabled), _define_property(_obj, verticalClassPrefix, vertical), _obj)); var containerClasses = classNames("".concat(classPrefix, "-container"), _define_property({}, "".concat(verticalClassPrefix, "-container"), vertical), className); var markClassName = useCallback(function(mark) { var classPrefix = 'nut-range-mark'; var verticalClassPrefix = 'nut-range-vertical-mark'; var lowerBound = min; var upperBound = max; if (range && Array.isArray(current)) { lowerBound = current[0]; upperBound = current[1]; } else { upperBound = current; } var isActive = mark <= upperBound && mark >= lowerBound; var _$classNames = [ "".concat(classPrefix, "-text-wrapper"), "".concat(isActive ? "".concat(classPrefix, "-text-wrapper-active") : '') ]; if (vertical) { _$classNames.push("".concat(verticalClassPrefix, "-text-wrapper")); isActive && _$classNames.push("".concat(verticalClassPrefix, "-text-active-wrapper")); } if (rtl) { _$classNames.push("".concat(rtlClassPrefix, "-mark-text-wrapper")); } return _$classNames.join(' '); }, [ min, max, range, current, vertical, rtl, rtlClassPrefix ]); var isRange = useCallback(function(val) { return !!range && Array.isArray(val); }, [ range ]); var calcMainAxis = useCallback(function() { var modelVal = current; return isRange(modelVal) ? "".concat((modelVal[1] - modelVal[0]) * 100 / scope, "%") : "".concat((modelVal - min) * 100 / scope, "%"); }, [ current, isRange, min, scope ]); var calcOffset = useCallback(function() { var modelVal = current; return isRange(modelVal) ? "".concat((modelVal[0] - min) * 100 / scope, "%") : "0%"; }, [ current, isRange, min, scope ]); var barStyle = useCallback(function() { if (vertical) { return { height: calcMainAxis(), top: calcOffset(), transition: dragStatus ? 'none' : undefined }; } var dir = rtl ? 'right' : 'left'; var _obj; return _obj = { width: calcMainAxis() }, _define_property(_obj, dir, calcOffset()), _define_property(_obj, "transition", dragStatus ? 'none' : undefined), _obj; }, [ calcMainAxis, calcOffset, dragStatus, rtl, vertical ]); var marksStyle = useCallback(function(mark) { var dir = rtl ? 'right' : 'left'; var style = _define_property({}, dir, "".concat((mark - min) / scope * 100, "%")); if (vertical) { style = { top: "".concat((mark - min) / scope * 100, "%") }; } return style; }, [ min, rtl, scope, vertical ]); var tickClass = useCallback(function(mark) { if (range && Array.isArray(current)) { return mark <= current[1] && mark >= current[0]; } return mark <= current; }, [ current, range ]); var format = useCallback(function(value) { value = Math.max(+min, Math.min(value, +max)); return Math.round(value / +step) * +step; }, [ max, min, step ]); var updateValue = useCallback(function(value, end) { if (isRange(value)) { value = handleOverlap(value).map(format); } else { value = format(value); } if (!isSameValue(value, current)) { setCurrent(value); } end && onEnd && onEnd(value); }, [ current, format, isRange, onEnd, setCurrent ]); var click = useCallback(function(event) { if (disabled || !root.current) { return; } setDragStatus(''); var rect = getRect(root.current); var delta = event.clientX - rect.left; var total = rect.width; if (vertical) { delta = event.clientY - rect.top; total = rect.height; } var value = min + delta / total * scope; setExactValue(current); if (isRange(current)) { var _current = _sliced_to_array(current, 2), left = _current[0], right = _current[1]; var middle = (left + right) / 2; if (value <= middle) { updateValue([ value, right ], true); } else { updateValue([ left, value ], true); } } else { updateValue(value, true); } }, [ current, disabled, isRange, min, scope, updateValue, vertical ]); var onTouchStart = useCallback(function(event) { if (disabled) { return; } touch.start(event); setExactValue(current); if (isRange(current)) { setStartValue(current.map(format)); } else { setStartValue(format(current)); } setDragStatus('start'); }, [ current, disabled, format, isRange, touch ]); var onTouchMove = useCallback(function(event) { event.stopPropagation(); if (disabled || !root.current) { return; } if (dragStatus === 'start') { onStart && onStart(); } touch.move(event); setDragStatus('draging'); var rect = getRect(root.current); var delta = touch.deltaX.current; var total = rect.width; var diff = delta / total * scope; diff = rtl ? -diff : diff; if (vertical) { delta = touch.deltaY.current; total = rect.height; diff = delta / total * scope; } var newValue; if (isRange(startValue)) { newValue = exactValue.slice(); newValue[buttonIndex] = startValue[buttonIndex] + diff; } else { newValue = startValue + diff; } setExactValue(newValue); updateValue(newValue); }, [ buttonIndex, disabled, dragStatus, exactValue, isRange, onStart, rtl, scope, startValue, touch, updateValue, vertical ]); var onTouchEnd = useCallback(function() { if (disabled) { return; } if (dragStatus === 'draging') { updateValue(current, true); } setDragStatus(''); }, [ current, disabled, dragStatus, updateValue ]); var curValue = useCallback(function(idx) { var modelVal = current; var value = typeof idx === 'number' ? modelVal[idx] : modelVal; return value; }, [ current ]); var renderButton = useCallback(function(index) { var buttonNumberTransform = vertical ? 'translate(100%, -50%)' : 'translate(-50%, -100%)'; var _obj, _obj1; return /*#__PURE__*/ React.createElement(React.Fragment, null, button || /*#__PURE__*/ React.createElement("div", { className: classNames("".concat(classPrefix, "-button"), (_obj = {}, _define_property(_obj, "".concat(verticalClassPrefix, "-button"), vertical), _define_property(_obj, "".concat(rtlClassPrefix, "-button"), rtl), _obj)), style: { transform: 'translate(-50%, -50%)' } }, currentDescription !== null && /*#__PURE__*/ React.createElement("div", { className: classNames("".concat(classPrefix, "-button-number"), (_obj1 = {}, _define_property(_obj1, "".concat(verticalClassPrefix, "-button-number"), vertical), _define_property(_obj1, "".concat(rtlClassPrefix, "-button-number"), rtl), _obj1)), style: { transform: buttonNumberTransform } }, currentDescription ? currentDescription(curValue(index)) : curValue(index)))); }, [ button, curValue, currentDescription, rtl, rtlClassPrefix, vertical ]); var renderMarks = useCallback(function() { if (marksList.length <= 0) return null; var _obj; var markcls = classNames("".concat(classPrefix, "-mark"), (_obj = {}, _define_property(_obj, "".concat(verticalClassPrefix, "-mark"), vertical), _define_property(_obj, "".concat(rtlClassPrefix, "-mark"), rtl), _obj)); var textcls = classNames("".concat(classPrefix, "-mark-text"), _define_property({}, "".concat(verticalClassPrefix, "-mark-text"), vertical)); return /*#__PURE__*/ React.createElement("div", { className: markcls }, marksList.map(function(mark) { var _obj; return /*#__PURE__*/ React.createElement("span", { key: mark, className: markClassName(mark), style: marksStyle(mark) }, /*#__PURE__*/ React.createElement("span", { className: textcls }, Array.isArray(marks) ? marksRef.current[mark] : marks[mark]), /*#__PURE__*/ React.createElement("span", { className: classNames("".concat(vertical ? verticalClassPrefix : classPrefix, "-tick"), (_obj = {}, _define_property(_obj, "".concat(vertical ? verticalClassPrefix : classPrefix, "-tick-active"), tickClass(mark)), _define_property(_obj, "".concat(rtlClassPrefix, "-tick"), rtl), _obj)) })); })); }, [ markClassName, marks, marksList, marksStyle, rtl, rtlClassPrefix, tickClass, vertical ]); var getWrapperTransform = useCallback(function() { var wrapperTransform = 'translate(-50%, -50%)'; return wrapperTransform; }, []); var renderRangeButton = useCallback(function() { return [ 0, 1 ].map(function(item, index) { var isLeft = index === 0; var suffix = isLeft ? 'left' : 'right'; var transform = 'translate(-50%, -50%)'; var _obj; var cls = classNames("".concat(classPrefix, "-button-wrapper-").concat(suffix), (_obj = {}, _define_property(_obj, "".concat(verticalClassPrefix, "-button-wrapper-").concat(suffix), vertical), _define_property(_obj, "".concat(rtlClassPrefix, "-button-wrapper-").concat(suffix), rtl), _obj)); return /*#__PURE__*/ React.createElement("div", { key: index, className: cls, style: { transform: transform }, onTouchStart: function(e) { setButtonIndex(index); onTouchStart(e); }, onTouchMove: onTouchMove, onTouchEnd: onTouchEnd, onTouchCancel: onTouchEnd, onClick: function(e) { return e.stopPropagation(); } }, renderButton(index)); }); }, [ onTouchEnd, onTouchMove, onTouchStart, renderButton, vertical, rtl, rtlClassPrefix ]); var renderSingleButton = useCallback(function() { return /*#__PURE__*/ React.createElement("div", { className: classNames("".concat(classPrefix, "-button-wrapper"), _define_property({}, "".concat(verticalClassPrefix, "-button-wrapper"), vertical)), style: { // @ts-ignore transform: getWrapperTransform() }, onTouchStart: onTouchStart, onTouchMove: onTouchMove, onTouchEnd: onTouchEnd, onTouchCancel: onTouchEnd, onClick: function(e) { return e.stopPropagation(); } }, renderButton()); }, [ getWrapperTransform, onTouchEnd, onTouchMove, onTouchStart, renderButton, vertical ]); var renderButtonWrapper = useCallback(function() { if (range) { return renderRangeButton(); } return renderSingleButton(); }, [ renderRangeButton, renderSingleButton, range ]); return /*#__PURE__*/ React.createElement("div", { className: containerClasses, style: style }, minDescription !== null && /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-min") }, minDescription || min), /*#__PURE__*/ React.createElement("div", { ref: root, className: classes, onClick: function(e) { return click(e); } }, renderMarks(), /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-bar"), style: barStyle() }, renderButtonWrapper())), maxDescription !== null && /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-max") }, maxDescription || max)); }; Range.displayName = 'NutRange';