@dbcdk/react-components 0.0.36 → 0.0.38

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.
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { TextWrap } from 'lucide-react';
3
- import { isValidElement } from 'react';
4
- import { useMemo, useState } from 'react';
3
+ import { isValidElement, useMemo, useState } from 'react';
5
4
  import styles from './CodeBlock.module.css';
6
5
  import { Button } from '../button/Button';
7
6
  import { CopyButton } from '../copy-button/CopyButton';
@@ -11,12 +11,33 @@ export function CopyButton(props) {
11
11
  const [copied, setCopied] = useState(false);
12
12
  const handleCopy = async () => {
13
13
  try {
14
+ if (!window.isSecureContext || !navigator.clipboard) {
15
+ throw new Error('Clipboard API unavailable');
16
+ }
14
17
  await navigator.clipboard.writeText(text);
15
18
  setCopied(true);
16
19
  setTimeout(() => setCopied(false), 1000);
17
20
  }
18
21
  catch (err) {
19
- console.error('Failed to copy: ', err);
22
+ console.error('Failed to copy:', err);
23
+ try {
24
+ const textarea = document.createElement('textarea');
25
+ textarea.value = text;
26
+ textarea.setAttribute('readonly', '');
27
+ textarea.style.position = 'fixed';
28
+ textarea.style.left = '-9999px';
29
+ document.body.appendChild(textarea);
30
+ textarea.select();
31
+ const success = document.execCommand('copy');
32
+ document.body.removeChild(textarea);
33
+ if (success) {
34
+ setCopied(true);
35
+ setTimeout(() => setCopied(false), 1000);
36
+ }
37
+ }
38
+ catch (fallbackErr) {
39
+ console.error('Fallback copy failed:', fallbackErr);
40
+ }
20
41
  }
21
42
  };
22
43
  if (props.style === 'link') {
@@ -1,4 +1,4 @@
1
1
  import type { JSX } from 'react';
2
2
  import type { TableProps } from './Table.types';
3
- export declare function Table<T extends Record<string, any>>({ data, dataKey, columns, selectedRows, selectionMode, allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant, size, viewMode, striped, fillViewport, tableWidth, tableRootRef, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement, showFirstLast, pageSizeOptions, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }: TableProps<T>): JSX.Element;
3
+ export declare function Table<T extends Record<string, any>>({ data, dataKey, columns, selectedRows, selectionMode, allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant, size, viewMode, striped, fillViewport, tableWidth, tableRootRef, measuringLayout, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement, showFirstLast, pageSizeOptions, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }: TableProps<T>): JSX.Element;
4
4
  export type { ColumnItem } from './Table.types';
@@ -9,7 +9,7 @@ import { TableLoadingBody } from './components/TableLoadingBody';
9
9
  import { cx } from './table.classes';
10
10
  import styles from './Table.module.css';
11
11
  import { getVisibleColumns, SELECTION_COLUMN_PX } from './table.utils';
12
- export function Table({ data, dataKey, columns, selectedRows, selectionMode = 'single', allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant = 'primary', size = 'md', viewMode, striped, fillViewport = false, tableWidth, tableRootRef, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement = 'bottom', showFirstLast = false, pageSizeOptions, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }) {
12
+ export function Table({ data, dataKey, columns, selectedRows, selectionMode = 'single', allRowsSelected, sortById, sortDirection, loading, emptyConfig, variant = 'primary', size = 'md', viewMode, striped, fillViewport = false, tableWidth, tableRootRef, measuringLayout = false, toolbar, headerExtras, take, skip, totalItemsCount, paginationPlacement = 'bottom', showFirstLast = false, pageSizeOptions, getRowSeverity, onRowClick, onRowMouseEnter, onRowSelect, onSelectAllRows, onSortChange, onPageChange, ...rest }) {
13
13
  const visibleColumns = useMemo(() => getVisibleColumns(columns), [columns]);
14
14
  const selectionInputName = useId();
15
15
  const hasSelection = Boolean(selectedRows && onRowSelect);
@@ -18,7 +18,7 @@ export function Table({ data, dataKey, columns, selectedRows, selectionMode = 's
18
18
  }, [onPageChange]);
19
19
  const bodyContent = loading && !data.length ? (_jsx(TableLoadingBody, { rows: take !== null && take !== void 0 ? take : 5, columns: visibleColumns, hasSelection: hasSelection })) : (_jsx(TableBody, { data: data, dataKey: dataKey, columns: visibleColumns, striped: striped, selectedRows: selectedRows, hasSelection: hasSelection, selectionMode: selectionMode, selectionInputName: selectionInputName, viewMode: viewMode, getRowSeverity: getRowSeverity, onRowClick: onRowClick, onRowMouseEnter: onRowMouseEnter, onRowSelect: onRowSelect }));
20
20
  const paginationEl = onPageChange && data.length > 0 ? (_jsx("div", { className: cx(styles.paginationSlot, paginationPlacement === 'top' && styles.paginationSlotTop), children: _jsx(Pagination, { itemsCount: totalItemsCount, take: take, skip: skip, onPageChange: handlePageChange, showFirstLast: showFirstLast, pageSizeOptions: pageSizeOptions }) })) : null;
21
- const tableClassName = cx(styles.tableRoot, styles[variant], styles[size], getRowSeverity && styles.severityTable);
21
+ const tableClassName = cx(styles.tableRoot, styles[variant], styles[size], measuringLayout && styles.measuringLayout, getRowSeverity && styles.severityTable);
22
22
  const tableShell = (_jsx("div", { ...rest, className: tableClassName, children: _jsx("div", { ref: tableRootRef, className: styles.tableScroll, children: !data.length && !loading ? (_jsx("div", { className: styles.emptyStateSlot, children: _jsx(TableEmptyState, { config: emptyConfig }) })) : (_jsxs("table", { className: styles.tableElement, "aria-rowcount": data.length, style: tableWidth != null ? { width: tableWidth } : undefined, children: [_jsxs("colgroup", { children: [hasSelection ? _jsx("col", { style: { width: SELECTION_COLUMN_PX } }) : null, visibleColumns.map(column => (_jsx("col", { style: column.width != null ? { width: column.width } : undefined }, column.id)))] }), _jsx(TableHeader, { columns: visibleColumns, hasSelection: hasSelection, selectionMode: selectionMode, allRowsSelected: allRowsSelected, onSelectAllRows: onSelectAllRows, sortById: sortById, sortDirection: sortDirection, onSortChange: onSortChange, headerExtras: headerExtras }), bodyContent] })) }) }));
23
23
  if (fillViewport) {
24
24
  return (_jsxs("div", { className: styles.fillViewportRoot, style: {
@@ -55,6 +55,10 @@
55
55
  max-inline-size: 100%;
56
56
  }
57
57
 
58
+ .measuringLayout {
59
+ visibility: hidden;
60
+ }
61
+
58
62
  .tableScroll {
59
63
  flex: 1 1 auto;
60
64
  min-block-size: 0;
@@ -157,7 +161,7 @@
157
161
 
158
162
  .headerCell.selectionCell,
159
163
  .cell.selectionCell {
160
- padding-inline: calc(var(--spacing-xxs) + 2px) var(--spacing-sm);
164
+ padding-inline: calc(var(--spacing-xxs) + 6px) var(--spacing-sm);
161
165
  cursor: pointer;
162
166
  overflow: visible;
163
167
  line-height: 0;
@@ -208,7 +212,7 @@
208
212
  cursor: pointer;
209
213
  }
210
214
 
211
- .clickableRow:hover > .cell {
215
+ .row:hover > .cell {
212
216
  background-color: var(--table-row-bg-hover);
213
217
  }
214
218
 
@@ -7,7 +7,6 @@ export interface ColumnItem<T> {
7
7
  header: string | (() => ReactNode);
8
8
  accessor?: keyof T;
9
9
  width?: number | string;
10
- fitContent?: boolean;
11
10
  sortable?: boolean;
12
11
  sortFunction?: (a: T, b: T) => -1 | 0 | 1;
13
12
  render?: (item: T) => ReactNode;
@@ -44,6 +43,7 @@ export type TableProps<T extends Record<string, any>> = Omit<HTMLAttributes<HTML
44
43
  fillViewport?: boolean;
45
44
  tableWidth?: number;
46
45
  tableRootRef?: Ref<HTMLDivElement>;
46
+ measuringLayout?: boolean;
47
47
  toolbar?: ReactNode;
48
48
  headerExtras?: (args: HeaderExtrasArgs<T>) => ReactNode;
49
49
  take?: number;
@@ -2,10 +2,8 @@ import { type ColumnDef, type SortingState } from '@tanstack/react-table';
2
2
  import * as React from 'react';
3
3
  import { TableProps, TableVariant } from './Table.types';
4
4
  import { ViewMode } from '../../hooks/useTableSettings';
5
- type Filterable<T> = Array<keyof T>;
6
- export type TanstackTableProps<T extends Record<string, any>> = Omit<TableProps<T>, 'columns' | 'onSortChange' | 'sortById' | 'sortDirection' | 'headerExtras' | 'gridTemplateColumns' | 'toolbar'> & {
5
+ export type TanstackTableProps<T extends Record<string, any>> = Omit<TableProps<T>, 'columns' | 'onSortChange' | 'sortById' | 'sortDirection' | 'headerExtras' | 'toolbar'> & {
7
6
  columns: ReadonlyArray<ColumnDef<T, any>>;
8
- filterable?: Filterable<T>;
9
7
  sorting?: SortingState;
10
8
  manualSorting?: boolean;
11
9
  onSortingChange?: (next: SortingState) => void;
@@ -15,4 +13,3 @@ export type TanstackTableProps<T extends Record<string, any>> = Omit<TableProps<
15
13
  visibleColumnIds?: string[];
16
14
  };
17
15
  export declare function TanstackTable<T extends Record<string, any>>(props: TanstackTableProps<T>): React.ReactNode;
18
- export {};
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import { useReactTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel, } from '@tanstack/react-table';
3
+ import { useReactTable, getCoreRowModel, getSortedRowModel, } from '@tanstack/react-table';
4
4
  import * as React from 'react';
5
5
  import ColumnResizer from './components/column-resizer/ColumnResizer';
6
6
  import { Table } from './Table';
@@ -18,17 +18,14 @@ export function TanstackTable(props) {
18
18
  setUiSorting(controlledSorting);
19
19
  }, [isControlledSorting, controlledSorting, uiSorting]);
20
20
  const columnVisibility = React.useMemo(() => buildColumnVisibilityFromVisibleIds(columns, visibleColumnIds), [columns, visibleColumnIds]);
21
- const [columnFilters, setColumnFilters] = React.useState([]);
22
21
  const [columnSizing, setColumnSizing] = React.useState({});
23
22
  const containerRef = React.useRef(null);
24
23
  const [availableWidth, setAvailableWidth] = React.useState(undefined);
25
- const [measuredFitContentWidths, setMeasuredFitContentWidths] = React.useState({});
26
24
  const table = useReactTable({
27
25
  data,
28
26
  columns: columns,
29
27
  state: {
30
28
  sorting: uiSorting,
31
- columnFilters,
32
29
  columnSizing,
33
30
  columnVisibility,
34
31
  },
@@ -38,11 +35,9 @@ export function TanstackTable(props) {
38
35
  setUiSorting(next);
39
36
  onSortingChange === null || onSortingChange === void 0 ? void 0 : onSortingChange(next);
40
37
  },
41
- onColumnFiltersChange: setColumnFilters,
42
38
  onColumnSizingChange: setColumnSizing,
43
39
  getCoreRowModel: getCoreRowModel(),
44
40
  getSortedRowModel: getSortedRowModel(),
45
- getFilteredRowModel: getFilteredRowModel(),
46
41
  manualSorting: manualSorting !== null && manualSorting !== void 0 ? manualSorting : false,
47
42
  enableColumnResizing: true,
48
43
  columnResizeMode: 'onChange',
@@ -69,31 +64,6 @@ export function TanstackTable(props) {
69
64
  observer.observe(el);
70
65
  return () => observer.disconnect();
71
66
  }, []);
72
- React.useLayoutEffect(() => {
73
- const root = containerRef.current;
74
- if (!root)
75
- return;
76
- const next = {};
77
- const nodes = root.querySelectorAll('[data-fit-content-column="true"][data-column-id]');
78
- nodes.forEach(node => {
79
- var _a;
80
- const id = node.dataset.columnId;
81
- if (!id)
82
- return;
83
- const width = Math.ceil(node.scrollWidth);
84
- if (width <= 0)
85
- return;
86
- next[id] = Math.max((_a = next[id]) !== null && _a !== void 0 ? _a : 0, width);
87
- });
88
- setMeasuredFitContentWidths(prev => {
89
- const prevKeys = Object.keys(prev);
90
- const nextKeys = Object.keys(next);
91
- if (prevKeys.length === nextKeys.length && nextKeys.every(key => prev[key] === next[key])) {
92
- return prev;
93
- }
94
- return next;
95
- });
96
- }, [data, columns, columnVisibility, props.loading, uiSorting]);
97
67
  const distributedLayout = React.useMemo(() => {
98
68
  if (availableWidth == null)
99
69
  return null;
@@ -103,17 +73,9 @@ export function TanstackTable(props) {
103
73
  defaultMinPx: 80,
104
74
  columnSizing,
105
75
  availableWidth,
106
- measuredFitContentWidths,
107
76
  });
108
- }, [
109
- table,
110
- selectedRows,
111
- onRowSelect,
112
- dataKey,
113
- columnSizing,
114
- availableWidth,
115
- measuredFitContentWidths,
116
- ]);
77
+ }, [table, selectedRows, onRowSelect, dataKey, columnSizing, availableWidth]);
78
+ const initialLayoutReady = availableWidth != null;
117
79
  const resolvedLayout = React.useMemo(() => {
118
80
  const next = {};
119
81
  table.getVisibleLeafColumns().forEach((column) => {
@@ -145,5 +107,5 @@ export function TanstackTable(props) {
145
107
  return null;
146
108
  return _jsx(ColumnResizer, { id: header.column.id, handler: handler });
147
109
  }, [table]);
148
- return (_jsx(Table, { ...tableProps, tableRootRef: containerRef, onSortChange: handleSortChange, dataKey: dataKey, data: visibleData, columns: columnItems, tableWidth: distributedLayout === null || distributedLayout === void 0 ? void 0 : distributedLayout.totalWidth, sortById: sortById, sortDirection: sortDirection, headerExtras: headerExtras, selectedRows: selectedRows, onRowSelect: onRowSelect }));
110
+ return (_jsx(Table, { ...tableProps, tableRootRef: containerRef, onSortChange: handleSortChange, dataKey: dataKey, data: visibleData, columns: columnItems, tableWidth: distributedLayout === null || distributedLayout === void 0 ? void 0 : distributedLayout.totalWidth, measuringLayout: !initialLayoutReady, sortById: sortById, sortDirection: sortDirection, headerExtras: headerExtras, selectedRows: selectedRows, onRowSelect: onRowSelect }));
149
111
  }
@@ -15,7 +15,7 @@ export function TableHeaderCell({ column, index, sortById, sortDirection, onSort
15
15
  const nextDirection = getNextSortDirection(column.sortable, active, sortDirection !== null && sortDirection !== void 0 ? sortDirection : null);
16
16
  onSortChange(column, nextDirection);
17
17
  };
18
- return (_jsxs("th", { className: cx(styles.headerCell, dividerClass), scope: "col", "aria-sort": ariaSort, "data-align": align, "data-divider": column.divider, "data-column-index": index, "data-column-id": column.id, "data-fit-content-column": column.fitContent || undefined, children: [_jsx("div", { className: alignClasses.inner, children: _jsx("div", { className: alignClasses.main, children: column.sortable ? (_jsxs("button", { type: "button", className: alignClasses.button, onClick: handleToggleSort, onKeyDown: e => {
18
+ return (_jsxs("th", { className: cx(styles.headerCell, dividerClass), scope: "col", "aria-sort": ariaSort, "data-align": align, "data-divider": column.divider, "data-column-index": index, children: [_jsx("div", { className: alignClasses.inner, children: _jsx("div", { className: alignClasses.main, children: column.sortable ? (_jsxs("button", { type: "button", className: alignClasses.button, onClick: handleToggleSort, onKeyDown: e => {
19
19
  if (!shouldToggleOnKey(e.key))
20
20
  return;
21
21
  e.preventDefault();
@@ -46,10 +46,8 @@ export function TableRow({ row, rowId, columns, selectedRows, hasSelection, sele
46
46
  onRowSelect === null || onRowSelect === void 0 ? void 0 : onRowSelect(rowId, checked);
47
47
  } })) }) }) })) : null, columns.map(column => {
48
48
  var _a;
49
- const allowWrap = column.fitContent
50
- ? false
51
- : shouldAllowWrap(column.allowWrap, isSelected, viewMode);
49
+ const allowWrap = shouldAllowWrap(column.allowWrap, isSelected, viewMode);
52
50
  const cellValue = getCellDisplayValue(row, column);
53
- return (_jsx("td", { className: cx(styles.cell, allowWrap ? styles.allowWrap : styles.nowrap, column.divider === 'left' && styles.dividerLeft, column.divider === 'right' && styles.dividerRight), "data-align": (_a = column.align) !== null && _a !== void 0 ? _a : 'left', "data-divider": column.divider, "data-column-id": column.id, "data-fit-content-column": column.fitContent || undefined, children: _jsx("div", { className: styles.cellContent, children: allowWrap ? cellValue : _jsx("div", { className: styles.cellValueEllipsis, children: cellValue }) }) }, column.id));
51
+ return (_jsx("td", { className: cx(styles.cell, allowWrap ? styles.allowWrap : styles.nowrap, column.divider === 'left' && styles.dividerLeft, column.divider === 'right' && styles.dividerRight), "data-align": (_a = column.align) !== null && _a !== void 0 ? _a : 'left', "data-divider": column.divider, children: _jsx("div", { className: styles.cellContent, children: allowWrap ? cellValue : _jsx("div", { className: styles.cellValueEllipsis, children: cellValue }) }) }, column.id));
54
52
  })] }));
55
53
  }
@@ -17,7 +17,6 @@ export declare function buildDistributedColumnWidths(args: {
17
17
  defaultMinPx: number;
18
18
  columnSizing: ColumnSizingState;
19
19
  availableWidth: number;
20
- measuredFitContentWidths?: Record<string, number>;
21
20
  }): {
22
21
  selectionWidth?: number;
23
22
  widths: Record<string, number>;
@@ -20,7 +20,7 @@ export function buildColumnVisibilityFromVisibleIds(defs, visibleColumnIds) {
20
20
  }
21
21
  export function mapDefsToColumnItems(defs, columnVisibility, resolvedLayout = {}) {
22
22
  return defs.map((def, index) => {
23
- var _a, _b, _c, _d, _e, _f, _g, _h;
23
+ var _a, _b, _c, _d, _e, _f, _g;
24
24
  const id = getColumnId(def, index);
25
25
  const accessorKey = def.accessorKey;
26
26
  const accessorFn = def.accessorFn;
@@ -55,11 +55,10 @@ export function mapDefsToColumnItems(defs, columnVisibility, resolvedLayout = {}
55
55
  render,
56
56
  hidden: !isVisible,
57
57
  width: (_e = resolvedLayout[id]) === null || _e === void 0 ? void 0 : _e.width,
58
- fitContent: (_f = meta.fitContent) !== null && _f !== void 0 ? _f : false,
59
58
  align: meta.align,
60
59
  verticalAlign: meta.verticalAlign,
61
- emptyPlaceholder: (_g = meta.emptyPlaceholder) !== null && _g !== void 0 ? _g : '-',
62
- allowWrap: (_h = meta.allowWrap) !== null && _h !== void 0 ? _h : false,
60
+ emptyPlaceholder: (_f = meta.emptyPlaceholder) !== null && _f !== void 0 ? _f : '-',
61
+ allowWrap: (_g = meta.allowWrap) !== null && _g !== void 0 ? _g : false,
63
62
  severity: meta.severity,
64
63
  divider: meta.divider,
65
64
  };
@@ -107,11 +106,11 @@ function toIntegerTrackWidths(tracks, targetWidth) {
107
106
  return Object.fromEntries(floored.map(track => [track.id, track.width]));
108
107
  }
109
108
  export function buildDistributedColumnWidths(args) {
110
- const { table, hasSelection, defaultMinPx, columnSizing, availableWidth, measuredFitContentWidths = {}, } = args;
109
+ const { table, hasSelection, defaultMinPx, columnSizing, availableWidth } = args;
111
110
  const leaf = table.getVisibleLeafColumns();
112
111
  const selectionWidth = hasSelection ? SELECTION_COLUMN_PX : 0;
113
112
  const tracks = leaf.map((c) => {
114
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
113
+ var _a, _b, _c, _d, _e;
115
114
  const def = c.columnDef;
116
115
  const meta = ((_b = ((_a = def.meta) !== null && _a !== void 0 ? _a : {})) !== null && _b !== void 0 ? _b : {});
117
116
  const min = Math.max(1, Number((_c = def.minSize) !== null && _c !== void 0 ? _c : defaultMinPx));
@@ -127,19 +126,7 @@ export function buildDistributedColumnWidths(args) {
127
126
  fixed: true,
128
127
  };
129
128
  }
130
- if (meta.fitContent) {
131
- const preferredRaw = Number((_g = (_f = (_e = (_d = measuredFitContentWidths[c.id]) !== null && _d !== void 0 ? _d : def.size) !== null && _e !== void 0 ? _e : def.maxSize) !== null && _f !== void 0 ? _f : def.minSize) !== null && _g !== void 0 ? _g : defaultMinPx);
132
- const preferred = Number.isFinite(preferredRaw) && preferredRaw > 0 ? preferredRaw : defaultMinPx;
133
- const fitWidth = Math.round(clamp(preferred, min, max));
134
- return {
135
- id: c.id,
136
- width: fitWidth,
137
- weight: 0,
138
- max: fitWidth,
139
- fixed: true,
140
- };
141
- }
142
- const rawWeight = Number((_j = (_h = meta.weight) !== null && _h !== void 0 ? _h : def.size) !== null && _j !== void 0 ? _j : DEFAULT_COLUMN_PX);
129
+ const rawWeight = Number((_e = (_d = meta.weight) !== null && _d !== void 0 ? _d : def.size) !== null && _e !== void 0 ? _e : DEFAULT_COLUMN_PX);
143
130
  const weight = Number.isFinite(rawWeight) && rawWeight > 0 ? rawWeight : DEFAULT_COLUMN_PX;
144
131
  return {
145
132
  id: c.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dbcdk/react-components",
3
- "version": "0.0.36",
3
+ "version": "0.0.38",
4
4
  "description": "Reusable React components for DBC projects",
5
5
  "license": "ISC",
6
6
  "author": "",
@@ -56,7 +56,7 @@
56
56
  "changeset": "changeset",
57
57
  "version-packages": "changeset version",
58
58
  "typecheck": "tsc -p tsconfig.json --noEmit",
59
- "pack-it": "npm run build && npm pack",
59
+ "pack-it": "rimraf ./*.tgz && npm run build && npm pack",
60
60
  "postbuild": "cpy \"src/**/*.css\" dist --parents && cpy \"src/styles/styles.css\" dist && cpy \"src/styles/fonts/**/*\" dist/styles/fonts",
61
61
  "yalc:publish": "npm run build && yalc publish --push",
62
62
  "yalc:push": "npm run build && yalc push --scripts --changed",