@nova-design-system/nova-react 3.28.0 → 3.29.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/README.md +1 -1
- package/dist/cjs/{index-Kxp9mv-Q.js → index-DgKzi_Pd.js} +405 -316
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/{nv-accordion-item.entry-fds_kk_3.js → nv-accordion-item.entry-D1o0gC5w.js} +3 -3
- package/dist/cjs/{nv-accordion.entry-BLs4N5ZL.js → nv-accordion.entry-DYJtq9Az.js} +1 -1
- package/dist/cjs/{nv-alert.entry-Bx1BiC8F.js → nv-alert.entry-CMtCdHmk.js} +2 -2
- package/dist/cjs/{nv-avatar.entry-DS88LME3.js → nv-avatar.entry-B6e7aG4W.js} +1 -1
- package/dist/cjs/{nv-badge_2.entry-vBPxmUmg.js → nv-badge_2.entry-RD3j0bJM.js} +7 -6
- package/dist/cjs/{nv-breadcrumb.entry-BOo3hA5y.js → nv-breadcrumb.entry-DgpqY2fr.js} +1 -1
- package/dist/cjs/{nv-breadcrumbs.entry-igHC_6Bd.js → nv-breadcrumbs.entry-CZgcDUw5.js} +1 -1
- package/dist/cjs/{nv-button.entry-BRQPmQbs.js → nv-button.entry-DR9NaRxG.js} +1 -1
- package/dist/cjs/{nv-buttongroup.entry-D3tG2EZ1.js → nv-buttongroup.entry-qO8r7WqG.js} +1 -1
- package/dist/cjs/{nv-calendar.entry-BpNHMTKr.js → nv-calendar.entry-DRlv3Xph.js} +1 -1
- package/dist/cjs/{nv-col.entry-lyIZqDsW.js → nv-col.entry-B7utJttP.js} +2 -2
- package/dist/cjs/{nv-datagrid.entry-BeemONKu.js → nv-datagrid.entry-digYmlnA.js} +1 -1
- package/dist/cjs/{nv-datagridcolumn.entry-B6kE4eVC.js → nv-datagridcolumn.entry-UwaDi-Hr.js} +1 -1
- package/dist/cjs/{nv-datetest.entry-C1uuC-ZG.js → nv-datetest.entry-BJtWaM2T.js} +1 -1
- package/dist/cjs/{nv-datetimetest.entry-Hthxbjj9.js → nv-datetimetest.entry-WaNPcHxh.js} +1 -1
- package/dist/cjs/{nv-dialog.entry-Cr9zwMPo.js → nv-dialog.entry-BI_mFT2G.js} +1 -1
- package/dist/cjs/{nv-dialogfooter_2.entry-DaaKojyE.js → nv-dialogfooter_2.entry-DU2ClBUR.js} +6 -4
- package/dist/cjs/{nv-drawer.entry-0UaYxCjh.js → nv-drawer.entry-BKF4CyOt.js} +1 -1
- package/dist/cjs/{nv-drawerfooter_2.entry-CqtuC7xP.js → nv-drawerfooter_2.entry-BSyUs7_4.js} +4 -2
- package/dist/cjs/{nv-fieldcheckbox.entry-DK3aO8C8.js → nv-fieldcheckbox.entry-l5FWToQi.js} +5 -5
- package/dist/cjs/{nv-fielddate.entry-BY-xF3KN.js → nv-fielddate.entry-BfviesNp.js} +2 -2
- package/dist/cjs/{nv-fielddaterange.entry-BT6qCQc3.js → nv-fielddaterange.entry-BvDkPLXG.js} +2 -2
- package/dist/cjs/{nv-fielddropdown.entry-CsVD067i.js → nv-fielddropdown.entry-B-nYjuMt.js} +2 -2
- package/dist/cjs/{nv-fielddropdownitem.entry-Crtfwlx7.js → nv-fielddropdownitem.entry-Dxqyb9DN.js} +1 -1
- package/dist/cjs/{nv-fieldmultiselect.entry-C2uoE60e.js → nv-fieldmultiselect.entry-CgO1RP0W.js} +115 -86
- package/dist/cjs/{nv-fieldnumber.entry-DzW5SiiZ.js → nv-fieldnumber.entry-stgdLi7x.js} +2 -2
- package/dist/cjs/{nv-fieldpassword.entry-D4r9Qxos.js → nv-fieldpassword.entry-CHA3JAUd.js} +2 -2
- package/dist/cjs/{nv-fieldradio.entry-DX0Ghx--.js → nv-fieldradio.entry-DHavVjB-.js} +1 -1
- package/dist/cjs/{nv-fieldselect.entry-_CglE66i.js → nv-fieldselect.entry-Dq5AsOFt.js} +2 -2
- package/dist/cjs/{nv-fieldslider.entry-6zt75uDU.js → nv-fieldslider.entry-SlF3BBUW.js} +1 -1
- package/dist/cjs/{nv-fieldtext.entry-B4X110wn.js → nv-fieldtext.entry-BYCc8SyD.js} +2 -2
- package/dist/cjs/{nv-fieldtextarea.entry-CeAMhA8Y.js → nv-fieldtextarea.entry-96JCOb9L.js} +2 -2
- package/dist/cjs/{nv-fieldtime.entry-BvzncwNd.js → nv-fieldtime.entry-BdzjxkaK.js} +15 -12
- package/dist/cjs/{nv-icon.entry-C2md2kmq.js → nv-icon.entry-CSRxi6BH.js} +2 -2
- package/dist/cjs/{nv-iconbutton_2.entry-D-zRpLjT.js → nv-iconbutton_2.entry-BtDxwMFD.js} +2 -2
- package/dist/cjs/{nv-menu.entry-DN_DkosX.js → nv-menu.entry-aX39SPH8.js} +1 -1
- package/dist/cjs/{nv-menuitem.entry-Cj6w33rq.js → nv-menuitem.entry-DzSp52G2.js} +2 -2
- package/dist/cjs/{nv-notification-bullet.entry-DagStJ3K.js → nv-notification-bullet.entry-D2yOXj46.js} +1 -1
- package/dist/cjs/{nv-notification.entry-oV69FpxE.js → nv-notification.entry-BRXHbtT8.js} +2 -2
- package/dist/cjs/{nv-notificationcontainer.entry-gQGHHeer.js → nv-notificationcontainer.entry-YNIM2_ah.js} +1 -1
- package/dist/cjs/{nv-pagination-nav.entry-BYvcVj1M.js → nv-pagination-nav.entry-uY1nT9aT.js} +1 -1
- package/dist/cjs/{nv-paginationtable.entry-CwCFQwbl.js → nv-paginationtable.entry-mr5KYXVC.js} +1 -1
- package/dist/cjs/{nv-popover.entry-DySToeSB.js → nv-popover.entry-_9ARKM70.js} +1 -1
- package/dist/cjs/{nv-row.entry-46ghuEeG.js → nv-row.entry-BMQvcqlU.js} +2 -2
- package/dist/cjs/{nv-sidebar.entry-B6opNG2r.js → nv-sidebar.entry-C4HTjJmz.js} +1 -1
- package/dist/cjs/{nv-sidebarcontent.entry-Pb8c2QoA.js → nv-sidebarcontent.entry-llnRwVuj.js} +1 -1
- package/dist/cjs/{nv-sidebardivider.entry-LCCO53Z5.js → nv-sidebardivider.entry--rQv8d5T.js} +1 -1
- package/dist/cjs/{nv-sidebarfooter.entry-DG5fkLHd.js → nv-sidebarfooter.entry-C5R0sUI_.js} +1 -1
- package/dist/cjs/{nv-sidebargroup.entry-DRqkSyQi.js → nv-sidebargroup.entry-DdrpLbU7.js} +1 -1
- package/dist/cjs/{nv-sidebarheader.entry-D6WvH2wG.js → nv-sidebarheader.entry-HuBPIsyf.js} +1 -1
- package/dist/cjs/{nv-sidebarlogo.entry-BorScwI-.js → nv-sidebarlogo.entry-TZNPoqnA.js} +1 -1
- package/dist/cjs/{nv-sidebarnavitem.entry-BEW74Rw3.js → nv-sidebarnavitem.entry-BWc3mF5I.js} +3 -3
- package/dist/cjs/{nv-sidebarnavsubitem.entry-EgaIlUfP.js → nv-sidebarnavsubitem.entry-DekANwO8.js} +1 -1
- package/dist/cjs/{nv-split.entry-CEC5Tuwz.js → nv-split.entry-BOwOB8FW.js} +1 -1
- package/dist/cjs/{nv-stack.entry-BR8lYaoI.js → nv-stack.entry-CaTiSLGN.js} +1 -1
- package/dist/cjs/{nv-table.entry-CISZFst5.js → nv-table.entry-LFZaS0Dy.js} +2 -2
- package/dist/cjs/{nv-tableheader.entry-DbdpTJGC.js → nv-tableheader.entry-CK50S8xW.js} +1 -1
- package/dist/cjs/{nv-timetest.entry-Dg1JEgAv.js → nv-timetest.entry-A9elKwkf.js} +1 -1
- package/dist/cjs/{nv-toggle.entry-DDfRpC1R.js → nv-toggle.entry-BGu-6rEs.js} +1 -1
- package/dist/cjs/{nv-togglebutton.entry-D7NkdIXP.js → nv-togglebutton.entry-BzAcBOgN.js} +1 -1
- package/dist/cjs/{nv-togglebuttongroup.entry-L8gitSUS.js → nv-togglebuttongroup.entry-CIWp7IXc.js} +1 -1
- package/dist/cjs/{nv-tooltip.entry-BElnrEqE.js → nv-tooltip.entry-CoGkSHpv.js} +1 -1
- package/dist/components/NvDatatable/NvDatatable.js +144 -55
- package/dist/types/components/NvDatatable/NvDatatable.d.ts +1 -1
- package/dist/types/components/NvDatatable/types.d.ts +5 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/providers/NotificationProvider.d.ts +2 -2
- package/package.json +1 -1
|
@@ -7,8 +7,7 @@ if (typeof window !== 'undefined' &&
|
|
|
7
7
|
defineNvPaginationtable();
|
|
8
8
|
}
|
|
9
9
|
import { applyRowSelection, applySelectAllSelection, shouldIgnoreSelectAllEvent, } from './selectionState';
|
|
10
|
-
function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filtering, selection, renderPagination, renderFiltering, stickyHeader, ...htmlProps }) {
|
|
11
|
-
const SELECTION_EVENT_SUPPRESSION_MS = 16;
|
|
10
|
+
function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filtering, selection, renderPagination, renderFiltering, onRowClick, stickyHeader, ...htmlProps }) {
|
|
12
11
|
const areSetsEqual = useCallback((a, b) => {
|
|
13
12
|
if (a.size !== b.size) {
|
|
14
13
|
return false;
|
|
@@ -32,9 +31,14 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
32
31
|
const selectionMode = selection?.mode ?? 'none';
|
|
33
32
|
const selectionEnabled = selectionMode !== 'none';
|
|
34
33
|
const selectAllEnabled = selection?.enableSelectAll ?? true;
|
|
34
|
+
const rowClickEnabled = typeof onRowClick === 'function';
|
|
35
35
|
const getSelectionRowId = useCallback((row) => selection?.getRowId?.(row) ?? '', [selection]);
|
|
36
36
|
const lastRowRef = useRef(null);
|
|
37
|
-
const
|
|
37
|
+
const selectAllIntentRef = useRef(false);
|
|
38
|
+
const rowSelectionIntentRef = useRef(null);
|
|
39
|
+
const selectAllIntentResetTimerRef = useRef(null);
|
|
40
|
+
const rowSelectionIntentResetTimerRef = useRef(null);
|
|
41
|
+
const INTENT_RESET_DELAY_MS = 16;
|
|
38
42
|
const debouncedSetFilter = useRef(null);
|
|
39
43
|
const setGlobalFilterDebounced = useCallback((value) => {
|
|
40
44
|
const debounceMs = filtering?.debounceMs ?? 300;
|
|
@@ -53,6 +57,12 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
53
57
|
if (debouncedSetFilter.current) {
|
|
54
58
|
clearTimeout(debouncedSetFilter.current);
|
|
55
59
|
}
|
|
60
|
+
if (selectAllIntentResetTimerRef.current) {
|
|
61
|
+
clearTimeout(selectAllIntentResetTimerRef.current);
|
|
62
|
+
}
|
|
63
|
+
if (rowSelectionIntentResetTimerRef.current) {
|
|
64
|
+
clearTimeout(rowSelectionIntentResetTimerRef.current);
|
|
65
|
+
}
|
|
56
66
|
};
|
|
57
67
|
}, []);
|
|
58
68
|
useEffect(() => {
|
|
@@ -237,8 +247,14 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
237
247
|
]);
|
|
238
248
|
const table = useReactTable(tableConfig);
|
|
239
249
|
const tableRows = table.getRowModel().rows;
|
|
250
|
+
const getCurrentVisibleRowIds = useCallback(() => {
|
|
251
|
+
return table
|
|
252
|
+
.getRowModel()
|
|
253
|
+
.rows.map((row) => getSelectionRowId(row.original))
|
|
254
|
+
.filter((id) => !!id);
|
|
255
|
+
}, [table, getSelectionRowId]);
|
|
240
256
|
const setSelectionState = useCallback((nextSelectedIds) => {
|
|
241
|
-
const current = new Set(
|
|
257
|
+
const current = new Set(selectedRowIdsRef.current);
|
|
242
258
|
const nextRaw = typeof nextSelectedIds === 'function'
|
|
243
259
|
? nextSelectedIds(new Set(current))
|
|
244
260
|
: nextSelectedIds;
|
|
@@ -246,27 +262,14 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
246
262
|
if (areSetsEqual(current, next)) {
|
|
247
263
|
return;
|
|
248
264
|
}
|
|
265
|
+
const hasExplicitSelectionIntent = selectAllIntentRef.current || rowSelectionIntentRef.current !== null;
|
|
266
|
+
if (!hasExplicitSelectionIntent && next.size < current.size) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
249
269
|
selectedRowIdsRef.current = next;
|
|
250
270
|
setSelectedRowIdsState(next);
|
|
251
271
|
selection?.onSelectionChange?.(new Set(next));
|
|
252
|
-
}, [selection,
|
|
253
|
-
const resolveCheckedChange = useCallback((event) => {
|
|
254
|
-
if (event && typeof event === 'object') {
|
|
255
|
-
const eventLike = event;
|
|
256
|
-
const target = eventLike.target;
|
|
257
|
-
const currentTarget = eventLike.currentTarget;
|
|
258
|
-
if (typeof eventLike.detail === 'boolean') {
|
|
259
|
-
return eventLike.detail;
|
|
260
|
-
}
|
|
261
|
-
if (typeof target?.checked === 'boolean') {
|
|
262
|
-
return target.checked;
|
|
263
|
-
}
|
|
264
|
-
if (typeof currentTarget?.checked === 'boolean') {
|
|
265
|
-
return currentTarget.checked;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
return undefined;
|
|
269
|
-
}, []);
|
|
272
|
+
}, [selection, areSetsEqual]);
|
|
270
273
|
const isRowSelected = useCallback((row) => {
|
|
271
274
|
if (!selectionEnabled) {
|
|
272
275
|
return false;
|
|
@@ -277,22 +280,18 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
277
280
|
const visibleRowIds = useMemo(() => tableRows
|
|
278
281
|
.map((row) => getSelectionRowId(row.original))
|
|
279
282
|
.filter((id) => !!id), [tableRows, getSelectionRowId]);
|
|
280
|
-
const visibleRowIdsSet = useMemo(() => new Set(visibleRowIds), [visibleRowIds]);
|
|
281
283
|
const setRowSelection = useCallback((row, isChecked) => {
|
|
282
284
|
if (!selectionEnabled) {
|
|
283
285
|
return;
|
|
284
286
|
}
|
|
285
|
-
if (suppressRowSelectionEventsRef.current) {
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
287
|
const rowId = getSelectionRowId(row);
|
|
289
288
|
if (!rowId) {
|
|
290
289
|
return;
|
|
291
290
|
}
|
|
292
|
-
|
|
291
|
+
const currentVisibleRowIdsSet = new Set(getCurrentVisibleRowIds());
|
|
292
|
+
if (!currentVisibleRowIdsSet.has(rowId)) {
|
|
293
293
|
return;
|
|
294
294
|
}
|
|
295
|
-
suppressRowSelectionEventsRef.current = true;
|
|
296
295
|
setSelectionState((current) => {
|
|
297
296
|
return applyRowSelection({
|
|
298
297
|
currentSelectedIds: current,
|
|
@@ -301,15 +300,12 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
301
300
|
selectionMode,
|
|
302
301
|
});
|
|
303
302
|
});
|
|
304
|
-
setTimeout(() => {
|
|
305
|
-
suppressRowSelectionEventsRef.current = false;
|
|
306
|
-
}, SELECTION_EVENT_SUPPRESSION_MS);
|
|
307
303
|
}, [
|
|
308
304
|
selectionEnabled,
|
|
309
305
|
getSelectionRowId,
|
|
310
|
-
visibleRowIdsSet,
|
|
311
306
|
selectionMode,
|
|
312
307
|
setSelectionState,
|
|
308
|
+
getCurrentVisibleRowIds,
|
|
313
309
|
]);
|
|
314
310
|
const selectAllState = useMemo(() => {
|
|
315
311
|
if (!selectionEnabled ||
|
|
@@ -333,34 +329,37 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
333
329
|
visibleRowIds,
|
|
334
330
|
selectedRowIdsState,
|
|
335
331
|
]);
|
|
332
|
+
const selectAllStateRef = useRef(selectAllState);
|
|
333
|
+
selectAllStateRef.current = selectAllState;
|
|
336
334
|
const handleSelectAllChanged = useCallback((isChecked) => {
|
|
337
335
|
if (!selectionEnabled ||
|
|
338
336
|
selectionMode !== 'multiple' ||
|
|
339
|
-
!selectAllEnabled
|
|
340
|
-
|
|
337
|
+
!selectAllEnabled) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
const currentVisibleRowIds = getCurrentVisibleRowIds();
|
|
341
|
+
if (!currentVisibleRowIds.length) {
|
|
341
342
|
return;
|
|
342
343
|
}
|
|
343
|
-
if (shouldIgnoreSelectAllEvent({
|
|
344
|
+
if (shouldIgnoreSelectAllEvent({
|
|
345
|
+
isChecked,
|
|
346
|
+
selectAllState: selectAllStateRef.current,
|
|
347
|
+
})) {
|
|
344
348
|
return;
|
|
345
349
|
}
|
|
346
|
-
suppressRowSelectionEventsRef.current = true;
|
|
347
350
|
setSelectionState((current) => {
|
|
348
351
|
return applySelectAllSelection({
|
|
349
352
|
currentSelectedIds: current,
|
|
350
|
-
visibleRowIds,
|
|
353
|
+
visibleRowIds: currentVisibleRowIds,
|
|
351
354
|
isChecked,
|
|
352
355
|
});
|
|
353
356
|
});
|
|
354
|
-
setTimeout(() => {
|
|
355
|
-
suppressRowSelectionEventsRef.current = false;
|
|
356
|
-
}, SELECTION_EVENT_SUPPRESSION_MS);
|
|
357
357
|
}, [
|
|
358
358
|
selectionEnabled,
|
|
359
359
|
selectionMode,
|
|
360
360
|
selectAllEnabled,
|
|
361
|
-
visibleRowIds,
|
|
362
|
-
selectAllState,
|
|
363
361
|
setSelectionState,
|
|
362
|
+
getCurrentVisibleRowIds,
|
|
364
363
|
]);
|
|
365
364
|
useEffect(() => {
|
|
366
365
|
if (!selectionEnabled || selection?.deselectOnFilter === false) {
|
|
@@ -474,7 +473,11 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
474
473
|
if (pagination?.labels?.pageSizeOption)
|
|
475
474
|
labelProps.labelPageSizeOption = pagination.labels.pageSizeOption;
|
|
476
475
|
return (React.createElement("div", { "data-testid": "default-pagination-wrapper", style: { marginTop: '16px' } },
|
|
477
|
-
React.createElement(NvPaginationtable, { pageIndex: api.pageIndex, pageSize: api.pageSize, pageCount: api.pageCount, rowCount: api.rowCount, ...labelProps, onPageIndexChanged: (e) =>
|
|
476
|
+
React.createElement(NvPaginationtable, { pageIndex: api.pageIndex, pageSize: api.pageSize, pageCount: api.pageCount, rowCount: api.rowCount, ...labelProps, onPageIndexChanged: (e) => {
|
|
477
|
+
api.setPageIndex(e.detail);
|
|
478
|
+
}, onPageSizeChanged: (e) => {
|
|
479
|
+
api.setPageSize(e.detail);
|
|
480
|
+
} })));
|
|
478
481
|
};
|
|
479
482
|
const filteringAPI = useMemo(() => {
|
|
480
483
|
if (!filtering) {
|
|
@@ -495,10 +498,69 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
495
498
|
filteredRows: filteredRowModel.rows.length,
|
|
496
499
|
};
|
|
497
500
|
}, [filtering, globalFilterState, table, setGlobalFilterDebounced]);
|
|
501
|
+
const markSelectAllIntentFromKey = (event) => {
|
|
502
|
+
if (event.key === ' ' || event.key === 'Enter') {
|
|
503
|
+
if (selectAllIntentResetTimerRef.current) {
|
|
504
|
+
clearTimeout(selectAllIntentResetTimerRef.current);
|
|
505
|
+
}
|
|
506
|
+
selectAllIntentRef.current = true;
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
const scheduleSelectAllIntentReset = () => {
|
|
510
|
+
if (selectAllIntentResetTimerRef.current) {
|
|
511
|
+
clearTimeout(selectAllIntentResetTimerRef.current);
|
|
512
|
+
}
|
|
513
|
+
selectAllIntentResetTimerRef.current = setTimeout(() => {
|
|
514
|
+
selectAllIntentRef.current = false;
|
|
515
|
+
selectAllIntentResetTimerRef.current = null;
|
|
516
|
+
}, INTENT_RESET_DELAY_MS);
|
|
517
|
+
};
|
|
518
|
+
const markRowSelectionIntentFromKey = (event, rowId) => {
|
|
519
|
+
if (event.key === ' ' || event.key === 'Enter') {
|
|
520
|
+
if (rowSelectionIntentResetTimerRef.current) {
|
|
521
|
+
clearTimeout(rowSelectionIntentResetTimerRef.current);
|
|
522
|
+
}
|
|
523
|
+
rowSelectionIntentRef.current = rowId;
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
const scheduleRowSelectionIntentReset = (rowId) => {
|
|
527
|
+
if (rowSelectionIntentResetTimerRef.current) {
|
|
528
|
+
clearTimeout(rowSelectionIntentResetTimerRef.current);
|
|
529
|
+
}
|
|
530
|
+
rowSelectionIntentResetTimerRef.current = setTimeout(() => {
|
|
531
|
+
if (rowSelectionIntentRef.current === rowId) {
|
|
532
|
+
rowSelectionIntentRef.current = null;
|
|
533
|
+
}
|
|
534
|
+
rowSelectionIntentResetTimerRef.current = null;
|
|
535
|
+
}, INTENT_RESET_DELAY_MS);
|
|
536
|
+
};
|
|
537
|
+
const renderRowSelectionCheckbox = useCallback((row, rowIndex) => {
|
|
538
|
+
const rowId = getSelectionRowId(row);
|
|
539
|
+
return (React.createElement(NvFieldcheckbox, { "data-testid": `datatable-row-${rowIndex}-checkbox`, checked: isRowSelected(row), label: `Select row ${rowIndex + 1}`, hideLabel: true, onPointerDownCapture: () => {
|
|
540
|
+
if (rowSelectionIntentResetTimerRef.current) {
|
|
541
|
+
clearTimeout(rowSelectionIntentResetTimerRef.current);
|
|
542
|
+
}
|
|
543
|
+
rowSelectionIntentRef.current = rowId;
|
|
544
|
+
}, onKeyDownCapture: (event) => {
|
|
545
|
+
markRowSelectionIntentFromKey(event, rowId);
|
|
546
|
+
}, onBlurCapture: () => {
|
|
547
|
+
scheduleRowSelectionIntentReset(rowId);
|
|
548
|
+
}, onCheckedChanged: (event) => {
|
|
549
|
+
if (!rowId || rowSelectionIntentRef.current !== rowId) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
try {
|
|
553
|
+
setRowSelection(row, event.detail);
|
|
554
|
+
}
|
|
555
|
+
finally {
|
|
556
|
+
rowSelectionIntentRef.current = null;
|
|
557
|
+
}
|
|
558
|
+
} }));
|
|
559
|
+
}, [getSelectionRowId, isRowSelected, setRowSelection]);
|
|
498
560
|
return (React.createElement(React.Fragment, null,
|
|
499
561
|
filteringAPI && renderFiltering && renderFiltering(filteringAPI),
|
|
500
562
|
React.createElement(NvTable, { ...htmlProps },
|
|
501
|
-
React.createElement("table",
|
|
563
|
+
React.createElement("table", { "data-row-click-enabled": rowClickEnabled ? 'true' : 'false' },
|
|
502
564
|
React.createElement("thead", { "data-sticky-top": stickyHeader ? 'true' : undefined }, table.getHeaderGroups().map((headerGroup) => (React.createElement("tr", { key: headerGroup.id }, headerGroup.headers.map((header) => {
|
|
503
565
|
const isSelectionHeader = header.id === '__selection__';
|
|
504
566
|
const canSort = header.column.getCanSort();
|
|
@@ -512,10 +574,22 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
512
574
|
: header.column.columnDef.enableResizing
|
|
513
575
|
? null
|
|
514
576
|
: true }, isSelectionHeader ? (selectionMode === 'multiple' && selectAllEnabled ? (React.createElement("div", { className: "flex items-center justify-center" },
|
|
515
|
-
React.createElement(NvFieldcheckbox, { "data-testid": "datatable-select-all-checkbox", checked: selectAllState === 'checked', indeterminate: selectAllState === 'indeterminate', label: "Select all rows", hideLabel: true,
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
577
|
+
React.createElement(NvFieldcheckbox, { "data-testid": "datatable-select-all-checkbox", checked: selectAllState === 'checked', indeterminate: selectAllState === 'indeterminate', label: "Select all rows", hideLabel: true, onPointerDownCapture: () => {
|
|
578
|
+
if (selectAllIntentResetTimerRef.current) {
|
|
579
|
+
clearTimeout(selectAllIntentResetTimerRef.current);
|
|
580
|
+
}
|
|
581
|
+
selectAllIntentRef.current = true;
|
|
582
|
+
}, onKeyDownCapture: markSelectAllIntentFromKey, onBlurCapture: () => {
|
|
583
|
+
scheduleSelectAllIntentReset();
|
|
584
|
+
}, onCheckedChanged: (event) => {
|
|
585
|
+
if (!selectAllIntentRef.current) {
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
try {
|
|
589
|
+
handleSelectAllChanged(event.detail);
|
|
590
|
+
}
|
|
591
|
+
finally {
|
|
592
|
+
selectAllIntentRef.current = false;
|
|
519
593
|
}
|
|
520
594
|
} }))) : null) : (React.createElement(NvTableheader, { sortable: canSort ? true : undefined, sortDirection: sortDirection || (canSort ? 'none' : undefined), onSortDirectionChanged: canSort
|
|
521
595
|
? header.column.getToggleSortingHandler()
|
|
@@ -525,14 +599,29 @@ function NvDatatable({ mode = 'client', columns, rows, pagination, sorting, filt
|
|
|
525
599
|
}))))),
|
|
526
600
|
React.createElement("tbody", null, tableRows.map((row, index) => {
|
|
527
601
|
const isLastRow = isInfiniteScroll && index === tableRows.length - 1;
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
602
|
+
const stableRowKey = getSelectionRowId(row.original) || row.id;
|
|
603
|
+
return (React.createElement("tr", { key: stableRowKey, "data-testid": `datatable-row-${index}`, ref: isLastRow ? lastRowRef : undefined, className: rowClickEnabled ? 'nv-datatable-row-clickable' : undefined, tabIndex: rowClickEnabled ? 0 : undefined, onClick: rowClickEnabled
|
|
604
|
+
? () => onRowClick?.({ row: row.original, rowIndex: index })
|
|
605
|
+
: undefined, onKeyDown: rowClickEnabled
|
|
606
|
+
? (event) => {
|
|
607
|
+
if (event.currentTarget !== event.target) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
611
|
+
event.preventDefault();
|
|
612
|
+
onRowClick?.({
|
|
613
|
+
row: row.original,
|
|
614
|
+
rowIndex: index,
|
|
615
|
+
});
|
|
616
|
+
}
|
|
534
617
|
}
|
|
535
|
-
|
|
618
|
+
: undefined }, row.getVisibleCells().map((cell) => (React.createElement("td", { key: cell.id, "data-testid": cell.column.id === '__selection__'
|
|
619
|
+
? 'datatable-cell-selection'
|
|
620
|
+
: `datatable-cell-${cell.column.id}`, onClick: cell.column.id === '__selection__'
|
|
621
|
+
? (event) => event.stopPropagation()
|
|
622
|
+
: undefined }, cell.column.id === '__selection__'
|
|
623
|
+
? renderRowSelectionCheckbox(row.original, index)
|
|
624
|
+
: flexRender(cell.column.columnDef.cell, cell.getContext()))))));
|
|
536
625
|
})))),
|
|
537
626
|
paginationAPI &&
|
|
538
627
|
(renderPagination
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { NvDatatableProps } from './types';
|
|
3
|
-
declare function NvDatatable<T>({ mode, columns, rows, pagination, sorting, filtering, selection, renderPagination, renderFiltering, stickyHeader, ...htmlProps }: NvDatatableProps<T>): React.JSX.Element;
|
|
3
|
+
declare function NvDatatable<T>({ mode, columns, rows, pagination, sorting, filtering, selection, renderPagination, renderFiltering, onRowClick, stickyHeader, ...htmlProps }: NvDatatableProps<T>): React.JSX.Element;
|
|
4
4
|
declare namespace NvDatatable {
|
|
5
5
|
var displayName: string;
|
|
6
6
|
}
|
|
@@ -9,11 +9,16 @@ export type NvDatatableProps<T> = {
|
|
|
9
9
|
sorting?: NvDatatableSortingConfig;
|
|
10
10
|
filtering?: NvDatatableFilteringConfig<T>;
|
|
11
11
|
selection?: NvDatatableSelectionConfigWithMode<T>;
|
|
12
|
+
onRowClick?: (args: NvDatatableRowClickEventArgs<T>) => void;
|
|
12
13
|
renderPagination?: (api: NvDatatableRenderPaginationAPI) => React.ReactNode;
|
|
13
14
|
renderFiltering?: (api: NvDatatableRenderFilteringAPI) => React.ReactNode;
|
|
14
15
|
stickyHeader?: boolean;
|
|
15
16
|
suppressHydrationWarning?: boolean;
|
|
16
17
|
} & Pick<ComponentProps<'div'>, 'className' | 'style'>;
|
|
18
|
+
export interface NvDatatableRowClickEventArgs<T> {
|
|
19
|
+
row: T;
|
|
20
|
+
rowIndex: number;
|
|
21
|
+
}
|
|
17
22
|
export type NvDatatableSelectionMode = 'none' | 'single' | 'multiple';
|
|
18
23
|
export interface NvDatatableSelectionConfig<T> {
|
|
19
24
|
mode?: NvDatatableSelectionMode;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './generated/components';
|
|
2
2
|
export * from '@nova-design-system/nova-webcomponents/constants';
|
|
3
|
+
export { type IconName } from '@nova-design-system/nova-webcomponents';
|
|
3
4
|
export { defineCustomElements } from '@nova-design-system/nova-webcomponents/loader';
|
|
4
5
|
export { useNotifications, NotificationProvider, type NotificationOptions, type NotificationContextValue, type NotificationProviderProps, type Notification, } from './providers/NotificationProvider';
|
|
5
6
|
export * from './components/NvDatatable';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
-
import { type NotificationPosition, type NotificationEmphasis, FeedbackColors } from '../index';
|
|
2
|
+
import { type NotificationPosition, type NotificationEmphasis, type IconName, FeedbackColors } from '../index';
|
|
3
3
|
export interface NotificationAction {
|
|
4
4
|
label: string;
|
|
5
5
|
onClick: () => void;
|
|
@@ -11,7 +11,7 @@ export interface NotificationOptions {
|
|
|
11
11
|
dismissible?: boolean;
|
|
12
12
|
emphasis?: `${NotificationEmphasis}`;
|
|
13
13
|
feedback?: `${FeedbackColors}`;
|
|
14
|
-
icon?:
|
|
14
|
+
icon?: `${IconName}`;
|
|
15
15
|
actions?: NotificationAction[];
|
|
16
16
|
actionSlot?: React.ReactElement;
|
|
17
17
|
duration?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nova-design-system/nova-react",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.29.0",
|
|
4
4
|
"description": "Nova is a design system created by Elia Group to empower creators to efficiently build solutions that people love to use.",
|
|
5
5
|
"author": "Elia Group",
|
|
6
6
|
"homepage": "https://nova.eliagroup.io",
|