@itwin/itwinui-react 1.33.1 → 1.34.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 (36) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/cjs/core/Table/Table.d.ts +5 -0
  3. package/cjs/core/Table/Table.js +8 -8
  4. package/cjs/core/Table/TableRowMemoized.js +1 -0
  5. package/cjs/core/Table/actionHandlers/resizeHandler.d.ts +2 -0
  6. package/cjs/core/Table/actionHandlers/selectHandler.d.ts +1 -0
  7. package/cjs/core/Table/filters/BaseFilter.js +1 -1
  8. package/cjs/core/Table/filters/FilterToggle.js +4 -4
  9. package/cjs/core/Table/hooks/index.d.ts +1 -0
  10. package/cjs/core/Table/hooks/index.js +3 -1
  11. package/cjs/core/Table/hooks/useColumnDragAndDrop.d.ts +2 -0
  12. package/cjs/core/Table/hooks/useColumnDragAndDrop.js +120 -0
  13. package/cjs/core/Table/hooks/useExpanderCell.js +1 -0
  14. package/cjs/core/Table/hooks/useResizeColumns.js +8 -4
  15. package/cjs/core/Table/hooks/useSelectionCell.js +1 -0
  16. package/cjs/core/ToggleSwitch/ToggleSwitch.js +13 -10
  17. package/cjs/core/UserIcon/UserIcon.js +1 -10
  18. package/cjs/types/react-table-config.d.ts +7 -0
  19. package/esm/core/Table/Table.d.ts +5 -0
  20. package/esm/core/Table/Table.js +10 -10
  21. package/esm/core/Table/TableRowMemoized.js +1 -0
  22. package/esm/core/Table/actionHandlers/resizeHandler.d.ts +2 -0
  23. package/esm/core/Table/actionHandlers/selectHandler.d.ts +1 -0
  24. package/esm/core/Table/filters/BaseFilter.js +1 -1
  25. package/esm/core/Table/filters/FilterToggle.js +4 -4
  26. package/esm/core/Table/hooks/index.d.ts +1 -0
  27. package/esm/core/Table/hooks/index.js +1 -0
  28. package/esm/core/Table/hooks/useColumnDragAndDrop.d.ts +2 -0
  29. package/esm/core/Table/hooks/useColumnDragAndDrop.js +116 -0
  30. package/esm/core/Table/hooks/useExpanderCell.js +1 -0
  31. package/esm/core/Table/hooks/useResizeColumns.js +8 -4
  32. package/esm/core/Table/hooks/useSelectionCell.js +1 -0
  33. package/esm/core/ToggleSwitch/ToggleSwitch.js +13 -10
  34. package/esm/core/UserIcon/UserIcon.js +1 -10
  35. package/esm/types/react-table-config.d.ts +7 -0
  36. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.34.0](https://www.github.com/iTwin/iTwinUI-react/compare/v1.33.1...v1.34.0) (2022-03-22)
4
+
5
+ ### What's new
6
+
7
+ * **Table:** support for draggable columns ([#561](https://www.github.com/iTwin/iTwinUI-react/issues/561)) ([0e741f5](https://www.github.com/iTwin/iTwinUI-react/commit/0e741f5c0838996a5f45c57abedf41daeef652d4))
8
+
9
+ ### Fixes
10
+
11
+ * **ToggleSwitch:** updated toggle switch styles through css package ([#592](https://www.github.com/iTwin/iTwinUI-react/issues/592)) ([3a0be35](https://www.github.com/iTwin/iTwinUI-react/commit/3a0be355d4363fe7d704c3fd6f975c509c65da2b))
12
+ * **UserIcon:** busy status now also shows an icon
13
+
3
14
  ### [1.33.1](https://www.github.com/iTwin/iTwinUI-react/compare/v1.33.0...v1.33.1) (2022-03-18)
4
15
 
5
16
  ### Fixes
@@ -170,6 +170,11 @@ export declare type TableProps<T extends Record<string, unknown> = Record<string
170
170
  * @beta
171
171
  */
172
172
  enableVirtualization?: boolean;
173
+ /**
174
+ * Flag whether columns can be reordered.
175
+ * @default false
176
+ */
177
+ enableColumnReordering?: boolean;
173
178
  } & Omit<CommonProps, 'title'>;
174
179
  /**
175
180
  * Table based on [react-table](https://react-table.tanstack.com/docs/api/overview).
@@ -94,9 +94,9 @@ var tableResizeEndAction = 'tableResizeEnd';
94
94
  */
95
95
  var Table = function (props) {
96
96
  var _a;
97
- 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, _m = props.enableVirtualization, enableVirtualization = _m === void 0 ? false : _m, 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", "enableVirtualization"]);
97
+ 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, _m = props.enableVirtualization, enableVirtualization = _m === void 0 ? false : _m, _o = props.enableColumnReordering, enableColumnReordering = _o === void 0 ? false : _o, 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", "enableVirtualization", "enableColumnReordering"]);
98
98
  (0, utils_1.useTheme)();
99
- var _o = react_1.default.useState(), ownerDocument = _o[0], setOwnerDocument = _o[1];
99
+ var _p = react_1.default.useState(), ownerDocument = _p[0], setOwnerDocument = _p[1];
100
100
  var defaultColumn = react_1.default.useMemo(function () { return ({
101
101
  maxWidth: 0,
102
102
  minWidth: 0,
@@ -152,7 +152,7 @@ var Table = function (props) {
152
152
  return getSubRows ? getSubRows(item, index) : item.subRows;
153
153
  });
154
154
  }, [data, getSubRows]);
155
- 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 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), react_table_1.useColumnOrder, (0, hooks_1.useColumnDragAndDrop)(enableColumnReordering));
156
156
  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;
157
157
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
158
158
  var key = _a[0], value = _a[1];
@@ -266,21 +266,21 @@ var Table = function (props) {
266
266
  className: 'iui-row',
267
267
  });
268
268
  return (react_1.default.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
269
- var _a = column.getSortByToggleProps(), onSortClick = _a.onClick, sortByProps = __rest(_a, ["onClick"]);
270
- 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)) }));
271
- return (react_1.default.createElement("div", __assign({}, columnProps, { key: columnProps.key, title: undefined, ref: function (el) {
269
+ 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, !!state.isTableResizing)) }));
270
+ return (react_1.default.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
272
271
  if (el && isResizable) {
273
272
  columnRefs.current[column.id] = el;
274
273
  column.resizeWidth = el.getBoundingClientRect().width;
275
274
  }
276
- }, onMouseDown: onSortClick }),
275
+ } }),
277
276
  column.render('Header'),
278
277
  !isLoading && (data.length != 0 || areFiltersSet) && (react_1.default.createElement(filters_1.FilterToggle, { column: column, ownerDocument: ownerDocument })),
279
278
  !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 })))),
280
279
  isResizable &&
281
280
  column.isResizerVisible &&
282
281
  index !== headerGroup.headers.length - 1 && (react_1.default.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
283
- react_1.default.createElement("div", { className: 'iui-resizer-bar' })))));
282
+ react_1.default.createElement("div", { className: 'iui-resizer-bar' }))),
283
+ enableColumnReordering && !column.disableReordering && (react_1.default.createElement("div", { className: 'iui-reorder-bar' }))));
284
284
  })));
285
285
  })),
286
286
  react_1.default.createElement("div", __assign({}, getTableBodyProps({
@@ -92,6 +92,7 @@ exports.TableRowMemoized = react_1.default.memo(exports.TableRow, function (prev
92
92
  prevProp.rowProps === nextProp.rowProps &&
93
93
  prevProp.expanderCell === nextProp.expanderCell &&
94
94
  prevProp.tableHasSubRows === nextProp.tableHasSubRows &&
95
+ prevProp.state.columnOrder === nextProp.state.columnOrder &&
95
96
  !nextProp.state.columnResizing.isResizingColumn &&
96
97
  !nextProp.state.isTableResizing;
97
98
  });
@@ -11,6 +11,7 @@ export declare const onTableResizeStart: <T extends Record<string, unknown>>(sta
11
11
  columnWidths: Record<string, number>;
12
12
  isResizingColumn?: string | undefined;
13
13
  };
14
+ columnReorderStartIndex: number;
14
15
  columnOrder: import("react-table").IdType<T>[];
15
16
  expanded: Record<import("react-table").IdType<T>, boolean>;
16
17
  filters: import("react-table").Filters<T>;
@@ -36,6 +37,7 @@ export declare const onTableResizeEnd: <T extends Record<string, unknown>>(state
36
37
  isResizingColumn?: string | undefined;
37
38
  };
38
39
  hiddenColumns?: import("react-table").IdType<T>[] | undefined;
40
+ columnReorderStartIndex: number;
39
41
  columnOrder: import("react-table").IdType<T>[];
40
42
  expanded: Record<import("react-table").IdType<T>, boolean>;
41
43
  filters: import("react-table").Filters<T>;
@@ -19,6 +19,7 @@ export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(
19
19
  isResizingColumn?: string | undefined;
20
20
  };
21
21
  isTableResizing?: boolean | undefined;
22
+ columnReorderStartIndex: number;
22
23
  columnOrder: import("react-table").IdType<T>[];
23
24
  expanded: Record<import("react-table").IdType<T>, boolean>;
24
25
  filters: import("react-table").Filters<T>;
@@ -31,7 +31,7 @@ var BaseFilter = function (props) {
31
31
  (0, utils_1.useTheme)();
32
32
  return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-column-filter', className), style: style,
33
33
  // Prevents from triggering sort
34
- onMouseDown: function (e) {
34
+ onClick: function (e) {
35
35
  e.stopPropagation();
36
36
  }, id: id }, children));
37
37
  };
@@ -54,10 +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 () {
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
58
  setIsVisible(function (v) { return !v; });
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))))));
59
+ // Prevents from triggering sort
60
+ e.stopPropagation();
61
+ } }, rest), column.filterValue ? react_1.default.createElement(Filter_1.default, null) : react_1.default.createElement(FilterHollow_1.default, null))))));
62
62
  };
63
63
  exports.FilterToggle = FilterToggle;
@@ -3,3 +3,4 @@ export { SELECTION_CELL_ID, useSelectionCell } from './useSelectionCell';
3
3
  export { useSubRowFiltering } from './useSubRowFiltering';
4
4
  export { useSubRowSelection } from './useSubRowSelection';
5
5
  export { useResizeColumns } from './useResizeColumns';
6
+ export { useColumnDragAndDrop } from './useColumnDragAndDrop';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useResizeColumns = exports.useSubRowSelection = exports.useSubRowFiltering = exports.useSelectionCell = exports.SELECTION_CELL_ID = exports.useExpanderCell = exports.EXPANDER_CELL_ID = void 0;
3
+ exports.useColumnDragAndDrop = 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.
@@ -17,3 +17,5 @@ var useSubRowSelection_1 = require("./useSubRowSelection");
17
17
  Object.defineProperty(exports, "useSubRowSelection", { enumerable: true, get: function () { return useSubRowSelection_1.useSubRowSelection; } });
18
18
  var useResizeColumns_1 = require("./useResizeColumns");
19
19
  Object.defineProperty(exports, "useResizeColumns", { enumerable: true, get: function () { return useResizeColumns_1.useResizeColumns; } });
20
+ var useColumnDragAndDrop_1 = require("./useColumnDragAndDrop");
21
+ Object.defineProperty(exports, "useColumnDragAndDrop", { enumerable: true, get: function () { return useColumnDragAndDrop_1.useColumnDragAndDrop; } });
@@ -0,0 +1,2 @@
1
+ import { Hooks } from 'react-table';
2
+ export declare const useColumnDragAndDrop: <T extends Record<string, unknown>>(isEnabled: boolean) => (hooks: Hooks<T>) => void;
@@ -0,0 +1,120 @@
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
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
14
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
15
+ if (ar || !(i in from)) {
16
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
17
+ ar[i] = from[i];
18
+ }
19
+ }
20
+ return to.concat(ar || Array.prototype.slice.call(from));
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.useColumnDragAndDrop = void 0;
24
+ var react_table_1 = require("react-table");
25
+ var REORDER_ACTIONS = {
26
+ columnDragStart: 'columnDragStart',
27
+ columnDragEnd: 'columnDragEnd',
28
+ };
29
+ var useColumnDragAndDrop = function (isEnabled) { return function (hooks) {
30
+ hooks.getDragAndDropProps = [defaultGetDragAndDropProps(isEnabled)];
31
+ hooks.stateReducers.push(reducer);
32
+ hooks.useInstance.push(useInstance);
33
+ }; };
34
+ exports.useColumnDragAndDrop = useColumnDragAndDrop;
35
+ var defaultGetDragAndDropProps = function (isEnabled) { return function (props, _a) {
36
+ var instance = _a.instance, header = _a.header;
37
+ if (!isEnabled || header.disableReordering) {
38
+ return props;
39
+ }
40
+ var onDragStart = function () {
41
+ instance.dispatch({
42
+ type: REORDER_ACTIONS.columnDragStart,
43
+ columnIndex: instance.flatHeaders.indexOf(header),
44
+ });
45
+ };
46
+ var setOnDragColumnStyle = function (event, position) {
47
+ var columnElement = event.currentTarget;
48
+ columnElement.classList.remove('iui-reorder-column-right');
49
+ columnElement.classList.remove('iui-reorder-column-left');
50
+ if (position === 'left') {
51
+ columnElement.classList.add('iui-reorder-column-left');
52
+ }
53
+ else if (position === 'right') {
54
+ columnElement.classList.add('iui-reorder-column-right');
55
+ }
56
+ };
57
+ var reorderColumns = function (tableColumns, srcIndex, dstIndex) {
58
+ var newTableColumns = __spreadArray([], tableColumns, true);
59
+ var removed = newTableColumns.splice(srcIndex, 1)[0];
60
+ newTableColumns.splice(dstIndex, 0, removed);
61
+ return newTableColumns;
62
+ };
63
+ var onDragOver = function (event) {
64
+ event.preventDefault();
65
+ var headerIndex = instance.flatHeaders.indexOf(header);
66
+ if (instance.state.columnReorderStartIndex !== headerIndex) {
67
+ setOnDragColumnStyle(event, instance.state.columnReorderStartIndex > headerIndex ? 'left' : 'right');
68
+ }
69
+ };
70
+ var onDragLeave = function (event) {
71
+ setOnDragColumnStyle(event);
72
+ };
73
+ var onDrop = function (event) {
74
+ event.preventDefault();
75
+ setOnDragColumnStyle(event);
76
+ var columnIds = instance.flatHeaders.map(function (x) { return x.id; });
77
+ var srcIndex = instance.state.columnReorderStartIndex;
78
+ var dstIndex = columnIds.findIndex(function (x) { return x === header.id; });
79
+ if (srcIndex === dstIndex || srcIndex === -1 || dstIndex === -1) {
80
+ return;
81
+ }
82
+ instance.setColumnOrder(reorderColumns(columnIds, srcIndex, dstIndex));
83
+ instance.dispatch({
84
+ type: REORDER_ACTIONS.columnDragEnd,
85
+ columnIndex: -1,
86
+ });
87
+ };
88
+ return [
89
+ props,
90
+ {
91
+ draggable: true,
92
+ onDragStart: onDragStart,
93
+ onDragOver: onDragOver,
94
+ onDragLeave: onDragLeave,
95
+ onDrop: onDrop,
96
+ },
97
+ ];
98
+ }; };
99
+ var reducer = function (newState, action) {
100
+ switch (action.type) {
101
+ case react_table_1.actions.init:
102
+ return __assign(__assign({}, newState), { columnReorderStartIndex: -1 });
103
+ case REORDER_ACTIONS.columnDragStart:
104
+ return __assign(__assign({}, newState), { columnReorderStartIndex: action.columnIndex });
105
+ case REORDER_ACTIONS.columnDragEnd:
106
+ return __assign(__assign({}, newState), { columnReorderStartIndex: -1 });
107
+ default:
108
+ return newState;
109
+ }
110
+ };
111
+ var useInstance = function (instance) {
112
+ var flatHeaders = instance.flatHeaders, getHooks = instance.getHooks;
113
+ var getInstance = (0, react_table_1.useGetLatest)(instance);
114
+ flatHeaders.forEach(function (header) {
115
+ header.getDragAndDropProps = (0, react_table_1.makePropGetter)(getHooks().getDragAndDropProps, {
116
+ instance: getInstance(),
117
+ header: header,
118
+ });
119
+ });
120
+ };
@@ -35,6 +35,7 @@ var useExpanderCell = function (subComponent, expanderCell, isRowDisabled) { ret
35
35
  maxWidth: 48,
36
36
  columnClassName: 'iui-slot',
37
37
  cellClassName: 'iui-slot',
38
+ disableReordering: true,
38
39
  Cell: function (props) {
39
40
  var row = props.row;
40
41
  if (!subComponent(row)) {
@@ -112,16 +112,20 @@ var defaultGetResizerProps = function (ownerDocument) { return function (props,
112
112
  return [
113
113
  props,
114
114
  {
115
- onMouseDown: function (e) {
116
- e.persist();
115
+ onClick: function (e) {
117
116
  // Prevents from triggering sort
118
117
  e.stopPropagation();
118
+ },
119
+ onMouseDown: function (e) {
120
+ e.persist();
121
+ // Prevents from triggering drag'n'drop
122
+ e.preventDefault();
119
123
  onResizeStart(e, header);
120
124
  },
121
125
  onTouchStart: function (e) {
122
126
  e.persist();
123
- // Prevents from triggering sort
124
- e.stopPropagation();
127
+ // Prevents from triggering drag'n'drop
128
+ e.preventDefault();
125
129
  onResizeStart(e, header);
126
130
  },
127
131
  style: {
@@ -45,6 +45,7 @@ var useSelectionCell = function (isSelectable, isRowDisabled) { return function
45
45
  maxWidth: 48,
46
46
  columnClassName: 'iui-slot',
47
47
  cellClassName: 'iui-slot',
48
+ disableReordering: true,
48
49
  Header: function (_a) {
49
50
  var getToggleAllRowsSelectedProps = _a.getToggleAllRowsSelectedProps, rows = _a.rows, initialRows = _a.initialRows, state = _a.state;
50
51
  var disabled = rows.every(function (row) { return isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original); });
@@ -57,20 +57,23 @@ exports.ToggleSwitch = react_1.default.forwardRef(function (props, ref) {
57
57
  (0, utils_1.useTheme)();
58
58
  var inputElementRef = react_1.default.useRef(null);
59
59
  var refs = (0, utils_1.useMergedRefs)(inputElementRef, ref);
60
+ var WrapperComponent = label ? 'label' : 'div';
60
61
  react_1.default.useEffect(function () {
61
62
  if (inputElementRef.current && setFocus) {
62
63
  inputElementRef.current.focus();
63
64
  }
64
65
  }, [setFocus]);
65
- return (react_1.default.createElement("label", { className: (0, classnames_1.default)('iui-toggle-switch', { 'iui-disabled': disabled }, className), style: style },
66
- react_1.default.createElement("input", __assign({ type: 'checkbox', disabled: disabled, ref: refs }, rest)),
67
- labelPosition === 'left' && label && (react_1.default.createElement("span", { className: 'iui-label' }, label)),
68
- react_1.default.createElement("span", { className: 'iui-toggle' },
69
- icon &&
70
- react_1.default.cloneElement(icon, {
71
- className: (0, classnames_1.default)('iui-icon', icon.props.className),
72
- }),
73
- react_1.default.createElement("span", { className: 'iui-handle' })),
74
- labelPosition === 'right' && label && (react_1.default.createElement("span", { className: 'iui-label' }, label))));
66
+ return (react_1.default.createElement(WrapperComponent, { className: (0, classnames_1.default)('iui-toggle-switch-wrapper', {
67
+ 'iui-disabled': disabled,
68
+ 'iui-label-on-right': label && labelPosition === 'right',
69
+ 'iui-label-on-left': label && labelPosition === 'left',
70
+ }, className), style: style },
71
+ react_1.default.createElement("input", __assign({ className: 'iui-toggle-switch', type: 'checkbox', role: 'switch', disabled: disabled, ref: refs }, rest)),
72
+ icon &&
73
+ react_1.default.cloneElement(icon, {
74
+ className: (0, classnames_1.default)('iui-toggle-switch-icon', icon.props.className),
75
+ 'aria-hidden': true,
76
+ }),
77
+ label && react_1.default.createElement("span", { className: 'iui-toggle-switch-label' }, label)));
75
78
  });
76
79
  exports.default = exports.ToggleSwitch;
@@ -30,9 +30,6 @@ exports.UserIcon = exports.defaultStatusTitles = void 0;
30
30
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
31
31
  * See LICENSE.md in the project root for license terms and full copyright notice.
32
32
  *--------------------------------------------------------------------------------------------*/
33
- var Away_1 = __importDefault(require("@itwin/itwinui-icons-react/cjs/icons/Away"));
34
- var Checkmark_1 = __importDefault(require("@itwin/itwinui-icons-react/cjs/icons/Checkmark"));
35
- var CloseSmall_1 = __importDefault(require("@itwin/itwinui-icons-react/cjs/icons/CloseSmall"));
36
33
  var classnames_1 = __importDefault(require("classnames"));
37
34
  var react_1 = __importDefault(require("react"));
38
35
  var utils_1 = require("../utils");
@@ -63,17 +60,11 @@ var UserIcon = function (props) {
63
60
  var _c = props.size, size = _c === void 0 ? 'small' : _c, status = props.status, abbreviation = props.abbreviation, image = props.image, _d = props.backgroundColor, backgroundColor = _d === void 0 ? 'white' : _d, title = props.title, translatedStatusTitles = props.translatedStatusTitles, className = props.className, style = props.style, rest = __rest(props, ["size", "status", "abbreviation", "image", "backgroundColor", "title", "translatedStatusTitles", "className", "style"]);
64
61
  (0, utils_1.useTheme)();
65
62
  var statusTitles = __assign(__assign({}, exports.defaultStatusTitles), translatedStatusTitles);
66
- var iconMap = {
67
- away: react_1.default.createElement(Away_1.default, { className: 'iui-status-symbol', "aria-hidden": true }),
68
- offline: react_1.default.createElement(CloseSmall_1.default, { className: 'iui-status-symbol', "aria-hidden": true }),
69
- online: react_1.default.createElement(Checkmark_1.default, { className: 'iui-status-symbol', "aria-hidden": true }),
70
- busy: react_1.default.createElement(react_1.default.Fragment, null),
71
- };
72
63
  return (react_1.default.createElement("span", __assign({ className: (0, classnames_1.default)('iui-user-icon', (_a = {}, _a["iui-" + size] = size !== 'medium', _a), className), title: title, style: style }, rest), image !== null && image !== void 0 ? image : (react_1.default.createElement("abbr", { className: 'iui-initials', style: { backgroundColor: backgroundColor } }, abbreviation === null || abbreviation === void 0 ? void 0 : abbreviation.substring(0, 2))),
73
64
  react_1.default.createElement("span", { className: 'iui-stroke' }),
74
65
  status && (react_1.default.createElement("span", { title: statusTitles[status], className: (0, classnames_1.default)('iui-status', (_b = {},
75
66
  _b["iui-" + status] = !!status,
76
- _b)), "aria-label": statusTitles[status] }, iconMap[status]))));
67
+ _b)), "aria-label": statusTitles[status] }))));
77
68
  };
78
69
  exports.UserIcon = UserIcon;
79
70
  exports.default = exports.UserIcon;
@@ -32,6 +32,7 @@ declare module 'react-table' {
32
32
  isResizingColumn?: string;
33
33
  };
34
34
  isTableResizing?: boolean;
35
+ columnReorderStartIndex: number;
35
36
  }
36
37
  interface ColumnInterface<D extends object = {}> extends UseSortByColumnOptions<D>, UseFiltersColumnOptions<D>, UseResizeColumnsColumnOptions<D> {
37
38
  /**
@@ -67,11 +68,17 @@ declare module 'react-table' {
67
68
  * }
68
69
  */
69
70
  cellRenderer?: (props: CellRendererProps<D>) => React.ReactNode;
71
+ /**
72
+ * If true, column can't be reordered.
73
+ * @default false
74
+ */
75
+ disableReordering?: boolean;
70
76
  }
71
77
  interface ColumnInstance<D extends object = {}> extends UseFiltersColumnProps<D>, UseGroupByColumnProps<D>, UseResizeColumnsColumnProps<D>, UseSortByColumnProps<D> {
72
78
  originalWidth: number;
73
79
  resizeWidth?: number;
74
80
  isResizerVisible?: boolean;
81
+ getDragAndDropProps: () => TableKeyedProps;
75
82
  }
76
83
  interface Cell<D extends object = {}> extends UseGroupByCellProps<D>, UseRowStateCellProps<D> {
77
84
  }
@@ -170,6 +170,11 @@ export declare type TableProps<T extends Record<string, unknown> = Record<string
170
170
  * @beta
171
171
  */
172
172
  enableVirtualization?: boolean;
173
+ /**
174
+ * Flag whether columns can be reordered.
175
+ * @default false
176
+ */
177
+ enableColumnReordering?: boolean;
173
178
  } & Omit<CommonProps, 'title'>;
174
179
  /**
175
180
  * Table based on [react-table](https://react-table.tanstack.com/docs/api/overview).
@@ -26,7 +26,7 @@ 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, } from 'react-table';
29
+ import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, useColumnOrder, } from 'react-table';
30
30
  import { ProgressRadial } from '../ProgressIndicators';
31
31
  import { useTheme, useResizeObserver } from '../utils';
32
32
  import '@itwin/itwinui-css/css/table.css';
@@ -36,7 +36,7 @@ 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, useResizeColumns, } from './hooks';
39
+ import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, useColumnDragAndDrop, } from './hooks';
40
40
  import { onExpandHandler, onFilterHandler, onSelectHandler, } from './actionHandlers';
41
41
  import { onSingleSelectHandler } from './actionHandlers/selectHandler';
42
42
  import { onTableResizeEnd, onTableResizeStart, } from './actionHandlers/resizeHandler';
@@ -88,9 +88,9 @@ var tableResizeEndAction = 'tableResizeEnd';
88
88
  */
89
89
  export var Table = function (props) {
90
90
  var _a;
91
- 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, _m = props.enableVirtualization, enableVirtualization = _m === void 0 ? false : _m, 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", "enableVirtualization"]);
91
+ 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, _m = props.enableVirtualization, enableVirtualization = _m === void 0 ? false : _m, _o = props.enableColumnReordering, enableColumnReordering = _o === void 0 ? false : _o, 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", "enableVirtualization", "enableColumnReordering"]);
92
92
  useTheme();
93
- var _o = React.useState(), ownerDocument = _o[0], setOwnerDocument = _o[1];
93
+ var _p = React.useState(), ownerDocument = _p[0], setOwnerDocument = _p[1];
94
94
  var defaultColumn = React.useMemo(function () { return ({
95
95
  maxWidth: 0,
96
96
  minWidth: 0,
@@ -146,7 +146,7 @@ export var Table = function (props) {
146
146
  return getSubRows ? getSubRows(item, index) : item.subRows;
147
147
  });
148
148
  }, [data, getSubRows]);
149
- 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 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), useColumnOrder, useColumnDragAndDrop(enableColumnReordering));
150
150
  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;
151
151
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
152
152
  var key = _a[0], value = _a[1];
@@ -260,21 +260,21 @@ export var Table = function (props) {
260
260
  className: 'iui-row',
261
261
  });
262
262
  return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
263
- var _a = column.getSortByToggleProps(), onSortClick = _a.onClick, sortByProps = __rest(_a, ["onClick"]);
264
- 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)) }));
265
- return (React.createElement("div", __assign({}, columnProps, { key: columnProps.key, title: undefined, ref: function (el) {
263
+ 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, !!state.isTableResizing)) }));
264
+ return (React.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
266
265
  if (el && isResizable) {
267
266
  columnRefs.current[column.id] = el;
268
267
  column.resizeWidth = el.getBoundingClientRect().width;
269
268
  }
270
- }, onMouseDown: onSortClick }),
269
+ } }),
271
270
  column.render('Header'),
272
271
  !isLoading && (data.length != 0 || areFiltersSet) && (React.createElement(FilterToggle, { column: column, ownerDocument: ownerDocument })),
273
272
  !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 })))),
274
273
  isResizable &&
275
274
  column.isResizerVisible &&
276
275
  index !== headerGroup.headers.length - 1 && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
277
- React.createElement("div", { className: 'iui-resizer-bar' })))));
276
+ React.createElement("div", { className: 'iui-resizer-bar' }))),
277
+ enableColumnReordering && !column.disableReordering && (React.createElement("div", { className: 'iui-reorder-bar' }))));
278
278
  })));
279
279
  })),
280
280
  React.createElement("div", __assign({}, getTableBodyProps({
@@ -85,6 +85,7 @@ export var TableRowMemoized = React.memo(TableRow, function (prevProp, nextProp)
85
85
  prevProp.rowProps === nextProp.rowProps &&
86
86
  prevProp.expanderCell === nextProp.expanderCell &&
87
87
  prevProp.tableHasSubRows === nextProp.tableHasSubRows &&
88
+ prevProp.state.columnOrder === nextProp.state.columnOrder &&
88
89
  !nextProp.state.columnResizing.isResizingColumn &&
89
90
  !nextProp.state.isTableResizing;
90
91
  });
@@ -11,6 +11,7 @@ export declare const onTableResizeStart: <T extends Record<string, unknown>>(sta
11
11
  columnWidths: Record<string, number>;
12
12
  isResizingColumn?: string | undefined;
13
13
  };
14
+ columnReorderStartIndex: number;
14
15
  columnOrder: import("react-table").IdType<T>[];
15
16
  expanded: Record<import("react-table").IdType<T>, boolean>;
16
17
  filters: import("react-table").Filters<T>;
@@ -36,6 +37,7 @@ export declare const onTableResizeEnd: <T extends Record<string, unknown>>(state
36
37
  isResizingColumn?: string | undefined;
37
38
  };
38
39
  hiddenColumns?: import("react-table").IdType<T>[] | undefined;
40
+ columnReorderStartIndex: number;
39
41
  columnOrder: import("react-table").IdType<T>[];
40
42
  expanded: Record<import("react-table").IdType<T>, boolean>;
41
43
  filters: import("react-table").Filters<T>;
@@ -19,6 +19,7 @@ export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(
19
19
  isResizingColumn?: string | undefined;
20
20
  };
21
21
  isTableResizing?: boolean | undefined;
22
+ columnReorderStartIndex: number;
22
23
  columnOrder: import("react-table").IdType<T>[];
23
24
  expanded: Record<import("react-table").IdType<T>, boolean>;
24
25
  filters: import("react-table").Filters<T>;
@@ -25,7 +25,7 @@ export var BaseFilter = function (props) {
25
25
  useTheme();
26
26
  return (React.createElement("div", { className: cx('iui-column-filter', className), style: style,
27
27
  // Prevents from triggering sort
28
- onMouseDown: function (e) {
28
+ onClick: function (e) {
29
29
  e.stopPropagation();
30
30
  }, id: id }, children));
31
31
  };
@@ -48,9 +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 () {
51
+ React.createElement(IconButton, __assign({ styleType: 'borderless', isActive: isVisible || column.filterValue, className: cx('iui-filter-button', className), onClick: function (e) {
52
52
  setIsVisible(function (v) { return !v; });
53
- },
54
- // Prevents from triggering sort
55
- onMouseDown: function (e) { return e.stopPropagation(); } }, rest), column.filterValue ? React.createElement(SvgFilter, null) : React.createElement(SvgFilterHollow, null))))));
53
+ // Prevents from triggering sort
54
+ e.stopPropagation();
55
+ } }, rest), column.filterValue ? React.createElement(SvgFilter, null) : React.createElement(SvgFilterHollow, null))))));
56
56
  };
@@ -3,3 +3,4 @@ export { SELECTION_CELL_ID, useSelectionCell } from './useSelectionCell';
3
3
  export { useSubRowFiltering } from './useSubRowFiltering';
4
4
  export { useSubRowSelection } from './useSubRowSelection';
5
5
  export { useResizeColumns } from './useResizeColumns';
6
+ export { useColumnDragAndDrop } from './useColumnDragAndDrop';
@@ -7,3 +7,4 @@ export { SELECTION_CELL_ID, useSelectionCell } from './useSelectionCell';
7
7
  export { useSubRowFiltering } from './useSubRowFiltering';
8
8
  export { useSubRowSelection } from './useSubRowSelection';
9
9
  export { useResizeColumns } from './useResizeColumns';
10
+ export { useColumnDragAndDrop } from './useColumnDragAndDrop';
@@ -0,0 +1,2 @@
1
+ import { Hooks } from 'react-table';
2
+ export declare const useColumnDragAndDrop: <T extends Record<string, unknown>>(isEnabled: boolean) => (hooks: Hooks<T>) => void;
@@ -0,0 +1,116 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
13
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
14
+ if (ar || !(i in from)) {
15
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
16
+ ar[i] = from[i];
17
+ }
18
+ }
19
+ return to.concat(ar || Array.prototype.slice.call(from));
20
+ };
21
+ import { actions, makePropGetter, useGetLatest, } from 'react-table';
22
+ var REORDER_ACTIONS = {
23
+ columnDragStart: 'columnDragStart',
24
+ columnDragEnd: 'columnDragEnd',
25
+ };
26
+ export var useColumnDragAndDrop = function (isEnabled) { return function (hooks) {
27
+ hooks.getDragAndDropProps = [defaultGetDragAndDropProps(isEnabled)];
28
+ hooks.stateReducers.push(reducer);
29
+ hooks.useInstance.push(useInstance);
30
+ }; };
31
+ var defaultGetDragAndDropProps = function (isEnabled) { return function (props, _a) {
32
+ var instance = _a.instance, header = _a.header;
33
+ if (!isEnabled || header.disableReordering) {
34
+ return props;
35
+ }
36
+ var onDragStart = function () {
37
+ instance.dispatch({
38
+ type: REORDER_ACTIONS.columnDragStart,
39
+ columnIndex: instance.flatHeaders.indexOf(header),
40
+ });
41
+ };
42
+ var setOnDragColumnStyle = function (event, position) {
43
+ var columnElement = event.currentTarget;
44
+ columnElement.classList.remove('iui-reorder-column-right');
45
+ columnElement.classList.remove('iui-reorder-column-left');
46
+ if (position === 'left') {
47
+ columnElement.classList.add('iui-reorder-column-left');
48
+ }
49
+ else if (position === 'right') {
50
+ columnElement.classList.add('iui-reorder-column-right');
51
+ }
52
+ };
53
+ var reorderColumns = function (tableColumns, srcIndex, dstIndex) {
54
+ var newTableColumns = __spreadArray([], tableColumns, true);
55
+ var removed = newTableColumns.splice(srcIndex, 1)[0];
56
+ newTableColumns.splice(dstIndex, 0, removed);
57
+ return newTableColumns;
58
+ };
59
+ var onDragOver = function (event) {
60
+ event.preventDefault();
61
+ var headerIndex = instance.flatHeaders.indexOf(header);
62
+ if (instance.state.columnReorderStartIndex !== headerIndex) {
63
+ setOnDragColumnStyle(event, instance.state.columnReorderStartIndex > headerIndex ? 'left' : 'right');
64
+ }
65
+ };
66
+ var onDragLeave = function (event) {
67
+ setOnDragColumnStyle(event);
68
+ };
69
+ var onDrop = function (event) {
70
+ event.preventDefault();
71
+ setOnDragColumnStyle(event);
72
+ var columnIds = instance.flatHeaders.map(function (x) { return x.id; });
73
+ var srcIndex = instance.state.columnReorderStartIndex;
74
+ var dstIndex = columnIds.findIndex(function (x) { return x === header.id; });
75
+ if (srcIndex === dstIndex || srcIndex === -1 || dstIndex === -1) {
76
+ return;
77
+ }
78
+ instance.setColumnOrder(reorderColumns(columnIds, srcIndex, dstIndex));
79
+ instance.dispatch({
80
+ type: REORDER_ACTIONS.columnDragEnd,
81
+ columnIndex: -1,
82
+ });
83
+ };
84
+ return [
85
+ props,
86
+ {
87
+ draggable: true,
88
+ onDragStart: onDragStart,
89
+ onDragOver: onDragOver,
90
+ onDragLeave: onDragLeave,
91
+ onDrop: onDrop,
92
+ },
93
+ ];
94
+ }; };
95
+ var reducer = function (newState, action) {
96
+ switch (action.type) {
97
+ case actions.init:
98
+ return __assign(__assign({}, newState), { columnReorderStartIndex: -1 });
99
+ case REORDER_ACTIONS.columnDragStart:
100
+ return __assign(__assign({}, newState), { columnReorderStartIndex: action.columnIndex });
101
+ case REORDER_ACTIONS.columnDragEnd:
102
+ return __assign(__assign({}, newState), { columnReorderStartIndex: -1 });
103
+ default:
104
+ return newState;
105
+ }
106
+ };
107
+ var useInstance = function (instance) {
108
+ var flatHeaders = instance.flatHeaders, getHooks = instance.getHooks;
109
+ var getInstance = useGetLatest(instance);
110
+ flatHeaders.forEach(function (header) {
111
+ header.getDragAndDropProps = makePropGetter(getHooks().getDragAndDropProps, {
112
+ instance: getInstance(),
113
+ header: header,
114
+ });
115
+ });
116
+ };
@@ -29,6 +29,7 @@ export var useExpanderCell = function (subComponent, expanderCell, isRowDisabled
29
29
  maxWidth: 48,
30
30
  columnClassName: 'iui-slot',
31
31
  cellClassName: 'iui-slot',
32
+ disableReordering: true,
32
33
  Cell: function (props) {
33
34
  var row = props.row;
34
35
  if (!subComponent(row)) {
@@ -108,16 +108,20 @@ var defaultGetResizerProps = function (ownerDocument) { return function (props,
108
108
  return [
109
109
  props,
110
110
  {
111
- onMouseDown: function (e) {
112
- e.persist();
111
+ onClick: function (e) {
113
112
  // Prevents from triggering sort
114
113
  e.stopPropagation();
114
+ },
115
+ onMouseDown: function (e) {
116
+ e.persist();
117
+ // Prevents from triggering drag'n'drop
118
+ e.preventDefault();
115
119
  onResizeStart(e, header);
116
120
  },
117
121
  onTouchStart: function (e) {
118
122
  e.persist();
119
- // Prevents from triggering sort
120
- e.stopPropagation();
123
+ // Prevents from triggering drag'n'drop
124
+ e.preventDefault();
121
125
  onResizeStart(e, header);
122
126
  },
123
127
  style: {
@@ -39,6 +39,7 @@ export var useSelectionCell = function (isSelectable, isRowDisabled) { return fu
39
39
  maxWidth: 48,
40
40
  columnClassName: 'iui-slot',
41
41
  cellClassName: 'iui-slot',
42
+ disableReordering: true,
42
43
  Header: function (_a) {
43
44
  var getToggleAllRowsSelectedProps = _a.getToggleAllRowsSelectedProps, rows = _a.rows, initialRows = _a.initialRows, state = _a.state;
44
45
  var disabled = rows.every(function (row) { return isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original); });
@@ -51,20 +51,23 @@ export var ToggleSwitch = React.forwardRef(function (props, ref) {
51
51
  useTheme();
52
52
  var inputElementRef = React.useRef(null);
53
53
  var refs = useMergedRefs(inputElementRef, ref);
54
+ var WrapperComponent = label ? 'label' : 'div';
54
55
  React.useEffect(function () {
55
56
  if (inputElementRef.current && setFocus) {
56
57
  inputElementRef.current.focus();
57
58
  }
58
59
  }, [setFocus]);
59
- return (React.createElement("label", { className: cx('iui-toggle-switch', { 'iui-disabled': disabled }, className), style: style },
60
- React.createElement("input", __assign({ type: 'checkbox', disabled: disabled, ref: refs }, rest)),
61
- labelPosition === 'left' && label && (React.createElement("span", { className: 'iui-label' }, label)),
62
- React.createElement("span", { className: 'iui-toggle' },
63
- icon &&
64
- React.cloneElement(icon, {
65
- className: cx('iui-icon', icon.props.className),
66
- }),
67
- React.createElement("span", { className: 'iui-handle' })),
68
- labelPosition === 'right' && label && (React.createElement("span", { className: 'iui-label' }, label))));
60
+ return (React.createElement(WrapperComponent, { className: cx('iui-toggle-switch-wrapper', {
61
+ 'iui-disabled': disabled,
62
+ 'iui-label-on-right': label && labelPosition === 'right',
63
+ 'iui-label-on-left': label && labelPosition === 'left',
64
+ }, className), style: style },
65
+ React.createElement("input", __assign({ className: 'iui-toggle-switch', type: 'checkbox', role: 'switch', disabled: disabled, ref: refs }, rest)),
66
+ icon &&
67
+ React.cloneElement(icon, {
68
+ className: cx('iui-toggle-switch-icon', icon.props.className),
69
+ 'aria-hidden': true,
70
+ }),
71
+ label && React.createElement("span", { className: 'iui-toggle-switch-label' }, label)));
69
72
  });
70
73
  export default ToggleSwitch;
@@ -24,9 +24,6 @@ var __rest = (this && this.__rest) || function (s, e) {
24
24
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
25
25
  * See LICENSE.md in the project root for license terms and full copyright notice.
26
26
  *--------------------------------------------------------------------------------------------*/
27
- import SvgAway from '@itwin/itwinui-icons-react/cjs/icons/Away';
28
- import SvgCheckmark from '@itwin/itwinui-icons-react/cjs/icons/Checkmark';
29
- import SvgCloseSmall from '@itwin/itwinui-icons-react/cjs/icons/CloseSmall';
30
27
  import cx from 'classnames';
31
28
  import React from 'react';
32
29
  import { useTheme } from '../utils';
@@ -57,16 +54,10 @@ export var UserIcon = function (props) {
57
54
  var _c = props.size, size = _c === void 0 ? 'small' : _c, status = props.status, abbreviation = props.abbreviation, image = props.image, _d = props.backgroundColor, backgroundColor = _d === void 0 ? 'white' : _d, title = props.title, translatedStatusTitles = props.translatedStatusTitles, className = props.className, style = props.style, rest = __rest(props, ["size", "status", "abbreviation", "image", "backgroundColor", "title", "translatedStatusTitles", "className", "style"]);
58
55
  useTheme();
59
56
  var statusTitles = __assign(__assign({}, defaultStatusTitles), translatedStatusTitles);
60
- var iconMap = {
61
- away: React.createElement(SvgAway, { className: 'iui-status-symbol', "aria-hidden": true }),
62
- offline: React.createElement(SvgCloseSmall, { className: 'iui-status-symbol', "aria-hidden": true }),
63
- online: React.createElement(SvgCheckmark, { className: 'iui-status-symbol', "aria-hidden": true }),
64
- busy: React.createElement(React.Fragment, null),
65
- };
66
57
  return (React.createElement("span", __assign({ className: cx('iui-user-icon', (_a = {}, _a["iui-" + size] = size !== 'medium', _a), className), title: title, style: style }, rest), image !== null && image !== void 0 ? image : (React.createElement("abbr", { className: 'iui-initials', style: { backgroundColor: backgroundColor } }, abbreviation === null || abbreviation === void 0 ? void 0 : abbreviation.substring(0, 2))),
67
58
  React.createElement("span", { className: 'iui-stroke' }),
68
59
  status && (React.createElement("span", { title: statusTitles[status], className: cx('iui-status', (_b = {},
69
60
  _b["iui-" + status] = !!status,
70
- _b)), "aria-label": statusTitles[status] }, iconMap[status]))));
61
+ _b)), "aria-label": statusTitles[status] }))));
71
62
  };
72
63
  export default UserIcon;
@@ -32,6 +32,7 @@ declare module 'react-table' {
32
32
  isResizingColumn?: string;
33
33
  };
34
34
  isTableResizing?: boolean;
35
+ columnReorderStartIndex: number;
35
36
  }
36
37
  interface ColumnInterface<D extends object = {}> extends UseSortByColumnOptions<D>, UseFiltersColumnOptions<D>, UseResizeColumnsColumnOptions<D> {
37
38
  /**
@@ -67,11 +68,17 @@ declare module 'react-table' {
67
68
  * }
68
69
  */
69
70
  cellRenderer?: (props: CellRendererProps<D>) => React.ReactNode;
71
+ /**
72
+ * If true, column can't be reordered.
73
+ * @default false
74
+ */
75
+ disableReordering?: boolean;
70
76
  }
71
77
  interface ColumnInstance<D extends object = {}> extends UseFiltersColumnProps<D>, UseGroupByColumnProps<D>, UseResizeColumnsColumnProps<D>, UseSortByColumnProps<D> {
72
78
  originalWidth: number;
73
79
  resizeWidth?: number;
74
80
  isResizerVisible?: boolean;
81
+ getDragAndDropProps: () => TableKeyedProps;
75
82
  }
76
83
  interface Cell<D extends object = {}> extends UseGroupByCellProps<D>, UseRowStateCellProps<D> {
77
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "1.33.1",
3
+ "version": "1.34.0",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "main": "cjs/index.js",
@@ -40,7 +40,7 @@
40
40
  "build-storybook": "build-storybook"
41
41
  },
42
42
  "dependencies": {
43
- "@itwin/itwinui-css": "^0.50.1",
43
+ "@itwin/itwinui-css": "^0.52.0",
44
44
  "@itwin/itwinui-icons-react": "^1.5.0",
45
45
  "@itwin/itwinui-illustrations-react": "^1.0.1",
46
46
  "@tippyjs/react": "^4.2.5",