@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
@@ -45,7 +45,10 @@ var customFilterFunctions_1 = require("./filters/customFilterFunctions");
45
45
  var hooks_1 = require("./hooks");
46
46
  var actionHandlers_1 = require("./actionHandlers");
47
47
  var selectHandler_1 = require("./actionHandlers/selectHandler");
48
+ var resizeHandler_1 = require("./actionHandlers/resizeHandler");
48
49
  var singleRowSelectedAction = 'singleRowSelected';
50
+ var tableResizeStartAction = 'tableResizeStart';
51
+ var tableResizeEndAction = 'tableResizeEnd';
49
52
  /**
50
53
  * Table based on [react-table](https://react-table.tanstack.com/docs/api/overview).
51
54
  * @example
@@ -90,9 +93,9 @@ var singleRowSelectedAction = 'singleRowSelected';
90
93
  */
91
94
  var Table = function (props) {
92
95
  var _a;
93
- 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"]);
96
+ 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"]);
94
97
  (0, utils_1.useTheme)();
95
- var _k = react_1.default.useState(), ownerDocument = _k[0], setOwnerDocument = _k[1];
98
+ var _m = react_1.default.useState(), ownerDocument = _m[0], setOwnerDocument = _m[1];
96
99
  var defaultColumn = react_1.default.useMemo(function () { return ({
97
100
  maxWidth: 0,
98
101
  minWidth: 0,
@@ -127,6 +130,14 @@ var Table = function (props) {
127
130
  (0, actionHandlers_1.onSelectHandler)(newState, instance, onSelect, isRowDisabled);
128
131
  break;
129
132
  }
133
+ case tableResizeStartAction: {
134
+ newState = (0, resizeHandler_1.onTableResizeStart)(newState);
135
+ break;
136
+ }
137
+ case tableResizeEndAction: {
138
+ newState = (0, resizeHandler_1.onTableResizeEnd)(newState, action);
139
+ break;
140
+ }
130
141
  default:
131
142
  break;
132
143
  }
@@ -140,8 +151,8 @@ var Table = function (props) {
140
151
  return getSubRows ? getSubRows(item, index) : item.subRows;
141
152
  });
142
153
  }, [data, getSubRows]);
143
- var instance = (0, react_table_1.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) }), react_table_1.useFlexLayout, react_table_1.useFilters, (0, hooks_1.useSubRowFiltering)(hasAnySubRows), react_table_1.useSortBy, react_table_1.useExpanded, react_table_1.usePagination, react_table_1.useRowSelect, hooks_1.useSubRowSelection, (0, hooks_1.useExpanderCell)(subComponent, expanderCell, isRowDisabled), (0, hooks_1.useSelectionCell)(isSelectable, isRowDisabled));
144
- 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;
154
+ var instance = (0, react_table_1.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) }), react_table_1.useFlexLayout, (0, hooks_1.useResizeColumns)(ownerDocument), react_table_1.useFilters, (0, hooks_1.useSubRowFiltering)(hasAnySubRows), react_table_1.useSortBy, react_table_1.useExpanded, react_table_1.usePagination, react_table_1.useRowSelect, hooks_1.useSubRowSelection, (0, hooks_1.useExpanderCell)(subComponent, expanderCell, isRowDisabled), (0, hooks_1.useSelectionCell)(isSelectable, isRowDisabled));
155
+ 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;
145
156
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
146
157
  var key = _a[0], value = _a[1];
147
158
  if (key.startsWith('data-') || key.startsWith('aria-')) {
@@ -187,24 +198,82 @@ var Table = function (props) {
187
198
  state.pageIndex,
188
199
  state.pageSize,
189
200
  ]);
201
+ var columnRefs = react_1.default.useRef({});
202
+ var previousTableWidth = react_1.default.useRef(0);
203
+ var onTableResize = react_1.default.useCallback(function (_a) {
204
+ var width = _a.width;
205
+ if (width === previousTableWidth.current) {
206
+ return;
207
+ }
208
+ previousTableWidth.current = width;
209
+ // Update column widths when table was resized
210
+ flatHeaders.forEach(function (header) {
211
+ if (columnRefs.current[header.id]) {
212
+ header.resizeWidth = columnRefs.current[header.id].getBoundingClientRect().width;
213
+ }
214
+ });
215
+ // If no column was resized then leave table resize handling to the flexbox
216
+ if (Object.keys(state.columnResizing.columnWidths).length === 0) {
217
+ return;
218
+ }
219
+ dispatch({ type: tableResizeStartAction });
220
+ }, [dispatch, state.columnResizing.columnWidths, flatHeaders]);
221
+ var resizeRef = (0, utils_1.useResizeObserver)(onTableResize)[0];
222
+ // Flexbox handles columns resize so we take new column widths before browser repaints.
223
+ react_1.default.useLayoutEffect(function () {
224
+ if (state.isTableResizing) {
225
+ var newColumnWidths_1 = {};
226
+ flatHeaders.forEach(function (column) {
227
+ if (columnRefs.current[column.id]) {
228
+ newColumnWidths_1[column.id] = columnRefs.current[column.id].getBoundingClientRect().width;
229
+ }
230
+ });
231
+ dispatch({ type: tableResizeEndAction, columnWidths: newColumnWidths_1 });
232
+ }
233
+ });
234
+ var headerRef = react_1.default.useRef(null);
235
+ var bodyRef = react_1.default.useRef(null);
190
236
  return (react_1.default.createElement(react_1.default.Fragment, null,
191
- react_1.default.createElement("div", __assign({ ref: function (element) { return setOwnerDocument(element === null || element === void 0 ? void 0 : element.ownerDocument); }, id: id }, getTableProps({
237
+ react_1.default.createElement("div", __assign({ ref: function (element) {
238
+ setOwnerDocument(element === null || element === void 0 ? void 0 : element.ownerDocument);
239
+ if (isResizable) {
240
+ resizeRef(element);
241
+ }
242
+ }, id: id }, getTableProps({
192
243
  className: (0, classnames_1.default)('iui-table', (_a = {}, _a["iui-" + density] = density !== 'default', _a), className),
193
244
  style: style,
194
245
  }), ariaDataAttributes),
195
- react_1.default.createElement("div", { className: 'iui-table-header' }, headerGroups.slice(1).map(function (headerGroup) {
246
+ react_1.default.createElement("div", { className: 'iui-table-header', ref: headerRef }, headerGroups.slice(1).map(function (headerGroup) {
196
247
  var headerGroupProps = headerGroup.getHeaderGroupProps({
197
248
  className: 'iui-row',
198
249
  });
199
- return (react_1.default.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column) {
200
- var columnProps = column.getHeaderProps(__assign(__assign({}, column.getSortByToggleProps()), { className: (0, classnames_1.default)('iui-cell', { 'iui-actionable': column.canSort }, { 'iui-sorted': column.isSorted }, column.columnClassName), style: __assign({}, (0, utils_2.getCellStyle)(column)) }));
201
- return (react_1.default.createElement("div", __assign({}, columnProps, { key: columnProps.key, title: undefined }),
250
+ return (react_1.default.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
251
+ var _a = column.getSortByToggleProps(), onSortClick = _a.onClick, sortByProps = __rest(_a, ["onClick"]);
252
+ var columnProps = column.getHeaderProps(__assign(__assign({}, sortByProps), { className: (0, classnames_1.default)('iui-cell', { 'iui-actionable': column.canSort }, { 'iui-sorted': column.isSorted }, column.columnClassName), style: __assign({}, (0, utils_2.getCellStyle)(column, !!state.isTableResizing)) }));
253
+ return (react_1.default.createElement("div", __assign({}, columnProps, { key: columnProps.key, title: undefined, ref: function (el) {
254
+ if (el && isResizable) {
255
+ columnRefs.current[column.id] = el;
256
+ column.resizeWidth = el.getBoundingClientRect().width;
257
+ }
258
+ }, onMouseDown: onSortClick }),
202
259
  column.render('Header'),
203
260
  !isLoading && (data.length != 0 || areFiltersSet) && (react_1.default.createElement(filters_1.FilterToggle, { column: column, ownerDocument: ownerDocument })),
204
- !isLoading && data.length != 0 && column.canSort && (react_1.default.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (react_1.default.createElement(SortUp_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (react_1.default.createElement(SortDown_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true }))))));
261
+ !isLoading && data.length != 0 && column.canSort && (react_1.default.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (react_1.default.createElement(SortUp_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (react_1.default.createElement(SortDown_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true })))),
262
+ isResizable &&
263
+ column.isResizerVisible &&
264
+ index !== headerGroup.headers.length - 1 && (react_1.default.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
265
+ react_1.default.createElement("div", { className: 'iui-resizer-bar' })))));
205
266
  })));
206
267
  })),
207
- react_1.default.createElement("div", __assign({}, getTableBodyProps({ className: 'iui-table-body' })),
268
+ react_1.default.createElement("div", __assign({}, getTableBodyProps({
269
+ className: (0, classnames_1.default)('iui-table-body', {
270
+ 'iui-zebra-striping': styleType === 'zebra-rows',
271
+ }),
272
+ }), { ref: bodyRef, onScroll: function () {
273
+ if (headerRef.current && bodyRef.current) {
274
+ headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
275
+ }
276
+ } }),
208
277
  data.length !== 0 &&
209
278
  page.map(function (row) {
210
279
  prepareRow(row);
@@ -41,7 +41,7 @@ var TableCell = function (props) {
41
41
  };
42
42
  var cellElementProps = cell.getCellProps({
43
43
  className: (0, classnames_1.default)('iui-cell', cell.column.cellClassName),
44
- style: __assign(__assign({}, (0, utils_1.getCellStyle)(cell.column)), getSubRowStyle()),
44
+ style: __assign(__assign({}, (0, utils_1.getCellStyle)(cell.column, !!tableInstance.state.isTableResizing)), getSubRowStyle()),
45
45
  });
46
46
  var cellProps = __assign(__assign({}, tableInstance), { cell: cell, row: cell.row, value: cell.value, column: cell.column });
47
47
  var cellContent = (react_1.default.createElement(react_1.default.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;
@@ -50,6 +50,7 @@ var defaultLocalization = {
50
50
  previousPage: 'Previous page',
51
51
  nextPage: 'Next page',
52
52
  goToPageLabel: function (page) { return "Go to page " + page; },
53
+ rowsPerPageLabel: 'Rows per page',
53
54
  };
54
55
  /**
55
56
  * Table paginator component. Recommended to pass to the `Table` as `paginatorRenderer` prop.
@@ -94,6 +95,7 @@ var TablePaginator = function (props) {
94
95
  .map(function (_, index) { return pageButton(index); });
95
96
  }, [pageButton, totalPagesCount]);
96
97
  var _e = (0, utils_1.useOverflow)(pageList), overflowRef = _e[0], visibleCount = _e[1];
98
+ var _f = (0, utils_1.useContainerWidth)(), paginatorResizeRef = _f[0], paginatorWidth = _f[1];
97
99
  var onKeyDown = function (event) {
98
100
  // alt + arrow keys are used by browser/assistive technologies
99
101
  if (event.altKey) {
@@ -144,12 +146,17 @@ var TablePaginator = function (props) {
144
146
  endPage = totalPagesCount;
145
147
  }
146
148
  var hasNoRows = totalPagesCount === 0;
149
+ var showPagesList = totalPagesCount > 1 || isLoading;
150
+ var showPageSizeList = pageSizeList && onPageSizeChange && !!totalRowsCount;
147
151
  var ellipsis = (react_1.default.createElement("span", { className: (0, classnames_1.default)('iui-ellipsis', { 'iui-small': size === 'small' }) }, "\u2026"));
148
152
  var noRowsContent = (react_1.default.createElement(react_1.default.Fragment, null, isLoading ? (react_1.default.createElement(ProgressIndicators_1.ProgressRadial, { indeterminate: true, size: 'small' })) : (react_1.default.createElement(Buttons_1.Button, { styleType: 'borderless', disabled: true, size: buttonSize }, "1"))));
149
- return (react_1.default.createElement("div", __assign({ className: (0, classnames_1.default)('iui-paginator', className) }, rest),
153
+ if (!showPagesList && !showPageSizeList) {
154
+ return null;
155
+ }
156
+ return (react_1.default.createElement("div", __assign({ className: (0, classnames_1.default)('iui-paginator', className), ref: paginatorResizeRef }, rest),
150
157
  react_1.default.createElement("div", { className: 'iui-left' }),
151
- react_1.default.createElement("div", { className: 'iui-center', ref: overflowRef },
152
- react_1.default.createElement(Buttons_1.IconButton, { styleType: 'borderless', disabled: currentPage === 0 || hasNoRows, onClick: function () { return onPageChange(currentPage - 1); }, size: buttonSize, "aria-label": localization.previousPage },
158
+ showPagesList && (react_1.default.createElement("div", { className: 'iui-center', ref: overflowRef },
159
+ react_1.default.createElement(Buttons_1.IconButton, { styleType: 'borderless', disabled: currentPage === 0, onClick: function () { return onPageChange(currentPage - 1); }, size: buttonSize, "aria-label": localization.previousPage },
153
160
  react_1.default.createElement(ChevronLeft_1.default, null)),
154
161
  react_1.default.createElement(ButtonGroup_1.ButtonGroup, { onKeyDown: onKeyDown, ref: pageListRef }, (function () {
155
162
  if (hasNoRows) {
@@ -171,13 +178,16 @@ var TablePaginator = function (props) {
171
178
  react_1.default.createElement(ProgressIndicators_1.ProgressRadial, { indeterminate: true, size: 'small' })))));
172
179
  })()),
173
180
  react_1.default.createElement(Buttons_1.IconButton, { styleType: 'borderless', disabled: currentPage === totalPagesCount - 1 || hasNoRows, onClick: function () { return onPageChange(currentPage + 1); }, size: buttonSize, "aria-label": localization.nextPage },
174
- react_1.default.createElement(ChevronRight_1.default, null))),
175
- react_1.default.createElement("div", { className: 'iui-right' }, pageSizeList && onPageSizeChange && !!totalRowsCount && (react_1.default.createElement(Buttons_1.DropdownButton, { styleType: 'borderless', size: buttonSize, menuItems: function (close) {
176
- return pageSizeList.map(function (size) { return (react_1.default.createElement(Menu_1.MenuItem, { key: size, isSelected: size === pageSize, onClick: function () {
177
- close();
178
- onPageSizeChange(size);
179
- } }, localization.pageSizeLabel(size))); });
180
- } }, localization.rangeLabel(currentPage * pageSize + 1, Math.min(totalRowsCount, (currentPage + 1) * pageSize), totalRowsCount, isLoading))))));
181
+ react_1.default.createElement(ChevronRight_1.default, null)))),
182
+ react_1.default.createElement("div", { className: 'iui-right' }, showPageSizeList && (react_1.default.createElement(react_1.default.Fragment, null,
183
+ localization.rowsPerPageLabel !== null &&
184
+ paginatorWidth >= 1024 && (react_1.default.createElement("span", { className: 'iui-paginator-page-size-label' }, localization.rowsPerPageLabel)),
185
+ react_1.default.createElement(Buttons_1.DropdownButton, { styleType: 'borderless', size: buttonSize, menuItems: function (close) {
186
+ return pageSizeList.map(function (size) { return (react_1.default.createElement(Menu_1.MenuItem, { key: size, isSelected: size === pageSize, onClick: function () {
187
+ close();
188
+ onPageSizeChange(size);
189
+ } }, localization.pageSizeLabel(size))); });
190
+ } }, localization.rangeLabel(currentPage * pageSize + 1, Math.min(totalRowsCount, (currentPage + 1) * pageSize), totalRowsCount, isLoading)))))));
181
191
  };
182
192
  exports.TablePaginator = TablePaginator;
183
193
  exports.default = exports.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;
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.TableRowMemoized = void 0;
17
+ exports.TableRowMemoized = exports.TableRow = void 0;
18
18
  /*---------------------------------------------------------------------------------------------
19
19
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
20
20
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -40,7 +40,7 @@ var TableRow = function (props) {
40
40
  rootMargin: intersectionMargin + "px",
41
41
  });
42
42
  var userRowProps = rowProps === null || rowProps === void 0 ? void 0 : rowProps(row);
43
- var mergedProps = __assign(__assign(__assign({}, row.getRowProps({ style: { flex: "0 0 auto" } })), userRowProps), {
43
+ var mergedProps = __assign(__assign(__assign({}, row.getRowProps({ style: { flex: "0 0 auto", minWidth: '100%' } })), userRowProps), {
44
44
  className: (0, classnames_1.default)('iui-row', {
45
45
  'iui-selected': row.isSelected,
46
46
  'iui-row-expanded': row.isExpanded && subComponent,
@@ -59,6 +59,7 @@ var TableRow = function (props) {
59
59
  subComponent && (react_1.default.createElement(utils_1.WithCSSTransition, { in: row.isExpanded },
60
60
  react_1.default.createElement("div", { className: 'iui-row iui-expanded-content' }, subComponent(row))))));
61
61
  };
62
+ exports.TableRow = TableRow;
62
63
  var hasAnySelectedSubRow = function (row, selectedRowIds) {
63
64
  if (selectedRowIds === null || selectedRowIds === void 0 ? void 0 : selectedRowIds[row.id]) {
64
65
  return true;
@@ -67,7 +68,7 @@ var hasAnySelectedSubRow = function (row, selectedRowIds) {
67
68
  return hasAnySelectedSubRow(subRow, selectedRowIds);
68
69
  });
69
70
  };
70
- exports.TableRowMemoized = react_1.default.memo(TableRow, function (prevProp, nextProp) {
71
+ exports.TableRowMemoized = react_1.default.memo(exports.TableRow, function (prevProp, nextProp) {
71
72
  var _a, _b, _c, _d;
72
73
  return prevProp.isLast === nextProp.isLast &&
73
74
  prevProp.onRowInViewport === nextProp.onRowInViewport &&
@@ -90,5 +91,7 @@ exports.TableRowMemoized = react_1.default.memo(TableRow, function (prevProp, ne
90
91
  prevProp.isDisabled === nextProp.isDisabled &&
91
92
  prevProp.rowProps === nextProp.rowProps &&
92
93
  prevProp.expanderCell === nextProp.expanderCell &&
93
- prevProp.tableHasSubRows === nextProp.tableHasSubRows;
94
+ prevProp.tableHasSubRows === nextProp.tableHasSubRows &&
95
+ !nextProp.state.columnResizing.isResizingColumn &&
96
+ !nextProp.state.isTableResizing;
94
97
  });
@@ -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,22 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.onTableResizeEnd = exports.onTableResizeStart = void 0;
15
+ var onTableResizeStart = function (state) {
16
+ return __assign(__assign({}, state), { isTableResizing: true });
17
+ };
18
+ exports.onTableResizeStart = onTableResizeStart;
19
+ var onTableResizeEnd = function (state, action) {
20
+ return __assign(__assign({}, state), { isTableResizing: false, columnResizing: __assign(__assign({}, state.columnResizing), { columnWidths: __assign({}, action.columnWidths) }) });
21
+ };
22
+ exports.onTableResizeEnd = onTableResizeEnd;
@@ -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
  }>;
@@ -29,7 +29,9 @@ var utils_1 = require("../../utils");
29
29
  var BaseFilter = function (props) {
30
30
  var children = props.children, className = props.className, style = props.style, id = props.id;
31
31
  (0, utils_1.useTheme)();
32
- return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-column-filter', className), style: style, onClick: function (e) {
32
+ return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-column-filter', className), style: style,
33
+ // Prevents from triggering sort
34
+ onMouseDown: function (e) {
33
35
  e.stopPropagation();
34
36
  }, id: id }, children));
35
37
  };
@@ -54,9 +54,10 @@ var FilterToggle = function (props) {
54
54
  close();
55
55
  }, [close, column]);
56
56
  return (react_1.default.createElement(react_1.default.Fragment, null, column.canFilter && column.Filter && (react_1.default.createElement(utils_1.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 },
57
- react_1.default.createElement(Buttons_1.IconButton, __assign({ styleType: 'borderless', isActive: isVisible || column.filterValue, className: (0, classnames_1.default)('iui-filter-button', className), onClick: function (e) {
58
- e.stopPropagation();
57
+ react_1.default.createElement(Buttons_1.IconButton, __assign({ styleType: 'borderless', isActive: isVisible || column.filterValue, className: (0, classnames_1.default)('iui-filter-button', className), onClick: function () {
59
58
  setIsVisible(function (v) { return !v; });
60
- } }, rest), column.filterValue ? react_1.default.createElement(Filter_1.default, null) : react_1.default.createElement(FilterHollow_1.default, null))))));
59
+ },
60
+ // Prevents from triggering sort
61
+ onMouseDown: function (e) { return e.stopPropagation(); } }, rest), column.filterValue ? react_1.default.createElement(Filter_1.default, null) : react_1.default.createElement(FilterHollow_1.default, null))))));
61
62
  };
62
63
  exports.FilterToggle = FilterToggle;
@@ -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';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useSubRowSelection = exports.useSubRowFiltering = exports.useSelectionCell = exports.SELECTION_CELL_ID = exports.useExpanderCell = exports.EXPANDER_CELL_ID = void 0;
3
+ exports.useResizeColumns = exports.useSubRowSelection = exports.useSubRowFiltering = exports.useSelectionCell = exports.SELECTION_CELL_ID = exports.useExpanderCell = exports.EXPANDER_CELL_ID = void 0;
4
4
  /*---------------------------------------------------------------------------------------------
5
5
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
6
6
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -15,3 +15,5 @@ var useSubRowFiltering_1 = require("./useSubRowFiltering");
15
15
  Object.defineProperty(exports, "useSubRowFiltering", { enumerable: true, get: function () { return useSubRowFiltering_1.useSubRowFiltering; } });
16
16
  var useSubRowSelection_1 = require("./useSubRowSelection");
17
17
  Object.defineProperty(exports, "useSubRowSelection", { enumerable: true, get: function () { return useSubRowSelection_1.useSubRowSelection; } });
18
+ var useResizeColumns_1 = require("./useResizeColumns");
19
+ Object.defineProperty(exports, "useResizeColumns", { enumerable: true, get: function () { return useResizeColumns_1.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
+ };