@dbcdk/react-components 0.0.195 → 0.0.197

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 (109) hide show
  1. package/README.md +78 -10
  2. package/dist/client.cjs +486 -614
  3. package/dist/client.d.ts +176 -102
  4. package/dist/client.js +102 -102
  5. package/dist/components/color-scheme-button/ColorSchemeButton.cjs +7 -4
  6. package/dist/components/color-scheme-button/ColorSchemeButton.d.ts +7 -3
  7. package/dist/components/color-scheme-button/ColorSchemeButton.js +7 -4
  8. package/dist/components/forms/text-area/Textarea.cjs +2 -1
  9. package/dist/components/forms/text-area/Textarea.d.ts +1 -0
  10. package/dist/components/forms/text-area/Textarea.js +2 -1
  11. package/dist/components/highlighted-text/HighlightedText.cjs +6 -3
  12. package/dist/components/highlighted-text/HighlightedText.js +7 -4
  13. package/dist/components/json-viewer/JsonNode.cjs +27 -67
  14. package/dist/components/json-viewer/JsonNode.d.ts +10 -0
  15. package/dist/components/json-viewer/JsonNode.js +28 -68
  16. package/dist/components/json-viewer/JsonRow.cjs +85 -0
  17. package/dist/components/json-viewer/JsonRow.d.ts +5 -0
  18. package/dist/components/json-viewer/JsonRow.js +79 -0
  19. package/dist/components/json-viewer/JsonViewer.cjs +36 -253
  20. package/dist/components/json-viewer/JsonViewer.js +37 -250
  21. package/dist/components/json-viewer/JsonViewerShell.cjs +208 -0
  22. package/dist/components/json-viewer/JsonViewerShell.d.ts +25 -0
  23. package/dist/components/json-viewer/JsonViewerShell.js +202 -0
  24. package/dist/components/json-viewer/TanstackJsonViewer.cjs +127 -0
  25. package/dist/components/json-viewer/TanstackJsonViewer.d.ts +17 -0
  26. package/dist/components/json-viewer/TanstackJsonViewer.js +121 -0
  27. package/dist/components/json-viewer/types.d.ts +27 -0
  28. package/dist/components/json-viewer/useJsonViewerState.cjs +111 -0
  29. package/dist/components/json-viewer/useJsonViewerState.d.ts +42 -0
  30. package/dist/components/json-viewer/useJsonViewerState.js +108 -0
  31. package/dist/components/json-viewer/utils.cjs +36 -0
  32. package/dist/components/json-viewer/utils.d.ts +21 -1
  33. package/dist/components/json-viewer/utils.js +35 -1
  34. package/dist/components/lightbox/Lightbox.cjs +2 -2
  35. package/dist/components/lightbox/Lightbox.d.ts +1 -1
  36. package/dist/components/lightbox/Lightbox.js +1 -1
  37. package/dist/components/menu/Menu.cjs +3 -23
  38. package/dist/components/menu/Menu.js +3 -23
  39. package/dist/components/menu/Menu.module.css +4 -3
  40. package/dist/components/metric-tile/MetricTile.cjs +3 -2
  41. package/dist/components/metric-tile/MetricTile.js +2 -1
  42. package/dist/components/overlay/tooltip/Tooltip.cjs +7 -2
  43. package/dist/components/overlay/tooltip/Tooltip.d.ts +7 -1
  44. package/dist/components/overlay/tooltip/Tooltip.js +7 -2
  45. package/dist/components/overlay/tooltip/useTooltipTrigger.cjs +7 -1
  46. package/dist/components/overlay/tooltip/useTooltipTrigger.js +7 -1
  47. package/dist/components/page-layout/PageLayout.module.css +1 -1
  48. package/dist/components/table/Table.cjs +45 -16
  49. package/dist/components/table/Table.d.ts +1 -1
  50. package/dist/components/table/Table.js +47 -18
  51. package/dist/components/table/Table.module.css +135 -7
  52. package/dist/components/table/Table.types.d.ts +47 -1
  53. package/dist/components/table/TanstackTable.cjs +30 -2
  54. package/dist/components/table/TanstackTable.js +31 -3
  55. package/dist/components/table/components/TableBody.d.ts +1 -2
  56. package/dist/components/table/components/TableHeader.cjs +6 -4
  57. package/dist/components/table/components/TableHeader.d.ts +2 -1
  58. package/dist/components/table/components/TableHeader.js +6 -4
  59. package/dist/components/table/components/TableHeaderCell.cjs +5 -4
  60. package/dist/components/table/components/TableHeaderCell.d.ts +3 -1
  61. package/dist/components/table/components/TableHeaderCell.js +5 -4
  62. package/dist/components/table/components/TableRow.cjs +1 -1
  63. package/dist/components/table/components/TableRow.d.ts +1 -2
  64. package/dist/components/table/components/TableRow.js +1 -1
  65. package/dist/components/table/components/TableSkeletonBody.cjs +30 -0
  66. package/dist/components/table/components/TableSkeletonBody.d.ts +13 -0
  67. package/dist/components/table/components/TableSkeletonBody.js +24 -0
  68. package/dist/components/table/components/table-settings/TableHeaderSettings.cjs +28 -0
  69. package/dist/components/table/components/table-settings/TableHeaderSettings.d.ts +11 -0
  70. package/dist/components/table/components/table-settings/TableHeaderSettings.js +26 -0
  71. package/dist/components/table/components/table-settings/TableSettings.cjs +82 -32
  72. package/dist/components/table/components/table-settings/TableSettings.d.ts +14 -6
  73. package/dist/components/table/components/table-settings/TableSettings.js +84 -34
  74. package/dist/components/table/table.utils.cjs +2 -0
  75. package/dist/components/table/table.utils.d.ts +6 -0
  76. package/dist/components/table/table.utils.js +2 -1
  77. package/dist/components/table/tableSettings.utils.cjs +29 -0
  78. package/dist/components/table/tableSettings.utils.d.ts +9 -0
  79. package/dist/components/table/tableSettings.utils.js +24 -0
  80. package/dist/components/table/tanstackTable.utils.cjs +18 -0
  81. package/dist/components/table/tanstackTable.utils.js +19 -1
  82. package/dist/components/theme-button/ThemeButton.cjs +9 -4
  83. package/dist/components/theme-button/ThemeButton.d.ts +4 -2
  84. package/dist/components/theme-button/ThemeButton.js +9 -4
  85. package/dist/components/theme-script/ThemeScript.cjs +10 -4
  86. package/dist/components/theme-script/ThemeScript.d.ts +9 -1
  87. package/dist/components/theme-script/ThemeScript.js +10 -4
  88. package/dist/hooks/useColorScheme.cjs +19 -15
  89. package/dist/hooks/useColorScheme.d.ts +12 -1
  90. package/dist/hooks/useColorScheme.js +20 -16
  91. package/dist/hooks/useGetActiveTheme.cjs +4 -3
  92. package/dist/hooks/useGetActiveTheme.d.ts +7 -1
  93. package/dist/hooks/useGetActiveTheme.js +4 -3
  94. package/dist/hooks/useTableData.cjs +11 -7
  95. package/dist/hooks/useTableData.d.ts +8 -2
  96. package/dist/hooks/useTableData.js +11 -7
  97. package/dist/hooks/useTableSettings.cjs +25 -9
  98. package/dist/hooks/useTableSettings.d.ts +9 -6
  99. package/dist/hooks/useTableSettings.js +25 -9
  100. package/dist/hooks/useTheme.cjs +15 -15
  101. package/dist/hooks/useTheme.d.ts +8 -0
  102. package/dist/hooks/useTheme.js +15 -15
  103. package/dist/styles/styles.css +7 -3
  104. package/dist/styles/themes/dbc/colors.css +1 -1
  105. package/dist/styles.css +1 -476
  106. package/dist/tanstack-virtual.cjs +12 -0
  107. package/dist/tanstack-virtual.d.ts +1 -0
  108. package/dist/tanstack-virtual.js +1 -0
  109. package/package.json +13 -1
@@ -58,7 +58,9 @@
58
58
  --table-component-cell-fg: var(--table-cell-fg);
59
59
  --table-component-cell-border: var(--table-border-subtle);
60
60
  --table-component-divider: var(--table-divider);
61
- --table-row-actions-reserve-inline: calc(var(--component-size-md) + 4px + var(--spacing-2xs));
61
+ /* Row actions button (component-size-sm) plus its inline-end offset. Keep in
62
+ sync with ROW_ACTIONS_RESERVE_PX in table.utils.ts. */
63
+ --table-row-actions-reserve-inline: calc(var(--component-size-sm) + var(--spacing-2xs));
62
64
 
63
65
  display: flex;
64
66
  flex-direction: column;
@@ -78,7 +80,7 @@
78
80
 
79
81
  .embedded {
80
82
  --table-component-header-bg: transparent;
81
- --table-component-header-fg: var(--color-fg-subtle);
83
+ --table-component-header-fg: var(--color-fg-muted);
82
84
  --table-component-header-font-weight: var(--font-weight-default);
83
85
  --table-component-row-bg: transparent;
84
86
  --table-component-row-bg-hover: var(--color-bg-contextual-subtle);
@@ -101,6 +103,9 @@
101
103
  min-block-size: 0;
102
104
  min-inline-size: 0;
103
105
  overflow: auto;
106
+ /* Always reserve the scrollbar's space, so the column widths don't change
107
+ when the body starts or stops scrolling (e.g. skeleton rows vs. data). */
108
+ scrollbar-gutter: stable;
104
109
  background: var(--table-component-row-bg);
105
110
  -webkit-overflow-scrolling: touch;
106
111
  }
@@ -450,6 +455,75 @@
450
455
  pointer-events: auto;
451
456
  }
452
457
 
458
+ /*
459
+ * Header actions (e.g. the settings trigger) sit at the inline end of the last
460
+ * header cell, lined up with the row-actions buttons below. Stacked above
461
+ * .thOverlayExtras so the column resizer doesn't swallow clicks on them.
462
+ */
463
+ .thEndAction {
464
+ position: absolute;
465
+ inset-block-start: 50%;
466
+ inset-inline-end: var(--spacing-2xs);
467
+ transform: translateY(-50%);
468
+ display: inline-flex;
469
+ align-items: center;
470
+ z-index: 8;
471
+ }
472
+
473
+ .headerActions {
474
+ display: inline-flex;
475
+ align-items: center;
476
+ gap: var(--spacing-2xs);
477
+ }
478
+
479
+ /*
480
+ * Keep header actions low-key: the settings trigger uses the same colour as
481
+ * the header's sort arrows and a compact square button, and header actions are
482
+ * only shown while the table is hovered - like the row-actions buttons. They
483
+ * stay visible while focused or while their menu is open, and always on
484
+ * devices without hover. They remain clickable while faded out.
485
+ * `button[data-…]` outranks Button's own `.button.inline` colour rule.
486
+ */
487
+ .thEndAction button[data-table-settings-trigger] {
488
+ color: var(--color-disabled-fg);
489
+ inline-size: var(--component-size-sm);
490
+ min-inline-size: var(--component-size-sm);
491
+ padding: 0;
492
+ }
493
+
494
+ .thEndAction button[data-table-settings-trigger]:hover,
495
+ .thEndAction button[data-table-settings-trigger][aria-expanded='true'] {
496
+ color: var(--color-fg-subtle);
497
+ }
498
+
499
+ .thEndAction {
500
+ opacity: 0;
501
+ transition: opacity 0.15s;
502
+ }
503
+
504
+ .tableElement:hover .thEndAction,
505
+ .thEndAction:focus-within,
506
+ .thEndAction:has([aria-expanded='true']) {
507
+ opacity: 1;
508
+ }
509
+
510
+ @media (hover: none) {
511
+ .thEndAction {
512
+ opacity: 1;
513
+ }
514
+ }
515
+
516
+ .toolbarWithHeaderActions {
517
+ display: flex;
518
+ align-items: center;
519
+ justify-content: space-between;
520
+ gap: var(--spacing-sm);
521
+ }
522
+
523
+ .toolbarWithHeaderActions > .headerActions {
524
+ margin-inline-start: auto;
525
+ }
526
+
453
527
  .sortIndicator {
454
528
  display: inline-flex;
455
529
  flex: 0 0 auto;
@@ -475,6 +549,22 @@
475
549
  color: var(--color-disabled-fg);
476
550
  }
477
551
 
552
+ /* Loading placeholder: a full text line (the cell's line-height) with the bar
553
+ centred in it, matching the height of a real single-line row. */
554
+ .skeletonCellContent {
555
+ display: flex;
556
+ align-items: center;
557
+ block-size: 1lh;
558
+ }
559
+
560
+ /* Table rows (incl. striped ones) need stronger bars than the default
561
+ skeleton to be visible. [role='status'] outranks .skeletonLoader, which
562
+ sets these variables on the item itself. */
563
+ .skeletonCellContent > [role='status'] {
564
+ --skeleton-base: var(--opac-bg-dark);
565
+ --skeleton-sheen: var(--opac-bg-default);
566
+ }
567
+
478
568
  .cellContent {
479
569
  display: flex;
480
570
  inline-size: 100%;
@@ -558,8 +648,19 @@
558
648
  text-overflow: clip;
559
649
  }
560
650
 
561
- .row:focus-within > .cell:not(.selectionCell) .cellContent,
562
- .row:focus-within > .cell:not(.selectionCell) .cellValueEllipsis {
651
+ /*
652
+ * Unwrap the row's content only for keyboard focus. Mouse clicks on the row
653
+ * don't match :focus-visible, so the row keeps its height.
654
+ * The row-actions button is excluded outright: its menu returns focus to it
655
+ * programmatically on close, and browsers (notably Safari/Firefox on macOS,
656
+ * where clicking a button doesn't focus it) may treat that as :focus-visible.
657
+ */
658
+ .row:focus-visible > .cell:not(.selectionCell) .cellContent,
659
+ .row:focus-visible > .cell:not(.selectionCell) .cellValueEllipsis,
660
+ .row:has(:focus-visible:not([data-row-context-menu])) > .cell:not(.selectionCell) .cellContent,
661
+ .row:has(:focus-visible:not([data-row-context-menu]))
662
+ > .cell:not(.selectionCell)
663
+ .cellValueEllipsis {
563
664
  white-space: normal;
564
665
  overflow-wrap: break-word;
565
666
  word-break: normal;
@@ -569,8 +670,8 @@
569
670
 
570
671
  .contextMenuTrigger {
571
672
  color: var(--color-fg-subtle);
572
- min-inline-size: calc(var(--component-size-md) + 4px);
573
- min-block-size: calc(var(--component-size-md) + 4px);
673
+ min-inline-size: var(--component-size-sm);
674
+ min-block-size: var(--component-size-sm);
574
675
  border-radius: 999px;
575
676
  background-color: transparent;
576
677
  position: relative;
@@ -578,9 +679,17 @@
578
679
  overflow: hidden;
579
680
  }
580
681
 
682
+ /*
683
+ * The row-actions button is centred on the cell's first line of text (cell
684
+ * padding + half the 20px line height) rather than on the whole cell, so it
685
+ * stays put when the row grows (wrapping, selection, expansion). For a
686
+ * single-line row this is the same spot as centring on the cell.
687
+ */
581
688
  .contextMenuOverlay {
689
+ --table-row-actions-cell-padding-block: 6px;
690
+
582
691
  position: absolute;
583
- inset-block-start: 50%;
692
+ inset-block-start: calc(var(--table-row-actions-cell-padding-block) + 10px);
584
693
  inset-inline-end: var(--spacing-2xs);
585
694
  transform: translateY(-50%);
586
695
  display: inline-flex;
@@ -595,6 +704,25 @@
595
704
  z-index: 2;
596
705
  }
597
706
 
707
+ .md .contextMenuOverlay {
708
+ --table-row-actions-cell-padding-block: var(--spacing-xs);
709
+ }
710
+
711
+ .sm .contextMenuOverlay {
712
+ --table-row-actions-cell-padding-block: var(--spacing-xxs);
713
+ }
714
+
715
+ /* Follow the cell's own vertical alignment when it isn't top-aligned. */
716
+ .cell[data-vertical-align='middle'] .contextMenuOverlay {
717
+ inset-block-start: 50%;
718
+ }
719
+
720
+ .cell[data-vertical-align='bottom'] .contextMenuOverlay {
721
+ inset-block-start: auto;
722
+ inset-block-end: calc(var(--table-row-actions-cell-padding-block) + 10px);
723
+ transform: translateY(50%);
724
+ }
725
+
598
726
  .contextMenuHoverOnly .contextMenuOverlay {
599
727
  opacity: 0;
600
728
  pointer-events: none;
@@ -1,7 +1,7 @@
1
1
  import type { HTMLAttributes, ReactNode, Ref } from 'react';
2
2
  import type { PageChangeEvent } from '../../components/pagination/Pagination';
3
3
  import type { Severity } from '../../constants/severity.types';
4
- import type { ViewMode } from '../../hooks/useTableSettings';
4
+ export type ViewMode = 'compact' | 'wrapped';
5
5
  export interface ColumnItem<T> {
6
6
  id: string;
7
7
  header: string | (() => ReactNode);
@@ -21,6 +21,35 @@ export interface ColumnItem<T> {
21
21
  severity?: any;
22
22
  allowOverflow?: boolean;
23
23
  }
24
+ /** Visibility fields shared by Table columns and accessor-shaped adapters. */
25
+ export interface TableSettingsColumn extends Partial<Pick<ColumnItem<unknown>, 'id' | 'hidden' | 'canHide'>> {
26
+ accessorKey?: PropertyKey;
27
+ header?: unknown;
28
+ enableHiding?: boolean;
29
+ meta?: unknown;
30
+ }
31
+ /**
32
+ * Settings state + setters that drive the table's built-in header settings
33
+ * menu. This is the shape `useTableSettings` returns, so its result can be
34
+ * passed straight through: `settings={useTableSettings(...)}`.
35
+ */
36
+ export interface TableSettingsController {
37
+ viewMode: ViewMode;
38
+ setViewMode: (mode: ViewMode) => void;
39
+ visibleColumnIds?: string[];
40
+ setVisibleColumnIds?: (ids: string[]) => void;
41
+ striped?: boolean;
42
+ setStriped?: (nextStriped: boolean) => void;
43
+ }
44
+ /** Labels and extra items for the table's built-in header settings menu. */
45
+ export interface TableSettingsMenuOptions {
46
+ /** Accessible name and tooltip for the trigger. Defaults to "Visningsindstillinger". */
47
+ triggerLabel?: string;
48
+ columnsLabel?: string;
49
+ allPresetLabel?: string;
50
+ standardPresetLabel?: string;
51
+ additionalSettings?: (close?: () => void) => ReactNode;
52
+ }
24
53
  export type HeaderExtrasArgs<T> = {
25
54
  column: ColumnItem<T>;
26
55
  index: number;
@@ -57,16 +86,33 @@ export type TableProps<T extends Record<string, any>> = Omit<HTMLAttributes<HTML
57
86
  variant?: TableVariant;
58
87
  size?: 'sm' | 'md';
59
88
  viewMode?: ViewMode;
89
+ striped?: boolean;
60
90
  fillViewport?: boolean;
61
91
  /** Extra space below the table, in addition to measured layout/pagination spacing. Defaults to 0. */
62
92
  fillViewportBottomOffset?: number;
63
93
  containScrolling?: boolean;
94
+ /**
95
+ * Pins the header while scrolling. Defaults to the top of the table's own
96
+ * scroll area when `containScrolling` is on; `false` turns it off.
97
+ */
64
98
  stickyHeader?: StickyHeader;
65
99
  tableWidth?: number;
66
100
  tableRootRef?: Ref<HTMLDivElement>;
67
101
  measuringLayout?: boolean;
68
102
  toolbar?: ReactNode;
69
103
  headerExtras?: (args: HeaderExtrasArgs<T>) => ReactNode;
104
+ /**
105
+ * Content rendered at the inline end of the header row, above the row
106
+ * actions column. Falls back to the toolbar when `showHeader` is false.
107
+ */
108
+ headerActions?: ReactNode;
109
+ /**
110
+ * Shows a settings menu (stripes, text wrapping, column visibility) in the
111
+ * header and applies its state to the table. Pass the result of
112
+ * `useTableSettings`. Explicit `viewMode`/`striped` props take precedence.
113
+ */
114
+ settings?: TableSettingsController;
115
+ settingsOptions?: TableSettingsMenuOptions;
70
116
  take?: number;
71
117
  skip?: number;
72
118
  totalItemsCount?: number;
@@ -5,6 +5,7 @@ var jsxRuntime = require('react/jsx-runtime');
5
5
  var reactTable = require('@tanstack/react-table');
6
6
  var React = require('react');
7
7
  var ColumnResizer = require('./components/column-resizer/ColumnResizer');
8
+ var TableHeaderSettings = require('./components/table-settings/TableHeaderSettings');
8
9
  var Table = require('./Table');
9
10
  var table_utils = require('./table.utils');
10
11
  var tanstackTable_utils = require('./tanstackTable.utils');
@@ -40,12 +41,18 @@ function TanstackTable(props) {
40
41
  sorting: controlledSorting,
41
42
  onSortingChange,
42
43
  optimisticSortingUi = true,
43
- visibleColumnIds,
44
+ visibleColumnIds: visibleColumnIdsProp,
44
45
  manualSorting,
46
+ viewMode,
47
+ striped,
48
+ settings,
49
+ settingsOptions,
50
+ headerActions: headerActionsProp,
45
51
  selectedRows,
46
52
  onRowSelect,
47
53
  ...tableProps
48
54
  } = props;
55
+ const visibleColumnIds = visibleColumnIdsProp != null ? visibleColumnIdsProp : settings == null ? void 0 : settings.visibleColumnIds;
49
56
  const isControlledSorting = controlledSorting != null;
50
57
  const [uiSorting, setUiSorting] = React__namespace.useState(controlledSorting != null ? controlledSorting : []);
51
58
  React__namespace.useEffect(() => {
@@ -116,7 +123,11 @@ function TanstackTable(props) {
116
123
  return tanstackTable_utils.buildDistributedColumnWidths({
117
124
  table,
118
125
  hasSelection: Boolean(selectedRows && onRowSelect && dataKey),
119
- hasContextMenu: Boolean(tableProps.getContextMenuItems),
126
+ // Row actions (context menu, expand toggle) and header actions (e.g. the
127
+ // settings menu) all reserve space at the end of the last column.
128
+ hasContextMenu: Boolean(
129
+ tableProps.getContextMenuItems || tableProps.expandableRows || settings || headerActionsProp != null
130
+ ),
120
131
  defaultMinPx: 80,
121
132
  columnSizing,
122
133
  availableWidth
@@ -127,6 +138,9 @@ function TanstackTable(props) {
127
138
  onRowSelect,
128
139
  dataKey,
129
140
  tableProps.getContextMenuItems,
141
+ tableProps.expandableRows,
142
+ settings,
143
+ headerActionsProp,
130
144
  columnSizing,
131
145
  availableWidth
132
146
  ]);
@@ -168,10 +182,24 @@ function TanstackTable(props) {
168
182
  },
169
183
  [table]
170
184
  );
185
+ const headerActions = headerActionsProp != null || settings ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
186
+ headerActionsProp,
187
+ settings ? /* @__PURE__ */ jsxRuntime.jsx(
188
+ TableHeaderSettings.TableHeaderSettings,
189
+ {
190
+ settings,
191
+ options: settingsOptions,
192
+ columns
193
+ }
194
+ ) : null
195
+ ] }) : void 0;
171
196
  return /* @__PURE__ */ jsxRuntime.jsx(
172
197
  Table.Table,
173
198
  {
174
199
  ...tableProps,
200
+ viewMode: viewMode != null ? viewMode : settings == null ? void 0 : settings.viewMode,
201
+ striped: striped != null ? striped : settings == null ? void 0 : settings.striped,
202
+ headerActions,
175
203
  tableRootRef: containerRef,
176
204
  onSortChange: handleSortChange,
177
205
  dataKey,
@@ -1,8 +1,9 @@
1
1
  'use client';
2
- import { jsx } from 'react/jsx-runtime';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import { useReactTable, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
4
4
  import * as React from 'react';
5
5
  import ColumnResizer from './components/column-resizer/ColumnResizer';
6
+ import { TableHeaderSettings } from './components/table-settings/TableHeaderSettings';
6
7
  import { Table } from './Table';
7
8
  import { DEFAULT_COLUMN_PX } from './table.utils';
8
9
  import { sortingEqual, buildColumnVisibilityFromVisibleIds, buildDistributedColumnWidths, mapDefsToColumnItems, getSortPropsFromSorting } from './tanstackTable.utils';
@@ -15,12 +16,18 @@ function TanstackTable(props) {
15
16
  sorting: controlledSorting,
16
17
  onSortingChange,
17
18
  optimisticSortingUi = true,
18
- visibleColumnIds,
19
+ visibleColumnIds: visibleColumnIdsProp,
19
20
  manualSorting,
21
+ viewMode,
22
+ striped,
23
+ settings,
24
+ settingsOptions,
25
+ headerActions: headerActionsProp,
20
26
  selectedRows,
21
27
  onRowSelect,
22
28
  ...tableProps
23
29
  } = props;
30
+ const visibleColumnIds = visibleColumnIdsProp != null ? visibleColumnIdsProp : settings == null ? void 0 : settings.visibleColumnIds;
24
31
  const isControlledSorting = controlledSorting != null;
25
32
  const [uiSorting, setUiSorting] = React.useState(controlledSorting != null ? controlledSorting : []);
26
33
  React.useEffect(() => {
@@ -91,7 +98,11 @@ function TanstackTable(props) {
91
98
  return buildDistributedColumnWidths({
92
99
  table,
93
100
  hasSelection: Boolean(selectedRows && onRowSelect && dataKey),
94
- hasContextMenu: Boolean(tableProps.getContextMenuItems),
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
+ ),
95
106
  defaultMinPx: 80,
96
107
  columnSizing,
97
108
  availableWidth
@@ -102,6 +113,9 @@ function TanstackTable(props) {
102
113
  onRowSelect,
103
114
  dataKey,
104
115
  tableProps.getContextMenuItems,
116
+ tableProps.expandableRows,
117
+ settings,
118
+ headerActionsProp,
105
119
  columnSizing,
106
120
  availableWidth
107
121
  ]);
@@ -143,10 +157,24 @@ function TanstackTable(props) {
143
157
  },
144
158
  [table]
145
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;
146
171
  return /* @__PURE__ */ jsx(
147
172
  Table,
148
173
  {
149
174
  ...tableProps,
175
+ viewMode: viewMode != null ? viewMode : settings == null ? void 0 : settings.viewMode,
176
+ striped: striped != null ? striped : settings == null ? void 0 : settings.striped,
177
+ headerActions,
150
178
  tableRootRef: containerRef,
151
179
  onSortChange: handleSortChange,
152
180
  dataKey,
@@ -1,6 +1,5 @@
1
1
  import type { ReactNode } from 'react';
2
- import type { ViewMode } from '../../../hooks/useTableSettings';
3
- import type { ColumnItem, TableContextMenuItem } from '../Table.types';
2
+ import type { ViewMode, ColumnItem, TableContextMenuItem } from '../../../components/table/Table.types';
4
3
  type Props<T extends Record<string, any>> = {
5
4
  data: T[];
6
5
  dataKey: keyof T;
@@ -20,14 +20,15 @@ function TableHeader({
20
20
  sortDirection,
21
21
  onSortChange,
22
22
  headerExtras,
23
- stickyTop
23
+ stickyTop,
24
+ headerActions
24
25
  }) {
25
26
  return /* @__PURE__ */ jsxRuntime.jsx(
26
27
  "thead",
27
28
  {
28
29
  className: styles__default.default.header,
29
30
  "data-sticky": Boolean(stickyTop),
30
- style: stickyTop ? { top: stickyTop, position: "sticky", zIndex: 2 } : void 0,
31
+ style: stickyTop ? { top: stickyTop, position: "sticky" } : void 0,
31
32
  children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: styles__default.default.headerRow, children: [
32
33
  hasSelection ? /* @__PURE__ */ jsxRuntime.jsx(
33
34
  TableSelectionCell.TableSelectionCell,
@@ -43,13 +44,14 @@ function TableHeader({
43
44
  {
44
45
  column,
45
46
  index,
46
- reserveInlineEnd: hasRowContextMenu && index === columns.length - 1,
47
+ reserveInlineEnd: (hasRowContextMenu || headerActions != null) && index === columns.length - 1,
48
+ endAction: index === columns.length - 1 ? headerActions : void 0,
47
49
  sortById,
48
50
  sortDirection,
49
51
  onSortChange,
50
52
  extraContent: headerExtras == null ? void 0 : headerExtras({ column, index })
51
53
  },
52
- column.id
54
+ index === columns.length - 1 && headerActions != null ? "__last" : column.id
53
55
  ))
54
56
  ] })
55
57
  }
@@ -12,6 +12,7 @@ type Props<T> = {
12
12
  onSortChange?: (column: ColumnItem<T>, direction: SortDirection) => void;
13
13
  headerExtras?: (args: HeaderExtrasArgs<T>) => ReactNode;
14
14
  stickyTop?: string;
15
+ headerActions?: ReactNode;
15
16
  };
16
- export declare function TableHeader<T>({ columns, hasSelection, selectionMode, hasRowContextMenu, allRowsSelected, onSelectAllRows, sortById, sortDirection, onSortChange, headerExtras, stickyTop, }: Props<T>): React.ReactNode;
17
+ export declare function TableHeader<T>({ columns, hasSelection, selectionMode, hasRowContextMenu, allRowsSelected, onSelectAllRows, sortById, sortDirection, onSortChange, headerExtras, stickyTop, headerActions, }: Props<T>): React.ReactNode;
17
18
  export {};
@@ -14,14 +14,15 @@ function TableHeader({
14
14
  sortDirection,
15
15
  onSortChange,
16
16
  headerExtras,
17
- stickyTop
17
+ stickyTop,
18
+ headerActions
18
19
  }) {
19
20
  return /* @__PURE__ */ jsx(
20
21
  "thead",
21
22
  {
22
23
  className: styles.header,
23
24
  "data-sticky": Boolean(stickyTop),
24
- style: stickyTop ? { top: stickyTop, position: "sticky", zIndex: 2 } : void 0,
25
+ style: stickyTop ? { top: stickyTop, position: "sticky" } : void 0,
25
26
  children: /* @__PURE__ */ jsxs("tr", { className: styles.headerRow, children: [
26
27
  hasSelection ? /* @__PURE__ */ jsx(
27
28
  TableSelectionCell,
@@ -37,13 +38,14 @@ function TableHeader({
37
38
  {
38
39
  column,
39
40
  index,
40
- reserveInlineEnd: hasRowContextMenu && index === columns.length - 1,
41
+ reserveInlineEnd: (hasRowContextMenu || headerActions != null) && index === columns.length - 1,
42
+ endAction: index === columns.length - 1 ? headerActions : void 0,
41
43
  sortById,
42
44
  sortDirection,
43
45
  onSortChange,
44
46
  extraContent: headerExtras == null ? void 0 : headerExtras({ column, index })
45
47
  },
46
- column.id
48
+ index === columns.length - 1 && headerActions != null ? "__last" : column.id
47
49
  ))
48
50
  ] })
49
51
  }
@@ -17,7 +17,8 @@ function TableHeaderCell({
17
17
  sortById,
18
18
  sortDirection,
19
19
  onSortChange,
20
- extraContent
20
+ extraContent,
21
+ endAction
21
22
  }) {
22
23
  const active = table_utils.isActiveSort(sortById, column.id);
23
24
  const ariaSort = table_utils.getAriaSort(column.sortable, active, sortDirection != null ? sortDirection : null);
@@ -59,10 +60,10 @@ function TableHeaderCell({
59
60
  ]
60
61
  }
61
62
  ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: alignClasses.label, children: table_utils.getHeaderLabel(column.header) }) }) }),
62
- extraContent != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.thOverlayExtras, children: extraContent }) : null
63
+ extraContent != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.thOverlayExtras, children: extraContent }) : null,
64
+ endAction != null ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.thEndAction, children: endAction }) : null
63
65
  ]
64
- },
65
- column.id
66
+ }
66
67
  );
67
68
  }
68
69
 
@@ -8,6 +8,8 @@ type Props<T> = {
8
8
  sortDirection?: SortDirection;
9
9
  onSortChange?: (column: ColumnItem<T>, direction: SortDirection) => void;
10
10
  extraContent?: ReactNode;
11
+ /** Rendered at the cell's inline end, in the space kept free by `reserveInlineEnd`. */
12
+ endAction?: ReactNode;
11
13
  };
12
- export declare function TableHeaderCell<T>({ column, index, reserveInlineEnd, sortById, sortDirection, onSortChange, extraContent, }: Props<T>): ReactNode;
14
+ export declare function TableHeaderCell<T>({ column, index, reserveInlineEnd, sortById, sortDirection, onSortChange, extraContent, endAction, }: Props<T>): ReactNode;
13
15
  export {};
@@ -11,7 +11,8 @@ function TableHeaderCell({
11
11
  sortById,
12
12
  sortDirection,
13
13
  onSortChange,
14
- extraContent
14
+ extraContent,
15
+ endAction
15
16
  }) {
16
17
  const active = isActiveSort(sortById, column.id);
17
18
  const ariaSort = getAriaSort(column.sortable, active, sortDirection != null ? sortDirection : null);
@@ -53,10 +54,10 @@ function TableHeaderCell({
53
54
  ]
54
55
  }
55
56
  ) : /* @__PURE__ */ jsx("span", { className: alignClasses.label, children: getHeaderLabel(column.header) }) }) }),
56
- extraContent != null ? /* @__PURE__ */ jsx("div", { className: styles.thOverlayExtras, children: extraContent }) : null
57
+ extraContent != null ? /* @__PURE__ */ jsx("div", { className: styles.thOverlayExtras, children: extraContent }) : null,
58
+ endAction != null ? /* @__PURE__ */ jsx("div", { className: styles.thEndAction, children: endAction }) : null
57
59
  ]
58
- },
59
- column.id
60
+ }
60
61
  );
61
62
  }
62
63
 
@@ -48,7 +48,7 @@ function TableRow({
48
48
  rowId,
49
49
  open: () => onRowClick == null ? void 0 : onRowClick(row)
50
50
  });
51
- const hasContextMenu = Boolean(contextMenuItems == null ? void 0 : contextMenuItems.length);
51
+ const hasContextMenu = Boolean(contextMenuItems == null ? void 0 : contextMenuItems.length) || canExpand && viewMode !== "wrapped";
52
52
  const { handleRowClick, handleRowKeyDown } = useTableRowInteractions.useTableRowInteractions({
53
53
  row,
54
54
  rowId,
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
- import type { ViewMode } from '../../../hooks/useTableSettings';
3
- import type { ColumnItem, TableContextMenuItem } from '../Table.types';
2
+ import type { ViewMode, ColumnItem, TableContextMenuItem } from '../../../components/table/Table.types';
4
3
  type Props<T extends Record<string, any>> = {
5
4
  row: T;
6
5
  rowId: string | number;
@@ -42,7 +42,7 @@ function TableRow({
42
42
  rowId,
43
43
  open: () => onRowClick == null ? void 0 : onRowClick(row)
44
44
  });
45
- const hasContextMenu = Boolean(contextMenuItems == null ? void 0 : contextMenuItems.length);
45
+ const hasContextMenu = Boolean(contextMenuItems == null ? void 0 : contextMenuItems.length) || canExpand && viewMode !== "wrapped";
46
46
  const { handleRowClick, handleRowKeyDown } = useTableRowInteractions({
47
47
  row,
48
48
  rowId,
@@ -0,0 +1,30 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var SkeletonLoaderItem = require('../../../components/skeleton-loader/skeleton-loader-item/SkeletonLoaderItem');
5
+ var table_classes = require('../table.classes');
6
+ var styles = require('../Table.module.css');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var styles__default = /*#__PURE__*/_interopDefault(styles);
11
+
12
+ function TableSkeletonBody({ columns, rows, hasSelection }) {
13
+ return /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: styles__default.default.body, "aria-busy": "true", children: Array.from({ length: rows }).map((_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: styles__default.default.row, children: [
14
+ hasSelection ? /* @__PURE__ */ jsxRuntime.jsx("td", { className: table_classes.cx(styles__default.default.cell, styles__default.default.selectionCell) }) : null,
15
+ columns.map((column, columnIndex) => {
16
+ var _a;
17
+ return /* @__PURE__ */ jsxRuntime.jsx("td", { className: styles__default.default.cell, "data-align": (_a = column.align) != null ? _a : "left", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles__default.default.skeletonCellContent, children: /* @__PURE__ */ jsxRuntime.jsx(
18
+ SkeletonLoaderItem.SkeletonLoaderItem,
19
+ {
20
+ width: `${55 + (rowIndex + columnIndex) % 3 * 15}%`,
21
+ height: 12,
22
+ radius: 4,
23
+ ariaLabel: "Indl\xE6ser r\xE6kke"
24
+ }
25
+ ) }) }, column.id);
26
+ })
27
+ ] }, rowIndex)) });
28
+ }
29
+
30
+ exports.TableSkeletonBody = TableSkeletonBody;
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { ColumnItem } from '../Table.types';
3
+ type Props<T> = {
4
+ columns: ColumnItem<T>[];
5
+ rows: number;
6
+ hasSelection: boolean;
7
+ };
8
+ /**
9
+ * Placeholder rows shown while a table loads, laid out in the table's own
10
+ * columns so the header stays in place and the skeleton starts at the top.
11
+ */
12
+ export declare function TableSkeletonBody<T>({ columns, rows, hasSelection }: Props<T>): ReactNode;
13
+ export {};