@wallarm-org/design-system 1.20.4 → 1.21.0

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 (26) hide show
  1. package/dist/components/Select/Select.d.ts +3 -1
  2. package/dist/components/Select/Select.js +6 -3
  3. package/dist/components/Table/EditableCell/EditableSelectCell.d.ts +1 -1
  4. package/dist/components/Table/EditableCell/EditableSelectCell.js +4 -1
  5. package/dist/components/Table/StickyGroupParent.js +7 -8
  6. package/dist/components/Table/TableBody/TableBodyCell.d.ts +3 -1
  7. package/dist/components/Table/TableBody/TableBodyCell.js +8 -1
  8. package/dist/components/Table/TableBody/TableBodyRowDndContext.d.ts +5 -0
  9. package/dist/components/Table/TableBody/TableBodyRowDndContext.js +65 -21
  10. package/dist/components/Table/TableBody/TableRowOverlay.js +2 -1
  11. package/dist/components/Table/TableColGroup.js +20 -17
  12. package/dist/components/Table/TableContext/TableProvider.js +3 -1
  13. package/dist/components/Table/TableContext/types.d.ts +1 -0
  14. package/dist/components/Table/TableHead.js +13 -8
  15. package/dist/components/Table/TableLoadingState.js +19 -13
  16. package/dist/components/Table/TableMasterCellActions.js +2 -5
  17. package/dist/components/Table/TableRow.js +37 -12
  18. package/dist/components/Table/TableRowExpanded.js +3 -2
  19. package/dist/components/Table/hooks/useStickyGroupParent.js +3 -1
  20. package/dist/components/Table/lib/constants.d.ts +1 -1
  21. package/dist/components/Table/lib/constants.js +1 -1
  22. package/dist/components/Table/lib/createDragHandleColumn.js +3 -3
  23. package/dist/components/Table/lib/useRowDnd.js +3 -13
  24. package/dist/components/Table/types.d.ts +8 -0
  25. package/dist/metadata/components.json +15 -4
  26. package/package.json +1 -1
@@ -3,9 +3,11 @@ import { type TestableProps } from '../../utils/testId';
3
3
  type SelectNativeProps<T extends CollectionItem> = Omit<SelectRootProps<T>, 'positioning' | 'lazyMount' | 'unmountOnExit'>;
4
4
  export interface SelectBaseProps {
5
5
  loading?: boolean;
6
+ /** Override default floating positioning (merged with DS defaults). */
7
+ positioning?: SelectRootProps<CollectionItem>['positioning'];
6
8
  }
7
9
  type SelectProps<T extends CollectionItem> = SelectNativeProps<T> & SelectBaseProps & TestableProps;
8
- export declare function Select<T extends CollectionItem>({ children, loading, disabled, 'data-testid': testId, ...props }: SelectProps<T>): import("react").JSX.Element;
10
+ export declare function Select<T extends CollectionItem>({ children, loading, disabled, positioning: positioningOverride, 'data-testid': testId, ...props }: SelectProps<T>): import("react").JSX.Element;
9
11
  export declare namespace Select {
10
12
  var displayName: string;
11
13
  }
@@ -3,14 +3,17 @@ import { useMemo } from "react";
3
3
  import { Select } from "@ark-ui/react/select";
4
4
  import { TestIdProvider } from "../../utils/testId.js";
5
5
  import { SelectSharedProvider } from "./SelectSharedContext/index.js";
6
- const Select_Select = ({ children, loading = false, disabled = false, 'data-testid': testId, ...props })=>{
6
+ const Select_Select = ({ children, loading = false, disabled = false, positioning: positioningOverride, 'data-testid': testId, ...props })=>{
7
7
  const positioning = useMemo(()=>({
8
8
  offset: {
9
9
  mainAxis: 4
10
10
  },
11
11
  gutter: 4,
12
- overflowPadding: 4
13
- }), []);
12
+ overflowPadding: 4,
13
+ ...positioningOverride
14
+ }), [
15
+ positioningOverride
16
+ ]);
14
17
  return /*#__PURE__*/ jsx(TestIdProvider, {
15
18
  value: testId,
16
19
  children: /*#__PURE__*/ jsx(SelectSharedProvider, {
@@ -11,7 +11,7 @@ export interface EditableSelectCellProps extends NativeProps, TestableProps {
11
11
  items: SelectDataItem[];
12
12
  /** Read-mode rendering of the selected value (e.g. a `Badge`). */
13
13
  children?: ReactNode;
14
- /** Shown when nothing is selected. Defaults to `'Select'`. */
14
+ /** Shown when nothing is selected. Defaults to `'Select'`. */
15
15
  placeholder?: ReactNode;
16
16
  ref?: Ref<HTMLDivElement>;
17
17
  }
@@ -6,7 +6,7 @@ import { cn } from "../../../utils/cn.js";
6
6
  import { useTestId } from "../../../utils/testId.js";
7
7
  import { Select as index_js_Select, SelectContent, SelectOption, SelectOptionIndicator, SelectOptionText, SelectPositioner, createListCollection } from "../../Select/index.js";
8
8
  import { editableCellIcon, editableCellPlaceholder, editableCellValue, editableCellVariants } from "./classes.js";
9
- const EditableSelectCell = ({ value, onCommit, items, children, placeholder = 'Select', className, ref, 'data-testid': testIdProp, ...rest })=>{
9
+ const EditableSelectCell = ({ value, onCommit, items, children, placeholder = 'Select', className, ref, 'data-testid': testIdProp, ...rest })=>{
10
10
  const testId = useTestId(void 0, testIdProp);
11
11
  const collection = useMemo(()=>createListCollection({
12
12
  items
@@ -21,6 +21,9 @@ const EditableSelectCell = ({ value, onCommit, items, children, placeholder = 'S
21
21
  value
22
22
  ] : [],
23
23
  "data-testid": testId,
24
+ positioning: {
25
+ placement: 'bottom-start'
26
+ },
24
27
  onValueChange: (details)=>{
25
28
  const next = details.value[0];
26
29
  if (next && next !== value) onCommit(next);
@@ -59,19 +59,18 @@ const StickyGroupParent = ({ tableWidth, headerHeight })=>{
59
59
  useWindowScroll,
60
60
  headerHeight
61
61
  ]);
62
- if (!stickyRow) return null;
63
- const cells = stickyRow.getVisibleCells();
64
- const systemCells = cells.filter((c)=>SYSTEM_COLUMN_IDS.has(c.column.id));
65
- const dataCells = cells.filter((c)=>!SYSTEM_COLUMN_IDS.has(c.column.id));
66
- const firstDataCell = dataCells[0];
67
- const isSelected = stickyRow.getIsAllSubRowsSelected();
62
+ const cells = stickyRow?.getVisibleCells();
63
+ const systemCells = cells?.filter((c)=>SYSTEM_COLUMN_IDS.has(c.column.id));
64
+ const dataCells = cells?.filter((c)=>!SYSTEM_COLUMN_IDS.has(c.column.id));
65
+ const firstDataCell = dataCells?.[0];
66
+ const isSelected = stickyRow?.getIsAllSubRowsSelected();
68
67
  return /*#__PURE__*/ jsx("div", {
69
- className: "sticky z-20 h-0 overflow-visible pointer-events-none",
68
+ className: "sticky z-[21] h-0 overflow-visible pointer-events-none",
70
69
  style: {
71
70
  top: headerHeight
72
71
  },
73
72
  "aria-hidden": "true",
74
- children: /*#__PURE__*/ jsx("div", {
73
+ children: stickyRow && /*#__PURE__*/ jsx("div", {
75
74
  className: "overflow-hidden",
76
75
  style: {
77
76
  height: rowRef.current?.offsetHeight ?? 40
@@ -10,8 +10,10 @@ interface TableBodyCellProps<T extends RowData> {
10
10
  lastRow?: boolean;
11
11
  dragListeners?: ReturnType<typeof useSortable>['listeners'];
12
12
  dragAttributes?: ReturnType<typeof useSortable>['attributes'];
13
+ /** Orange line indicator for row drag-and-drop placement */
14
+ dropIndicator?: 'above' | 'below';
13
15
  }
14
- export declare function TableBodyCell<T extends RowData>({ cell, colSpan, className, disablePinnedShadow, lastRow, dragListeners, dragAttributes, }: TableBodyCellProps<T>): import("react").JSX.Element;
16
+ export declare function TableBodyCell<T extends RowData>({ cell, colSpan, className, disablePinnedShadow, lastRow, dragListeners, dragAttributes, dropIndicator, }: TableBodyCellProps<T>): import("react").JSX.Element;
15
17
  export declare namespace TableBodyCell {
16
18
  var displayName: string;
17
19
  }
@@ -8,7 +8,11 @@ import { TABLE_EXPAND_COLUMN_ID, getAlignClass, getExpandBorderClass, getPinning
8
8
  import { Td } from "../primitives/index.js";
9
9
  import { useTableContext } from "../TableContext/index.js";
10
10
  import { TableMasterCellActions } from "../TableMasterCellActions.js";
11
- const TableBodyCell = ({ cell, colSpan, className, disablePinnedShadow, lastRow, dragListeners, dragAttributes })=>{
11
+ const DROP_INDICATOR_SHADOW = {
12
+ above: 'inset 0 2px 0 0 var(--color-border-strong-warning)',
13
+ below: 'inset 0 -2px 0 0 var(--color-border-strong-warning)'
14
+ };
15
+ const TableBodyCell = ({ cell, colSpan, className, disablePinnedShadow, lastRow, dragListeners, dragAttributes, dropIndicator })=>{
12
16
  const { allLeafColumns, masterColumnId } = useTableContext();
13
17
  const testId = useTestId('body-cell');
14
18
  const column = cell.column;
@@ -74,6 +78,9 @@ const TableBodyCell = ({ cell, colSpan, className, disablePinnedShadow, lastRow,
74
78
  ...dndStyle,
75
79
  ...isCut && {
76
80
  overflow: 'hidden'
81
+ },
82
+ ...dropIndicator && {
83
+ boxShadow: DROP_INDICATOR_SHADOW[dropIndicator]
77
84
  }
78
85
  },
79
86
  colSpan: colSpan,
@@ -1,4 +1,9 @@
1
1
  import { type FC, type ReactNode } from 'react';
2
+ interface RowDndIndicatorState {
3
+ activeId: string | null;
4
+ overId: string | null;
5
+ }
6
+ export declare const useRowDndIndicator: () => RowDndIndicatorState;
2
7
  interface TableBodyRowDndContextProps {
3
8
  children: ReactNode;
4
9
  }
@@ -1,9 +1,25 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { useCallback, useMemo, useState } from "react";
2
+ import { createContext, useCallback, useContext, useMemo, useState } from "react";
3
3
  import { DndContext, DragOverlay, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
4
4
  import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
5
5
  import { useTableContext } from "../TableContext/index.js";
6
6
  import { TableRowOverlay } from "./TableRowOverlay.js";
7
+ const ROW_DND_INDICATOR_DEFAULT = {
8
+ activeId: null,
9
+ overId: null
10
+ };
11
+ const RowDndIndicatorContext = /*#__PURE__*/ createContext(ROW_DND_INDICATOR_DEFAULT);
12
+ const useRowDndIndicator = ()=>useContext(RowDndIndicatorContext);
13
+ const CURSOR_STYLE_ATTR = 'data-table-row-drag';
14
+ function setCursorGrabbing() {
15
+ const style = document.createElement('style');
16
+ style.setAttribute(CURSOR_STYLE_ATTR, '');
17
+ style.textContent = '* { cursor: grabbing !important; }';
18
+ document.head.appendChild(style);
19
+ }
20
+ function resetCursor() {
21
+ document.head.querySelector(`style[${CURSOR_STYLE_ATTR}]`)?.remove();
22
+ }
7
23
  const TableBodyRowDndContext = ({ children })=>{
8
24
  const { rowDndEnabled, onRowReorder } = useTableContext();
9
25
  if (!rowDndEnabled) return children;
@@ -19,19 +35,37 @@ const TableBodyRowDndContextInner = ({ children, onRowReorder })=>{
19
35
  rows
20
36
  ]);
21
37
  const [activeRow, setActiveRow] = useState(null);
38
+ const [activeId, setActiveId] = useState(null);
39
+ const [overId, setOverId] = useState(null);
40
+ const indicatorState = useMemo(()=>({
41
+ activeId,
42
+ overId
43
+ }), [
44
+ activeId,
45
+ overId
46
+ ]);
22
47
  const sensors = useSensors(useSensor(PointerSensor, {
23
48
  activationConstraint: {
24
49
  distance: 5
25
50
  }
26
51
  }), useSensor(KeyboardSensor));
27
52
  const handleDragStart = useCallback((event)=>{
28
- const row = rows.find((r)=>r.id === String(event.active.id));
53
+ const id = String(event.active.id);
54
+ const row = rows.find((r)=>r.id === id);
29
55
  setActiveRow(row ?? null);
56
+ setActiveId(id);
57
+ setCursorGrabbing();
30
58
  }, [
31
59
  rows
32
60
  ]);
61
+ const handleDragOver = useCallback((event)=>{
62
+ setOverId(event.over ? String(event.over.id) : null);
63
+ }, []);
33
64
  const handleDragEnd = useCallback((event)=>{
34
65
  setActiveRow(null);
66
+ setActiveId(null);
67
+ setOverId(null);
68
+ resetCursor();
35
69
  const { active, over } = event;
36
70
  if (!over || active.id === over.id) return;
37
71
  onRowReorder?.({
@@ -43,26 +77,36 @@ const TableBodyRowDndContextInner = ({ children, onRowReorder })=>{
43
77
  ]);
44
78
  const handleDragCancel = useCallback(()=>{
45
79
  setActiveRow(null);
80
+ setActiveId(null);
81
+ setOverId(null);
82
+ resetCursor();
46
83
  }, []);
47
- return /*#__PURE__*/ jsxs(DndContext, {
48
- sensors: sensors,
49
- collisionDetection: closestCenter,
50
- onDragStart: handleDragStart,
51
- onDragEnd: handleDragEnd,
52
- onDragCancel: handleDragCancel,
53
- children: [
54
- /*#__PURE__*/ jsx(SortableContext, {
55
- items: rowIds,
56
- strategy: verticalListSortingStrategy,
57
- children: children
58
- }),
59
- /*#__PURE__*/ jsx(DragOverlay, {
60
- children: activeRow ? /*#__PURE__*/ jsx(TableRowOverlay, {
61
- row: activeRow
62
- }) : null
63
- })
64
- ]
84
+ return /*#__PURE__*/ jsx(RowDndIndicatorContext.Provider, {
85
+ value: indicatorState,
86
+ children: /*#__PURE__*/ jsxs(DndContext, {
87
+ sensors: sensors,
88
+ collisionDetection: closestCenter,
89
+ onDragStart: handleDragStart,
90
+ onDragOver: handleDragOver,
91
+ onDragEnd: handleDragEnd,
92
+ onDragCancel: handleDragCancel,
93
+ children: [
94
+ /*#__PURE__*/ jsx(SortableContext, {
95
+ items: rowIds,
96
+ strategy: verticalListSortingStrategy,
97
+ children: children
98
+ }),
99
+ /*#__PURE__*/ jsx(DragOverlay, {
100
+ style: {
101
+ cursor: 'grabbing'
102
+ },
103
+ children: activeRow ? /*#__PURE__*/ jsx(TableRowOverlay, {
104
+ row: activeRow
105
+ }) : null
106
+ })
107
+ ]
108
+ })
65
109
  });
66
110
  };
67
111
  TableBodyRowDndContext.displayName = 'TableBodyRowDndContext';
68
- export { TableBodyRowDndContext };
112
+ export { TableBodyRowDndContext, useRowDndIndicator };
@@ -10,7 +10,8 @@ const TableRowOverlayInner = ({ row })=>{
10
10
  return /*#__PURE__*/ jsx("table", {
11
11
  className: "w-full table-fixed border-collapse",
12
12
  style: {
13
- tableLayout: 'fixed'
13
+ tableLayout: 'fixed',
14
+ cursor: 'grabbing'
14
15
  },
15
16
  children: /*#__PURE__*/ jsx("tbody", {
16
17
  children: /*#__PURE__*/ jsx(Tr, {
@@ -1,4 +1,4 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { TABLE_DRAG_HANDLE_COLUMN_ID, TABLE_EXPAND_COLUMN_ID, TABLE_SELECT_COLUMN_ID } from "./lib/index.js";
3
3
  import { useTableContext } from "./TableContext/index.js";
4
4
  const SYSTEM_COLUMN_IDS = new Set([
@@ -7,27 +7,30 @@ const SYSTEM_COLUMN_IDS = new Set([
7
7
  TABLE_DRAG_HANDLE_COLUMN_ID
8
8
  ]);
9
9
  const TableColGroup = ({ tableWidth })=>{
10
- const { table } = useTableContext();
10
+ const { table, stretch } = useTableContext();
11
11
  const columns = table.getVisibleLeafColumns();
12
12
  const isFixed = (col)=>SYSTEM_COLUMN_IDS.has(col.id) || !col.getCanResize() && col.columnDef.minSize === col.columnDef.maxSize || col.columnDef.meta?.resizeType === 'cut';
13
13
  const fixedWidth = columns.filter(isFixed).reduce((sum, c)=>sum + c.getSize(), 0);
14
14
  const totalFlexSize = columns.filter((c)=>!isFixed(c)).reduce((sum, c)=>sum + c.getSize(), 0);
15
15
  const availableForFlex = tableWidth - fixedWidth;
16
- return /*#__PURE__*/ jsx("colgroup", {
17
- children: columns.map((col)=>{
18
- if (isFixed(col)) return /*#__PURE__*/ jsx("col", {
19
- style: {
20
- width: col.getSize()
21
- }
22
- }, col.id);
23
- if (0 === totalFlexSize) return /*#__PURE__*/ jsx("col", {}, col.id);
24
- const pixelWidth = col.getSize() / totalFlexSize * availableForFlex;
25
- return /*#__PURE__*/ jsx("col", {
26
- style: {
27
- width: pixelWidth
28
- }
29
- }, col.id);
30
- })
16
+ return /*#__PURE__*/ jsxs("colgroup", {
17
+ children: [
18
+ columns.map((col)=>{
19
+ if (isFixed(col) || !stretch) return /*#__PURE__*/ jsx("col", {
20
+ style: {
21
+ width: col.getSize()
22
+ }
23
+ }, col.id);
24
+ if (0 === totalFlexSize) return /*#__PURE__*/ jsx("col", {}, col.id);
25
+ const pixelWidth = col.getSize() / totalFlexSize * availableForFlex;
26
+ return /*#__PURE__*/ jsx("col", {
27
+ style: {
28
+ width: pixelWidth
29
+ }
30
+ }, col.id);
31
+ }),
32
+ !stretch && /*#__PURE__*/ jsx("col", {}, "_filler")
33
+ ]
31
34
  });
32
35
  };
33
36
  TableColGroup.displayName = 'TableColGroup';
@@ -15,7 +15,7 @@ const toTanStackPinning = (p, pinnedLeft)=>({
15
15
  end: p?.right ?? []
16
16
  });
17
17
  const TableProvider = (props)=>{
18
- const { data, columns, isLoading = false, isLoadingPrevious = false, skeletonCount = TABLE_SKELETON_ROWS, children, getRowId, sorting: sortingProp, onSortingChange, manualSorting = false, rowSelection: rowSelectionProp, onRowSelectionChange, enableSelectAllRows = true, onSelectAllRows, columnSizing: columnSizingProp, onColumnSizingChange, columnPinning: columnPinningProp, onColumnPinningChange, columnOrder: columnOrderProp, onColumnOrderChange, grouping: groupingProp, onGroupingChange, expanded: expandedProp, onExpandedChange, renderGroupRow, getSubRows, renderExpandedRow, columnVisibility: columnVisibilityProp, onColumnVisibilityChange, defaultColumnVisibility, defaultColumnOrder, columnGroups, virtualized, estimateRowHeight, overscan = TABLE_VIRTUALIZATION_OVERSCAN, onEndReached, onEndReachedThreshold, onStartReached, onStartReachedThreshold, initialScrollToRowId, onRowReorder, onMasterCellClick, activeRowId: activeRowIdProp, onSettingsOpenChange } = props;
18
+ const { data, columns, isLoading = false, isLoadingPrevious = false, skeletonCount = TABLE_SKELETON_ROWS, children, getRowId, sorting: sortingProp, onSortingChange, manualSorting = false, rowSelection: rowSelectionProp, onRowSelectionChange, enableSelectAllRows = true, onSelectAllRows, columnSizing: columnSizingProp, onColumnSizingChange, columnPinning: columnPinningProp, onColumnPinningChange, columnOrder: columnOrderProp, onColumnOrderChange, grouping: groupingProp, onGroupingChange, expanded: expandedProp, onExpandedChange, renderGroupRow, getSubRows, renderExpandedRow, columnVisibility: columnVisibilityProp, onColumnVisibilityChange, defaultColumnVisibility, defaultColumnOrder, columnGroups, virtualized, stretch = true, estimateRowHeight, overscan = TABLE_VIRTUALIZATION_OVERSCAN, onEndReached, onEndReachedThreshold, onStartReached, onStartReachedThreshold, initialScrollToRowId, onRowReorder, onMasterCellClick, activeRowId: activeRowIdProp, onSettingsOpenChange } = props;
19
19
  const masterCellActiveRowId = activeRowIdProp ?? null;
20
20
  const sortingEnabled = !!onSortingChange;
21
21
  const selectionEnabled = !!onRowSelectionChange;
@@ -203,6 +203,7 @@ const TableProvider = (props)=>{
203
203
  visibilityEnabled,
204
204
  hasSubRowGrouping: !!getSubRows,
205
205
  virtualized,
206
+ stretch,
206
207
  renderExpandedRow: renderExpandedRow,
207
208
  estimateRowHeight,
208
209
  overscan,
@@ -245,6 +246,7 @@ const TableProvider = (props)=>{
245
246
  visibilityEnabled,
246
247
  getSubRows,
247
248
  virtualized,
249
+ stretch,
248
250
  renderExpandedRow,
249
251
  estimateRowHeight,
250
252
  overscan,
@@ -25,6 +25,7 @@ export interface TableContextValue<T extends RowData> {
25
25
  visibilityEnabled: boolean;
26
26
  hasSubRowGrouping: boolean;
27
27
  virtualized: TableVirtualized | undefined;
28
+ stretch: boolean;
28
29
  renderExpandedRow?: (row: Row<DSTableFeatures, T>) => ReactNode;
29
30
  estimateRowHeight?: (index: number) => number;
30
31
  overscan: number;
@@ -1,21 +1,26 @@
1
- import { jsx } from "react/jsx-runtime";
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  import { useTestId } from "../../utils/testId.js";
4
- import { THead, Tr } from "./primitives/index.js";
4
+ import { THead, Th, Tr } from "./primitives/index.js";
5
5
  import { useTableContext } from "./TableContext/index.js";
6
6
  import { TableHeadCell } from "./TableHeadCell.js";
7
7
  const TableHead = ()=>{
8
- const { table } = useTableContext();
8
+ const { table, stretch } = useTableContext();
9
9
  const testId = useTestId('head');
10
10
  const hasTextDescription = table.getAllLeafColumns().some((col)=>col.columnDef.meta?.description?.type === 'text');
11
11
  return /*#__PURE__*/ jsx(THead, {
12
12
  className: cn('sticky top-0 z-30', hasTextDescription ? 'h-48' : 'h-32'),
13
13
  "data-testid": testId,
14
- children: table.getHeaderGroups().map((headerGroup)=>/*#__PURE__*/ jsx(Tr, {
15
- children: headerGroup.headers.map((header)=>/*#__PURE__*/ jsx(TableHeadCell, {
16
- header: header,
17
- hasTextDescription: hasTextDescription
18
- }, header.id))
14
+ children: table.getHeaderGroups().map((headerGroup)=>/*#__PURE__*/ jsxs(Tr, {
15
+ children: [
16
+ headerGroup.headers.map((header)=>/*#__PURE__*/ jsx(TableHeadCell, {
17
+ header: header,
18
+ hasTextDescription: hasTextDescription
19
+ }, header.id)),
20
+ !stretch && /*#__PURE__*/ jsx(Th, {
21
+ "aria-hidden": true
22
+ })
23
+ ]
19
24
  }, headerGroup.id))
20
25
  });
21
26
  };
@@ -1,11 +1,11 @@
1
- import { Fragment, jsx } from "react/jsx-runtime";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  import { useTestId } from "../../utils/testId.js";
4
4
  import { Skeleton } from "../Skeleton/index.js";
5
5
  import { Td, Tr } from "./primitives/index.js";
6
6
  import { useTableContext } from "./TableContext/index.js";
7
7
  const TableLoadingState = ({ position = 'end', count })=>{
8
- const { table, skeletonCount } = useTableContext();
8
+ const { table, skeletonCount, stretch } = useTableContext();
9
9
  const testId = useTestId('start' === position ? 'loading-start' : 'loading');
10
10
  const columns = table.getVisibleLeafColumns();
11
11
  const lastRowIdx = (count ?? skeletonCount) - 1;
@@ -14,19 +14,25 @@ const TableLoadingState = ({ position = 'end', count })=>{
14
14
  length: count ?? skeletonCount
15
15
  }, (_, rowIdx)=>{
16
16
  const key = `skeleton-${rowIdx}`;
17
- return /*#__PURE__*/ jsx(Tr, {
17
+ return /*#__PURE__*/ jsxs(Tr, {
18
18
  "data-testid": 0 === rowIdx ? testId : void 0,
19
19
  "data-loading-position": position,
20
- children: columns.map((column)=>/*#__PURE__*/ jsx(Td, {
21
- className: cn('px-16 py-8 border-b border-r border-border-primary-light', 'end' === position && rowIdx === lastRowIdx && 'border-b-0'),
22
- style: {
23
- width: column.getSize()
24
- },
25
- children: /*#__PURE__*/ jsx(Skeleton, {
26
- width: "100%",
27
- height: "20px"
28
- })
29
- }, column.id))
20
+ children: [
21
+ columns.map((column)=>/*#__PURE__*/ jsx(Td, {
22
+ className: cn('px-16 py-8 border-b border-r border-border-primary-light', 'end' === position && rowIdx === lastRowIdx && 'border-b-0'),
23
+ style: {
24
+ width: column.getSize()
25
+ },
26
+ children: /*#__PURE__*/ jsx(Skeleton, {
27
+ width: "100%",
28
+ height: "20px"
29
+ })
30
+ }, column.id)),
31
+ !stretch && /*#__PURE__*/ jsx(Td, {
32
+ pinned: false,
33
+ "aria-hidden": true
34
+ })
35
+ ]
30
36
  }, key);
31
37
  })
32
38
  });
@@ -1,11 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  const TableMasterCellActions = ({ children })=>/*#__PURE__*/ jsx("div", {
4
- className: cn('shrink-0 grid grid-cols-[0fr] opacity-0 pr-4', 'group-hover/row:grid-cols-[1fr] group-hover/row:opacity-100 group-hover/row:pl-4', 'group-data-[selected]/row:grid-cols-[1fr] group-data-[selected]/row:opacity-100 group-data-[selected]/row:pl-4', 'group-data-[preview-active]/row:grid-cols-[1fr] group-data-[preview-active]/row:opacity-100 group-data-[preview-active]/row:pl-4'),
5
- children: /*#__PURE__*/ jsx("div", {
6
- className: "overflow-hidden flex items-center gap-2",
7
- children: children
8
- })
4
+ className: cn('shrink-0 pl-4 pr-4 flex items-center gap-2', 'opacity-0 pointer-events-none', 'group-hover/row:opacity-100 group-hover/row:pointer-events-auto', 'group-data-[selected]/row:opacity-100 group-data-[selected]/row:pointer-events-auto', 'group-data-[preview-active]/row:opacity-100 group-data-[preview-active]/row:pointer-events-auto'),
5
+ children: children
9
6
  });
10
7
  TableMasterCellActions.displayName = 'TableMasterCellActions';
11
8
  export { TableMasterCellActions };
@@ -5,6 +5,7 @@ import { useTestId } from "../../utils/testId.js";
5
5
  import { TABLE_DRAG_HANDLE_COLUMN_ID, TABLE_EXPAND_COLUMN_ID, TABLE_SELECT_COLUMN_ID, useRowDnd } from "./lib/index.js";
6
6
  import { Td, Tr } from "./primitives/index.js";
7
7
  import { TableBodyCell } from "./TableBody/TableBodyCell.js";
8
+ import { useRowDndIndicator } from "./TableBody/TableBodyRowDndContext.js";
8
9
  import { useTableContext } from "./TableContext/index.js";
9
10
  import { TableRowExpanded } from "./TableRowExpanded.js";
10
11
  const SYSTEM_COLUMN_IDS = new Set([
@@ -13,9 +14,10 @@ const SYSTEM_COLUMN_IDS = new Set([
13
14
  TABLE_DRAG_HANDLE_COLUMN_ID
14
15
  ]);
15
16
  const TableRowInner = ({ row, ref, 'data-index': dataIndex })=>{
16
- const { table, expandingEnabled, activeRowId, isLoading, renderExpandedRow } = useTableContext();
17
+ const { table, expandingEnabled, activeRowId, isLoading, renderExpandedRow, stretch, hasSubRowGrouping, allLeafColumns } = useTableContext();
17
18
  const testId = useTestId('row');
18
19
  const { canDnd, isDragging, setNodeRef, style: dndStyle, attributes, listeners } = useRowDnd(row);
20
+ const { activeId, overId } = useRowDndIndicator();
19
21
  const isGroupParent = row.subRows.length > 0;
20
22
  const isSelected = isGroupParent ? row.getIsAllSubRowsSelected() : row.getIsSelected();
21
23
  const isPreviewActive = activeRowId === row.id;
@@ -38,6 +40,11 @@ const TableRowInner = ({ row, ref, 'data-index': dataIndex })=>{
38
40
  const systemCells = cells.filter((c)=>SYSTEM_COLUMN_IDS.has(c.column.id));
39
41
  const dataCells = cells.filter((c)=>!SYSTEM_COLUMN_IDS.has(c.column.id));
40
42
  const firstDataCell = dataCells[0];
43
+ const stickyStyle = hasSubRowGrouping && row.getIsExpanded() ? {
44
+ position: 'sticky',
45
+ top: allLeafColumns.some((c)=>c.columnDef.meta?.description?.type === 'text') ? 48 : 32,
46
+ zIndex: 20
47
+ } : void 0;
41
48
  return /*#__PURE__*/ jsxs(Fragment, {
42
49
  children: [
43
50
  /*#__PURE__*/ jsxs(Tr, {
@@ -49,6 +56,7 @@ const TableRowInner = ({ row, ref, 'data-index': dataIndex })=>{
49
56
  "data-selected": isSelected || void 0,
50
57
  "data-preview-active": isPreviewActive || void 0,
51
58
  "aria-selected": isSelected || void 0,
59
+ style: stickyStyle,
52
60
  children: [
53
61
  systemCells.map((cell)=>/*#__PURE__*/ jsx(TableBodyCell, {
54
62
  cell: cell,
@@ -67,7 +75,11 @@ const TableRowInner = ({ row, ref, 'data-index': dataIndex })=>{
67
75
  width: cell.column.getSize()
68
76
  },
69
77
  "aria-hidden": "true"
70
- }, cell.id))
78
+ }, cell.id)),
79
+ !stretch && /*#__PURE__*/ jsx(Td, {
80
+ pinned: false,
81
+ "aria-hidden": true
82
+ })
71
83
  ]
72
84
  }),
73
85
  expandingEnabled && /*#__PURE__*/ jsx(TableRowExpanded, {
@@ -77,9 +89,15 @@ const TableRowInner = ({ row, ref, 'data-index': dataIndex })=>{
77
89
  ]
78
90
  });
79
91
  }
92
+ let dropIndicator;
93
+ if (overId === row.id && null != activeId && activeId !== row.id) {
94
+ const activeIndex = flatRows.findIndex((r)=>r.id === activeId);
95
+ const overIndex = flatRows.findIndex((r)=>r.id === row.id);
96
+ if (-1 !== activeIndex && -1 !== overIndex) dropIndicator = activeIndex < overIndex ? 'below' : 'above';
97
+ }
80
98
  return /*#__PURE__*/ jsxs(Fragment, {
81
99
  children: [
82
- /*#__PURE__*/ jsx(Tr, {
100
+ /*#__PURE__*/ jsxs(Tr, {
83
101
  ref: composedRef,
84
102
  "data-index": dataIndex,
85
103
  "data-row-id": row.id,
@@ -91,15 +109,22 @@ const TableRowInner = ({ row, ref, 'data-index': dataIndex })=>{
91
109
  "aria-selected": isSelected || void 0,
92
110
  "data-depth": row.depth > 0 ? row.depth : void 0,
93
111
  style: dndStyle,
94
- children: row.getVisibleCells().map((cell)=>{
95
- const isDragHandle = cell.column.id === TABLE_DRAG_HANDLE_COLUMN_ID;
96
- return /*#__PURE__*/ jsx(TableBodyCell, {
97
- cell: cell,
98
- dragListeners: isDragHandle ? listeners : void 0,
99
- dragAttributes: isDragHandle ? attributes : void 0,
100
- lastRow: isLastRow
101
- }, cell.id);
102
- })
112
+ children: [
113
+ row.getVisibleCells().map((cell)=>{
114
+ const isDragHandle = cell.column.id === TABLE_DRAG_HANDLE_COLUMN_ID;
115
+ return /*#__PURE__*/ jsx(TableBodyCell, {
116
+ cell: cell,
117
+ dragListeners: isDragHandle ? listeners : void 0,
118
+ dragAttributes: isDragHandle ? attributes : void 0,
119
+ lastRow: isLastRow,
120
+ dropIndicator: dropIndicator
121
+ }, cell.id);
122
+ }),
123
+ !stretch && /*#__PURE__*/ jsx(Td, {
124
+ pinned: false,
125
+ "aria-hidden": true
126
+ })
127
+ ]
103
128
  }),
104
129
  expandingEnabled && /*#__PURE__*/ jsx(TableRowExpanded, {
105
130
  row: row,
@@ -5,12 +5,13 @@ import { TABLE_EXPAND_COLUMN_ID } from "./lib/index.js";
5
5
  import { Td, Tr } from "./primitives/index.js";
6
6
  import { useTableContext } from "./TableContext/index.js";
7
7
  const TableRowExpanded = ({ row, dndStyle, lastRow })=>{
8
- const { table, renderExpandedRow } = useTableContext();
8
+ const { table, stretch, renderExpandedRow } = useTableContext();
9
9
  const testId = useTestId('row-expanded');
10
10
  if (!row.getIsExpanded() || !renderExpandedRow) return null;
11
11
  const visibleColumns = table.getVisibleLeafColumns();
12
12
  const hasExpandColumn = visibleColumns.some((col)=>col.id === TABLE_EXPAND_COLUMN_ID);
13
- const contentColSpan = hasExpandColumn ? visibleColumns.length - 1 : visibleColumns.length;
13
+ const fillerOffset = stretch ? 0 : 1;
14
+ const contentColSpan = (hasExpandColumn ? visibleColumns.length - 1 : visibleColumns.length) + fillerOffset;
14
15
  return /*#__PURE__*/ jsxs(Tr, {
15
16
  "data-testid": testId,
16
17
  style: dndStyle,
@@ -55,6 +55,7 @@ const useStickyGroupParent = (options)=>{
55
55
  const [pushUpOffset, setPushUpOffset] = useState(0);
56
56
  const rafRef = useRef(0);
57
57
  const prevStickyRowIdRef = useRef(null);
58
+ const prevOffsetRef = useRef(0);
58
59
  const compute = useCallback(()=>{
59
60
  if (!enabled) {
60
61
  if (null !== prevStickyRowIdRef.current) {
@@ -98,8 +99,9 @@ const useStickyGroupParent = (options)=>{
98
99
  }
99
100
  }
100
101
  const newId = foundRow?.id ?? null;
101
- if (newId !== prevStickyRowIdRef.current || 0 !== offset) {
102
+ if (newId !== prevStickyRowIdRef.current || offset !== prevOffsetRef.current) {
102
103
  prevStickyRowIdRef.current = newId;
104
+ prevOffsetRef.current = offset;
103
105
  setStickyRow(foundRow);
104
106
  setPushUpOffset(offset);
105
107
  }
@@ -8,7 +8,7 @@ export declare const TABLE_SELECT_COLUMN_WIDTH = 33;
8
8
  export declare const TABLE_EXPAND_COLUMN_ID = "_expand";
9
9
  export declare const TABLE_EXPAND_COLUMN_WIDTH = 33;
10
10
  export declare const TABLE_DRAG_HANDLE_COLUMN_ID = "_dragHandle";
11
- export declare const TABLE_DRAG_HANDLE_COLUMN_WIDTH = 33;
11
+ export declare const TABLE_DRAG_HANDLE_COLUMN_WIDTH = 24;
12
12
  export declare const TABLE_END_REACHED_THRESHOLD = 200;
13
13
  export declare const TABLE_START_REACHED_THRESHOLD = 200;
14
14
  /** Minimum time (ms) between successive edge-reached callbacks. */
@@ -7,7 +7,7 @@ const TABLE_SELECT_COLUMN_WIDTH = 33;
7
7
  const TABLE_EXPAND_COLUMN_ID = '_expand';
8
8
  const TABLE_EXPAND_COLUMN_WIDTH = 33;
9
9
  const TABLE_DRAG_HANDLE_COLUMN_ID = '_dragHandle';
10
- const TABLE_DRAG_HANDLE_COLUMN_WIDTH = 33;
10
+ const TABLE_DRAG_HANDLE_COLUMN_WIDTH = 24;
11
11
  const TABLE_END_REACHED_THRESHOLD = 200;
12
12
  const TABLE_START_REACHED_THRESHOLD = 200;
13
13
  const SCROLL_EDGE_COOLDOWN_MS = 200;
@@ -11,13 +11,13 @@ const createDragHandleColumn = ()=>({
11
11
  enableHiding: false,
12
12
  enablePinning: false,
13
13
  meta: {
14
- headerClassName: 'px-8 py-4',
15
- cellClassName: 'px-8 py-8'
14
+ headerClassName: 'px-4 py-4',
15
+ cellClassName: 'px-4 py-8'
16
16
  },
17
17
  header: ()=>null,
18
18
  cell: ()=>/*#__PURE__*/ jsx(GripVertical, {
19
19
  size: "sm",
20
- className: "text-text-tertiary"
20
+ className: "text-text-secondary"
21
21
  })
22
22
  });
23
23
  export { createDragHandleColumn };
@@ -1,24 +1,14 @@
1
1
  import { useSortable } from "@dnd-kit/sortable";
2
- import { CSS } from "@dnd-kit/utilities";
3
2
  import { useTableContext } from "../TableContext/useTableContext.js";
4
3
  const useRowDnd = (row)=>{
5
4
  const { rowDndEnabled } = useTableContext();
6
5
  const canDnd = rowDndEnabled && 0 === row.subRows.length;
7
- const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
6
+ const { attributes, listeners, setNodeRef, isDragging } = useSortable({
8
7
  id: row.id,
9
8
  disabled: !canDnd
10
9
  });
11
- const style = canDnd ? {
12
- transform: CSS.Translate.toString(transform ? {
13
- ...transform,
14
- x: 0
15
- } : null),
16
- transition,
17
- ...isDragging && {
18
- opacity: 0.5,
19
- position: 'relative',
20
- zIndex: 100
21
- }
10
+ const style = canDnd && isDragging ? {
11
+ opacity: 0.4
22
12
  } : {};
23
13
  return {
24
14
  canDnd,
@@ -247,6 +247,14 @@ export interface TableProps<T> extends TestableProps {
247
247
  onSettingsOpenChange?: (open: boolean) => void;
248
248
  /** Enable row virtualization. `'container'` virtualizes within the scroll container; `'window'` virtualizes against the browser window. */
249
249
  virtualized?: TableVirtualized;
250
+ /**
251
+ * Whether columns stretch proportionally to fill the container width.
252
+ * When `false`, columns use their defined sizes and the table may be
253
+ * narrower than its container.
254
+ *
255
+ * Default: `true`.
256
+ */
257
+ stretch?: boolean;
250
258
  estimateRowHeight?: (index: number) => number;
251
259
  overscan?: number;
252
260
  /** Callback fired when the user scrolls near the end (bottom) of the table */
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.20.3",
3
- "generatedAt": "2026-09-16T12:28:29.151Z",
2
+ "version": "1.20.4",
3
+ "generatedAt": "2026-09-16T18:12:26.773Z",
4
4
  "components": [
5
5
  {
6
6
  "name": "Accordion",
@@ -79360,6 +79360,12 @@
79360
79360
  "required": false,
79361
79361
  "description": "Enable row virtualization. `'container'` virtualizes within the scroll container; `'window'` virtualizes against the browser window."
79362
79362
  },
79363
+ {
79364
+ "name": "stretch",
79365
+ "type": "boolean | undefined",
79366
+ "required": false,
79367
+ "description": "Whether columns stretch proportionally to fill the container width.\nWhen `false`, columns use their defined sizes and the table may be\nnarrower than its container.\n\nDefault: `true`."
79368
+ },
79363
79369
  {
79364
79370
  "name": "estimateRowHeight",
79365
79371
  "type": "((index: number) => number) | undefined",
@@ -80672,7 +80678,7 @@
80672
80678
  "name": "placeholder",
80673
80679
  "type": "ReactNode",
80674
80680
  "required": false,
80675
- "description": "Shown when nothing is selected. Defaults to `'Select'`."
80681
+ "description": "Shown when nothing is selected. Defaults to `'Select'`."
80676
80682
  },
80677
80683
  {
80678
80684
  "name": "color",
@@ -85364,6 +85370,11 @@
85364
85370
  "code": "() => {\n const [sorting, setSorting] = useState<TableSortingState>([{ id: 'firstDetected', desc: true }]);\n\n return (\n <Table\n data={securityEvents}\n columns={securityColumns}\n getRowId={row => row.id}\n sorting={sorting}\n onSortingChange={setSorting}\n />\n );\n}",
85365
85371
  "description": "The minimum — `data`, `columns`, `getRowId` and a column to open sorted on. The header stays\nput as the body scrolls."
85366
85372
  },
85373
+ {
85374
+ "name": "NoStretch",
85375
+ "code": "() => {\n const narrowColumns: TableColumnDef<SecurityEvent>[] = [\n securityColumnHelper.accessor('objectName', {\n header: 'Object name',\n size: 200,\n }),\n securityColumnHelper.accessor('status', {\n header: 'Status',\n size: 120,\n }),\n securityColumnHelper.accessor('requests', {\n header: 'Requests',\n size: 100,\n }),\n ];\n\n return (\n <Table data={securityEvents} columns={narrowColumns} getRowId={row => row.id} stretch={false} />\n );\n}",
85376
+ "description": "`stretch={false}` — columns keep their defined widths and do not expand to fill the container.\nEmpty space appears on the right when the total column width is less than the container width."
85377
+ },
85367
85378
  {
85368
85379
  "name": "WithPagination",
85369
85380
  "code": "() => {\n const allData = useMemo(() => createLargeSecurityEvents(47), []);\n const { pageData, ...pagination } = useClientPagination(allData, 10);\n\n return (\n <VStack gap={12}>\n <Table data={pageData} columns={securityColumns} getRowId={row => row.id} />\n <Pagination {...pagination} align='right' aria-label='Security events'>\n <PaginationPageSize options={[10, 25, 50]} />\n <PaginationPrevious />\n <PaginationList />\n <PaginationNext />\n </Pagination>\n </VStack>\n );\n}",
@@ -85551,7 +85562,7 @@
85551
85562
  },
85552
85563
  {
85553
85564
  "name": "InlineCellEditing",
85554
- "code": "() => {\n const [data, setData] = useState<SecurityEvent[]>(() => securityEvents.slice(0, 6));\n // Category starts unselected for every row, so the select shows its placeholder.\n const [categories, setCategories] = useState<Record<string, string>>({});\n\n const updateCell = useCallback(\n <K extends keyof SecurityEvent>(rowId: string, key: K, value: SecurityEvent[K]) => {\n setData(prev => prev.map(row => (row.id === rowId ? { ...row, [key]: value } : row)));\n },\n [],\n );\n\n const columns = useMemo<TableColumnDef<SecurityEvent>[]>(\n () => [\n // The first column is the Table's pinned \"master\" column — keep it\n // read-only; editable cells live in the plain columns after it.\n securityColumnHelper.accessor('sourceIp', {\n header: 'Source',\n size: 200,\n meta: { resizeType: 'cut' as const },\n cell: ({ getValue }) => <Text size='sm'>{getValue()}</Text>,\n }),\n securityColumnHelper.accessor('objectName', {\n header: 'Object name',\n size: 400,\n meta: EDITABLE_CELL_COLUMN_META,\n cell: ({ row, getValue }) => (\n <EditableTextCell\n value={getValue()}\n aria-label='Edit object name'\n onCommit={value => updateCell(row.id, 'objectName', value)}\n />\n ),\n }),\n securityColumnHelper.accessor('status', {\n header: 'Status',\n size: 200,\n meta: EDITABLE_CELL_COLUMN_META,\n cell: ({ row, getValue }) => (\n <EditableSelectCell\n value={getValue()}\n items={statusItems}\n onCommit={value => updateCell(row.id, 'status', value as SecurityEvent['status'])}\n >\n <StatusBadge value={getValue()} />\n </EditableSelectCell>\n ),\n }),\n // Empty-by-default select: consumer supplies the `placeholder` text.\n securityColumnHelper.display({\n id: 'category',\n header: 'Category',\n size: 200,\n meta: EDITABLE_CELL_COLUMN_META,\n cell: ({ row }) => {\n const value = categories[row.id] ?? '';\n return (\n <EditableSelectCell\n value={value}\n items={categoryItems}\n placeholder='Select'\n aria-label='Edit category'\n onCommit={next => setCategories(prev => ({ ...prev, [row.id]: next }))}\n >\n {categoryItems.find(item => item.value === value)?.label}\n </EditableSelectCell>\n );\n },\n }),\n securityColumnHelper.accessor('parameter', {\n header: 'Parameters',\n size: 240,\n meta: { resizeType: 'cut' as const },\n cell: ({ getValue }) => <InlineCodeSnippet code={getValue()} size='sm' copyable={false} />,\n }),\n ],\n [updateCell, categories],\n );\n\n return (\n <VStack gap={12} align='stretch'>\n <span className='sb-annotation'>click a cell to edit it</span>\n <Table data={data} columns={columns} getRowId={row => row.id} />\n </VStack>\n );\n}"
85565
+ "code": "() => {\n const [data, setData] = useState<SecurityEvent[]>(() => securityEvents.slice(0, 6));\n // Category starts unselected for every row, so the select shows its placeholder.\n const [categories, setCategories] = useState<Record<string, string>>({});\n\n const updateCell = useCallback(\n <K extends keyof SecurityEvent>(rowId: string, key: K, value: SecurityEvent[K]) => {\n setData(prev => prev.map(row => (row.id === rowId ? { ...row, [key]: value } : row)));\n },\n [],\n );\n\n const columns = useMemo<TableColumnDef<SecurityEvent>[]>(\n () => [\n // The first column is the Table's pinned \"master\" column — keep it\n // read-only; editable cells live in the plain columns after it.\n securityColumnHelper.accessor('sourceIp', {\n header: 'Source',\n size: 200,\n meta: { resizeType: 'cut' as const },\n cell: ({ getValue }) => <Text size='sm'>{getValue()}</Text>,\n }),\n securityColumnHelper.accessor('objectName', {\n header: 'Object name',\n size: 400,\n meta: EDITABLE_CELL_COLUMN_META,\n cell: ({ row, getValue }) => (\n <EditableTextCell\n value={getValue()}\n aria-label='Edit object name'\n onCommit={value => updateCell(row.id, 'objectName', value)}\n />\n ),\n }),\n securityColumnHelper.accessor('status', {\n header: 'Status',\n size: 200,\n meta: EDITABLE_CELL_COLUMN_META,\n cell: ({ row, getValue }) => (\n <EditableSelectCell\n value={getValue()}\n items={statusItems}\n onCommit={value => updateCell(row.id, 'status', value as SecurityEvent['status'])}\n >\n <StatusBadge value={getValue()} />\n </EditableSelectCell>\n ),\n }),\n // Empty-by-default select: consumer supplies the `placeholder` text.\n securityColumnHelper.display({\n id: 'category',\n header: 'Category',\n size: 200,\n meta: EDITABLE_CELL_COLUMN_META,\n cell: ({ row }) => {\n const value = categories[row.id] ?? '';\n return (\n <EditableSelectCell\n value={value}\n items={categoryItems}\n placeholder='Select'\n aria-label='Edit category'\n onCommit={next => setCategories(prev => ({ ...prev, [row.id]: next }))}\n >\n {categoryItems.find(item => item.value === value)?.label}\n </EditableSelectCell>\n );\n },\n }),\n securityColumnHelper.accessor('parameter', {\n header: 'Parameters',\n size: 240,\n meta: { resizeType: 'cut' as const },\n cell: ({ getValue }) => <InlineCodeSnippet code={getValue()} size='sm' copyable={false} />,\n }),\n ],\n [updateCell, categories],\n );\n\n return (\n <VStack gap={12} align='stretch'>\n <span className='sb-annotation'>click a cell to edit it</span>\n <Table data={data} columns={columns} getRowId={row => row.id} />\n </VStack>\n );\n}"
85555
85566
  },
85556
85567
  {
85557
85568
  "name": "StickyGroupParentStory",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wallarm-org/design-system",
3
- "version": "1.20.4",
3
+ "version": "1.21.0",
4
4
  "description": "Core design system library with React components and Storybook documentation",
5
5
  "publishConfig": {
6
6
  "access": "public",