UNPKG

@nutui/nutui-react

Version:

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

220 lines (219 loc) 9.73 kB
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 React, { useRef, useEffect, useState, createContext } from "react"; import { useGesture } from "@use-gesture/react"; import { animated } from "@react-spring/web"; import classNames from "classnames"; import { ComponentDefaults } from "../../utils/typings"; export var elevatorContext = /*#__PURE__*/ createContext({}); var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { height: '200px', floorKey: 'title', list: [], sticky: false, spaceHeight: 23, titleHeight: 35, showKeys: true }); export var Elevator = function(props) { var _ref = _object_spread({}, defaultProps, props), height = _ref.height, floorKey = _ref.floorKey, list = _ref.list, sticky = _ref.sticky, spaceHeight = _ref.spaceHeight, titleHeight = _ref.titleHeight, showKeys = _ref.showKeys, className = _ref.className, style = _ref.style, onItemClick = _ref.onItemClick, onIndexClick = _ref.onIndexClick, children = _ref.children, rest = _object_without_properties(_ref, [ "height", "floorKey", "list", "sticky", "spaceHeight", "titleHeight", "showKeys", "className", "style", "onItemClick", "onIndexClick", "children" ]); var classPrefix = 'nut-elevator'; var listview = useRef(null); var initData = { anchorIndex: 0, listHeight: [], listGroup: [], scrollY: 0 }; var touchState = useRef({ y1: 0, y2: 0 }); var _useState = _sliced_to_array(useState(0), 2), scrollY = _useState[0], setScrollY = _useState[1]; var _useState1 = _sliced_to_array(useState({}), 2), currentData = _useState1[0], setCurrentData = _useState1[1]; var _useState2 = _sliced_to_array(useState(''), 2), currentKey = _useState2[0], setCurrentKey = _useState2[1]; var _useState3 = _sliced_to_array(useState(0), 2), currentIndex = _useState3[0], setCurrentIndex = _useState3[1]; var _useState4 = _sliced_to_array(useState(0), 2), codeIndex = _useState4[0], setCodeIndex = _useState4[1]; var _useState5 = _sliced_to_array(useState(false), 2), scrollStart = _useState5[0], setScrollStart = _useState5[1]; var state = useRef(initData); var resetScrollState = function() { setScrollStart(false); }; var clientHeight = function() { return listview.current ? listview.current.clientHeight : 0; }; var getData = function(el, name) { var prefix = 'data-'; return el.getAttribute(prefix + name); }; var calculateHeight = function() { var height = 0; state.current.listHeight.push(height); for(var i = 0; i < state.current.listGroup.length; i++){ var item = state.current.listGroup[i]; height += item.clientHeight; state.current.listHeight.push(height); } }; var scrollTo = function(index) { if (!index && index !== 0) { return; } if (!state.current.listHeight.length) { calculateHeight(); } var 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); if (listview.current) { listview.current.scrollTo(0, state.current.listHeight[cacheIndex]); } }; var bind = useGesture({ onDragStart: function(param) { var target = param.target, offset = param.offset; setScrollStart(true); var index = Number(getData(target, 'index')); touchState.current.y1 = offset[1]; state.current.anchorIndex = +index; setCodeIndex(function(codeIndex) { return codeIndex + index; }); scrollTo(index); }, onDragEnd: function(param) { var offset = param.offset; touchState.current.y2 = offset[1]; var delta = (touchState.current.y2 - touchState.current.y1) / spaceHeight || 0; // delta 是一个浮点数, 需要四舍五入一下, 否则页面会找不到最终计算后的index var cacheIndex = state.current.anchorIndex + Math.round(delta); setCodeIndex(cacheIndex); scrollTo(cacheIndex); resetScrollState(); } }); var handleClickItem = function(key, item) { onItemClick && onItemClick(key, item); setCurrentData(item); setCurrentKey(key); }; var handleClickIndex = function(key) { onIndexClick && onIndexClick(key); }; var setListGroup = function() { if (listview.current) { var els = listview.current.querySelectorAll('.nut-elevator-list-item'); els.forEach(function(el) { if (el != null && !state.current.listGroup.includes(el)) { state.current.listGroup.push(el); } }); } }; var listViewScroll = function(e) { var listHeight = state.current.listHeight; if (!listHeight.length) { calculateHeight(); } var target = e.target; var scrollTop = target.scrollTop; scrollTop = Math.ceil(scrollTop); state.current.scrollY = scrollTop; setScrollY(scrollTop); for(var i = 0; i < listHeight.length - 1; i++){ var height1 = listHeight[i]; var height2 = listHeight[i + 1]; if (state.current.scrollY >= height1 && state.current.scrollY < height2) { setCurrentIndex(i); return; } } setCurrentIndex(listHeight.length - 2); }; useEffect(function() { if (listview.current) { setListGroup(); listview.current.addEventListener('scroll', listViewScroll); } }, [ listview ]); var _obj; return /*#__PURE__*/ React.createElement("div", _object_spread({ className: "".concat(classPrefix, " ").concat(className), style: style }, rest), sticky && scrollY > 0 ? /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-list-fixed") }, /*#__PURE__*/ React.createElement("span", { className: "".concat(classPrefix, "-list-fixed-title") }, list[currentIndex][floorKey])) : null, /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-list"), style: { height: Number.isNaN(+height) ? height : "".concat(height, "px") } }, /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-list-inner"), ref: listview }, list.map(function(item, idx) { return /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-list-item"), key: idx }, /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-list-item-code") }, item[floorKey]), /*#__PURE__*/ React.createElement(React.Fragment, null, item.list.map(function(subitem) { var _obj; return /*#__PURE__*/ React.createElement("div", { 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 && currentKey === item[floorKey]), _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("div", { className: classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-code-current"), true), _define_property(_obj, "".concat(classPrefix, "-code-current-current"), true), _obj)) }, list[codeIndex][floorKey]) : null, /*#__PURE__*/ React.createElement("div", { className: "".concat(classPrefix, "-bars") }, /*#__PURE__*/ React.createElement(animated.div, _object_spread_props(_object_spread({ className: "".concat(classPrefix, "-bars-inner") }, bind()), { style: { touchAction: 'pan-y' } }), list.map(function(item, index) { var _obj; return /*#__PURE__*/ React.createElement("div", { className: classNames((_obj = {}, _define_property(_obj, "".concat(classPrefix, "-bars-inner-item"), true), _define_property(_obj, "".concat(classPrefix, "-bars-inner-item-active"), item[floorKey] === list[currentIndex][floorKey]), _obj)), "data-index": index, key: index, onClick: function() { return handleClickIndex(item[floorKey]); } }, item[floorKey]); })))) : null); }; Elevator.displayName = 'NutElevator'; Elevator.Context = elevatorContext;