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