@dbcdk/react-components 0.0.197 → 0.0.198

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 (55) hide show
  1. package/dist/components/json-viewer/JsonViewer.module.css +52 -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 -10
  5. package/dist/components/line-viewer/LineViewer.d.ts +1 -1
  6. package/dist/components/line-viewer/LineViewer.js +15 -10
  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 +64 -64
  22. package/dist/components/table/TanstackTable.js +67 -67
  23. package/dist/components/table/columnLayout.utils.cjs +146 -0
  24. package/dist/components/table/columnLayout.utils.d.ts +44 -0
  25. package/dist/components/table/columnLayout.utils.js +141 -0
  26. package/dist/components/table/components/TableHeader.cjs +3 -1
  27. package/dist/components/table/components/TableHeader.d.ts +2 -1
  28. package/dist/components/table/components/TableHeader.js +3 -1
  29. package/dist/components/table/components/TableHeaderCell.cjs +29 -19
  30. package/dist/components/table/components/TableHeaderCell.d.ts +2 -1
  31. package/dist/components/table/components/TableHeaderCell.js +29 -19
  32. package/dist/components/table/hooks/useElementWidth.cjs +40 -0
  33. package/dist/components/table/hooks/useElementWidth.d.ts +7 -0
  34. package/dist/components/table/hooks/useElementWidth.js +38 -0
  35. package/dist/components/table/table.utils.cjs +24 -2
  36. package/dist/components/table/table.utils.d.ts +40 -2
  37. package/dist/components/table/table.utils.js +20 -2
  38. package/dist/components/table/tanstackTable.utils.cjs +33 -97
  39. package/dist/components/table/tanstackTable.utils.d.ts +24 -8
  40. package/dist/components/table/tanstackTable.utils.js +34 -99
  41. package/dist/components/xml-viewer/XmlViewer.cjs +15 -10
  42. package/dist/components/xml-viewer/XmlViewer.d.ts +1 -1
  43. package/dist/components/xml-viewer/XmlViewer.js +15 -10
  44. package/dist/components/xml-viewer/XmlViewer.module.css +58 -3
  45. package/dist/hooks/useScrollOverflow.cjs +71 -0
  46. package/dist/hooks/useScrollOverflow.d.ts +23 -0
  47. package/dist/hooks/useScrollOverflow.js +69 -0
  48. package/dist/hooks/useTableSettings.cjs +2 -1
  49. package/dist/hooks/useTableSettings.d.ts +1 -0
  50. package/dist/hooks/useTableSettings.js +2 -1
  51. package/dist/index.css +1 -0
  52. package/dist/utils/refs.utils.cjs +13 -0
  53. package/dist/utils/refs.utils.d.ts +7 -0
  54. package/dist/utils/refs.utils.js +11 -0
  55. package/package.json +1 -1
@@ -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,
@@ -14,6 +14,7 @@ function TableHeaderCell({
14
14
  column,
15
15
  index,
16
16
  reserveInlineEnd = false,
17
+ compactHeaderActionReserve = false,
17
18
  sortById,
18
19
  sortDirection,
19
20
  onSortChange,
@@ -39,27 +40,36 @@ function TableHeaderCell({
39
40
  "data-divider": column.divider,
40
41
  "data-column-index": index,
41
42
  children: [
42
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: alignClasses.inner, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: table_classes.cx(alignClasses.main, reserveInlineEnd && styles__default.default.thMainWithActionsReserve), children: column.sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
43
- "button",
43
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: alignClasses.inner, children: /* @__PURE__ */ jsxRuntime.jsx(
44
+ "div",
44
45
  {
45
- type: "button",
46
- className: alignClasses.button,
47
- onClick: handleToggleSort,
48
- onKeyDown: (e) => {
49
- if (!table_utils.shouldToggleOnKey(e.key)) return;
50
- e.preventDefault();
51
- handleToggleSort();
52
- },
53
- children: [
54
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: alignClasses.label, children: table_utils.getHeaderLabel(column.header) }),
55
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.sortIndicator, "aria-hidden": "true", children: [
56
- active && sortDirection === "asc" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: styles__default.default.activeSort }),
57
- active && sortDirection === "desc" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: styles__default.default.activeSort }),
58
- !active && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: styles__default.default.inActiveSort })
59
- ] })
60
- ]
46
+ className: table_classes.cx(
47
+ alignClasses.main,
48
+ reserveInlineEnd && (compactHeaderActionReserve ? styles__default.default.thMainWithHeaderActionsReserve : styles__default.default.thMainWithActionsReserve)
49
+ ),
50
+ children: column.sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
51
+ "button",
52
+ {
53
+ type: "button",
54
+ className: alignClasses.button,
55
+ onClick: handleToggleSort,
56
+ onKeyDown: (e) => {
57
+ if (!table_utils.shouldToggleOnKey(e.key)) return;
58
+ e.preventDefault();
59
+ handleToggleSort();
60
+ },
61
+ children: [
62
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: alignClasses.label, children: table_utils.getHeaderLabel(column.header) }),
63
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: styles__default.default.sortIndicator, "aria-hidden": "true", children: [
64
+ active && sortDirection === "asc" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: styles__default.default.activeSort }),
65
+ active && sortDirection === "desc" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: styles__default.default.activeSort }),
66
+ !active && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: styles__default.default.inActiveSort })
67
+ ] })
68
+ ]
69
+ }
70
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: alignClasses.label, children: table_utils.getHeaderLabel(column.header) })
61
71
  }
62
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: alignClasses.label, children: table_utils.getHeaderLabel(column.header) }) }) }),
72
+ ) }),
63
73
  extraContent != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.thOverlayExtras, children: extraContent }) : null,
64
74
  endAction != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.thEndAction, children: endAction }) : null
65
75
  ]
@@ -4,6 +4,7 @@ type Props<T> = {
4
4
  column: ColumnItem<T>;
5
5
  index: number;
6
6
  reserveInlineEnd?: boolean;
7
+ compactHeaderActionReserve?: boolean;
7
8
  sortById?: string;
8
9
  sortDirection?: SortDirection;
9
10
  onSortChange?: (column: ColumnItem<T>, direction: SortDirection) => void;
@@ -11,5 +12,5 @@ type Props<T> = {
11
12
  /** Rendered at the cell's inline end, in the space kept free by `reserveInlineEnd`. */
12
13
  endAction?: ReactNode;
13
14
  };
14
- export declare function TableHeaderCell<T>({ column, index, reserveInlineEnd, sortById, sortDirection, onSortChange, extraContent, endAction, }: Props<T>): ReactNode;
15
+ export declare function TableHeaderCell<T>({ column, index, reserveInlineEnd, compactHeaderActionReserve, sortById, sortDirection, onSortChange, extraContent, endAction, }: Props<T>): ReactNode;
15
16
  export {};
@@ -8,6 +8,7 @@ function TableHeaderCell({
8
8
  column,
9
9
  index,
10
10
  reserveInlineEnd = false,
11
+ compactHeaderActionReserve = false,
11
12
  sortById,
12
13
  sortDirection,
13
14
  onSortChange,
@@ -33,27 +34,36 @@ function TableHeaderCell({
33
34
  "data-divider": column.divider,
34
35
  "data-column-index": index,
35
36
  children: [
36
- /* @__PURE__ */ jsx("div", { className: alignClasses.inner, children: /* @__PURE__ */ jsx("div", { className: cx(alignClasses.main, reserveInlineEnd && styles.thMainWithActionsReserve), children: column.sortable ? /* @__PURE__ */ jsxs(
37
- "button",
37
+ /* @__PURE__ */ jsx("div", { className: alignClasses.inner, children: /* @__PURE__ */ jsx(
38
+ "div",
38
39
  {
39
- type: "button",
40
- className: alignClasses.button,
41
- onClick: handleToggleSort,
42
- onKeyDown: (e) => {
43
- if (!shouldToggleOnKey(e.key)) return;
44
- e.preventDefault();
45
- handleToggleSort();
46
- },
47
- children: [
48
- /* @__PURE__ */ jsx("span", { className: alignClasses.label, children: getHeaderLabel(column.header) }),
49
- /* @__PURE__ */ jsxs("span", { className: styles.sortIndicator, "aria-hidden": "true", children: [
50
- active && sortDirection === "asc" && /* @__PURE__ */ jsx(ArrowUp, { className: styles.activeSort }),
51
- active && sortDirection === "desc" && /* @__PURE__ */ jsx(ArrowDown, { className: styles.activeSort }),
52
- !active && /* @__PURE__ */ jsx(ArrowDown, { className: styles.inActiveSort })
53
- ] })
54
- ]
40
+ className: cx(
41
+ alignClasses.main,
42
+ reserveInlineEnd && (compactHeaderActionReserve ? styles.thMainWithHeaderActionsReserve : styles.thMainWithActionsReserve)
43
+ ),
44
+ children: column.sortable ? /* @__PURE__ */ jsxs(
45
+ "button",
46
+ {
47
+ type: "button",
48
+ className: alignClasses.button,
49
+ onClick: handleToggleSort,
50
+ onKeyDown: (e) => {
51
+ if (!shouldToggleOnKey(e.key)) return;
52
+ e.preventDefault();
53
+ handleToggleSort();
54
+ },
55
+ children: [
56
+ /* @__PURE__ */ jsx("span", { className: alignClasses.label, children: getHeaderLabel(column.header) }),
57
+ /* @__PURE__ */ jsxs("span", { className: styles.sortIndicator, "aria-hidden": "true", children: [
58
+ active && sortDirection === "asc" && /* @__PURE__ */ jsx(ArrowUp, { className: styles.activeSort }),
59
+ active && sortDirection === "desc" && /* @__PURE__ */ jsx(ArrowDown, { className: styles.activeSort }),
60
+ !active && /* @__PURE__ */ jsx(ArrowDown, { className: styles.inActiveSort })
61
+ ] })
62
+ ]
63
+ }
64
+ ) : /* @__PURE__ */ jsx("span", { className: alignClasses.label, children: getHeaderLabel(column.header) })
55
65
  }
56
- ) : /* @__PURE__ */ jsx("span", { className: alignClasses.label, children: getHeaderLabel(column.header) }) }) }),
66
+ ) }),
57
67
  extraContent != null ? /* @__PURE__ */ jsx("div", { className: styles.thOverlayExtras, children: extraContent }) : null,
58
68
  endAction != null ? /* @__PURE__ */ jsx("div", { className: styles.thEndAction, children: endAction }) : null
59
69
  ]
@@ -0,0 +1,40 @@
1
+ 'use client';
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+
6
+ function measureContentWidth(el) {
7
+ const style = getComputedStyle(el);
8
+ const width = parseFloat(style.width);
9
+ if (!Number.isFinite(width)) return el.clientWidth;
10
+ const px = (value) => parseFloat(value) || 0;
11
+ const borders = px(style.borderLeftWidth) + px(style.borderRightWidth);
12
+ const padding = px(style.paddingLeft) + px(style.paddingRight);
13
+ const scrollbar = Math.max(0, el.offsetWidth - el.clientWidth - borders);
14
+ const borderBox = style.boxSizing === "border-box" ? width : width + padding + borders;
15
+ const widthExcludesScrollbar = el.offsetWidth - borderBox > scrollbar / 2;
16
+ const contentWidth = (style.boxSizing === "border-box" ? width - borders - padding : width) - (widthExcludesScrollbar ? 0 : scrollbar);
17
+ return Math.floor(contentWidth);
18
+ }
19
+ function useElementWidth(ref, enabled = true) {
20
+ const [width, setWidth] = react.useState(void 0);
21
+ react.useLayoutEffect(() => {
22
+ const el = ref.current;
23
+ if (!enabled || !el) return;
24
+ const updateWidth = () => {
25
+ const next = measureContentWidth(el);
26
+ setWidth(next > 0 ? next : void 0);
27
+ };
28
+ updateWidth();
29
+ if (typeof ResizeObserver === "undefined") {
30
+ window.addEventListener("resize", updateWidth);
31
+ return () => window.removeEventListener("resize", updateWidth);
32
+ }
33
+ const observer = new ResizeObserver(updateWidth);
34
+ observer.observe(el);
35
+ return () => observer.disconnect();
36
+ }, [ref, enabled]);
37
+ return enabled ? width : void 0;
38
+ }
39
+
40
+ exports.useElementWidth = useElementWidth;
@@ -0,0 +1,7 @@
1
+ import type { RefObject } from 'react';
2
+ /**
3
+ * Tracks the content width of `ref`'s element. Stays `undefined` until the
4
+ * first client measurement (and while `enabled` is false), so callers can hide
5
+ * layout that depends on it instead of rendering a wrong first frame.
6
+ */
7
+ export declare function useElementWidth(ref: RefObject<HTMLElement | null>, enabled?: boolean): number | undefined;
@@ -0,0 +1,38 @@
1
+ 'use client';
2
+ import { useState, useLayoutEffect } from 'react';
3
+
4
+ function measureContentWidth(el) {
5
+ const style = getComputedStyle(el);
6
+ const width = parseFloat(style.width);
7
+ if (!Number.isFinite(width)) return el.clientWidth;
8
+ const px = (value) => parseFloat(value) || 0;
9
+ const borders = px(style.borderLeftWidth) + px(style.borderRightWidth);
10
+ const padding = px(style.paddingLeft) + px(style.paddingRight);
11
+ const scrollbar = Math.max(0, el.offsetWidth - el.clientWidth - borders);
12
+ const borderBox = style.boxSizing === "border-box" ? width : width + padding + borders;
13
+ const widthExcludesScrollbar = el.offsetWidth - borderBox > scrollbar / 2;
14
+ const contentWidth = (style.boxSizing === "border-box" ? width - borders - padding : width) - (widthExcludesScrollbar ? 0 : scrollbar);
15
+ return Math.floor(contentWidth);
16
+ }
17
+ function useElementWidth(ref, enabled = true) {
18
+ const [width, setWidth] = useState(void 0);
19
+ useLayoutEffect(() => {
20
+ const el = ref.current;
21
+ if (!enabled || !el) return;
22
+ const updateWidth = () => {
23
+ const next = measureContentWidth(el);
24
+ setWidth(next > 0 ? next : void 0);
25
+ };
26
+ updateWidth();
27
+ if (typeof ResizeObserver === "undefined") {
28
+ window.addEventListener("resize", updateWidth);
29
+ return () => window.removeEventListener("resize", updateWidth);
30
+ }
31
+ const observer = new ResizeObserver(updateWidth);
32
+ observer.observe(el);
33
+ return () => observer.disconnect();
34
+ }, [ref, enabled]);
35
+ return enabled ? width : void 0;
36
+ }
37
+
38
+ export { useElementWidth };
@@ -1,9 +1,27 @@
1
1
  'use strict';
2
2
 
3
3
  const SELECTION_COLUMN_PX = 32;
4
- const ACTIONS_COLUMN_PX = 0;
4
+ const HEADER_ACTIONS_RESERVE_PX = 20;
5
5
  const ROW_ACTIONS_RESERVE_PX = 32;
6
6
  const DEFAULT_COLUMN_PX = 150;
7
+ const DEFAULT_VIEW_MODE = "wrapped";
8
+ function showsExpandToggle(expandableRows, viewMode) {
9
+ return Boolean(expandableRows) && viewMode !== "wrapped";
10
+ }
11
+ function reservesRowActionsSpace(args) {
12
+ return args.hasRowActions || args.showHeader && args.hasHeaderActions;
13
+ }
14
+ function getActionsReserve(args) {
15
+ const { hasRowActions, hasSettings, hasOtherHeaderActions, showHeader } = args;
16
+ const reserves = reservesRowActionsSpace({
17
+ hasRowActions,
18
+ hasHeaderActions: hasSettings || hasOtherHeaderActions,
19
+ showHeader
20
+ });
21
+ if (!reserves) return { px: 0, compactHeader: false };
22
+ const compactHeader = showHeader && hasSettings && !hasOtherHeaderActions && !hasRowActions;
23
+ return { px: compactHeader ? HEADER_ACTIONS_RESERVE_PX : ROW_ACTIONS_RESERVE_PX, compactHeader };
24
+ }
7
25
  function getVisibleColumns(columns) {
8
26
  return columns.filter((column) => !column.hidden);
9
27
  }
@@ -46,10 +64,12 @@ function getCellDisplayValue(row, column) {
46
64
  return empty;
47
65
  }
48
66
 
49
- exports.ACTIONS_COLUMN_PX = ACTIONS_COLUMN_PX;
50
67
  exports.DEFAULT_COLUMN_PX = DEFAULT_COLUMN_PX;
68
+ exports.DEFAULT_VIEW_MODE = DEFAULT_VIEW_MODE;
69
+ exports.HEADER_ACTIONS_RESERVE_PX = HEADER_ACTIONS_RESERVE_PX;
51
70
  exports.ROW_ACTIONS_RESERVE_PX = ROW_ACTIONS_RESERVE_PX;
52
71
  exports.SELECTION_COLUMN_PX = SELECTION_COLUMN_PX;
72
+ exports.getActionsReserve = getActionsReserve;
53
73
  exports.getAriaSort = getAriaSort;
54
74
  exports.getCellDisplayValue = getCellDisplayValue;
55
75
  exports.getHeaderLabel = getHeaderLabel;
@@ -57,5 +77,7 @@ exports.getNextSortDirection = getNextSortDirection;
57
77
  exports.getVisibleColumns = getVisibleColumns;
58
78
  exports.isActiveSort = isActiveSort;
59
79
  exports.isModifierClick = isModifierClick;
80
+ exports.reservesRowActionsSpace = reservesRowActionsSpace;
60
81
  exports.shouldAllowWrap = shouldAllowWrap;
61
82
  exports.shouldToggleOnKey = shouldToggleOnKey;
83
+ exports.showsExpandToggle = showsExpandToggle;
@@ -1,7 +1,13 @@
1
1
  import type { ReactNode } from 'react';
2
- import type { ColumnItem } from './Table.types';
2
+ import type { ColumnItem, ViewMode } from './Table.types';
3
3
  export declare const SELECTION_COLUMN_PX: 32;
4
- export declare const ACTIONS_COLUMN_PX: 0;
4
+ /**
5
+ * Smaller reserve used when the only action is the header's settings button:
6
+ * the button overlaps the header cell's own padding. Must match
7
+ * `.thMainWithHeaderActionsReserve` in Table.module.css
8
+ * (component-size-sm 30px - spacing-sm 12px + spacing-2xs 2px).
9
+ */
10
+ export declare const HEADER_ACTIONS_RESERVE_PX: 20;
5
11
  /**
6
12
  * Space kept free at the inline end of the last column for the row actions
7
13
  * button and header actions. Must match `--table-row-actions-reserve-inline`
@@ -9,7 +15,39 @@ export declare const ACTIONS_COLUMN_PX: 0;
9
15
  */
10
16
  export declare const ROW_ACTIONS_RESERVE_PX: 32;
11
17
  export declare const DEFAULT_COLUMN_PX: 150;
18
+ /** View mode when neither the `viewMode` prop nor table settings set one. */
19
+ export declare const DEFAULT_VIEW_MODE: ViewMode;
20
+ /**
21
+ * Whether rows show the expand toggle: only in compact mode, since wrapped
22
+ * rows already show their full content.
23
+ */
24
+ export declare function showsExpandToggle(expandableRows: boolean | undefined, viewMode: ViewMode): boolean;
12
25
  export type SortDirection = 'asc' | 'desc' | null;
26
+ /**
27
+ * Whether the last column reserves `ROW_ACTIONS_RESERVE_PX` at its inline end:
28
+ * row actions (context menu, expand toggle) always do, header actions (e.g.
29
+ * the settings menu) only while the header row that holds them is shown.
30
+ */
31
+ export declare function reservesRowActionsSpace(args: {
32
+ hasRowActions: boolean;
33
+ hasHeaderActions: boolean;
34
+ showHeader: boolean;
35
+ }): boolean;
36
+ /**
37
+ * How much space the last column reserves for actions: none, the smaller
38
+ * `HEADER_ACTIONS_RESERVE_PX` when the header's settings button is the only
39
+ * action, or the full `ROW_ACTIONS_RESERVE_PX`. Shared by Table and
40
+ * TanstackTable so the computed widths match the header's padding.
41
+ */
42
+ export declare function getActionsReserve(args: {
43
+ hasRowActions: boolean;
44
+ hasSettings: boolean;
45
+ hasOtherHeaderActions: boolean;
46
+ showHeader: boolean;
47
+ }): {
48
+ px: number;
49
+ compactHeader: boolean;
50
+ };
13
51
  export declare function getVisibleColumns<T>(columns: Array<ColumnItem<T>>): Array<ColumnItem<T>>;
14
52
  export declare function getHeaderLabel(header: string | (() => ReactNode)): ReactNode;
15
53
  export declare function isActiveSort(sortById: string | undefined, columnId: string): boolean;
@@ -1,7 +1,25 @@
1
1
  const SELECTION_COLUMN_PX = 32;
2
- const ACTIONS_COLUMN_PX = 0;
2
+ const HEADER_ACTIONS_RESERVE_PX = 20;
3
3
  const ROW_ACTIONS_RESERVE_PX = 32;
4
4
  const DEFAULT_COLUMN_PX = 150;
5
+ const DEFAULT_VIEW_MODE = "wrapped";
6
+ function showsExpandToggle(expandableRows, viewMode) {
7
+ return Boolean(expandableRows) && viewMode !== "wrapped";
8
+ }
9
+ function reservesRowActionsSpace(args) {
10
+ return args.hasRowActions || args.showHeader && args.hasHeaderActions;
11
+ }
12
+ function getActionsReserve(args) {
13
+ const { hasRowActions, hasSettings, hasOtherHeaderActions, showHeader } = args;
14
+ const reserves = reservesRowActionsSpace({
15
+ hasRowActions,
16
+ hasHeaderActions: hasSettings || hasOtherHeaderActions,
17
+ showHeader
18
+ });
19
+ if (!reserves) return { px: 0, compactHeader: false };
20
+ const compactHeader = showHeader && hasSettings && !hasOtherHeaderActions && !hasRowActions;
21
+ return { px: compactHeader ? HEADER_ACTIONS_RESERVE_PX : ROW_ACTIONS_RESERVE_PX, compactHeader };
22
+ }
5
23
  function getVisibleColumns(columns) {
6
24
  return columns.filter((column) => !column.hidden);
7
25
  }
@@ -44,4 +62,4 @@ function getCellDisplayValue(row, column) {
44
62
  return empty;
45
63
  }
46
64
 
47
- export { ACTIONS_COLUMN_PX, DEFAULT_COLUMN_PX, ROW_ACTIONS_RESERVE_PX, SELECTION_COLUMN_PX, getAriaSort, getCellDisplayValue, getHeaderLabel, getNextSortDirection, getVisibleColumns, isActiveSort, isModifierClick, shouldAllowWrap, shouldToggleOnKey };
65
+ export { DEFAULT_COLUMN_PX, DEFAULT_VIEW_MODE, HEADER_ACTIONS_RESERVE_PX, ROW_ACTIONS_RESERVE_PX, SELECTION_COLUMN_PX, getActionsReserve, getAriaSort, getCellDisplayValue, getHeaderLabel, getNextSortDirection, getVisibleColumns, isActiveSort, isModifierClick, reservesRowActionsSpace, shouldAllowWrap, shouldToggleOnKey, showsExpandToggle };