zarm
Version:
基于 React 的移动端UI库
190 lines (158 loc) • 7.02 kB
JavaScript
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;