@itwin/itwinui-react 1.40.0 → 1.42.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.
- package/CHANGELOG.md +34 -0
- package/cjs/core/ComboBox/ComboBox.js +22 -18
- package/cjs/core/ErrorPage/ErrorPage.d.ts +3 -1
- package/cjs/core/ErrorPage/ErrorPage.js +31 -1
- package/cjs/core/Modal/Modal.d.ts +1 -0
- package/cjs/core/Modal/Modal.js +11 -8
- package/cjs/core/Table/Table.d.ts +23 -0
- package/cjs/core/Table/Table.js +15 -9
- package/cjs/core/Table/TableRowMemoized.d.ts +4 -0
- package/cjs/core/Table/TableRowMemoized.js +15 -3
- package/cjs/core/Table/cells/EditableCell.js +7 -2
- package/cjs/core/Table/hooks/index.d.ts +1 -0
- package/cjs/core/Table/hooks/index.js +3 -1
- package/cjs/core/Table/hooks/useScrollToRow.d.ts +11 -0
- package/cjs/core/Table/hooks/useScrollToRow.js +49 -0
- package/cjs/core/Tree/Tree.d.ts +9 -0
- package/cjs/core/Tree/Tree.js +67 -19
- package/cjs/core/Tree/TreeContext.d.ts +4 -0
- package/cjs/core/Tree/TreeNode.js +8 -9
- package/cjs/core/Typography/Small/Small.js +1 -1
- package/cjs/core/utils/components/VirtualScroll.js +2 -2
- package/cjs/core/utils/hooks/index.d.ts +1 -0
- package/cjs/core/utils/hooks/index.js +1 -0
- package/cjs/core/utils/hooks/useLatestRef.d.ts +9 -0
- package/cjs/core/utils/hooks/useLatestRef.js +26 -0
- package/esm/core/ComboBox/ComboBox.js +23 -19
- package/esm/core/ErrorPage/ErrorPage.d.ts +3 -1
- package/esm/core/ErrorPage/ErrorPage.js +31 -1
- package/esm/core/Modal/Modal.d.ts +1 -0
- package/esm/core/Modal/Modal.js +11 -8
- package/esm/core/Table/Table.d.ts +23 -0
- package/esm/core/Table/Table.js +17 -11
- package/esm/core/Table/TableRowMemoized.d.ts +4 -0
- package/esm/core/Table/TableRowMemoized.js +15 -3
- package/esm/core/Table/cells/EditableCell.js +7 -2
- package/esm/core/Table/hooks/index.d.ts +1 -0
- package/esm/core/Table/hooks/index.js +1 -0
- package/esm/core/Table/hooks/useScrollToRow.d.ts +11 -0
- package/esm/core/Table/hooks/useScrollToRow.js +42 -0
- package/esm/core/Tree/Tree.d.ts +9 -0
- package/esm/core/Tree/Tree.js +68 -20
- package/esm/core/Tree/TreeContext.d.ts +4 -0
- package/esm/core/Tree/TreeNode.js +8 -9
- package/esm/core/Typography/Small/Small.js +1 -1
- package/esm/core/utils/components/VirtualScroll.js +2 -2
- package/esm/core/utils/hooks/index.d.ts +1 -0
- package/esm/core/utils/hooks/index.js +1 -0
- package/esm/core/utils/hooks/useLatestRef.d.ts +9 -0
- package/esm/core/utils/hooks/useLatestRef.js +19 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.42.0](https://www.github.com/iTwin/iTwinUI-react/compare/v1.41.0...v1.42.0) (2022-07-26)
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
* **ComboBox:** Prevent infinite loop when `options` change ([#738](https://www.github.com/iTwin/iTwinUI-react/issues/738)) ([7788f45](https://www.github.com/iTwin/iTwinUI-react/commit/7788f451fcbf9dd7959d3fa727c0cdee3485bbcd))
|
|
8
|
+
* **Small:** Use `small` element instead of `p` ([#735](https://www.github.com/iTwin/iTwinUI-react/issues/735)) ([c59f213](https://www.github.com/iTwin/iTwinUI-react/commit/c59f21326e049bce50e24c729a46482b74ef63c3))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### What's new
|
|
12
|
+
|
|
13
|
+
* **Table:** Scroll table to selected item ([#689](https://www.github.com/iTwin/iTwinUI-react/issues/689)) ([afa947b](https://www.github.com/iTwin/iTwinUI-react/commit/afa947b15411305c1bfc57b239d916fc599acfbe))
|
|
14
|
+
* **Tree:** Virtualization ([#713](https://www.github.com/iTwin/iTwinUI-react/issues/713)) ([d4d3575](https://www.github.com/iTwin/iTwinUI-react/commit/d4d35758fa0c8f00811f387cc8453b82e9773c85))
|
|
15
|
+
|
|
16
|
+
## [1.41.0](https://www.github.com/iTwin/iTwinUI-react/compare/v1.40.1...v1.41.0) (2022-07-13)
|
|
17
|
+
|
|
18
|
+
### What's new
|
|
19
|
+
|
|
20
|
+
* **ErrorPage:** Add time-out and redirect status codes ([#715](https://www.github.com/iTwin/iTwinUI-react/issues/715)) ([a5fb85f](https://www.github.com/iTwin/iTwinUI-react/commit/a5fb85f1f0ef9517a065db02384875d7c5d87f95))
|
|
21
|
+
* **Modal:** Update classes through the css package update ([#724](https://www.github.com/iTwin/iTwinUI-react/issues/724)) ([d13e0bf](https://www.github.com/iTwin/iTwinUI-react/commit/d13e0bf7941581a3b8d275b744bf77ebd7ae95d4))
|
|
22
|
+
- Now `style` and `className` props are applied on the dialog element itself.
|
|
23
|
+
* Border radius was changed from `3px` to `4px` through the css package update in all elements ([#724](https://www.github.com/iTwin/iTwinUI-react/issues/724)) ([d13e0bf](https://www.github.com/iTwin/iTwinUI-react/commit/d13e0bf7941581a3b8d275b744bf77ebd7ae95d4))
|
|
24
|
+
|
|
25
|
+
### Fixes
|
|
26
|
+
|
|
27
|
+
* **Combobox:** Allow users to reset the value ([#728](https://www.github.com/iTwin/iTwinUI-react/issues/728)) ([f6c0b0d](https://www.github.com/iTwin/iTwinUI-react/commit/f6c0b0d66ac9ac725a23e07980c9dd7298084ae4))
|
|
28
|
+
* **Table:** Prevent crashing when clearing editable cell ([#732](https://www.github.com/iTwin/iTwinUI-react/issues/732)) ([0dedd3b](https://www.github.com/iTwin/iTwinUI-react/commit/0dedd3b8804ce98ce836d4bbbf58db83a4f9bfde))
|
|
29
|
+
* **Table:** Set correct intersection root for margin to work ([#708](https://www.github.com/iTwin/iTwinUI-react/issues/708)) ([55e4848](https://www.github.com/iTwin/iTwinUI-react/commit/55e48481f95c3351c127d495bd3c20134fd4a77f))
|
|
30
|
+
|
|
31
|
+
### [1.40.1](https://www.github.com/iTwin/iTwinUI-react/compare/v1.40.0...v1.40.1) (2022-06-17)
|
|
32
|
+
|
|
33
|
+
### Fixes
|
|
34
|
+
|
|
35
|
+
* **Table:** Horizontal scroll is working when virtual scroll is enabled ([#711](https://www.github.com/iTwin/iTwinUI-react/issues/711)) ([d3db504](https://www.github.com/iTwin/iTwinUI-react/commit/d3db504d3a44a4da2c1f34a392f99aae478ef2a3))
|
|
36
|
+
|
|
3
37
|
## [1.40.0](https://www.github.com/iTwin/iTwinUI-react/compare/v1.39.0...v1.40.0) (2022-06-10)
|
|
4
38
|
|
|
5
39
|
### What's new
|
|
@@ -74,11 +74,10 @@ var ComboBox = function (props) {
|
|
|
74
74
|
var inputRef = react_1.default.useRef(null);
|
|
75
75
|
var menuRef = react_1.default.useRef(null);
|
|
76
76
|
var toggleButtonRef = react_1.default.useRef(null);
|
|
77
|
-
|
|
78
|
-
var
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}, [onChange]);
|
|
77
|
+
var mounted = react_1.default.useRef(false);
|
|
78
|
+
var valuePropRef = (0, utils_1.useLatestRef)(valueProp);
|
|
79
|
+
var onChangeProp = (0, utils_1.useLatestRef)(onChange);
|
|
80
|
+
var optionsRef = (0, utils_1.useLatestRef)(options);
|
|
82
81
|
// Record to store all extra information (e.g. original indexes), where the key is the id of the option
|
|
83
82
|
var optionsExtraInfoRef = react_1.default.useRef({});
|
|
84
83
|
// Clear the extra info when the options change so that it can be reinitialized below
|
|
@@ -97,7 +96,9 @@ var ComboBox = function (props) {
|
|
|
97
96
|
// Reducer where all the component-wide state is stored
|
|
98
97
|
var _e = react_1.default.useReducer(helpers_1.comboBoxReducer, {
|
|
99
98
|
isOpen: false,
|
|
100
|
-
selectedIndex:
|
|
99
|
+
selectedIndex: valueProp
|
|
100
|
+
? optionsRef.current.findIndex(function (option) { return option.value === valueProp; })
|
|
101
|
+
: -1,
|
|
101
102
|
focusedIndex: -1,
|
|
102
103
|
}), _f = _e[0], isOpen = _f.isOpen, selectedIndex = _f.selectedIndex, focusedIndex = _f.focusedIndex, dispatch = _e[1];
|
|
103
104
|
react_1.default.useLayoutEffect(function () {
|
|
@@ -105,7 +106,7 @@ var ComboBox = function (props) {
|
|
|
105
106
|
// When the dropdown opens
|
|
106
107
|
if (isOpen) {
|
|
107
108
|
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); // Focus the input
|
|
108
|
-
setFilteredOptions(
|
|
109
|
+
setFilteredOptions(optionsRef.current); // Reset the filtered list
|
|
109
110
|
dispatch(['focus']);
|
|
110
111
|
}
|
|
111
112
|
// When the dropdown closes
|
|
@@ -114,10 +115,10 @@ var ComboBox = function (props) {
|
|
|
114
115
|
dispatch(['focus']);
|
|
115
116
|
// Reset the input value
|
|
116
117
|
setInputValue(selectedIndex != undefined && selectedIndex >= 0
|
|
117
|
-
? (_b =
|
|
118
|
+
? (_b = optionsRef.current[selectedIndex]) === null || _b === void 0 ? void 0 : _b.label
|
|
118
119
|
: '');
|
|
119
120
|
}
|
|
120
|
-
}, [isOpen,
|
|
121
|
+
}, [isOpen, optionsRef, selectedIndex]);
|
|
121
122
|
// Set min-width of menu to be same as input
|
|
122
123
|
var _g = react_1.default.useState(0), minWidth = _g[0], setMinWidth = _g[1];
|
|
123
124
|
react_1.default.useEffect(function () {
|
|
@@ -148,14 +149,14 @@ var ComboBox = function (props) {
|
|
|
148
149
|
var value = event.currentTarget.value;
|
|
149
150
|
setInputValue(value);
|
|
150
151
|
dispatch(['open']); // reopen when typing
|
|
151
|
-
setFilteredOptions((_a = filterFunction === null || filterFunction === void 0 ? void 0 : filterFunction(
|
|
152
|
+
setFilteredOptions((_a = filterFunction === null || filterFunction === void 0 ? void 0 : filterFunction(optionsRef.current, value)) !== null && _a !== void 0 ? _a : optionsRef.current.filter(function (option) {
|
|
152
153
|
return option.label.toLowerCase().includes(value.toLowerCase());
|
|
153
154
|
}));
|
|
154
155
|
if (focusedIndex != -1) {
|
|
155
156
|
dispatch(['focus', -1]);
|
|
156
157
|
}
|
|
157
158
|
(_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onChange) === null || _b === void 0 ? void 0 : _b.call(inputProps, event);
|
|
158
|
-
}, [filterFunction, focusedIndex, inputProps,
|
|
159
|
+
}, [filterFunction, focusedIndex, inputProps, optionsRef]);
|
|
159
160
|
// When the value prop changes, update the selectedIndex
|
|
160
161
|
react_1.default.useEffect(function () {
|
|
161
162
|
dispatch([
|
|
@@ -166,14 +167,17 @@ var ComboBox = function (props) {
|
|
|
166
167
|
// Call user-defined onChange when the value actually changes
|
|
167
168
|
react_1.default.useEffect(function () {
|
|
168
169
|
var _a, _b;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
170
|
+
// Prevent user-defined onChange to be called on mount
|
|
171
|
+
if (!mounted.current) {
|
|
172
|
+
mounted.current = true;
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
var currentValue = (_a = optionsRef.current[selectedIndex]) === null || _a === void 0 ? void 0 : _a.value;
|
|
176
|
+
if (currentValue === valuePropRef.current || selectedIndex === -1) {
|
|
177
|
+
return;
|
|
175
178
|
}
|
|
176
|
-
|
|
179
|
+
(_b = onChangeProp.current) === null || _b === void 0 ? void 0 : _b.call(onChangeProp, currentValue);
|
|
180
|
+
}, [onChangeProp, optionsRef, selectedIndex, valuePropRef]);
|
|
177
181
|
var getMenuItem = react_1.default.useCallback(function (option, filteredIndex) {
|
|
178
182
|
var optionId = getOptionId(option, id);
|
|
179
183
|
var __originalIndex = optionsExtraInfoRef.current[optionId].__originalIndex;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { CommonProps } from '../utils';
|
|
3
3
|
import '@itwin/itwinui-css/css/non-ideal-state.css';
|
|
4
|
-
export declare type ErrorPageType = '401' | '403' | '404' | '500' | '502' | '503' | 'generic';
|
|
4
|
+
export declare type ErrorPageType = '300' | '301' | '302' | '303' | '304' | '305' | '307' | '308' | '401' | '403' | '404' | '408' | '500' | '502' | '503' | '504' | 'generic';
|
|
5
5
|
export declare type ErrorTypeTranslations = {
|
|
6
6
|
badGateway: string;
|
|
7
7
|
error: string;
|
|
8
8
|
forbidden: string;
|
|
9
9
|
internalServerError: string;
|
|
10
|
+
redirect?: string;
|
|
10
11
|
pageNotFound: string;
|
|
11
12
|
serviceUnavailable: string;
|
|
13
|
+
timedOut?: string;
|
|
12
14
|
unauthorized: string;
|
|
13
15
|
};
|
|
14
16
|
export declare type ErrorPageProps = {
|
|
@@ -37,6 +37,8 @@ var _500_1 = __importDefault(require("@itwin/itwinui-illustrations-react/cjs/ill
|
|
|
37
37
|
var _502_1 = __importDefault(require("@itwin/itwinui-illustrations-react/cjs/illustrations/502"));
|
|
38
38
|
var _503_1 = __importDefault(require("@itwin/itwinui-illustrations-react/cjs/illustrations/503"));
|
|
39
39
|
var Error_1 = __importDefault(require("@itwin/itwinui-illustrations-react/cjs/illustrations/Error"));
|
|
40
|
+
var Redirect_1 = __importDefault(require("@itwin/itwinui-illustrations-react/cjs/illustrations/Redirect"));
|
|
41
|
+
var TimedOut_1 = __importDefault(require("@itwin/itwinui-illustrations-react/cjs/illustrations/TimedOut"));
|
|
40
42
|
var react_1 = __importDefault(require("react"));
|
|
41
43
|
var Button_1 = require("../Buttons/Button");
|
|
42
44
|
var utils_1 = require("../utils");
|
|
@@ -50,9 +52,19 @@ require("@itwin/itwinui-css/css/non-ideal-state.css");
|
|
|
50
52
|
var ErrorPage = function (props) {
|
|
51
53
|
var errorType = props.errorType, errorName = props.errorName, errorMessage = props.errorMessage, primaryButtonHandle = props.primaryButtonHandle, primaryButtonLabel = props.primaryButtonLabel, secondaryButtonHandle = props.secondaryButtonHandle, secondaryButtonLabel = props.secondaryButtonLabel, translatedErrorMessages = props.translatedErrorMessages, className = props.className, rest = __rest(props, ["errorType", "errorName", "errorMessage", "primaryButtonHandle", "primaryButtonLabel", "secondaryButtonHandle", "secondaryButtonLabel", "translatedErrorMessages", "className"]);
|
|
52
54
|
(0, utils_1.useTheme)();
|
|
53
|
-
var defaultErrorMessages = __assign({ badGateway: 'Bad gateway', error: 'Error', forbidden: 'Forbidden', internalServerError: 'Internal server error', pageNotFound: 'Page not found', serviceUnavailable: 'Service unavailable', unauthorized: 'Unauthorized' }, translatedErrorMessages);
|
|
55
|
+
var defaultErrorMessages = __assign({ badGateway: 'Bad gateway', error: 'Error', forbidden: 'Forbidden', internalServerError: 'Internal server error', redirect: 'Redirect', pageNotFound: 'Page not found', serviceUnavailable: 'Service unavailable', timedOut: 'Timed out', unauthorized: 'Unauthorized' }, translatedErrorMessages);
|
|
54
56
|
function getErrorIcon() {
|
|
55
57
|
switch (errorType) {
|
|
58
|
+
case '300':
|
|
59
|
+
case '301':
|
|
60
|
+
case '302':
|
|
61
|
+
case '303':
|
|
62
|
+
case '304':
|
|
63
|
+
case '305':
|
|
64
|
+
case '307':
|
|
65
|
+
case '308': {
|
|
66
|
+
return react_1.default.createElement(Redirect_1.default, { className: 'iui-non-ideal-state-illustration' });
|
|
67
|
+
}
|
|
56
68
|
case '401': {
|
|
57
69
|
return react_1.default.createElement(_401_1.default, { className: 'iui-non-ideal-state-illustration' });
|
|
58
70
|
}
|
|
@@ -62,6 +74,10 @@ var ErrorPage = function (props) {
|
|
|
62
74
|
case '404': {
|
|
63
75
|
return react_1.default.createElement(_404_1.default, { className: 'iui-non-ideal-state-illustration' });
|
|
64
76
|
}
|
|
77
|
+
case '408':
|
|
78
|
+
case '504': {
|
|
79
|
+
return react_1.default.createElement(TimedOut_1.default, { className: 'iui-non-ideal-state-illustration' });
|
|
80
|
+
}
|
|
65
81
|
case '500': {
|
|
66
82
|
return react_1.default.createElement(_500_1.default, { className: 'iui-non-ideal-state-illustration' });
|
|
67
83
|
}
|
|
@@ -82,6 +98,16 @@ var ErrorPage = function (props) {
|
|
|
82
98
|
return errorName;
|
|
83
99
|
}
|
|
84
100
|
switch (errorType) {
|
|
101
|
+
case '300':
|
|
102
|
+
case '301':
|
|
103
|
+
case '302':
|
|
104
|
+
case '303':
|
|
105
|
+
case '304':
|
|
106
|
+
case '305':
|
|
107
|
+
case '307':
|
|
108
|
+
case '308': {
|
|
109
|
+
return defaultErrorMessages.redirect || '';
|
|
110
|
+
}
|
|
85
111
|
case '401': {
|
|
86
112
|
return defaultErrorMessages.unauthorized;
|
|
87
113
|
}
|
|
@@ -91,6 +117,10 @@ var ErrorPage = function (props) {
|
|
|
91
117
|
case '404': {
|
|
92
118
|
return defaultErrorMessages.pageNotFound;
|
|
93
119
|
}
|
|
120
|
+
case '408':
|
|
121
|
+
case '504': {
|
|
122
|
+
return defaultErrorMessages.timedOut || '';
|
|
123
|
+
}
|
|
94
124
|
case '500': {
|
|
95
125
|
return defaultErrorMessages.internalServerError;
|
|
96
126
|
}
|
package/cjs/core/Modal/Modal.js
CHANGED
|
@@ -36,6 +36,7 @@ var classnames_1 = __importDefault(require("classnames"));
|
|
|
36
36
|
var Close_1 = __importDefault(require("@itwin/itwinui-icons-react/cjs/icons/Close"));
|
|
37
37
|
var utils_1 = require("../utils");
|
|
38
38
|
require("@itwin/itwinui-css/css/dialog.css");
|
|
39
|
+
require("@itwin/itwinui-css/css/backdrop.css");
|
|
39
40
|
var IconButton_1 = require("../Buttons/IconButton");
|
|
40
41
|
var react_transition_group_1 = require("react-transition-group");
|
|
41
42
|
/**
|
|
@@ -118,15 +119,17 @@ var Modal = function (props) {
|
|
|
118
119
|
onClose(event);
|
|
119
120
|
}
|
|
120
121
|
};
|
|
121
|
-
return !!container ? (react_dom_1.default.createPortal(react_1.default.createElement(
|
|
122
|
+
return !!container ? (react_dom_1.default.createPortal(react_1.default.createElement(react_1.default.Fragment, null,
|
|
123
|
+
react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-backdrop', { 'iui-backdrop-visible': isOpen }), tabIndex: -1, onKeyDown: handleKeyDown, ref: overlayRef, onMouseDown: handleMouseDown }),
|
|
122
124
|
react_1.default.createElement(utils_1.FocusTrap, null,
|
|
123
|
-
react_1.default.createElement("div",
|
|
124
|
-
react_1.default.createElement(
|
|
125
|
-
react_1.default.createElement("div", { className: 'iui-dialog-
|
|
126
|
-
react_1.default.createElement("div", { className: 'iui-dialog-title' },
|
|
127
|
-
|
|
128
|
-
react_1.default.createElement(
|
|
129
|
-
|
|
125
|
+
react_1.default.createElement("div", null,
|
|
126
|
+
react_1.default.createElement(react_transition_group_1.CSSTransition, { in: isOpen, classNames: 'iui-dialog-animation', timeout: { exit: 600 }, unmountOnExit: true },
|
|
127
|
+
react_1.default.createElement("div", __assign({ className: (0, classnames_1.default)('iui-dialog', { 'iui-dialog-default': styleType === 'default' }, { 'iui-dialog-full-page': styleType === 'fullPage' }, { 'iui-dialog-visible': isOpen }, className), id: id, style: style, role: 'dialog', "aria-modal": 'true' }, rest),
|
|
128
|
+
react_1.default.createElement("div", { className: 'iui-dialog-title-bar' },
|
|
129
|
+
react_1.default.createElement("div", { className: 'iui-dialog-title' }, title),
|
|
130
|
+
isDismissible && (react_1.default.createElement(IconButton_1.IconButton, { size: 'small', styleType: 'borderless', onClick: onClose, "aria-label": 'Close' },
|
|
131
|
+
react_1.default.createElement(Close_1.default, null)))),
|
|
132
|
+
children))))), container)) : (react_1.default.createElement(react_1.default.Fragment, null));
|
|
130
133
|
};
|
|
131
134
|
exports.Modal = Modal;
|
|
132
135
|
exports.default = exports.Modal;
|
|
@@ -182,6 +182,29 @@ export declare type TableProps<T extends Record<string, unknown> = Record<string
|
|
|
182
182
|
* @default false
|
|
183
183
|
*/
|
|
184
184
|
enableColumnReordering?: boolean;
|
|
185
|
+
/**
|
|
186
|
+
* Function that returns index of the row that you want to scroll to.
|
|
187
|
+
*
|
|
188
|
+
* It doesn't work with paginated tables and with lazy-loading.
|
|
189
|
+
* @beta
|
|
190
|
+
* @example
|
|
191
|
+
* <Table
|
|
192
|
+
* scrollToRow={React.useCallback(
|
|
193
|
+
* (rows, data) => rows.findIndex((row) => row.original === data[250]),
|
|
194
|
+
* []
|
|
195
|
+
* )}
|
|
196
|
+
* {...restProps}
|
|
197
|
+
* />
|
|
198
|
+
* @example
|
|
199
|
+
* <Table
|
|
200
|
+
* scrollToRow={React.useCallback(
|
|
201
|
+
* (rows, data) => rows.findIndex((row) => row.original.id === data[250].id),
|
|
202
|
+
* []
|
|
203
|
+
* )}
|
|
204
|
+
* {...restProps}
|
|
205
|
+
* />
|
|
206
|
+
*/
|
|
207
|
+
scrollToRow?: (rows: Row<T>[], data: T[]) => number;
|
|
185
208
|
} & Omit<CommonProps, 'title'>;
|
|
186
209
|
/**
|
|
187
210
|
* Table based on [react-table](https://react-table.tanstack.com/docs/api/overview).
|
package/cjs/core/Table/Table.js
CHANGED
|
@@ -240,6 +240,7 @@ var Table = function (props) {
|
|
|
240
240
|
state.pageIndex,
|
|
241
241
|
state.pageSize,
|
|
242
242
|
]);
|
|
243
|
+
var _r = (0, hooks_1.useScrollToRow)(__assign(__assign({}, props), { page: page })), scrollToIndex = _r.scrollToIndex, tableRowRef = _r.tableRowRef;
|
|
243
244
|
var columnRefs = react_1.default.useRef({});
|
|
244
245
|
var previousTableWidth = react_1.default.useRef(0);
|
|
245
246
|
var onTableResize = react_1.default.useCallback(function (_a) {
|
|
@@ -275,22 +276,27 @@ var Table = function (props) {
|
|
|
275
276
|
});
|
|
276
277
|
var headerRef = react_1.default.useRef(null);
|
|
277
278
|
var bodyRef = react_1.default.useRef(null);
|
|
279
|
+
// Using `useState` to rerender rows when table body ref is available
|
|
280
|
+
var _s = react_1.default.useState(null), bodyRefState = _s[0], setBodyRefState = _s[1];
|
|
278
281
|
var getPreparedRow = react_1.default.useCallback(function (index) {
|
|
279
282
|
var row = page[index];
|
|
280
283
|
prepareRow(row);
|
|
281
|
-
return (react_1.default.createElement(TableRowMemoized_1.TableRowMemoized, { row: row, rowProps: rowProps, isLast: index === page.length - 1, onRowInViewport: onRowInViewportRef, onBottomReached: onBottomReachedRef, intersectionMargin: intersectionMargin, state: state, key: row.getRowProps().key, onClick: onRowClickHandler, subComponent: subComponent, isDisabled: !!(isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original)), tableHasSubRows: hasAnySubRows, tableInstance: instance, expanderCell: expanderCell }));
|
|
284
|
+
return (react_1.default.createElement(TableRowMemoized_1.TableRowMemoized, { row: row, rowProps: rowProps, isLast: index === page.length - 1, onRowInViewport: onRowInViewportRef, onBottomReached: onBottomReachedRef, intersectionMargin: intersectionMargin, state: state, key: row.getRowProps().key, onClick: onRowClickHandler, subComponent: subComponent, isDisabled: !!(isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original)), tableHasSubRows: hasAnySubRows, tableInstance: instance, expanderCell: expanderCell, bodyRef: bodyRefState, tableRowRef: enableVirtualization ? undefined : tableRowRef(row) }));
|
|
282
285
|
}, [
|
|
283
286
|
page,
|
|
284
|
-
expanderCell,
|
|
285
|
-
hasAnySubRows,
|
|
286
|
-
instance,
|
|
287
|
-
intersectionMargin,
|
|
288
|
-
isRowDisabled,
|
|
289
|
-
onRowClickHandler,
|
|
290
287
|
prepareRow,
|
|
291
288
|
rowProps,
|
|
289
|
+
intersectionMargin,
|
|
292
290
|
state,
|
|
291
|
+
onRowClickHandler,
|
|
293
292
|
subComponent,
|
|
293
|
+
isRowDisabled,
|
|
294
|
+
hasAnySubRows,
|
|
295
|
+
instance,
|
|
296
|
+
expanderCell,
|
|
297
|
+
bodyRefState,
|
|
298
|
+
enableVirtualization,
|
|
299
|
+
tableRowRef,
|
|
294
300
|
]);
|
|
295
301
|
var virtualizedItemRenderer = react_1.default.useCallback(function (index) { return getPreparedRow(index); }, [getPreparedRow]);
|
|
296
302
|
var updateStickyState = function () {
|
|
@@ -366,13 +372,13 @@ var Table = function (props) {
|
|
|
366
372
|
'iui-zebra-striping': styleType === 'zebra-rows',
|
|
367
373
|
}),
|
|
368
374
|
style: { outline: 0 },
|
|
369
|
-
}), { ref: bodyRef, onScroll: function () {
|
|
375
|
+
}), { ref: (0, utils_1.mergeRefs)(bodyRef, setBodyRefState), onScroll: function () {
|
|
370
376
|
if (headerRef.current && bodyRef.current) {
|
|
371
377
|
headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
|
|
372
378
|
updateStickyState();
|
|
373
379
|
}
|
|
374
380
|
}, tabIndex: -1 }),
|
|
375
|
-
data.length !== 0 && (react_1.default.createElement(react_1.default.Fragment, null, enableVirtualization ? (react_1.default.createElement(VirtualScroll_1.default, { itemsLength: page.length, itemRenderer: virtualizedItemRenderer })) : (page.map(function (_, index) { return getPreparedRow(index); })))),
|
|
381
|
+
data.length !== 0 && (react_1.default.createElement(react_1.default.Fragment, null, enableVirtualization ? (react_1.default.createElement(VirtualScroll_1.default, { itemsLength: page.length, itemRenderer: virtualizedItemRenderer, scrollToIndex: scrollToIndex })) : (page.map(function (_, index) { return getPreparedRow(index); })))),
|
|
376
382
|
isLoading && data.length === 0 && (react_1.default.createElement("div", { className: 'iui-table-empty' },
|
|
377
383
|
react_1.default.createElement(ProgressIndicators_1.ProgressRadial, { indeterminate: true }))),
|
|
378
384
|
isLoading && data.length !== 0 && (react_1.default.createElement("div", { className: 'iui-row' },
|
|
@@ -20,6 +20,8 @@ export declare const TableRow: <T extends Record<string, unknown>>(props: {
|
|
|
20
20
|
tableHasSubRows: boolean;
|
|
21
21
|
tableInstance: TableInstance<T>;
|
|
22
22
|
expanderCell?: ((cellProps: CellProps<T, any>) => React.ReactNode) | undefined;
|
|
23
|
+
bodyRef: HTMLDivElement | null;
|
|
24
|
+
tableRowRef?: React.Ref<HTMLDivElement> | undefined;
|
|
23
25
|
}) => JSX.Element;
|
|
24
26
|
export declare const TableRowMemoized: <T extends Record<string, unknown>>(props: {
|
|
25
27
|
row: Row<T>;
|
|
@@ -35,4 +37,6 @@ export declare const TableRowMemoized: <T extends Record<string, unknown>>(props
|
|
|
35
37
|
tableHasSubRows: boolean;
|
|
36
38
|
tableInstance: TableInstance<T>;
|
|
37
39
|
expanderCell?: ((cellProps: CellProps<T, any>) => React.ReactNode) | undefined;
|
|
40
|
+
bodyRef: HTMLDivElement | null;
|
|
41
|
+
tableRowRef?: React.Ref<HTMLDivElement> | undefined;
|
|
38
42
|
}) => JSX.Element;
|
|
@@ -30,14 +30,25 @@ var TableCell_1 = require("./TableCell");
|
|
|
30
30
|
* When adding new features check whether it changes state that affects row. If it does then add equality check to `React.memo`.
|
|
31
31
|
*/
|
|
32
32
|
var TableRow = function (props) {
|
|
33
|
-
var row = props.row, rowProps = props.rowProps, isLast = props.isLast, onRowInViewport = props.onRowInViewport, onBottomReached = props.onBottomReached, intersectionMargin = props.intersectionMargin, onClick = props.onClick, subComponent = props.subComponent, isDisabled = props.isDisabled, tableHasSubRows = props.tableHasSubRows, tableInstance = props.tableInstance, expanderCell = props.expanderCell;
|
|
33
|
+
var row = props.row, rowProps = props.rowProps, isLast = props.isLast, onRowInViewport = props.onRowInViewport, onBottomReached = props.onBottomReached, intersectionMargin = props.intersectionMargin, onClick = props.onClick, subComponent = props.subComponent, isDisabled = props.isDisabled, tableHasSubRows = props.tableHasSubRows, tableInstance = props.tableInstance, expanderCell = props.expanderCell, bodyRef = props.bodyRef, tableRowRef = props.tableRowRef;
|
|
34
34
|
var onIntersect = react_1.default.useCallback(function () {
|
|
35
35
|
var _a, _b;
|
|
36
36
|
(_a = onRowInViewport.current) === null || _a === void 0 ? void 0 : _a.call(onRowInViewport, row.original);
|
|
37
37
|
isLast && ((_b = onBottomReached.current) === null || _b === void 0 ? void 0 : _b.call(onBottomReached));
|
|
38
38
|
}, [isLast, onBottomReached, onRowInViewport, row.original]);
|
|
39
|
-
var
|
|
39
|
+
var intersectionRoot = react_1.default.useMemo(function () {
|
|
40
|
+
var _a, _b;
|
|
41
|
+
var isTableBodyScrollable = ((_a = bodyRef === null || bodyRef === void 0 ? void 0 : bodyRef.scrollHeight) !== null && _a !== void 0 ? _a : 0) > ((_b = bodyRef === null || bodyRef === void 0 ? void 0 : bodyRef.offsetHeight) !== null && _b !== void 0 ? _b : 0);
|
|
42
|
+
// If table body is scrollable, make it the intersection root
|
|
43
|
+
if (isTableBodyScrollable) {
|
|
44
|
+
return bodyRef;
|
|
45
|
+
}
|
|
46
|
+
// Otherwise, make the viewport the intersection root
|
|
47
|
+
return undefined;
|
|
48
|
+
}, [bodyRef]);
|
|
49
|
+
var intersectionRef = (0, utils_1.useIntersection)(onIntersect, {
|
|
40
50
|
rootMargin: "".concat(intersectionMargin, "px"),
|
|
51
|
+
root: intersectionRoot,
|
|
41
52
|
});
|
|
42
53
|
var userRowProps = rowProps === null || rowProps === void 0 ? void 0 : rowProps(row);
|
|
43
54
|
var mergedProps = __assign(__assign(__assign({}, row.getRowProps({ style: { flex: "0 0 auto", minWidth: '100%' } })), userRowProps), {
|
|
@@ -47,7 +58,7 @@ var TableRow = function (props) {
|
|
|
47
58
|
'iui-disabled': isDisabled,
|
|
48
59
|
}, userRowProps === null || userRowProps === void 0 ? void 0 : userRowProps.className),
|
|
49
60
|
});
|
|
50
|
-
var refs = (0, utils_1.useMergedRefs)(
|
|
61
|
+
var refs = (0, utils_1.useMergedRefs)(intersectionRef, mergedProps.ref, tableRowRef);
|
|
51
62
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
52
63
|
react_1.default.createElement("div", __assign({}, mergedProps, { ref: refs, onClick: function (event) {
|
|
53
64
|
var _a;
|
|
@@ -97,6 +108,7 @@ exports.TableRowMemoized = react_1.default.memo(exports.TableRow, function (prev
|
|
|
97
108
|
prevProp.rowProps === nextProp.rowProps &&
|
|
98
109
|
prevProp.expanderCell === nextProp.expanderCell &&
|
|
99
110
|
prevProp.tableHasSubRows === nextProp.tableHasSubRows &&
|
|
111
|
+
prevProp.bodyRef === nextProp.bodyRef &&
|
|
100
112
|
prevProp.state.columnOrder === nextProp.state.columnOrder &&
|
|
101
113
|
!nextProp.state.columnResizing.isResizingColumn &&
|
|
102
114
|
prevProp.state.isTableResizing === nextProp.state.isTableResizing &&
|
|
@@ -31,6 +31,7 @@ exports.EditableCell = void 0;
|
|
|
31
31
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
32
32
|
*--------------------------------------------------------------------------------------------*/
|
|
33
33
|
var react_1 = __importDefault(require("react"));
|
|
34
|
+
var utils_1 = require("../../utils");
|
|
34
35
|
/**
|
|
35
36
|
* Editable cell.
|
|
36
37
|
* It should be passed to `cellRenderer`.
|
|
@@ -53,8 +54,9 @@ var EditableCell = function (props) {
|
|
|
53
54
|
react_1.default.useEffect(function () {
|
|
54
55
|
setValue(sanitizeString(cellProps.value));
|
|
55
56
|
}, [cellProps.value]);
|
|
56
|
-
var _b = react_1.default.useState(
|
|
57
|
-
|
|
57
|
+
var _b = react_1.default.useState((0, utils_1.getRandomValue)(10)), key = _b[0], setKey = _b[1];
|
|
58
|
+
var _c = react_1.default.useState(false), isDirty = _c[0], setIsDirty = _c[1];
|
|
59
|
+
return (react_1.default.createElement("div", __assign({}, cellElementProps, { contentEditable: true, suppressContentEditableWarning: true, key: key }, rest, { onInput: function (e) {
|
|
58
60
|
var _a;
|
|
59
61
|
setValue(sanitizeString(e.target.innerText));
|
|
60
62
|
setIsDirty(true);
|
|
@@ -65,6 +67,9 @@ var EditableCell = function (props) {
|
|
|
65
67
|
onCellEdit(cellProps.column.id, value, cellProps.row.original);
|
|
66
68
|
}
|
|
67
69
|
(_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, e);
|
|
70
|
+
// Prevents error when text is cleared.
|
|
71
|
+
// New key makes React to reattach with the DOM so it won't complain about deleted text node.
|
|
72
|
+
setKey((0, utils_1.getRandomValue)(10));
|
|
68
73
|
}, onKeyDown: function (e) {
|
|
69
74
|
var _a;
|
|
70
75
|
// Prevents from adding HTML elements (div, br) inside a cell on Enter press
|
|
@@ -4,4 +4,5 @@ export { useSubRowFiltering } from './useSubRowFiltering';
|
|
|
4
4
|
export { useSubRowSelection } from './useSubRowSelection';
|
|
5
5
|
export { useResizeColumns } from './useResizeColumns';
|
|
6
6
|
export { useColumnDragAndDrop } from './useColumnDragAndDrop';
|
|
7
|
+
export { useScrollToRow } from './useScrollToRow';
|
|
7
8
|
export { useStickyColumns } from './useStickyColumns';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useStickyColumns = exports.useColumnDragAndDrop = exports.useResizeColumns = exports.useSubRowSelection = exports.useSubRowFiltering = exports.useSelectionCell = exports.useExpanderCell = void 0;
|
|
3
|
+
exports.useStickyColumns = exports.useScrollToRow = exports.useColumnDragAndDrop = exports.useResizeColumns = exports.useSubRowSelection = exports.useSubRowFiltering = exports.useSelectionCell = exports.useExpanderCell = 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,5 +17,7 @@ var useResizeColumns_1 = require("./useResizeColumns");
|
|
|
17
17
|
Object.defineProperty(exports, "useResizeColumns", { enumerable: true, get: function () { return useResizeColumns_1.useResizeColumns; } });
|
|
18
18
|
var useColumnDragAndDrop_1 = require("./useColumnDragAndDrop");
|
|
19
19
|
Object.defineProperty(exports, "useColumnDragAndDrop", { enumerable: true, get: function () { return useColumnDragAndDrop_1.useColumnDragAndDrop; } });
|
|
20
|
+
var useScrollToRow_1 = require("./useScrollToRow");
|
|
21
|
+
Object.defineProperty(exports, "useScrollToRow", { enumerable: true, get: function () { return useScrollToRow_1.useScrollToRow; } });
|
|
20
22
|
var useStickyColumns_1 = require("./useStickyColumns");
|
|
21
23
|
Object.defineProperty(exports, "useStickyColumns", { enumerable: true, get: function () { return useStickyColumns_1.useStickyColumns; } });
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Row } from 'react-table';
|
|
2
|
+
import { TableProps } from '../Table';
|
|
3
|
+
declare type ScrollToRow<T extends Record<string, unknown>> = {
|
|
4
|
+
scrollToIndex: number | undefined;
|
|
5
|
+
tableRowRef: (row: Row<T>) => (element: HTMLDivElement) => void;
|
|
6
|
+
};
|
|
7
|
+
declare type ScrollToRowProps<T extends Record<string, unknown>> = TableProps<T> & {
|
|
8
|
+
page: Row<T>[];
|
|
9
|
+
};
|
|
10
|
+
export declare function useScrollToRow<T extends Record<string, unknown>>({ data, enableVirtualization, page, paginatorRenderer, scrollToRow, onBottomReached, }: ScrollToRowProps<T>): ScrollToRow<T>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useScrollToRow = void 0;
|
|
7
|
+
/*---------------------------------------------------------------------------------------------
|
|
8
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
9
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
10
|
+
*--------------------------------------------------------------------------------------------*/
|
|
11
|
+
var react_1 = __importDefault(require("react"));
|
|
12
|
+
function useScrollToRow(_a) {
|
|
13
|
+
var data = _a.data, enableVirtualization = _a.enableVirtualization, page = _a.page, paginatorRenderer = _a.paginatorRenderer, scrollToRow = _a.scrollToRow, onBottomReached = _a.onBottomReached;
|
|
14
|
+
var rowRefs = react_1.default.useRef({});
|
|
15
|
+
// Refs prevents from having `page` and `data` as dependencies
|
|
16
|
+
// therefore we avoid unnecessary scroll to row.
|
|
17
|
+
var pageRef = react_1.default.useRef(page);
|
|
18
|
+
pageRef.current = page;
|
|
19
|
+
var dataRef = react_1.default.useRef(data);
|
|
20
|
+
dataRef.current = data;
|
|
21
|
+
// For virtualized tables, all we need to do is pass the index of the item
|
|
22
|
+
// to the VirtualScroll component
|
|
23
|
+
var scrollToIndex = react_1.default.useMemo(function () {
|
|
24
|
+
if (!scrollToRow || paginatorRenderer || onBottomReached) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
var index = scrollToRow(pageRef.current, dataRef.current);
|
|
28
|
+
return index < 0 ? undefined : index;
|
|
29
|
+
}, [onBottomReached, paginatorRenderer, scrollToRow]);
|
|
30
|
+
// For non-virtualized tables, we need to add a ref to each row
|
|
31
|
+
// and scroll to the element
|
|
32
|
+
react_1.default.useEffect(function () {
|
|
33
|
+
var _a;
|
|
34
|
+
if (enableVirtualization ||
|
|
35
|
+
scrollToIndex === undefined ||
|
|
36
|
+
scrollToIndex === null ||
|
|
37
|
+
scrollToIndex < 0) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
(_a = rowRefs.current[pageRef.current[scrollToIndex].id]) === null || _a === void 0 ? void 0 : _a.scrollIntoView();
|
|
41
|
+
}, [enableVirtualization, scrollToIndex]);
|
|
42
|
+
var tableRowRef = react_1.default.useCallback(function (row) {
|
|
43
|
+
return function (element) {
|
|
44
|
+
rowRefs.current[row.id] = element;
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
return { scrollToIndex: scrollToIndex, tableRowRef: tableRowRef };
|
|
48
|
+
}
|
|
49
|
+
exports.useScrollToRow = useScrollToRow;
|
package/cjs/core/Tree/Tree.d.ts
CHANGED
|
@@ -68,6 +68,15 @@ export declare type TreeProps<T> = {
|
|
|
68
68
|
* }, [expandedNodes]);
|
|
69
69
|
*/
|
|
70
70
|
getNode: (node: T) => NodeData<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Virtualization is used to have a better performance with a lot of nodes.
|
|
73
|
+
*
|
|
74
|
+
* When enabled, Tree DOM structure will change - it will have a wrapper div
|
|
75
|
+
* to which `className` and `style` will be applied.
|
|
76
|
+
* @default false
|
|
77
|
+
* @beta
|
|
78
|
+
*/
|
|
79
|
+
enableVirtualization?: boolean;
|
|
71
80
|
} & Omit<CommonProps, 'title'>;
|
|
72
81
|
/**
|
|
73
82
|
* Tree component used to display a hierarchical structure of `TreeNodes`.
|