UNPKG

@nutui/nutui-react

Version:

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

179 lines (178 loc) 7.5 kB
import { _ as __rest } from "./tslib.es6.js"; import React__default, { useState, useEffect, useCallback, useRef } from "react"; import classNames from "classnames"; import { ArrowDown } from "@nutui/icons-react"; import { useConfig, useRtl } from "./ConfigProvider.js"; import { C as ComponentDefaults } from "./typings.js"; import { u as usePropsValue } from "./use-props-value.js"; function useTableSticky(columns, rtl = false) { const [isSticky, setIsSticky] = useState(false); const [stickyColumnStyleMap, setStickyColumnStyleMap] = useState({}); const [stickyColumnClassMap, setStickyColumnClassMap] = useState({}); const [stickyLeftWidth, setStickyLeftWidth] = useState(0); const [stickyRightWidth, setStickyRightWidth] = useState(0); useEffect(() => { const leftColumns = columns.filter((item) => item.fixed === "left") || []; const rightColumns = columns.filter((item) => item.fixed === "right") || []; const middleColumns = columns.filter((item) => !item.fixed) || []; const _columnStyleMap = {}; const _columnClassMap = {}; let _stickyLeftWidth = 0; let _stickyRightWidth = 0; leftColumns.forEach((curr, index) => { const dir = rtl ? "right" : "left"; _columnStyleMap[curr.key] = { [dir]: _stickyLeftWidth || 0, width: curr.width || "auto" }; _columnClassMap[curr.key] = { "nut-table-fixed-left": true, "nut-table-fixed-left-last": index === leftColumns.length - 1 }; _stickyLeftWidth += curr.width || 0; }); middleColumns.forEach((curr) => { _columnStyleMap[curr.key] = { width: curr.width || "auto" }; }); for (let i = rightColumns.length - 1; i >= 0; i--) { const curr = rightColumns[i]; const dir = rtl ? "left" : "right"; _columnStyleMap[curr.key] = { [dir]: _stickyRightWidth || 0, width: curr.width || "auto" }; _columnClassMap[curr.key] = { "nut-table-fixed-right": true, "nut-table-fixed-right-first": i === 0 }; _stickyRightWidth += curr.width || 0; } setIsSticky(leftColumns.length > 0 || rightColumns.length > 0); setStickyColumnStyleMap(_columnStyleMap); setStickyColumnClassMap(_columnClassMap); setStickyLeftWidth(_stickyLeftWidth); setStickyRightWidth(_stickyRightWidth); }, [columns]); const getStickyStyle = useCallback((key) => { return stickyColumnStyleMap[key]; }, [stickyColumnStyleMap]); const getStickyClass = useCallback((key) => { return stickyColumnClassMap[key]; }, [stickyColumnClassMap]); return { isSticky, stickyLeftWidth, stickyRightWidth, getStickyClass, getStickyStyle }; } const defaultProps = Object.assign(Object.assign({}, ComponentDefaults), { columns: [], data: [], bordered: true, striped: false, noData: "", sorterIcon: null, showHeader: true }); const Table = (props) => { const { locale } = useConfig(); const rtl = useRtl(); defaultProps.noData = locale.noData; const _a = Object.assign(Object.assign({}, defaultProps), props), { children, className, style, columns, data, bordered, summary, striped, noData, sorterIcon, showHeader, onSort } = _a, rest = __rest(_a, ["children", "className", "style", "columns", "data", "bordered", "summary", "striped", "noData", "sorterIcon", "showHeader", "onSort"]); const sortedMapping = useRef({}); const [innerValue, setValue] = usePropsValue({ defaultValue: data, finalValue: [] }); const { isSticky, stickyLeftWidth, stickyRightWidth, getStickyClass, getStickyStyle } = useTableSticky(columns, rtl); useEffect(() => { setValue(data); }, [data]); const classPrefix = "nut-table"; const headerClassPrefix = `${classPrefix}-main-head-tr`; const bodyClassPrefix = `${classPrefix}-main-body-tr`; const cls = classNames(classPrefix, className); const handleSorterClick = (item) => { if (item.sorter && !sortedMapping.current[item.key]) { const copied = [...innerValue]; if (typeof item.sorter === "function") { copied.sort(item.sorter); } else if (item.sorter === "default") { copied.sort(); } sortedMapping.current[item.key] = true; setValue(copied, true); onSort && onSort(item, copied); } else { sortedMapping.current[item.key] = false; setValue(data); } }; const cellClasses = (item) => { return { [`${headerClassPrefix}-border`]: bordered, [`${headerClassPrefix}-align${item.align ? item.align : ""}`]: true }; }; const getColumnItem = (value) => { return columns.filter((item) => item.key === value)[0]; }; const renderHeadCells = () => { return columns.map((item, index) => { return React__default.createElement( "div", { className: classNames(`${headerClassPrefix}-th`, cellClasses(item), getStickyClass(item.key)), key: item.key, onClick: () => handleSorterClick(item), style: getStickyStyle(item.key) }, item.title, " ", item.sorter && (sorterIcon || React__default.createElement(ArrowDown, { width: "12px", height: "12px" })) ); }); }; const sortDataItem = () => { return columns.map((columns2) => { return [columns2.key, columns2.render]; }); }; const renderBodyTds = (item, rowIndex) => { return sortDataItem().map(([value, render]) => { return React__default.createElement("div", { className: classNames(`${bodyClassPrefix}-td`, cellClasses(getColumnItem(value)), getStickyClass(value)), key: value, style: getStickyStyle(value) }, typeof item[value] === "function" || typeof render === "function" ? React__default.createElement("div", null, render ? render(item, rowIndex) : item[value](item)) : item[value]); }); }; const renderBodyTrs = () => { return innerValue.map((item, index) => { const inner = renderBodyTds(item, index); const { rowRender } = item; if (rowRender && typeof rowRender === "function") { return rowRender(item, index, { inner }); } return React__default.createElement("div", { className: bodyClassPrefix, key: index }, inner); }); }; return React__default.createElement( "div", Object.assign({ className: cls }, rest), React__default.createElement( "div", { className: classNames(`${classPrefix}-wrapper ${isSticky ? `${classPrefix}-wrapper-sticky` : ""}`), style }, React__default.createElement( "div", { className: classNames(`${classPrefix}-main`, { [`${classPrefix}-main-striped`]: striped }) }, showHeader && React__default.createElement( "div", { className: `${classPrefix}-main-head` }, React__default.createElement("div", { className: headerClassPrefix }, renderHeadCells()) ), React__default.createElement("div", { className: `${classPrefix}-main-body` }, renderBodyTrs()) ) ), isSticky ? React__default.createElement( React__default.Fragment, null, React__default.createElement("div", { className: `${classPrefix}-sticky-left`, style: { width: stickyLeftWidth } }), React__default.createElement("div", { className: `${classPrefix}-sticky-right`, style: { width: stickyRightWidth } }) ) : null, (summary || innerValue.length === 0) && React__default.createElement("div", { className: `${classPrefix}-summary` }, summary || noData) ); }; Table.displayName = "NutTable"; export { Table as default };