UNPKG

@nutui/nutui-react-taro

Version:

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

275 lines (274 loc) 12 kB
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; 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 _object_without_properties } from "@swc/helpers/_/_object_without_properties"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator"; import React, { useEffect, useRef, useState, createContext, useMemo } from "react"; import Taro, { nextTick, createSelectorQuery } from "@tarojs/taro"; import { ScrollView, View, Text } from "@tarojs/components"; import classNames from "classnames"; import { ComponentDefaults } from "../../utils/typings"; import { harmony } from "../../utils/taro/platform"; import { useUuid } from "../../hooks/use-uuid"; import raf from "../../utils/raf"; import { usePropsValue } from "../../hooks"; export var elevatorContext = /*#__PURE__*/ createContext({}); var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { mode: 'horizontal', height: '200px', floorKey: 'title', list: [], sticky: false, spaceHeight: 18, showKeys: true, defaultValue: undefined, value: undefined }); export var Elevator = function(props) { var _ref = _object_spread({}, defaultProps, props), value = _ref.value, defaultValue = _ref.defaultValue, mode = _ref.mode, height = _ref.height, floorKey = _ref.floorKey, list = _ref.list, sticky = _ref.sticky, spaceHeight = _ref.spaceHeight, showKeys = _ref.showKeys, className = _ref.className, style = _ref.style, onItemClick = _ref.onItemClick, onIndexClick = _ref.onIndexClick, children = _ref.children, rest = _object_without_properties(_ref, [ "value", "defaultValue", "mode", "height", "floorKey", "list", "sticky", "spaceHeight", "showKeys", "className", "style", "onItemClick", "onIndexClick", "children" ]); var uuid = useUuid(); var classPrefix = 'nut-elevator'; var initData = { anchorIndex: 0, listHeight: [], scrollY: 0 }; var touchState = useRef({ y1: 0, y2: 0 }); var _usePropsValue = _sliced_to_array(usePropsValue({ value: value, defaultValue: defaultValue || {} }), 2), currentData = _usePropsValue[0], setCurrentData = _usePropsValue[1]; var _useState = _sliced_to_array(useState(0), 2), codeIndex = _useState[0], setCodeIndex = _useState[1]; var _useState1 = _sliced_to_array(useState(false), 2), scrollStart = _useState1[0], setScrollStart = _useState1[1]; var state = useRef(initData); var scrolling = useRef(false); var _useState2 = _sliced_to_array(useState(0), 2), scrollTop = _useState2[0], setScrollTop = _useState2[1]; var _useState3 = _sliced_to_array(useState(0), 2), scrollY = _useState3[0], setScrollY = _useState3[1]; var resetScrollState = function() { setScrollStart(false); }; var getData = function(el) { if (!el.dataset.index) { return '0'; } return el.dataset.index; }; var calculateHeight = function() { state.current.listHeight = [ 0 ]; var query = createSelectorQuery(); query.selectAll("#".concat(classPrefix, "-").concat(uuid, " .").concat(classPrefix, "-list-item")).boundingClientRect().exec(function() { var rect = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : []; if (rect[0] && rect[0].length) { // rect[0] = rect[0].reverse() state.current.listHeight = rect[0].reduce(function(acc, item, index) { // 当前项的高度等于前面所有项的高度之和 var height = acc[index] + item.height; acc.push(height); return acc; }, [ 0 ]); } }); }; var scrollTo = function(index) { return _async_to_generator(function() { var cacheIndex, scrollTop; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: if (!index && index !== 0) { return [ 2 ]; } if (!!state.current.listHeight.length) return [ 3, 2 ]; return [ 4, calculateHeight() ]; case 1: _state.sent(); _state.label = 2; case 2: cacheIndex = index; if (index < 0) { cacheIndex = 0; } if (index > state.current.listHeight.length - 2) { cacheIndex = Math.max(0, state.current.listHeight.length - 2); } setCodeIndex(cacheIndex); scrollTop = state.current.listHeight[cacheIndex]; setScrollTop(scrollTop); if (mode === 'vertical' && sticky) { setScrollY(Math.floor(scrollTop) > 0 ? 1 : 0); } return [ 2 ]; } }); })(); }; var touchMove = function(e) { var firstTouch = e.touches[0]; touchState.current.y2 = firstTouch.pageY; var delta = (touchState.current.y2 - touchState.current.y1) / spaceHeight || 0; var cacheIndex = state.current.anchorIndex + Math.round(delta); setCodeIndex(cacheIndex); scrollTo(cacheIndex); }; var touchEnd = function() { resetScrollState(); }; var touchStart = function(e) { var index = Number(getData(e.target)); var firstTouch = e.touches[0]; scrolling.current = true; touchState.current.y1 = firstTouch.pageY; state.current.anchorIndex = +index; setScrollStart(true); setCodeIndex(index); scrollTo(index); }; var handleClickItem = function(key, item) { onItemClick && onItemClick(key, item); setCurrentData(item); }; var handleClickIndex = function(key) { onIndexClick && onIndexClick(key); }; var listViewScroll = function(e) { raf(function() { var listHeight = state.current.listHeight; if (!listHeight.length) { calculateHeight(); } var target = e.target; var scrollTop = target.scrollTop; state.current.scrollY = Math.floor(scrollTop); Taro.getEnv() === 'WEB' && setScrollTop(scrollTop); if (mode === 'vertical' && sticky) { setScrollY(Math.floor(scrollTop) > 0 ? 1 : 0); } if (scrolling.current) return; var index = listHeight.findIndex(function(height, i) { return state.current.scrollY >= height && state.current.scrollY < (listHeight[i + 1] || Infinity); }); if (index !== -1 && index !== codeIndex) { setCodeIndex(index); } }); }; var getWrapStyle = useMemo(function() { var calcHeight = Number.isNaN(+height) ? height : "".concat(height, "px"); return { height: harmony() ? Number(height) : calcHeight }; }, [ height ]); useEffect(function() { nextTick(function() { calculateHeight(); }); }, []); var _obj; return /*#__PURE__*/ React.createElement("div", _object_spread({ className: "".concat(classPrefix, " ").concat(className, " ").concat(classPrefix, "-").concat(mode, " "), id: "".concat(classPrefix, "-").concat(uuid), style: style }, rest), /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-list"), style: getWrapStyle }, /*#__PURE__*/ React.createElement(ScrollView, { scrollTop: scrollTop, scrollY: true, enhanced: true, scrollWithAnimation: false, scrollAnchoring: true, className: "".concat(classPrefix, "-list-inner"), onScroll: listViewScroll, onTouchStart: function(e) { scrolling.current = false; } }, list.map(function(item, idx) { return /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-list-item nut-elevator-item-").concat(idx), key: idx }, /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-list-item-code") }, item[floorKey]), /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-list-item-sublist") }, item.list.map(function(subitem) { var _obj; return /*#__PURE__*/ React.createElement(View, { className: classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-list-item-name"), true), _define_property(_obj, "".concat(classPrefix, "-list-item-name-highcolor"), currentData.id === subitem.id), _obj)), key: subitem.id, onClick: function() { return handleClickItem(item[floorKey], subitem); } }, children ? /*#__PURE__*/ React.createElement(React.Fragment, null, /*#__PURE__*/ React.createElement(elevatorContext.Provider, { value: subitem }, children)) : subitem.name); }))); }))), showKeys ? /*#__PURE__*/ React.createElement(React.Fragment, null, list.length && scrollStart ? /*#__PURE__*/ React.createElement(View, { className: classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-code-current"), true), _define_property(_obj, "".concat(classPrefix, "-code-current-current"), true), _obj)) }, list[codeIndex] && String(list[codeIndex][floorKey])) : null, /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-bars") }, /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-bars-inner") }, list.map(function(item, index) { var _obj; return /*#__PURE__*/ React.createElement(View, { className: classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-bars-inner-item"), true), _define_property(_obj, "".concat(classPrefix, "-bars-inner-item-active"), item[floorKey] === list[codeIndex][floorKey]), _obj)), "data-index": index, key: index, onClick: function() { return handleClickIndex(item[floorKey]); }, onTouchStart: function(event) { return touchStart(event); }, onTouchMove: function(event) { return touchMove(event); }, onTouchEnd: touchEnd, style: { touchAction: 'pan-y' } }, String(item[floorKey])); })))) : null, mode === 'vertical' && sticky && scrollY > 0 ? /*#__PURE__*/ React.createElement(View, { className: "".concat(classPrefix, "-list-fixed") }, /*#__PURE__*/ React.createElement(Text, { className: "".concat(classPrefix, "-list-fixed-title") }, list[codeIndex] && String(list[codeIndex][floorKey]))) : null); }; Elevator.displayName = 'NutElevator'; Elevator.Context = elevatorContext;