gui-one-nutui-react-taro
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
543 lines (542 loc) • 20.3 kB
JavaScript
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 };