@lobehub/ui 5.60.0 → 5.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/es/EmojiPicker/AvatarUploader.mjs +1 -1
  2. package/es/Form/components/FormSubmitFooter.mjs +1 -1
  3. package/es/base-ui/Input/style.d.mts +1 -1
  4. package/es/base-ui/Pagination/Pagination.mjs +158 -41
  5. package/es/base-ui/Pagination/Pagination.mjs.map +1 -1
  6. package/es/base-ui/Pagination/helpers.mjs +3 -3
  7. package/es/base-ui/Pagination/helpers.mjs.map +1 -1
  8. package/es/base-ui/Pagination/index.d.mts +2 -2
  9. package/es/base-ui/Pagination/style.mjs +39 -0
  10. package/es/base-ui/Pagination/style.mjs.map +1 -1
  11. package/es/base-ui/Pagination/type.d.mts +42 -4
  12. package/es/base-ui/QRCode/QRCode.mjs +1 -1
  13. package/es/base-ui/Table/Column.d.mts +9 -0
  14. package/es/base-ui/Table/Column.mjs +7 -0
  15. package/es/base-ui/Table/Column.mjs.map +1 -0
  16. package/es/base-ui/Table/ColumnGroup.d.mts +12 -0
  17. package/es/base-ui/Table/ColumnGroup.mjs +7 -0
  18. package/es/base-ui/Table/ColumnGroup.mjs.map +1 -0
  19. package/es/base-ui/Table/ExpandIcon.mjs +33 -0
  20. package/es/base-ui/Table/ExpandIcon.mjs.map +1 -0
  21. package/es/base-ui/Table/FilterDropdown.mjs +284 -0
  22. package/es/base-ui/Table/FilterDropdown.mjs.map +1 -0
  23. package/es/base-ui/Table/LoadingSkeleton.mjs +83 -0
  24. package/es/base-ui/Table/LoadingSkeleton.mjs.map +1 -0
  25. package/es/base-ui/Table/Table.d.mts +21 -3
  26. package/es/base-ui/Table/Table.mjs +444 -97
  27. package/es/base-ui/Table/Table.mjs.map +1 -1
  28. package/es/base-ui/Table/columnUtils.mjs +56 -0
  29. package/es/base-ui/Table/columnUtils.mjs.map +1 -0
  30. package/es/base-ui/Table/index.d.mts +4 -2
  31. package/es/base-ui/Table/selectionUtils.d.mts +9 -0
  32. package/es/base-ui/Table/selectionUtils.mjs +128 -0
  33. package/es/base-ui/Table/selectionUtils.mjs.map +1 -0
  34. package/es/base-ui/Table/semantic.mjs +55 -0
  35. package/es/base-ui/Table/semantic.mjs.map +1 -0
  36. package/es/base-ui/Table/style.mjs +801 -161
  37. package/es/base-ui/Table/style.mjs.map +1 -1
  38. package/es/base-ui/Table/type.d.mts +471 -37
  39. package/es/base-ui/Table/useBreakpoint.mjs +41 -0
  40. package/es/base-ui/Table/useBreakpoint.mjs.map +1 -0
  41. package/es/base-ui/Table/useFilter.mjs +64 -0
  42. package/es/base-ui/Table/useFilter.mjs.map +1 -0
  43. package/es/base-ui/Table/useSelection.mjs +421 -0
  44. package/es/base-ui/Table/useSelection.mjs.map +1 -0
  45. package/es/base-ui/Table/useSorter.mjs +152 -0
  46. package/es/base-ui/Table/useSorter.mjs.map +1 -0
  47. package/es/base-ui/Table/useTableState.mjs +82 -55
  48. package/es/base-ui/Table/useTableState.mjs.map +1 -1
  49. package/es/base-ui/index.d.mts +6 -4
  50. package/es/base-ui/index.mjs +9 -9
  51. package/es/chat/EditableMessageList/EditableMessageList.mjs +1 -1
  52. package/es/chat/MessageInput/MessageInput.mjs +1 -1
  53. package/es/chat/MessageModal/MessageModal.mjs +1 -1
  54. package/es/chat/TokenTag/TokenTag.mjs +1 -1
  55. package/es/i18n/resources/en/index.d.mts +3 -2
  56. package/es/i18n/resources/en/index.mjs +4 -2
  57. package/es/i18n/resources/en/index.mjs.map +1 -1
  58. package/es/i18n/resources/en/table.d.mts +23 -0
  59. package/es/i18n/resources/en/table.mjs +24 -0
  60. package/es/i18n/resources/en/table.mjs.map +1 -0
  61. package/es/i18n/resources/zhCn/index.d.mts +3 -2
  62. package/es/i18n/resources/zhCn/index.mjs +4 -2
  63. package/es/i18n/resources/zhCn/index.mjs.map +1 -1
  64. package/es/i18n/resources/zhCn/table.d.mts +23 -0
  65. package/es/i18n/resources/zhCn/table.mjs +24 -0
  66. package/es/i18n/resources/zhCn/table.mjs.map +1 -0
  67. package/es/i18n/types.d.mts +2 -1
  68. package/es/index.mjs +2 -2
  69. package/package.json +2 -2
  70. package/es/base-ui/Table/FilterMenu.mjs +0 -45
  71. package/es/base-ui/Table/FilterMenu.mjs.map +0 -1
  72. package/es/base-ui/Table/TableBody.mjs +0 -59
  73. package/es/base-ui/Table/TableBody.mjs.map +0 -1
  74. package/es/base-ui/Table/TableHead.mjs +0 -50
  75. package/es/base-ui/Table/TableHead.mjs.map +0 -1
  76. package/es/base-ui/Table/features.mjs +0 -12
  77. package/es/base-ui/Table/features.mjs.map +0 -1
  78. package/es/base-ui/Table/fixedOffsets.mjs +0 -29
  79. package/es/base-ui/Table/fixedOffsets.mjs.map +0 -1
  80. package/es/base-ui/Table/toColumnDefs.mjs +0 -26
  81. package/es/base-ui/Table/toColumnDefs.mjs.map +0 -1
@@ -1,133 +1,480 @@
1
1
  "use client";
2
+ import { Tooltip } from "../Tooltip/Tooltip.mjs";
3
+ import ActionIcon from "../ActionIcon/ActionIcon.mjs";
4
+ import { useTranslation } from "../../i18n/useTranslation.mjs";
2
5
  import { useEventCallback } from "../../hooks/useEventCallback.mjs";
3
6
  import Pagination from "../Pagination/Pagination.mjs";
4
7
  import Spin from "../Spin/Spin.mjs";
5
- import { tableFeatureSet } from "./features.mjs";
6
- import { styles } from "./style.mjs";
7
- import FilterMenu from "./FilterMenu.mjs";
8
- import { getFixedOffsets } from "./fixedOffsets.mjs";
9
- import { toColumnDefs } from "./toColumnDefs.mjs";
10
- import TableBody from "./TableBody.mjs";
11
- import TableHead from "./TableHead.mjs";
8
+ import Empty from "../../Empty/Empty.mjs";
9
+ import table_default from "../../i18n/resources/en/table.mjs";
10
+ import Column from "./Column.mjs";
11
+ import ColumnGroup from "./ColumnGroup.mjs";
12
+ import { SELECTION_ALL, SELECTION_COLUMN, SELECTION_INVERT, SELECTION_NONE, isPlainObject } from "./selectionUtils.mjs";
13
+ import { assertColumnKeys, fillColumns, flattenColumns, getColumnId, getColumnPos, isColumnGroup, isColumnVisibleAt, renderColumnTitle } from "./columnUtils.mjs";
14
+ import renderExpandIcon from "./ExpandIcon.mjs";
15
+ import { PREFIX_CLS, styles } from "./style.mjs";
16
+ import FilterDropdown, { TableMeasureRowContext } from "./FilterDropdown.mjs";
17
+ import TableLoadingSkeleton from "./LoadingSkeleton.mjs";
18
+ import { normalizeClassNames, normalizeStyles, resolveSemantic } from "./semantic.mjs";
19
+ import { useBreakpoint } from "./useBreakpoint.mjs";
20
+ import { useSelection } from "./useSelection.mjs";
21
+ import { DEFAULT_SORT_DIRECTIONS, getMultiplePriority, getNextSortOrder } from "./useSorter.mjs";
12
22
  import { useTableState } from "./useTableState.mjs";
13
- import { memo, useEffect, useMemo } from "react";
23
+ import { memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef } from "react";
14
24
  import { jsx, jsxs } from "react/jsx-runtime";
15
25
  import { cx } from "antd-style";
16
- import { useTable } from "@tanstack/react-table";
26
+ import { ArrowDownFromLine, ArrowUpDown, ArrowUpToLine } from "lucide-react";
27
+ import RcTable, { EXPAND_COLUMN, INTERNAL_HOOKS, Summary, VirtualTable, convertChildrenToColumns } from "@rc-component/table";
17
28
  //#region src/base-ui/Table/Table.tsx
18
29
  const EMPTY_DATA = [];
30
+ const DEFAULT_INDENT_SIZE = 15;
31
+ const DEFAULT_SORTER_TOOLTIP = { target: "full-header" };
32
+ /**
33
+ * Estimated `virtual` row height per size, like antd: padding × 2 + 14px × 22/14 line + 1px border.
34
+ * rc-virtual-list still measures the real rows; this only seeds the scroll range.
35
+ */
36
+ const VIRTUAL_ROW_HEIGHT = {
37
+ large: 55,
38
+ medium: 47,
39
+ middle: 47,
40
+ small: 39
41
+ };
42
+ const sizeClassName = {
43
+ large: styles.sizeLarge,
44
+ medium: styles.sizeMedium,
45
+ middle: styles.sizeMedium,
46
+ small: styles.sizeSmall
47
+ };
48
+ const sortTipOf = (next, locale) => next === "descend" ? locale.triggerDesc : next === "ascend" ? locale.triggerAsc : locale.cancelSort;
49
+ const ariaSortOf = (order) => order === "ascend" ? "ascending" : order === "descend" ? "descending" : "none";
50
+ const paginationAlignClassName = {
51
+ center: styles.paginationCenter,
52
+ end: styles.paginationEnd,
53
+ start: styles.paginationStart
54
+ };
55
+ /** antd `normalizePlacement`: `topLeft` / `bottomStart` → `start`, `*Center` → `center`, else `end`. */
56
+ const normalizePlacement = (placement) => {
57
+ const lower = placement.toLowerCase();
58
+ if (lower.includes("center")) return "center";
59
+ return lower.includes("left") || lower.includes("start") ? "start" : "end";
60
+ };
61
+ const wrapMeasureRow = (measureRow) => /* @__PURE__ */ jsx(TableMeasureRowContext, {
62
+ value: true,
63
+ children: measureRow
64
+ });
65
+ /** antd's ref shape: the root element itself, extended with `nativeElement` and `scrollTo`. */
66
+ const toTableRef = (element, scrollTo) => {
67
+ const extra = {
68
+ nativeElement: element,
69
+ scrollTo
70
+ };
71
+ return new Proxy(element, { get(target, prop) {
72
+ if (prop in extra) return extra[prop];
73
+ const value = Reflect.get(target, prop, target);
74
+ return typeof value === "function" ? value.bind(target) : value;
75
+ } });
76
+ };
19
77
  const TableInner = (props) => {
20
- const { bordered = false, className, classNames, columns, dataSource = EMPTY_DATA, emptyText, loading = false, onChange, onRow, pagination, ref, renderFilter, rowClassName, rowKey, scroll, size = "middle", style, styles: customStyles, tableLayout } = props;
78
+ const { variant = "borderless", children, childrenColumnName: legacyChildrenColumnName, className, classNames, column: columnDefaults, columns: columnsProp, components, dataSource = EMPTY_DATA, emptyText, expandable, expandedRowRender: legacyExpandedRowRender, expandIcon: legacyExpandIcon, expandIconColumnIndex: legacyExpandIconColumnIndex, footer, getPopupContainer, indentSize: legacyIndentSize, loading = false, locale, measureRowRender, onChange, onHeaderRow, onRow, onScroll, pagination, ref, rootClassName, rowClassName, rowHoverable = true, rowKey = "key", rowSelection, scroll, showHeader, showSorterTooltip: tableShowSorterTooltip = DEFAULT_SORTER_TOOLTIP, size: sizeProp, sortDirections: tableSortDirections = DEFAULT_SORT_DIRECTIONS, sticky, style, styles: customStyles, summary, tableLayout, title, virtual } = props;
79
+ const size = sizeProp ?? "middle";
80
+ const { t } = useTranslation(table_default);
81
+ const tableLocale = useMemo(() => ({
82
+ cancelSort: t("table.cancelSort"),
83
+ collapse: t("table.collapse"),
84
+ expand: t("table.expand"),
85
+ filterCheckAll: t("table.filterCheckAll"),
86
+ filterConfirm: t("table.filterConfirm"),
87
+ filterEmptyText: t("table.filterEmptyText"),
88
+ filterReset: t("table.filterReset"),
89
+ filterSearchPlaceholder: t("table.filterSearchPlaceholder"),
90
+ filterTitle: t("table.filterTitle"),
91
+ selectAll: t("table.selectAll"),
92
+ selectInvert: t("table.selectInvert"),
93
+ selectNone: t("table.selectNone"),
94
+ selectionAll: t("table.selectionAll"),
95
+ sortTitle: t("table.sortTitle"),
96
+ triggerAsc: t("table.triggerAsc"),
97
+ triggerDesc: t("table.triggerDesc"),
98
+ ...locale?.filterCheckall !== void 0 && { filterCheckAll: locale.filterCheckall },
99
+ ...locale
100
+ }), [t, locale]);
101
+ const semanticInfo = { props };
102
+ const mergedClassNames = normalizeClassNames(resolveSemantic(classNames, semanticInfo));
103
+ const mergedStyles = normalizeStyles(resolveSemantic(customStyles, semanticInfo));
104
+ const rawColumns = useMemo(() => columnsProp ?? convertChildrenToColumns(children), [columnsProp, children]);
105
+ const columns = useMemo(() => fillColumns(rawColumns, columnDefaults), [rawColumns, columnDefaults]);
106
+ assertColumnKeys(columns);
107
+ const needResponsive = useMemo(() => flattenColumns(columns).some(({ column }) => column.responsive), [columns]);
108
+ const screens = useBreakpoint(needResponsive);
109
+ const hasRowSelection = Boolean(rowSelection);
110
+ const childrenColumnName = expandable?.childrenColumnName ?? legacyChildrenColumnName ?? "children";
111
+ const expandType = useMemo(() => {
112
+ if (dataSource.some((record) => isPlainObject(record) && record[childrenColumnName])) return "nest";
113
+ if (legacyExpandedRowRender || expandable?.expandedRowRender) return "row";
114
+ return null;
115
+ }, [
116
+ childrenColumnName,
117
+ dataSource,
118
+ legacyExpandedRowRender,
119
+ expandable?.expandedRowRender
120
+ ]);
121
+ const mergedExpandable = useMemo(() => {
122
+ const config = {
123
+ childrenColumnName: legacyChildrenColumnName,
124
+ expandedRowRender: legacyExpandedRowRender,
125
+ expandIconColumnIndex: legacyExpandIconColumnIndex,
126
+ ...expandable,
127
+ expandIcon: expandable?.expandIcon ?? legacyExpandIcon ?? ((iconProps) => renderExpandIcon(iconProps, tableLocale))
128
+ };
129
+ if (expandType === "nest" && config.expandIconColumnIndex === void 0) config.expandIconColumnIndex = hasRowSelection ? 1 : 0;
130
+ else if ((config.expandIconColumnIndex ?? 0) > 0 && hasRowSelection) config.expandIconColumnIndex = config.expandIconColumnIndex - 1;
131
+ if (virtual && config.columnWidth === void 0) config.columnWidth = 48;
132
+ if (typeof config.indentSize !== "number") config.indentSize = typeof legacyIndentSize === "number" ? legacyIndentSize : DEFAULT_INDENT_SIZE;
133
+ return config;
134
+ }, [
135
+ expandable,
136
+ legacyChildrenColumnName,
137
+ legacyExpandedRowRender,
138
+ legacyExpandIcon,
139
+ legacyExpandIconColumnIndex,
140
+ legacyIndentSize,
141
+ expandType,
142
+ hasRowSelection,
143
+ virtual,
144
+ tableLocale
145
+ ]);
146
+ const rootRef = useRef(null);
147
+ const rcRef = useRef(null);
148
+ useImperativeHandle(ref, () => toTableRef(rootRef.current, (config) => rcRef.current?.scrollTo(config)), []);
21
149
  const state = useTableState({
150
+ childrenColumnName,
22
151
  columns,
152
+ dataSource,
23
153
  onChange,
154
+ onTableChange: () => {
155
+ if (scroll && scroll.scrollToFirstRowOnChange !== false) rcRef.current?.scrollTo({ top: 0 });
156
+ },
24
157
  pagination
25
158
  });
26
- const columnDefs = useMemo(() => toColumnDefs(columns), [columns]);
27
- const fixedOffsets = useMemo(() => getFixedOffsets(columns), [columns]);
28
- const table = useTable({
29
- columns: columnDefs,
30
- data: dataSource,
31
- enableMultiSort: false,
32
- enableSortingRemoval: true,
33
- features: tableFeatureSet,
34
- getRowId: (record) => String(typeof rowKey === "function" ? rowKey(record) : record[rowKey]),
35
- manualSorting: state.manualSorting,
36
- onColumnFiltersChange: state.onColumnFiltersChange,
37
- onSortingChange: state.onSortingChange,
38
- state: {
39
- columnFilters: state.columnFilters,
40
- sorting: state.sorting
41
- }
42
- });
43
- const allRows = table.getRowModel().rows;
44
- const { page } = state;
45
- const clientPaginated = pagination !== false && state.config?.total === void 0;
46
- const total = state.config?.total ?? allRows.length;
47
- const pageCount = Math.max(1, Math.ceil(total / page.pageSize));
48
- const pageIndex = Math.min(page.pageIndex, pageCount - 1);
49
- const rows = clientPaginated ? allRows.slice(pageIndex * page.pageSize, (pageIndex + 1) * page.pageSize) : allRows;
159
+ const { config: paginationConfig, data: allRows, filterStates, page, sortStates, titleProps } = state;
160
+ const { pageIndex, pageSize } = page;
161
+ const { total } = state;
162
+ const rows = useMemo(() => {
163
+ if (pagination === false) return allRows;
164
+ if (allRows.length < total && allRows.length <= pageSize) return allRows;
165
+ return allRows.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize);
166
+ }, [
167
+ allRows,
168
+ pagination,
169
+ pageIndex,
170
+ pageSize,
171
+ total
172
+ ]);
173
+ const getRowKey = useMemo(() => typeof rowKey === "function" ? rowKey : (record) => record?.[rowKey], [rowKey]);
174
+ const recordMap = useMemo(() => {
175
+ const map = /* @__PURE__ */ new Map();
176
+ const dig = (records) => {
177
+ records.forEach((record, index) => {
178
+ map.set(getRowKey(record, index), record);
179
+ const children = isPlainObject(record) ? record[childrenColumnName] : void 0;
180
+ if (Array.isArray(children)) dig(children);
181
+ });
182
+ };
183
+ dig(dataSource);
184
+ return map;
185
+ }, [
186
+ dataSource,
187
+ childrenColumnName,
188
+ getRowKey
189
+ ]);
190
+ const getRecordByKey = useCallback((key) => recordMap.get(key), [recordMap]);
191
+ const mergedRowSelection = useMemo(() => {
192
+ if (!virtual || !rowSelection || rowSelection.columnWidth !== void 0) return rowSelection;
193
+ const withDropdown = Boolean(rowSelection.selections) && rowSelection.type !== "radio";
194
+ return {
195
+ ...rowSelection,
196
+ columnWidth: 32 + (withDropdown ? 24 : 0) + (variant === "outlined" ? 16 : 0)
197
+ };
198
+ }, [
199
+ virtual,
200
+ rowSelection,
201
+ variant
202
+ ]);
203
+ const [transformSelectionColumns, selectedKeySet] = useSelection({
204
+ childrenColumnName,
205
+ data: allRows,
206
+ expandType,
207
+ getRecordByKey,
208
+ getRowKey,
209
+ locale: tableLocale,
210
+ pageData: rows
211
+ }, mergedRowSelection);
212
+ const mergedRowClassName = useCallback((record, index, indent) => cx(selectedKeySet.has(getRowKey(record, index)) && `lobe-table-row-selected`, typeof rowClassName === "function" ? rowClassName(record, index, indent) : rowClassName), [
213
+ selectedKeySet,
214
+ getRowKey,
215
+ rowClassName
216
+ ]);
217
+ const clientPaginated = pagination !== false && paginationConfig?.total === void 0;
50
218
  const syncClampedPage = useEventCallback(() => state.clampPage(pageIndex));
51
219
  useEffect(() => {
52
- if (clientPaginated && pageIndex !== page.pageIndex) syncClampedPage();
220
+ if (clientPaginated && pageIndex !== state.rawPageIndex) syncClampedPage();
53
221
  }, [
54
222
  clientPaginated,
55
223
  pageIndex,
56
- page.pageIndex,
224
+ state.rawPageIndex,
57
225
  syncClampedPage
58
226
  ]);
59
- const minWidth = scroll?.x === "max-content" ? "100%" : scroll?.x;
60
- return /* @__PURE__ */ jsxs("div", {
61
- className: cx(styles.root, className),
62
- ref,
63
- style,
64
- children: [/* @__PURE__ */ jsxs("div", {
65
- className: cx(styles.wrapper, bordered && styles.bordered, classNames?.wrapper),
66
- "data-table-wrapper": "",
67
- style: {
68
- maxHeight: scroll?.y,
69
- ...customStyles?.wrapper
70
- },
71
- children: [/* @__PURE__ */ jsxs("table", {
72
- className: cx(styles.table, size === "small" ? styles.small : styles.middle),
73
- style: {
74
- minWidth,
75
- tableLayout,
76
- width: scroll?.x === "max-content" ? "max-content" : "100%"
77
- },
78
- children: [/* @__PURE__ */ jsx(TableHead, {
79
- classNames,
80
- columnIds: state.columnIds,
81
- columns,
82
- fixedOffsets,
83
- getColumn: (id) => table.getColumn(id),
84
- styles: customStyles,
85
- renderFilter: (column, id) => {
86
- if (renderFilter) return renderFilter(column, id, table);
87
- const tableColumn = table.getColumn(id);
88
- const value = tableColumn?.getFilterValue() ?? [];
89
- return /* @__PURE__ */ jsx(FilterMenu, {
90
- filters: column.filters ?? [],
91
- label: typeof column.title === "string" ? column.title : id,
92
- value,
93
- onChange: (next) => tableColumn?.setFilterValue(next.length > 0 ? next : void 0)
94
- });
227
+ const { spinning: isLoading = true, tip, variant: spinVariant = "network", ...spinRest } = typeof loading === "object" ? loading : { spinning: loading };
228
+ const spinProps = {
229
+ variant: spinVariant,
230
+ ...spinRest
231
+ };
232
+ const triggerSort = useEventCallback(state.triggerSort);
233
+ const triggerFilter = useEventCallback(state.triggerFilter);
234
+ const rcColumns = useMemo(() => {
235
+ const transform = (list, parentPos) => list.flatMap((column, index) => {
236
+ if (column === EXPAND_COLUMN || column === SELECTION_COLUMN) return [column];
237
+ const pos = getColumnPos(index, parentPos);
238
+ if (!isColumnVisibleAt(column, screens)) return [];
239
+ const id = getColumnId(column, pos);
240
+ const { defaultFilteredValue: _defaultFilteredValue, defaultSortOrder: _defaultSortOrder, filterDropdown, filterDropdownOpen: _filterDropdownOpen, filterDropdownProps: _filterDropdownProps, filtered: _filtered, filteredValue: _filteredValue, filterIcon: _filterIcon, filterMode: _filterMode, filterMultiple: _filterMultiple, filterOnClose: _filterOnClose, filterResetToDefaultFilteredValue: _filterResetToDefaultFilteredValue, filters: columnFilters, filterSearch: _filterSearch, onFilter: _onFilter, onFilterDropdownOpenChange: _onFilterDropdownOpenChange, onHeaderCell, responsive: _responsive, showSorterTooltip: columnShowSorterTooltip, sortDirections: columnSortDirections, sortIcon, sortOrder: _sortOrder, sorter, title: columnTitle, ...rest } = column;
241
+ const order = sorter ? sortStates.find(({ key }) => key === id)?.sortOrder : void 0;
242
+ const titleNode = renderColumnTitle(columnTitle, titleProps);
243
+ const titleText = typeof titleNode === "string" || typeof titleNode === "number" ? String(titleNode) : void 0;
244
+ const titleContent = column.ellipsis ? /* @__PURE__ */ jsx("span", {
245
+ className: cx(styles.columnTitle, `${PREFIX_CLS}-column-title`),
246
+ children: titleNode
247
+ }) : titleNode;
248
+ const filterNode = columnFilters || filterDropdown ? /* @__PURE__ */ jsx(FilterDropdown, {
249
+ column,
250
+ columnKey: id,
251
+ filterState: filterStates.find(({ key }) => key === id),
252
+ getPopupContainer,
253
+ label: titleText ?? id,
254
+ locale: tableLocale,
255
+ triggerFilter
256
+ }) : null;
257
+ const hasControls = Boolean(sorter) || Boolean(filterNode);
258
+ let sorterNode = null;
259
+ if (sorter) {
260
+ const nextOrder = getNextSortOrder(columnSortDirections ?? tableSortDirections, order);
261
+ const showTooltip = columnShowSorterTooltip ?? tableShowSorterTooltip;
262
+ const { target, ...tooltipOptions } = typeof showTooltip === "object" ? showTooltip : {};
263
+ const tooltipProps = {
264
+ title: sortTipOf(nextOrder, tableLocale),
265
+ ...tooltipOptions
266
+ };
267
+ const withTooltip = (node) => /* @__PURE__ */ jsx(Tooltip, {
268
+ ...tooltipProps,
269
+ children: node
270
+ });
271
+ const iconOnlyTooltip = Boolean(showTooltip) && target === "sorter-icon";
272
+ const onSort = () => triggerSort({
273
+ column,
274
+ key: id,
275
+ multiplePriority: getMultiplePriority(column),
276
+ sortOrder: nextOrder
277
+ });
278
+ const sortAction = /* @__PURE__ */ jsx(ActionIcon, {
279
+ active: Boolean(order),
280
+ className: cx(styles.sortCaret, `${PREFIX_CLS}-column-sorter`),
281
+ "data-order": order ?? void 0,
282
+ size: "small",
283
+ icon: sortIcon ? sortIcon({ sortOrder: order ?? null }) : order === "ascend" ? ArrowUpToLine : order === "descend" ? ArrowDownFromLine : ArrowUpDown,
284
+ ...iconOnlyTooltip && showTooltip ? {
285
+ title: tooltipProps.title,
286
+ tooltipProps: tooltipOptions
287
+ } : {},
288
+ onClick: (event) => {
289
+ event.stopPropagation();
290
+ onSort();
95
291
  }
96
- }), /* @__PURE__ */ jsx(TableBody, {
97
- classNames,
98
- columnIds: state.columnIds,
99
- columns,
100
- emptyText,
101
- fixedOffsets,
102
- loading,
103
- rowClassName,
104
- rows,
105
- styles: customStyles,
106
- onRow
107
- })]
108
- }), loading && rows.length > 0 && /* @__PURE__ */ jsx("div", {
109
- className: styles.loading,
110
- "data-table-loading": "",
111
- children: /* @__PURE__ */ jsx(Spin, {})
112
- })]
113
- }), pagination !== false && total > 0 && /* @__PURE__ */ jsx("div", {
114
- className: styles.pagination,
292
+ });
293
+ const group = /* @__PURE__ */ jsxs("span", {
294
+ className: cx(styles.sortButton, `${PREFIX_CLS}-column-sorters`),
295
+ title: showTooltip ? void 0 : tableLocale.sortTitle,
296
+ children: [/* @__PURE__ */ jsx("span", {
297
+ className: styles.sortTitle,
298
+ onClick: onSort,
299
+ children: titleContent
300
+ }), sortAction]
301
+ });
302
+ sorterNode = showTooltip && !iconOnlyTooltip ? withTooltip(group) : group;
303
+ }
304
+ return {
305
+ ...rest,
306
+ className: cx(rest.className, order ? [`${PREFIX_CLS}-column-sort`, styles.sortedColumn] : void 0),
307
+ children: isColumnGroup(column) ? transform(column.children, pos) : void 0,
308
+ key: id,
309
+ onHeaderCell: () => {
310
+ const cell = onHeaderCell?.(column);
311
+ return {
312
+ ...sorter && { "aria-sort": ariaSortOf(order) },
313
+ ...column.ellipsis && hasControls && titleText && { title: titleText },
314
+ ...cell,
315
+ className: cx(sorter && `lobe-table-column-has-sorters`, cell?.className)
316
+ };
317
+ },
318
+ title: hasControls ? /* @__PURE__ */ jsxs("span", {
319
+ className: styles.headerInner,
320
+ children: [sorterNode ?? titleContent, filterNode]
321
+ }) : titleContent
322
+ };
323
+ });
324
+ return transform(columns);
325
+ }, [
326
+ columns,
327
+ screens,
328
+ sortStates,
329
+ filterStates,
330
+ titleProps,
331
+ getPopupContainer,
332
+ triggerFilter,
333
+ triggerSort,
334
+ tableSortDirections,
335
+ tableShowSorterTooltip,
336
+ tableLocale
337
+ ]);
338
+ const mergedOnRow = useMemo(() => (record, index) => {
339
+ const rowProps = onRow?.(record, index ?? 0) ?? {};
340
+ return {
341
+ ...rowProps,
342
+ className: cx(rowProps.onClick && styles.clickable, rowProps.className)
343
+ };
344
+ }, [onRow]);
345
+ const hasFixedColumn = useMemo(() => Boolean(rowSelection?.fixed) || flattenColumns(columns).some(({ column }) => column.fixed && !column.hidden), [columns, rowSelection?.fixed]);
346
+ const mergedTableLayout = tableLayout ?? (hasFixedColumn && scroll?.x !== "max-content" ? "fixed" : void 0);
347
+ let topPagination = null;
348
+ let bottomPagination = null;
349
+ if (paginationConfig && total > 0) {
350
+ const { current: _current, defaultCurrent: _defaultCurrent, defaultPageSize: _defaultPageSize, onChange: _onChange, onShowSizeChange: _onShowSizeChange, pageSize: _pageSize, placement, position, total: _total, className: paginationClassName, classNames: paginationClassNames, size: paginationSize, styles: paginationStyles, ...paginationRest } = paginationConfig;
351
+ const pageCount = Math.ceil(total / pageSize);
352
+ const renderPagination = (align, side) => /* @__PURE__ */ jsx("div", {
353
+ className: cx(styles.pagination, side === "top" && styles.paginationTop, paginationAlignClassName[align], `${PREFIX_CLS}-pagination-wrapper`),
115
354
  children: /* @__PURE__ */ jsx(Pagination, {
355
+ ...paginationRest,
116
356
  current: pageIndex + 1,
117
- pageSize: page.pageSize,
118
- pageSizeOptions: state.config?.pageSizeOptions,
119
- showSizeChanger: state.config?.showSizeChanger,
357
+ pageSize,
358
+ size: paginationSize ?? (sizeProp && sizeProp !== "large" ? "small" : void 0),
120
359
  total,
121
- onChange: (next, pageSize) => state.onPaginationChange({
360
+ className: cx(`${PREFIX_CLS}-pagination`, `${PREFIX_CLS}-pagination-${align}`, paginationClassName),
361
+ classNames: {
362
+ item: cx(mergedClassNames.pagination.item, paginationClassNames?.item),
363
+ root: cx(mergedClassNames.pagination.root, paginationClassNames?.root)
364
+ },
365
+ styles: {
366
+ item: {
367
+ ...paginationStyles?.item,
368
+ ...mergedStyles.pagination.item
369
+ },
370
+ root: {
371
+ ...paginationStyles?.root,
372
+ ...mergedStyles.pagination.root
373
+ }
374
+ },
375
+ onChange: (next, nextPageSize) => state.onPaginationChange({
122
376
  pageIndex: next - 1,
123
- pageSize
377
+ pageSize: nextPageSize
124
378
  })
125
379
  })
126
- })]
380
+ });
381
+ if (!(paginationRest.hideOnSinglePage && pageCount <= 1)) {
382
+ const mergedPlacement = placement ?? position;
383
+ if (Array.isArray(mergedPlacement)) {
384
+ const find = (side) => mergedPlacement.find((item) => item.includes(side));
385
+ const top = find("top");
386
+ const bottom = find("bottom");
387
+ const none = mergedPlacement.every((item) => item === "none");
388
+ if (top) topPagination = renderPagination(normalizePlacement(top), "top");
389
+ if (bottom) bottomPagination = renderPagination(normalizePlacement(bottom), "bottom");
390
+ if (!top && !bottom && !none) bottomPagination = renderPagination("end", "bottom");
391
+ } else bottomPagination = renderPagination("end", "bottom");
392
+ }
393
+ }
394
+ const customEmpty = locale?.emptyText ?? emptyText;
395
+ const emptyNode = isLoading ? /* @__PURE__ */ jsx(TableLoadingSkeleton, {
396
+ columns,
397
+ expandColumn: Boolean(expandType),
398
+ rows: pagination === false ? 5 : Math.min(5, pageSize),
399
+ screens,
400
+ selectionColumn: hasRowSelection,
401
+ size
402
+ }) : customEmpty === void 0 ? /* @__PURE__ */ jsx(Empty, { description: t("table.emptyText") }) : typeof customEmpty === "function" ? customEmpty() : customEmpty;
403
+ const TableComponent = virtual ? VirtualTable : RcTable;
404
+ return /* @__PURE__ */ jsxs("div", {
405
+ ref: rootRef,
406
+ style: {
407
+ ...mergedStyles.root,
408
+ ...style
409
+ },
410
+ className: cx(styles.root, `${PREFIX_CLS}-wrapper`, rootClassName, className, mergedClassNames.root),
411
+ children: [
412
+ topPagination,
413
+ /* @__PURE__ */ jsxs("div", {
414
+ className: styles.spinContainer,
415
+ "data-table-wrapper": "",
416
+ children: [/* @__PURE__ */ jsx(TableComponent, {
417
+ ...virtual && { listItemHeight: VIRTUAL_ROW_HEIGHT[size] },
418
+ columns: rcColumns,
419
+ components,
420
+ data: rows,
421
+ emptyText: emptyNode,
422
+ expandable: mergedExpandable,
423
+ footer,
424
+ internalHooks: INTERNAL_HOOKS,
425
+ prefixCls: PREFIX_CLS,
426
+ ref: rcRef,
427
+ rowClassName: mergedRowClassName,
428
+ rowHoverable,
429
+ rowKey,
430
+ scroll,
431
+ showHeader,
432
+ sticky,
433
+ summary,
434
+ tableLayout: mergedTableLayout,
435
+ title,
436
+ transformColumns: transformSelectionColumns,
437
+ className: cx(styles.table, sizeClassName[size], `${PREFIX_CLS}-${size === "middle" ? "medium" : size}`, variant === "outlined" && styles.outlined, variant === "filled" && styles.filled, `${PREFIX_CLS}-${variant}`, rowHoverable && styles.hoverable),
438
+ classNames: {
439
+ body: mergedClassNames.body,
440
+ content: mergedClassNames.content,
441
+ footer: mergedClassNames.footer,
442
+ header: mergedClassNames.header,
443
+ section: mergedClassNames.section,
444
+ title: mergedClassNames.title
445
+ },
446
+ measureRowRender: (measureRow) => wrapMeasureRow(measureRowRender ? measureRowRender(measureRow) : measureRow),
447
+ styles: {
448
+ body: mergedStyles.body,
449
+ content: mergedStyles.content,
450
+ footer: mergedStyles.footer,
451
+ header: mergedStyles.header,
452
+ section: mergedStyles.section,
453
+ title: mergedStyles.title
454
+ },
455
+ onHeaderRow,
456
+ onRow: mergedOnRow,
457
+ onScroll
458
+ }), isLoading && /* @__PURE__ */ jsxs("div", {
459
+ className: styles.loading,
460
+ "data-table-loading": "",
461
+ children: [/* @__PURE__ */ jsx(Spin, { ...spinProps }), tip]
462
+ })]
463
+ }),
464
+ bottomPagination
465
+ ]
127
466
  });
128
467
  };
129
468
  const Table = memo(TableInner);
130
469
  Table.displayName = "Table";
470
+ Table.Column = Column;
471
+ Table.ColumnGroup = ColumnGroup;
472
+ Table.EXPAND_COLUMN = EXPAND_COLUMN;
473
+ Table.SELECTION_COLUMN = SELECTION_COLUMN;
474
+ Table.SELECTION_ALL = SELECTION_ALL;
475
+ Table.SELECTION_INVERT = SELECTION_INVERT;
476
+ Table.SELECTION_NONE = SELECTION_NONE;
477
+ Table.Summary = Summary;
131
478
  //#endregion
132
479
  export { TableInner, Table as default };
133
480