UNPKG

gui-one-nutui-react-taro

Version:

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

543 lines (542 loc) 20.3 kB
import _defineProperty from "@babel/runtime/helpers/defineProperty"; import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties"; import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator"; import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; var _excluded = ["isVisible", "title", "listData", "defaultValueData", "onConfirm", "onClose", "onCloseUpdate", "onChange", "className", "style", "threeDimensional", "swipeDuration"]; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } import _regeneratorRuntime from "@babel/runtime/regenerator"; import React__default, { useState, useRef, useEffect, useImperativeHandle } from 'react'; import { P as Popup } from './popup.taro-33d0bbc8.js'; import { u as useTouch } from './useTouch-a2ea68c6.js'; import { g as getRectByTaro } from './useClientRect-bf69d7b3.js'; import { u as useConfig } from './configprovider.taro-6c7b3056.js'; import { c as cn } from './bem-893ad28d.js'; var InternalPickerSlot = function InternalPickerSlot(props, ref) { var _props$keyIndex = props.keyIndex, keyIndex = _props$keyIndex === void 0 ? 0 : _props$keyIndex, defaultValue = props.defaultValue, _props$listData = props.listData, listData = _props$listData === void 0 ? [] : _props$listData, _props$threeDimension = props.threeDimensional, threeDimensional = _props$threeDimension === void 0 ? true : _props$threeDimension, _props$swipeDuration = props.swipeDuration, swipeDuration = _props$swipeDuration === void 0 ? 1000 : _props$swipeDuration, _props$itemShow = props.itemShow, itemShow = _props$itemShow === void 0 ? false : _props$itemShow, chooseItem = props.chooseItem; var touch = useTouch(); var DEFAULT_DURATION = 200; // 触发惯性滑动条件: // 在手指离开屏幕时,如果和上一次 move 时的间隔小于 `MOMENTUM_TIME` 且 move // 距离大于 `MOMENTUM_DISTANCE` 时,执行惯性滑动 var INERTIA_TIME = 300; var INERTIA_DISTANCE = 15; var _useState = useState(1), _useState2 = _slicedToArray(_useState, 2), currIndex = _useState2[0], setCurrIndex = _useState2[1]; // let lineSpacing = 36 var lineSpacing = useRef(36); var _useState3 = useState(0), _useState4 = _slicedToArray(_useState3, 2), touchTime = _useState4[0], setTouchTime = _useState4[1]; var _useState5 = useState('0deg'), _useState6 = _slicedToArray(_useState5, 2), touchDeg = _useState6[0], setTouchDeg = _useState6[1]; var rotation = 20; var moving = useRef(false); var timer; var listbox = useRef(null); var rollerRef = useRef(null); var pickerSlotRef = useRef(null); var _useState7 = useState(0), _useState8 = _slicedToArray(_useState7, 2), startTime = _useState8[0], setStartTime = _useState8[1]; var _useState9 = useState(0), _useState10 = _slicedToArray(_useState9, 2), startY = _useState10[0], setStartY = _useState10[1]; var transformY = useRef(0); var _useState11 = useState(0), _useState12 = _slicedToArray(_useState11, 2), scrollDistance = _useState12[0], setScrollDistance = _useState12[1]; var isHidden = function isHidden(index) { if (index >= currIndex + 8 || index <= currIndex - 8) { return true; } return false; }; var setTransform = function setTransform() { var translateY = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var type = arguments.length > 1 ? arguments[1] : undefined; var time = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_DURATION; var deg = arguments.length > 3 ? arguments[3] : undefined; var nTime = time; if (type !== 'end') { nTime = 0; } setTouchTime(nTime); setTouchDeg(deg); setScrollDistance(translateY); }; var setMove = function setMove(move, type, time) { console.log('move'); var updateMove = move + transformY.current; if (type === 'end') { // 限定滚动距离 if (updateMove > 0) { updateMove = 0; } if (updateMove < -(listData.length - 1) * lineSpacing.current) { updateMove = -(listData.length - 1) * lineSpacing.current; } // 设置滚动距离为lineSpacing的倍数值 var endMove = Math.round(updateMove / lineSpacing.current) * lineSpacing.current; var deg = "".concat((Math.abs(Math.round(endMove / lineSpacing.current)) + 1) * rotation, "deg"); setTransform(endMove, type, time, deg); setCurrIndex(Math.abs(Math.round(endMove / lineSpacing.current)) + 1); } else { var _deg = 0; var currentDeg = (-updateMove / lineSpacing.current + 1) * rotation; // picker 滚动的最大角度 var maxDeg = (listData.length + 1) * rotation; var minDeg = 0; _deg = Math.min(Math.max(currentDeg, minDeg), maxDeg); if (minDeg < _deg && _deg < maxDeg) { setTransform(updateMove, '', undefined, "".concat(_deg, "deg")); setCurrIndex(Math.abs(Math.round(updateMove / lineSpacing.current)) + 1); } } }; var setChooseValue = function setChooseValue(move) { chooseItem && chooseItem(listData === null || listData === void 0 ? void 0 : listData[Math.round(-move / lineSpacing.current)], keyIndex); }; // 开始滚动 var touchStart = function touchStart(event) { touch.start(event); setStartY(touch.deltaY); setStartTime(Date.now()); transformY.current = scrollDistance; }; var touchMove = function touchMove(event) { touch.move(event); if (touch.isVertical) { moving.current = true; preventDefault(event, true); } var move = touch.deltaY - startY; setMove(move); }; var touchEnd = function touchEnd(event) { if (!moving.current) return; var move = touch.deltaY - startY; var moveTime = Date.now() - startTime; // 区分是否为惯性滚动 if (moveTime <= INERTIA_TIME && Math.abs(move) > INERTIA_DISTANCE) { // 惯性滚动 var distance = momentum(move, moveTime); setMove(distance, 'end', +swipeDuration); } else { setMove(move, 'end'); } setTimeout(function () { touch.reset(); }, 0); }; // 惯性滚动 距离 var momentum = function momentum(distance, duration) { var nDistance = distance; // 惯性滚动的速度 var speed = Math.abs(nDistance / duration); // 惯性滚动的距离 nDistance = speed / 0.003 * (nDistance < 0 ? -1 : 1); return nDistance; }; var modifyStatus = function modifyStatus(type, val) { var value = val || defaultValue; var index = -1; if (value) { listData.some(function (item, idx) { if (item.value === value) { index = idx; return true; } return false; }); } else { listData.forEach(function (item, i) { if (item.value === defaultValue) { index = i; } }); } setCurrIndex(index === -1 ? 1 : index + 1); var move = index === -1 ? 0 : index * lineSpacing.current; type && setChooseValue(-move); setMove(-move); }; // 惯性滚动结束 var stopMomentum = function stopMomentum() { moving.current = false; setTouchTime(0); setChooseValue(scrollDistance); }; // 阻止默认事件 var preventDefault = function preventDefault(event, isStopPropagation) { /* istanbul ignore else */ if (typeof event.cancelable !== 'boolean' || event.cancelable) { event.preventDefault(); } if (isStopPropagation) { event.stopPropagation(); } }; var getReference = /*#__PURE__*/function () { var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() { var refe; return _regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: _context.next = 2; return getRectByTaro(listbox === null || listbox === void 0 ? void 0 : listbox.current); case 2: refe = _context.sent; console.log(refe); lineSpacing.current = refe.height ? refe.height : 36; modifyStatus(true); case 6: case "end": return _context.stop(); } } }, _callee); })); return function getReference() { return _ref2.apply(this, arguments); }; }(); var touchRollerStyle = function touchRollerStyle() { return { transition: "transform ".concat(touchTime, "ms cubic-bezier(0.17, 0.89, 0.45, 1)"), transform: "rotate3d(1, 0, 0, ".concat(touchDeg, ")") }; }; var touchTileStyle = function touchTileStyle() { return { transition: "transform ".concat(touchTime, "ms cubic-bezier(0.17, 0.89, 0.45, 1)"), transform: "translate3d(0, ".concat(scrollDistance, "px, 0)") }; }; useEffect(function () { setScrollDistance(0); transformY.current = 0; modifyStatus(false); return function () { clearTimeout(timer); }; }, [listData]); useEffect(function () { if (itemShow) { setTimeout(function () { getReference(); }, 200); } }, [itemShow]); useImperativeHandle(ref, function () { return { stopMomentum: stopMomentum, moving: moving.current }; }); return React__default.createElement("div", { className: "nut-picker-list", ref: pickerSlotRef, onTouchStart: touchStart, onTouchMove: touchMove, onTouchEnd: touchEnd }, React__default.createElement("div", { className: "nut-picker-roller", ref: rollerRef, style: threeDimensional ? touchRollerStyle() : touchTileStyle(), onTransitionEnd: stopMomentum }, threeDimensional && listData.map(function (item, index) { return React__default.createElement("div", { className: "nut-picker-roller-item ".concat(isHidden(index + 1) && 'nut-picker-roller-item-hidden'), style: { transform: "rotate3d(1, 0, 0, ".concat(-rotation * (index + 1), "deg) translate3d(0px, 0px, 104px)"), height: "".concat(lineSpacing.current, "px"), lineHeight: "".concat(lineSpacing.current, "px") }, key: item.value ? item.value : index }, React__default.createElement(React__default.Fragment, null, item.text ? item.text : item)); }), !threeDimensional && listData.map(function (item, index) { return React__default.createElement("div", { className: "nut-picker-roller-item-tile", key: item.value ? item.value : index, style: { height: "".concat(lineSpacing.current, "px"), lineHeight: "".concat(lineSpacing.current, "px") } }, React__default.createElement(React__default.Fragment, null, item.text ? item.text : item)); })), React__default.createElement("div", { className: "nut-picker-mask" }), React__default.createElement("div", { className: "nut-picker-indicator", ref: listbox })); }; var PickerSlot = React__default.forwardRef(InternalPickerSlot); function useRefs() { var refs = React__default.useRef([]); var setRefs = React__default.useCallback(function (index) { return function (el) { if (el) refs.current[index] = el; }; }, []); var reset = React__default.useCallback(function () { refs.current = []; }, []); return [refs.current, setRefs, reset]; } var InternalPicker = function InternalPicker(props, ref) { var _useConfig = useConfig(), locale = _useConfig.locale; var isVisible = props.isVisible, title = props.title, _props$listData2 = props.listData, listData = _props$listData2 === void 0 ? [] : _props$listData2, defaultValueData = props.defaultValueData, onConfirm = props.onConfirm, onClose = props.onClose, onCloseUpdate = props.onCloseUpdate, onChange = props.onChange, className = props.className, style = props.style, threeDimensional = props.threeDimensional, swipeDuration = props.swipeDuration, rest = _objectWithoutProperties(props, _excluded); var _useState13 = useState([]), _useState14 = _slicedToArray(_useState13, 2), chooseValueData = _useState14[0], setchooseValueData = _useState14[1]; // 选择的数据的 value 值, 每一条数据的 value 值 var _useState15 = useState(0), _useState16 = _slicedToArray(_useState15, 2), columnIndex = _useState16[0], setcolumnIndex = _useState16[1]; // 选中列 var pickerRef = useRef(null); var _useRefs = useRefs(), _useRefs2 = _slicedToArray(_useRefs, 2), refs = _useRefs2[0], setRefs = _useRefs2[1]; var _useState17 = useState([]), _useState18 = _slicedToArray(_useState17, 2), columnsList = _useState18[0], setColumnsList = _useState18[1]; // 格式化后每一列的数据 var b = cn('picker'); var isConfirmEvent = useRef(false); // 默认值修改 useEffect(function () { if (defaultValueData && defaultValueData.length !== 0 && defaultValueData.toString() !== chooseValueData.toString()) { var data = _toConsumableArray(defaultValueData); setchooseValueData(data); setColumnsList(normalListData()); } }, [defaultValueData]); // 选中值进行修改 useEffect(function () { onChange && onChange(columnIndex, chooseValueData, selectedOptions()); if (isConfirmEvent.current) { isConfirmEvent.current = false; onConfirm && onConfirm(chooseValueData, selectedOptions()); } }, [chooseValueData]); // 列表格式修改 useEffect(function () { init(); }, [listData]); var closeActionSheet = function closeActionSheet() { onClose && onClose(chooseValueData, selectedOptions()); onCloseUpdate && onCloseUpdate(chooseValueData, selectedOptions(), pickerRef); }; // 点击确定 var confirm = function confirm() { var movings = false; refs.forEach(function (_ref) { if (_ref.moving) movings = true; _ref.stopMomentum(); }); if (movings) { isConfirmEvent.current = true; } else { onConfirm && onConfirm(chooseValueData, selectedOptions()); } onClose && onClose(chooseValueData, selectedOptions()); setTimeout(function () { isConfirmEvent.current = false; }, 0); }; var selectedOptions = function selectedOptions() { var optins = []; columnsList.map(function (column, index) { var currOptions = []; currOptions = column.filter(function (item) { return item.value === chooseValueData[index]; }); if (currOptions[0]) { optins.push(currOptions[0]); } else { column[0] && optins.push(column[0]); } return column; }); return optins; }; // 选择每一列的数据 var _chooseItem = function chooseItem(option, columnIndex) { if (option && Object.keys(option).length) { // 是否移动后是否与之前有差异 if (chooseValueData[columnIndex] !== option.value) { if (columnsType() === 'cascade') { chooseValueData[columnIndex] = option.value ? option.value : ''; setchooseValueData(_toConsumableArray(chooseValueData)); var index = columnIndex; var cursor = option; while (cursor && cursor.children && cursor.children[0]) { chooseValueData[index + 1] = cursor.children[0].value; setchooseValueData(_toConsumableArray(chooseValueData)); index++; var cc = cursor.children[0]; cursor = cc; } // 当前改变列的下一列 children 值为空 if (cursor && cursor.children) { chooseValueData[index + 1] = ''; setchooseValueData(_toConsumableArray(chooseValueData)); } setColumnsList(normalListData()); } else { setchooseValueData(function (data) { var cdata = _toConsumableArray(data); cdata[columnIndex] = Object.prototype.hasOwnProperty.call(option, 'value') ? option.value : ''; return cdata; }); } setcolumnIndex(columnIndex); } } }; // 传入的数据格式化 var normalListData = function normalListData() { var type = columnsType(); switch (type) { case 'multiple': return listData; case 'cascade': // 级联数据处理 return formatCascade(listData, chooseValueData); default: return [listData]; } }; // 每一列的类型 var columnsType = function columnsType() { var firstColumn = listData[0]; if (firstColumn) { if (Array.isArray(firstColumn)) { return 'multiple'; } if ('children' in firstColumn) { return 'cascade'; } } return 'single'; }; // 级联数据格式化 var formatCascade = function formatCascade(columns, defaultValues) { var formatted = []; var cursor = { text: '', value: '', children: columns }; var columnIndex = 0; var _loop = function _loop() { var options = cursor.children; var value = defaultValues[columnIndex]; var index = options.findIndex(function (columnItem) { return columnItem.value === value; }); if (index === -1) index = 0; cursor = cursor.children[index]; columnIndex++; formatted.push(options); }; while (cursor && cursor.children) { _loop(); } return formatted; }; var init = function init() { var data = []; var normalData = normalListData(); setColumnsList(normalData); normalData.length > 0 && normalData.map(function (item) { item[0] && data.push(item[0].value); return item; }); if (!defaultValueData && chooseValueData.length === 0) { setchooseValueData([].concat(data)); } }; var renderToolbar = function renderToolbar() { return React__default.createElement("div", { className: b('control') }, React__default.createElement("span", { className: b('cancel-btn'), onClick: function onClick() { return closeActionSheet(); } }, locale.cancel), React__default.createElement("div", { className: b('title') }, title || ''), React__default.createElement("span", { className: b('confirm-btn'), onClick: confirm }, locale.confirm)); }; return React__default.createElement(Popup, { visible: isVisible, position: "bottom", onClose: function onClose() { closeActionSheet(); } }, React__default.createElement("div", _objectSpread({ className: "".concat(b(), " ").concat(className || ''), style: style }, rest), renderToolbar(), React__default.createElement("div", { className: b('panel'), ref: pickerRef }, columnsList === null || columnsList === void 0 ? void 0 : columnsList.map(function (item, index) { return React__default.createElement(PickerSlot, { ref: setRefs(index), defaultValue: chooseValueData === null || chooseValueData === void 0 ? void 0 : chooseValueData[index], listData: item, threeDimensional: threeDimensional, chooseItem: function chooseItem(value, index) { return _chooseItem(value, index); }, swipeDuration: swipeDuration, key: index, keyIndex: index, itemShow: isVisible }); })))); }; var Picker = React__default.forwardRef(InternalPicker); export { Picker as P };