UNPKG

zarm

Version:

基于 React 的移动端UI库

190 lines (158 loc) 7.02 kB
import _slicedToArray from "@babel/runtime/helpers/slicedToArray"; import BScroll from '@better-scroll/core'; import WheelPlugin from '@better-scroll/wheel'; import { createBEM } from '@zarm-design/bem'; import isEqual from 'lodash/isEqual'; import React, { createRef, useEffect, useRef } from 'react'; import { ConfigContext } from '../config-provider'; import { resolvedFieldNames } from '../picker-view/utils'; import { useEventCallback, usePrevious, useSafeLayoutEffect } from '../utils/hooks'; BScroll.use(WheelPlugin); var getValue = function getValue(props) { var _props$fieldNames; if ('defaultValue' in props) { return props.defaultValue; } if ('value' in props) { return props.value; } if (Array.isArray(props.dataSource) && props.dataSource[0] && (_props$fieldNames = props.fieldNames) !== null && _props$fieldNames !== void 0 && _props$fieldNames.value) { var _props$fieldNames2; return props.dataSource[0][(_props$fieldNames2 = props.fieldNames) === null || _props$fieldNames2 === void 0 ? void 0 : _props$fieldNames2.value]; } }; var Wheel = function Wheel(props) { var className = props.className, value = props.value, defaultValue = props.defaultValue, dataSource = props.dataSource, disabled = props.disabled, stopScroll = props.stopScroll, itemRender = props.itemRender, onChange = props.onChange; var scrollInstance = useRef(null); var wheelWrapperRef = /*#__PURE__*/createRef(); var currentValue = getValue(props); var prevValue = usePrevious(value); var prevDataSource = usePrevious(dataSource); var prevStopScroll = usePrevious(stopScroll); var _React$useContext = React.useContext(ConfigContext), prefixCls = _React$useContext.prefixCls; var heightRef = React.useRef(0); var bem = createBEM('wheel', { prefixCls: prefixCls }); var fieldNames = resolvedFieldNames(props.fieldNames); var getSelectedIndex = function getSelectedIndex(changedValue, newDataSource) { var index = 0; if (newDataSource) { newDataSource.some(function (item, i) { if (item[fieldNames.value] === changedValue) { index = i; return true; } return false; }); } return index; }; var fireValueChange = function fireValueChange(changedValue) { if (changedValue === currentValue) { return; } onChange === null || onChange === void 0 ? void 0 : onChange(changedValue); }; var handleScrollEnd = useEventCallback(function () { var _scrollInstance$curre; var index = (_scrollInstance$curre = scrollInstance.current) === null || _scrollInstance$curre === void 0 ? void 0 : _scrollInstance$curre.getSelectedIndex(); var child = dataSource === null || dataSource === void 0 ? void 0 : dataSource[index]; if (child) { fireValueChange(child[fieldNames.value]); } }, []); useSafeLayoutEffect(function () { var _wheelWrapperRef$curr, _scrollInstance$curre4; var resize; heightRef.current = ((_wheelWrapperRef$curr = wheelWrapperRef.current) === null || _wheelWrapperRef$curr === void 0 ? void 0 : _wheelWrapperRef$curr.clientHeight) || 0; var initIndex = getSelectedIndex(currentValue, dataSource); if (wheelWrapperRef.current) { var _scrollInstance$curre2; scrollInstance.current = new BScroll(wheelWrapperRef.current, { wheel: { selectedIndex: initIndex, wheelWrapperClass: bem('content'), wheelItemClass: bem('item') }, probeType: 3 }); if ((_scrollInstance$curre2 = scrollInstance.current.scroller) !== null && _scrollInstance$curre2 !== void 0 && _scrollInstance$curre2.wrapper) { resize = new ResizeObserver(function (entries) { var _scrollInstance$curre3; var _ref = entries || [], _ref2 = _slicedToArray(_ref, 1), entry = _ref2[0]; if (entry.contentRect.height === heightRef.current) return; heightRef.current = entry.contentRect.height; (_scrollInstance$curre3 = scrollInstance.current) === null || _scrollInstance$curre3 === void 0 ? void 0 : _scrollInstance$curre3.refresh(); }); resize.observe(scrollInstance.current.scroller.wrapper); } } (_scrollInstance$curre4 = scrollInstance.current) === null || _scrollInstance$curre4 === void 0 ? void 0 : _scrollInstance$curre4.on('scrollEnd', function () { handleScrollEnd(); }); return function () { var _resize, _scrollInstance$curre5; (_resize = resize) === null || _resize === void 0 ? void 0 : _resize.disconnect(); (_scrollInstance$curre5 = scrollInstance.current) === null || _scrollInstance$curre5 === void 0 ? void 0 : _scrollInstance$curre5.destroy(); }; }, []); useEffect(function () { var _scrollInstance$curre6; disabled && ((_scrollInstance$curre6 = scrollInstance.current) === null || _scrollInstance$curre6 === void 0 ? void 0 : _scrollInstance$curre6.disable()); }, [disabled]); useEffect(function () { var _scrollInstance$curre7; if (isEqual(prevDataSource, dataSource)) return; (_scrollInstance$curre7 = scrollInstance.current) === null || _scrollInstance$curre7 === void 0 ? void 0 : _scrollInstance$curre7.refresh(); var targetIndex = dataSource === null || dataSource === void 0 ? void 0 : dataSource.findIndex(function (item) { return item[fieldNames.value] === value; }); if (targetIndex >= 0) return; handleScrollEnd(); }, [dataSource, fieldNames, value]); useEffect(function () { var oldIndex = getSelectedIndex(prevValue, prevDataSource); var newIndex = getSelectedIndex(value, dataSource); if (newIndex !== oldIndex) { var _scrollInstance$curre8; (_scrollInstance$curre8 = scrollInstance.current) === null || _scrollInstance$curre8 === void 0 ? void 0 : _scrollInstance$curre8.wheelTo(newIndex); } if (stopScroll && prevStopScroll !== stopScroll) { var _scrollInstance$curre9; (_scrollInstance$curre9 = scrollInstance.current) === null || _scrollInstance$curre9 === void 0 ? void 0 : _scrollInstance$curre9.stop(); } }, [value, defaultValue, dataSource, stopScroll, fieldNames.value]); var items = dataSource.map(function (item, index) { var itemCls = bem('item', [{ selected: currentValue === item[fieldNames.value], disabled: disabled }]); return /*#__PURE__*/React.createElement("div", { key: +index, className: itemCls }, (itemRender === null || itemRender === void 0 ? void 0 : itemRender(item)) || (item === null || item === void 0 ? void 0 : item[fieldNames.label])); }); return /*#__PURE__*/React.createElement("div", { className: bem([className]), ref: wheelWrapperRef }, /*#__PURE__*/React.createElement("div", { className: bem('content') }, items)); }; Wheel.displayName = 'Wheel'; Wheel.defaultProps = { dataSource: [], stopScroll: false }; export default Wheel;