@itwin/itwinui-react 1.38.0 → 1.40.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.
Files changed (106) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/cjs/core/Carousel/Carousel.js +21 -12
  3. package/cjs/core/Carousel/CarouselContext.d.ts +4 -2
  4. package/cjs/core/Carousel/CarouselDotsList.js +1 -0
  5. package/cjs/core/Carousel/CarouselNavigation.js +8 -10
  6. package/cjs/core/Carousel/CarouselSlide.js +3 -7
  7. package/cjs/core/Carousel/CarouselSlider.js +23 -28
  8. package/cjs/core/ColorPicker/ColorPickerContext.d.ts +2 -2
  9. package/cjs/core/ComboBox/ComboBox.d.ts +17 -1
  10. package/cjs/core/ComboBox/ComboBox.js +50 -24
  11. package/cjs/core/ComboBox/ComboBoxDropdown.d.ts +5 -6
  12. package/cjs/core/ComboBox/ComboBoxInput.js +28 -9
  13. package/cjs/core/ComboBox/ComboBoxMenu.js +46 -2
  14. package/cjs/core/ComboBox/ComboBoxMenuItem.js +2 -3
  15. package/cjs/core/ComboBox/helpers.d.ts +8 -3
  16. package/cjs/core/ComboBox/helpers.js +1 -1
  17. package/cjs/core/DatePicker/DatePicker.d.ts +1 -1
  18. package/cjs/core/Menu/MenuItemSkeleton.d.ts +32 -0
  19. package/cjs/core/Menu/MenuItemSkeleton.js +53 -0
  20. package/cjs/core/Menu/index.d.ts +2 -0
  21. package/cjs/core/Menu/index.js +3 -1
  22. package/cjs/core/Select/Select.js +1 -1
  23. package/cjs/core/Table/Table.js +68 -25
  24. package/cjs/core/Table/TableCell.js +10 -3
  25. package/cjs/core/Table/TablePaginator.js +1 -1
  26. package/cjs/core/Table/TableRowMemoized.js +5 -1
  27. package/cjs/core/Table/actionHandlers/resizeHandler.d.ts +8 -0
  28. package/cjs/core/Table/actionHandlers/selectHandler.d.ts +4 -0
  29. package/cjs/core/Table/columns/selectionColumn.js +4 -2
  30. package/cjs/core/Table/filters/tableFilters.d.ts +3 -3
  31. package/cjs/core/Table/hooks/index.d.ts +1 -0
  32. package/cjs/core/Table/hooks/index.js +3 -1
  33. package/cjs/core/Table/hooks/useExpanderCell.js +11 -1
  34. package/cjs/core/Table/hooks/useStickyColumns.d.ts +2 -0
  35. package/cjs/core/Table/hooks/useStickyColumns.js +84 -0
  36. package/cjs/core/Table/utils.d.ts +1 -0
  37. package/cjs/core/Table/utils.js +36 -1
  38. package/cjs/core/Toast/Toaster.d.ts +1 -1
  39. package/cjs/core/Toast/Toaster.js +72 -29
  40. package/cjs/core/index.d.ts +2 -2
  41. package/cjs/core/index.js +4 -3
  42. package/cjs/core/utils/components/Popover.d.ts +1 -18
  43. package/cjs/core/utils/components/VirtualScroll.d.ts +35 -1
  44. package/cjs/core/utils/components/VirtualScroll.js +159 -26
  45. package/cjs/core/utils/components/VisuallyHidden.d.ts +9 -0
  46. package/cjs/core/utils/components/VisuallyHidden.js +44 -0
  47. package/cjs/core/utils/components/WithCSSTransition.d.ts +1 -2
  48. package/cjs/core/utils/components/icons.d.ts +4 -4
  49. package/cjs/core/utils/components/index.d.ts +1 -0
  50. package/cjs/core/utils/components/index.js +1 -0
  51. package/cjs/core/utils/hooks/useOverflow.js +4 -2
  52. package/cjs/core/utils/hooks/useTheme.d.ts +1 -1
  53. package/cjs/types/react-table-config.d.ts +9 -0
  54. package/esm/core/Carousel/Carousel.js +21 -12
  55. package/esm/core/Carousel/CarouselContext.d.ts +4 -2
  56. package/esm/core/Carousel/CarouselDotsList.js +1 -0
  57. package/esm/core/Carousel/CarouselNavigation.js +8 -10
  58. package/esm/core/Carousel/CarouselSlide.js +3 -7
  59. package/esm/core/Carousel/CarouselSlider.js +24 -29
  60. package/esm/core/ColorPicker/ColorPickerContext.d.ts +2 -2
  61. package/esm/core/ComboBox/ComboBox.d.ts +17 -1
  62. package/esm/core/ComboBox/ComboBox.js +50 -24
  63. package/esm/core/ComboBox/ComboBoxDropdown.d.ts +5 -6
  64. package/esm/core/ComboBox/ComboBoxInput.js +28 -9
  65. package/esm/core/ComboBox/ComboBoxMenu.js +47 -3
  66. package/esm/core/ComboBox/ComboBoxMenuItem.js +2 -3
  67. package/esm/core/ComboBox/helpers.d.ts +8 -3
  68. package/esm/core/ComboBox/helpers.js +1 -1
  69. package/esm/core/DatePicker/DatePicker.d.ts +1 -1
  70. package/esm/core/Menu/MenuItemSkeleton.d.ts +32 -0
  71. package/esm/core/Menu/MenuItemSkeleton.js +46 -0
  72. package/esm/core/Menu/index.d.ts +2 -0
  73. package/esm/core/Menu/index.js +1 -0
  74. package/esm/core/Select/Select.js +1 -1
  75. package/esm/core/Table/Table.js +70 -27
  76. package/esm/core/Table/TableCell.js +11 -4
  77. package/esm/core/Table/TablePaginator.js +1 -1
  78. package/esm/core/Table/TableRowMemoized.js +5 -1
  79. package/esm/core/Table/actionHandlers/resizeHandler.d.ts +8 -0
  80. package/esm/core/Table/actionHandlers/selectHandler.d.ts +4 -0
  81. package/esm/core/Table/columns/selectionColumn.js +4 -2
  82. package/esm/core/Table/filters/tableFilters.d.ts +3 -3
  83. package/esm/core/Table/hooks/index.d.ts +1 -0
  84. package/esm/core/Table/hooks/index.js +1 -0
  85. package/esm/core/Table/hooks/useExpanderCell.js +8 -1
  86. package/esm/core/Table/hooks/useStickyColumns.d.ts +2 -0
  87. package/esm/core/Table/hooks/useStickyColumns.js +80 -0
  88. package/esm/core/Table/utils.d.ts +1 -0
  89. package/esm/core/Table/utils.js +34 -0
  90. package/esm/core/Toast/Toaster.d.ts +1 -1
  91. package/esm/core/Toast/Toaster.js +50 -30
  92. package/esm/core/index.d.ts +2 -2
  93. package/esm/core/index.js +1 -1
  94. package/esm/core/utils/components/Popover.d.ts +1 -18
  95. package/esm/core/utils/components/VirtualScroll.d.ts +35 -1
  96. package/esm/core/utils/components/VirtualScroll.js +157 -25
  97. package/esm/core/utils/components/VisuallyHidden.d.ts +9 -0
  98. package/esm/core/utils/components/VisuallyHidden.js +38 -0
  99. package/esm/core/utils/components/WithCSSTransition.d.ts +1 -2
  100. package/esm/core/utils/components/icons.d.ts +4 -4
  101. package/esm/core/utils/components/index.d.ts +1 -0
  102. package/esm/core/utils/components/index.js +1 -0
  103. package/esm/core/utils/hooks/useOverflow.js +4 -2
  104. package/esm/core/utils/hooks/useTheme.d.ts +1 -1
  105. package/esm/types/react-table-config.d.ts +9 -0
  106. package/package.json +24 -39
@@ -32,11 +32,11 @@ import { useTheme, useResizeObserver } from '../utils';
32
32
  import '@itwin/itwinui-css/css/table.css';
33
33
  import SvgSortDown from '@itwin/itwinui-icons-react/cjs/icons/SortDown';
34
34
  import SvgSortUp from '@itwin/itwinui-icons-react/cjs/icons/SortUp';
35
- import { getCellStyle } from './utils';
35
+ import { getCellStyle, getStickyStyle } from './utils';
36
36
  import { TableRowMemoized } from './TableRowMemoized';
37
37
  import { FilterToggle } from './filters';
38
38
  import { customFilterFunctions } from './filters/customFilterFunctions';
39
- import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, useColumnDragAndDrop, } from './hooks';
39
+ import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, useColumnDragAndDrop, useStickyColumns, } from './hooks';
40
40
  import { onExpandHandler, onFilterHandler, onSelectHandler, onSingleSelectHandler, onTableResizeEnd, onTableResizeStart, } from './actionHandlers';
41
41
  import VirtualScroll from '../utils/components/VirtualScroll';
42
42
  import { SELECTION_CELL_ID } from './columns';
@@ -171,8 +171,8 @@ export var Table = function (props) {
171
171
  return getSubRows ? getSubRows(item, index) : item.subRows;
172
172
  });
173
173
  }, [data, getSubRows]);
174
- var instance = useTable(__assign(__assign({ manualPagination: !paginatorRenderer, paginateExpandedRows: false }, props), { columns: columns, defaultColumn: defaultColumn, disableSortBy: !isSortable, stateReducer: tableStateReducer, filterTypes: filterTypes, selectSubRows: selectSubRows, data: data, getSubRows: getSubRows, initialState: __assign({ pageSize: pageSize }, props.initialState) }), useFlexLayout, useResizeColumns(ownerDocument), useFilters, useSubRowFiltering(hasAnySubRows), useSortBy, useExpanded, usePagination, useRowSelect, useSubRowSelection, useExpanderCell(subComponent, expanderCell, isRowDisabled), useSelectionCell(isSelectable, selectionMode, isRowDisabled), useColumnOrder, useColumnDragAndDrop(enableColumnReordering));
175
- var getTableProps = instance.getTableProps, rows = instance.rows, headerGroups = instance.headerGroups, getTableBodyProps = instance.getTableBodyProps, prepareRow = instance.prepareRow, state = instance.state, allColumns = instance.allColumns, filteredFlatRows = instance.filteredFlatRows, dispatch = instance.dispatch, page = instance.page, gotoPage = instance.gotoPage, setPageSize = instance.setPageSize, flatHeaders = instance.flatHeaders;
174
+ var instance = useTable(__assign(__assign({ manualPagination: !paginatorRenderer, paginateExpandedRows: false }, props), { columns: columns, defaultColumn: defaultColumn, disableSortBy: !isSortable, stateReducer: tableStateReducer, filterTypes: filterTypes, selectSubRows: selectSubRows, data: data, getSubRows: getSubRows, initialState: __assign({ pageSize: pageSize }, props.initialState) }), useFlexLayout, useResizeColumns(ownerDocument), useFilters, useSubRowFiltering(hasAnySubRows), useSortBy, useExpanded, usePagination, useRowSelect, useSubRowSelection, useExpanderCell(subComponent, expanderCell, isRowDisabled), useSelectionCell(isSelectable, selectionMode, isRowDisabled), useColumnOrder, useColumnDragAndDrop(enableColumnReordering), useStickyColumns);
175
+ var getTableProps = instance.getTableProps, rows = instance.rows, headerGroups = instance.headerGroups, getTableBodyProps = instance.getTableBodyProps, prepareRow = instance.prepareRow, state = instance.state, allColumns = instance.allColumns, filteredFlatRows = instance.filteredFlatRows, dispatch = instance.dispatch, page = instance.page, gotoPage = instance.gotoPage, setPageSize = instance.setPageSize, flatHeaders = instance.flatHeaders, visibleColumns = instance.visibleColumns;
176
176
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
177
177
  var key = _a[0], value = _a[1];
178
178
  if (key.startsWith('data-') || key.startsWith('aria-')) {
@@ -181,6 +181,12 @@ export var Table = function (props) {
181
181
  return result;
182
182
  }, {});
183
183
  var areFiltersSet = allColumns.some(function (column) { return column.filterValue != null && column.filterValue !== ''; });
184
+ var showFilterButton = function (column) {
185
+ return (data.length !== 0 || areFiltersSet) && column.canFilter;
186
+ };
187
+ var showSortButton = function (column) {
188
+ return data.length !== 0 && column.canSort;
189
+ };
184
190
  var onRowClickHandler = React.useCallback(function (event, row) {
185
191
  var isDisabled = isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original);
186
192
  if (!isDisabled) {
@@ -281,6 +287,30 @@ export var Table = function (props) {
281
287
  subComponent,
282
288
  ]);
283
289
  var virtualizedItemRenderer = React.useCallback(function (index) { return getPreparedRow(index); }, [getPreparedRow]);
290
+ var updateStickyState = function () {
291
+ if (!bodyRef.current || flatHeaders.every(function (header) { return !header.sticky; })) {
292
+ return;
293
+ }
294
+ if (bodyRef.current.scrollLeft !== 0) {
295
+ dispatch({ type: TableActions.setScrolledRight, value: true });
296
+ }
297
+ else {
298
+ dispatch({ type: TableActions.setScrolledRight, value: false });
299
+ }
300
+ // If scrolled a bit to the left looking from the right side
301
+ if (bodyRef.current.scrollLeft !==
302
+ bodyRef.current.scrollWidth - bodyRef.current.clientWidth) {
303
+ dispatch({ type: TableActions.setScrolledLeft, value: true });
304
+ }
305
+ else {
306
+ dispatch({ type: TableActions.setScrolledLeft, value: false });
307
+ }
308
+ };
309
+ React.useEffect(function () {
310
+ updateStickyState();
311
+ // Call only on init
312
+ // eslint-disable-next-line react-hooks/exhaustive-deps
313
+ }, []);
284
314
  return (React.createElement(React.Fragment, null,
285
315
  React.createElement("div", __assign({ ref: function (element) {
286
316
  setOwnerDocument(element === null || element === void 0 ? void 0 : element.ownerDocument);
@@ -289,30 +319,42 @@ export var Table = function (props) {
289
319
  }
290
320
  }, id: id }, getTableProps({
291
321
  className: cx('iui-table', (_a = {}, _a["iui-".concat(density)] = density !== 'default', _a), className),
292
- style: style,
322
+ style: __assign({ minWidth: 0 }, style),
293
323
  }), ariaDataAttributes),
294
- React.createElement("div", { className: 'iui-table-header', ref: headerRef }, headerGroups.slice(1).map(function (headerGroup) {
295
- var headerGroupProps = headerGroup.getHeaderGroupProps({
296
- className: 'iui-row',
297
- });
298
- return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
299
- var columnProps = column.getHeaderProps(__assign(__assign({}, column.getSortByToggleProps()), { className: cx('iui-cell', { 'iui-actionable': column.canSort }, { 'iui-sorted': column.isSorted }, column.columnClassName), style: __assign(__assign({}, getCellStyle(column, !!state.isTableResizing)), { flexWrap: 'unset' }) }));
300
- return (React.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
301
- if (el && isResizable) {
302
- columnRefs.current[column.id] = el;
303
- column.resizeWidth = el.getBoundingClientRect().width;
304
- }
305
- } }),
306
- column.render('Header'),
307
- (data.length !== 0 || areFiltersSet) && (React.createElement(FilterToggle, { column: column, ownerDocument: ownerDocument })),
308
- data.length !== 0 && column.canSort && (React.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (React.createElement(SvgSortDown, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (React.createElement(SvgSortUp, { className: 'iui-icon iui-sort', "aria-hidden": true })))),
309
- isResizable &&
310
- column.isResizerVisible &&
311
- index !== headerGroup.headers.length - 1 && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
312
- React.createElement("div", { className: 'iui-resizer-bar' }))),
313
- enableColumnReordering && !column.disableReordering && (React.createElement("div", { className: 'iui-reorder-bar' }))));
314
- })));
315
- })),
324
+ React.createElement("div", { className: 'iui-table-header-wrapper', ref: headerRef },
325
+ React.createElement("div", { className: 'iui-table-header' }, headerGroups.slice(1).map(function (headerGroup) {
326
+ var headerGroupProps = headerGroup.getHeaderGroupProps({
327
+ className: 'iui-row',
328
+ });
329
+ return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
330
+ var columnProps = column.getHeaderProps(__assign(__assign({}, column.getSortByToggleProps()), { className: cx('iui-cell', {
331
+ 'iui-actionable': column.canSort,
332
+ 'iui-sorted': column.isSorted,
333
+ 'iui-cell-sticky': !!column.sticky,
334
+ }, column.columnClassName), style: __assign(__assign(__assign({}, getCellStyle(column, !!state.isTableResizing)), getStickyStyle(column, visibleColumns)), { flexWrap: 'unset' }) }));
335
+ return (React.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
336
+ if (el) {
337
+ columnRefs.current[column.id] = el;
338
+ column.resizeWidth = el.getBoundingClientRect().width;
339
+ }
340
+ } }),
341
+ column.render('Header'),
342
+ (showFilterButton(column) ||
343
+ showSortButton(column)) && (React.createElement("div", { className: 'iui-table-header-actions-container' },
344
+ showFilterButton(column) && (React.createElement(FilterToggle, { column: column, ownerDocument: ownerDocument })),
345
+ showSortButton(column) && (React.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (React.createElement(SvgSortDown, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (React.createElement(SvgSortUp, { className: 'iui-icon iui-sort', "aria-hidden": true })))))),
346
+ isResizable &&
347
+ column.isResizerVisible &&
348
+ index !== headerGroup.headers.length - 1 && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
349
+ React.createElement("div", { className: 'iui-resizer-bar' }))),
350
+ enableColumnReordering &&
351
+ !column.disableReordering && (React.createElement("div", { className: 'iui-reorder-bar' })),
352
+ column.sticky === 'left' &&
353
+ state.sticky.isScrolledToRight && (React.createElement("div", { className: 'iui-cell-shadow-right' })),
354
+ column.sticky === 'right' &&
355
+ state.sticky.isScrolledToLeft && (React.createElement("div", { className: 'iui-cell-shadow-left' }))));
356
+ })));
357
+ }))),
316
358
  React.createElement("div", __assign({}, getTableBodyProps({
317
359
  className: cx('iui-table-body', {
318
360
  'iui-zebra-striping': styleType === 'zebra-rows',
@@ -321,6 +363,7 @@ export var Table = function (props) {
321
363
  }), { ref: bodyRef, onScroll: function () {
322
364
  if (headerRef.current && bodyRef.current) {
323
365
  headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
366
+ updateStickyState();
324
367
  }
325
368
  }, tabIndex: -1 }),
326
369
  data.length !== 0 && (React.createElement(React.Fragment, null, enableVirtualization ? (React.createElement(VirtualScroll, { itemsLength: page.length, itemRenderer: virtualizedItemRenderer })) : (page.map(function (_, index) { return getPreparedRow(index); })))),
@@ -15,7 +15,7 @@ var __assign = (this && this.__assign) || function () {
15
15
  *--------------------------------------------------------------------------------------------*/
16
16
  import React from 'react';
17
17
  import cx from 'classnames';
18
- import { getCellStyle } from './utils';
18
+ import { getCellStyle, getStickyStyle } from './utils';
19
19
  import { SubRowExpander } from './SubRowExpander';
20
20
  import { SELECTION_CELL_ID } from './columns';
21
21
  import { DefaultCell } from './cells';
@@ -34,8 +34,10 @@ export var TableCell = function (props) {
34
34
  };
35
35
  };
36
36
  var cellElementProps = cell.getCellProps({
37
- className: cx('iui-cell', cell.column.cellClassName),
38
- style: __assign(__assign({}, getCellStyle(cell.column, !!tableInstance.state.isTableResizing)), getSubRowStyle()),
37
+ className: cx('iui-cell', cell.column.cellClassName, {
38
+ 'iui-cell-sticky': !!cell.column.sticky,
39
+ }),
40
+ style: __assign(__assign(__assign({}, getCellStyle(cell.column, !!tableInstance.state.isTableResizing)), getSubRowStyle()), getStickyStyle(cell.column, tableInstance.visibleColumns)),
39
41
  });
40
42
  var cellProps = __assign(__assign({}, tableInstance), { cell: cell, row: cell.row, value: cell.value, column: cell.column });
41
43
  var cellContent = (React.createElement(React.Fragment, null,
@@ -44,7 +46,12 @@ export var TableCell = function (props) {
44
46
  var cellRendererProps = {
45
47
  cellElementProps: cellElementProps,
46
48
  cellProps: cellProps,
47
- children: cellContent,
49
+ children: (React.createElement(React.Fragment, null,
50
+ cellContent,
51
+ cell.column.sticky === 'left' &&
52
+ tableInstance.state.sticky.isScrolledToRight && (React.createElement("div", { className: 'iui-cell-shadow-right' })),
53
+ cell.column.sticky === 'right' &&
54
+ tableInstance.state.sticky.isScrolledToLeft && (React.createElement("div", { className: 'iui-cell-shadow-left' })))),
48
55
  };
49
56
  return (React.createElement(React.Fragment, null, cell.column.cellRenderer ? (cell.column.cellRenderer(__assign(__assign({}, cellRendererProps), { isDisabled: function () { return isDisabled; } }))) : (React.createElement(DefaultCell, __assign({}, cellRendererProps, { isDisabled: function () { return isDisabled; } })))));
50
57
  };
@@ -143,7 +143,7 @@ export var TablePaginator = function (props) {
143
143
  }
144
144
  var hasNoRows = totalPagesCount === 0;
145
145
  var showPagesList = totalPagesCount > 1 || isLoading;
146
- var showPageSizeList = pageSizeList && onPageSizeChange && !!totalRowsCount;
146
+ var showPageSizeList = pageSizeList && !!onPageSizeChange && !!totalRowsCount;
147
147
  var ellipsis = (React.createElement("span", { className: cx('iui-paginator-ellipsis', {
148
148
  'iui-paginator-ellipsis-small': size === 'small',
149
149
  }) }, "\u2026"));
@@ -92,5 +92,9 @@ export var TableRowMemoized = React.memo(TableRow, function (prevProp, nextProp)
92
92
  prevProp.tableHasSubRows === nextProp.tableHasSubRows &&
93
93
  prevProp.state.columnOrder === nextProp.state.columnOrder &&
94
94
  !nextProp.state.columnResizing.isResizingColumn &&
95
- prevProp.state.isTableResizing === nextProp.state.isTableResizing;
95
+ prevProp.state.isTableResizing === nextProp.state.isTableResizing &&
96
+ prevProp.state.sticky.isScrolledToLeft ===
97
+ nextProp.state.sticky.isScrolledToLeft &&
98
+ prevProp.state.sticky.isScrolledToRight ===
99
+ nextProp.state.sticky.isScrolledToRight;
96
100
  });
@@ -12,6 +12,10 @@ export declare const onTableResizeStart: <T extends Record<string, unknown>>(sta
12
12
  isResizingColumn?: string | undefined;
13
13
  };
14
14
  columnReorderStartIndex: number;
15
+ sticky: {
16
+ isScrolledToRight?: boolean | undefined;
17
+ isScrolledToLeft?: boolean | undefined;
18
+ };
15
19
  columnOrder: import("react-table").IdType<T>[];
16
20
  expanded: Record<import("react-table").IdType<T>, boolean>;
17
21
  filters: import("react-table").Filters<T>;
@@ -38,6 +42,10 @@ export declare const onTableResizeEnd: <T extends Record<string, unknown>>(state
38
42
  };
39
43
  hiddenColumns?: import("react-table").IdType<T>[] | undefined;
40
44
  columnReorderStartIndex: number;
45
+ sticky: {
46
+ isScrolledToRight?: boolean | undefined;
47
+ isScrolledToLeft?: boolean | undefined;
48
+ };
41
49
  columnOrder: import("react-table").IdType<T>[];
42
50
  expanded: Record<import("react-table").IdType<T>, boolean>;
43
51
  filters: import("react-table").Filters<T>;
@@ -20,6 +20,10 @@ export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(
20
20
  };
21
21
  isTableResizing?: boolean | undefined;
22
22
  columnReorderStartIndex: number;
23
+ sticky: {
24
+ isScrolledToRight?: boolean | undefined;
25
+ isScrolledToLeft?: boolean | undefined;
26
+ };
23
27
  columnOrder: import("react-table").IdType<T>[];
24
28
  expanded: Record<import("react-table").IdType<T>, boolean>;
25
29
  filters: import("react-table").Filters<T>;
@@ -49,11 +49,13 @@ export var SelectionColumn = function (props) {
49
49
  var getToggleAllRowsSelectedProps = _a.getToggleAllRowsSelectedProps, rows = _a.rows, initialRows = _a.initialRows, state = _a.state;
50
50
  var disabled = rows.every(function (row) { return isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(row.original); });
51
51
  var checked = initialRows.every(function (row) { return state.selectedRowIds[row.id] || (isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(row.original)); });
52
- return (React.createElement(Checkbox, __assign({}, getToggleAllRowsSelectedProps(), { style: {}, checked: checked && !disabled, indeterminate: !checked && Object.keys(state.selectedRowIds).length > 0, disabled: disabled })));
52
+ return (React.createElement(Checkbox, __assign({}, getToggleAllRowsSelectedProps(), { style: {}, title: '' // Removes default title that comes from react-table
53
+ , checked: checked && !disabled, indeterminate: !checked && Object.keys(state.selectedRowIds).length > 0, disabled: disabled })));
53
54
  },
54
55
  Cell: function (_a) {
55
56
  var row = _a.row;
56
- return (React.createElement(Checkbox, __assign({}, row.getToggleRowSelectedProps(), { style: {}, disabled: isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(row.original), onClick: function (e) { return e.stopPropagation(); } })));
57
+ return (React.createElement(Checkbox, __assign({}, row.getToggleRowSelectedProps(), { style: {}, title: '' // Removes default title that comes from react-table
58
+ , disabled: isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(row.original), onClick: function (e) { return e.stopPropagation(); } })));
57
59
  },
58
60
  cellRenderer: function (props) { return (React.createElement(DefaultCell, __assign({}, props, { isDisabled: function (rowData) { return !!(isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(rowData)); } }))); },
59
61
  };
@@ -28,7 +28,7 @@ export declare const tableFilters: {
28
28
  * Basic filter with a single input field.
29
29
  * @param translatedLabels Translated filter labels.
30
30
  */
31
- TextFilter: (translatedLabels?: FilterButtonBarTranslation | undefined) => <T extends Record<string, unknown>>(props: TableFilterProps<T>) => JSX.Element;
31
+ TextFilter: (translatedLabels?: FilterButtonBarTranslation) => <T extends Record<string, unknown>>(props: TableFilterProps<T>) => JSX.Element;
32
32
  /**
33
33
  * Date range filter.
34
34
  *
@@ -39,7 +39,7 @@ export declare const tableFilters: {
39
39
  * If your data is different type e.g. `string`, you can use `accessor` property in column description:
40
40
  * `accessor: (rowData) => new Date(rowData.date)`.
41
41
  */
42
- DateRangeFilter: (options?: DateRangeFilterOptions | undefined) => <T_1 extends Record<string, unknown>>(props: TableFilterProps<T_1>) => JSX.Element;
42
+ DateRangeFilter: (options?: DateRangeFilterOptions) => <T_1 extends Record<string, unknown>>(props: TableFilterProps<T_1>) => JSX.Element;
43
43
  /**
44
44
  * Number range filter.
45
45
  *
@@ -48,5 +48,5 @@ export declare const tableFilters: {
48
48
  * `accessor: (rowData) => Number(rowData.numberProp)`.
49
49
  * @param translatedLabels Translated filter labels.
50
50
  */
51
- NumberRangeFilter: (translatedLabels?: (NumberRangeTranslation & FilterButtonBarTranslation) | undefined) => <T_2 extends Record<string, unknown>>(props: NumberRangeFilterProps<T_2>) => JSX.Element;
51
+ NumberRangeFilter: (translatedLabels?: NumberRangeTranslation & FilterButtonBarTranslation) => <T_2 extends Record<string, unknown>>(props: NumberRangeFilterProps<T_2>) => JSX.Element;
52
52
  };
@@ -4,3 +4,4 @@ export { useSubRowFiltering } from './useSubRowFiltering';
4
4
  export { useSubRowSelection } from './useSubRowSelection';
5
5
  export { useResizeColumns } from './useResizeColumns';
6
6
  export { useColumnDragAndDrop } from './useColumnDragAndDrop';
7
+ export { useStickyColumns } from './useStickyColumns';
@@ -8,3 +8,4 @@ export { useSubRowFiltering } from './useSubRowFiltering';
8
8
  export { useSubRowSelection } from './useSubRowSelection';
9
9
  export { useResizeColumns } from './useResizeColumns';
10
10
  export { useColumnDragAndDrop } from './useColumnDragAndDrop';
11
+ export { useStickyColumns } from './useStickyColumns';
@@ -18,6 +18,11 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
18
18
  }
19
19
  return to.concat(ar || Array.prototype.slice.call(from));
20
20
  };
21
+ /*---------------------------------------------------------------------------------------------
22
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
23
+ * See LICENSE.md in the project root for license terms and full copyright notice.
24
+ *--------------------------------------------------------------------------------------------*/
25
+ import React from 'react';
21
26
  import { ExpanderColumn, EXPANDER_CELL_ID } from '../columns';
22
27
  export var useExpanderCell = function (subComponent, expanderCell, isRowDisabled) { return function (hooks) {
23
28
  if (!subComponent) {
@@ -33,7 +38,9 @@ export var useExpanderCell = function (subComponent, expanderCell, isRowDisabled
33
38
  isDisabled: isRowDisabled,
34
39
  });
35
40
  return __spreadArray([
36
- __assign(__assign({}, expanderColumn), { Cell: expanderCell !== null && expanderCell !== void 0 ? expanderCell : expanderColumn.Cell })
41
+ __assign(__assign({}, expanderColumn), { Cell: expanderCell
42
+ ? function (cellProps) { return React.createElement(React.Fragment, null, expanderCell(cellProps)); }
43
+ : expanderColumn.Cell })
37
44
  ], columns, true);
38
45
  });
39
46
  }; };
@@ -0,0 +1,2 @@
1
+ import { Hooks } from 'react-table';
2
+ export declare const useStickyColumns: <T extends Record<string, unknown>>(hooks: Hooks<T>) => void;
@@ -0,0 +1,80 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
13
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
14
+ if (ar || !(i in from)) {
15
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
16
+ ar[i] = from[i];
17
+ }
18
+ }
19
+ return to.concat(ar || Array.prototype.slice.call(from));
20
+ };
21
+ /*---------------------------------------------------------------------------------------------
22
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
23
+ * See LICENSE.md in the project root for license terms and full copyright notice.
24
+ *--------------------------------------------------------------------------------------------*/
25
+ import { actions, } from 'react-table';
26
+ actions.setScrolledLeft = 'setScrolledLeft';
27
+ actions.setScrolledRight = 'setScrolledRight';
28
+ export var useStickyColumns = function (hooks) {
29
+ hooks.stateReducers.push(reducer);
30
+ hooks.useInstance.push(useInstance);
31
+ };
32
+ var reducer = function (newState, action) {
33
+ var _a, _b;
34
+ if (action.type === actions.init) {
35
+ return __assign(__assign({}, newState), { sticky: {} });
36
+ }
37
+ if (action.type === actions.setScrolledLeft &&
38
+ ((_a = newState.sticky) === null || _a === void 0 ? void 0 : _a.isScrolledToLeft) !== action.value // Prevents unnecessary re-render
39
+ ) {
40
+ return __assign(__assign({}, newState), { sticky: __assign(__assign({}, newState.sticky), { isScrolledToLeft: action.value }) });
41
+ }
42
+ if (action.type === actions.setScrolledRight &&
43
+ ((_b = newState.sticky) === null || _b === void 0 ? void 0 : _b.isScrolledToRight) !== action.value // Prevents unnecessary re-render
44
+ ) {
45
+ return __assign(__assign({}, newState), { sticky: __assign(__assign({}, newState.sticky), { isScrolledToRight: action.value }) });
46
+ }
47
+ return newState;
48
+ };
49
+ var useInstance = function (instance) {
50
+ var flatHeaders = instance.flatHeaders;
51
+ // Edge case. Saving original sticky state in case sticky columns are reordered.
52
+ flatHeaders.forEach(function (header) {
53
+ var _a;
54
+ if (!header.originalSticky) {
55
+ header.originalSticky = (_a = header.sticky) !== null && _a !== void 0 ? _a : 'none';
56
+ }
57
+ header.sticky =
58
+ header.originalSticky === 'none' ? undefined : header.originalSticky;
59
+ });
60
+ // If there is a column that is sticked to the left, make every column prior to that sticky too.
61
+ var hasLeftStickyColumn = false;
62
+ __spreadArray([], flatHeaders, true).reverse().forEach(function (header) {
63
+ if (header.sticky === 'left') {
64
+ hasLeftStickyColumn = true;
65
+ }
66
+ if (hasLeftStickyColumn) {
67
+ header.sticky = 'left';
68
+ }
69
+ });
70
+ // If there is a column that is sticked to the right, make every column after to that sticky too.
71
+ var hasRightStickyColumn = false;
72
+ flatHeaders.forEach(function (header) {
73
+ if (header.sticky === 'right') {
74
+ hasRightStickyColumn = true;
75
+ }
76
+ if (hasRightStickyColumn) {
77
+ header.sticky = 'right';
78
+ }
79
+ });
80
+ };
@@ -1,2 +1,3 @@
1
1
  import { ColumnInstance } from 'react-table';
2
2
  export declare const getCellStyle: <T extends Record<string, unknown>>(column: ColumnInstance<T>, isTableResizing: boolean) => React.CSSProperties | undefined;
3
+ export declare const getStickyStyle: <T extends Record<string, unknown>>(column: ColumnInstance<T>, columnList: ColumnInstance<T>[]) => React.CSSProperties;
@@ -1,3 +1,12 @@
1
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
2
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
3
+ if (ar || !(i in from)) {
4
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
5
+ ar[i] = from[i];
6
+ }
7
+ }
8
+ return to.concat(ar || Array.prototype.slice.call(from));
9
+ };
1
10
  export var getCellStyle = function (column, isTableResizing) {
2
11
  var style = {};
3
12
  style.flex = "1 1 145px";
@@ -20,3 +29,28 @@ export var getCellStyle = function (column, isTableResizing) {
20
29
  }
21
30
  return style;
22
31
  };
32
+ export var getStickyStyle = function (column, columnList) {
33
+ if (!column.sticky) {
34
+ return {};
35
+ }
36
+ var left = 0;
37
+ for (var _i = 0, columnList_1 = columnList; _i < columnList_1.length; _i++) {
38
+ var col = columnList_1[_i];
39
+ if (col.id === column.id) {
40
+ break;
41
+ }
42
+ left += Number(col.width || col.resizeWidth || 0);
43
+ }
44
+ var right = 0;
45
+ for (var _a = 0, _b = __spreadArray([], columnList, true).reverse(); _a < _b.length; _a++) {
46
+ var col = _b[_a];
47
+ if (col.id === column.id) {
48
+ break;
49
+ }
50
+ right += Number(col.width || col.resizeWidth || 0);
51
+ }
52
+ return {
53
+ '--iui-table-sticky-left': column.sticky === 'left' ? "".concat(left, "px") : undefined,
54
+ '--iui-table-sticky-right': column.sticky === 'right' ? "".concat(right, "px") : undefined,
55
+ };
56
+ };
@@ -22,6 +22,7 @@ export default class Toaster {
22
22
  private settings;
23
23
  private toastsRef;
24
24
  private isInitialized;
25
+ private asyncInit;
25
26
  /**
26
27
  * Set global Toaster settings for toasts order and placement.
27
28
  * Settings will be applied to new toasts on the page.
@@ -41,7 +42,6 @@ export default class Toaster {
41
42
  };
42
43
  private createToast;
43
44
  private removeToast;
44
- private createContainer;
45
45
  private updateView;
46
46
  private closeToast;
47
47
  closeAll(): void;
@@ -59,12 +59,13 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
59
59
  * See LICENSE.md in the project root for license terms and full copyright notice.
60
60
  *--------------------------------------------------------------------------------------------*/
61
61
  import React from 'react';
62
- import ReactDOM from 'react-dom';
63
- import { getContainer } from '../utils';
62
+ import * as ReactDOM from 'react-dom';
63
+ import { getContainer, getDocument } from '../utils';
64
64
  import { ToastWrapper } from './ToastWrapper';
65
65
  var TOASTS_CONTAINER_ID = 'iui-toasts-container';
66
66
  var Toaster = /** @class */ (function () {
67
67
  function Toaster() {
68
+ var _this = this;
68
69
  this.toasts = [];
69
70
  this.lastId = 0;
70
71
  this.settings = {
@@ -73,19 +74,60 @@ var Toaster = /** @class */ (function () {
73
74
  };
74
75
  this.toastsRef = React.createRef();
75
76
  this.isInitialized = false;
77
+ // Create container on demand.
78
+ // Cannot do it in constructor, because SSG/SSR apps would fail.
79
+ this.asyncInit = function () { return __awaiter(_this, void 0, void 0, function () {
80
+ var container, toastWrapper, _ReactDOM, _ReactDOMInternals, root;
81
+ var _a, _b;
82
+ return __generator(this, function (_c) {
83
+ if (this.isInitialized) {
84
+ return [2 /*return*/];
85
+ }
86
+ container = (_a = getContainer(TOASTS_CONTAINER_ID)) !== null && _a !== void 0 ? _a : (_b = getDocument()) === null || _b === void 0 ? void 0 : _b.body;
87
+ if (!container) {
88
+ return [2 /*return*/];
89
+ }
90
+ this.isInitialized = true;
91
+ toastWrapper = React.createElement(ToastWrapper, { ref: this.toastsRef });
92
+ _ReactDOM = ReactDOM;
93
+ // v18 mode
94
+ if (_ReactDOM.createRoot) {
95
+ _ReactDOMInternals = _ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
96
+ // suppress warning about importing createRoot from react-dom/client
97
+ if (_ReactDOMInternals) {
98
+ _ReactDOMInternals.usingClientEntryPoint = true;
99
+ }
100
+ root = _ReactDOM.createRoot(container);
101
+ root.render(toastWrapper);
102
+ // revert suppression, not to influence users app
103
+ if (_ReactDOMInternals) {
104
+ _ReactDOMInternals.usingClientEntryPoint = false;
105
+ }
106
+ }
107
+ else {
108
+ // v17 and before
109
+ ReactDOM.render(toastWrapper, container);
110
+ }
111
+ return [2 /*return*/];
112
+ });
113
+ }); };
76
114
  }
77
115
  /**
78
116
  * Set global Toaster settings for toasts order and placement.
79
117
  * Settings will be applied to new toasts on the page.
80
118
  */
81
119
  Toaster.prototype.setSettings = function (newSettings) {
82
- var _a, _b, _c, _d, _e;
120
+ var _this = this;
121
+ var _a, _b, _c;
83
122
  (_a = newSettings.placement) !== null && _a !== void 0 ? _a : (newSettings.placement = this.settings.placement);
84
123
  (_b = newSettings.order) !== null && _b !== void 0 ? _b : (newSettings.order = ((_c = newSettings.placement) === null || _c === void 0 ? void 0 : _c.startsWith('bottom'))
85
124
  ? 'ascending'
86
125
  : 'descending');
87
126
  this.settings = newSettings;
88
- (_d = this.toastsRef.current) === null || _d === void 0 ? void 0 : _d.setPlacement((_e = this.settings.placement) !== null && _e !== void 0 ? _e : 'top');
127
+ this.asyncInit().then(function () {
128
+ var _a, _b;
129
+ (_a = _this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setPlacement((_b = _this.settings.placement) !== null && _b !== void 0 ? _b : 'top');
130
+ });
89
131
  };
90
132
  Toaster.prototype.positive = function (content, options) {
91
133
  return this.createToast(content, 'positive', options);
@@ -117,34 +159,12 @@ var Toaster = /** @class */ (function () {
117
159
  this.toasts = this.toasts.filter(function (toast) { return toast.id !== id; });
118
160
  this.updateView();
119
161
  };
120
- // Create container on demand.
121
- // Cannot do it in constructor, because SSG/SSR apps would fail.
122
- Toaster.prototype.createContainer = function () {
123
- return __awaiter(this, void 0, void 0, function () {
124
- var container;
125
- return __generator(this, function (_a) {
126
- container = getContainer(TOASTS_CONTAINER_ID);
127
- if (!container) {
128
- return [2 /*return*/];
129
- }
130
- ReactDOM.render(React.createElement(ToastWrapper, { ref: this.toastsRef }), container);
131
- return [2 /*return*/];
132
- });
133
- });
134
- };
135
162
  Toaster.prototype.updateView = function () {
136
163
  var _this = this;
137
- var _a;
138
- if (!this.isInitialized) {
139
- this.createContainer().then(function () {
140
- var _a;
141
- _this.isInitialized = true;
142
- (_a = _this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setToasts(_this.toasts);
143
- });
144
- }
145
- else {
146
- (_a = this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setToasts(this.toasts);
147
- }
164
+ this.asyncInit().then(function () {
165
+ var _a;
166
+ (_a = _this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setToasts(_this.toasts);
167
+ });
148
168
  };
149
169
  Toaster.prototype.closeToast = function (toastId) {
150
170
  this.toasts = this.toasts.map(function (toast) {
@@ -48,8 +48,8 @@ export { LabeledSelect } from './LabeledSelect';
48
48
  export type { LabeledSelectProps } from './LabeledSelect';
49
49
  export { LabeledTextarea } from './LabeledTextarea';
50
50
  export type { LabeledTextareaProps } from './LabeledTextarea';
51
- export { Menu, MenuItem, MenuDivider, MenuExtraContent } from './Menu';
52
- export type { MenuProps, MenuItemProps, MenuDividerProps, MenuExtraContentProps, } from './Menu';
51
+ export { Menu, MenuItem, MenuDivider, MenuExtraContent, MenuItemSkeleton, } from './Menu';
52
+ export type { MenuProps, MenuItemProps, MenuDividerProps, MenuExtraContentProps, MenuItemSkeletonProps, } from './Menu';
53
53
  export { Modal, ModalButtonBar, ModalContent } from './Modal';
54
54
  export type { ModalProps, ModalButtonBarProps, ModalContentProps, } from './Modal';
55
55
  export { ProgressLinear, ProgressRadial } from './ProgressIndicators';
package/esm/core/index.js CHANGED
@@ -27,7 +27,7 @@ export { LabeledInput } from './LabeledInput';
27
27
  export { InputGroup } from './InputGroup';
28
28
  export { LabeledSelect } from './LabeledSelect';
29
29
  export { LabeledTextarea } from './LabeledTextarea';
30
- export { Menu, MenuItem, MenuDivider, MenuExtraContent } from './Menu';
30
+ export { Menu, MenuItem, MenuDivider, MenuExtraContent, MenuItemSkeleton, } from './Menu';
31
31
  export { Modal, ModalButtonBar, ModalContent } from './Modal';
32
32
  export { ProgressLinear, ProgressRadial } from './ProgressIndicators';
33
33
  export { Radio } from './Radio';