@itwin/itwinui-react 3.15.2 → 3.15.4
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 +19 -0
- package/DEV-cjs/core/Breadcrumbs/Breadcrumbs.js +85 -65
- package/DEV-cjs/core/ButtonGroup/ButtonGroup.js +32 -27
- package/DEV-cjs/core/ComboBox/ComboBox.js +9 -6
- package/DEV-cjs/core/DatePicker/DatePicker.js +14 -4
- package/DEV-cjs/core/Popover/Popover.js +44 -16
- package/DEV-cjs/core/ProgressIndicators/ProgressLinear.js +2 -1
- package/DEV-cjs/core/Select/SelectTagContainer.js +27 -13
- package/DEV-cjs/core/Table/ColumnHeader.js +21 -28
- package/DEV-cjs/core/Table/Table.js +17 -10
- package/DEV-cjs/core/Table/TablePaginator.js +111 -88
- package/DEV-cjs/core/Table/cells/DefaultCell.js +3 -3
- package/DEV-cjs/core/Table/utils.js +3 -3
- package/DEV-cjs/core/TransferList/TransferList.js +18 -6
- package/DEV-cjs/styles.js +1 -1
- package/DEV-cjs/utils/components/MiddleTextTruncation.js +19 -14
- package/DEV-cjs/utils/components/OverflowContainer.js +63 -0
- package/DEV-cjs/utils/components/index.js +1 -0
- package/DEV-cjs/utils/hooks/useOverflow.js +12 -8
- package/DEV-esm/core/Breadcrumbs/Breadcrumbs.js +86 -67
- package/DEV-esm/core/ButtonGroup/ButtonGroup.js +33 -28
- package/DEV-esm/core/ComboBox/ComboBox.js +9 -6
- package/DEV-esm/core/DatePicker/DatePicker.js +12 -4
- package/DEV-esm/core/Popover/Popover.js +45 -17
- package/DEV-esm/core/ProgressIndicators/ProgressLinear.js +2 -1
- package/DEV-esm/core/Select/SelectTagContainer.js +24 -13
- package/DEV-esm/core/Table/ColumnHeader.js +28 -29
- package/DEV-esm/core/Table/Table.js +18 -11
- package/DEV-esm/core/Table/TablePaginator.js +112 -89
- package/DEV-esm/core/Table/cells/DefaultCell.js +4 -4
- package/DEV-esm/core/Table/utils.js +1 -1
- package/DEV-esm/core/TransferList/TransferList.js +14 -2
- package/DEV-esm/styles.js +1 -1
- package/DEV-esm/utils/components/MiddleTextTruncation.js +19 -14
- package/DEV-esm/utils/components/OverflowContainer.js +50 -0
- package/DEV-esm/utils/components/index.js +1 -0
- package/DEV-esm/utils/hooks/useOverflow.js +8 -8
- package/cjs/core/Breadcrumbs/Breadcrumbs.js +84 -64
- package/cjs/core/ButtonGroup/ButtonGroup.js +32 -27
- package/cjs/core/ComboBox/ComboBox.js +9 -6
- package/cjs/core/DatePicker/DatePicker.js +14 -4
- package/cjs/core/Popover/Popover.d.ts +10 -0
- package/cjs/core/Popover/Popover.js +44 -16
- package/cjs/core/ProgressIndicators/ProgressLinear.js +2 -1
- package/cjs/core/Select/SelectTagContainer.js +27 -13
- package/cjs/core/Table/ColumnHeader.d.ts +8 -12
- package/cjs/core/Table/ColumnHeader.js +21 -28
- package/cjs/core/Table/Table.js +13 -10
- package/cjs/core/Table/TablePaginator.js +111 -88
- package/cjs/core/Table/cells/DefaultCell.js +3 -3
- package/cjs/core/Table/utils.d.ts +2 -2
- package/cjs/core/Table/utils.js +3 -3
- package/cjs/core/TransferList/TransferList.d.ts +1 -1
- package/cjs/core/TransferList/TransferList.js +18 -6
- package/cjs/styles.js +1 -1
- package/cjs/utils/components/MiddleTextTruncation.js +19 -14
- package/cjs/utils/components/OverflowContainer.d.ts +37 -0
- package/cjs/utils/components/OverflowContainer.js +62 -0
- package/cjs/utils/components/index.d.ts +1 -0
- package/cjs/utils/components/index.js +1 -0
- package/cjs/utils/hooks/useOverflow.d.ts +2 -3
- package/cjs/utils/hooks/useOverflow.js +12 -8
- package/esm/core/Breadcrumbs/Breadcrumbs.js +85 -66
- package/esm/core/ButtonGroup/ButtonGroup.js +33 -28
- package/esm/core/ComboBox/ComboBox.js +9 -6
- package/esm/core/DatePicker/DatePicker.js +12 -4
- package/esm/core/Popover/Popover.d.ts +10 -0
- package/esm/core/Popover/Popover.js +45 -17
- package/esm/core/ProgressIndicators/ProgressLinear.js +2 -1
- package/esm/core/Select/SelectTagContainer.js +24 -13
- package/esm/core/Table/ColumnHeader.d.ts +8 -12
- package/esm/core/Table/ColumnHeader.js +28 -29
- package/esm/core/Table/Table.js +14 -11
- package/esm/core/Table/TablePaginator.js +112 -89
- package/esm/core/Table/cells/DefaultCell.js +4 -4
- package/esm/core/Table/utils.d.ts +2 -2
- package/esm/core/Table/utils.js +1 -1
- package/esm/core/TransferList/TransferList.d.ts +1 -1
- package/esm/core/TransferList/TransferList.js +14 -2
- package/esm/styles.js +1 -1
- package/esm/utils/components/MiddleTextTruncation.js +19 -14
- package/esm/utils/components/OverflowContainer.d.ts +37 -0
- package/esm/utils/components/OverflowContainer.js +49 -0
- package/esm/utils/components/index.d.ts +1 -0
- package/esm/utils/components/index.js +1 -0
- package/esm/utils/hooks/useOverflow.d.ts +2 -3
- package/esm/utils/hooks/useOverflow.js +8 -8
- package/package.json +1 -1
- package/styles.css +8 -8
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
useLatestRef,
|
|
25
25
|
useVirtualScroll,
|
|
26
26
|
} from '../../utils/index.js';
|
|
27
|
-
import {
|
|
27
|
+
import { TableInstanceContext } from './utils.js';
|
|
28
28
|
import { TableRowMemoized } from './TableRowMemoized.js';
|
|
29
29
|
import { customFilterFunctions } from './filters/customFilterFunctions.js';
|
|
30
30
|
import {
|
|
@@ -299,7 +299,6 @@ export const Table = (props) => {
|
|
|
299
299
|
gotoPage,
|
|
300
300
|
setPageSize,
|
|
301
301
|
flatHeaders,
|
|
302
|
-
visibleColumns,
|
|
303
302
|
setGlobalFilter,
|
|
304
303
|
} = instance;
|
|
305
304
|
let headerGroups = _headerGroups;
|
|
@@ -310,6 +309,10 @@ export const Table = (props) => {
|
|
|
310
309
|
"Table's `columns` prop should not have a top-level `Header` or sub-columns. They are only allowed to be passed for backwards compatibility.\n See https://github.com/iTwin/iTwinUI/wiki/iTwinUI-react-v2-migration-guide#breaking-changes",
|
|
311
310
|
);
|
|
312
311
|
}
|
|
312
|
+
if (subComponent && data.some((item) => !!item.subRows?.length))
|
|
313
|
+
logWarning(
|
|
314
|
+
'Passing both `subComponent` and `data` with `subRows` is not supported. There are features designed for `subRows` that are not compatible with `subComponent` and vice versa.',
|
|
315
|
+
);
|
|
313
316
|
let ariaDataAttributes = Object.entries(rest).reduce(
|
|
314
317
|
(result, [key, value]) => {
|
|
315
318
|
if (key.startsWith('data-') || key.startsWith('aria-'))
|
|
@@ -547,9 +550,9 @@ export const Table = (props) => {
|
|
|
547
550
|
updateStickyState();
|
|
548
551
|
}, []);
|
|
549
552
|
return React.createElement(
|
|
550
|
-
|
|
553
|
+
TableInstanceContext.Provider,
|
|
551
554
|
{
|
|
552
|
-
value: instance
|
|
555
|
+
value: instance,
|
|
553
556
|
},
|
|
554
557
|
React.createElement(
|
|
555
558
|
Box,
|
|
@@ -608,19 +611,23 @@ export const Table = (props) => {
|
|
|
608
611
|
return React.createElement(ColumnHeader, {
|
|
609
612
|
...dragAndDropProps,
|
|
610
613
|
key: dragAndDropProps.key || column.id || index,
|
|
611
|
-
columnRefs: columnRefs,
|
|
612
614
|
column: column,
|
|
613
|
-
index: index,
|
|
614
615
|
areFiltersSet: areFiltersSet,
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
616
|
+
columnHasExpanders:
|
|
617
|
+
hasAnySubRows &&
|
|
618
|
+
index ===
|
|
619
|
+
headerGroup.headers.findIndex(
|
|
620
|
+
(c) => c.id !== SELECTION_CELL_ID,
|
|
621
|
+
),
|
|
622
|
+
isLast: index === headerGroup.headers.length - 1,
|
|
623
|
+
isTableEmpty: 0 === data.length,
|
|
619
624
|
isResizable: isResizable,
|
|
620
625
|
columnResizeMode: columnResizeMode,
|
|
621
626
|
enableColumnReordering: enableColumnReordering,
|
|
622
627
|
density: density,
|
|
623
|
-
|
|
628
|
+
ref: (el) => {
|
|
629
|
+
if (el) columnRefs.current[column.id] = el;
|
|
630
|
+
},
|
|
624
631
|
});
|
|
625
632
|
}),
|
|
626
633
|
),
|
|
@@ -8,12 +8,13 @@ import { MenuItem } from '../Menu/MenuItem.js';
|
|
|
8
8
|
import {
|
|
9
9
|
getBoundedValue,
|
|
10
10
|
useGlobals,
|
|
11
|
-
useOverflow,
|
|
12
11
|
useContainerWidth,
|
|
13
12
|
SvgChevronLeft,
|
|
14
13
|
SvgChevronRight,
|
|
15
14
|
Box,
|
|
15
|
+
OverflowContainer,
|
|
16
16
|
} from '../../utils/index.js';
|
|
17
|
+
import { styles } from '../../styles.js';
|
|
17
18
|
let defaultLocalization = {
|
|
18
19
|
pageSizeLabel: (size) => `${size} per page`,
|
|
19
20
|
rangeLabel: (startIndex, endIndex, totalRows, isLoading) =>
|
|
@@ -55,7 +56,7 @@ export const TablePaginator = (props) => {
|
|
|
55
56
|
);
|
|
56
57
|
let pageListRef = React.useRef(null);
|
|
57
58
|
let [focusedIndex, setFocusedIndex] = React.useState(currentPage);
|
|
58
|
-
React.
|
|
59
|
+
React.useLayoutEffect(() => {
|
|
59
60
|
setFocusedIndex(currentPage);
|
|
60
61
|
}, [currentPage]);
|
|
61
62
|
let needFocus = React.useRef(false);
|
|
@@ -64,7 +65,7 @@ export const TablePaginator = (props) => {
|
|
|
64
65
|
if (isMounted.current && needFocus.current) {
|
|
65
66
|
let buttonToFocus = Array.from(
|
|
66
67
|
pageListRef.current?.querySelectorAll(
|
|
67
|
-
'
|
|
68
|
+
`.${styles['iui-table-paginator-page-button']}`,
|
|
68
69
|
) ?? [],
|
|
69
70
|
).find((el) => el.textContent?.trim() === (focusedIndex + 1).toString());
|
|
70
71
|
buttonToFocus?.focus();
|
|
@@ -73,35 +74,7 @@ export const TablePaginator = (props) => {
|
|
|
73
74
|
isMounted.current = true;
|
|
74
75
|
}, [focusedIndex]);
|
|
75
76
|
let buttonSize = 'default' != size ? 'small' : void 0;
|
|
76
|
-
let pageButton = React.useCallback(
|
|
77
|
-
(index, tabIndex = index === focusedIndex ? 0 : -1) =>
|
|
78
|
-
React.createElement(
|
|
79
|
-
Button,
|
|
80
|
-
{
|
|
81
|
-
key: index,
|
|
82
|
-
className: 'iui-table-paginator-page-button',
|
|
83
|
-
styleType: 'borderless',
|
|
84
|
-
size: buttonSize,
|
|
85
|
-
'data-iui-active': index === currentPage,
|
|
86
|
-
onClick: () => onPageChange(index),
|
|
87
|
-
'aria-current': index === currentPage,
|
|
88
|
-
'aria-label': localization.goToPageLabel(index + 1),
|
|
89
|
-
tabIndex: tabIndex,
|
|
90
|
-
},
|
|
91
|
-
index + 1,
|
|
92
|
-
),
|
|
93
|
-
[focusedIndex, currentPage, localization, buttonSize, onPageChange],
|
|
94
|
-
);
|
|
95
77
|
let totalPagesCount = Math.ceil(totalRowsCount / pageSize);
|
|
96
|
-
let pageList = React.useMemo(
|
|
97
|
-
() =>
|
|
98
|
-
new Array(totalPagesCount)
|
|
99
|
-
.fill(null)
|
|
100
|
-
.map((_, index) => pageButton(index)),
|
|
101
|
-
[pageButton, totalPagesCount],
|
|
102
|
-
);
|
|
103
|
-
let [overflowRef, visibleCount] = useOverflow(pageList);
|
|
104
|
-
let [paginatorResizeRef, paginatorWidth] = useContainerWidth();
|
|
105
78
|
let onKeyDown = (event) => {
|
|
106
79
|
if (event.altKey) return;
|
|
107
80
|
let focusPage = (delta) => {
|
|
@@ -132,30 +105,10 @@ export const TablePaginator = (props) => {
|
|
|
132
105
|
break;
|
|
133
106
|
}
|
|
134
107
|
};
|
|
135
|
-
let
|
|
136
|
-
let startPage = focusedIndex - halfVisibleCount;
|
|
137
|
-
let endPage = focusedIndex + halfVisibleCount + 1;
|
|
138
|
-
if (startPage < 0) {
|
|
139
|
-
endPage = Math.min(totalPagesCount, endPage + Math.abs(startPage));
|
|
140
|
-
startPage = 0;
|
|
141
|
-
}
|
|
142
|
-
if (endPage > totalPagesCount) {
|
|
143
|
-
startPage = Math.max(0, startPage - (endPage - totalPagesCount));
|
|
144
|
-
endPage = totalPagesCount;
|
|
145
|
-
}
|
|
146
|
-
let hasNoRows = 0 === totalPagesCount;
|
|
108
|
+
let [paginatorResizeRef, paginatorWidth] = useContainerWidth();
|
|
147
109
|
let showPagesList = totalPagesCount > 1 || isLoading;
|
|
148
110
|
let showPageSizeList = pageSizeList && !!onPageSizeChange && !!totalRowsCount;
|
|
149
|
-
let
|
|
150
|
-
Box,
|
|
151
|
-
{
|
|
152
|
-
as: 'span',
|
|
153
|
-
className: cx('iui-table-paginator-ellipsis', {
|
|
154
|
-
'iui-table-paginator-ellipsis-small': 'small' === size,
|
|
155
|
-
}),
|
|
156
|
-
},
|
|
157
|
-
'…',
|
|
158
|
-
);
|
|
111
|
+
let hasNoRows = 0 === totalPagesCount;
|
|
159
112
|
let noRowsContent = React.createElement(
|
|
160
113
|
React.Fragment,
|
|
161
114
|
null,
|
|
@@ -196,10 +149,10 @@ export const TablePaginator = (props) => {
|
|
|
196
149
|
),
|
|
197
150
|
showPagesList &&
|
|
198
151
|
React.createElement(
|
|
199
|
-
|
|
152
|
+
OverflowContainer,
|
|
200
153
|
{
|
|
201
154
|
className: 'iui-center',
|
|
202
|
-
|
|
155
|
+
itemsCount: totalPagesCount,
|
|
203
156
|
},
|
|
204
157
|
React.createElement(
|
|
205
158
|
IconButton,
|
|
@@ -220,40 +173,17 @@ export const TablePaginator = (props) => {
|
|
|
220
173
|
onKeyDown: onKeyDown,
|
|
221
174
|
ref: pageListRef,
|
|
222
175
|
},
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
ellipsis,
|
|
235
|
-
),
|
|
236
|
-
pageList.slice(startPage, endPage),
|
|
237
|
-
endPage !== totalPagesCount &&
|
|
238
|
-
!isLoading &&
|
|
239
|
-
React.createElement(
|
|
240
|
-
React.Fragment,
|
|
241
|
-
null,
|
|
242
|
-
ellipsis,
|
|
243
|
-
pageButton(totalPagesCount - 1, 0),
|
|
244
|
-
),
|
|
245
|
-
isLoading &&
|
|
246
|
-
React.createElement(
|
|
247
|
-
React.Fragment,
|
|
248
|
-
null,
|
|
249
|
-
ellipsis,
|
|
250
|
-
React.createElement(ProgressRadial, {
|
|
251
|
-
indeterminate: true,
|
|
252
|
-
size: 'small',
|
|
253
|
-
}),
|
|
254
|
-
),
|
|
255
|
-
);
|
|
256
|
-
})(),
|
|
176
|
+
hasNoRows
|
|
177
|
+
? noRowsContent
|
|
178
|
+
: React.createElement(TablePaginatorPageButtons, {
|
|
179
|
+
size: size,
|
|
180
|
+
focusedIndex: focusedIndex,
|
|
181
|
+
totalPagesCount: totalPagesCount,
|
|
182
|
+
onPageChange: onPageChange,
|
|
183
|
+
currentPage: currentPage,
|
|
184
|
+
localization: localization,
|
|
185
|
+
isLoading: isLoading,
|
|
186
|
+
}),
|
|
257
187
|
),
|
|
258
188
|
React.createElement(
|
|
259
189
|
IconButton,
|
|
@@ -318,3 +248,96 @@ export const TablePaginator = (props) => {
|
|
|
318
248
|
),
|
|
319
249
|
);
|
|
320
250
|
};
|
|
251
|
+
let TablePaginatorPageButtons = (props) => {
|
|
252
|
+
let {
|
|
253
|
+
focusedIndex,
|
|
254
|
+
totalPagesCount,
|
|
255
|
+
onPageChange,
|
|
256
|
+
currentPage,
|
|
257
|
+
localization,
|
|
258
|
+
isLoading,
|
|
259
|
+
size,
|
|
260
|
+
} = props;
|
|
261
|
+
let { visibleCount } = OverflowContainer.useContext();
|
|
262
|
+
let buttonSize = 'default' != size ? 'small' : void 0;
|
|
263
|
+
let pageButton = React.useCallback(
|
|
264
|
+
(index, tabIndex = index === focusedIndex ? 0 : -1) =>
|
|
265
|
+
React.createElement(
|
|
266
|
+
Button,
|
|
267
|
+
{
|
|
268
|
+
key: index,
|
|
269
|
+
className: 'iui-table-paginator-page-button',
|
|
270
|
+
styleType: 'borderless',
|
|
271
|
+
size: buttonSize,
|
|
272
|
+
'data-iui-active': index === currentPage,
|
|
273
|
+
onClick: () => onPageChange(index),
|
|
274
|
+
'aria-current': index === currentPage,
|
|
275
|
+
'aria-label': localization.goToPageLabel?.(index + 1),
|
|
276
|
+
tabIndex: tabIndex,
|
|
277
|
+
},
|
|
278
|
+
index + 1,
|
|
279
|
+
),
|
|
280
|
+
[focusedIndex, currentPage, localization, buttonSize, onPageChange],
|
|
281
|
+
);
|
|
282
|
+
let pageList = React.useMemo(
|
|
283
|
+
() =>
|
|
284
|
+
new Array(totalPagesCount)
|
|
285
|
+
.fill(null)
|
|
286
|
+
.map((_, index) => pageButton(index)),
|
|
287
|
+
[pageButton, totalPagesCount],
|
|
288
|
+
);
|
|
289
|
+
let halfVisibleCount = Math.floor(visibleCount / 2);
|
|
290
|
+
let startPage = focusedIndex - halfVisibleCount;
|
|
291
|
+
let endPage = focusedIndex + halfVisibleCount + 1;
|
|
292
|
+
if (startPage < 0) {
|
|
293
|
+
endPage = Math.min(totalPagesCount, endPage + Math.abs(startPage));
|
|
294
|
+
startPage = 0;
|
|
295
|
+
}
|
|
296
|
+
if (endPage > totalPagesCount) {
|
|
297
|
+
startPage = Math.max(0, startPage - (endPage - totalPagesCount));
|
|
298
|
+
endPage = totalPagesCount;
|
|
299
|
+
}
|
|
300
|
+
let ellipsis = React.createElement(
|
|
301
|
+
Box,
|
|
302
|
+
{
|
|
303
|
+
as: 'span',
|
|
304
|
+
className: cx('iui-table-paginator-ellipsis', {
|
|
305
|
+
'iui-table-paginator-ellipsis-small': 'small' === size,
|
|
306
|
+
}),
|
|
307
|
+
},
|
|
308
|
+
'…',
|
|
309
|
+
);
|
|
310
|
+
if (1 === visibleCount) return pageButton(focusedIndex);
|
|
311
|
+
let showStartEllipsis = startPage > 1;
|
|
312
|
+
let showEndEllipsis = endPage < totalPagesCount - 1;
|
|
313
|
+
return React.createElement(
|
|
314
|
+
React.Fragment,
|
|
315
|
+
null,
|
|
316
|
+
0 !== startPage &&
|
|
317
|
+
React.createElement(
|
|
318
|
+
React.Fragment,
|
|
319
|
+
null,
|
|
320
|
+
pageButton(0, 0),
|
|
321
|
+
showStartEllipsis ? ellipsis : null,
|
|
322
|
+
),
|
|
323
|
+
pageList.slice(startPage, endPage),
|
|
324
|
+
endPage !== totalPagesCount &&
|
|
325
|
+
!isLoading &&
|
|
326
|
+
React.createElement(
|
|
327
|
+
React.Fragment,
|
|
328
|
+
null,
|
|
329
|
+
showEndEllipsis ? ellipsis : null,
|
|
330
|
+
pageButton(totalPagesCount - 1, 0),
|
|
331
|
+
),
|
|
332
|
+
isLoading &&
|
|
333
|
+
React.createElement(
|
|
334
|
+
React.Fragment,
|
|
335
|
+
null,
|
|
336
|
+
ellipsis,
|
|
337
|
+
React.createElement(ProgressRadial, {
|
|
338
|
+
indeterminate: true,
|
|
339
|
+
size: 'small',
|
|
340
|
+
}),
|
|
341
|
+
),
|
|
342
|
+
);
|
|
343
|
+
};
|
|
@@ -2,14 +2,14 @@ import * as React from 'react';
|
|
|
2
2
|
import { defaultColumn } from 'react-table';
|
|
3
3
|
import cx from 'classnames';
|
|
4
4
|
import { Box, LineClamp, ShadowRoot } from '../../../utils/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { TableInstanceContext } from '../utils.js';
|
|
6
6
|
export const DefaultCell = (props) => {
|
|
7
|
-
let
|
|
7
|
+
let instance = React.useContext(TableInstanceContext);
|
|
8
8
|
let isCustomCell = React.useMemo(
|
|
9
9
|
() =>
|
|
10
|
-
|
|
10
|
+
instance?.columns.find(({ id }) => props.cellProps.column.id === id)
|
|
11
11
|
?.Cell !== defaultColumn.Cell,
|
|
12
|
-
[
|
|
12
|
+
[instance, props.cellProps.column.id],
|
|
13
13
|
);
|
|
14
14
|
let {
|
|
15
15
|
cellElementProps: {
|
|
@@ -47,4 +47,4 @@ export const getSubRowStyle = ({ density = 'default', depth = 1 }) => {
|
|
|
47
47
|
paddingInlineStart: cellPadding + depth * multiplier,
|
|
48
48
|
};
|
|
49
49
|
};
|
|
50
|
-
export const
|
|
50
|
+
export const TableInstanceContext = React.createContext(void 0);
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { List } from '../List/List.js';
|
|
12
12
|
import { ListItem } from '../List/ListItem.js';
|
|
13
13
|
import { Label } from '../Label/Label.js';
|
|
14
|
+
import { ButtonGroup } from '../ButtonGroup/ButtonGroup.js';
|
|
14
15
|
let TransferListComponent = polymorphic.div('iui-transfer-list-wrapper');
|
|
15
16
|
TransferListComponent.displayName = 'TransferList';
|
|
16
17
|
let TransferListListboxWrapper = React.forwardRef((props, ref) => {
|
|
@@ -152,8 +153,19 @@ let TransferListListboxLabel = React.forwardRef((props, ref) => {
|
|
|
152
153
|
);
|
|
153
154
|
});
|
|
154
155
|
TransferListListboxLabel.displayName = 'TransferList.ListboxLabel';
|
|
155
|
-
let TransferListToolbar =
|
|
156
|
-
|
|
156
|
+
let TransferListToolbar = React.forwardRef((props, ref) => {
|
|
157
|
+
let { className, children, ...rest } = props;
|
|
158
|
+
return React.createElement(
|
|
159
|
+
ButtonGroup,
|
|
160
|
+
{
|
|
161
|
+
role: 'toolbar',
|
|
162
|
+
ref: ref,
|
|
163
|
+
...rest,
|
|
164
|
+
orientation: 'vertical',
|
|
165
|
+
className: cx('iui-transfer-list-toolbar', className),
|
|
166
|
+
},
|
|
167
|
+
children,
|
|
168
|
+
);
|
|
157
169
|
});
|
|
158
170
|
TransferListToolbar.displayName = 'TransferList.Toolbar';
|
|
159
171
|
export const TransferList = Object.assign(TransferListComponent, {
|
package/DEV-esm/styles.js
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { OverflowContainer } from './OverflowContainer.js';
|
|
3
3
|
let ELLIPSIS_CHAR = '…';
|
|
4
4
|
export const MiddleTextTruncation = (props) => {
|
|
5
|
-
let { text,
|
|
6
|
-
let [ref, visibleCount] = useOverflow(text);
|
|
7
|
-
let truncatedText = React.useMemo(() => {
|
|
8
|
-
if (visibleCount < text.length)
|
|
9
|
-
return `${text.substring(
|
|
10
|
-
0,
|
|
11
|
-
visibleCount - endCharsCount - ELLIPSIS_CHAR.length,
|
|
12
|
-
)}${ELLIPSIS_CHAR}${text.substring(text.length - endCharsCount)}`;
|
|
13
|
-
return text;
|
|
14
|
-
}, [endCharsCount, text, visibleCount]);
|
|
5
|
+
let { text, style, ...rest } = props;
|
|
15
6
|
return React.createElement(
|
|
16
|
-
|
|
7
|
+
OverflowContainer,
|
|
17
8
|
{
|
|
9
|
+
as: 'span',
|
|
18
10
|
style: {
|
|
19
11
|
display: 'flex',
|
|
20
12
|
minWidth: 0,
|
|
@@ -22,10 +14,23 @@ export const MiddleTextTruncation = (props) => {
|
|
|
22
14
|
whiteSpace: 'nowrap',
|
|
23
15
|
...style,
|
|
24
16
|
},
|
|
25
|
-
|
|
17
|
+
itemsCount: text.length,
|
|
26
18
|
...rest,
|
|
27
19
|
},
|
|
28
|
-
|
|
20
|
+
React.createElement(MiddleTextTruncationContent, props),
|
|
29
21
|
);
|
|
30
22
|
};
|
|
31
23
|
MiddleTextTruncation.displayName = 'MiddleTextTruncation';
|
|
24
|
+
let MiddleTextTruncationContent = (props) => {
|
|
25
|
+
let { text, endCharsCount = 6, textRenderer } = props;
|
|
26
|
+
let { visibleCount } = OverflowContainer.useContext();
|
|
27
|
+
let truncatedText = React.useMemo(() => {
|
|
28
|
+
if (visibleCount < text.length)
|
|
29
|
+
return `${text.substring(
|
|
30
|
+
0,
|
|
31
|
+
visibleCount - endCharsCount - ELLIPSIS_CHAR.length,
|
|
32
|
+
)}${ELLIPSIS_CHAR}${text.substring(text.length - endCharsCount)}`;
|
|
33
|
+
return text;
|
|
34
|
+
}, [endCharsCount, text, visibleCount]);
|
|
35
|
+
return textRenderer?.(truncatedText, text) ?? truncatedText;
|
|
36
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useMergedRefs } from '../hooks/useMergedRefs.js';
|
|
3
|
+
import { Box } from './Box.js';
|
|
4
|
+
import { useOverflow } from '../hooks/useOverflow.js';
|
|
5
|
+
import { useSafeContext } from '../hooks/useSafeContext.js';
|
|
6
|
+
let OverflowContainerComponent = React.forwardRef((props, ref) => {
|
|
7
|
+
let { itemsCount, children, overflowOrientation, ...rest } = props;
|
|
8
|
+
let [containerRef, visibleCount] = useOverflow(
|
|
9
|
+
itemsCount,
|
|
10
|
+
false,
|
|
11
|
+
overflowOrientation,
|
|
12
|
+
);
|
|
13
|
+
let overflowContainerContextValue = React.useMemo(
|
|
14
|
+
() => ({
|
|
15
|
+
visibleCount,
|
|
16
|
+
itemsCount,
|
|
17
|
+
}),
|
|
18
|
+
[itemsCount, visibleCount],
|
|
19
|
+
);
|
|
20
|
+
return React.createElement(
|
|
21
|
+
OverflowContainerContext.Provider,
|
|
22
|
+
{
|
|
23
|
+
value: overflowContainerContextValue,
|
|
24
|
+
},
|
|
25
|
+
React.createElement(
|
|
26
|
+
Box,
|
|
27
|
+
{
|
|
28
|
+
ref: useMergedRefs(ref, containerRef),
|
|
29
|
+
...rest,
|
|
30
|
+
},
|
|
31
|
+
children,
|
|
32
|
+
),
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
let OverflowContainerOverflowNode = (props) => {
|
|
36
|
+
let { children } = props;
|
|
37
|
+
let { visibleCount, itemsCount } = useOverflowContainerContext();
|
|
38
|
+
let isOverflowing = visibleCount < itemsCount;
|
|
39
|
+
return isOverflowing ? children : null;
|
|
40
|
+
};
|
|
41
|
+
export const OverflowContainer = Object.assign(OverflowContainerComponent, {
|
|
42
|
+
OverflowNode: OverflowContainerOverflowNode,
|
|
43
|
+
useContext: useOverflowContainerContext,
|
|
44
|
+
});
|
|
45
|
+
let OverflowContainerContext = React.createContext(void 0);
|
|
46
|
+
OverflowContainerContext.displayName = 'OverflowContainerContext';
|
|
47
|
+
function useOverflowContainerContext() {
|
|
48
|
+
let overflowContainerContext = useSafeContext(OverflowContainerContext);
|
|
49
|
+
return overflowContainerContext;
|
|
50
|
+
}
|
|
@@ -4,13 +4,13 @@ import { useResizeObserver } from './useResizeObserver.js';
|
|
|
4
4
|
import { useLayoutEffect } from './useIsomorphicLayoutEffect.js';
|
|
5
5
|
let STARTING_MAX_ITEMS_COUNT = 20;
|
|
6
6
|
export const useOverflow = (
|
|
7
|
-
|
|
7
|
+
itemsCount,
|
|
8
8
|
disabled = false,
|
|
9
9
|
orientation = 'horizontal',
|
|
10
10
|
) => {
|
|
11
11
|
let containerRef = React.useRef(null);
|
|
12
12
|
let [visibleCount, setVisibleCount] = React.useState(() =>
|
|
13
|
-
disabled ?
|
|
13
|
+
disabled ? itemsCount : Math.min(itemsCount, STARTING_MAX_ITEMS_COUNT),
|
|
14
14
|
);
|
|
15
15
|
let needsFullRerender = React.useRef(true);
|
|
16
16
|
let [containerSize, setContainerSize] = React.useState(0);
|
|
@@ -23,12 +23,12 @@ export const useOverflow = (
|
|
|
23
23
|
let [resizeRef, observer] = useResizeObserver(updateContainerSize);
|
|
24
24
|
let resizeObserverRef = React.useRef(observer);
|
|
25
25
|
useLayoutEffect(() => {
|
|
26
|
-
if (disabled) setVisibleCount(
|
|
26
|
+
if (disabled) setVisibleCount(itemsCount);
|
|
27
27
|
else {
|
|
28
|
-
setVisibleCount(Math.min(
|
|
28
|
+
setVisibleCount(Math.min(itemsCount, STARTING_MAX_ITEMS_COUNT));
|
|
29
29
|
needsFullRerender.current = true;
|
|
30
30
|
}
|
|
31
|
-
}, [containerSize, disabled,
|
|
31
|
+
}, [containerSize, disabled, itemsCount]);
|
|
32
32
|
let mergedRefs = useMergedRefs(containerRef, resizeRef);
|
|
33
33
|
useLayoutEffect(() => {
|
|
34
34
|
if (!containerRef.current || disabled) {
|
|
@@ -48,14 +48,14 @@ export const useOverflow = (
|
|
|
48
48
|
0,
|
|
49
49
|
);
|
|
50
50
|
let currentVisibleCount =
|
|
51
|
-
visibleCount || Math.min(
|
|
51
|
+
visibleCount || Math.min(itemsCount, STARTING_MAX_ITEMS_COUNT);
|
|
52
52
|
let avgItemSize = childrenSize / currentVisibleCount;
|
|
53
53
|
let visibleItems = Math.floor(availableSize / avgItemSize);
|
|
54
54
|
if (!isNaN(visibleItems))
|
|
55
|
-
setVisibleCount(Math.min(
|
|
55
|
+
setVisibleCount(Math.min(itemsCount, 2 * visibleItems));
|
|
56
56
|
}
|
|
57
57
|
needsFullRerender.current = false;
|
|
58
|
-
}, [containerSize, visibleCount, disabled,
|
|
58
|
+
}, [containerSize, visibleCount, disabled, itemsCount, orientation]);
|
|
59
59
|
useLayoutEffect(() => {
|
|
60
60
|
previousContainerSize.current = containerSize;
|
|
61
61
|
}, [containerSize]);
|