@dbcdk/react-components 0.0.197 → 0.0.199
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.
- package/dist/components/json-viewer/JsonViewer.module.css +53 -0
- package/dist/components/json-viewer/JsonViewerShell.cjs +147 -143
- package/dist/components/json-viewer/JsonViewerShell.js +149 -145
- package/dist/components/line-viewer/LineViewer.cjs +15 -21
- package/dist/components/line-viewer/LineViewer.d.ts +1 -1
- package/dist/components/line-viewer/LineViewer.js +16 -22
- package/dist/components/line-viewer/LineViewer.module.css +58 -3
- package/dist/components/page-layout/PageLayout.module.css +1 -1
- package/dist/components/scroll-fade/ScrollFade.cjs +42 -0
- package/dist/components/scroll-fade/ScrollFade.d.ts +18 -0
- package/dist/components/scroll-fade/ScrollFade.js +36 -0
- package/dist/components/scroll-fade/ScrollFade.module.css +71 -0
- package/dist/components/search-box/SearchBox.cjs +39 -35
- package/dist/components/search-box/SearchBox.d.ts +2 -0
- package/dist/components/search-box/SearchBox.js +39 -35
- package/dist/components/table/Table.cjs +52 -23
- package/dist/components/table/Table.d.ts +1 -1
- package/dist/components/table/Table.js +53 -24
- package/dist/components/table/Table.module.css +4 -0
- package/dist/components/table/Table.types.d.ts +27 -0
- package/dist/components/table/TanstackTable.cjs +63 -106
- package/dist/components/table/TanstackTable.d.ts +5 -0
- package/dist/components/table/TanstackTable.js +66 -106
- package/dist/components/table/columnLayout.utils.cjs +146 -0
- package/dist/components/table/columnLayout.utils.d.ts +44 -0
- package/dist/components/table/columnLayout.utils.js +141 -0
- package/dist/components/table/components/TableHeader.cjs +3 -1
- package/dist/components/table/components/TableHeader.d.ts +2 -1
- package/dist/components/table/components/TableHeader.js +3 -1
- package/dist/components/table/components/TableHeaderCell.cjs +29 -19
- package/dist/components/table/components/TableHeaderCell.d.ts +2 -1
- package/dist/components/table/components/TableHeaderCell.js +29 -19
- package/dist/components/table/hooks/useClientPagination.cjs +66 -0
- package/dist/components/table/hooks/useClientPagination.d.ts +32 -0
- package/dist/components/table/hooks/useClientPagination.js +64 -0
- package/dist/components/table/hooks/useDistributedLayout.cjs +44 -0
- package/dist/components/table/hooks/useDistributedLayout.d.ts +16 -0
- package/dist/components/table/hooks/useDistributedLayout.js +42 -0
- package/dist/components/table/hooks/useElementWidth.cjs +40 -0
- package/dist/components/table/hooks/useElementWidth.d.ts +7 -0
- package/dist/components/table/hooks/useElementWidth.js +38 -0
- package/dist/components/table/hooks/useResizeHeaderExtras.cjs +87 -0
- package/dist/components/table/hooks/useResizeHeaderExtras.d.ts +17 -0
- package/dist/components/table/hooks/useResizeHeaderExtras.js +62 -0
- package/dist/components/table/hooks/useUiSorting.cjs +18 -0
- package/dist/components/table/hooks/useUiSorting.d.ts +3 -0
- package/dist/components/table/hooks/useUiSorting.js +16 -0
- package/dist/components/table/table.utils.cjs +24 -2
- package/dist/components/table/table.utils.d.ts +40 -2
- package/dist/components/table/table.utils.js +20 -2
- package/dist/components/table/tanstackTable.utils.cjs +33 -97
- package/dist/components/table/tanstackTable.utils.d.ts +24 -8
- package/dist/components/table/tanstackTable.utils.js +34 -99
- package/dist/components/xml-viewer/XmlViewer.cjs +15 -21
- package/dist/components/xml-viewer/XmlViewer.d.ts +1 -1
- package/dist/components/xml-viewer/XmlViewer.js +16 -22
- package/dist/components/xml-viewer/XmlViewer.module.css +58 -3
- package/dist/hooks/useScrollOverflow.cjs +71 -0
- package/dist/hooks/useScrollOverflow.d.ts +23 -0
- package/dist/hooks/useScrollOverflow.js +69 -0
- package/dist/hooks/useTableSettings.cjs +2 -1
- package/dist/hooks/useTableSettings.d.ts +1 -0
- package/dist/hooks/useTableSettings.js +2 -1
- package/dist/index.css +1 -0
- package/dist/utils/refs.utils.cjs +13 -0
- package/dist/utils/refs.utils.d.ts +7 -0
- package/dist/utils/refs.utils.js +11 -0
- package/package.json +1 -1
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
3
|
import { useReactTable, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
5
|
+
import { useClientPagination } from './hooks/useClientPagination';
|
|
6
|
+
import { useDistributedLayout } from './hooks/useDistributedLayout';
|
|
7
|
+
import { useElementWidth } from './hooks/useElementWidth';
|
|
8
|
+
import { useResizeHeaderExtras } from './hooks/useResizeHeaderExtras';
|
|
9
|
+
import { useUiSorting } from './hooks/useUiSorting';
|
|
7
10
|
import { Table } from './Table';
|
|
8
|
-
import { DEFAULT_COLUMN_PX } from './table.utils';
|
|
9
|
-
import {
|
|
11
|
+
import { DEFAULT_COLUMN_PX, DEFAULT_VIEW_MODE, getActionsReserve, showsExpandToggle } from './table.utils';
|
|
12
|
+
import { buildColumnVisibilityFromVisibleIds, applyNeighborResize, getSortPropsFromSorting } from './tanstackTable.utils';
|
|
10
13
|
|
|
11
14
|
function TanstackTable(props) {
|
|
15
|
+
var _a, _b;
|
|
12
16
|
const {
|
|
13
17
|
data,
|
|
14
18
|
dataKey,
|
|
@@ -18,6 +22,11 @@ function TanstackTable(props) {
|
|
|
18
22
|
optimisticSortingUi = true,
|
|
19
23
|
visibleColumnIds: visibleColumnIdsProp,
|
|
20
24
|
manualSorting,
|
|
25
|
+
clientPagination = false,
|
|
26
|
+
take: takeProp,
|
|
27
|
+
skip: skipProp,
|
|
28
|
+
totalItemsCount: totalItemsCountProp,
|
|
29
|
+
onPageChange,
|
|
21
30
|
viewMode,
|
|
22
31
|
striped,
|
|
23
32
|
settings,
|
|
@@ -28,37 +37,50 @@ function TanstackTable(props) {
|
|
|
28
37
|
...tableProps
|
|
29
38
|
} = props;
|
|
30
39
|
const visibleColumnIds = visibleColumnIdsProp != null ? visibleColumnIdsProp : settings == null ? void 0 : settings.visibleColumnIds;
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
const [uiSorting, setUiSorting] = useUiSorting(controlledSorting);
|
|
41
|
+
const pagination = useClientPagination({
|
|
42
|
+
enabled: clientPagination,
|
|
43
|
+
rowCount: data.length,
|
|
44
|
+
take: takeProp,
|
|
45
|
+
skip: skipProp,
|
|
46
|
+
totalItemsCount: totalItemsCountProp,
|
|
47
|
+
onPageChange
|
|
48
|
+
});
|
|
49
|
+
const { resetPage } = pagination;
|
|
38
50
|
const columnVisibility = React.useMemo(
|
|
39
51
|
() => buildColumnVisibilityFromVisibleIds(columns, visibleColumnIds),
|
|
40
52
|
[columns, visibleColumnIds]
|
|
41
53
|
);
|
|
42
54
|
const [columnSizing, setColumnSizing] = React.useState({});
|
|
55
|
+
const neighborResizeRef = React.useRef(null);
|
|
43
56
|
const containerRef = React.useRef(null);
|
|
44
|
-
const
|
|
57
|
+
const availableWidth = useElementWidth(containerRef);
|
|
45
58
|
const table = useReactTable({
|
|
46
59
|
data,
|
|
47
60
|
columns,
|
|
48
61
|
state: {
|
|
49
62
|
sorting: uiSorting,
|
|
50
63
|
columnSizing,
|
|
51
|
-
columnVisibility
|
|
64
|
+
columnVisibility,
|
|
65
|
+
...pagination.paginationState ? { pagination: pagination.paginationState } : {}
|
|
52
66
|
},
|
|
53
67
|
onSortingChange: (updater) => {
|
|
54
68
|
const next = typeof updater === "function" ? updater(uiSorting) : updater;
|
|
55
69
|
if (optimisticSortingUi) setUiSorting(next);
|
|
70
|
+
resetPage();
|
|
56
71
|
onSortingChange == null ? void 0 : onSortingChange(next);
|
|
57
72
|
},
|
|
58
|
-
onColumnSizingChange:
|
|
73
|
+
onColumnSizingChange: (updater) => {
|
|
74
|
+
setColumnSizing((prev) => {
|
|
75
|
+
const next = typeof updater === "function" ? updater(prev) : updater;
|
|
76
|
+
const resize = neighborResizeRef.current;
|
|
77
|
+
return resize && table.getState().columnSizingInfo.isResizingColumn === resize.columnId ? applyNeighborResize(next, resize) : next;
|
|
78
|
+
});
|
|
79
|
+
},
|
|
59
80
|
getCoreRowModel: getCoreRowModel(),
|
|
60
81
|
getSortedRowModel: getSortedRowModel(),
|
|
61
82
|
manualSorting: manualSorting != null ? manualSorting : false,
|
|
83
|
+
...pagination.tableOptions,
|
|
62
84
|
enableColumnResizing: true,
|
|
63
85
|
columnResizeMode: "onChange",
|
|
64
86
|
defaultColumn: {
|
|
@@ -67,116 +89,54 @@ function TanstackTable(props) {
|
|
|
67
89
|
size: DEFAULT_COLUMN_PX
|
|
68
90
|
}
|
|
69
91
|
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (typeof ResizeObserver === "undefined") {
|
|
79
|
-
window.addEventListener("resize", updateWidth);
|
|
80
|
-
return () => window.removeEventListener("resize", updateWidth);
|
|
81
|
-
}
|
|
82
|
-
const observer = new ResizeObserver((entries) => {
|
|
83
|
-
var _a, _b, _c;
|
|
84
|
-
const entry = entries[0];
|
|
85
|
-
if (!entry) {
|
|
86
|
-
updateWidth();
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
const contentWidth = (_c = (_b = (_a = entry.contentBoxSize) == null ? void 0 : _a[0]) == null ? void 0 : _b.inlineSize) != null ? _c : entry.contentRect.width;
|
|
90
|
-
const next = Math.floor(contentWidth);
|
|
91
|
-
setAvailableWidth(next > 0 ? next : void 0);
|
|
92
|
-
});
|
|
93
|
-
observer.observe(el);
|
|
94
|
-
return () => observer.disconnect();
|
|
95
|
-
}, []);
|
|
96
|
-
const distributedLayout = React.useMemo(() => {
|
|
97
|
-
if (availableWidth == null) return null;
|
|
98
|
-
return buildDistributedColumnWidths({
|
|
99
|
-
table,
|
|
100
|
-
hasSelection: Boolean(selectedRows && onRowSelect && dataKey),
|
|
101
|
-
// Row actions (context menu, expand toggle) and header actions (e.g. the
|
|
102
|
-
// settings menu) all reserve space at the end of the last column.
|
|
103
|
-
hasContextMenu: Boolean(
|
|
104
|
-
tableProps.getContextMenuItems || tableProps.expandableRows || settings || headerActionsProp != null
|
|
105
|
-
),
|
|
106
|
-
defaultMinPx: 80,
|
|
107
|
-
columnSizing,
|
|
108
|
-
availableWidth
|
|
109
|
-
});
|
|
110
|
-
}, [
|
|
92
|
+
const resolvedViewMode = (_a = viewMode != null ? viewMode : settings == null ? void 0 : settings.viewMode) != null ? _a : DEFAULT_VIEW_MODE;
|
|
93
|
+
const { px: actionReservePx } = getActionsReserve({
|
|
94
|
+
hasRowActions: Boolean(tableProps.getContextMenuItems) || showsExpandToggle(tableProps.expandableRows, resolvedViewMode),
|
|
95
|
+
hasSettings: Boolean(settings),
|
|
96
|
+
hasOtherHeaderActions: headerActionsProp != null,
|
|
97
|
+
showHeader: (_b = tableProps.showHeader) != null ? _b : true
|
|
98
|
+
});
|
|
99
|
+
const { distributedLayout, columnItems } = useDistributedLayout({
|
|
111
100
|
table,
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
dataKey,
|
|
115
|
-
tableProps.getContextMenuItems,
|
|
116
|
-
tableProps.expandableRows,
|
|
117
|
-
settings,
|
|
118
|
-
headerActionsProp,
|
|
101
|
+
columns,
|
|
102
|
+
columnVisibility,
|
|
119
103
|
columnSizing,
|
|
120
|
-
availableWidth
|
|
121
|
-
|
|
104
|
+
availableWidth,
|
|
105
|
+
hasSelection: Boolean(selectedRows && onRowSelect && dataKey),
|
|
106
|
+
actionReservePx
|
|
107
|
+
});
|
|
122
108
|
const initialLayoutReady = availableWidth != null;
|
|
123
|
-
const resolvedLayout = React.useMemo(() => {
|
|
124
|
-
const next = {};
|
|
125
|
-
table.getVisibleLeafColumns().forEach((column) => {
|
|
126
|
-
next[column.id] = {
|
|
127
|
-
width: distributedLayout == null ? void 0 : distributedLayout.widths[column.id]
|
|
128
|
-
};
|
|
129
|
-
});
|
|
130
|
-
return next;
|
|
131
|
-
}, [table, distributedLayout]);
|
|
132
|
-
const columnItems = React.useMemo(
|
|
133
|
-
() => mapDefsToColumnItems(columns, columnVisibility, resolvedLayout),
|
|
134
|
-
[columns, columnVisibility, resolvedLayout]
|
|
135
|
-
);
|
|
136
109
|
const visibleData = table.getRowModel().rows.map((r) => r.original);
|
|
137
110
|
const { sortById, sortDirection } = getSortPropsFromSorting(uiSorting);
|
|
138
111
|
const handleSortChange = React.useCallback(
|
|
139
112
|
(column, direction) => {
|
|
140
113
|
const next = direction == null ? [] : [{ id: column.id, desc: direction === "desc" }];
|
|
141
114
|
if (optimisticSortingUi) setUiSorting(next);
|
|
115
|
+
resetPage();
|
|
142
116
|
onSortingChange == null ? void 0 : onSortingChange(next);
|
|
143
117
|
},
|
|
144
|
-
[optimisticSortingUi, onSortingChange]
|
|
118
|
+
[optimisticSortingUi, setUiSorting, resetPage, onSortingChange]
|
|
145
119
|
);
|
|
146
|
-
const headerExtras =
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const canResize = (_c = (_b = (_a = header.column).getCanResize) == null ? void 0 : _b.call(_a)) != null ? _c : false;
|
|
154
|
-
const handler = (_d = header.getResizeHandler) == null ? void 0 : _d.call(header);
|
|
155
|
-
if (!canResize || !handler) return null;
|
|
156
|
-
return /* @__PURE__ */ jsx(ColumnResizer, { id: header.column.id, handler });
|
|
157
|
-
},
|
|
158
|
-
[table]
|
|
159
|
-
);
|
|
160
|
-
const headerActions = headerActionsProp != null || settings ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
161
|
-
headerActionsProp,
|
|
162
|
-
settings ? /* @__PURE__ */ jsx(
|
|
163
|
-
TableHeaderSettings,
|
|
164
|
-
{
|
|
165
|
-
settings,
|
|
166
|
-
options: settingsOptions,
|
|
167
|
-
columns
|
|
168
|
-
}
|
|
169
|
-
) : null
|
|
170
|
-
] }) : void 0;
|
|
120
|
+
const headerExtras = useResizeHeaderExtras({
|
|
121
|
+
table,
|
|
122
|
+
widths: distributedLayout == null ? void 0 : distributedLayout.widths,
|
|
123
|
+
actionReservePx,
|
|
124
|
+
neighborResizeRef,
|
|
125
|
+
setColumnSizing
|
|
126
|
+
});
|
|
171
127
|
return /* @__PURE__ */ jsx(
|
|
172
128
|
Table,
|
|
173
129
|
{
|
|
174
130
|
...tableProps,
|
|
175
|
-
viewMode:
|
|
131
|
+
viewMode: resolvedViewMode,
|
|
176
132
|
striped: striped != null ? striped : settings == null ? void 0 : settings.striped,
|
|
177
|
-
headerActions,
|
|
133
|
+
headerActions: headerActionsProp,
|
|
134
|
+
settings,
|
|
135
|
+
settingsOptions,
|
|
136
|
+
settingsColumns: columns,
|
|
178
137
|
tableRootRef: containerRef,
|
|
179
138
|
onSortChange: handleSortChange,
|
|
139
|
+
...pagination.tableProps,
|
|
180
140
|
dataKey,
|
|
181
141
|
data: visibleData,
|
|
182
142
|
columns: columnItems,
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var table_utils = require('./table.utils');
|
|
4
|
+
|
|
5
|
+
const DEFAULT_MIN_COLUMN_PX = 80;
|
|
6
|
+
function toIntegerTrackWidths(tracks, targetWidth) {
|
|
7
|
+
const floored = tracks.map((track) => ({
|
|
8
|
+
id: track.id,
|
|
9
|
+
width: Math.floor(track.width),
|
|
10
|
+
fraction: track.width - Math.floor(track.width)
|
|
11
|
+
}));
|
|
12
|
+
const baseTotal = floored.reduce((sum, track) => sum + track.width, 0);
|
|
13
|
+
let remainder = Math.max(0, targetWidth - baseTotal);
|
|
14
|
+
floored.slice().sort((a, b) => b.fraction - a.fraction).forEach((track) => {
|
|
15
|
+
if (remainder <= 0) return;
|
|
16
|
+
track.width += 1;
|
|
17
|
+
remainder -= 1;
|
|
18
|
+
});
|
|
19
|
+
return Object.fromEntries(floored.map((track) => [track.id, track.width]));
|
|
20
|
+
}
|
|
21
|
+
function distributeColumnWidths(args) {
|
|
22
|
+
const {
|
|
23
|
+
hasSelection,
|
|
24
|
+
hasContextMenu = false,
|
|
25
|
+
contextMenuReservePx = table_utils.ROW_ACTIONS_RESERVE_PX,
|
|
26
|
+
availableWidth
|
|
27
|
+
} = args;
|
|
28
|
+
const selectionWidth = hasSelection ? table_utils.SELECTION_COLUMN_PX : 0;
|
|
29
|
+
const tracks = args.tracks.map((track) => {
|
|
30
|
+
const min = Math.max(1, track.min);
|
|
31
|
+
const max = track.max != null ? Math.max(min, track.max) : void 0;
|
|
32
|
+
if (track.fixedWidth != null) {
|
|
33
|
+
return {
|
|
34
|
+
id: track.id,
|
|
35
|
+
width: track.fixedWidth,
|
|
36
|
+
weight: 0,
|
|
37
|
+
min,
|
|
38
|
+
max: track.fixedWidth,
|
|
39
|
+
fixed: true
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
id: track.id,
|
|
44
|
+
width: min,
|
|
45
|
+
weight: Number.isFinite(track.weight) && track.weight > 0 ? track.weight : 1,
|
|
46
|
+
min,
|
|
47
|
+
max,
|
|
48
|
+
fixed: false
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
const lastTrack = tracks[tracks.length - 1];
|
|
52
|
+
if (hasContextMenu && lastTrack && !lastTrack.fixed) {
|
|
53
|
+
lastTrack.width += contextMenuReservePx;
|
|
54
|
+
lastTrack.min += contextMenuReservePx;
|
|
55
|
+
if (lastTrack.max != null) lastTrack.max += contextMenuReservePx;
|
|
56
|
+
}
|
|
57
|
+
const fixedWidth = selectionWidth + tracks.reduce((sum, track) => sum + track.width, 0);
|
|
58
|
+
let remaining = Math.max(0, availableWidth - fixedWidth);
|
|
59
|
+
let active = tracks.filter(
|
|
60
|
+
(track) => !track.fixed && (track.max == null || track.width < track.max)
|
|
61
|
+
);
|
|
62
|
+
while (remaining > 0.5 && active.length > 0) {
|
|
63
|
+
const totalWeight = active.reduce((sum, track) => sum + track.weight, 0);
|
|
64
|
+
if (totalWeight <= 0) break;
|
|
65
|
+
let consumed = 0;
|
|
66
|
+
const nextActive = [];
|
|
67
|
+
for (const track of active) {
|
|
68
|
+
const share = remaining * track.weight / totalWeight;
|
|
69
|
+
const maxGrow = track.max == null ? share : Math.max(0, track.max - track.width);
|
|
70
|
+
const growth = Math.min(share, maxGrow);
|
|
71
|
+
track.width += growth;
|
|
72
|
+
consumed += growth;
|
|
73
|
+
if (track.max == null || track.width < track.max - 0.5) {
|
|
74
|
+
nextActive.push(track);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (consumed <= 0.5) break;
|
|
78
|
+
remaining -= consumed;
|
|
79
|
+
active = nextActive;
|
|
80
|
+
}
|
|
81
|
+
const flexible = tracks.filter((track) => !track.fixed);
|
|
82
|
+
if (remaining > 0.5 && flexible.length > 0 && flexible.every((track) => track.max != null)) {
|
|
83
|
+
const stretchable = flexible.filter((track) => track.max > track.min);
|
|
84
|
+
const totalWeight = stretchable.reduce((sum, track) => sum + track.weight, 0);
|
|
85
|
+
if (totalWeight > 0) {
|
|
86
|
+
for (const track of stretchable) {
|
|
87
|
+
track.width += remaining * track.weight / totalWeight;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (tracks.length > 0 && flexible.length === 0) {
|
|
92
|
+
const target = availableWidth - selectionWidth;
|
|
93
|
+
const minOf = (track) => track.min + (hasContextMenu && track === lastTrack ? contextMenuReservePx : 0);
|
|
94
|
+
let scalable = tracks;
|
|
95
|
+
while (scalable.length > 0) {
|
|
96
|
+
const frozenWidth = tracks.filter((track) => !scalable.includes(track)).reduce((sum, track) => sum + track.width, 0);
|
|
97
|
+
const scalableWidth = scalable.reduce((sum, track) => sum + track.width, 0);
|
|
98
|
+
const factor = (target - frozenWidth) / scalableWidth;
|
|
99
|
+
const belowMin = scalable.filter((track) => track.width * factor < minOf(track));
|
|
100
|
+
if (belowMin.length === 0) {
|
|
101
|
+
for (const track of scalable) track.width *= factor;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
for (const track of belowMin) track.width = minOf(track);
|
|
105
|
+
scalable = scalable.filter((track) => !belowMin.includes(track));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const floatTrackTotal = tracks.reduce((sum, track) => sum + track.width, 0);
|
|
109
|
+
const targetTrackWidth = Math.min(
|
|
110
|
+
Math.floor(floatTrackTotal + 1e-6),
|
|
111
|
+
availableWidth - selectionWidth
|
|
112
|
+
);
|
|
113
|
+
const widths = toIntegerTrackWidths(tracks, targetTrackWidth);
|
|
114
|
+
const totalWidth = selectionWidth + Object.values(widths).reduce((sum, width) => sum + width, 0);
|
|
115
|
+
return {
|
|
116
|
+
selectionWidth: hasSelection ? table_utils.SELECTION_COLUMN_PX : void 0,
|
|
117
|
+
widths,
|
|
118
|
+
totalWidth,
|
|
119
|
+
availableWidth,
|
|
120
|
+
shouldOverflow: totalWidth > availableWidth
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function usesDistributedWidths(columns) {
|
|
124
|
+
return columns.some(
|
|
125
|
+
(column) => column.minWidth != null || column.maxWidth != null || column.weight != null
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
function buildColumnTracks(columns) {
|
|
129
|
+
return columns.map((column) => {
|
|
130
|
+
var _a, _b;
|
|
131
|
+
if (typeof column.width === "number") {
|
|
132
|
+
return { id: column.id, min: column.width, max: column.width, weight: 1 };
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
id: column.id,
|
|
136
|
+
min: (_a = column.minWidth) != null ? _a : DEFAULT_MIN_COLUMN_PX,
|
|
137
|
+
max: column.maxWidth,
|
|
138
|
+
weight: (_b = column.weight) != null ? _b : 1
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
exports.DEFAULT_MIN_COLUMN_PX = DEFAULT_MIN_COLUMN_PX;
|
|
144
|
+
exports.buildColumnTracks = buildColumnTracks;
|
|
145
|
+
exports.distributeColumnWidths = distributeColumnWidths;
|
|
146
|
+
exports.usesDistributedWidths = usesDistributedWidths;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ColumnItem } from './Table.types';
|
|
2
|
+
/** Minimum width of a flexible column that doesn't set `minWidth`. */
|
|
3
|
+
export declare const DEFAULT_MIN_COLUMN_PX: 80;
|
|
4
|
+
/**
|
|
5
|
+
* Sizing constraints for one column, as input to `distributeColumnWidths`.
|
|
6
|
+
* A track grows from `min` towards `max` by its share of `weight`; a track
|
|
7
|
+
* with `fixedWidth` (e.g. resized by the user) keeps exactly that width.
|
|
8
|
+
*/
|
|
9
|
+
export type ColumnTrack = {
|
|
10
|
+
id: string;
|
|
11
|
+
min: number;
|
|
12
|
+
max?: number;
|
|
13
|
+
weight: number;
|
|
14
|
+
fixedWidth?: number;
|
|
15
|
+
};
|
|
16
|
+
export type DistributedColumnWidths = {
|
|
17
|
+
selectionWidth?: number;
|
|
18
|
+
widths: Record<string, number>;
|
|
19
|
+
totalWidth: number;
|
|
20
|
+
availableWidth: number;
|
|
21
|
+
shouldOverflow: boolean;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Spreads `availableWidth` over the tracks: every track starts at its `min`,
|
|
25
|
+
* then the remaining space is shared by `weight` until each track hits its
|
|
26
|
+
* `max`. Fixed tracks keep their width. If the minimums don't fit, the result
|
|
27
|
+
* is wider than `availableWidth` and the table scrolls horizontally.
|
|
28
|
+
*/
|
|
29
|
+
export declare function distributeColumnWidths(args: {
|
|
30
|
+
tracks: ReadonlyArray<ColumnTrack>;
|
|
31
|
+
hasSelection: boolean;
|
|
32
|
+
hasContextMenu?: boolean;
|
|
33
|
+
contextMenuReservePx?: number;
|
|
34
|
+
availableWidth: number;
|
|
35
|
+
}): DistributedColumnWidths;
|
|
36
|
+
/** True when any column opts into distributed sizing via `minWidth`, `maxWidth` or `weight`. */
|
|
37
|
+
export declare function usesDistributedWidths<T>(columns: ReadonlyArray<ColumnItem<T>>): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Maps Table columns to tracks. A numeric `width` pins the column
|
|
40
|
+
* (min = max = width); other columns flex between `minWidth` (default
|
|
41
|
+
* `DEFAULT_MIN_COLUMN_PX`) and `maxWidth`, sharing leftover space by
|
|
42
|
+
* `weight` (default 1).
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildColumnTracks<T>(columns: ReadonlyArray<ColumnItem<T>>): ColumnTrack[];
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { ROW_ACTIONS_RESERVE_PX, SELECTION_COLUMN_PX } from './table.utils';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_MIN_COLUMN_PX = 80;
|
|
4
|
+
function toIntegerTrackWidths(tracks, targetWidth) {
|
|
5
|
+
const floored = tracks.map((track) => ({
|
|
6
|
+
id: track.id,
|
|
7
|
+
width: Math.floor(track.width),
|
|
8
|
+
fraction: track.width - Math.floor(track.width)
|
|
9
|
+
}));
|
|
10
|
+
const baseTotal = floored.reduce((sum, track) => sum + track.width, 0);
|
|
11
|
+
let remainder = Math.max(0, targetWidth - baseTotal);
|
|
12
|
+
floored.slice().sort((a, b) => b.fraction - a.fraction).forEach((track) => {
|
|
13
|
+
if (remainder <= 0) return;
|
|
14
|
+
track.width += 1;
|
|
15
|
+
remainder -= 1;
|
|
16
|
+
});
|
|
17
|
+
return Object.fromEntries(floored.map((track) => [track.id, track.width]));
|
|
18
|
+
}
|
|
19
|
+
function distributeColumnWidths(args) {
|
|
20
|
+
const {
|
|
21
|
+
hasSelection,
|
|
22
|
+
hasContextMenu = false,
|
|
23
|
+
contextMenuReservePx = ROW_ACTIONS_RESERVE_PX,
|
|
24
|
+
availableWidth
|
|
25
|
+
} = args;
|
|
26
|
+
const selectionWidth = hasSelection ? SELECTION_COLUMN_PX : 0;
|
|
27
|
+
const tracks = args.tracks.map((track) => {
|
|
28
|
+
const min = Math.max(1, track.min);
|
|
29
|
+
const max = track.max != null ? Math.max(min, track.max) : void 0;
|
|
30
|
+
if (track.fixedWidth != null) {
|
|
31
|
+
return {
|
|
32
|
+
id: track.id,
|
|
33
|
+
width: track.fixedWidth,
|
|
34
|
+
weight: 0,
|
|
35
|
+
min,
|
|
36
|
+
max: track.fixedWidth,
|
|
37
|
+
fixed: true
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
id: track.id,
|
|
42
|
+
width: min,
|
|
43
|
+
weight: Number.isFinite(track.weight) && track.weight > 0 ? track.weight : 1,
|
|
44
|
+
min,
|
|
45
|
+
max,
|
|
46
|
+
fixed: false
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
const lastTrack = tracks[tracks.length - 1];
|
|
50
|
+
if (hasContextMenu && lastTrack && !lastTrack.fixed) {
|
|
51
|
+
lastTrack.width += contextMenuReservePx;
|
|
52
|
+
lastTrack.min += contextMenuReservePx;
|
|
53
|
+
if (lastTrack.max != null) lastTrack.max += contextMenuReservePx;
|
|
54
|
+
}
|
|
55
|
+
const fixedWidth = selectionWidth + tracks.reduce((sum, track) => sum + track.width, 0);
|
|
56
|
+
let remaining = Math.max(0, availableWidth - fixedWidth);
|
|
57
|
+
let active = tracks.filter(
|
|
58
|
+
(track) => !track.fixed && (track.max == null || track.width < track.max)
|
|
59
|
+
);
|
|
60
|
+
while (remaining > 0.5 && active.length > 0) {
|
|
61
|
+
const totalWeight = active.reduce((sum, track) => sum + track.weight, 0);
|
|
62
|
+
if (totalWeight <= 0) break;
|
|
63
|
+
let consumed = 0;
|
|
64
|
+
const nextActive = [];
|
|
65
|
+
for (const track of active) {
|
|
66
|
+
const share = remaining * track.weight / totalWeight;
|
|
67
|
+
const maxGrow = track.max == null ? share : Math.max(0, track.max - track.width);
|
|
68
|
+
const growth = Math.min(share, maxGrow);
|
|
69
|
+
track.width += growth;
|
|
70
|
+
consumed += growth;
|
|
71
|
+
if (track.max == null || track.width < track.max - 0.5) {
|
|
72
|
+
nextActive.push(track);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (consumed <= 0.5) break;
|
|
76
|
+
remaining -= consumed;
|
|
77
|
+
active = nextActive;
|
|
78
|
+
}
|
|
79
|
+
const flexible = tracks.filter((track) => !track.fixed);
|
|
80
|
+
if (remaining > 0.5 && flexible.length > 0 && flexible.every((track) => track.max != null)) {
|
|
81
|
+
const stretchable = flexible.filter((track) => track.max > track.min);
|
|
82
|
+
const totalWeight = stretchable.reduce((sum, track) => sum + track.weight, 0);
|
|
83
|
+
if (totalWeight > 0) {
|
|
84
|
+
for (const track of stretchable) {
|
|
85
|
+
track.width += remaining * track.weight / totalWeight;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (tracks.length > 0 && flexible.length === 0) {
|
|
90
|
+
const target = availableWidth - selectionWidth;
|
|
91
|
+
const minOf = (track) => track.min + (hasContextMenu && track === lastTrack ? contextMenuReservePx : 0);
|
|
92
|
+
let scalable = tracks;
|
|
93
|
+
while (scalable.length > 0) {
|
|
94
|
+
const frozenWidth = tracks.filter((track) => !scalable.includes(track)).reduce((sum, track) => sum + track.width, 0);
|
|
95
|
+
const scalableWidth = scalable.reduce((sum, track) => sum + track.width, 0);
|
|
96
|
+
const factor = (target - frozenWidth) / scalableWidth;
|
|
97
|
+
const belowMin = scalable.filter((track) => track.width * factor < minOf(track));
|
|
98
|
+
if (belowMin.length === 0) {
|
|
99
|
+
for (const track of scalable) track.width *= factor;
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
for (const track of belowMin) track.width = minOf(track);
|
|
103
|
+
scalable = scalable.filter((track) => !belowMin.includes(track));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const floatTrackTotal = tracks.reduce((sum, track) => sum + track.width, 0);
|
|
107
|
+
const targetTrackWidth = Math.min(
|
|
108
|
+
Math.floor(floatTrackTotal + 1e-6),
|
|
109
|
+
availableWidth - selectionWidth
|
|
110
|
+
);
|
|
111
|
+
const widths = toIntegerTrackWidths(tracks, targetTrackWidth);
|
|
112
|
+
const totalWidth = selectionWidth + Object.values(widths).reduce((sum, width) => sum + width, 0);
|
|
113
|
+
return {
|
|
114
|
+
selectionWidth: hasSelection ? SELECTION_COLUMN_PX : void 0,
|
|
115
|
+
widths,
|
|
116
|
+
totalWidth,
|
|
117
|
+
availableWidth,
|
|
118
|
+
shouldOverflow: totalWidth > availableWidth
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function usesDistributedWidths(columns) {
|
|
122
|
+
return columns.some(
|
|
123
|
+
(column) => column.minWidth != null || column.maxWidth != null || column.weight != null
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
function buildColumnTracks(columns) {
|
|
127
|
+
return columns.map((column) => {
|
|
128
|
+
var _a, _b;
|
|
129
|
+
if (typeof column.width === "number") {
|
|
130
|
+
return { id: column.id, min: column.width, max: column.width, weight: 1 };
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
id: column.id,
|
|
134
|
+
min: (_a = column.minWidth) != null ? _a : DEFAULT_MIN_COLUMN_PX,
|
|
135
|
+
max: column.maxWidth,
|
|
136
|
+
weight: (_b = column.weight) != null ? _b : 1
|
|
137
|
+
};
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { DEFAULT_MIN_COLUMN_PX, buildColumnTracks, distributeColumnWidths, usesDistributedWidths };
|
|
@@ -21,7 +21,8 @@ function TableHeader({
|
|
|
21
21
|
onSortChange,
|
|
22
22
|
headerExtras,
|
|
23
23
|
stickyTop,
|
|
24
|
-
headerActions
|
|
24
|
+
headerActions,
|
|
25
|
+
compactHeaderActionReserve = false
|
|
25
26
|
}) {
|
|
26
27
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27
28
|
"thead",
|
|
@@ -45,6 +46,7 @@ function TableHeader({
|
|
|
45
46
|
column,
|
|
46
47
|
index,
|
|
47
48
|
reserveInlineEnd: (hasRowContextMenu || headerActions != null) && index === columns.length - 1,
|
|
49
|
+
compactHeaderActionReserve,
|
|
48
50
|
endAction: index === columns.length - 1 ? headerActions : void 0,
|
|
49
51
|
sortById,
|
|
50
52
|
sortDirection,
|
|
@@ -13,6 +13,7 @@ type Props<T> = {
|
|
|
13
13
|
headerExtras?: (args: HeaderExtrasArgs<T>) => ReactNode;
|
|
14
14
|
stickyTop?: string;
|
|
15
15
|
headerActions?: ReactNode;
|
|
16
|
+
compactHeaderActionReserve?: boolean;
|
|
16
17
|
};
|
|
17
|
-
export declare function TableHeader<T>({ columns, hasSelection, selectionMode, hasRowContextMenu, allRowsSelected, onSelectAllRows, sortById, sortDirection, onSortChange, headerExtras, stickyTop, headerActions, }: Props<T>): React.ReactNode;
|
|
18
|
+
export declare function TableHeader<T>({ columns, hasSelection, selectionMode, hasRowContextMenu, allRowsSelected, onSelectAllRows, sortById, sortDirection, onSortChange, headerExtras, stickyTop, headerActions, compactHeaderActionReserve, }: Props<T>): React.ReactNode;
|
|
18
19
|
export {};
|
|
@@ -15,7 +15,8 @@ function TableHeader({
|
|
|
15
15
|
onSortChange,
|
|
16
16
|
headerExtras,
|
|
17
17
|
stickyTop,
|
|
18
|
-
headerActions
|
|
18
|
+
headerActions,
|
|
19
|
+
compactHeaderActionReserve = false
|
|
19
20
|
}) {
|
|
20
21
|
return /* @__PURE__ */ jsx(
|
|
21
22
|
"thead",
|
|
@@ -39,6 +40,7 @@ function TableHeader({
|
|
|
39
40
|
column,
|
|
40
41
|
index,
|
|
41
42
|
reserveInlineEnd: (hasRowContextMenu || headerActions != null) && index === columns.length - 1,
|
|
43
|
+
compactHeaderActionReserve,
|
|
42
44
|
endAction: index === columns.length - 1 ? headerActions : void 0,
|
|
43
45
|
sortById,
|
|
44
46
|
sortDirection,
|