@itwin/itwinui-react 1.25.0 → 1.28.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 (110) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/cjs/core/ButtonGroup/ButtonGroup.js +2 -4
  3. package/cjs/core/Buttons/Button/Button.d.ts +1 -1
  4. package/cjs/core/Buttons/Button/Button.js +4 -5
  5. package/cjs/core/Buttons/IconButton/IconButton.js +2 -3
  6. package/cjs/core/Buttons/SplitButton/SplitButton.js +5 -3
  7. package/cjs/core/Checkbox/Checkbox.d.ts +11 -0
  8. package/cjs/core/Checkbox/Checkbox.js +14 -4
  9. package/cjs/core/ColorPicker/ColorSwatch.d.ts +1 -1
  10. package/cjs/core/ComboBox/ComboBox.d.ts +2 -2
  11. package/cjs/core/DatePicker/DatePicker.d.ts +1 -1
  12. package/cjs/core/ErrorPage/ErrorPage.d.ts +2 -1
  13. package/cjs/core/ErrorPage/ErrorPage.js +3 -2
  14. package/cjs/core/InformationPanel/InformationPanel.d.ts +4 -1
  15. package/cjs/core/InformationPanel/InformationPanel.js +4 -1
  16. package/cjs/core/InformationPanel/InformationPanelContent.d.ts +42 -0
  17. package/cjs/core/InformationPanel/InformationPanelContent.js +66 -0
  18. package/cjs/core/InformationPanel/index.d.ts +2 -0
  19. package/cjs/core/InformationPanel/index.js +3 -1
  20. package/cjs/core/LabeledInput/LabeledInput.d.ts +2 -2
  21. package/cjs/core/Menu/MenuItem.d.ts +1 -1
  22. package/cjs/core/Modal/ModalButtonBar.d.ts +2 -1
  23. package/cjs/core/Modal/ModalButtonBar.js +3 -2
  24. package/cjs/core/Table/Table.d.ts +13 -0
  25. package/cjs/core/Table/Table.js +80 -11
  26. package/cjs/core/Table/TableCell.js +1 -1
  27. package/cjs/core/Table/TablePaginator.d.ts +7 -7
  28. package/cjs/core/Table/TablePaginator.js +20 -10
  29. package/cjs/core/Table/TableRowMemoized.d.ts +21 -0
  30. package/cjs/core/Table/TableRowMemoized.js +7 -4
  31. package/cjs/core/Table/actionHandlers/resizeHandler.d.ts +51 -0
  32. package/cjs/core/Table/actionHandlers/resizeHandler.js +22 -0
  33. package/cjs/core/Table/actionHandlers/selectHandler.d.ts +10 -7
  34. package/cjs/core/Table/filters/BaseFilter.js +3 -1
  35. package/cjs/core/Table/filters/FilterToggle.js +4 -3
  36. package/cjs/core/Table/hooks/index.d.ts +1 -0
  37. package/cjs/core/Table/hooks/index.js +3 -1
  38. package/cjs/core/Table/hooks/useResizeColumns.d.ts +5 -0
  39. package/cjs/core/Table/hooks/useResizeColumns.js +273 -0
  40. package/cjs/core/Table/utils.d.ts +1 -1
  41. package/cjs/core/Table/utils.js +8 -2
  42. package/cjs/core/Tabs/Tabs.d.ts +4 -0
  43. package/cjs/core/Tabs/Tabs.js +3 -8
  44. package/cjs/core/index.d.ts +4 -4
  45. package/cjs/core/index.js +4 -2
  46. package/cjs/core/utils/components/MiddleTextTruncation.d.ts +21 -0
  47. package/cjs/core/utils/components/MiddleTextTruncation.js +56 -0
  48. package/cjs/core/utils/components/index.d.ts +1 -0
  49. package/cjs/core/utils/components/index.js +1 -0
  50. package/cjs/core/utils/hooks/index.d.ts +1 -0
  51. package/cjs/core/utils/hooks/index.js +1 -0
  52. package/cjs/core/utils/hooks/useContainerWidth.d.ts +17 -0
  53. package/cjs/core/utils/hooks/useContainerWidth.js +50 -0
  54. package/cjs/core/utils/hooks/useOverflow.d.ts +1 -1
  55. package/cjs/types/react-table-config.d.ts +16 -3
  56. package/esm/core/ButtonGroup/ButtonGroup.js +2 -4
  57. package/esm/core/Buttons/Button/Button.d.ts +1 -1
  58. package/esm/core/Buttons/Button/Button.js +4 -5
  59. package/esm/core/Buttons/IconButton/IconButton.js +2 -3
  60. package/esm/core/Buttons/SplitButton/SplitButton.js +5 -3
  61. package/esm/core/Checkbox/Checkbox.d.ts +11 -0
  62. package/esm/core/Checkbox/Checkbox.js +14 -4
  63. package/esm/core/ColorPicker/ColorSwatch.d.ts +1 -1
  64. package/esm/core/ComboBox/ComboBox.d.ts +2 -2
  65. package/esm/core/DatePicker/DatePicker.d.ts +1 -1
  66. package/esm/core/ErrorPage/ErrorPage.d.ts +2 -1
  67. package/esm/core/ErrorPage/ErrorPage.js +3 -2
  68. package/esm/core/InformationPanel/InformationPanel.d.ts +4 -1
  69. package/esm/core/InformationPanel/InformationPanel.js +4 -1
  70. package/esm/core/InformationPanel/InformationPanelContent.d.ts +42 -0
  71. package/esm/core/InformationPanel/InformationPanelContent.js +59 -0
  72. package/esm/core/InformationPanel/index.d.ts +2 -0
  73. package/esm/core/InformationPanel/index.js +1 -0
  74. package/esm/core/LabeledInput/LabeledInput.d.ts +2 -2
  75. package/esm/core/Menu/MenuItem.d.ts +1 -1
  76. package/esm/core/Modal/ModalButtonBar.d.ts +2 -1
  77. package/esm/core/Modal/ModalButtonBar.js +3 -2
  78. package/esm/core/Table/Table.d.ts +13 -0
  79. package/esm/core/Table/Table.js +82 -13
  80. package/esm/core/Table/TableCell.js +1 -1
  81. package/esm/core/Table/TablePaginator.d.ts +7 -7
  82. package/esm/core/Table/TablePaginator.js +21 -11
  83. package/esm/core/Table/TableRowMemoized.d.ts +21 -0
  84. package/esm/core/Table/TableRowMemoized.js +5 -3
  85. package/esm/core/Table/actionHandlers/resizeHandler.d.ts +51 -0
  86. package/esm/core/Table/actionHandlers/resizeHandler.js +17 -0
  87. package/esm/core/Table/actionHandlers/selectHandler.d.ts +10 -7
  88. package/esm/core/Table/filters/BaseFilter.js +3 -1
  89. package/esm/core/Table/filters/FilterToggle.js +4 -3
  90. package/esm/core/Table/hooks/index.d.ts +1 -0
  91. package/esm/core/Table/hooks/index.js +1 -0
  92. package/esm/core/Table/hooks/useResizeColumns.d.ts +5 -0
  93. package/esm/core/Table/hooks/useResizeColumns.js +269 -0
  94. package/esm/core/Table/utils.d.ts +1 -1
  95. package/esm/core/Table/utils.js +8 -2
  96. package/esm/core/Tabs/Tabs.d.ts +4 -0
  97. package/esm/core/Tabs/Tabs.js +4 -9
  98. package/esm/core/index.d.ts +4 -4
  99. package/esm/core/index.js +2 -2
  100. package/esm/core/utils/components/MiddleTextTruncation.d.ts +21 -0
  101. package/esm/core/utils/components/MiddleTextTruncation.js +49 -0
  102. package/esm/core/utils/components/index.d.ts +1 -0
  103. package/esm/core/utils/components/index.js +1 -0
  104. package/esm/core/utils/hooks/index.d.ts +1 -0
  105. package/esm/core/utils/hooks/index.js +1 -0
  106. package/esm/core/utils/hooks/useContainerWidth.d.ts +17 -0
  107. package/esm/core/utils/hooks/useContainerWidth.js +43 -0
  108. package/esm/core/utils/hooks/useOverflow.d.ts +1 -1
  109. package/esm/types/react-table-config.d.ts +16 -3
  110. package/package.json +14 -5
@@ -28,7 +28,7 @@ import React from 'react';
28
28
  import cx from 'classnames';
29
29
  import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, } from 'react-table';
30
30
  import { ProgressRadial } from '../ProgressIndicators';
31
- import { useTheme } 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';
@@ -36,10 +36,13 @@ import { getCellStyle } 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, } from './hooks';
39
+ import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, } from './hooks';
40
40
  import { onExpandHandler, onFilterHandler, onSelectHandler, } from './actionHandlers';
41
41
  import { onSingleSelectHandler } from './actionHandlers/selectHandler';
42
+ import { onTableResizeEnd, onTableResizeStart, } from './actionHandlers/resizeHandler';
42
43
  var singleRowSelectedAction = 'singleRowSelected';
44
+ var tableResizeStartAction = 'tableResizeStart';
45
+ var tableResizeEndAction = 'tableResizeEnd';
43
46
  /**
44
47
  * Table based on [react-table](https://react-table.tanstack.com/docs/api/overview).
45
48
  * @example
@@ -84,9 +87,9 @@ var singleRowSelectedAction = 'singleRowSelected';
84
87
  */
85
88
  export var Table = function (props) {
86
89
  var _a;
87
- 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.isSortable, isSortable = _d === void 0 ? false : _d, onSort = props.onSort, stateReducer = props.stateReducer, onBottomReached = props.onBottomReached, onRowInViewport = props.onRowInViewport, _e = props.intersectionMargin, intersectionMargin = _e === void 0 ? 300 : _e, subComponent = props.subComponent, onExpand = props.onExpand, onFilter = props.onFilter, emptyFilteredTableContent = props.emptyFilteredTableContent, filterFunctions = props.filterTypes, expanderCell = props.expanderCell, isRowDisabled = props.isRowDisabled, rowProps = props.rowProps, _f = props.density, density = _f === void 0 ? 'default' : _f, _g = props.selectSubRows, selectSubRows = _g === void 0 ? true : _g, getSubRows = props.getSubRows, _h = props.selectRowOnClick, selectRowOnClick = _h === void 0 ? true : _h, paginatorRenderer = props.paginatorRenderer, _j = props.pageSize, pageSize = _j === void 0 ? 25 : _j, rest = __rest(props, ["data", "columns", "isLoading", "emptyTableContent", "className", "style", "id", "isSelectable", "onSelect", "onRowClick", "isSortable", "onSort", "stateReducer", "onBottomReached", "onRowInViewport", "intersectionMargin", "subComponent", "onExpand", "onFilter", "emptyFilteredTableContent", "filterTypes", "expanderCell", "isRowDisabled", "rowProps", "density", "selectSubRows", "getSubRows", "selectRowOnClick", "paginatorRenderer", "pageSize"]);
90
+ 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.isSortable, isSortable = _d === void 0 ? false : _d, onSort = props.onSort, stateReducer = props.stateReducer, onBottomReached = props.onBottomReached, onRowInViewport = props.onRowInViewport, _e = props.intersectionMargin, intersectionMargin = _e === void 0 ? 300 : _e, subComponent = props.subComponent, onExpand = props.onExpand, onFilter = props.onFilter, emptyFilteredTableContent = props.emptyFilteredTableContent, filterFunctions = props.filterTypes, expanderCell = props.expanderCell, isRowDisabled = props.isRowDisabled, rowProps = props.rowProps, _f = props.density, density = _f === void 0 ? 'default' : _f, _g = props.selectSubRows, selectSubRows = _g === void 0 ? true : _g, getSubRows = props.getSubRows, _h = props.selectRowOnClick, selectRowOnClick = _h === void 0 ? true : _h, paginatorRenderer = props.paginatorRenderer, _j = props.pageSize, pageSize = _j === void 0 ? 25 : _j, _k = props.isResizable, isResizable = _k === void 0 ? false : _k, _l = props.styleType, styleType = _l === void 0 ? 'default' : _l, rest = __rest(props, ["data", "columns", "isLoading", "emptyTableContent", "className", "style", "id", "isSelectable", "onSelect", "onRowClick", "isSortable", "onSort", "stateReducer", "onBottomReached", "onRowInViewport", "intersectionMargin", "subComponent", "onExpand", "onFilter", "emptyFilteredTableContent", "filterTypes", "expanderCell", "isRowDisabled", "rowProps", "density", "selectSubRows", "getSubRows", "selectRowOnClick", "paginatorRenderer", "pageSize", "isResizable", "styleType"]);
88
91
  useTheme();
89
- var _k = React.useState(), ownerDocument = _k[0], setOwnerDocument = _k[1];
92
+ var _m = React.useState(), ownerDocument = _m[0], setOwnerDocument = _m[1];
90
93
  var defaultColumn = React.useMemo(function () { return ({
91
94
  maxWidth: 0,
92
95
  minWidth: 0,
@@ -121,6 +124,14 @@ export var Table = function (props) {
121
124
  onSelectHandler(newState, instance, onSelect, isRowDisabled);
122
125
  break;
123
126
  }
127
+ case tableResizeStartAction: {
128
+ newState = onTableResizeStart(newState);
129
+ break;
130
+ }
131
+ case tableResizeEndAction: {
132
+ newState = onTableResizeEnd(newState, action);
133
+ break;
134
+ }
124
135
  default:
125
136
  break;
126
137
  }
@@ -134,8 +145,8 @@ export var Table = function (props) {
134
145
  return getSubRows ? getSubRows(item, index) : item.subRows;
135
146
  });
136
147
  }, [data, getSubRows]);
137
- 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, useFilters, useSubRowFiltering(hasAnySubRows), useSortBy, useExpanded, usePagination, useRowSelect, useSubRowSelection, useExpanderCell(subComponent, expanderCell, isRowDisabled), useSelectionCell(isSelectable, isRowDisabled));
138
- 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;
148
+ 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, isRowDisabled));
149
+ 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;
139
150
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
140
151
  var key = _a[0], value = _a[1];
141
152
  if (key.startsWith('data-') || key.startsWith('aria-')) {
@@ -181,24 +192,82 @@ export var Table = function (props) {
181
192
  state.pageIndex,
182
193
  state.pageSize,
183
194
  ]);
195
+ var columnRefs = React.useRef({});
196
+ var previousTableWidth = React.useRef(0);
197
+ var onTableResize = React.useCallback(function (_a) {
198
+ var width = _a.width;
199
+ if (width === previousTableWidth.current) {
200
+ return;
201
+ }
202
+ previousTableWidth.current = width;
203
+ // Update column widths when table was resized
204
+ flatHeaders.forEach(function (header) {
205
+ if (columnRefs.current[header.id]) {
206
+ header.resizeWidth = columnRefs.current[header.id].getBoundingClientRect().width;
207
+ }
208
+ });
209
+ // If no column was resized then leave table resize handling to the flexbox
210
+ if (Object.keys(state.columnResizing.columnWidths).length === 0) {
211
+ return;
212
+ }
213
+ dispatch({ type: tableResizeStartAction });
214
+ }, [dispatch, state.columnResizing.columnWidths, flatHeaders]);
215
+ var resizeRef = useResizeObserver(onTableResize)[0];
216
+ // Flexbox handles columns resize so we take new column widths before browser repaints.
217
+ React.useLayoutEffect(function () {
218
+ if (state.isTableResizing) {
219
+ var newColumnWidths_1 = {};
220
+ flatHeaders.forEach(function (column) {
221
+ if (columnRefs.current[column.id]) {
222
+ newColumnWidths_1[column.id] = columnRefs.current[column.id].getBoundingClientRect().width;
223
+ }
224
+ });
225
+ dispatch({ type: tableResizeEndAction, columnWidths: newColumnWidths_1 });
226
+ }
227
+ });
228
+ var headerRef = React.useRef(null);
229
+ var bodyRef = React.useRef(null);
184
230
  return (React.createElement(React.Fragment, null,
185
- React.createElement("div", __assign({ ref: function (element) { return setOwnerDocument(element === null || element === void 0 ? void 0 : element.ownerDocument); }, id: id }, getTableProps({
231
+ React.createElement("div", __assign({ ref: function (element) {
232
+ setOwnerDocument(element === null || element === void 0 ? void 0 : element.ownerDocument);
233
+ if (isResizable) {
234
+ resizeRef(element);
235
+ }
236
+ }, id: id }, getTableProps({
186
237
  className: cx('iui-table', (_a = {}, _a["iui-" + density] = density !== 'default', _a), className),
187
238
  style: style,
188
239
  }), ariaDataAttributes),
189
- React.createElement("div", { className: 'iui-table-header' }, headerGroups.slice(1).map(function (headerGroup) {
240
+ React.createElement("div", { className: 'iui-table-header', ref: headerRef }, headerGroups.slice(1).map(function (headerGroup) {
190
241
  var headerGroupProps = headerGroup.getHeaderGroupProps({
191
242
  className: 'iui-row',
192
243
  });
193
- return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column) {
194
- var columnProps = column.getHeaderProps(__assign(__assign({}, column.getSortByToggleProps()), { className: cx('iui-cell', { 'iui-actionable': column.canSort }, { 'iui-sorted': column.isSorted }, column.columnClassName), style: __assign({}, getCellStyle(column)) }));
195
- return (React.createElement("div", __assign({}, columnProps, { key: columnProps.key, title: undefined }),
244
+ return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
245
+ var _a = column.getSortByToggleProps(), onSortClick = _a.onClick, sortByProps = __rest(_a, ["onClick"]);
246
+ var columnProps = column.getHeaderProps(__assign(__assign({}, sortByProps), { className: cx('iui-cell', { 'iui-actionable': column.canSort }, { 'iui-sorted': column.isSorted }, column.columnClassName), style: __assign({}, getCellStyle(column, !!state.isTableResizing)) }));
247
+ return (React.createElement("div", __assign({}, columnProps, { key: columnProps.key, title: undefined, ref: function (el) {
248
+ if (el && isResizable) {
249
+ columnRefs.current[column.id] = el;
250
+ column.resizeWidth = el.getBoundingClientRect().width;
251
+ }
252
+ }, onMouseDown: onSortClick }),
196
253
  column.render('Header'),
197
254
  !isLoading && (data.length != 0 || areFiltersSet) && (React.createElement(FilterToggle, { column: column, ownerDocument: ownerDocument })),
198
- !isLoading && data.length != 0 && column.canSort && (React.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (React.createElement(SvgSortUp, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (React.createElement(SvgSortDown, { className: 'iui-icon iui-sort', "aria-hidden": true }))))));
255
+ !isLoading && data.length != 0 && column.canSort && (React.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (React.createElement(SvgSortUp, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (React.createElement(SvgSortDown, { className: 'iui-icon iui-sort', "aria-hidden": true })))),
256
+ isResizable &&
257
+ column.isResizerVisible &&
258
+ index !== headerGroup.headers.length - 1 && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
259
+ React.createElement("div", { className: 'iui-resizer-bar' })))));
199
260
  })));
200
261
  })),
201
- React.createElement("div", __assign({}, getTableBodyProps({ className: 'iui-table-body' })),
262
+ React.createElement("div", __assign({}, getTableBodyProps({
263
+ className: cx('iui-table-body', {
264
+ 'iui-zebra-striping': styleType === 'zebra-rows',
265
+ }),
266
+ }), { ref: bodyRef, onScroll: function () {
267
+ if (headerRef.current && bodyRef.current) {
268
+ headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
269
+ }
270
+ } }),
202
271
  data.length !== 0 &&
203
272
  page.map(function (row) {
204
273
  prepareRow(row);
@@ -35,7 +35,7 @@ export var TableCell = function (props) {
35
35
  };
36
36
  var cellElementProps = cell.getCellProps({
37
37
  className: cx('iui-cell', cell.column.cellClassName),
38
- style: __assign(__assign({}, getCellStyle(cell.column)), getSubRowStyle()),
38
+ style: __assign(__assign({}, getCellStyle(cell.column, !!tableInstance.state.isTableResizing)), getSubRowStyle()),
39
39
  });
40
40
  var cellProps = __assign(__assign({}, tableInstance), { cell: cell, row: cell.row, value: cell.value, column: cell.column });
41
41
  var cellContent = (React.createElement(React.Fragment, null,
@@ -30,12 +30,7 @@ export declare type TablePaginatorProps = {
30
30
  /**
31
31
  * Function that returns a label for the range of rows within the current page and the length of the whole data.
32
32
  * @default
33
- * (
34
- * startIndex: number,
35
- * endIndex: number,
36
- * totalRows: number,
37
- * isLoading: boolean,
38
- * ) =>
33
+ * (startIndex, endIndex, totalRows, isLoading) =>
39
34
  * isLoading
40
35
  * ? `${startIndex}-${endIndex}…`
41
36
  * : `${startIndex}-${endIndex} of ${totalRows}`;
@@ -56,6 +51,11 @@ export declare type TablePaginatorProps = {
56
51
  * @default (page: number) => `Go to page ${page}`
57
52
  */
58
53
  goToPageLabel?: (page: number) => string;
54
+ /**
55
+ * A label shown next to the page size selector. Use `null` to hide.
56
+ * @default 'Rows per page'
57
+ */
58
+ rowsPerPageLabel?: string | null;
59
59
  };
60
60
  } & TablePaginatorRendererProps & Omit<CommonProps, 'title'>;
61
61
  /**
@@ -67,5 +67,5 @@ export declare type TablePaginatorProps = {
67
67
  * paginatorRenderer={(props) => <TablePaginator {...props} />}
68
68
  * />
69
69
  */
70
- export declare const TablePaginator: (props: TablePaginatorProps) => JSX.Element;
70
+ export declare const TablePaginator: (props: TablePaginatorProps) => JSX.Element | null;
71
71
  export default TablePaginator;
@@ -33,7 +33,7 @@ import { ButtonGroup } from '../ButtonGroup';
33
33
  import { IconButton, Button, DropdownButton } from '../Buttons';
34
34
  import { ProgressRadial } from '../ProgressIndicators';
35
35
  import { MenuItem } from '../Menu';
36
- import { getBoundedValue, useTheme, useOverflow } from '../utils';
36
+ import { getBoundedValue, useTheme, useOverflow, useContainerWidth, } from '../utils';
37
37
  var defaultLocalization = {
38
38
  pageSizeLabel: function (size) { return size + " per page"; },
39
39
  rangeLabel: function (startIndex, endIndex, totalRows, isLoading) {
@@ -44,6 +44,7 @@ var defaultLocalization = {
44
44
  previousPage: 'Previous page',
45
45
  nextPage: 'Next page',
46
46
  goToPageLabel: function (page) { return "Go to page " + page; },
47
+ rowsPerPageLabel: 'Rows per page',
47
48
  };
48
49
  /**
49
50
  * Table paginator component. Recommended to pass to the `Table` as `paginatorRenderer` prop.
@@ -88,6 +89,7 @@ export var TablePaginator = function (props) {
88
89
  .map(function (_, index) { return pageButton(index); });
89
90
  }, [pageButton, totalPagesCount]);
90
91
  var _e = useOverflow(pageList), overflowRef = _e[0], visibleCount = _e[1];
92
+ var _f = useContainerWidth(), paginatorResizeRef = _f[0], paginatorWidth = _f[1];
91
93
  var onKeyDown = function (event) {
92
94
  // alt + arrow keys are used by browser/assistive technologies
93
95
  if (event.altKey) {
@@ -138,12 +140,17 @@ export var TablePaginator = function (props) {
138
140
  endPage = totalPagesCount;
139
141
  }
140
142
  var hasNoRows = totalPagesCount === 0;
143
+ var showPagesList = totalPagesCount > 1 || isLoading;
144
+ var showPageSizeList = pageSizeList && onPageSizeChange && !!totalRowsCount;
141
145
  var ellipsis = (React.createElement("span", { className: cx('iui-ellipsis', { 'iui-small': size === 'small' }) }, "\u2026"));
142
146
  var noRowsContent = (React.createElement(React.Fragment, null, isLoading ? (React.createElement(ProgressRadial, { indeterminate: true, size: 'small' })) : (React.createElement(Button, { styleType: 'borderless', disabled: true, size: buttonSize }, "1"))));
143
- return (React.createElement("div", __assign({ className: cx('iui-paginator', className) }, rest),
147
+ if (!showPagesList && !showPageSizeList) {
148
+ return null;
149
+ }
150
+ return (React.createElement("div", __assign({ className: cx('iui-paginator', className), ref: paginatorResizeRef }, rest),
144
151
  React.createElement("div", { className: 'iui-left' }),
145
- React.createElement("div", { className: 'iui-center', ref: overflowRef },
146
- React.createElement(IconButton, { styleType: 'borderless', disabled: currentPage === 0 || hasNoRows, onClick: function () { return onPageChange(currentPage - 1); }, size: buttonSize, "aria-label": localization.previousPage },
152
+ showPagesList && (React.createElement("div", { className: 'iui-center', ref: overflowRef },
153
+ React.createElement(IconButton, { styleType: 'borderless', disabled: currentPage === 0, onClick: function () { return onPageChange(currentPage - 1); }, size: buttonSize, "aria-label": localization.previousPage },
147
154
  React.createElement(SvgChevronLeft, null)),
148
155
  React.createElement(ButtonGroup, { onKeyDown: onKeyDown, ref: pageListRef }, (function () {
149
156
  if (hasNoRows) {
@@ -165,12 +172,15 @@ export var TablePaginator = function (props) {
165
172
  React.createElement(ProgressRadial, { indeterminate: true, size: 'small' })))));
166
173
  })()),
167
174
  React.createElement(IconButton, { styleType: 'borderless', disabled: currentPage === totalPagesCount - 1 || hasNoRows, onClick: function () { return onPageChange(currentPage + 1); }, size: buttonSize, "aria-label": localization.nextPage },
168
- React.createElement(SvgChevronRight, null))),
169
- React.createElement("div", { className: 'iui-right' }, pageSizeList && onPageSizeChange && !!totalRowsCount && (React.createElement(DropdownButton, { styleType: 'borderless', size: buttonSize, menuItems: function (close) {
170
- return pageSizeList.map(function (size) { return (React.createElement(MenuItem, { key: size, isSelected: size === pageSize, onClick: function () {
171
- close();
172
- onPageSizeChange(size);
173
- } }, localization.pageSizeLabel(size))); });
174
- } }, localization.rangeLabel(currentPage * pageSize + 1, Math.min(totalRowsCount, (currentPage + 1) * pageSize), totalRowsCount, isLoading))))));
175
+ React.createElement(SvgChevronRight, null)))),
176
+ React.createElement("div", { className: 'iui-right' }, showPageSizeList && (React.createElement(React.Fragment, null,
177
+ localization.rowsPerPageLabel !== null &&
178
+ paginatorWidth >= 1024 && (React.createElement("span", { className: 'iui-paginator-page-size-label' }, localization.rowsPerPageLabel)),
179
+ React.createElement(DropdownButton, { styleType: 'borderless', size: buttonSize, menuItems: function (close) {
180
+ return pageSizeList.map(function (size) { return (React.createElement(MenuItem, { key: size, isSelected: size === pageSize, onClick: function () {
181
+ close();
182
+ onPageSizeChange(size);
183
+ } }, localization.pageSizeLabel(size))); });
184
+ } }, localization.rangeLabel(currentPage * pageSize + 1, Math.min(totalRowsCount, (currentPage + 1) * pageSize), totalRowsCount, isLoading)))))));
175
185
  };
176
186
  export default TablePaginator;
@@ -1,5 +1,26 @@
1
1
  import React from 'react';
2
2
  import { CellProps, Row, TableInstance, TableState } from 'react-table';
3
+ /**
4
+ * Memoization is needed to avoid unnecessary re-renders of all rows when additional data is added when lazy-loading.
5
+ * Using `isLast` here instead of passing data length to avoid re-renders of all rows when more data is added. Now only the last row re-renders.
6
+ * Although state is not used it is needed for `React.memo` to check state that changes row state e.g. selection.
7
+ * When adding new features check whether it changes state that affects row. If it does then add equality check to `React.memo`.
8
+ */
9
+ export declare const TableRow: <T extends Record<string, unknown>>(props: {
10
+ row: Row<T>;
11
+ rowProps?: ((row: Row<T>) => React.ComponentPropsWithRef<'div'>) | undefined;
12
+ isLast: boolean;
13
+ onRowInViewport: React.MutableRefObject<((rowData: T) => void) | undefined>;
14
+ onBottomReached: React.MutableRefObject<(() => void) | undefined>;
15
+ intersectionMargin: number;
16
+ state: TableState<T>;
17
+ onClick?: ((event: React.MouseEvent, row: Row<T>) => void) | undefined;
18
+ subComponent?: ((row: Row<T>) => React.ReactNode) | undefined;
19
+ isDisabled: boolean;
20
+ tableHasSubRows: boolean;
21
+ tableInstance: TableInstance<T>;
22
+ expanderCell?: ((cellProps: CellProps<T, any>) => React.ReactNode) | undefined;
23
+ }) => JSX.Element;
3
24
  export declare const TableRowMemoized: <T extends Record<string, unknown>>(props: {
4
25
  row: Row<T>;
5
26
  rowProps?: ((row: Row<T>) => React.ComponentPropsWithRef<'div'>) | undefined;
@@ -23,7 +23,7 @@ import { TableCell } from './TableCell';
23
23
  * Although state is not used it is needed for `React.memo` to check state that changes row state e.g. selection.
24
24
  * When adding new features check whether it changes state that affects row. If it does then add equality check to `React.memo`.
25
25
  */
26
- var TableRow = function (props) {
26
+ export var TableRow = function (props) {
27
27
  var row = props.row, rowProps = props.rowProps, isLast = props.isLast, onRowInViewport = props.onRowInViewport, onBottomReached = props.onBottomReached, intersectionMargin = props.intersectionMargin, onClick = props.onClick, subComponent = props.subComponent, isDisabled = props.isDisabled, tableHasSubRows = props.tableHasSubRows, tableInstance = props.tableInstance, expanderCell = props.expanderCell;
28
28
  var onIntersect = React.useCallback(function () {
29
29
  var _a, _b;
@@ -34,7 +34,7 @@ var TableRow = function (props) {
34
34
  rootMargin: intersectionMargin + "px",
35
35
  });
36
36
  var userRowProps = rowProps === null || rowProps === void 0 ? void 0 : rowProps(row);
37
- var mergedProps = __assign(__assign(__assign({}, row.getRowProps({ style: { flex: "0 0 auto" } })), userRowProps), {
37
+ var mergedProps = __assign(__assign(__assign({}, row.getRowProps({ style: { flex: "0 0 auto", minWidth: '100%' } })), userRowProps), {
38
38
  className: cx('iui-row', {
39
39
  'iui-selected': row.isSelected,
40
40
  'iui-row-expanded': row.isExpanded && subComponent,
@@ -84,5 +84,7 @@ export var TableRowMemoized = React.memo(TableRow, function (prevProp, nextProp)
84
84
  prevProp.isDisabled === nextProp.isDisabled &&
85
85
  prevProp.rowProps === nextProp.rowProps &&
86
86
  prevProp.expanderCell === nextProp.expanderCell &&
87
- prevProp.tableHasSubRows === nextProp.tableHasSubRows;
87
+ prevProp.tableHasSubRows === nextProp.tableHasSubRows &&
88
+ !nextProp.state.columnResizing.isResizingColumn &&
89
+ !nextProp.state.isTableResizing;
88
90
  });
@@ -0,0 +1,51 @@
1
+ import { ActionType, TableState } from 'react-table';
2
+ export declare const onTableResizeStart: <T extends Record<string, unknown>>(state: TableState<T>) => {
3
+ isTableResizing: boolean;
4
+ hiddenColumns?: import("react-table").IdType<T>[] | undefined;
5
+ columnResizing: {
6
+ startX?: number | undefined;
7
+ columnWidth?: number | undefined;
8
+ nextColumnWidth?: number | undefined;
9
+ headerIdWidths?: [string, number][] | undefined;
10
+ nextHeaderIdWidths?: [string, number][] | undefined;
11
+ columnWidths: Record<string, number>;
12
+ isResizingColumn?: string | undefined;
13
+ };
14
+ columnOrder: import("react-table").IdType<T>[];
15
+ expanded: Record<import("react-table").IdType<T>, boolean>;
16
+ filters: import("react-table").Filters<T>;
17
+ globalFilter: any;
18
+ groupBy: import("react-table").IdType<T>[];
19
+ pageSize: number;
20
+ pageIndex: number;
21
+ selectedRowIds: Record<import("react-table").IdType<T>, boolean>;
22
+ rowState: Record<string, {
23
+ cellState: import("react-table").UseRowStateLocalState<T, unknown>;
24
+ }>;
25
+ sortBy: import("react-table").SortingRule<T>[];
26
+ };
27
+ export declare const onTableResizeEnd: <T extends Record<string, unknown>>(state: TableState<T>, action: ActionType) => {
28
+ isTableResizing: boolean;
29
+ columnResizing: {
30
+ columnWidths: any;
31
+ startX?: number | undefined;
32
+ columnWidth?: number | undefined;
33
+ nextColumnWidth?: number | undefined;
34
+ headerIdWidths?: [string, number][] | undefined;
35
+ nextHeaderIdWidths?: [string, number][] | undefined;
36
+ isResizingColumn?: string | undefined;
37
+ };
38
+ hiddenColumns?: import("react-table").IdType<T>[] | undefined;
39
+ columnOrder: import("react-table").IdType<T>[];
40
+ expanded: Record<import("react-table").IdType<T>, boolean>;
41
+ filters: import("react-table").Filters<T>;
42
+ globalFilter: any;
43
+ groupBy: import("react-table").IdType<T>[];
44
+ pageSize: number;
45
+ pageIndex: number;
46
+ selectedRowIds: Record<import("react-table").IdType<T>, boolean>;
47
+ rowState: Record<string, {
48
+ cellState: import("react-table").UseRowStateLocalState<T, unknown>;
49
+ }>;
50
+ sortBy: import("react-table").SortingRule<T>[];
51
+ };
@@ -0,0 +1,17 @@
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
+ export var onTableResizeStart = function (state) {
13
+ return __assign(__assign({}, state), { isTableResizing: true });
14
+ };
15
+ export var onTableResizeEnd = function (state, action) {
16
+ return __assign(__assign({}, state), { isTableResizing: false, columnResizing: __assign(__assign({}, state.columnResizing), { columnWidths: __assign({}, action.columnWidths) }) });
17
+ };
@@ -9,6 +9,16 @@ export declare const onSelectHandler: <T extends Record<string, unknown>>(newSta
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
10
  selectedRowIds: Record<string, boolean>;
11
11
  hiddenColumns?: import("react-table").IdType<T>[] | undefined;
12
+ columnResizing: {
13
+ startX?: number | undefined;
14
+ columnWidth?: number | undefined;
15
+ nextColumnWidth?: number | undefined;
16
+ headerIdWidths?: [string, number][] | undefined;
17
+ nextHeaderIdWidths?: [string, number][] | undefined;
18
+ columnWidths: Record<string, number>;
19
+ isResizingColumn?: string | undefined;
20
+ };
21
+ isTableResizing?: boolean | undefined;
12
22
  columnOrder: import("react-table").IdType<T>[];
13
23
  expanded: Record<import("react-table").IdType<T>, boolean>;
14
24
  filters: import("react-table").Filters<T>;
@@ -16,13 +26,6 @@ export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(
16
26
  groupBy: import("react-table").IdType<T>[];
17
27
  pageSize: number;
18
28
  pageIndex: number;
19
- columnResizing: {
20
- startX?: number | undefined;
21
- columnWidth: number;
22
- headerIdWidths: Record<string, number>;
23
- columnWidths: any;
24
- isResizingColumn?: string | undefined;
25
- };
26
29
  rowState: Record<string, {
27
30
  cellState: import("react-table").UseRowStateLocalState<T, unknown>;
28
31
  }>;
@@ -23,7 +23,9 @@ import { useTheme } from '../../utils';
23
23
  export var BaseFilter = function (props) {
24
24
  var children = props.children, className = props.className, style = props.style, id = props.id;
25
25
  useTheme();
26
- return (React.createElement("div", { className: cx('iui-column-filter', className), style: style, onClick: function (e) {
26
+ return (React.createElement("div", { className: cx('iui-column-filter', className), style: style,
27
+ // Prevents from triggering sort
28
+ onMouseDown: function (e) {
27
29
  e.stopPropagation();
28
30
  }, id: id }, children));
29
31
  };
@@ -48,8 +48,9 @@ export var FilterToggle = function (props) {
48
48
  close();
49
49
  }, [close, column]);
50
50
  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
- React.createElement(IconButton, __assign({ styleType: 'borderless', isActive: isVisible || column.filterValue, className: cx('iui-filter-button', className), onClick: function (e) {
52
- e.stopPropagation();
51
+ React.createElement(IconButton, __assign({ styleType: 'borderless', isActive: isVisible || column.filterValue, className: cx('iui-filter-button', className), onClick: function () {
53
52
  setIsVisible(function (v) { return !v; });
54
- } }, rest), column.filterValue ? React.createElement(SvgFilter, null) : React.createElement(SvgFilterHollow, null))))));
53
+ },
54
+ // Prevents from triggering sort
55
+ onMouseDown: function (e) { return e.stopPropagation(); } }, rest), column.filterValue ? React.createElement(SvgFilter, null) : React.createElement(SvgFilterHollow, null))))));
55
56
  };
@@ -2,3 +2,4 @@ export { EXPANDER_CELL_ID, useExpanderCell } from './useExpanderCell';
2
2
  export { SELECTION_CELL_ID, useSelectionCell } from './useSelectionCell';
3
3
  export { useSubRowFiltering } from './useSubRowFiltering';
4
4
  export { useSubRowSelection } from './useSubRowSelection';
5
+ export { useResizeColumns } from './useResizeColumns';
@@ -6,3 +6,4 @@ export { EXPANDER_CELL_ID, useExpanderCell } from './useExpanderCell';
6
6
  export { SELECTION_CELL_ID, useSelectionCell } from './useSelectionCell';
7
7
  export { useSubRowFiltering } from './useSubRowFiltering';
8
8
  export { useSubRowSelection } from './useSubRowSelection';
9
+ export { useResizeColumns } from './useResizeColumns';
@@ -0,0 +1,5 @@
1
+ import { Hooks } from 'react-table';
2
+ export declare const useResizeColumns: {
3
+ <T extends Record<string, unknown>>(ownerDocument: Document | undefined): (hooks: Hooks<T>) => void;
4
+ pluginName: string;
5
+ };