@drivenets/design-system 0.12.1 → 0.13.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 +15 -0
- package/dist/index.cjs +1097 -308
- package/dist/index.d.cts +1118 -982
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +1118 -982
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1089 -309
- package/dist/index.js.map +1 -1
- package/dist/index.min.css +1 -1
- package/package.json +31 -31
- package/src/components/ds-date-input/ds-date-input.utils.ts +2 -2
- package/src/components/ds-drawer/ds-drawer.tsx +2 -0
- package/src/components/ds-form-control/ds-form-control.tsx +14 -11
- package/src/components/ds-form-control/ds-form-control.types.ts +4 -0
- package/src/components/ds-grid/ds-grid.tsx +1 -2
- package/src/components/ds-modal/ds-modal.tsx +3 -0
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.module.scss +21 -2
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx +14 -11
- package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.types.ts +1 -6
- package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.module.scss +2 -2
- package/src/components/ds-table/components/ds-table-cell/ds-table-cell.module.scss +2 -0
- package/src/components/ds-table/components/ds-table-cell/ds-table-cell.tsx +42 -11
- package/src/components/ds-table/components/ds-table-header/ds-table-header.module.scss +24 -4
- package/src/components/ds-table/components/ds-table-header/ds-table-header.tsx +22 -1
- package/src/components/ds-table/components/ds-table-row/ds-table-row.module.scss +22 -0
- package/src/components/ds-table/components/ds-table-row/ds-table-row.tsx +1 -0
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.module.scss +19 -0
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.tsx +2 -1
- package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.types.ts +1 -1
- package/src/components/ds-table/components/edit/cell-editors/cell-editors.module.scss +3 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-checkbox.tsx +27 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-date.tsx +50 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-number.tsx +51 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-select.tsx +36 -0
- package/src/components/ds-table/components/edit/cell-editors/ds-table-edit-cell-text.tsx +50 -0
- package/src/components/ds-table/components/edit/cell-editors/index.ts +14 -0
- package/src/components/ds-table/components/edit/cell-editors/table-edit-form-control.tsx +31 -0
- package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.module.scss +28 -0
- package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.tsx +39 -0
- package/src/components/ds-table/components/edit/ds-table-editable-cell/ds-table-editable-cell.types.ts +7 -0
- package/src/components/ds-table/components/edit/ds-table-editable-cell/index.ts +2 -0
- package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.module.scss +48 -0
- package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.tsx +76 -0
- package/src/components/ds-table/components/edit/ds-table-editing-cell/ds-table-editing-cell.types.ts +5 -0
- package/src/components/ds-table/components/edit/ds-table-editing-cell/index.ts +2 -0
- package/src/components/ds-table/context/ds-table-context.ts +79 -1
- package/src/components/ds-table/ds-table-column.types.ts +12 -0
- package/src/components/ds-table/ds-table.module.scss +100 -10
- package/src/components/ds-table/ds-table.tsx +18 -19
- package/src/components/ds-table/ds-table.types.ts +52 -0
- package/src/components/ds-table/filters/adapters/create-checkbox-filter-adapter.tsx +24 -40
- package/src/components/ds-table/filters/adapters/create-dual-range-filter-adapter.tsx +10 -31
- package/src/components/ds-table/filters/adapters/create-filter-adapter.ts +6 -98
- package/src/components/ds-table/filters/components/checkbox-filter/checkbox-filter.module.scss +36 -0
- package/src/components/ds-table/filters/components/checkbox-filter/checkbox-filter.tsx +92 -13
- package/src/components/ds-table/filters/components/checkbox-filter/index.ts +1 -1
- package/src/components/ds-table/filters/components/column-filter-popover/column-filter-popover.module.scss +42 -0
- package/src/components/ds-table/filters/components/column-filter-popover/column-filter-popover.tsx +89 -0
- package/src/components/ds-table/filters/components/column-filter-popover/column-filter-popover.types.ts +25 -0
- package/src/components/ds-table/filters/components/column-filter-popover/index.ts +5 -0
- package/src/components/ds-table/filters/hooks/use-table-filters.ts +113 -78
- package/src/components/ds-table/filters/index.ts +2 -44
- package/src/components/ds-table/filters/types/column-meta.augmentation.ts +19 -0
- package/src/components/ds-table/filters/types/filter-adapter.types.ts +48 -81
- package/src/components/ds-table/hooks/use-cell-editor.ts +81 -0
- package/src/components/ds-table/index.ts +29 -0
- package/src/components/ds-table/utils/column-size.ts +9 -8
- package/src/components/ds-tag/ds-tag.tsx +2 -2
- package/src/components/ds-workspace-layout/ds-workspace-layout.context.ts +19 -0
- package/src/components/ds-workspace-layout/ds-workspace-layout.module.scss +166 -0
- package/src/components/ds-workspace-layout/ds-workspace-layout.tsx +135 -0
- package/src/components/ds-workspace-layout/ds-workspace-layout.types.ts +52 -0
- package/src/components/ds-workspace-layout/index.ts +11 -0
- package/src/index.ts +1 -1
- package/src/styles/_scrollbars.scss +37 -0
- package/src/utils/restore-document-body-modal-styles.ts +44 -0
- package/src/utils/use-ark-dialog-body-lock-cleanup.ts +36 -0
- package/src/components/ds-workspace/ds-workspace.module.scss +0 -55
- package/src/components/ds-workspace/ds-workspace.tsx +0 -37
- package/src/components/ds-workspace/ds-workspace.types.ts +0 -17
- package/src/components/ds-workspace/index.ts +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drivenets/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.cts",
|
|
@@ -62,50 +62,50 @@
|
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
65
|
-
"@eslint/compat": "^2.0
|
|
65
|
+
"@eslint/compat": "^2.1.0",
|
|
66
66
|
"@faker-js/faker": "^10.3.0",
|
|
67
|
-
"@hookform/resolvers": "^5.
|
|
68
|
-
"@rolldown/plugin-babel": "^0.2.
|
|
69
|
-
"@storybook/addon-a11y": "^10.
|
|
70
|
-
"@storybook/addon-docs": "^10.
|
|
67
|
+
"@hookform/resolvers": "^5.4.0",
|
|
68
|
+
"@rolldown/plugin-babel": "^0.2.3",
|
|
69
|
+
"@storybook/addon-a11y": "^10.4.1",
|
|
70
|
+
"@storybook/addon-docs": "^10.4.1",
|
|
71
71
|
"@storybook/addon-mcp": "^0.6.0",
|
|
72
|
-
"@storybook/addon-vitest": "^10.
|
|
73
|
-
"@storybook/react-vite": "^10.
|
|
74
|
-
"@tanstack/react-query": "^5.
|
|
75
|
-
"@tanstack/react-router": "^1.
|
|
76
|
-
"@tsdown/css": "^0.
|
|
72
|
+
"@storybook/addon-vitest": "^10.4.1",
|
|
73
|
+
"@storybook/react-vite": "^10.4.1",
|
|
74
|
+
"@tanstack/react-query": "^5.100.14",
|
|
75
|
+
"@tanstack/react-router": "^1.170.8",
|
|
76
|
+
"@tsdown/css": "^0.22.0",
|
|
77
77
|
"@types/eslint-plugin-jsx-a11y": "^6.10.1",
|
|
78
|
-
"@types/react": "^19.2.
|
|
78
|
+
"@types/react": "^19.2.15",
|
|
79
79
|
"@types/react-dom": "^19.2.3",
|
|
80
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
81
|
-
"@vitejs/plugin-react": "^6.0.
|
|
82
|
-
"@vitest/browser-playwright": "^4.1.
|
|
83
|
-
"@vitest/coverage-v8": "^4.1.
|
|
80
|
+
"@typescript/native-preview": "7.0.0-dev.20260521.1",
|
|
81
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
82
|
+
"@vitest/browser-playwright": "^4.1.7",
|
|
83
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
84
84
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
85
85
|
"eslint": "^10.0.1",
|
|
86
86
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
87
87
|
"eslint-plugin-react": "^7.37.5",
|
|
88
|
-
"eslint-plugin-react-hooks": "^7.
|
|
89
|
-
"eslint-plugin-storybook": "^10.
|
|
88
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
89
|
+
"eslint-plugin-storybook": "^10.4.1",
|
|
90
90
|
"mockdate": "^3.0.5",
|
|
91
|
-
"playwright": "^1.
|
|
92
|
-
"publint": "^0.3.
|
|
93
|
-
"react": "^19.2.
|
|
94
|
-
"react-dom": "^19.2.
|
|
95
|
-
"react-hook-form": "^7.
|
|
91
|
+
"playwright": "^1.60.0",
|
|
92
|
+
"publint": "^0.3.21",
|
|
93
|
+
"react": "^19.2.6",
|
|
94
|
+
"react-dom": "^19.2.6",
|
|
95
|
+
"react-hook-form": "^7.76.1",
|
|
96
96
|
"remark-gfm": "^4.0.1",
|
|
97
|
-
"sass-embedded": "^1.
|
|
98
|
-
"storybook": "^10.
|
|
99
|
-
"tsdown": "^0.
|
|
97
|
+
"sass-embedded": "^1.100.0",
|
|
98
|
+
"storybook": "^10.4.1",
|
|
99
|
+
"tsdown": "^0.22.0",
|
|
100
100
|
"typed-scss-modules": "^8.1.1",
|
|
101
101
|
"typescript": "^6.0.3",
|
|
102
102
|
"typescript-plugin-css-modules": "^5.2.0",
|
|
103
|
-
"vite": "8.0.
|
|
104
|
-
"vitest": "^4.1.
|
|
103
|
+
"vite": "8.0.14",
|
|
104
|
+
"vitest": "^4.1.7",
|
|
105
105
|
"vitest-browser-react": "^2.1.0",
|
|
106
|
-
"zod": "^4.3
|
|
107
|
-
"@drivenets/
|
|
108
|
-
"@drivenets/
|
|
106
|
+
"zod": "^4.4.3",
|
|
107
|
+
"@drivenets/eslint-plugin-internal": "0.0.0",
|
|
108
|
+
"@drivenets/vite-plugin-design-system": "0.0.9"
|
|
109
109
|
},
|
|
110
110
|
"scripts": {
|
|
111
111
|
"start": "storybook dev -p 6006",
|
|
@@ -23,7 +23,7 @@ interface ParsedDateRange {
|
|
|
23
23
|
*/
|
|
24
24
|
export const isoStringToDateValue = (isoDate: string): DateValue | undefined => {
|
|
25
25
|
try {
|
|
26
|
-
return parseDate(isoDate)
|
|
26
|
+
return parseDate(isoDate);
|
|
27
27
|
} catch {
|
|
28
28
|
return undefined;
|
|
29
29
|
}
|
|
@@ -109,7 +109,7 @@ const parseDateString = (dateStr: string): DateValue | null => {
|
|
|
109
109
|
return null;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
return new CalendarDate(yearNum, monthNum, dayNum)
|
|
112
|
+
return new CalendarDate(yearNum, monthNum, dayNum);
|
|
113
113
|
};
|
|
114
114
|
|
|
115
115
|
/**
|
|
@@ -6,6 +6,7 @@ import type { DsDrawerProps } from './ds-drawer.types';
|
|
|
6
6
|
import styles from './ds-drawer.module.scss';
|
|
7
7
|
import { DsIcon } from '../ds-icon';
|
|
8
8
|
import { DsTypography } from '../ds-typography';
|
|
9
|
+
import { useArkDialogBodyLockCleanup } from '../../utils/use-ark-dialog-body-lock-cleanup';
|
|
9
10
|
import { useResponsiveValue } from '../../utils/responsive';
|
|
10
11
|
|
|
11
12
|
const DsDrawer = ({
|
|
@@ -22,6 +23,7 @@ const DsDrawer = ({
|
|
|
22
23
|
children,
|
|
23
24
|
}: DsDrawerProps) => {
|
|
24
25
|
const resolvedColumns = useResponsiveValue(columns);
|
|
26
|
+
useArkDialogBodyLockCleanup(open, backdrop);
|
|
25
27
|
|
|
26
28
|
const handleOpenChange = (details: { open: boolean }) => {
|
|
27
29
|
onOpenChange(details.open);
|
|
@@ -45,6 +45,7 @@ const DsFormControl = ({
|
|
|
45
45
|
id,
|
|
46
46
|
status,
|
|
47
47
|
label,
|
|
48
|
+
hideLabel = false,
|
|
48
49
|
required = false,
|
|
49
50
|
slots,
|
|
50
51
|
message,
|
|
@@ -68,17 +69,19 @@ const DsFormControl = ({
|
|
|
68
69
|
)}
|
|
69
70
|
style={style}
|
|
70
71
|
>
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
{!hideLabel && (
|
|
73
|
+
<div className={styles.labelContainer}>
|
|
74
|
+
<label
|
|
75
|
+
htmlFor={controlId}
|
|
76
|
+
className={classNames(styles.label, {
|
|
77
|
+
[styles.required]: required,
|
|
78
|
+
})}
|
|
79
|
+
>
|
|
80
|
+
{label}
|
|
81
|
+
</label>
|
|
82
|
+
{slots?.endAdornment && <div className={styles.endAdornment}>{slots.endAdornment}</div>}
|
|
83
|
+
</div>
|
|
84
|
+
)}
|
|
82
85
|
|
|
83
86
|
{children}
|
|
84
87
|
|
|
@@ -17,6 +17,10 @@ export interface DsFormControlProps extends React.PropsWithChildren {
|
|
|
17
17
|
* Label text
|
|
18
18
|
*/
|
|
19
19
|
label: string;
|
|
20
|
+
/**
|
|
21
|
+
* When true, the label row is not rendered (e.g. inline table cell editors).
|
|
22
|
+
*/
|
|
23
|
+
hideLabel?: boolean;
|
|
20
24
|
/**
|
|
21
25
|
* Marks the field as required
|
|
22
26
|
*/
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { CSSProperties } from 'react';
|
|
2
1
|
import classNames from 'classnames';
|
|
3
2
|
|
|
4
3
|
import type { DsGridBaseProps, DsGridItemBaseProps } from './ds-grid.types';
|
|
@@ -32,7 +31,7 @@ export const DsGridBase = ({
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
return (
|
|
35
|
-
<div className={gridClass} style={{ ...style, ...cssVars }
|
|
34
|
+
<div className={gridClass} style={{ ...style, ...cssVars }}>
|
|
36
35
|
{children}
|
|
37
36
|
</div>
|
|
38
37
|
);
|
|
@@ -4,6 +4,7 @@ import { Portal } from '@ark-ui/react/portal';
|
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import type { DsModalProps } from './ds-modal.types';
|
|
6
6
|
import styles from './ds-modal.module.scss';
|
|
7
|
+
import { useArkDialogBodyLockCleanup } from '../../utils/use-ark-dialog-body-lock-cleanup';
|
|
7
8
|
import { DsIcon } from '../ds-icon';
|
|
8
9
|
import { DsTypography } from '../ds-typography';
|
|
9
10
|
|
|
@@ -24,6 +25,8 @@ const DsModal = ({
|
|
|
24
25
|
children,
|
|
25
26
|
onOpenChange,
|
|
26
27
|
}: DsModalProps) => {
|
|
28
|
+
useArkDialogBodyLockCleanup(open, modal);
|
|
29
|
+
|
|
27
30
|
const handleOpenChange = (details: { open: boolean }) => {
|
|
28
31
|
onOpenChange(details.open);
|
|
29
32
|
};
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
@use '../../../../styles/scrollbars' as scrollbars;
|
|
2
|
+
|
|
1
3
|
.body {
|
|
2
|
-
display:
|
|
4
|
+
display: block;
|
|
5
|
+
position: relative;
|
|
6
|
+
overflow-y: auto;
|
|
7
|
+
flex: 1;
|
|
8
|
+
min-height: 0;
|
|
9
|
+
scrollbar-gutter: stable;
|
|
10
|
+
|
|
11
|
+
@include scrollbars.scrollbar-on-hover;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// 1px row pinned at `top: <totalSize>` (set inline) so absolutely-positioned
|
|
15
|
+
// rows extend the parent's scrollable overflow area.
|
|
16
|
+
.sentinel {
|
|
17
|
+
position: absolute;
|
|
18
|
+
left: 0;
|
|
19
|
+
width: 1px;
|
|
20
|
+
height: 1px;
|
|
21
|
+
pointer-events: none;
|
|
22
|
+
visibility: hidden;
|
|
3
23
|
}
|
|
4
24
|
|
|
5
25
|
.emptyState {
|
|
6
26
|
position: absolute;
|
|
7
27
|
inset: 0;
|
|
8
|
-
top: var(--ds-table-header-height);
|
|
9
28
|
}
|
package/src/components/ds-table/components/ds-table-body-virtualized/ds-table-body-virtualized.tsx
CHANGED
|
@@ -10,7 +10,6 @@ import { useInfiniteScroll } from './use-infinite-scroll';
|
|
|
10
10
|
|
|
11
11
|
export const DsTableBodyVirtualized = <TData,>({
|
|
12
12
|
table,
|
|
13
|
-
tableContainerRef,
|
|
14
13
|
emptyState,
|
|
15
14
|
estimateSize,
|
|
16
15
|
overscan,
|
|
@@ -20,6 +19,7 @@ export const DsTableBodyVirtualized = <TData,>({
|
|
|
20
19
|
}: DsTableBodyVirtualizedProps<TData>) => {
|
|
21
20
|
const rowsMapRef = useRef(new Map<string, HTMLTableRowElement>());
|
|
22
21
|
const rowHeightsMapRef = useRef(new Map<string, number>());
|
|
22
|
+
const tbodyRef = useRef<HTMLTableSectionElement>(null);
|
|
23
23
|
|
|
24
24
|
const { rows } = table.getRowModel();
|
|
25
25
|
|
|
@@ -32,16 +32,16 @@ export const DsTableBodyVirtualized = <TData,>({
|
|
|
32
32
|
return item ? `${item.row.id}${item.isExpandedRowContent ? '-expanded-content' : ''}` : String(index);
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
-
const { loadDataIfNeeded } = useInfiniteScroll(
|
|
35
|
+
const { loadDataIfNeeded } = useInfiniteScroll(tbodyRef, rows.length, infiniteScroll);
|
|
36
36
|
|
|
37
|
-
const rowVirtualizer = useVirtualizer<
|
|
37
|
+
const rowVirtualizer = useVirtualizer<HTMLTableSectionElement, HTMLTableRowElement>({
|
|
38
38
|
count: rowsAndExpandedRowContent.length,
|
|
39
39
|
estimateSize: (index) => {
|
|
40
40
|
const cachedHeight = rowHeightsMapRef.current.get(getItemKey(index));
|
|
41
41
|
return cachedHeight || estimateSize;
|
|
42
42
|
}, // estimate row height for accurate scrollbar dragging
|
|
43
43
|
getItemKey,
|
|
44
|
-
getScrollElement: () =>
|
|
44
|
+
getScrollElement: () => tbodyRef.current,
|
|
45
45
|
// measure dynamic row height, except in firefox because it measures table border height incorrectly
|
|
46
46
|
measureElement:
|
|
47
47
|
typeof window !== 'undefined' && navigator.userAgent.indexOf('Firefox') === -1
|
|
@@ -86,6 +86,7 @@ export const DsTableBodyVirtualized = <TData,>({
|
|
|
86
86
|
|
|
87
87
|
return (
|
|
88
88
|
<DsTableBody
|
|
89
|
+
ref={tbodyRef}
|
|
89
90
|
rowsMapRef={rowsMapRef}
|
|
90
91
|
rowHeightsMapRef={rowHeightsMapRef}
|
|
91
92
|
rowVirtualizer={rowVirtualizer}
|
|
@@ -97,7 +98,8 @@ export const DsTableBodyVirtualized = <TData,>({
|
|
|
97
98
|
};
|
|
98
99
|
|
|
99
100
|
interface DsTableBodyProps<TData> {
|
|
100
|
-
|
|
101
|
+
ref: RefObject<HTMLTableSectionElement | null>;
|
|
102
|
+
rowVirtualizer: Virtualizer<HTMLTableSectionElement, HTMLTableRowElement>;
|
|
101
103
|
rowsMapRef: RefObject<Map<string, HTMLTableRowElement>>;
|
|
102
104
|
rowHeightsMapRef: RefObject<Map<string, number>>;
|
|
103
105
|
rowsAndExpandedRowContent: {
|
|
@@ -109,6 +111,7 @@ interface DsTableBodyProps<TData> {
|
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
function DsTableBody<TData>({
|
|
114
|
+
ref,
|
|
112
115
|
rowVirtualizer,
|
|
113
116
|
rowsMapRef,
|
|
114
117
|
rowHeightsMapRef,
|
|
@@ -117,14 +120,10 @@ function DsTableBody<TData>({
|
|
|
117
120
|
rowSelection,
|
|
118
121
|
}: DsTableBodyProps<TData>) {
|
|
119
122
|
const virtualRows = rowVirtualizer.getVirtualItems();
|
|
123
|
+
const totalSize = rowVirtualizer.getTotalSize();
|
|
120
124
|
|
|
121
125
|
return (
|
|
122
|
-
<TableBody
|
|
123
|
-
className={styles.body}
|
|
124
|
-
style={{
|
|
125
|
-
height: `${rowVirtualizer.getTotalSize().toString()}px`, // tells scrollbar how big the table is
|
|
126
|
-
}}
|
|
127
|
-
>
|
|
126
|
+
<TableBody ref={ref} className={styles.body}>
|
|
128
127
|
{virtualRows.length > 0 ? (
|
|
129
128
|
virtualRows.map((virtualRow) => {
|
|
130
129
|
const row = rowsAndExpandedRowContent[virtualRow.index];
|
|
@@ -150,6 +149,10 @@ function DsTableBody<TData>({
|
|
|
150
149
|
<TableCell className={styles.emptyState}>{emptyState || EMPTY_TABLE_STATE_TEXT}</TableCell>
|
|
151
150
|
</TableRow>
|
|
152
151
|
)}
|
|
152
|
+
|
|
153
|
+
<tr aria-hidden className={styles.sentinel} style={{ top: `${totalSize.toString()}px` }}>
|
|
154
|
+
<td />
|
|
155
|
+
</tr>
|
|
153
156
|
</TableBody>
|
|
154
157
|
);
|
|
155
158
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
2
|
import { type RowSelectionState, type Table } from '@tanstack/react-table';
|
|
3
3
|
|
|
4
4
|
export interface DsTableBodyVirtualizedProps<TData> {
|
|
@@ -7,11 +7,6 @@ export interface DsTableBodyVirtualizedProps<TData> {
|
|
|
7
7
|
* and column state.
|
|
8
8
|
*/
|
|
9
9
|
table: Table<TData>;
|
|
10
|
-
/**
|
|
11
|
-
* Ref to the scrollable container that hosts the virtualized rows. Required by
|
|
12
|
-
* the virtualizer to measure viewport size and listen for scroll events.
|
|
13
|
-
*/
|
|
14
|
-
tableContainerRef: RefObject<HTMLDivElement | null>;
|
|
15
10
|
/**
|
|
16
11
|
* Optional content rendered in place of rows when the table has no data.
|
|
17
12
|
*/
|
package/src/components/ds-table/components/ds-table-bulk-actions/ds-table-bulk-actions.module.scss
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
@use '../../../../styles/typography';
|
|
2
2
|
|
|
3
3
|
.bulkActionsContainer {
|
|
4
|
-
position:
|
|
4
|
+
position: absolute;
|
|
5
5
|
bottom: 20px;
|
|
6
6
|
left: 50%;
|
|
7
7
|
transform: translateX(-50%);
|
|
8
8
|
background-color: var(--color-dap-gray-050);
|
|
9
9
|
border-radius: 8px;
|
|
10
10
|
box-shadow: 0 4px 12px #0445cc66;
|
|
11
|
-
z-index:
|
|
11
|
+
z-index: 1;
|
|
12
12
|
display: flex;
|
|
13
13
|
align-items: center;
|
|
14
14
|
border-radius: 8px;
|
|
@@ -2,31 +2,31 @@ import { type Cell, flexRender } from '@tanstack/react-table';
|
|
|
2
2
|
import classnames from 'classnames';
|
|
3
3
|
import { DsIcon } from '../../../ds-icon';
|
|
4
4
|
import { DsDropdownMenu } from '../../../ds-dropdown-menu';
|
|
5
|
+
import { useDsTableContext } from '../../context/ds-table-context';
|
|
6
|
+
import { DsTableEditableCell } from '../edit/ds-table-editable-cell';
|
|
7
|
+
import { DsTableEditingCell } from '../edit/ds-table-editing-cell';
|
|
5
8
|
import styles from './ds-table-cell.module.scss';
|
|
6
9
|
import type { DsTableCellProps } from './ds-table-cell.types';
|
|
7
10
|
|
|
8
|
-
const DsDefaultTableCell = <TData, TValue>({ cell }: { cell: Cell<TData, TValue> }) => {
|
|
9
|
-
return (
|
|
10
|
-
<div className={styles.tableCellEllipsis}>
|
|
11
|
-
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
12
|
-
</div>
|
|
13
|
-
);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
11
|
export const DsTableCell = <TData, TValue>({
|
|
17
12
|
row,
|
|
18
13
|
cell,
|
|
19
14
|
primaryRowActions = [],
|
|
20
15
|
secondaryRowActions = [],
|
|
21
16
|
}: DsTableCellProps<TData, TValue>) => {
|
|
17
|
+
const { editing } = useDsTableContext<TData, TValue>();
|
|
18
|
+
const isCellBeingEdited =
|
|
19
|
+
editing !== null && editing.cell.row.id === row.id && editing.cell.column.id === cell.column.id;
|
|
20
|
+
|
|
22
21
|
const visiblePrimary = primaryRowActions.filter((action) => !action.hidden?.(row.original));
|
|
23
22
|
const visibleSecondary = secondaryRowActions.filter((action) => !action.hidden?.(row.original));
|
|
24
23
|
|
|
25
|
-
if (visiblePrimary.length || visibleSecondary.length) {
|
|
24
|
+
if (!isCellBeingEdited && (visiblePrimary.length || visibleSecondary.length)) {
|
|
26
25
|
const hasSecondaryRowActions = visibleSecondary.length > 0;
|
|
26
|
+
|
|
27
27
|
return (
|
|
28
28
|
<div className={styles.lastCell}>
|
|
29
|
-
<
|
|
29
|
+
<CellContent cell={cell} isCellBeingEdited={isCellBeingEdited} />
|
|
30
30
|
<div className={styles.cellActions}>
|
|
31
31
|
{visiblePrimary.map((action, i) => {
|
|
32
32
|
const isDisabled = action.disabled?.(row.original);
|
|
@@ -95,5 +95,36 @@ export const DsTableCell = <TData, TValue>({
|
|
|
95
95
|
</div>
|
|
96
96
|
);
|
|
97
97
|
}
|
|
98
|
-
|
|
98
|
+
|
|
99
|
+
return <CellContent cell={cell} isCellBeingEdited={isCellBeingEdited} />;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
interface CellContentProps<TData, TValue> {
|
|
103
|
+
cell: Cell<TData, TValue>;
|
|
104
|
+
isCellBeingEdited: boolean;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const CellContent = <TData, TValue>({ cell, isCellBeingEdited }: CellContentProps<TData, TValue>) => {
|
|
108
|
+
const columnDef = cell.column.columnDef;
|
|
109
|
+
const isEditable = typeof columnDef.editCell === 'function';
|
|
110
|
+
|
|
111
|
+
if (isCellBeingEdited) {
|
|
112
|
+
return <DsTableEditingCell cell={cell} />;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (isEditable) {
|
|
116
|
+
return (
|
|
117
|
+
<DsTableEditableCell cell={cell}>
|
|
118
|
+
<div className={styles.tableCellEllipsis}>
|
|
119
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
120
|
+
</div>
|
|
121
|
+
</DsTableEditableCell>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<div className={styles.tableCellEllipsis}>
|
|
127
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
99
130
|
};
|
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
@use '../../styles/variables' as vars;
|
|
3
3
|
|
|
4
4
|
.stickyHeader {
|
|
5
|
-
position: sticky;
|
|
6
|
-
top: 0;
|
|
7
|
-
z-index: 10;
|
|
8
5
|
background-color: var(--background);
|
|
9
6
|
}
|
|
10
7
|
|
|
11
8
|
.virtualizedHeader {
|
|
12
|
-
display:
|
|
9
|
+
display: block;
|
|
13
10
|
}
|
|
14
11
|
|
|
15
12
|
.headerRow {
|
|
@@ -57,6 +54,7 @@
|
|
|
57
54
|
|
|
58
55
|
.selectHeaderCell {
|
|
59
56
|
padding: 0;
|
|
57
|
+
justify-content: center;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
.headerSortContainer {
|
|
@@ -66,3 +64,25 @@
|
|
|
66
64
|
gap: vars.$header-sort-gap;
|
|
67
65
|
height: 100%;
|
|
68
66
|
}
|
|
67
|
+
|
|
68
|
+
.filterTriggerContainer {
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
margin-left: vars.$header-sort-gap;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.filterableHeader {
|
|
75
|
+
&:hover .filterTriggerContainer > * {
|
|
76
|
+
opacity: 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
&:focus-within .filterTriggerContainer > * {
|
|
80
|
+
opacity: 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.filterActive {
|
|
85
|
+
.filterTriggerContainer > * {
|
|
86
|
+
opacity: 1;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -9,6 +9,8 @@ import { useDsTableContext } from '../../context/ds-table-context';
|
|
|
9
9
|
import { getColumnSizeStyle } from '../../utils/column-size';
|
|
10
10
|
import { SELECT_COLUMN_ID } from '../../utils/constants';
|
|
11
11
|
import { DsStack } from '../../../ds-stack';
|
|
12
|
+
import { DsTableColumnFilterPopover } from '../../filters/components/column-filter-popover';
|
|
13
|
+
import type { ResolvedColumnFilter } from '../../filters/types/filter-adapter.types';
|
|
12
14
|
|
|
13
15
|
const DsTableHeader = <TData,>({ table }: DsTableHeaderProps<TData>) => {
|
|
14
16
|
const { stickyHeader, bordered, virtualized } = useDsTableContext<TData, unknown>();
|
|
@@ -27,10 +29,15 @@ const DsTableHeader = <TData,>({ table }: DsTableHeaderProps<TData>) => {
|
|
|
27
29
|
)}
|
|
28
30
|
>
|
|
29
31
|
{headerGroup.headers.map((header) => {
|
|
30
|
-
const headerStyle = getColumnSizeStyle(header.column.getSize()
|
|
32
|
+
const headerStyle = getColumnSizeStyle(header.column.getSize());
|
|
31
33
|
const canSort = header.column.getCanSort();
|
|
32
34
|
const isSelectColumn = header.column.id === SELECT_COLUMN_ID;
|
|
33
35
|
|
|
36
|
+
const metaFilter = header.column.columnDef.meta?.filter;
|
|
37
|
+
const resolvedFilter: ResolvedColumnFilter | undefined =
|
|
38
|
+
metaFilter && 'render' in metaFilter ? metaFilter : undefined;
|
|
39
|
+
const hasActiveColumnFilter = resolvedFilter?.hasActiveFilter ?? false;
|
|
40
|
+
|
|
34
41
|
return (
|
|
35
42
|
<TableHead
|
|
36
43
|
key={header.id}
|
|
@@ -38,6 +45,8 @@ const DsTableHeader = <TData,>({ table }: DsTableHeaderProps<TData>) => {
|
|
|
38
45
|
styles.headerCell,
|
|
39
46
|
canSort && styles.sortableHeader,
|
|
40
47
|
isSelectColumn && styles.selectHeaderCell,
|
|
48
|
+
resolvedFilter && styles.filterableHeader,
|
|
49
|
+
hasActiveColumnFilter && styles.filterActive,
|
|
41
50
|
)}
|
|
42
51
|
onClick={header.column.getToggleSortingHandler()}
|
|
43
52
|
style={headerStyle}
|
|
@@ -67,6 +76,18 @@ const DsTableHeader = <TData,>({ table }: DsTableHeaderProps<TData>) => {
|
|
|
67
76
|
)}
|
|
68
77
|
</div>
|
|
69
78
|
)}
|
|
79
|
+
{resolvedFilter && (
|
|
80
|
+
<div className={styles.filterTriggerContainer}>
|
|
81
|
+
<DsTableColumnFilterPopover
|
|
82
|
+
hasActiveFilter={resolvedFilter.hasActiveFilter}
|
|
83
|
+
onApply={resolvedFilter.onApply}
|
|
84
|
+
onClear={resolvedFilter.onClear}
|
|
85
|
+
onCancel={resolvedFilter.onCancel}
|
|
86
|
+
>
|
|
87
|
+
{resolvedFilter.render()}
|
|
88
|
+
</DsTableColumnFilterPopover>
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
70
91
|
</div>
|
|
71
92
|
)}
|
|
72
93
|
</TableHead>
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
background-color: var(--background-secondary);
|
|
51
51
|
|
|
52
52
|
& > td {
|
|
53
|
+
flex: 1;
|
|
54
|
+
min-width: 0;
|
|
53
55
|
padding: var(--standard);
|
|
54
56
|
}
|
|
55
57
|
|
|
@@ -80,4 +82,24 @@
|
|
|
80
82
|
.selectableCell {
|
|
81
83
|
padding: 0;
|
|
82
84
|
text-align: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.tableRow .editableCell {
|
|
89
|
+
padding: 1px;
|
|
90
|
+
|
|
91
|
+
&:hover {
|
|
92
|
+
border: 1px solid var(--border-secondary-hover);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&:focus-within {
|
|
96
|
+
border: 1px solid var(--border-action-primary);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&:hover,
|
|
100
|
+
&:focus-within {
|
|
101
|
+
padding: 0;
|
|
102
|
+
border-bottom-width: 2px;
|
|
103
|
+
background: var(--background);
|
|
104
|
+
}
|
|
83
105
|
}
|
|
@@ -118,6 +118,7 @@ const DsTableRow = <TData,>({ ref, row, isSelected }: DsTableRowProps<TData>) =>
|
|
|
118
118
|
styles.tableCell,
|
|
119
119
|
cell.column.id === EXPANDER_COLUMN_ID && styles.expandableCell,
|
|
120
120
|
cell.column.id === SELECT_COLUMN_ID && styles.selectableCell,
|
|
121
|
+
typeof cell.column.columnDef.editCell === 'function' && styles.editableCell,
|
|
121
122
|
)}
|
|
122
123
|
style={cellStyle}
|
|
123
124
|
>
|
|
@@ -79,3 +79,22 @@
|
|
|
79
79
|
|
|
80
80
|
@include table-mixins.expanded-row-border('bottom');
|
|
81
81
|
}
|
|
82
|
+
|
|
83
|
+
.row td.editableCell {
|
|
84
|
+
padding: 1px;
|
|
85
|
+
|
|
86
|
+
&:hover {
|
|
87
|
+
border: 1px solid var(--border-secondary-hover);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
&:focus-within {
|
|
91
|
+
border: 1px solid var(--border-action-primary);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&:hover,
|
|
95
|
+
&:focus-within {
|
|
96
|
+
padding: 0;
|
|
97
|
+
border-bottom-width: 2px;
|
|
98
|
+
background: var(--background);
|
|
99
|
+
}
|
|
100
|
+
}
|
package/src/components/ds-table/components/ds-table-row-virtualized/ds-table-row-virtualized.tsx
CHANGED
|
@@ -67,7 +67,7 @@ export const DsTableRowVirtualized = <TData,>({
|
|
|
67
67
|
<>
|
|
68
68
|
{row.getVisibleCells().map((cell, idx) => {
|
|
69
69
|
const isLastColumn = idx === row.getVisibleCells().length - 1;
|
|
70
|
-
const cellStyle = getColumnSizeStyle(cell.column.getSize()
|
|
70
|
+
const cellStyle = getColumnSizeStyle(cell.column.getSize());
|
|
71
71
|
|
|
72
72
|
return (
|
|
73
73
|
<TableCell
|
|
@@ -77,6 +77,7 @@ export const DsTableRowVirtualized = <TData,>({
|
|
|
77
77
|
styles.cell,
|
|
78
78
|
cell.column.id === EXPANDER_COLUMN_ID && styles.expandableCell,
|
|
79
79
|
cell.column.id === SELECT_COLUMN_ID && styles.selectableCell,
|
|
80
|
+
typeof cell.column.columnDef.editCell === 'function' && styles.editableCell,
|
|
80
81
|
)}
|
|
81
82
|
>
|
|
82
83
|
{isLastColumn ? (
|
|
@@ -25,7 +25,7 @@ export interface DsTableRowVirtualizedProps<TData> {
|
|
|
25
25
|
/**
|
|
26
26
|
* TanStack virtualizer driving the scroll window for the table body.
|
|
27
27
|
*/
|
|
28
|
-
rowVirtualizer: Virtualizer<
|
|
28
|
+
rowVirtualizer: Virtualizer<HTMLTableSectionElement, HTMLTableRowElement>;
|
|
29
29
|
/**
|
|
30
30
|
* Virtual item descriptor for this row (index, start, size) from the virtualizer.
|
|
31
31
|
*/
|