@itwin/itwinui-react 3.15.3 → 3.15.5

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.
Files changed (81) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/DEV-cjs/core/Breadcrumbs/Breadcrumbs.js +85 -65
  3. package/DEV-cjs/core/ButtonGroup/ButtonGroup.js +32 -27
  4. package/DEV-cjs/core/ComboBox/ComboBox.js +9 -6
  5. package/DEV-cjs/core/DatePicker/DatePicker.js +14 -4
  6. package/DEV-cjs/core/Popover/Popover.js +44 -16
  7. package/DEV-cjs/core/Select/SelectTagContainer.js +27 -13
  8. package/DEV-cjs/core/Table/ColumnHeader.js +21 -28
  9. package/DEV-cjs/core/Table/Table.js +78 -53
  10. package/DEV-cjs/core/Table/TablePaginator.js +111 -88
  11. package/DEV-cjs/core/Table/cells/DefaultCell.js +3 -3
  12. package/DEV-cjs/core/Table/utils.js +3 -3
  13. package/DEV-cjs/styles.js +1 -1
  14. package/DEV-cjs/utils/components/MiddleTextTruncation.js +19 -14
  15. package/DEV-cjs/utils/components/OverflowContainer.js +63 -0
  16. package/DEV-cjs/utils/components/index.js +1 -0
  17. package/DEV-cjs/utils/hooks/useOverflow.js +12 -8
  18. package/DEV-esm/core/Breadcrumbs/Breadcrumbs.js +86 -67
  19. package/DEV-esm/core/ButtonGroup/ButtonGroup.js +33 -28
  20. package/DEV-esm/core/ComboBox/ComboBox.js +9 -6
  21. package/DEV-esm/core/DatePicker/DatePicker.js +12 -4
  22. package/DEV-esm/core/Popover/Popover.js +45 -17
  23. package/DEV-esm/core/Select/SelectTagContainer.js +24 -13
  24. package/DEV-esm/core/Table/ColumnHeader.js +28 -29
  25. package/DEV-esm/core/Table/Table.js +79 -54
  26. package/DEV-esm/core/Table/TablePaginator.js +112 -89
  27. package/DEV-esm/core/Table/cells/DefaultCell.js +4 -4
  28. package/DEV-esm/core/Table/utils.js +1 -1
  29. package/DEV-esm/styles.js +1 -1
  30. package/DEV-esm/utils/components/MiddleTextTruncation.js +19 -14
  31. package/DEV-esm/utils/components/OverflowContainer.js +50 -0
  32. package/DEV-esm/utils/components/index.js +1 -0
  33. package/DEV-esm/utils/hooks/useOverflow.js +8 -8
  34. package/cjs/core/Breadcrumbs/Breadcrumbs.js +84 -64
  35. package/cjs/core/ButtonGroup/ButtonGroup.js +32 -27
  36. package/cjs/core/ComboBox/ComboBox.js +9 -6
  37. package/cjs/core/DatePicker/DatePicker.js +14 -4
  38. package/cjs/core/NonIdealState/NonIdealState.d.ts +15 -11
  39. package/cjs/core/Popover/Popover.d.ts +10 -0
  40. package/cjs/core/Popover/Popover.js +44 -16
  41. package/cjs/core/Select/SelectTagContainer.js +27 -13
  42. package/cjs/core/Table/ColumnHeader.d.ts +8 -12
  43. package/cjs/core/Table/ColumnHeader.js +21 -28
  44. package/cjs/core/Table/Table.js +74 -53
  45. package/cjs/core/Table/TablePaginator.js +111 -88
  46. package/cjs/core/Table/cells/DefaultCell.js +3 -3
  47. package/cjs/core/Table/utils.d.ts +2 -2
  48. package/cjs/core/Table/utils.js +3 -3
  49. package/cjs/styles.js +1 -1
  50. package/cjs/utils/components/MiddleTextTruncation.js +19 -14
  51. package/cjs/utils/components/OverflowContainer.d.ts +37 -0
  52. package/cjs/utils/components/OverflowContainer.js +62 -0
  53. package/cjs/utils/components/index.d.ts +1 -0
  54. package/cjs/utils/components/index.js +1 -0
  55. package/cjs/utils/hooks/useOverflow.d.ts +2 -3
  56. package/cjs/utils/hooks/useOverflow.js +12 -8
  57. package/esm/core/Breadcrumbs/Breadcrumbs.js +85 -66
  58. package/esm/core/ButtonGroup/ButtonGroup.js +33 -28
  59. package/esm/core/ComboBox/ComboBox.js +9 -6
  60. package/esm/core/DatePicker/DatePicker.js +12 -4
  61. package/esm/core/NonIdealState/NonIdealState.d.ts +15 -11
  62. package/esm/core/Popover/Popover.d.ts +10 -0
  63. package/esm/core/Popover/Popover.js +45 -17
  64. package/esm/core/Select/SelectTagContainer.js +24 -13
  65. package/esm/core/Table/ColumnHeader.d.ts +8 -12
  66. package/esm/core/Table/ColumnHeader.js +28 -29
  67. package/esm/core/Table/Table.js +75 -54
  68. package/esm/core/Table/TablePaginator.js +112 -89
  69. package/esm/core/Table/cells/DefaultCell.js +4 -4
  70. package/esm/core/Table/utils.d.ts +2 -2
  71. package/esm/core/Table/utils.js +1 -1
  72. package/esm/styles.js +1 -1
  73. package/esm/utils/components/MiddleTextTruncation.js +19 -14
  74. package/esm/utils/components/OverflowContainer.d.ts +37 -0
  75. package/esm/utils/components/OverflowContainer.js +49 -0
  76. package/esm/utils/components/index.d.ts +1 -0
  77. package/esm/utils/components/index.js +1 -0
  78. package/esm/utils/hooks/useOverflow.d.ts +2 -3
  79. package/esm/utils/hooks/useOverflow.js +8 -8
  80. package/package.json +1 -1
  81. package/styles.css +8 -8
@@ -24,7 +24,7 @@ import {
24
24
  useLatestRef,
25
25
  useVirtualScroll,
26
26
  } from '../../utils/index.js';
27
- import { TableColumnsContext } from './utils.js';
27
+ import { TableInstanceContext } from './utils.js';
28
28
  import { TableRowMemoized } from './TableRowMemoized.js';
29
29
  import { customFilterFunctions } from './filters/customFilterFunctions.js';
30
30
  import {
@@ -53,6 +53,7 @@ let singleRowSelectedAction = 'singleRowSelected';
53
53
  let shiftRowSelectedAction = 'shiftRowSelected';
54
54
  export const tableResizeStartAction = 'tableResizeStart';
55
55
  let tableResizeEndAction = 'tableResizeEnd';
56
+ let 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 (!rowHasParent.has(originalRow)) {
247
- rowHasParent.add(originalRow);
248
- return [originalRow];
249
- }
250
- return originalRow.subRows || [];
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
+ ];
255
+ },
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;
251
267
  },
252
- [rowHasParent],
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),
@@ -299,7 +316,6 @@ export const Table = (props) => {
299
316
  gotoPage,
300
317
  setPageSize,
301
318
  flatHeaders,
302
- visibleColumns,
303
319
  setGlobalFilter,
304
320
  } = instance;
305
321
  let headerGroups = _headerGroups;
@@ -310,6 +326,10 @@ export const Table = (props) => {
310
326
  "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
327
  );
312
328
  }
329
+ if (subComponent && data.some((item) => !!item.subRows?.length))
330
+ logWarning(
331
+ '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.',
332
+ );
313
333
  let ariaDataAttributes = Object.entries(rest).reduce(
314
334
  (result, [key, value]) => {
315
335
  if (key.startsWith('data-') || key.startsWith('aria-'))
@@ -466,51 +486,52 @@ export const Table = (props) => {
466
486
  (index, virtualItem, virtualizer) => {
467
487
  let row = page[index];
468
488
  prepareRow(row);
469
- if (row.subRows.length > 0 || !subComponent)
470
- return React.createElement(TableRowMemoized, {
471
- row: row,
472
- rowProps: rowProps,
473
- isLast: index === page.length - 1,
474
- onRowInViewport: onRowInViewportRef,
475
- onBottomReached: onBottomReachedRef,
476
- intersectionMargin: intersectionMargin,
477
- state: state,
478
- key: row.getRowProps().key,
479
- onClick: onRowClickHandler,
480
- subComponent: subComponent,
481
- isDisabled: !!isRowDisabled?.(row.original),
482
- tableHasSubRows: hasAnySubRows,
483
- tableInstance: instance,
484
- expanderCell: expanderCell,
485
- scrollContainerRef: tableRef.current,
486
- tableRowRef: enableVirtualization ? void 0 : tableRowRef(row),
487
- density: density,
488
- virtualItem: virtualItem,
489
- virtualizer: virtualizer,
490
- });
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
- );
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
+ });
503
524
  },
504
525
  [
505
526
  page,
506
527
  prepareRow,
528
+ subComponent,
507
529
  rowProps,
508
530
  onRowInViewportRef,
509
531
  onBottomReachedRef,
510
532
  intersectionMargin,
511
533
  state,
512
534
  onRowClickHandler,
513
- subComponent,
514
535
  isRowDisabled,
515
536
  hasAnySubRows,
516
537
  instance,
@@ -547,9 +568,9 @@ export const Table = (props) => {
547
568
  updateStickyState();
548
569
  }, []);
549
570
  return React.createElement(
550
- TableColumnsContext.Provider,
571
+ TableInstanceContext.Provider,
551
572
  {
552
- value: instance.columns,
573
+ value: instance,
553
574
  },
554
575
  React.createElement(
555
576
  Box,
@@ -608,19 +629,23 @@ export const Table = (props) => {
608
629
  return React.createElement(ColumnHeader, {
609
630
  ...dragAndDropProps,
610
631
  key: dragAndDropProps.key || column.id || index,
611
- columnRefs: columnRefs,
612
632
  column: column,
613
- index: index,
614
633
  areFiltersSet: areFiltersSet,
615
- hasAnySubRows: hasAnySubRows,
616
- headers: headerGroup.headers,
617
- state: state,
618
- data: data,
634
+ columnHasExpanders:
635
+ hasAnySubRows &&
636
+ index ===
637
+ headerGroup.headers.findIndex(
638
+ (c) => c.id !== SELECTION_CELL_ID,
639
+ ),
640
+ isLast: index === headerGroup.headers.length - 1,
641
+ isTableEmpty: 0 === data.length,
619
642
  isResizable: isResizable,
620
643
  columnResizeMode: columnResizeMode,
621
644
  enableColumnReordering: enableColumnReordering,
622
645
  density: density,
623
- visibleColumns: visibleColumns,
646
+ ref: (el) => {
647
+ if (el) columnRefs.current[column.id] = el;
648
+ },
624
649
  });
625
650
  }),
626
651
  ),
@@ -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.useEffect(() => {
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
- '.iui-table-paginator-page-button',
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 halfVisibleCount = Math.floor(visibleCount / 2);
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 ellipsis = React.createElement(
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
- Box,
152
+ OverflowContainer,
200
153
  {
201
154
  className: 'iui-center',
202
- ref: overflowRef,
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
- if (hasNoRows) return noRowsContent;
225
- if (1 === visibleCount) return pageButton(focusedIndex);
226
- return React.createElement(
227
- React.Fragment,
228
- null,
229
- 0 !== startPage &&
230
- React.createElement(
231
- React.Fragment,
232
- null,
233
- pageButton(0, 0),
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 { TableColumnsContext } from '../utils.js';
5
+ import { TableInstanceContext } from '../utils.js';
6
6
  export const DefaultCell = (props) => {
7
- let instanceColumns = React.useContext(TableColumnsContext);
7
+ let instance = React.useContext(TableInstanceContext);
8
8
  let isCustomCell = React.useMemo(
9
9
  () =>
10
- instanceColumns.find(({ id }) => props.cellProps.column.id === id)
10
+ instance?.columns.find(({ id }) => props.cellProps.column.id === id)
11
11
  ?.Cell !== defaultColumn.Cell,
12
- [instanceColumns, props.cellProps.column.id],
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 TableColumnsContext = React.createContext([]);
50
+ export const TableInstanceContext = React.createContext(void 0);
package/DEV-esm/styles.js CHANGED
@@ -1,4 +1,4 @@
1
- const t = '3.15.3';
1
+ const t = '3.15.5';
2
2
  const u = new Proxy(
3
3
  {},
4
4
  {
@@ -1,20 +1,12 @@
1
1
  import * as React from 'react';
2
- import { useOverflow } from '../hooks/useOverflow.js';
2
+ import { OverflowContainer } from './OverflowContainer.js';
3
3
  let ELLIPSIS_CHAR = '…';
4
4
  export const MiddleTextTruncation = (props) => {
5
- let { text, endCharsCount = 6, textRenderer, style, ...rest } = props;
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
- 'span',
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
- ref: ref,
17
+ itemsCount: text.length,
26
18
  ...rest,
27
19
  },
28
- textRenderer?.(truncatedText, text) ?? truncatedText,
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
+ }
@@ -12,3 +12,4 @@ export * from './Portal.js';
12
12
  export * from './ShadowRoot.js';
13
13
  export * from './LineClamp.js';
14
14
  export * from './FieldsetBase.js';
15
+ export * from './OverflowContainer.js';
@@ -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
- items,
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 ? items.length : Math.min(items.length, STARTING_MAX_ITEMS_COUNT),
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(items.length);
26
+ if (disabled) setVisibleCount(itemsCount);
27
27
  else {
28
- setVisibleCount(Math.min(items.length, STARTING_MAX_ITEMS_COUNT));
28
+ setVisibleCount(Math.min(itemsCount, STARTING_MAX_ITEMS_COUNT));
29
29
  needsFullRerender.current = true;
30
30
  }
31
- }, [containerSize, disabled, items]);
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(items.length, STARTING_MAX_ITEMS_COUNT);
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(items.length, 2 * visibleItems));
55
+ setVisibleCount(Math.min(itemsCount, 2 * visibleItems));
56
56
  }
57
57
  needsFullRerender.current = false;
58
- }, [containerSize, visibleCount, disabled, items.length, orientation]);
58
+ }, [containerSize, visibleCount, disabled, itemsCount, orientation]);
59
59
  useLayoutEffect(() => {
60
60
  previousContainerSize.current = containerSize;
61
61
  }, [containerSize]);