@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.
Files changed (68) hide show
  1. package/dist/components/json-viewer/JsonViewer.module.css +53 -0
  2. package/dist/components/json-viewer/JsonViewerShell.cjs +147 -143
  3. package/dist/components/json-viewer/JsonViewerShell.js +149 -145
  4. package/dist/components/line-viewer/LineViewer.cjs +15 -21
  5. package/dist/components/line-viewer/LineViewer.d.ts +1 -1
  6. package/dist/components/line-viewer/LineViewer.js +16 -22
  7. package/dist/components/line-viewer/LineViewer.module.css +58 -3
  8. package/dist/components/page-layout/PageLayout.module.css +1 -1
  9. package/dist/components/scroll-fade/ScrollFade.cjs +42 -0
  10. package/dist/components/scroll-fade/ScrollFade.d.ts +18 -0
  11. package/dist/components/scroll-fade/ScrollFade.js +36 -0
  12. package/dist/components/scroll-fade/ScrollFade.module.css +71 -0
  13. package/dist/components/search-box/SearchBox.cjs +39 -35
  14. package/dist/components/search-box/SearchBox.d.ts +2 -0
  15. package/dist/components/search-box/SearchBox.js +39 -35
  16. package/dist/components/table/Table.cjs +52 -23
  17. package/dist/components/table/Table.d.ts +1 -1
  18. package/dist/components/table/Table.js +53 -24
  19. package/dist/components/table/Table.module.css +4 -0
  20. package/dist/components/table/Table.types.d.ts +27 -0
  21. package/dist/components/table/TanstackTable.cjs +63 -106
  22. package/dist/components/table/TanstackTable.d.ts +5 -0
  23. package/dist/components/table/TanstackTable.js +66 -106
  24. package/dist/components/table/columnLayout.utils.cjs +146 -0
  25. package/dist/components/table/columnLayout.utils.d.ts +44 -0
  26. package/dist/components/table/columnLayout.utils.js +141 -0
  27. package/dist/components/table/components/TableHeader.cjs +3 -1
  28. package/dist/components/table/components/TableHeader.d.ts +2 -1
  29. package/dist/components/table/components/TableHeader.js +3 -1
  30. package/dist/components/table/components/TableHeaderCell.cjs +29 -19
  31. package/dist/components/table/components/TableHeaderCell.d.ts +2 -1
  32. package/dist/components/table/components/TableHeaderCell.js +29 -19
  33. package/dist/components/table/hooks/useClientPagination.cjs +66 -0
  34. package/dist/components/table/hooks/useClientPagination.d.ts +32 -0
  35. package/dist/components/table/hooks/useClientPagination.js +64 -0
  36. package/dist/components/table/hooks/useDistributedLayout.cjs +44 -0
  37. package/dist/components/table/hooks/useDistributedLayout.d.ts +16 -0
  38. package/dist/components/table/hooks/useDistributedLayout.js +42 -0
  39. package/dist/components/table/hooks/useElementWidth.cjs +40 -0
  40. package/dist/components/table/hooks/useElementWidth.d.ts +7 -0
  41. package/dist/components/table/hooks/useElementWidth.js +38 -0
  42. package/dist/components/table/hooks/useResizeHeaderExtras.cjs +87 -0
  43. package/dist/components/table/hooks/useResizeHeaderExtras.d.ts +17 -0
  44. package/dist/components/table/hooks/useResizeHeaderExtras.js +62 -0
  45. package/dist/components/table/hooks/useUiSorting.cjs +18 -0
  46. package/dist/components/table/hooks/useUiSorting.d.ts +3 -0
  47. package/dist/components/table/hooks/useUiSorting.js +16 -0
  48. package/dist/components/table/table.utils.cjs +24 -2
  49. package/dist/components/table/table.utils.d.ts +40 -2
  50. package/dist/components/table/table.utils.js +20 -2
  51. package/dist/components/table/tanstackTable.utils.cjs +33 -97
  52. package/dist/components/table/tanstackTable.utils.d.ts +24 -8
  53. package/dist/components/table/tanstackTable.utils.js +34 -99
  54. package/dist/components/xml-viewer/XmlViewer.cjs +15 -21
  55. package/dist/components/xml-viewer/XmlViewer.d.ts +1 -1
  56. package/dist/components/xml-viewer/XmlViewer.js +16 -22
  57. package/dist/components/xml-viewer/XmlViewer.module.css +58 -3
  58. package/dist/hooks/useScrollOverflow.cjs +71 -0
  59. package/dist/hooks/useScrollOverflow.d.ts +23 -0
  60. package/dist/hooks/useScrollOverflow.js +69 -0
  61. package/dist/hooks/useTableSettings.cjs +2 -1
  62. package/dist/hooks/useTableSettings.d.ts +1 -0
  63. package/dist/hooks/useTableSettings.js +2 -1
  64. package/dist/index.css +1 -0
  65. package/dist/utils/refs.utils.cjs +13 -0
  66. package/dist/utils/refs.utils.d.ts +7 -0
  67. package/dist/utils/refs.utils.js +11 -0
  68. package/package.json +1 -1
@@ -1,14 +1,18 @@
1
1
  'use client';
2
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
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 ColumnResizer from './components/column-resizer/ColumnResizer';
6
- import { TableHeaderSettings } from './components/table-settings/TableHeaderSettings';
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 { sortingEqual, buildColumnVisibilityFromVisibleIds, buildDistributedColumnWidths, mapDefsToColumnItems, getSortPropsFromSorting } from './tanstackTable.utils';
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 isControlledSorting = controlledSorting != null;
32
- const [uiSorting, setUiSorting] = React.useState(controlledSorting != null ? controlledSorting : []);
33
- React.useEffect(() => {
34
- if (!isControlledSorting) return;
35
- if (sortingEqual(uiSorting, controlledSorting)) return;
36
- setUiSorting(controlledSorting);
37
- }, [isControlledSorting, controlledSorting, uiSorting]);
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 [availableWidth, setAvailableWidth] = React.useState(void 0);
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: setColumnSizing,
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
- React.useLayoutEffect(() => {
71
- const el = containerRef.current;
72
- if (!el) return;
73
- const updateWidth = () => {
74
- const next = el.clientWidth;
75
- setAvailableWidth(next > 0 ? next : void 0);
76
- };
77
- updateWidth();
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
- selectedRows,
113
- onRowSelect,
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 = React.useCallback(
147
- ({ index }) => {
148
- var _a, _b, _c, _d;
149
- const headerGroups = table.getHeaderGroups();
150
- const leafHeaders = headerGroups.length > 0 ? headerGroups[headerGroups.length - 1].headers : [];
151
- const header = leafHeaders[index];
152
- if (!header) return null;
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: viewMode != null ? viewMode : settings == null ? void 0 : settings.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,