@drivenets/design-system 0.16.0 → 0.18.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.
- package/CHANGELOG.md +31 -0
- package/dist/index.cjs +1893 -824
- package/dist/index.d.cts +363 -247
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +363 -247
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1896 -829
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +25 -25
- package/src/components/ds-alert-banner/ds-alert-banner-global.figma.ts +49 -0
- package/src/components/ds-alert-banner/ds-alert-banner.figma.ts +51 -0
- package/src/components/ds-alert-banner/ds-alert-banner.tsx +7 -6
- package/src/components/ds-autocomplete/ds-autocomplete.figma.ts +2 -2
- package/src/components/ds-autocomplete/ds-autocomplete.module.scss +15 -4
- package/src/components/ds-autocomplete/ds-autocomplete.tsx +10 -3
- package/src/components/ds-autocomplete/ds-autocomplete.types.ts +8 -0
- package/src/components/ds-avatar/ds-avatar.figma.ts +2 -2
- package/src/components/ds-avatar-group/ds-avatar-group.figma.ts +2 -2
- package/src/components/ds-breadcrumb/ds-breadcrumb.figma.ts +2 -2
- package/src/components/ds-button-v3/ds-button-v3.figma.ts +7 -5
- package/src/components/ds-button-v3/ds-button-v3.module.scss +84 -17
- package/src/components/ds-button-v3/ds-button-v3.tsx +2 -0
- package/src/components/ds-button-v3/ds-button-v3.types.ts +11 -2
- package/src/components/ds-button-v3/ds-button-v4.figma.ts +121 -0
- package/src/components/ds-card/figma/ds-card-content.figma.ts +2 -2
- package/src/components/ds-card/figma/ds-card-footer.figma.ts +2 -2
- package/src/components/ds-card/figma/ds-card-header.figma.ts +2 -2
- package/src/components/ds-card/figma/ds-card.figma.ts +2 -2
- package/src/components/ds-catalog-layout/ds-catalog-layout.figma.ts +51 -0
- package/src/components/ds-catalog-layout/ds-catalog-layout.tsx +9 -8
- package/src/components/ds-checkbox/ds-checkbox-level-2.figma.ts +2 -2
- package/src/components/ds-checkbox/ds-checkbox.figma.ts +2 -2
- package/src/components/ds-checkbox-group/ds-checkbox-group.figma.ts +2 -2
- package/src/components/ds-comment-bubble/ds-comment-bubble.figma.ts +52 -0
- package/src/components/ds-comment-card/ds-comment-card.figma.ts +36 -0
- package/src/components/ds-comment-indicator/ds-comment-indicator.figma.ts +32 -0
- package/src/components/ds-comments-drawer/components/comments-filter-modal/index.ts +0 -1
- package/src/components/ds-comments-drawer/ds-comments-drawer.figma.ts +19 -0
- package/src/components/ds-confirmation/ds-confirmation.tsx +13 -11
- package/src/components/ds-date-picker/ds-date-picker.figma.ts +2 -2
- package/src/components/ds-divider/ds-divider.figma.ts +2 -2
- package/src/components/ds-drawer/ds-drawer.tsx +11 -10
- package/src/components/ds-drawer/figma/ds-drawer-content.figma.ts +2 -2
- package/src/components/ds-drawer/figma/ds-drawer-footer.figma.ts +2 -2
- package/src/components/ds-drawer/figma/ds-drawer-header.figma.ts +2 -2
- package/src/components/ds-drawer/figma/ds-drawer.figma.ts +2 -2
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-footer.figma.ts +2 -2
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-group.figma.ts +2 -2
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-item.figma.ts +2 -2
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu-separator.figma.ts +2 -2
- package/src/components/ds-dropdown-menu/figma/ds-dropdown-menu.figma.ts +2 -2
- package/src/components/ds-expandable-text-input/ds-expandable-text-input.figma.ts +2 -2
- package/src/components/ds-file-upload/components/file-upload-item/index.ts +0 -1
- package/src/components/ds-file-upload/ds-file-upload.figma.ts +2 -2
- package/src/components/ds-filter-status-icon/ds-filter-status-icon.figma.ts +2 -2
- package/src/components/ds-form-control/ds-form-control.figma.ts +2 -2
- package/src/components/ds-form-control/ds-form-control.tsx +15 -13
- package/src/components/ds-icon/figma/ds-icon-material.figma.batch.ts +1 -1
- package/src/components/ds-icon/figma/ds-icon-special.figma.batch.ts +1 -1
- package/src/components/ds-key-value-pair/ds-key-value-pair.figma.ts +2 -2
- package/src/components/ds-loader/ds-loader.figma.ts +2 -2
- package/src/components/ds-modal/ds-modal.tsx +10 -9
- package/src/components/ds-modal/figma/ds-modal-content.figma.ts +2 -2
- package/src/components/ds-modal/figma/ds-modal-footer.figma.ts +2 -2
- package/src/components/ds-modal/figma/ds-modal-header.figma.ts +2 -2
- package/src/components/ds-modal/figma/ds-modal.figma.ts +2 -2
- package/src/components/ds-number-input/ds-number-input.tsx +1 -0
- package/src/components/ds-panel/ds-panel.figma.ts +2 -2
- package/src/components/ds-popover/figma/ds-popover-content-item.figma.ts +2 -2
- package/src/components/ds-popover/figma/ds-popover-content.figma.ts +2 -2
- package/src/components/ds-popover/figma/ds-popover-footer.figma.ts +2 -2
- package/src/components/ds-popover/figma/ds-popover-header.figma.ts +2 -2
- package/src/components/ds-popover/figma/ds-popover.figma.ts +2 -2
- package/src/components/ds-progress-arc/ds-progress-arc.figma.ts +2 -2
- package/src/components/ds-progress-donut/ds-progress-donut.figma.ts +2 -2
- package/src/components/ds-progress-linear/ds-progress-linear.figma.ts +2 -2
- package/src/components/ds-progress-task-bar/ds-progress-task-bar.figma.ts +2 -2
- package/src/components/ds-radio-group/figma/ds-radio-group-item.figma.ts +2 -2
- package/src/components/ds-radio-group/figma/ds-radio-group.figma.ts +2 -2
- package/src/components/ds-segment-group/figma/ds-segment-group-item.figma.ts +2 -2
- package/src/components/ds-segment-group/figma/ds-segment-group.figma.ts +2 -2
- package/src/components/ds-select/ds-select.figma.ts +4 -3
- package/src/components/ds-select/ds-select.tsx +6 -1
- package/src/components/ds-select/ds-select.types.ts +2 -1
- package/src/components/ds-site-node/ds-site-node.figma.ts +2 -2
- package/src/components/ds-slider/ds-slider.figma.ts +29 -0
- package/src/components/ds-slider/ds-slider.module.scss +104 -0
- package/src/components/ds-slider/ds-slider.tsx +118 -0
- package/src/components/ds-slider/ds-slider.types.ts +102 -0
- package/src/components/ds-slider/ds-slider.utils.ts +14 -0
- package/src/components/ds-slider/index.ts +11 -0
- package/src/components/ds-smart-tabs/ds-smart-tabs.tsx +5 -4
- package/src/components/ds-smart-tabs/figma/ds-smart-tabs-tab.figma.ts +83 -0
- package/src/components/ds-smart-tabs/figma/ds-smart-tabs.figma.ts +23 -0
- package/src/components/ds-spinner/ds-spinner.figma.ts +2 -2
- package/src/components/ds-split-button/ds-split-button.figma.ts +2 -2
- package/src/components/ds-status-badge-v2/ds-status-badge-v2.figma.ts +2 -2
- package/src/components/ds-stepper/ds-stepper.figma.ts +2 -2
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.module.scss +5 -1
- package/src/components/ds-table/components/ds-table-group-header-cell/ds-table-group-header-cell.tsx +15 -3
- package/src/components/ds-table/components/ds-table-group-header-cell/index.ts +0 -1
- package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +17 -3
- package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +30 -9
- package/src/components/ds-table/components/ds-table-resize-handle/ds-table-resize-handle.module.scss +23 -0
- package/src/components/ds-table/components/ds-table-resize-handle/ds-table-resize-handle.tsx +218 -0
- package/src/components/ds-table/components/ds-table-resize-handle/ds-table-resize-handle.types.ts +14 -0
- package/src/components/ds-table/components/ds-table-resize-handle/index.ts +1 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.module.scss +18 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.tsx +16 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.types.ts +13 -0
- package/src/components/ds-table/components/ds-table-resize-overlay/index.ts +1 -0
- package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +1 -1
- package/src/components/ds-table/components/ds-table-row/ds-table-row.tsx +9 -2
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.module.scss +2 -1
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.tsx +9 -2
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-checkbox.tsx +2 -2
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-date.tsx +2 -1
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-number.tsx +2 -1
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-select.tsx +2 -1
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-text.tsx +2 -1
- package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.tsx +12 -3
- package/src/components/ds-table/context/ds-table-context.tsx +208 -0
- package/src/components/ds-table/ds-table-defaults.ts +42 -0
- package/src/components/ds-table/ds-table.module.scss +19 -1
- package/src/components/ds-table/ds-table.tsx +163 -235
- package/src/components/ds-table/ds-table.types.ts +59 -47
- package/src/components/ds-table/figma/ds-table-expandable.figma.ts +2 -2
- package/src/components/ds-table/figma/ds-table.figma.ts +2 -2
- package/src/components/ds-table/grouping/utils/column-group.ts +7 -5
- package/src/components/ds-table/hooks/use-cell-editor.ts +5 -1
- package/src/components/ds-table/hooks/use-column-resize.ts +385 -0
- package/src/components/ds-table/hooks/use-editing-state.ts +190 -0
- package/src/components/ds-table/index.ts +1 -0
- package/src/components/ds-table/styles/_variables.scss +2 -1
- package/src/components/ds-table/utils/column-size-meta.augmentation.ts +16 -0
- package/src/components/ds-table/utils/column-size.ts +213 -10
- package/src/components/ds-table/utils/column-size.unit.test.ts +213 -0
- package/src/components/ds-table/utils/constants.ts +28 -0
- package/src/components/ds-table/utils/frozen-body.ts +33 -0
- package/src/components/ds-table/utils/frozen-body.unit.test.ts +44 -0
- package/src/components/ds-table/utils/table-api.ts +42 -0
- package/src/components/ds-table/utils/table-api.unit.test.ts +82 -0
- package/src/components/ds-table/utils/table-columns.tsx +119 -0
- package/src/components/ds-table/utils/table-columns.unit.test.ts +199 -0
- package/src/components/ds-tabs/figma/ds-tabs-tab-vertical.figma.ts +2 -2
- package/src/components/ds-tabs/figma/ds-tabs-tab.figma.ts +2 -2
- package/src/components/ds-tabs/figma/ds-tabs-vertical.figma.ts +2 -2
- package/src/components/ds-tabs/figma/ds-tabs.figma.ts +2 -2
- package/src/components/ds-tag/ds-tag.figma.ts +51 -0
- package/src/components/ds-tag-filter/ds-tag-filter.figma.ts +16 -0
- package/src/components/ds-text-input/ds-input-field-v02.figma.ts +31 -6
- package/src/components/ds-text-input/ds-text-input.figma.ts +5 -4
- package/src/components/ds-text-input/ds-text-input.tsx +1 -0
- package/src/components/ds-text-input/ds-text-input.types.ts +1 -1
- package/src/components/ds-time-picker/ds-time-picker.figma.ts +2 -2
- package/src/components/ds-toast/ds-toast.figma.ts +3 -3
- package/src/components/ds-toggle/ds-toggle.figma.ts +2 -2
- package/src/components/ds-tooltip/ds-tooltip.figma.ts +2 -2
- package/src/components/ds-tree/ds-tree.figma.ts +54 -0
- package/src/components/ds-tree/ds-tree.module.scss +2 -2
- package/src/components/ds-tree/ds-tree.tsx +6 -0
- package/src/components/ds-tree/ds-tree.types.ts +16 -0
- package/src/components/ds-typography/ds-typography.figma.ts +2 -2
- package/src/components/ds-user-card/ds-user-card.figma.ts +2 -2
- package/src/components/ds-vertical-tabs/ds-vertical-tabs.tsx +13 -6
- package/src/components/ds-workspace-layout/ds-workspace-layout.figma.ts +99 -0
- package/src/components/ds-workspace-layout/ds-workspace-layout.module.scss +1 -8
- package/src/components/ds-workspace-layout/ds-workspace-layout.tsx +11 -10
- package/src/index.ts +1 -0
- package/src/styles/_gradients.scss +19 -0
- package/src/styles/_root.scss +39 -15
- package/src/styles/_typography.scss +1 -0
- package/src/styles/shared/_input.scss +10 -0
- package/src/styles/styles.scss +1 -0
- package/src/components/ds-table/context/ds-table-context.ts +0 -112
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useEffect,
|
|
3
|
+
useRef,
|
|
4
|
+
type KeyboardEvent,
|
|
5
|
+
type MouseEvent,
|
|
6
|
+
type PointerEvent,
|
|
7
|
+
type TouchEvent,
|
|
8
|
+
} from 'react';
|
|
9
|
+
import { useDsTableContext } from '../../context/ds-table-context';
|
|
10
|
+
import { defaultDsTableLocale } from '../../ds-table.types';
|
|
11
|
+
import {
|
|
12
|
+
RESIZE_KEYBOARD_STEP,
|
|
13
|
+
RESIZE_KEYBOARD_STEP_LARGE,
|
|
14
|
+
RESIZE_MIN_COLUMN_WIDTH,
|
|
15
|
+
} from '../../utils/constants';
|
|
16
|
+
import type { DsTableResizeHandleProps } from './ds-table-resize-handle.types';
|
|
17
|
+
import styles from './ds-table-resize-handle.module.scss';
|
|
18
|
+
|
|
19
|
+
const clientPointFromEvent = (event: Event): { x: number; y: number } | null => {
|
|
20
|
+
if (event instanceof MouseEvent) {
|
|
21
|
+
return { x: event.clientX, y: event.clientY };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (typeof TouchEvent !== 'undefined' && event instanceof TouchEvent) {
|
|
25
|
+
const touch = event.changedTouches[0];
|
|
26
|
+
return touch ? { x: touch.clientX, y: touch.clientY } : null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return null;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Handle straddling the right edge of a resizable header cell.
|
|
34
|
+
*
|
|
35
|
+
* Drag is TanStack v8 `header.getResizeHandler()`. Hover drives the full-height
|
|
36
|
+
* overlay; double-click restores snapshot origin widths for this header's
|
|
37
|
+
* leaves. As a focusable `separator`, Arrow keys nudge the width (Shift for a
|
|
38
|
+
* larger step) for keyboard operability (WCAG 2.1.1).
|
|
39
|
+
*/
|
|
40
|
+
export const DsTableResizeHandle = <TData, TValue>({ header }: DsTableResizeHandleProps<TData, TValue>) => {
|
|
41
|
+
const {
|
|
42
|
+
resizeContainerRef,
|
|
43
|
+
onResizeHover,
|
|
44
|
+
onResizeDragStart,
|
|
45
|
+
onResizeReset,
|
|
46
|
+
onResizeKeyboardNudge,
|
|
47
|
+
locale,
|
|
48
|
+
} = useDsTableContext<TData, TValue>();
|
|
49
|
+
const handleRef = useRef<HTMLDivElement>(null);
|
|
50
|
+
const isPointerOverRef = useRef(false);
|
|
51
|
+
const detachDragEndRef = useRef<(() => void) | null>(null);
|
|
52
|
+
|
|
53
|
+
useEffect(
|
|
54
|
+
() => () => {
|
|
55
|
+
detachDragEndRef.current?.();
|
|
56
|
+
},
|
|
57
|
+
[],
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const label = { ...defaultDsTableLocale, ...locale }.resizeColumn;
|
|
61
|
+
|
|
62
|
+
const measureCellRightOffset = (): number | null => {
|
|
63
|
+
const containerEl = resizeContainerRef?.current;
|
|
64
|
+
const cellEl = handleRef.current?.closest<HTMLElement>('th');
|
|
65
|
+
if (!containerEl || !cellEl) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
// The overlay is absolutely positioned inside the horizontally scrollable
|
|
69
|
+
// container, so its offset must be in the container's scrolled content
|
|
70
|
+
// space — add `scrollLeft` to the viewport-relative distance.
|
|
71
|
+
return (
|
|
72
|
+
cellEl.getBoundingClientRect().right - containerEl.getBoundingClientRect().left + containerEl.scrollLeft
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const reportHover = () => {
|
|
77
|
+
const offset = measureCellRightOffset();
|
|
78
|
+
if (offset === null) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
onResizeHover?.(header.column.id, offset);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const clearHover = () => {
|
|
85
|
+
isPointerOverRef.current = false;
|
|
86
|
+
onResizeHover?.(null, null);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const syncHoverAtPoint = (clientX: number, clientY: number) => {
|
|
90
|
+
const handleEl = handleRef.current;
|
|
91
|
+
const doc = handleEl?.ownerDocument ?? document;
|
|
92
|
+
const hit = doc.elementFromPoint(clientX, clientY);
|
|
93
|
+
if (handleEl && hit && (hit === handleEl || handleEl.contains(hit))) {
|
|
94
|
+
isPointerOverRef.current = true;
|
|
95
|
+
reportHover();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
clearHover();
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const attachDragEndListeners = () => {
|
|
103
|
+
detachDragEndRef.current?.();
|
|
104
|
+
|
|
105
|
+
const doc = handleRef.current?.ownerDocument ?? document;
|
|
106
|
+
const onDragEnd = (event: Event) => {
|
|
107
|
+
detachDragEndRef.current?.();
|
|
108
|
+
detachDragEndRef.current = null;
|
|
109
|
+
|
|
110
|
+
const point = clientPointFromEvent(event);
|
|
111
|
+
clearHover();
|
|
112
|
+
|
|
113
|
+
const frame = handleRef.current?.ownerDocument.defaultView ?? window;
|
|
114
|
+
frame.requestAnimationFrame(() => {
|
|
115
|
+
if (!point) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
syncHoverAtPoint(point.x, point.y);
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
doc.addEventListener('mouseup', onDragEnd);
|
|
124
|
+
doc.addEventListener('touchend', onDragEnd);
|
|
125
|
+
detachDragEndRef.current = () => {
|
|
126
|
+
doc.removeEventListener('mouseup', onDragEnd);
|
|
127
|
+
doc.removeEventListener('touchend', onDragEnd);
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const handlePointerEnter = () => {
|
|
132
|
+
isPointerOverRef.current = true;
|
|
133
|
+
reportHover();
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const handlePointerLeave = () => {
|
|
137
|
+
clearHover();
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const startDrag = () => {
|
|
141
|
+
const offset = measureCellRightOffset();
|
|
142
|
+
if (offset !== null) {
|
|
143
|
+
onResizeDragStart?.(offset);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const handlePointerDown = (event: PointerEvent<HTMLDivElement>) => {
|
|
148
|
+
if (event.pointerType === 'touch') {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
event.stopPropagation();
|
|
153
|
+
startDrag();
|
|
154
|
+
header.getResizeHandler(handleRef.current?.ownerDocument ?? document)(event);
|
|
155
|
+
attachDragEndListeners();
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const handleTouchStart = (event: TouchEvent<HTMLDivElement>) => {
|
|
159
|
+
event.stopPropagation();
|
|
160
|
+
startDrag();
|
|
161
|
+
header.getResizeHandler(handleRef.current?.ownerDocument ?? document)(event);
|
|
162
|
+
attachDragEndListeners();
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const handleReset = (event: MouseEvent<HTMLDivElement>) => {
|
|
166
|
+
event.preventDefault();
|
|
167
|
+
event.stopPropagation();
|
|
168
|
+
const leafIds = header.column.getLeafColumns().map((column) => column.id);
|
|
169
|
+
onResizeReset?.(leafIds);
|
|
170
|
+
if (isPointerOverRef.current) {
|
|
171
|
+
reportHover();
|
|
172
|
+
} else {
|
|
173
|
+
clearHover();
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
|
|
178
|
+
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
event.preventDefault();
|
|
183
|
+
event.stopPropagation();
|
|
184
|
+
const step = event.shiftKey ? RESIZE_KEYBOARD_STEP_LARGE : RESIZE_KEYBOARD_STEP;
|
|
185
|
+
const delta = event.key === 'ArrowRight' ? step : -step;
|
|
186
|
+
onResizeKeyboardNudge?.(header.column.id, delta);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Only leaves expose a meaningful min; a group boundary's min/max would be
|
|
190
|
+
// misleading, so announce the current size but omit bounds for groups.
|
|
191
|
+
const isLeaf = header.subHeaders.length === 0;
|
|
192
|
+
|
|
193
|
+
// A focusable role="separator" with aria-valuenow/valuemin and arrow-key
|
|
194
|
+
// handling is the WAI-ARIA window-splitter pattern, which is interactive.
|
|
195
|
+
// jsx-a11y's role taxonomy does not model focusable separators, so its
|
|
196
|
+
// non-interactive rules misfire on this element.
|
|
197
|
+
/* eslint-disable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */
|
|
198
|
+
return (
|
|
199
|
+
<div
|
|
200
|
+
ref={handleRef}
|
|
201
|
+
role="separator"
|
|
202
|
+
aria-orientation="vertical"
|
|
203
|
+
aria-label={label}
|
|
204
|
+
tabIndex={0}
|
|
205
|
+
aria-valuenow={Math.round(header.getSize())}
|
|
206
|
+
aria-valuemin={isLeaf ? (header.column.columnDef.minSize ?? RESIZE_MIN_COLUMN_WIDTH) : undefined}
|
|
207
|
+
className={styles.resizeHandle}
|
|
208
|
+
onPointerDown={handlePointerDown}
|
|
209
|
+
onPointerEnter={handlePointerEnter}
|
|
210
|
+
onPointerLeave={handlePointerLeave}
|
|
211
|
+
onTouchStart={handleTouchStart}
|
|
212
|
+
onClick={(event) => event.stopPropagation()}
|
|
213
|
+
onDoubleClick={handleReset}
|
|
214
|
+
onKeyDown={handleKeyDown}
|
|
215
|
+
/>
|
|
216
|
+
);
|
|
217
|
+
/* eslint-enable jsx-a11y/no-noninteractive-element-interactions, jsx-a11y/no-noninteractive-tabindex */
|
|
218
|
+
};
|
package/src/components/ds-table/components/ds-table-resize-handle/ds-table-resize-handle.types.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Header } from '@tanstack/react-table';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Props for the column resize handle rendered on the right edge of a resizable
|
|
5
|
+
* header cell.
|
|
6
|
+
*/
|
|
7
|
+
export interface DsTableResizeHandleProps<TData, TValue> {
|
|
8
|
+
/**
|
|
9
|
+
* The header (leaf or group) whose right edge this handle resizes. A group
|
|
10
|
+
* handle uses TanStack's resize handler, which scales that group's leaf
|
|
11
|
+
* columns.
|
|
12
|
+
*/
|
|
13
|
+
header: Header<TData, TValue>;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DsTableResizeHandle } from './ds-table-resize-handle';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
@use '../../styles/variables' as vars;
|
|
2
|
+
|
|
3
|
+
.resizeOverlay {
|
|
4
|
+
position: absolute;
|
|
5
|
+
top: 0;
|
|
6
|
+
bottom: 0;
|
|
7
|
+
width: vars.$resize-divider-width;
|
|
8
|
+
background: var(--border-light);
|
|
9
|
+
// `left` is the cell's right edge; nudge the divider right by 1px so its 2px
|
|
10
|
+
// band aligns flush with the 2px group border drawn from that edge rightward.
|
|
11
|
+
transform: translateX(calc(-50% + #{vars.$border-width}));
|
|
12
|
+
pointer-events: none;
|
|
13
|
+
z-index: 2;
|
|
14
|
+
|
|
15
|
+
&[data-resize-phase='dragging'] {
|
|
16
|
+
background: var(--border-action-primary);
|
|
17
|
+
}
|
|
18
|
+
}
|
package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.tsx
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DsTableResizeOverlayProps } from './ds-table-resize-overlay.types';
|
|
2
|
+
import styles from './ds-table-resize-overlay.module.scss';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Full-height divider that tracks the active column's right edge during hover
|
|
6
|
+
* and drag resize.
|
|
7
|
+
*/
|
|
8
|
+
export const DsTableResizeOverlay = ({ offset, phase }: DsTableResizeOverlayProps) => (
|
|
9
|
+
<div
|
|
10
|
+
className={styles.resizeOverlay}
|
|
11
|
+
style={{ left: offset }}
|
|
12
|
+
data-resize-overlay
|
|
13
|
+
data-resize-phase={phase}
|
|
14
|
+
aria-hidden
|
|
15
|
+
/>
|
|
16
|
+
);
|
package/src/components/ds-table/components/ds-table-resize-overlay/ds-table-resize-overlay.types.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type DsTableResizeOverlayPhase = 'hover' | 'dragging';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Props for the full-height column resize divider overlay.
|
|
5
|
+
*/
|
|
6
|
+
export interface DsTableResizeOverlayProps {
|
|
7
|
+
/**
|
|
8
|
+
* Distance from the table container's left edge to the column's right edge,
|
|
9
|
+
* in pixels.
|
|
10
|
+
*/
|
|
11
|
+
offset: number;
|
|
12
|
+
phase: DsTableResizeOverlayPhase;
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DsTableResizeOverlay } from './ds-table-resize-overlay';
|
|
@@ -9,7 +9,7 @@ import type { DsTableRowProps } from './ds-table-row.types';
|
|
|
9
9
|
import styles from './ds-table-row.module.scss';
|
|
10
10
|
import { useDsTableContext } from '../../context/ds-table-context';
|
|
11
11
|
import { mergeRefs } from '../../../../utils/merge-refs';
|
|
12
|
-
import {
|
|
12
|
+
import { getBodyCellSizeStyle, isExplicitColumnWidth } from '../../utils/column-size';
|
|
13
13
|
import { isFirstLeafColumnOfGroup } from '../../grouping';
|
|
14
14
|
import { EXPANDER_COLUMN_ID, REORDER_COLUMN_ID, SELECT_COLUMN_ID } from '../../utils/constants';
|
|
15
15
|
|
|
@@ -52,6 +52,7 @@ const DsTableRow = <TData,>({ ref, row, isSelected }: DsTableRowProps<TData>) =>
|
|
|
52
52
|
secondaryRowActions,
|
|
53
53
|
activeRowId,
|
|
54
54
|
loading,
|
|
55
|
+
resizeSizingReady,
|
|
55
56
|
} = useDsTableContext<TData, unknown>();
|
|
56
57
|
const isExpanded = row.getIsExpanded();
|
|
57
58
|
const isActive = activeRowId === row.id;
|
|
@@ -98,7 +99,13 @@ const DsTableRow = <TData,>({ ref, row, isSelected }: DsTableRowProps<TData>) =>
|
|
|
98
99
|
onDoubleClick={() => onRowDoubleClick?.(row.original)}
|
|
99
100
|
>
|
|
100
101
|
{row.getVisibleCells().map((cell, idx) => {
|
|
101
|
-
const
|
|
102
|
+
const columnSizing = cell.getContext().table.getState().columnSizing;
|
|
103
|
+
const cellStyle = getBodyCellSizeStyle(
|
|
104
|
+
cell.column.id,
|
|
105
|
+
cell.column.getSize(),
|
|
106
|
+
isExplicitColumnWidth(cell.column, resizeSizingReady ? columnSizing : {}),
|
|
107
|
+
!!resizeSizingReady,
|
|
108
|
+
);
|
|
102
109
|
|
|
103
110
|
if (cell.column.id === REORDER_COLUMN_ID) {
|
|
104
111
|
return (
|
package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import classnames from 'classnames';
|
|
2
2
|
import styles from './ds-table-row-virtualized.module.scss';
|
|
3
3
|
import { useDsTableContext } from '../../context/ds-table-context';
|
|
4
|
-
import {
|
|
4
|
+
import { getBodyCellSizeStyle, isExplicitColumnWidth } from '../../utils/column-size';
|
|
5
5
|
import { isFirstLeafColumnOfGroup } from '../../grouping';
|
|
6
6
|
import { TableCell, TableRow } from '../core-table';
|
|
7
7
|
import type { DsTableRowVirtualizedProps } from './ds-table-row-virtualized.types';
|
|
@@ -27,6 +27,7 @@ export const DsTableRowVirtualized = <TData,>({
|
|
|
27
27
|
onRowClick,
|
|
28
28
|
onRowDoubleClick,
|
|
29
29
|
loading,
|
|
30
|
+
resizeSizingReady,
|
|
30
31
|
} = useDsTableContext<TData, unknown>();
|
|
31
32
|
const isExpanded = row.getIsExpanded();
|
|
32
33
|
const isActive = activeRowId === row.id;
|
|
@@ -70,7 +71,13 @@ export const DsTableRowVirtualized = <TData,>({
|
|
|
70
71
|
<>
|
|
71
72
|
{row.getVisibleCells().map((cell, idx) => {
|
|
72
73
|
const isLastColumn = idx === row.getVisibleCells().length - 1;
|
|
73
|
-
const
|
|
74
|
+
const columnSizing = cell.getContext().table.getState().columnSizing;
|
|
75
|
+
const cellStyle = getBodyCellSizeStyle(
|
|
76
|
+
cell.column.id,
|
|
77
|
+
cell.column.getSize(),
|
|
78
|
+
isExplicitColumnWidth(cell.column, resizeSizingReady ? columnSizing : {}),
|
|
79
|
+
!!resizeSizingReady,
|
|
80
|
+
);
|
|
74
81
|
|
|
75
82
|
return (
|
|
76
83
|
<TableCell
|
package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-checkbox.tsx
CHANGED
|
@@ -13,14 +13,14 @@ export const DsTableEditCellCheckbox = <TData extends RowData>({
|
|
|
13
13
|
cellContext,
|
|
14
14
|
disabled,
|
|
15
15
|
}: DsTableEditCellCheckboxProps<TData>) => {
|
|
16
|
-
const { value, setValue } = useCellEditor<TData, boolean>({
|
|
16
|
+
const { value, setValue, isPending } = useCellEditor<TData, boolean>({
|
|
17
17
|
cellContext,
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<DsCheckbox
|
|
22
22
|
checked={value}
|
|
23
|
-
disabled={disabled}
|
|
23
|
+
disabled={disabled || isPending}
|
|
24
24
|
onCheckedChange={(checked) => setValue(checked === true)}
|
|
25
25
|
/>
|
|
26
26
|
);
|
|
@@ -22,7 +22,7 @@ export const DsTableEditCellDate = <TData extends RowData>({
|
|
|
22
22
|
max,
|
|
23
23
|
placeholder,
|
|
24
24
|
}: DsTableEditCellDateProps<TData>) => {
|
|
25
|
-
const { value, setValue, error } = useCellEditor<TData, DsTableEditCellDateValue>({
|
|
25
|
+
const { value, setValue, error, isPending } = useCellEditor<TData, DsTableEditCellDateValue>({
|
|
26
26
|
cellContext,
|
|
27
27
|
});
|
|
28
28
|
|
|
@@ -34,6 +34,7 @@ export const DsTableEditCellDate = <TData extends RowData>({
|
|
|
34
34
|
min={min}
|
|
35
35
|
max={max}
|
|
36
36
|
placeholder={placeholder}
|
|
37
|
+
disabled={isPending}
|
|
37
38
|
onChange={setValue}
|
|
38
39
|
slotProps={
|
|
39
40
|
error
|
|
@@ -20,7 +20,7 @@ export const DsTableEditCellNumber = <TData extends RowData>({
|
|
|
20
20
|
max,
|
|
21
21
|
step,
|
|
22
22
|
}: DsTableEditCellNumberProps<TData>) => {
|
|
23
|
-
const { value, setValue, error } = useCellEditor<TData, number>({
|
|
23
|
+
const { value, setValue, error, isPending } = useCellEditor<TData, number>({
|
|
24
24
|
cellContext,
|
|
25
25
|
});
|
|
26
26
|
|
|
@@ -44,6 +44,7 @@ export const DsTableEditCellNumber = <TData extends RowData>({
|
|
|
44
44
|
min={min}
|
|
45
45
|
max={max}
|
|
46
46
|
step={step}
|
|
47
|
+
disabled={isPending}
|
|
47
48
|
onValueChange={setValue}
|
|
48
49
|
/>
|
|
49
50
|
</TableEditFormControl>
|
|
@@ -18,7 +18,7 @@ export const DsTableEditCellSelect = <TData extends RowData>({
|
|
|
18
18
|
options,
|
|
19
19
|
placeholder,
|
|
20
20
|
}: DsTableEditCellSelectProps<TData>) => {
|
|
21
|
-
const { value, setValue, error } = useCellEditor<TData, string>({
|
|
21
|
+
const { value, setValue, error, isPending } = useCellEditor<TData, string>({
|
|
22
22
|
cellContext,
|
|
23
23
|
});
|
|
24
24
|
|
|
@@ -29,6 +29,7 @@ export const DsTableEditCellSelect = <TData extends RowData>({
|
|
|
29
29
|
value={value}
|
|
30
30
|
options={options}
|
|
31
31
|
placeholder={placeholder}
|
|
32
|
+
disabled={isPending}
|
|
32
33
|
onValueChange={setValue}
|
|
33
34
|
/>
|
|
34
35
|
</TableEditFormControl>
|
|
@@ -19,7 +19,7 @@ export const DsTableEditCellText = <TData extends RowData>({
|
|
|
19
19
|
placeholder,
|
|
20
20
|
maxLength,
|
|
21
21
|
}: DsTableEditCellTextProps<TData>) => {
|
|
22
|
-
const { value, setValue, error } = useCellEditor<TData, string>({
|
|
22
|
+
const { value, setValue, error, isPending } = useCellEditor<TData, string>({
|
|
23
23
|
cellContext,
|
|
24
24
|
});
|
|
25
25
|
|
|
@@ -42,6 +42,7 @@ export const DsTableEditCellText = <TData extends RowData>({
|
|
|
42
42
|
value={value}
|
|
43
43
|
placeholder={placeholder}
|
|
44
44
|
maxLength={maxLength}
|
|
45
|
+
disabled={isPending}
|
|
45
46
|
onValueChange={setValue}
|
|
46
47
|
slots={error ? { endAdornment: <DsIcon icon="error" size="tiny" /> } : undefined}
|
|
47
48
|
/>
|
package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useRef, type
|
|
1
|
+
import { useEffect, useRef, type SubmitEvent } from 'react';
|
|
2
2
|
import { flexRender } from '@tanstack/react-table';
|
|
3
3
|
import { DsButtonV3 } from '../../../../ds-button-v3';
|
|
4
4
|
import { DsStack } from '../../../../ds-stack';
|
|
@@ -7,13 +7,20 @@ import styles from './ds-table-editing-cell.module.scss';
|
|
|
7
7
|
import type { DsTableEditingCellProps } from './ds-table-editing-cell.types';
|
|
8
8
|
|
|
9
9
|
export const DsTableEditingCell = <TData, TValue>({ cell }: DsTableEditingCellProps<TData, TValue>) => {
|
|
10
|
-
const { commit, cancel } = useDsTableContext<TData, TValue>();
|
|
10
|
+
const { commit, cancel, editing } = useDsTableContext<TData, TValue>();
|
|
11
11
|
const columnDef = cell.column.columnDef;
|
|
12
12
|
const editAnchorRef = useRef<HTMLDivElement>(null);
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const isActiveCell = editing?.cell.id === cell.id;
|
|
15
|
+
const isPending = isActiveCell && editing.pending;
|
|
16
|
+
const hasError = isActiveCell && editing.error !== null;
|
|
17
|
+
|
|
18
|
+
const handleSubmit = (event: SubmitEvent<HTMLFormElement>) => {
|
|
15
19
|
event.preventDefault();
|
|
16
20
|
event.stopPropagation();
|
|
21
|
+
if (isPending || hasError) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
17
24
|
commit();
|
|
18
25
|
};
|
|
19
26
|
|
|
@@ -62,6 +69,8 @@ export const DsTableEditingCell = <TData, TValue>({ cell }: DsTableEditingCellPr
|
|
|
62
69
|
variant="tertiary"
|
|
63
70
|
size="small"
|
|
64
71
|
icon="check"
|
|
72
|
+
loading={isPending}
|
|
73
|
+
disabled={hasError}
|
|
65
74
|
aria-label="Confirm edit"
|
|
66
75
|
onClick={(event) => {
|
|
67
76
|
event.stopPropagation();
|