@dbcdk/react-components 0.0.18 → 0.0.20

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.
@@ -4,9 +4,33 @@ import { useReactTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel,
4
4
  import * as React from 'react';
5
5
  import ColumnResizer from './components/column-resizer/ColumnResizer';
6
6
  import { Table } from './Table';
7
- import { buildColumnVisibilityFromVisibleIds, mapDefsToColumnItems, sortingEqual, getSortPropsFromSorting, buildColumnStyles, columnItemsToIdSet, } from './tanstackTable.utils';
7
+ import { buildColumnVisibilityFromVisibleIds, mapDefsToColumnItems, sortingEqual, getSortPropsFromSorting, columnItemsToIdSet, } from './tanstackTable.utils';
8
+ function buildGridTemplateColumns(args) {
9
+ var _a, _b, _c, _d;
10
+ const { table, allowedIds, hasSelection, selectionPx, defaultMinPx } = args;
11
+ const parts = [];
12
+ if (hasSelection)
13
+ parts.push(`${selectionPx}px`);
14
+ const leaf = table.getVisibleLeafColumns().filter(c => allowedIds.has(c.id));
15
+ for (const c of leaf) {
16
+ const def = c.columnDef;
17
+ const min = Number((_a = def.minSize) !== null && _a !== void 0 ? _a : defaultMinPx);
18
+ const maxRaw = def.maxSize;
19
+ const max = maxRaw == null ? Number.POSITIVE_INFINITY : Number(maxRaw);
20
+ const size = Number((_d = (_c = (_b = c.getSize) === null || _b === void 0 ? void 0 : _b.call(c)) !== null && _c !== void 0 ? _c : def.size) !== null && _d !== void 0 ? _d : min);
21
+ if (Number.isFinite(min) && Number.isFinite(max) && min > 0 && max === min) {
22
+ parts.push(`${Math.round(min)}px`);
23
+ continue;
24
+ }
25
+ // Weight based on size so wide columns keep more room
26
+ const weight = Math.max(1, Math.min(6, Math.round(size / 100)));
27
+ // Respect minSize; scroll if mins don't fit
28
+ parts.push(`minmax(${Math.round(min)}px, ${weight}fr)`);
29
+ }
30
+ return parts.join(' ');
31
+ }
8
32
  export function TanstackTable(props) {
9
- const { data, dataKey, columns, filterable = [], sorting: controlledSorting, onSortingChange, optimisticSortingUi = true, visibleColumnIds, manualSorting, ...tableProps } = props;
33
+ const { data, dataKey, columns, sorting: controlledSorting, onSortingChange, optimisticSortingUi = true, visibleColumnIds, manualSorting, selectedRows, onRowSelect, ...tableProps } = props;
10
34
  const isControlledSorting = controlledSorting != null;
11
35
  const [uiSorting, setUiSorting] = React.useState(controlledSorting !== null && controlledSorting !== void 0 ? controlledSorting : []);
12
36
  React.useEffect(() => {
@@ -53,19 +77,11 @@ export function TanstackTable(props) {
53
77
  const allowedIds = React.useMemo(() => columnItemsToIdSet(columnItems), [columnItems]);
54
78
  const visibleData = table.getRowModel().rows.map(r => r.original);
55
79
  const { sortById, sortDirection } = getSortPropsFromSorting(uiSorting);
56
- const columnStyles = React.useMemo(() => {
57
- const leafCols = table.getAllLeafColumns();
58
- return buildColumnStyles(leafCols, allowedIds, { minWidth: 80, maxWidth: 800 });
59
- }, [table, columnSizing, allowedIds]);
60
80
  const handleSortChange = React.useCallback((column, direction) => {
61
- // Translate Table's direction -> TanStack SortingState
62
81
  const next = direction == null ? [] : [{ id: column.id, desc: direction === 'desc' }];
63
- // Mirror TanStack's onSortingChange behavior
64
82
  if (optimisticSortingUi)
65
83
  setUiSorting(next);
66
84
  onSortingChange === null || onSortingChange === void 0 ? void 0 : onSortingChange(next);
67
- // If you are doing server-side sorting, you likely also want:
68
- // table.resetPageIndex?.() or external pagination reset (depends on your setup)
69
85
  }, [optimisticSortingUi, onSortingChange]);
70
86
  const headerExtras = React.useCallback(({ index }) => {
71
87
  var _a, _b, _c, _d;
@@ -80,5 +96,15 @@ export function TanstackTable(props) {
80
96
  return null;
81
97
  return _jsx(ColumnResizer, { id: header.column.id, handler: handler });
82
98
  }, [table]);
83
- return (_jsx(Table, { ...tableProps, onSortChange: handleSortChange, dataKey: dataKey, data: visibleData, columns: columnItems, sortById: sortById, sortDirection: sortDirection, columnStyles: columnStyles, headerExtras: headerExtras }));
99
+ const hasSelection = Boolean(selectedRows && onRowSelect && dataKey);
100
+ const gridTemplateColumns = React.useMemo(() => {
101
+ return buildGridTemplateColumns({
102
+ table,
103
+ allowedIds,
104
+ hasSelection,
105
+ selectionPx: 36,
106
+ defaultMinPx: 80,
107
+ });
108
+ }, [table, allowedIds, hasSelection, columnSizing]);
109
+ return (_jsx(Table, { ...tableProps, onSortChange: handleSortChange, dataKey: dataKey, data: visibleData, columns: columnItems, sortById: sortById, sortDirection: sortDirection, gridTemplateColumns: gridTemplateColumns, headerExtras: headerExtras, selectedRows: selectedRows, onRowSelect: onRowSelect }));
84
110
  }
@@ -4,14 +4,9 @@ export type TableEmptyConfig = {
4
4
  /** Keep it short + system-like */
5
5
  title?: string;
6
6
  description?: ReactNode;
7
- /**
8
- * Optional custom actions (rendered after built-ins).
9
- * Good for injecting extra links/buttons from the table page.
10
- */
11
7
  actions?: ReactNode;
12
8
  onBack?: () => void;
13
9
  onRefresh?: () => void;
14
- /** New: clear filters */
15
10
  onClearFilters?: () => void;
16
11
  showClearFilters?: boolean;
17
12
  clearFiltersLabel?: ReactNode;
@@ -1,18 +1,15 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ArrowLeft } from 'lucide-react';
3
- import { Button } from '../../../../components/button/Button';
4
3
  const defaultEmptyConfig = {
5
4
  enabled: true,
6
5
  title: 'Ingen resultater',
7
6
  description: _jsx("span", { children: "Ingen data at vise." }),
8
7
  showBack: false,
9
8
  showRefresh: false,
10
- // default: show button if handler exists
11
9
  showClearFilters: true,
12
10
  backLabel: (_jsxs(_Fragment, { children: [_jsx(ArrowLeft, { size: 16 }), "Tilbage"] })),
13
11
  refreshLabel: _jsx(_Fragment, { children: "Indl\u00E6s igen" }),
14
12
  clearFiltersLabel: _jsx(_Fragment, { children: "Nulstil alle filtre" }),
15
- // "system-like": less hero, less vertical drama
16
13
  className: 'dbc-flex dbc-flex-column dbc-items-start dbc-justify-start dbc-text-left dbc-gap-sm dbc-py-lg',
17
14
  };
18
15
  export function TableEmptyState({ config }) {
@@ -22,9 +19,5 @@ export function TableEmptyState({ config }) {
22
19
  };
23
20
  if (!merged.enabled)
24
21
  return null;
25
- const showBack = merged.showBack && typeof merged.onBack === 'function';
26
- const showRefresh = merged.showRefresh && typeof merged.onRefresh === 'function';
27
- const showClearFilters = merged.showClearFilters && typeof merged.onClearFilters === 'function';
28
- const hasAnyActions = Boolean(merged.actions) || showBack || showRefresh || showClearFilters;
29
- return (_jsxs("div", { className: merged.className, children: [_jsx("div", { className: "dbc-text-sm", children: merged.description }), hasAnyActions && (_jsxs("div", { className: "dbc-flex dbc-gap-sm dbc-mt-xs", children: [showClearFilters && (_jsx(Button, { type: "button", variant: "secondary", onClick: merged.onClearFilters, children: merged.clearFiltersLabel })), showRefresh && (_jsx(Button, { type: "button", variant: "secondary", onClick: merged.onRefresh, children: merged.refreshLabel })), showBack && (_jsx(Button, { type: "button", variant: "secondary", onClick: merged.onBack, children: merged.backLabel })), merged.actions] }))] }));
22
+ return (_jsxs("div", { className: "dbc-flex dbc-flex-column dbc-gap-md dbc-pt-sm dbc-pb-sm", children: [_jsx("span", { className: "dbc-text-sm dbc-muted-text", children: merged.description }), merged.actions ? _jsx("span", { className: "dbc-flex dbc-gap-sm", children: merged.actions }) : null] }));
30
23
  }
@@ -2,14 +2,12 @@ export function getVisibleColumns(columns) {
2
2
  return columns.filter(c => !c.hidden);
3
3
  }
4
4
  export function getColumnStyle(columnId, columnStyles, alignment, verticalAlignment) {
5
- var _a;
6
5
  const baseStyle = columnStyles === null || columnStyles === void 0 ? void 0 : columnStyles[columnId];
7
6
  return {
8
7
  ...(baseStyle !== null && baseStyle !== void 0 ? baseStyle : {}),
9
8
  ...(alignment === 'right' ? { fontVariantNumeric: 'tabular-nums' } : null),
10
9
  verticalAlign: verticalAlignment !== null && verticalAlignment !== void 0 ? verticalAlignment : 'top',
11
10
  textAlign: alignment !== null && alignment !== void 0 ? alignment : 'left',
12
- minWidth: (_a = baseStyle === null || baseStyle === void 0 ? void 0 : baseStyle.minWidth) !== null && _a !== void 0 ? _a : 0,
13
11
  };
14
12
  }
15
13
  export function getHeaderLabel(header) {
@@ -60,12 +60,15 @@ body.dbc-app {
60
60
 
61
61
  .dbc-table {
62
62
  --card-label-width: 260px;
63
-
64
63
  border-collapse: collapse;
65
64
  font-size: var(--font-size-sm);
66
65
  line-height: var(--line-height-normal);
67
66
  }
68
67
 
68
+ .dbc-table--hover tr:hover {
69
+ background-color: var(--color-bg-contextual);
70
+ }
71
+
69
72
  .dbc-table tr + tr th,
70
73
  .dbc-table tr + tr td {
71
74
  padding-block: var(--spacing-xxs);
@@ -60,12 +60,15 @@ body.dbc-app {
60
60
 
61
61
  .dbc-table {
62
62
  --card-label-width: 260px;
63
-
64
63
  border-collapse: collapse;
65
64
  font-size: var(--font-size-sm);
66
65
  line-height: var(--line-height-normal);
67
66
  }
68
67
 
68
+ .dbc-table--hover tr:hover {
69
+ background-color: var(--color-bg-contextual);
70
+ }
71
+
69
72
  .dbc-table tr + tr th,
70
73
  .dbc-table tr + tr td {
71
74
  padding-block: var(--spacing-xxs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcdk/react-components",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "Reusable React components for DBC projects",
5
5
  "license": "ISC",
6
6
  "author": "",