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