@itwin/itwinui-react 3.15.4 → 3.16.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 +30 -0
- package/DEV-cjs/core/Breadcrumbs/Breadcrumbs.js +2 -2
- package/DEV-cjs/core/Checkbox/Checkbox.js +4 -6
- package/DEV-cjs/core/ComboBox/ComboBox.js +10 -6
- package/DEV-cjs/core/DatePicker/DatePicker.js +9 -1
- package/DEV-cjs/core/Dialog/Dialog.js +1 -1
- package/DEV-cjs/core/Panels/Panels.js +319 -0
- package/DEV-cjs/core/Panels/helpers.js +62 -0
- package/DEV-cjs/core/Radio/Radio.js +4 -6
- package/DEV-cjs/core/RadioTiles/RadioTileGroup.js +9 -2
- package/DEV-cjs/core/Select/SelectTag.js +9 -11
- package/DEV-cjs/core/Select/SelectTagContainer.js +2 -2
- package/DEV-cjs/core/Stepper/Stepper.js +1 -0
- package/DEV-cjs/core/Stepper/StepperStep.js +2 -1
- package/DEV-cjs/core/Table/Table.js +64 -47
- package/DEV-cjs/core/Table/TablePaginator.js +15 -3
- package/DEV-cjs/core/Table/actionHandlers/selectHandler.js +10 -7
- package/DEV-cjs/core/Table/columns/selectionColumn.js +6 -1
- package/DEV-cjs/core/Tree/Tree.js +1 -0
- package/DEV-cjs/index.js +4 -0
- package/DEV-cjs/styles.js +1 -1
- package/DEV-cjs/utils/components/MiddleTextTruncation.js +22 -4
- package/DEV-cjs/utils/components/OverflowContainer.js +170 -27
- package/DEV-cjs/utils/hooks/index.js +1 -1
- package/DEV-cjs/utils/hooks/useInstance.js +38 -0
- package/DEV-esm/core/Breadcrumbs/Breadcrumbs.js +2 -2
- package/DEV-esm/core/Checkbox/Checkbox.js +5 -10
- package/DEV-esm/core/ComboBox/ComboBox.js +10 -6
- package/DEV-esm/core/DatePicker/DatePicker.js +11 -1
- package/DEV-esm/core/Dialog/Dialog.js +1 -1
- package/DEV-esm/core/Panels/Panels.js +301 -0
- package/DEV-esm/core/Panels/helpers.js +42 -0
- package/DEV-esm/core/Radio/Radio.js +4 -9
- package/DEV-esm/core/RadioTiles/RadioTileGroup.js +8 -2
- package/DEV-esm/core/Select/SelectTag.js +9 -11
- package/DEV-esm/core/Select/SelectTagContainer.js +2 -2
- package/DEV-esm/core/Stepper/Stepper.js +1 -0
- package/DEV-esm/core/Stepper/StepperStep.js +2 -1
- package/DEV-esm/core/Table/Table.js +61 -47
- package/DEV-esm/core/Table/TablePaginator.js +16 -3
- package/DEV-esm/core/Table/actionHandlers/selectHandler.js +10 -7
- package/DEV-esm/core/Table/columns/selectionColumn.js +6 -1
- package/DEV-esm/core/Tree/Tree.js +1 -0
- package/DEV-esm/index.js +1 -0
- package/DEV-esm/styles.js +1 -1
- package/DEV-esm/utils/components/MiddleTextTruncation.js +22 -4
- package/DEV-esm/utils/components/OverflowContainer.js +143 -4
- package/DEV-esm/utils/hooks/index.js +1 -1
- package/DEV-esm/utils/hooks/useInstance.js +18 -0
- package/cjs/core/Breadcrumbs/Breadcrumbs.js +2 -2
- package/cjs/core/Checkbox/Checkbox.js +4 -6
- package/cjs/core/ComboBox/ComboBox.d.ts +13 -0
- package/cjs/core/ComboBox/ComboBox.js +10 -6
- package/cjs/core/DatePicker/DatePicker.d.ts +2 -2
- package/cjs/core/DatePicker/DatePicker.js +2 -1
- package/cjs/core/Dialog/Dialog.js +1 -1
- package/cjs/core/Dialog/DialogContext.d.ts +6 -2
- package/cjs/core/NonIdealState/NonIdealState.d.ts +15 -11
- package/cjs/core/Panels/Panels.d.ts +174 -0
- package/cjs/core/Panels/Panels.js +312 -0
- package/cjs/core/Panels/helpers.d.ts +23 -0
- package/cjs/core/Panels/helpers.js +61 -0
- package/cjs/core/Radio/Radio.js +4 -6
- package/cjs/core/RadioTiles/RadioTileGroup.d.ts +3 -1
- package/cjs/core/RadioTiles/RadioTileGroup.js +9 -2
- package/cjs/core/Select/SelectTag.d.ts +3 -1
- package/cjs/core/Select/SelectTag.js +9 -11
- package/cjs/core/Select/SelectTagContainer.js +2 -2
- package/cjs/core/Stepper/Stepper.d.ts +4 -0
- package/cjs/core/Stepper/Stepper.js +1 -0
- package/cjs/core/Stepper/StepperStep.d.ts +4 -0
- package/cjs/core/Stepper/StepperStep.js +2 -1
- package/cjs/core/Table/Table.d.ts +1 -0
- package/cjs/core/Table/Table.js +64 -47
- package/cjs/core/Table/TablePaginator.js +15 -3
- package/cjs/core/Table/actionHandlers/selectHandler.js +10 -7
- package/cjs/core/Table/columns/selectionColumn.js +6 -1
- package/cjs/core/Tree/Tree.js +1 -0
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +4 -0
- package/cjs/styles.js +1 -1
- package/cjs/utils/components/MiddleTextTruncation.d.ts +5 -7
- package/cjs/utils/components/MiddleTextTruncation.js +22 -4
- package/cjs/utils/components/OverflowContainer.d.ts +1 -0
- package/cjs/utils/components/OverflowContainer.js +170 -27
- package/cjs/utils/hooks/index.d.ts +1 -1
- package/cjs/utils/hooks/index.js +1 -1
- package/cjs/utils/hooks/useInstance.d.ts +22 -0
- package/cjs/utils/hooks/useInstance.js +38 -0
- package/esm/core/Breadcrumbs/Breadcrumbs.js +2 -2
- package/esm/core/Checkbox/Checkbox.js +5 -10
- package/esm/core/ComboBox/ComboBox.d.ts +13 -0
- package/esm/core/ComboBox/ComboBox.js +10 -6
- package/esm/core/DatePicker/DatePicker.d.ts +2 -2
- package/esm/core/DatePicker/DatePicker.js +4 -1
- package/esm/core/Dialog/Dialog.js +1 -1
- package/esm/core/Dialog/DialogContext.d.ts +6 -2
- package/esm/core/NonIdealState/NonIdealState.d.ts +15 -11
- package/esm/core/Panels/Panels.d.ts +174 -0
- package/esm/core/Panels/Panels.js +294 -0
- package/esm/core/Panels/helpers.d.ts +23 -0
- package/esm/core/Panels/helpers.js +41 -0
- package/esm/core/Radio/Radio.js +4 -9
- package/esm/core/RadioTiles/RadioTileGroup.d.ts +3 -1
- package/esm/core/RadioTiles/RadioTileGroup.js +8 -2
- package/esm/core/Select/SelectTag.d.ts +3 -1
- package/esm/core/Select/SelectTag.js +9 -11
- package/esm/core/Select/SelectTagContainer.js +2 -2
- package/esm/core/Stepper/Stepper.d.ts +4 -0
- package/esm/core/Stepper/Stepper.js +1 -0
- package/esm/core/Stepper/StepperStep.d.ts +4 -0
- package/esm/core/Stepper/StepperStep.js +2 -1
- package/esm/core/Table/Table.d.ts +1 -0
- package/esm/core/Table/Table.js +61 -47
- package/esm/core/Table/TablePaginator.js +16 -3
- package/esm/core/Table/actionHandlers/selectHandler.js +10 -7
- package/esm/core/Table/columns/selectionColumn.js +6 -1
- package/esm/core/Tree/Tree.js +1 -0
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/styles.js +1 -1
- package/esm/utils/components/MiddleTextTruncation.d.ts +5 -7
- package/esm/utils/components/MiddleTextTruncation.js +22 -4
- package/esm/utils/components/OverflowContainer.d.ts +1 -0
- package/esm/utils/components/OverflowContainer.js +143 -4
- package/esm/utils/hooks/index.d.ts +1 -1
- package/esm/utils/hooks/index.js +1 -1
- package/esm/utils/hooks/useInstance.d.ts +22 -0
- package/esm/utils/hooks/useInstance.js +18 -0
- package/package.json +2 -2
- package/styles.css +8 -8
- package/DEV-cjs/utils/hooks/useOverflow.js +0 -76
- package/DEV-esm/utils/hooks/useOverflow.js +0 -63
- package/cjs/utils/hooks/useOverflow.d.ts +0 -23
- package/cjs/utils/hooks/useOverflow.js +0 -76
- package/esm/utils/hooks/useOverflow.d.ts +0 -23
- package/esm/utils/hooks/useOverflow.js +0 -63
|
@@ -53,6 +53,7 @@ let singleRowSelectedAction = 'singleRowSelected';
|
|
|
53
53
|
let shiftRowSelectedAction = 'shiftRowSelected';
|
|
54
54
|
export const tableResizeStartAction = 'tableResizeStart';
|
|
55
55
|
let tableResizeEndAction = 'tableResizeEnd';
|
|
56
|
+
export const iuiId = Symbol('iui-id');
|
|
56
57
|
let flattenColumns = (columns) => {
|
|
57
58
|
let flatColumns = [];
|
|
58
59
|
columns.forEach((column) => {
|
|
@@ -105,6 +106,7 @@ export const Table = (props) => {
|
|
|
105
106
|
headerProps,
|
|
106
107
|
bodyProps,
|
|
107
108
|
emptyTableContentProps,
|
|
109
|
+
getRowId,
|
|
108
110
|
...rest
|
|
109
111
|
} = props;
|
|
110
112
|
useGlobals();
|
|
@@ -240,16 +242,30 @@ export const Table = (props) => {
|
|
|
240
242
|
),
|
|
241
243
|
[data, getSubRows],
|
|
242
244
|
);
|
|
243
|
-
let [rowHasParent] = React.useState(() => new WeakSet());
|
|
244
245
|
let getSubRowsWithSubComponents = React.useCallback(
|
|
245
|
-
(originalRow) => {
|
|
246
|
-
if (
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
246
|
+
(originalRow, relativeIndex) => {
|
|
247
|
+
if (originalRow[iuiId]) return [];
|
|
248
|
+
if (originalRow.subRows) return originalRow.subRows;
|
|
249
|
+
return [
|
|
250
|
+
{
|
|
251
|
+
[iuiId]: `subcomponent-${relativeIndex}`,
|
|
252
|
+
...originalRow,
|
|
253
|
+
},
|
|
254
|
+
];
|
|
251
255
|
},
|
|
252
|
-
[
|
|
256
|
+
[],
|
|
257
|
+
);
|
|
258
|
+
let getRowIdWithSubComponents = React.useCallback(
|
|
259
|
+
(originalRow, relativeIndex, parent) => {
|
|
260
|
+
let defaultRowId = parent
|
|
261
|
+
? `${parent.id}.${relativeIndex}`
|
|
262
|
+
: `${relativeIndex}`;
|
|
263
|
+
let rowIdFromUser = getRowId?.(originalRow, relativeIndex, parent);
|
|
264
|
+
if (void 0 !== rowIdFromUser && originalRow[iuiId])
|
|
265
|
+
return `${rowIdFromUser}-${defaultRowId}`;
|
|
266
|
+
return rowIdFromUser ?? defaultRowId;
|
|
267
|
+
},
|
|
268
|
+
[getRowId],
|
|
253
269
|
);
|
|
254
270
|
let instance = useTable(
|
|
255
271
|
{
|
|
@@ -269,6 +285,7 @@ export const Table = (props) => {
|
|
|
269
285
|
...props.initialState,
|
|
270
286
|
},
|
|
271
287
|
columnResizeMode,
|
|
288
|
+
getRowId: subComponent ? getRowIdWithSubComponents : getRowId,
|
|
272
289
|
},
|
|
273
290
|
useFlexLayout,
|
|
274
291
|
useResizeColumns(ownerDocument),
|
|
@@ -469,51 +486,52 @@ export const Table = (props) => {
|
|
|
469
486
|
(index, virtualItem, virtualizer) => {
|
|
470
487
|
let row = page[index];
|
|
471
488
|
prepareRow(row);
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
489
|
+
let isRowASubComponent = !!row.original[iuiId] && !!subComponent;
|
|
490
|
+
if (isRowASubComponent)
|
|
491
|
+
return React.createElement(
|
|
492
|
+
TableExpandableContentMemoized,
|
|
493
|
+
{
|
|
494
|
+
key: row.getRowProps().key,
|
|
495
|
+
virtualItem: virtualItem,
|
|
496
|
+
ref: enableVirtualization
|
|
497
|
+
? virtualizer?.measureElement
|
|
498
|
+
: tableRowRef(row),
|
|
499
|
+
isDisabled: !!isRowDisabled?.(row.original),
|
|
500
|
+
},
|
|
501
|
+
subComponent(row),
|
|
502
|
+
);
|
|
503
|
+
return React.createElement(TableRowMemoized, {
|
|
504
|
+
row: row,
|
|
505
|
+
rowProps: rowProps,
|
|
506
|
+
isLast: index === page.length - 1,
|
|
507
|
+
onRowInViewport: onRowInViewportRef,
|
|
508
|
+
onBottomReached: onBottomReachedRef,
|
|
509
|
+
intersectionMargin: intersectionMargin,
|
|
510
|
+
state: state,
|
|
511
|
+
key: row.getRowProps().key,
|
|
512
|
+
onClick: onRowClickHandler,
|
|
513
|
+
subComponent: subComponent,
|
|
514
|
+
isDisabled: !!isRowDisabled?.(row.original),
|
|
515
|
+
tableHasSubRows: hasAnySubRows,
|
|
516
|
+
tableInstance: instance,
|
|
517
|
+
expanderCell: expanderCell,
|
|
518
|
+
scrollContainerRef: tableRef.current,
|
|
519
|
+
tableRowRef: enableVirtualization ? void 0 : tableRowRef(row),
|
|
520
|
+
density: density,
|
|
521
|
+
virtualItem: virtualItem,
|
|
522
|
+
virtualizer: virtualizer,
|
|
523
|
+
});
|
|
506
524
|
},
|
|
507
525
|
[
|
|
508
526
|
page,
|
|
509
527
|
prepareRow,
|
|
528
|
+
subComponent,
|
|
510
529
|
rowProps,
|
|
511
530
|
onRowInViewportRef,
|
|
512
531
|
onBottomReachedRef,
|
|
513
532
|
intersectionMargin,
|
|
514
533
|
state,
|
|
515
534
|
onRowClickHandler,
|
|
516
|
-
subComponent,
|
|
517
535
|
isRowDisabled,
|
|
518
536
|
hasAnySubRows,
|
|
519
537
|
instance,
|
|
@@ -647,11 +665,7 @@ export const Table = (props) => {
|
|
|
647
665
|
},
|
|
648
666
|
bodyProps?.className,
|
|
649
667
|
),
|
|
650
|
-
style: {
|
|
651
|
-
outline: 0,
|
|
652
|
-
},
|
|
653
668
|
}),
|
|
654
|
-
tabIndex: -1,
|
|
655
669
|
'aria-multiselectable':
|
|
656
670
|
(isSelectable && 'multi' === selectionMode) || void 0,
|
|
657
671
|
},
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
SvgChevronRight,
|
|
14
14
|
Box,
|
|
15
15
|
OverflowContainer,
|
|
16
|
+
useLayoutEffect,
|
|
16
17
|
} from '../../utils/index.js';
|
|
17
18
|
import { styles } from '../../styles.js';
|
|
18
19
|
let defaultLocalization = {
|
|
@@ -56,7 +57,7 @@ export const TablePaginator = (props) => {
|
|
|
56
57
|
);
|
|
57
58
|
let pageListRef = React.useRef(null);
|
|
58
59
|
let [focusedIndex, setFocusedIndex] = React.useState(currentPage);
|
|
59
|
-
|
|
60
|
+
useLayoutEffect(() => {
|
|
60
61
|
setFocusedIndex(currentPage);
|
|
61
62
|
}, [currentPage]);
|
|
62
63
|
let needFocus = React.useRef(false);
|
|
@@ -178,6 +179,7 @@ export const TablePaginator = (props) => {
|
|
|
178
179
|
: React.createElement(TablePaginatorPageButtons, {
|
|
179
180
|
size: size,
|
|
180
181
|
focusedIndex: focusedIndex,
|
|
182
|
+
setFocusedIndex: setFocusedIndex,
|
|
181
183
|
totalPagesCount: totalPagesCount,
|
|
182
184
|
onPageChange: onPageChange,
|
|
183
185
|
currentPage: currentPage,
|
|
@@ -251,6 +253,7 @@ export const TablePaginator = (props) => {
|
|
|
251
253
|
let TablePaginatorPageButtons = (props) => {
|
|
252
254
|
let {
|
|
253
255
|
focusedIndex,
|
|
256
|
+
setFocusedIndex,
|
|
254
257
|
totalPagesCount,
|
|
255
258
|
onPageChange,
|
|
256
259
|
currentPage,
|
|
@@ -270,14 +273,24 @@ let TablePaginatorPageButtons = (props) => {
|
|
|
270
273
|
styleType: 'borderless',
|
|
271
274
|
size: buttonSize,
|
|
272
275
|
'data-iui-active': index === currentPage,
|
|
273
|
-
onClick: () =>
|
|
276
|
+
onClick: () => {
|
|
277
|
+
setFocusedIndex(index);
|
|
278
|
+
onPageChange(index);
|
|
279
|
+
},
|
|
274
280
|
'aria-current': index === currentPage,
|
|
275
281
|
'aria-label': localization.goToPageLabel?.(index + 1),
|
|
276
282
|
tabIndex: tabIndex,
|
|
277
283
|
},
|
|
278
284
|
index + 1,
|
|
279
285
|
),
|
|
280
|
-
[
|
|
286
|
+
[
|
|
287
|
+
focusedIndex,
|
|
288
|
+
buttonSize,
|
|
289
|
+
currentPage,
|
|
290
|
+
localization,
|
|
291
|
+
setFocusedIndex,
|
|
292
|
+
onPageChange,
|
|
293
|
+
],
|
|
281
294
|
);
|
|
282
295
|
let pageList = React.useMemo(
|
|
283
296
|
() =>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { iuiId } from '../Table.js';
|
|
1
2
|
let onSelectHandler = (newState, instance, onSelect, isRowDisabled) => {
|
|
2
3
|
if (!instance?.rows.length) {
|
|
3
4
|
onSelect?.([], newState);
|
|
@@ -7,14 +8,16 @@ let onSelectHandler = (newState, instance, onSelect, isRowDisabled) => {
|
|
|
7
8
|
let handleRow = (row) => {
|
|
8
9
|
if (isRowDisabled?.(row.original)) return false;
|
|
9
10
|
let isAllSubSelected = true;
|
|
10
|
-
row.initialSubRows
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (row.initialSubRows[0]?.original[iuiId] === void 0)
|
|
12
|
+
row.initialSubRows.forEach((subRow) => {
|
|
13
|
+
let result = handleRow(subRow);
|
|
14
|
+
if (!result) isAllSubSelected = false;
|
|
15
|
+
});
|
|
14
16
|
if (
|
|
15
|
-
|
|
16
|
-
(!
|
|
17
|
-
|
|
17
|
+
newState.selectedRowIds[row.id] &&
|
|
18
|
+
(!instance.selectSubRows ||
|
|
19
|
+
!row.initialSubRows.length ||
|
|
20
|
+
isAllSubSelected)
|
|
18
21
|
)
|
|
19
22
|
newSelectedRowIds[row.id] = true;
|
|
20
23
|
return !!newSelectedRowIds[row.id];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Checkbox } from '../../Checkbox/Checkbox.js';
|
|
3
3
|
import { DefaultCell } from '../cells/index.js';
|
|
4
|
+
import { iuiId } from '../Table.js';
|
|
4
5
|
export const SELECTION_CELL_ID = 'iui-table-checkbox-selector';
|
|
5
6
|
export const SelectionColumn = (props = {}) => {
|
|
6
7
|
let { isDisabled, density } = props;
|
|
@@ -50,7 +51,11 @@ export const SelectionColumn = (props = {}) => {
|
|
|
50
51
|
disabled: isDisabled?.(row.original),
|
|
51
52
|
onClick: (e) => e.stopPropagation(),
|
|
52
53
|
onChange: () => {
|
|
53
|
-
if (
|
|
54
|
+
if (
|
|
55
|
+
row.subRows.length > 0 &&
|
|
56
|
+
selectSubRows &&
|
|
57
|
+
void 0 === row.initialSubRows[0].original[iuiId]
|
|
58
|
+
)
|
|
54
59
|
row.toggleRowSelected(
|
|
55
60
|
!row.subRows.every(
|
|
56
61
|
(subRow) => subRow.isSelected || isDisabled?.(subRow.original),
|
package/DEV-esm/index.js
CHANGED
|
@@ -64,6 +64,7 @@ export { ModalContent } from './core/Modal/ModalContent.js';
|
|
|
64
64
|
export { ModalButtonBar } from './core/Modal/ModalButtonBar.js';
|
|
65
65
|
export { NotificationMarker } from './core/NotificationMarker/NotificationMarker.js';
|
|
66
66
|
export { Overlay } from './core/Overlay/Overlay.js';
|
|
67
|
+
export { Panels as unstable_Panels } from './core/Panels/Panels.js';
|
|
67
68
|
export { ProgressLinear } from './core/ProgressIndicators/ProgressLinear.js';
|
|
68
69
|
export { ProgressRadial } from './core/ProgressIndicators/ProgressRadial.js';
|
|
69
70
|
export { Radio } from './core/Radio/Radio.js';
|
package/DEV-esm/styles.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { OverflowContainer } from './OverflowContainer.js';
|
|
3
|
+
import { VisuallyHidden } from '../../core/VisuallyHidden/VisuallyHidden.js';
|
|
4
|
+
import { ShadowRoot } from './ShadowRoot.js';
|
|
3
5
|
let ELLIPSIS_CHAR = '…';
|
|
4
|
-
export const MiddleTextTruncation = (props) => {
|
|
5
|
-
let { text, style, ...rest } = props;
|
|
6
|
+
export const MiddleTextTruncation = React.forwardRef((props, forwardedRef) => {
|
|
7
|
+
let { text, endCharsCount, textRenderer, style, ...rest } = props;
|
|
6
8
|
return React.createElement(
|
|
7
9
|
OverflowContainer,
|
|
8
10
|
{
|
|
@@ -16,10 +18,26 @@ export const MiddleTextTruncation = (props) => {
|
|
|
16
18
|
},
|
|
17
19
|
itemsCount: text.length,
|
|
18
20
|
...rest,
|
|
21
|
+
ref: forwardedRef,
|
|
19
22
|
},
|
|
20
|
-
React.createElement(
|
|
23
|
+
React.createElement(
|
|
24
|
+
ShadowRoot,
|
|
25
|
+
null,
|
|
26
|
+
React.createElement(VisuallyHidden, null, text),
|
|
27
|
+
React.createElement('slot', {
|
|
28
|
+
'aria-hidden': true,
|
|
29
|
+
style: {
|
|
30
|
+
pointerEvents: 'none',
|
|
31
|
+
},
|
|
32
|
+
}),
|
|
33
|
+
),
|
|
34
|
+
React.createElement(MiddleTextTruncationContent, {
|
|
35
|
+
text: text,
|
|
36
|
+
endCharsCount: endCharsCount,
|
|
37
|
+
textRenderer: textRenderer,
|
|
38
|
+
}),
|
|
21
39
|
);
|
|
22
|
-
};
|
|
40
|
+
});
|
|
23
41
|
MiddleTextTruncation.displayName = 'MiddleTextTruncation';
|
|
24
42
|
let MiddleTextTruncationContent = (props) => {
|
|
25
43
|
let { text, endCharsCount = 6, textRenderer } = props;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useMergedRefs } from '../hooks/useMergedRefs.js';
|
|
3
3
|
import { Box } from './Box.js';
|
|
4
|
-
import {
|
|
4
|
+
import { useLayoutEffect } from '../hooks/useIsomorphicLayoutEffect.js';
|
|
5
5
|
import { useSafeContext } from '../hooks/useSafeContext.js';
|
|
6
|
-
|
|
6
|
+
import { isUnitTest } from '../functions/dev.js';
|
|
7
|
+
import { useResizeObserver } from '../hooks/useResizeObserver.js';
|
|
8
|
+
let OverflowContainerMain = React.forwardRef((props, forwardedRef) => {
|
|
7
9
|
let { itemsCount, children, overflowOrientation, ...rest } = props;
|
|
8
10
|
let [containerRef, visibleCount] = useOverflow(
|
|
9
11
|
itemsCount,
|
|
10
|
-
false,
|
|
11
12
|
overflowOrientation,
|
|
12
13
|
);
|
|
13
14
|
let overflowContainerContextValue = React.useMemo(
|
|
@@ -25,7 +26,7 @@ let OverflowContainerComponent = React.forwardRef((props, ref) => {
|
|
|
25
26
|
React.createElement(
|
|
26
27
|
Box,
|
|
27
28
|
{
|
|
28
|
-
ref: useMergedRefs(
|
|
29
|
+
ref: useMergedRefs(forwardedRef, containerRef),
|
|
29
30
|
...rest,
|
|
30
31
|
},
|
|
31
32
|
children,
|
|
@@ -38,12 +39,150 @@ let OverflowContainerOverflowNode = (props) => {
|
|
|
38
39
|
let isOverflowing = visibleCount < itemsCount;
|
|
39
40
|
return isOverflowing ? children : null;
|
|
40
41
|
};
|
|
42
|
+
let OverflowContainerComponent = React.forwardRef((props, forwardedRef) => {
|
|
43
|
+
let { itemsCount, overflowOrientation = 'horizontal', ...rest } = props;
|
|
44
|
+
let [size, setSize] = React.useState(null);
|
|
45
|
+
let [resizeRef] = useResizeObserver(setSize);
|
|
46
|
+
let ref = useMergedRefs(resizeRef, forwardedRef);
|
|
47
|
+
let key = `${itemsCount}${
|
|
48
|
+
'vertical' === overflowOrientation ? size?.height : size?.width
|
|
49
|
+
}`;
|
|
50
|
+
return React.createElement(OverflowContainerMain, {
|
|
51
|
+
...rest,
|
|
52
|
+
key: key,
|
|
53
|
+
ref: ref,
|
|
54
|
+
itemsCount: itemsCount,
|
|
55
|
+
overflowOrientation: overflowOrientation,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
41
58
|
export const OverflowContainer = Object.assign(OverflowContainerComponent, {
|
|
42
59
|
OverflowNode: OverflowContainerOverflowNode,
|
|
43
60
|
useContext: useOverflowContainerContext,
|
|
44
61
|
});
|
|
45
62
|
let OverflowContainerContext = React.createContext(void 0);
|
|
46
63
|
OverflowContainerContext.displayName = 'OverflowContainerContext';
|
|
64
|
+
let useOverflow = (itemsCount, orientation = 'horizontal') => {
|
|
65
|
+
let [guessState, dispatch] = React.useReducer(
|
|
66
|
+
overflowGuessReducer,
|
|
67
|
+
{
|
|
68
|
+
itemsCount,
|
|
69
|
+
},
|
|
70
|
+
overflowGuessReducerInitialState,
|
|
71
|
+
);
|
|
72
|
+
let containerRef = React.useRef(null);
|
|
73
|
+
let isGuessing = React.useRef(false);
|
|
74
|
+
useLayoutEffect(() => {
|
|
75
|
+
let { minGuess, maxGuess, isStabilized, visibleCount } = guessState;
|
|
76
|
+
if (isStabilized) return;
|
|
77
|
+
guessVisibleCount();
|
|
78
|
+
function guessVisibleCount() {
|
|
79
|
+
if (isStabilized || isGuessing.current || isUnitTest) return;
|
|
80
|
+
try {
|
|
81
|
+
isGuessing.current = true;
|
|
82
|
+
if (null == containerRef.current) return;
|
|
83
|
+
let dimension = 'horizontal' === orientation ? 'Width' : 'Height';
|
|
84
|
+
let availableSize = containerRef.current[`offset${dimension}`];
|
|
85
|
+
let requiredSize = containerRef.current[`scroll${dimension}`];
|
|
86
|
+
let isOverflowing = availableSize < requiredSize;
|
|
87
|
+
if (
|
|
88
|
+
0 === itemsCount ||
|
|
89
|
+
(1 === visibleCount && isOverflowing) ||
|
|
90
|
+
(visibleCount === itemsCount && !isOverflowing) ||
|
|
91
|
+
(maxGuess - minGuess === 1 && visibleCount === minGuess)
|
|
92
|
+
) {
|
|
93
|
+
dispatch({
|
|
94
|
+
type: 'stabilize',
|
|
95
|
+
});
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (maxGuess === visibleCount && !isOverflowing) {
|
|
99
|
+
dispatch({
|
|
100
|
+
type: 'shiftGuessRangeForward',
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
isOverflowing
|
|
105
|
+
? dispatch({
|
|
106
|
+
type: 'decreaseMaxGuess',
|
|
107
|
+
currentState: guessState,
|
|
108
|
+
})
|
|
109
|
+
: dispatch({
|
|
110
|
+
type: 'increaseMinGuess',
|
|
111
|
+
currentState: guessState,
|
|
112
|
+
});
|
|
113
|
+
} finally {
|
|
114
|
+
isGuessing.current = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}, [guessState, itemsCount, orientation]);
|
|
118
|
+
return [containerRef, guessState.visibleCount];
|
|
119
|
+
};
|
|
120
|
+
let STARTING_MAX_ITEMS_COUNT = 32;
|
|
121
|
+
let overflowGuessReducerInitialState = ({ itemsCount }) => {
|
|
122
|
+
let initialVisibleCount = Math.min(itemsCount, STARTING_MAX_ITEMS_COUNT);
|
|
123
|
+
return isUnitTest
|
|
124
|
+
? {
|
|
125
|
+
isStabilized: true,
|
|
126
|
+
minGuess: null,
|
|
127
|
+
maxGuess: null,
|
|
128
|
+
itemsCount,
|
|
129
|
+
visibleCount: itemsCount,
|
|
130
|
+
}
|
|
131
|
+
: {
|
|
132
|
+
isStabilized: false,
|
|
133
|
+
minGuess: 0,
|
|
134
|
+
maxGuess: initialVisibleCount,
|
|
135
|
+
itemsCount,
|
|
136
|
+
visibleCount: initialVisibleCount,
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
let overflowGuessReducer = (state, action) => {
|
|
140
|
+
let getSafeVisibleCount = ({ visibleCount, itemsCount }) =>
|
|
141
|
+
Math.min(itemsCount, visibleCount);
|
|
142
|
+
switch (action.type) {
|
|
143
|
+
case 'decreaseMaxGuess':
|
|
144
|
+
case 'increaseMinGuess':
|
|
145
|
+
if (state.isStabilized) return state;
|
|
146
|
+
let newMinGuess = state.minGuess;
|
|
147
|
+
let newMaxGuess = state.maxGuess;
|
|
148
|
+
if ('decreaseMaxGuess' === action.type)
|
|
149
|
+
newMaxGuess = action.currentState.visibleCount;
|
|
150
|
+
else newMinGuess = action.currentState.visibleCount;
|
|
151
|
+
let newVisibleCount = Math.floor((newMinGuess + newMaxGuess) / 2);
|
|
152
|
+
return {
|
|
153
|
+
...state,
|
|
154
|
+
isStabilized: false,
|
|
155
|
+
minGuess: newMinGuess,
|
|
156
|
+
maxGuess: newMaxGuess,
|
|
157
|
+
visibleCount: getSafeVisibleCount({
|
|
158
|
+
visibleCount: newVisibleCount,
|
|
159
|
+
itemsCount: state.itemsCount,
|
|
160
|
+
}),
|
|
161
|
+
};
|
|
162
|
+
case 'shiftGuessRangeForward':
|
|
163
|
+
if (state.isStabilized) return state;
|
|
164
|
+
let doubleOfMaxGuess = 2 * state.maxGuess;
|
|
165
|
+
return {
|
|
166
|
+
...state,
|
|
167
|
+
isStabilized: false,
|
|
168
|
+
minGuess: state.maxGuess,
|
|
169
|
+
maxGuess: doubleOfMaxGuess,
|
|
170
|
+
visibleCount: getSafeVisibleCount({
|
|
171
|
+
visibleCount: doubleOfMaxGuess,
|
|
172
|
+
itemsCount: state.itemsCount,
|
|
173
|
+
}),
|
|
174
|
+
};
|
|
175
|
+
case 'stabilize':
|
|
176
|
+
return {
|
|
177
|
+
...state,
|
|
178
|
+
isStabilized: true,
|
|
179
|
+
minGuess: null,
|
|
180
|
+
maxGuess: null,
|
|
181
|
+
};
|
|
182
|
+
default:
|
|
183
|
+
return state;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
47
186
|
function useOverflowContainerContext() {
|
|
48
187
|
let overflowContainerContext = useSafeContext(OverflowContainerContext);
|
|
49
188
|
return overflowContainerContext;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export * from './useEventListener.js';
|
|
2
2
|
export * from './useMergedRefs.js';
|
|
3
|
-
export * from './useOverflow.js';
|
|
4
3
|
export * from './useResizeObserver.js';
|
|
5
4
|
export * from './useContainerWidth.js';
|
|
6
5
|
export * from './useGlobals.js';
|
|
@@ -14,4 +13,5 @@ export * from './useId.js';
|
|
|
14
13
|
export * from './useControlledState.js';
|
|
15
14
|
export * from './useSyncExternalStore.js';
|
|
16
15
|
export * from './useVirtualScroll.js';
|
|
16
|
+
export * from './useInstance.js';
|
|
17
17
|
export * from './useWarningLogger.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useSyncExternalStore } from './useSyncExternalStore.js';
|
|
3
|
+
class Instance {}
|
|
4
|
+
export const useInstance = () => React.useMemo(() => new Instance(), []);
|
|
5
|
+
export const useSynchronizeInstance = (instance, properties) => {
|
|
6
|
+
let synchronize = React.useCallback(() => {
|
|
7
|
+
if (!(instance instanceof Instance)) return () => {};
|
|
8
|
+
Object.assign(instance, properties);
|
|
9
|
+
return () => {
|
|
10
|
+
for (let key in properties) delete instance[key];
|
|
11
|
+
};
|
|
12
|
+
}, [instance, properties]);
|
|
13
|
+
return useSyncExternalStore(
|
|
14
|
+
synchronize,
|
|
15
|
+
() => instance,
|
|
16
|
+
() => instance,
|
|
17
|
+
);
|
|
18
|
+
};
|
|
@@ -15,7 +15,7 @@ const _classnames = _interop_require_default._(require('classnames'));
|
|
|
15
15
|
const _index = require('../../utils/index.js');
|
|
16
16
|
const _Button = require('../Buttons/Button.js');
|
|
17
17
|
const _Anchor = require('../Typography/Anchor.js');
|
|
18
|
-
const BreadcrumbsComponent = _react.forwardRef((props,
|
|
18
|
+
const BreadcrumbsComponent = _react.forwardRef((props, forwardedRef) => {
|
|
19
19
|
let {
|
|
20
20
|
children: childrenProp,
|
|
21
21
|
currentIndex = _react.Children.count(childrenProp) - 1,
|
|
@@ -33,7 +33,7 @@ const BreadcrumbsComponent = _react.forwardRef((props, ref) => {
|
|
|
33
33
|
{
|
|
34
34
|
as: 'nav',
|
|
35
35
|
className: (0, _classnames.default)('iui-breadcrumbs', className),
|
|
36
|
-
ref:
|
|
36
|
+
ref: forwardedRef,
|
|
37
37
|
'aria-label': 'Breadcrumb',
|
|
38
38
|
...rest,
|
|
39
39
|
},
|
|
@@ -46,11 +46,11 @@ const Checkbox = _react.forwardRef((props, ref) => {
|
|
|
46
46
|
'iui-checkbox',
|
|
47
47
|
{
|
|
48
48
|
'iui-checkbox-visibility': 'eyeball' === variant,
|
|
49
|
-
'iui-loading': isLoading,
|
|
50
49
|
},
|
|
51
50
|
className,
|
|
52
51
|
),
|
|
53
52
|
style: style,
|
|
53
|
+
'data-iui-loading': isLoading ? 'true' : void 0,
|
|
54
54
|
disabled: disabled || isLoading,
|
|
55
55
|
type: 'checkbox',
|
|
56
56
|
ref: refs,
|
|
@@ -71,13 +71,11 @@ const Checkbox = _react.forwardRef((props, ref) => {
|
|
|
71
71
|
as: 'label',
|
|
72
72
|
className: (0, _classnames.default)(
|
|
73
73
|
'iui-checkbox-wrapper',
|
|
74
|
-
{
|
|
75
|
-
'iui-disabled': disabled,
|
|
76
|
-
[`iui-${status}`]: !!status,
|
|
77
|
-
'iui-loading': isLoading,
|
|
78
|
-
},
|
|
79
74
|
wrapperClassName,
|
|
80
75
|
),
|
|
76
|
+
'data-iui-disabled': disabled ? 'true' : void 0,
|
|
77
|
+
'data-iui-status': status,
|
|
78
|
+
'data-iui-loading': isLoading ? 'true' : void 0,
|
|
81
79
|
...restWrapperProps,
|
|
82
80
|
},
|
|
83
81
|
checkbox,
|
|
@@ -33,11 +33,24 @@ export type ComboboxMultipleTypeProps<T> = {
|
|
|
33
33
|
* Callback fired when selected value changes.
|
|
34
34
|
*/
|
|
35
35
|
onChange?: (value: T) => void;
|
|
36
|
+
/**
|
|
37
|
+
* Only applicable when `multiple` is enabled.
|
|
38
|
+
*
|
|
39
|
+
* If `true`, toggling an option will clear the filter.
|
|
40
|
+
* Useful when users would likely want to re-filter after toggling an option.
|
|
41
|
+
*
|
|
42
|
+
* If `false`, the filter will remain as-is after toggling an option.
|
|
43
|
+
* Useful when users would likely want to toggle multiple options from the _same_ filtered results.
|
|
44
|
+
*
|
|
45
|
+
* @default true
|
|
46
|
+
*/
|
|
47
|
+
clearFilterOnOptionToggle?: never;
|
|
36
48
|
} | {
|
|
37
49
|
multiple: true;
|
|
38
50
|
value?: T[] | null | undefined;
|
|
39
51
|
defaultValue?: T[] | null;
|
|
40
52
|
onChange?: (value: T[], event: MultipleOnChangeProps<T>) => void;
|
|
53
|
+
clearFilterOnOptionToggle?: boolean;
|
|
41
54
|
};
|
|
42
55
|
export type ComboBoxProps<T> = {
|
|
43
56
|
/**
|
|
@@ -51,6 +51,7 @@ const ComboBox = _react.forwardRef((props, forwardedRef) => {
|
|
|
51
51
|
onHide: onHideProp,
|
|
52
52
|
id = inputProps?.id ? `iui-${inputProps.id}-cb` : idPrefix,
|
|
53
53
|
defaultValue,
|
|
54
|
+
clearFilterOnOptionToggle = true,
|
|
54
55
|
...rest
|
|
55
56
|
} = props;
|
|
56
57
|
let inputRef = _react.useRef(null);
|
|
@@ -204,7 +205,6 @@ const ComboBox = _react.forwardRef((props, forwardedRef) => {
|
|
|
204
205
|
preventScroll: true,
|
|
205
206
|
});
|
|
206
207
|
if (optionsRef.current[__originalIndex]?.disabled) return;
|
|
207
|
-
setIsInputDirty(false);
|
|
208
208
|
if (multiple) {
|
|
209
209
|
let actionType = isMenuItemSelected(__originalIndex)
|
|
210
210
|
? 'removed'
|
|
@@ -222,7 +222,10 @@ const ComboBox = _react.forwardRef((props, forwardedRef) => {
|
|
|
222
222
|
.filter(Boolean)
|
|
223
223
|
.join(', '),
|
|
224
224
|
);
|
|
225
|
-
|
|
225
|
+
if (clearFilterOnOptionToggle) {
|
|
226
|
+
setInputValue('');
|
|
227
|
+
setIsInputDirty(false);
|
|
228
|
+
}
|
|
226
229
|
} else {
|
|
227
230
|
setSelectedIndexes(__originalIndex);
|
|
228
231
|
hide();
|
|
@@ -230,13 +233,14 @@ const ComboBox = _react.forwardRef((props, forwardedRef) => {
|
|
|
230
233
|
}
|
|
231
234
|
},
|
|
232
235
|
[
|
|
233
|
-
|
|
234
|
-
isMenuItemSelected,
|
|
236
|
+
optionsRef,
|
|
235
237
|
multiple,
|
|
238
|
+
isMenuItemSelected,
|
|
239
|
+
selectedChangeHandler,
|
|
240
|
+
setSelectedIndexes,
|
|
236
241
|
onChangeHandler,
|
|
237
|
-
|
|
242
|
+
clearFilterOnOptionToggle,
|
|
238
243
|
hide,
|
|
239
|
-
setSelectedIndexes,
|
|
240
244
|
],
|
|
241
245
|
);
|
|
242
246
|
let getMenuItem = _react.useCallback(
|