@itwin/itwinui-react 1.45.0 → 1.47.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 (96) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/cjs/core/Breadcrumbs/Breadcrumbs.d.ts +116 -0
  3. package/cjs/core/Breadcrumbs/Breadcrumbs.js +2 -3
  4. package/cjs/core/ButtonGroup/ButtonGroup.js +1 -1
  5. package/cjs/core/ColorPicker/ColorSwatch.d.ts +1 -1
  6. package/cjs/core/DatePicker/DatePicker.d.ts +24 -4
  7. package/cjs/core/DatePicker/DatePicker.js +116 -19
  8. package/cjs/core/Dialog/Dialog.d.ts +5 -5
  9. package/cjs/core/Dialog/Dialog.js +38 -6
  10. package/cjs/core/Dialog/DialogBackdrop.d.ts +2 -2
  11. package/cjs/core/Dialog/DialogBackdrop.js +2 -2
  12. package/cjs/core/Dialog/DialogContext.d.ts +31 -0
  13. package/cjs/core/Dialog/DialogDragContext.d.ts +8 -0
  14. package/cjs/core/Dialog/DialogDragContext.js +28 -0
  15. package/cjs/core/Dialog/DialogMain.d.ts +2 -2
  16. package/cjs/core/Dialog/DialogMain.js +46 -6
  17. package/cjs/core/Dialog/DialogTitleBar.d.ts +2 -2
  18. package/cjs/core/Dialog/DialogTitleBar.js +12 -2
  19. package/cjs/core/Modal/Modal.js +1 -1
  20. package/cjs/core/Table/Table.d.ts +6 -0
  21. package/cjs/core/Table/Table.js +73 -17
  22. package/cjs/core/Table/actionHandlers/index.d.ts +1 -1
  23. package/cjs/core/Table/actionHandlers/index.js +2 -1
  24. package/cjs/core/Table/actionHandlers/resizeHandler.d.ts +2 -0
  25. package/cjs/core/Table/actionHandlers/selectHandler.d.ts +5 -0
  26. package/cjs/core/Table/actionHandlers/selectHandler.js +35 -2
  27. package/cjs/core/Table/filters/FilterToggle.d.ts +0 -1
  28. package/cjs/core/Table/filters/FilterToggle.js +3 -3
  29. package/cjs/core/Table/hooks/useResizeColumns.d.ts +33 -1
  30. package/cjs/core/Table/hooks/useResizeColumns.js +89 -29
  31. package/cjs/core/index.d.ts +3 -1
  32. package/cjs/core/index.js +6 -3
  33. package/cjs/core/utils/components/Resizer.d.ts +31 -0
  34. package/cjs/core/utils/components/Resizer.js +206 -0
  35. package/cjs/core/utils/components/VirtualScroll.js +26 -24
  36. package/cjs/core/utils/components/index.d.ts +1 -0
  37. package/cjs/core/utils/components/index.js +1 -0
  38. package/cjs/core/utils/functions/index.d.ts +1 -0
  39. package/cjs/core/utils/functions/index.js +1 -0
  40. package/cjs/core/utils/functions/styles.d.ts +6 -0
  41. package/cjs/core/utils/functions/styles.js +21 -0
  42. package/cjs/core/utils/hooks/useContainerWidth.d.ts +1 -1
  43. package/cjs/core/utils/hooks/useDragAndDrop.d.ts +14 -0
  44. package/cjs/core/utils/hooks/useDragAndDrop.js +110 -0
  45. package/cjs/core/utils/hooks/useEventListener.d.ts +1 -1
  46. package/cjs/core/utils/hooks/useOverflow.d.ts +1 -1
  47. package/cjs/core/utils/hooks/useResizeObserver.d.ts +1 -1
  48. package/cjs/types/react-table-config.d.ts +13 -1
  49. package/esm/core/Breadcrumbs/Breadcrumbs.d.ts +116 -0
  50. package/esm/core/Breadcrumbs/Breadcrumbs.js +2 -3
  51. package/esm/core/ButtonGroup/ButtonGroup.js +1 -1
  52. package/esm/core/ColorPicker/ColorSwatch.d.ts +1 -1
  53. package/esm/core/DatePicker/DatePicker.d.ts +24 -4
  54. package/esm/core/DatePicker/DatePicker.js +116 -19
  55. package/esm/core/Dialog/Dialog.d.ts +5 -5
  56. package/esm/core/Dialog/Dialog.js +37 -5
  57. package/esm/core/Dialog/DialogBackdrop.d.ts +2 -2
  58. package/esm/core/Dialog/DialogBackdrop.js +2 -2
  59. package/esm/core/Dialog/DialogContext.d.ts +31 -0
  60. package/esm/core/Dialog/DialogDragContext.d.ts +8 -0
  61. package/esm/core/Dialog/DialogDragContext.js +21 -0
  62. package/esm/core/Dialog/DialogMain.d.ts +2 -2
  63. package/esm/core/Dialog/DialogMain.js +47 -7
  64. package/esm/core/Dialog/DialogTitleBar.d.ts +2 -2
  65. package/esm/core/Dialog/DialogTitleBar.js +12 -2
  66. package/esm/core/Modal/Modal.js +1 -1
  67. package/esm/core/Table/Table.d.ts +6 -0
  68. package/esm/core/Table/Table.js +76 -20
  69. package/esm/core/Table/actionHandlers/index.d.ts +1 -1
  70. package/esm/core/Table/actionHandlers/index.js +1 -1
  71. package/esm/core/Table/actionHandlers/resizeHandler.d.ts +2 -0
  72. package/esm/core/Table/actionHandlers/selectHandler.d.ts +5 -0
  73. package/esm/core/Table/actionHandlers/selectHandler.js +33 -1
  74. package/esm/core/Table/filters/FilterToggle.d.ts +0 -1
  75. package/esm/core/Table/filters/FilterToggle.js +4 -4
  76. package/esm/core/Table/hooks/useResizeColumns.d.ts +33 -1
  77. package/esm/core/Table/hooks/useResizeColumns.js +89 -29
  78. package/esm/core/index.d.ts +3 -1
  79. package/esm/core/index.js +2 -1
  80. package/esm/core/utils/components/Resizer.d.ts +31 -0
  81. package/esm/core/utils/components/Resizer.js +199 -0
  82. package/esm/core/utils/components/VirtualScroll.js +26 -24
  83. package/esm/core/utils/components/index.d.ts +1 -0
  84. package/esm/core/utils/components/index.js +1 -0
  85. package/esm/core/utils/functions/index.d.ts +1 -0
  86. package/esm/core/utils/functions/index.js +1 -0
  87. package/esm/core/utils/functions/styles.d.ts +6 -0
  88. package/esm/core/utils/functions/styles.js +17 -0
  89. package/esm/core/utils/hooks/useContainerWidth.d.ts +1 -1
  90. package/esm/core/utils/hooks/useDragAndDrop.d.ts +14 -0
  91. package/esm/core/utils/hooks/useDragAndDrop.js +103 -0
  92. package/esm/core/utils/hooks/useEventListener.d.ts +1 -1
  93. package/esm/core/utils/hooks/useOverflow.d.ts +1 -1
  94. package/esm/core/utils/hooks/useResizeObserver.d.ts +1 -1
  95. package/esm/types/react-table-config.d.ts +13 -1
  96. package/package.json +1 -1
@@ -26,9 +26,9 @@ var __rest = (this && this.__rest) || function (s, e) {
26
26
  *--------------------------------------------------------------------------------------------*/
27
27
  import React from 'react';
28
28
  import cx from 'classnames';
29
- import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, useColumnOrder, } from 'react-table';
29
+ import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, useColumnOrder, useGlobalFilter, } from 'react-table';
30
30
  import { ProgressRadial } from '../ProgressIndicators';
31
- import { useTheme, useResizeObserver, mergeRefs } from '../utils';
31
+ 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';
@@ -37,10 +37,11 @@ import { TableRowMemoized } from './TableRowMemoized';
37
37
  import { FilterToggle } from './filters';
38
38
  import { customFilterFunctions } from './filters/customFilterFunctions';
39
39
  import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, useColumnDragAndDrop, useScrollToRow, useStickyColumns, } from './hooks';
40
- import { onExpandHandler, onFilterHandler, onSelectHandler, onSingleSelectHandler, onTableResizeEnd, onTableResizeStart, } from './actionHandlers';
40
+ import { onExpandHandler, onFilterHandler, onSelectHandler, onShiftSelectHandler, onSingleSelectHandler, onTableResizeEnd, onTableResizeStart, } from './actionHandlers';
41
41
  import VirtualScroll from '../utils/components/VirtualScroll';
42
42
  import { SELECTION_CELL_ID } from './columns';
43
43
  var singleRowSelectedAction = 'singleRowSelected';
44
+ var shiftRowSelectedAction = 'shiftRowSelected';
44
45
  export var tableResizeStartAction = 'tableResizeStart';
45
46
  var tableResizeEndAction = 'tableResizeEnd';
46
47
  var flattenColumns = function (columns) {
@@ -97,9 +98,9 @@ var flattenColumns = function (columns) {
97
98
  */
98
99
  export var Table = function (props) {
99
100
  var _a;
100
- var data = props.data, columns = props.columns, _b = props.isLoading, isLoading = _b === void 0 ? false : _b, emptyTableContent = props.emptyTableContent, className = props.className, style = props.style, id = props.id, _c = props.isSelectable, isSelectable = _c === void 0 ? false : _c, onSelect = props.onSelect, onRowClick = props.onRowClick, _d = props.selectionMode, selectionMode = _d === void 0 ? 'multi' : _d, _e = props.isSortable, isSortable = _e === void 0 ? false : _e, onSort = props.onSort, stateReducer = props.stateReducer, onBottomReached = props.onBottomReached, onRowInViewport = props.onRowInViewport, _f = props.intersectionMargin, intersectionMargin = _f === void 0 ? 300 : _f, subComponent = props.subComponent, onExpand = props.onExpand, onFilter = props.onFilter, emptyFilteredTableContent = props.emptyFilteredTableContent, filterFunctions = props.filterTypes, expanderCell = props.expanderCell, isRowDisabled = props.isRowDisabled, rowProps = props.rowProps, _g = props.density, density = _g === void 0 ? 'default' : _g, _h = props.selectSubRows, selectSubRows = _h === void 0 ? true : _h, getSubRows = props.getSubRows, _j = props.selectRowOnClick, selectRowOnClick = _j === void 0 ? true : _j, paginatorRenderer = props.paginatorRenderer, _k = props.pageSize, pageSize = _k === void 0 ? 25 : _k, _l = props.isResizable, isResizable = _l === void 0 ? false : _l, _m = props.styleType, styleType = _m === void 0 ? 'default' : _m, _o = props.enableVirtualization, enableVirtualization = _o === void 0 ? false : _o, _p = props.enableColumnReordering, enableColumnReordering = _p === void 0 ? false : _p, rest = __rest(props, ["data", "columns", "isLoading", "emptyTableContent", "className", "style", "id", "isSelectable", "onSelect", "onRowClick", "selectionMode", "isSortable", "onSort", "stateReducer", "onBottomReached", "onRowInViewport", "intersectionMargin", "subComponent", "onExpand", "onFilter", "emptyFilteredTableContent", "filterTypes", "expanderCell", "isRowDisabled", "rowProps", "density", "selectSubRows", "getSubRows", "selectRowOnClick", "paginatorRenderer", "pageSize", "isResizable", "styleType", "enableVirtualization", "enableColumnReordering"]);
101
+ var data = props.data, columns = props.columns, _b = props.isLoading, isLoading = _b === void 0 ? false : _b, emptyTableContent = props.emptyTableContent, className = props.className, style = props.style, id = props.id, _c = props.isSelectable, isSelectable = _c === void 0 ? false : _c, onSelect = props.onSelect, onRowClick = props.onRowClick, _d = props.selectionMode, selectionMode = _d === void 0 ? 'multi' : _d, _e = props.isSortable, isSortable = _e === void 0 ? false : _e, onSort = props.onSort, stateReducer = props.stateReducer, onBottomReached = props.onBottomReached, onRowInViewport = props.onRowInViewport, _f = props.intersectionMargin, intersectionMargin = _f === void 0 ? 300 : _f, subComponent = props.subComponent, onExpand = props.onExpand, onFilter = props.onFilter, globalFilterValue = props.globalFilterValue, emptyFilteredTableContent = props.emptyFilteredTableContent, filterFunctions = props.filterTypes, expanderCell = props.expanderCell, isRowDisabled = props.isRowDisabled, rowProps = props.rowProps, _g = props.density, density = _g === void 0 ? 'default' : _g, _h = props.selectSubRows, selectSubRows = _h === void 0 ? true : _h, getSubRows = props.getSubRows, _j = props.selectRowOnClick, selectRowOnClick = _j === void 0 ? true : _j, paginatorRenderer = props.paginatorRenderer, _k = props.pageSize, pageSize = _k === void 0 ? 25 : _k, _l = props.isResizable, isResizable = _l === void 0 ? false : _l, _m = props.columnResizeMode, columnResizeMode = _m === void 0 ? 'fit' : _m, _o = props.styleType, styleType = _o === void 0 ? 'default' : _o, _p = props.enableVirtualization, enableVirtualization = _p === void 0 ? false : _p, _q = props.enableColumnReordering, enableColumnReordering = _q === void 0 ? false : _q, rest = __rest(props, ["data", "columns", "isLoading", "emptyTableContent", "className", "style", "id", "isSelectable", "onSelect", "onRowClick", "selectionMode", "isSortable", "onSort", "stateReducer", "onBottomReached", "onRowInViewport", "intersectionMargin", "subComponent", "onExpand", "onFilter", "globalFilterValue", "emptyFilteredTableContent", "filterTypes", "expanderCell", "isRowDisabled", "rowProps", "density", "selectSubRows", "getSubRows", "selectRowOnClick", "paginatorRenderer", "pageSize", "isResizable", "columnResizeMode", "styleType", "enableVirtualization", "enableColumnReordering"]);
101
102
  useTheme();
102
- var _q = React.useState(), ownerDocument = _q[0], setOwnerDocument = _q[1];
103
+ var ownerDocument = React.useRef();
103
104
  var defaultColumn = React.useMemo(function () { return ({
104
105
  maxWidth: 0,
105
106
  minWidth: 0,
@@ -116,6 +117,36 @@ export var Table = function (props) {
116
117
  var flatColumns = flattenColumns(columns);
117
118
  return flatColumns.some(function (column) { return column.id === SELECTION_CELL_ID; });
118
119
  }, [columns]);
120
+ var disableUserSelect = React.useCallback(function (e) {
121
+ if (e.key === 'Shift') {
122
+ ownerDocument.current &&
123
+ (ownerDocument.current.documentElement.style.userSelect = 'none');
124
+ }
125
+ }, []);
126
+ var enableUserSelect = React.useCallback(function (e) {
127
+ if (e.key === 'Shift') {
128
+ ownerDocument.current &&
129
+ (ownerDocument.current.documentElement.style.userSelect = '');
130
+ }
131
+ }, []);
132
+ React.useEffect(function () {
133
+ if (!isSelectable || selectionMode !== 'multi') {
134
+ return;
135
+ }
136
+ var ownerDoc = ownerDocument.current;
137
+ ownerDoc === null || ownerDoc === void 0 ? void 0 : ownerDoc.addEventListener('keydown', disableUserSelect);
138
+ ownerDoc === null || ownerDoc === void 0 ? void 0 : ownerDoc.addEventListener('keyup', enableUserSelect);
139
+ return function () {
140
+ ownerDoc === null || ownerDoc === void 0 ? void 0 : ownerDoc.removeEventListener('keydown', disableUserSelect);
141
+ ownerDoc === null || ownerDoc === void 0 ? void 0 : ownerDoc.removeEventListener('keyup', enableUserSelect);
142
+ };
143
+ }, [
144
+ isSelectable,
145
+ selectionMode,
146
+ ownerDocument,
147
+ disableUserSelect,
148
+ enableUserSelect,
149
+ ]);
119
150
  var tableStateReducer = React.useCallback(function (newState, action, previousState, instance) {
120
151
  switch (action.type) {
121
152
  case TableActions.toggleSortBy:
@@ -134,6 +165,12 @@ export var Table = function (props) {
134
165
  hasManualSelectionColumn ? undefined : isRowDisabled);
135
166
  break;
136
167
  }
168
+ case shiftRowSelectedAction: {
169
+ newState = onShiftSelectHandler(newState, action, instance, onSelect,
170
+ // If it has manual selection column, then we can't check whether row is disabled
171
+ hasManualSelectionColumn ? undefined : isRowDisabled);
172
+ break;
173
+ }
137
174
  case TableActions.toggleRowSelected:
138
175
  case TableActions.toggleAllRowsSelected:
139
176
  case TableActions.toggleAllPageRowsSelected: {
@@ -171,8 +208,8 @@ export var Table = function (props) {
171
208
  return getSubRows ? getSubRows(item, index) : item.subRows;
172
209
  });
173
210
  }, [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), 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;
211
+ 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), columnResizeMode: columnResizeMode }), useFlexLayout, useResizeColumns(ownerDocument), useFilters, useSubRowFiltering(hasAnySubRows), useGlobalFilter, useSortBy, useExpanded, usePagination, useRowSelect, useSubRowSelection, useExpanderCell(subComponent, expanderCell, isRowDisabled), useSelectionCell(isSelectable, selectionMode, isRowDisabled), useColumnOrder, useColumnDragAndDrop(enableColumnReordering), useStickyColumns);
212
+ var getTableProps = instance.getTableProps, rows = instance.rows, headerGroups = instance.headerGroups, getTableBodyProps = instance.getTableBodyProps, prepareRow = instance.prepareRow, state = instance.state, allColumns = instance.allColumns, dispatch = instance.dispatch, page = instance.page, gotoPage = instance.gotoPage, setPageSize = instance.setPageSize, flatHeaders = instance.flatHeaders, visibleColumns = instance.visibleColumns, setGlobalFilter = instance.setGlobalFilter;
176
213
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
177
214
  var key = _a[0], value = _a[1];
178
215
  if (key.startsWith('data-') || key.startsWith('aria-')) {
@@ -180,7 +217,7 @@ export var Table = function (props) {
180
217
  }
181
218
  return result;
182
219
  }, {});
183
- var areFiltersSet = allColumns.some(function (column) { return column.filterValue != null && column.filterValue !== ''; });
220
+ var areFiltersSet = allColumns.some(function (column) { return column.filterValue != null && column.filterValue !== ''; }) || !!globalFilterValue;
184
221
  var showFilterButton = function (column) {
185
222
  return (data.length !== 0 || areFiltersSet) && column.canFilter;
186
223
  };
@@ -196,7 +233,14 @@ export var Table = function (props) {
196
233
  !isDisabled &&
197
234
  selectRowOnClick &&
198
235
  !event.isDefaultPrevented()) {
199
- if (!row.isSelected && (selectionMode === 'single' || !event.ctrlKey)) {
236
+ if (selectionMode === 'multi' && event.shiftKey) {
237
+ dispatch({
238
+ type: shiftRowSelectedAction,
239
+ id: row.id,
240
+ });
241
+ }
242
+ else if (!row.isSelected &&
243
+ (selectionMode === 'single' || !event.ctrlKey)) {
200
244
  dispatch({
201
245
  type: singleRowSelectedAction,
202
246
  id: row.id,
@@ -214,6 +258,9 @@ export var Table = function (props) {
214
258
  dispatch,
215
259
  onRowClick,
216
260
  ]);
261
+ React.useEffect(function () {
262
+ setGlobalFilter(globalFilterValue);
263
+ }, [globalFilterValue, setGlobalFilter]);
217
264
  React.useEffect(function () {
218
265
  setPageSize(pageSize);
219
266
  }, [pageSize, setPageSize]);
@@ -239,6 +286,7 @@ export var Table = function (props) {
239
286
  var previousTableWidth = React.useRef(0);
240
287
  var onTableResize = React.useCallback(function (_a) {
241
288
  var width = _a.width;
289
+ instance.tableWidth = width;
242
290
  if (width === previousTableWidth.current) {
243
291
  return;
244
292
  }
@@ -254,7 +302,7 @@ export var Table = function (props) {
254
302
  return;
255
303
  }
256
304
  dispatch({ type: tableResizeStartAction });
257
- }, [dispatch, state.columnResizing.columnWidths, flatHeaders]);
305
+ }, [dispatch, state.columnResizing.columnWidths, flatHeaders, instance]);
258
306
  var resizeRef = useResizeObserver(onTableResize)[0];
259
307
  // Flexbox handles columns resize so we take new column widths before browser repaints.
260
308
  React.useLayoutEffect(function () {
@@ -270,12 +318,10 @@ export var Table = function (props) {
270
318
  });
271
319
  var headerRef = React.useRef(null);
272
320
  var bodyRef = React.useRef(null);
273
- // Using `useState` to rerender rows when table body ref is available
274
- var _s = React.useState(null), bodyRefState = _s[0], setBodyRefState = _s[1];
275
321
  var getPreparedRow = React.useCallback(function (index) {
276
322
  var row = page[index];
277
323
  prepareRow(row);
278
- return (React.createElement(TableRowMemoized, { row: row, rowProps: rowProps, isLast: index === page.length - 1, onRowInViewport: onRowInViewportRef, onBottomReached: onBottomReachedRef, intersectionMargin: intersectionMargin, state: state, key: row.getRowProps().key, onClick: onRowClickHandler, subComponent: subComponent, isDisabled: !!(isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original)), tableHasSubRows: hasAnySubRows, tableInstance: instance, expanderCell: expanderCell, bodyRef: bodyRefState, tableRowRef: enableVirtualization ? undefined : tableRowRef(row) }));
324
+ return (React.createElement(TableRowMemoized, { row: row, rowProps: rowProps, isLast: index === page.length - 1, onRowInViewport: onRowInViewportRef, onBottomReached: onBottomReachedRef, intersectionMargin: intersectionMargin, state: state, key: row.getRowProps().key, onClick: onRowClickHandler, subComponent: subComponent, isDisabled: !!(isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original)), tableHasSubRows: hasAnySubRows, tableInstance: instance, expanderCell: expanderCell, bodyRef: bodyRef.current, tableRowRef: enableVirtualization ? undefined : tableRowRef(row) }));
279
325
  }, [
280
326
  page,
281
327
  prepareRow,
@@ -288,7 +334,6 @@ export var Table = function (props) {
288
334
  hasAnySubRows,
289
335
  instance,
290
336
  expanderCell,
291
- bodyRefState,
292
337
  enableVirtualization,
293
338
  tableRowRef,
294
339
  ]);
@@ -317,9 +362,10 @@ export var Table = function (props) {
317
362
  // Call only on init
318
363
  // eslint-disable-next-line react-hooks/exhaustive-deps
319
364
  }, []);
365
+ var isHeaderDirectClick = React.useRef(false);
320
366
  return (React.createElement(React.Fragment, null,
321
367
  React.createElement("div", __assign({ ref: function (element) {
322
- setOwnerDocument(element === null || element === void 0 ? void 0 : element.ownerDocument);
368
+ ownerDocument.current = element === null || element === void 0 ? void 0 : element.ownerDocument;
323
369
  if (isResizable) {
324
370
  resizeRef(element);
325
371
  }
@@ -338,7 +384,8 @@ export var Table = function (props) {
338
384
  className: 'iui-row',
339
385
  });
340
386
  return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
341
- var columnProps = column.getHeaderProps(__assign(__assign({}, column.getSortByToggleProps()), { className: cx('iui-cell', {
387
+ var _a = column.getSortByToggleProps(), onClick = _a.onClick, restSortProps = __rest(_a, ["onClick"]);
388
+ var columnProps = column.getHeaderProps(__assign(__assign({}, restSortProps), { className: cx('iui-cell', {
342
389
  'iui-actionable': column.canSort,
343
390
  'iui-sorted': column.isSorted,
344
391
  'iui-cell-sticky': !!column.sticky,
@@ -348,16 +395,25 @@ export var Table = function (props) {
348
395
  columnRefs.current[column.id] = el;
349
396
  column.resizeWidth = el.getBoundingClientRect().width;
350
397
  }
398
+ }, onMouseDown: function () {
399
+ isHeaderDirectClick.current = true;
400
+ }, onClick: function (e) {
401
+ // Prevents from triggering sort when resizing and mouse is released in the middle of header
402
+ if (isHeaderDirectClick.current) {
403
+ onClick === null || onClick === void 0 ? void 0 : onClick(e);
404
+ isHeaderDirectClick.current = false;
405
+ }
351
406
  } }),
352
407
  column.render('Header'),
353
408
  (showFilterButton(column) ||
354
409
  showSortButton(column)) && (React.createElement("div", { className: 'iui-table-header-actions-container' },
355
- showFilterButton(column) && (React.createElement(FilterToggle, { column: column, ownerDocument: ownerDocument })),
410
+ showFilterButton(column) && (React.createElement(FilterToggle, { column: column })),
356
411
  showSortButton(column) && (React.createElement("div", { className: 'iui-cell-end-icon' }, column.isSortedDesc ||
357
412
  (!column.isSorted && column.sortDescFirst) ? (React.createElement(SvgSortDown, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (React.createElement(SvgSortUp, { className: 'iui-icon iui-sort', "aria-hidden": true })))))),
358
413
  isResizable &&
359
414
  column.isResizerVisible &&
360
- index !== headerGroup.headers.length - 1 && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
415
+ (index !== headerGroup.headers.length - 1 ||
416
+ columnResizeMode === 'expand') && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
361
417
  React.createElement("div", { className: 'iui-resizer-bar' }))),
362
418
  enableColumnReordering &&
363
419
  !column.disableReordering && (React.createElement("div", { className: 'iui-reorder-bar' })),
@@ -372,7 +428,7 @@ export var Table = function (props) {
372
428
  'iui-zebra-striping': styleType === 'zebra-rows',
373
429
  }),
374
430
  style: { outline: 0 },
375
- }), { ref: mergeRefs(bodyRef, setBodyRefState), onScroll: function () {
431
+ }), { ref: bodyRef, onScroll: function () {
376
432
  if (headerRef.current && bodyRef.current) {
377
433
  headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
378
434
  updateStickyState();
@@ -387,7 +443,7 @@ export var Table = function (props) {
387
443
  !isLoading && data.length === 0 && !areFiltersSet && (React.createElement("div", { className: 'iui-table-empty' },
388
444
  React.createElement("div", null, emptyTableContent))),
389
445
  !isLoading &&
390
- (data.length === 0 || filteredFlatRows.length === 0) &&
446
+ (data.length === 0 || rows.length === 0) &&
391
447
  areFiltersSet && (React.createElement("div", { className: 'iui-table-empty' },
392
448
  React.createElement("div", null, emptyFilteredTableContent)))), paginatorRenderer === null || paginatorRenderer === void 0 ? void 0 :
393
449
  paginatorRenderer(paginatorRendererProps))));
@@ -1,4 +1,4 @@
1
1
  export { onExpandHandler } from './expandHandler';
2
2
  export { onFilterHandler } from './filterHandler';
3
- export { onSelectHandler, onSingleSelectHandler } from './selectHandler';
3
+ export { onSelectHandler, onSingleSelectHandler, onShiftSelectHandler, } from './selectHandler';
4
4
  export { onTableResizeStart, onTableResizeEnd } from './resizeHandler';
@@ -4,5 +4,5 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  export { onExpandHandler } from './expandHandler';
6
6
  export { onFilterHandler } from './filterHandler';
7
- export { onSelectHandler, onSingleSelectHandler } from './selectHandler';
7
+ export { onSelectHandler, onSingleSelectHandler, onShiftSelectHandler, } from './selectHandler';
8
8
  export { onTableResizeStart, onTableResizeEnd } from './resizeHandler';
@@ -16,6 +16,7 @@ export declare const onTableResizeStart: <T extends Record<string, unknown>>(sta
16
16
  isScrolledToRight?: boolean | undefined;
17
17
  isScrolledToLeft?: boolean | undefined;
18
18
  };
19
+ lastSelectedRowId?: string | undefined;
19
20
  columnOrder: import("react-table").IdType<T>[];
20
21
  expanded: Record<import("react-table").IdType<T>, boolean>;
21
22
  filters: import("react-table").Filters<T>;
@@ -46,6 +47,7 @@ export declare const onTableResizeEnd: <T extends Record<string, unknown>>(state
46
47
  isScrolledToRight?: boolean | undefined;
47
48
  isScrolledToLeft?: boolean | undefined;
48
49
  };
50
+ lastSelectedRowId?: string | undefined;
49
51
  columnOrder: import("react-table").IdType<T>[];
50
52
  expanded: Record<import("react-table").IdType<T>, boolean>;
51
53
  filters: import("react-table").Filters<T>;
@@ -7,6 +7,7 @@ export declare const onSelectHandler: <T extends Record<string, unknown>>(newSta
7
7
  * Handles selection when clicked on a row.
8
8
  */
9
9
  export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(state: TableState<T>, action: ActionType, instance?: TableInstance<T> | undefined, onSelect?: ((selectedData: T[] | undefined, tableState?: TableState<T> | undefined) => void) | undefined, isRowDisabled?: ((rowData: T) => boolean) | undefined) => {
10
+ lastSelectedRowId: any;
10
11
  selectedRowIds: Record<string, boolean>;
11
12
  hiddenColumns?: import("react-table").IdType<T>[] | undefined;
12
13
  columnResizing: {
@@ -36,3 +37,7 @@ export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(
36
37
  }>;
37
38
  sortBy: import("react-table").SortingRule<T>[];
38
39
  };
40
+ /**
41
+ * Handles selection when clicked on a row while shift key is pressed.
42
+ */
43
+ export declare const onShiftSelectHandler: <T extends Record<string, unknown>>(state: TableState<T>, action: ActionType, instance?: TableInstance<T> | undefined, onSelect?: ((selectedData: T[] | undefined, tableState?: TableState<T> | undefined) => void) | undefined, isRowDisabled?: ((rowData: T) => boolean) | undefined) => TableState<T>;
@@ -57,11 +57,43 @@ export var onSingleSelectHandler = function (state, action, instance, onSelect,
57
57
  };
58
58
  handleRow_1(instance.rowsById[action.id]);
59
59
  }
60
- var newState = __assign(__assign({}, state), { selectedRowIds: selectedRowIds });
60
+ var newState = __assign(__assign({}, state), { lastSelectedRowId: action.id, selectedRowIds: selectedRowIds });
61
61
  // Passing to `onSelectHandler` to handle filtered sub-rows
62
62
  onSelectHandler(newState, instance, onSelect, isRowDisabled);
63
63
  return newState;
64
64
  };
65
+ /**
66
+ * Handles selection when clicked on a row while shift key is pressed.
67
+ */
68
+ export var onShiftSelectHandler = function (state, action, instance, onSelect, isRowDisabled) {
69
+ if (instance == null) {
70
+ return state;
71
+ }
72
+ var startIndex = Math.max(0, instance.flatRows.findIndex(function (row) { return row.id === state.lastSelectedRowId; }));
73
+ var endIndex = Math.max(0, instance.flatRows.findIndex(function (row) { return row.id === action.id; }));
74
+ if (startIndex > endIndex) {
75
+ var temp = startIndex;
76
+ startIndex = endIndex;
77
+ endIndex = temp;
78
+ }
79
+ var selectedRowIds = {};
80
+ // 1. Select all rows between start and end
81
+ instance.flatRows
82
+ .slice(startIndex, endIndex + 1)
83
+ .forEach(function (r) { return (selectedRowIds[r.id] = true); });
84
+ // 2. Select all children of the last row (endIndex)
85
+ // Since lastRow's children come after endIndex + 1 (not selected in step 1)
86
+ var handleRow = function (row) {
87
+ selectedRowIds[row.id] = true;
88
+ row.subRows.forEach(function (r) { return handleRow(r); });
89
+ };
90
+ handleRow(instance.flatRows[endIndex]);
91
+ var newState = __assign(__assign({}, state), { selectedRowIds: selectedRowIds });
92
+ // 3.1 Deselect all selected disabled rows and their children
93
+ // 3.2 Convert all partially selected rows marked with tick mark to horizontal line
94
+ onSelectHandler(newState, instance, onSelect, isRowDisabled);
95
+ return newState;
96
+ };
65
97
  var getSelectedData = function (selectedRowIds, instance) {
66
98
  var selectedData = [];
67
99
  var setSelectedData = function (row) {
@@ -4,7 +4,6 @@ import '@itwin/itwinui-css/css/table.css';
4
4
  import { StylingProps } from '../../utils';
5
5
  export declare type FilterToggleProps<T extends Record<string, unknown>> = {
6
6
  column: HeaderGroup<T>;
7
- ownerDocument?: Document;
8
7
  } & StylingProps;
9
8
  /**
10
9
  * Handles showing filter icon and opening filter component.
@@ -29,15 +29,15 @@ import SvgFilter from '@itwin/itwinui-icons-react/cjs/icons/Filter';
29
29
  import React from 'react';
30
30
  import cx from 'classnames';
31
31
  import '@itwin/itwinui-css/css/table.css';
32
- import { useTheme, Popover, getDocument } from '../../utils';
32
+ import { useTheme, Popover } from '../../utils';
33
33
  import { IconButton } from '../../Buttons';
34
34
  /**
35
35
  * Handles showing filter icon and opening filter component.
36
36
  */
37
37
  export var FilterToggle = function (props) {
38
- var column = props.column, _a = props.ownerDocument, ownerDocument = _a === void 0 ? getDocument() : _a, className = props.className, rest = __rest(props, ["column", "ownerDocument", "className"]);
38
+ var column = props.column, className = props.className, rest = __rest(props, ["column", "className"]);
39
39
  useTheme();
40
- var _b = React.useState(false), isVisible = _b[0], setIsVisible = _b[1];
40
+ var _a = React.useState(false), isVisible = _a[0], setIsVisible = _a[1];
41
41
  var close = React.useCallback(function () { return setIsVisible(false); }, []);
42
42
  var setFilter = React.useCallback(function (filterValue) {
43
43
  column.setFilter(filterValue);
@@ -48,7 +48,7 @@ export var FilterToggle = function (props) {
48
48
  close();
49
49
  }, [close, column]);
50
50
  var isColumnFiltered = column.filterValue != null && column.filterValue !== '';
51
- return (React.createElement(React.Fragment, null, column.canFilter && column.Filter && (React.createElement(Popover, { content: column.render('Filter', { close: close, setFilter: setFilter, clearFilter: clearFilter }), placement: 'bottom-start', visible: isVisible, onClickOutside: close, appendTo: ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.body },
51
+ return (React.createElement(React.Fragment, null, column.canFilter && column.Filter && (React.createElement(Popover, { content: column.render('Filter', { close: close, setFilter: setFilter, clearFilter: clearFilter }), placement: 'bottom-start', visible: isVisible, onClickOutside: close },
52
52
  React.createElement(IconButton, __assign({ styleType: 'borderless', isActive: isVisible || isColumnFiltered, className: cx('iui-filter-button', className), onClick: function (e) {
53
53
  setIsVisible(function (v) { return !v; });
54
54
  // Prevents from triggering sort
@@ -1,5 +1,37 @@
1
+ /**
2
+ * Copied from react-table as useResizeColumns and made some changes:
3
+ * - Added TS typings
4
+ * - Added sibling/next column resize when resizing
5
+ * - Favoring min/max widths when resizing
6
+ * - Added owner document support
7
+ * @link https://github.com/tannerlinsley/react-table/blob/master/src/plugin-hooks/useResizeColumns.js
8
+ */
9
+ /**
10
+ * MIT License
11
+ *
12
+ * Copyright (c) 2016 Tanner Linsley
13
+ *
14
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ * of this software and associated documentation files (the "Software"), to deal
16
+ * in the Software without restriction, including without limitation the rights
17
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ * copies of the Software, and to permit persons to whom the Software is
19
+ * furnished to do so, subject to the following conditions:
20
+ *
21
+ * The above copyright notice and this permission notice shall be included in all
22
+ * copies or substantial portions of the Software.
23
+ *
24
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ * SOFTWARE.
31
+ */
32
+ import React from 'react';
1
33
  import { Hooks } from 'react-table';
2
34
  export declare const useResizeColumns: {
3
- <T extends Record<string, unknown>>(ownerDocument: Document | undefined): (hooks: Hooks<T>) => void;
35
+ <T extends Record<string, unknown>>(ownerDocument: React.RefObject<Document | undefined>): (hooks: Hooks<T>) => void;
4
36
  pluginName: string;
5
37
  };
@@ -29,24 +29,19 @@ var isTouchEvent = function (event) {
29
29
  };
30
30
  var defaultGetResizerProps = function (ownerDocument) { return function (props, _a) {
31
31
  var instance = _a.instance, header = _a.header, nextHeader = _a.nextHeader;
32
- if (!ownerDocument) {
33
- return props;
34
- }
35
- var dispatch = instance.dispatch, flatHeaders = instance.flatHeaders;
32
+ var dispatch = instance.dispatch;
36
33
  var onResizeStart = function (e, header) {
34
+ var _a, _b, _c;
37
35
  // lets not respond to multiple touches (e.g. 2 or 3 fingers)
38
36
  if (isTouchEvent(e) && e.touches && e.touches.length > 1) {
39
37
  return;
40
38
  }
41
- // Setting `width` here because it might take several rerenders until actual column width is set.
42
- flatHeaders.forEach(function (h) {
43
- if (!h.width) {
44
- h.width = h.resizeWidth;
45
- }
46
- });
47
- var headerIdWidths = getLeafHeaders(header).map(function (d) { return [d.id, d.width]; });
39
+ var headerIdWidths = getLeafHeaders(header).map(function (d) { return [
40
+ d.id,
41
+ getHeaderWidth(d),
42
+ ]; });
48
43
  var nextHeaderIdWidths = nextHeader
49
- ? getLeafHeaders(nextHeader).map(function (d) { return [d.id, d.width]; })
44
+ ? getLeafHeaders(nextHeader).map(function (d) { return [d.id, getHeaderWidth(d)]; })
50
45
  : [];
51
46
  var clientX = isTouchEvent(e)
52
47
  ? Math.round(e.touches[0].clientX)
@@ -65,8 +60,10 @@ var defaultGetResizerProps = function (ownerDocument) { return function (props,
65
60
  moveHandler: function (e) { return dispatchMove(e.clientX); },
66
61
  upEvent: 'mouseup',
67
62
  upHandler: function () {
68
- ownerDocument.removeEventListener('mousemove', handlersAndEvents.mouse.moveHandler);
69
- ownerDocument.removeEventListener('mouseup', handlersAndEvents.mouse.upHandler);
63
+ var _a, _b, _c;
64
+ (_a = ownerDocument.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('mousemove', handlersAndEvents.mouse.moveHandler);
65
+ (_b = ownerDocument.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('mouseup', handlersAndEvents.mouse.upHandler);
66
+ (_c = ownerDocument.current) === null || _c === void 0 ? void 0 : _c.removeEventListener('mouseleave', handlersAndEvents.mouse.upHandler);
70
67
  dispatchEnd();
71
68
  },
72
69
  },
@@ -81,8 +78,9 @@ var defaultGetResizerProps = function (ownerDocument) { return function (props,
81
78
  },
82
79
  upEvent: 'touchend',
83
80
  upHandler: function () {
84
- ownerDocument.removeEventListener(handlersAndEvents.touch.moveEvent, handlersAndEvents.touch.moveHandler);
85
- ownerDocument.removeEventListener(handlersAndEvents.touch.upEvent, handlersAndEvents.touch.moveHandler);
81
+ var _a, _b;
82
+ (_a = ownerDocument.current) === null || _a === void 0 ? void 0 : _a.removeEventListener(handlersAndEvents.touch.moveEvent, handlersAndEvents.touch.moveHandler);
83
+ (_b = ownerDocument.current) === null || _b === void 0 ? void 0 : _b.removeEventListener(handlersAndEvents.touch.upEvent, handlersAndEvents.touch.moveHandler);
86
84
  dispatchEnd();
87
85
  },
88
86
  },
@@ -93,13 +91,16 @@ var defaultGetResizerProps = function (ownerDocument) { return function (props,
93
91
  var passiveIfSupported = passiveEventSupported()
94
92
  ? { passive: false }
95
93
  : false;
96
- ownerDocument.addEventListener(events.moveEvent, events.moveHandler, passiveIfSupported);
97
- ownerDocument.addEventListener(events.upEvent, events.upHandler, passiveIfSupported);
94
+ (_a = ownerDocument.current) === null || _a === void 0 ? void 0 : _a.addEventListener(events.moveEvent, events.moveHandler, passiveIfSupported);
95
+ (_b = ownerDocument.current) === null || _b === void 0 ? void 0 : _b.addEventListener(events.upEvent, events.upHandler, passiveIfSupported);
96
+ if (!isTouchEvent(e)) {
97
+ (_c = ownerDocument.current) === null || _c === void 0 ? void 0 : _c.addEventListener('mouseleave', handlersAndEvents.mouse.upHandler, passiveIfSupported);
98
+ }
98
99
  dispatch({
99
100
  type: actions.columnStartResizing,
100
101
  columnId: header.id,
101
- columnWidth: header.width,
102
- nextColumnWidth: nextHeader === null || nextHeader === void 0 ? void 0 : nextHeader.width,
102
+ columnWidth: getHeaderWidth(header),
103
+ nextColumnWidth: getHeaderWidth(nextHeader),
103
104
  headerIdWidths: headerIdWidths,
104
105
  nextHeaderIdWidths: nextHeaderIdWidths,
105
106
  clientX: clientX,
@@ -116,6 +117,8 @@ var defaultGetResizerProps = function (ownerDocument) { return function (props,
116
117
  e.persist();
117
118
  // Prevents from triggering drag'n'drop
118
119
  e.preventDefault();
120
+ // Prevents from triggering sort
121
+ e.stopPropagation();
119
122
  onResizeStart(e, header);
120
123
  },
121
124
  onTouchStart: function (e) {
@@ -151,13 +154,29 @@ var reducer = function (newState, action, previousState, instance) {
151
154
  if (action.type === actions.columnResizing) {
152
155
  var clientX = action.clientX;
153
156
  var _a = newState.columnResizing, _b = _a.startX, startX = _b === void 0 ? 0 : _b, _c = _a.columnWidth, columnWidth = _c === void 0 ? 1 : _c, _d = _a.nextColumnWidth, nextColumnWidth = _d === void 0 ? 1 : _d, _e = _a.headerIdWidths, headerIdWidths = _e === void 0 ? [] : _e, _f = _a.nextHeaderIdWidths, nextHeaderIdWidths = _f === void 0 ? [] : _f;
157
+ if (!instance) {
158
+ return newState;
159
+ }
154
160
  var deltaX = clientX - startX;
155
161
  var newColumnWidths = getColumnWidths(headerIdWidths, deltaX / columnWidth);
156
- var newNextColumnWidths = getColumnWidths(nextHeaderIdWidths, -deltaX / nextColumnWidth);
157
- if (!isNewColumnWidthsValid(newColumnWidths, instance === null || instance === void 0 ? void 0 : instance.flatHeaders) ||
158
- !isNewColumnWidthsValid(newNextColumnWidths, instance === null || instance === void 0 ? void 0 : instance.flatHeaders)) {
162
+ var isTableWidthDecreasing = calculateTableWidth(newColumnWidths, instance.flatHeaders) <
163
+ instance.tableWidth;
164
+ var newNextColumnWidths = (instance === null || instance === void 0 ? void 0 : instance.columnResizeMode) === 'fit' ||
165
+ ((instance === null || instance === void 0 ? void 0 : instance.columnResizeMode) === 'expand' && isTableWidthDecreasing)
166
+ ? getColumnWidths(nextHeaderIdWidths, -deltaX / nextColumnWidth)
167
+ : {};
168
+ if (!isNewColumnWidthsValid(newColumnWidths, instance.flatHeaders) ||
169
+ !isNewColumnWidthsValid(newNextColumnWidths, instance.flatHeaders) ||
170
+ !isNewTableWidthValid(__assign(__assign({}, newColumnWidths), newNextColumnWidths), instance)) {
159
171
  return newState;
160
172
  }
173
+ // Setting `width` here because it might take several rerenders until actual column width is set.
174
+ // Also setting after the actual resize happened.
175
+ instance === null || instance === void 0 ? void 0 : instance.flatHeaders.forEach(function (h) {
176
+ if (!h.width) {
177
+ h.width = h.resizeWidth;
178
+ }
179
+ });
161
180
  return __assign(__assign({}, newState), { columnResizing: __assign(__assign({}, newState.columnResizing), { columnWidths: __assign(__assign(__assign({}, newState.columnResizing.columnWidths), newColumnWidths), newNextColumnWidths) }) });
162
181
  }
163
182
  if (action.type === actions.columnDoneResizing) {
@@ -197,25 +216,53 @@ var isNewColumnWidthsValid = function (columnWidths, headers) {
197
216
  }
198
217
  return true;
199
218
  };
219
+ var isNewTableWidthValid = function (columnWidths, instance) {
220
+ if (instance.columnResizeMode === 'fit') {
221
+ return true;
222
+ }
223
+ var newTableWidth = 0;
224
+ for (var _i = 0, _a = instance.flatHeaders; _i < _a.length; _i++) {
225
+ var header = _a[_i];
226
+ newTableWidth += columnWidths[header.id]
227
+ ? columnWidths[header.id]
228
+ : getHeaderWidth(header);
229
+ }
230
+ // `tableWidth` is whole number therefore we need to round the `newTableWidth`
231
+ if (Math.round(newTableWidth) < instance.tableWidth) {
232
+ return false;
233
+ }
234
+ return true;
235
+ };
200
236
  var useInstanceBeforeDimensions = function (instance) {
201
- var flatHeaders = instance.flatHeaders, getHooks = instance.getHooks, columnResizing = instance.state.columnResizing;
237
+ var flatHeaders = instance.flatHeaders, getHooks = instance.getHooks, columnResizing = instance.state.columnResizing, columnResizeMode = instance.columnResizeMode;
202
238
  var getInstance = useGetLatest(instance);
203
239
  flatHeaders.forEach(function (header, index) {
204
240
  var _a;
205
241
  var resizeWidth = columnResizing.columnWidths[header.id];
206
242
  header.width = resizeWidth || header.width || header.originalWidth;
207
243
  header.isResizing = columnResizing.isResizingColumn === header.id;
208
- var headerToResize = header.disableResizing
244
+ var headerToResize = header.disableResizing && columnResizeMode === 'fit'
209
245
  ? getPreviousResizableHeader(header, instance)
210
246
  : header;
211
- var nextResizableHeader = getNextResizableHeader(header, instance);
247
+ // When `columnResizeMode` is `expand` and it is a last column,
248
+ // then try to find some column on the left side to resize
249
+ // when table width is decreasing.
250
+ var nextResizableHeader = columnResizeMode === 'expand' && index === flatHeaders.length - 1
251
+ ? getPreviousResizableHeader(header, instance)
252
+ : getNextResizableHeader(header, instance);
212
253
  header.canResize =
213
254
  header.disableResizing != null ? !header.disableResizing : true;
214
255
  // Show resizer when header is resizable or when next header is resizable
215
256
  // and there is resizable columns on the left side of the resizer.
216
- header.isResizerVisible =
217
- (header.canResize && !!nextResizableHeader) ||
218
- (headerToResize && !!((_a = instance.flatHeaders[index + 1]) === null || _a === void 0 ? void 0 : _a.canResize));
257
+ if (columnResizeMode === 'fit') {
258
+ header.isResizerVisible =
259
+ (header.canResize && !!nextResizableHeader) ||
260
+ (headerToResize && !!((_a = instance.flatHeaders[index + 1]) === null || _a === void 0 ? void 0 : _a.canResize));
261
+ // When resize mode is `expand` show resizer on the current resizable column.
262
+ }
263
+ else {
264
+ header.isResizerVisible = header.canResize && !!headerToResize;
265
+ }
219
266
  header.getResizerProps = makePropGetter(getHooks().getResizerProps, {
220
267
  instance: getInstance(),
221
268
  header: headerToResize,
@@ -255,6 +302,19 @@ function getLeafHeaders(header) {
255
302
  recurseHeader(header);
256
303
  return leafHeaders;
257
304
  }
305
+ var getHeaderWidth = function (header) {
306
+ return Number(header.width || header.resizeWidth || 0);
307
+ };
308
+ var calculateTableWidth = function (columnWidths, headers) {
309
+ var newTableWidth = 0;
310
+ for (var _i = 0, headers_1 = headers; _i < headers_1.length; _i++) {
311
+ var header = headers_1[_i];
312
+ newTableWidth += columnWidths[header.id]
313
+ ? columnWidths[header.id]
314
+ : getHeaderWidth(header);
315
+ }
316
+ return newTableWidth;
317
+ };
258
318
  // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#safely_detecting_option_support
259
319
  var passiveSupported = null;
260
320
  var passiveEventSupported = function () {