@itwin/itwinui-react 3.19.3 → 3.19.4

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 CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.19.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2633](https://github.com/iTwin/iTwinUI/pull/2633): Fixed horizontal scroll in `Tree` with `enableVirtualization` so that all nodes are equally wide instead of using their intrinsic width.
8
+ - c07a7166f1cbf5d8ec6c86389da2f9e1870af6d6: Fixed a theme bridge issue where `<Checkbox indeterminate>` was not displaying correctly in light theme.
9
+ - 6d73dbecc2a5d57d1c4979ddbc7ef931744aebeb: Added `aria-haspopup` attribute to `DropdownMenu`'s trigger.
10
+
3
11
  ## 3.19.3
4
12
 
5
13
  ### Patch Changes
@@ -177,6 +177,7 @@ const Menu = _react.forwardRef((props, ref) => {
177
177
  let reference = (0, _index.cloneElementWithRef)(trigger, (triggerChild) =>
178
178
  getReferenceProps(
179
179
  popover.getReferenceProps({
180
+ 'aria-haspopup': 'menu',
180
181
  ...triggerChild.props,
181
182
  'aria-expanded': popover.open,
182
183
  ref: (0, _index.mergeRefs)(triggerRef, popover.refs.setReference),
@@ -197,15 +197,32 @@ const TreeElement = _index.polymorphic.div('iui-tree', {
197
197
  const VirtualizedTree = _react.forwardRef(
198
198
  ({ flatNodesList, itemRenderer, scrollToIndex, ...rest }, ref) => {
199
199
  let parentRef = _react.useRef(null);
200
+ let virtualizerRootRef = _react.useRef(null);
200
201
  let getItemKey = _react.useCallback(
201
202
  (index) => flatNodesList[index].nodeProps.nodeId,
202
203
  [flatNodesList],
203
204
  );
205
+ let onVirtualizerChange = _react.useMemo(
206
+ () =>
207
+ debounce((virtualizer) => {
208
+ if (!virtualizer || !virtualizerRootRef.current) return;
209
+ virtualizerRootRef.current.style.width = '';
210
+ let widestNodeWidth = 0;
211
+ virtualizer.elementsCache.forEach((el) => {
212
+ if (el.clientWidth > widestNodeWidth)
213
+ widestNodeWidth = el.clientWidth;
214
+ });
215
+ if (widestNodeWidth)
216
+ virtualizerRootRef.current.style.width = `${widestNodeWidth}px`;
217
+ }, 100),
218
+ [],
219
+ );
204
220
  let { virtualizer, css: virtualizerCss } = (0, _index.useVirtualScroll)({
205
221
  count: flatNodesList.length,
206
222
  getScrollElement: () => parentRef.current,
207
223
  estimateSize: () => 39,
208
224
  getItemKey,
225
+ onChange: onVirtualizerChange,
209
226
  });
210
227
  (0, _index.useLayoutEffect)(() => {
211
228
  if (scrollToIndex) virtualizer.scrollToIndex(scrollToIndex);
@@ -235,13 +252,22 @@ const VirtualizedTree = _react.forwardRef(
235
252
  style: {
236
253
  minBlockSize: virtualizer.getTotalSize(),
237
254
  },
255
+ ref: virtualizerRootRef,
238
256
  },
239
257
  _react.createElement('slot', null),
240
258
  ),
241
259
  ),
242
260
  _react.createElement(
243
- _react.Fragment,
244
- null,
261
+ _TreeContext.VirtualizedTreeContext.Provider,
262
+ {
263
+ value: _react.useMemo(
264
+ () => ({
265
+ virtualizer,
266
+ onVirtualizerChange,
267
+ }),
268
+ [virtualizer, onVirtualizerChange],
269
+ ),
270
+ },
245
271
  virtualizer
246
272
  .getVirtualItems()
247
273
  .map((virtualItem) =>
@@ -252,3 +278,12 @@ const VirtualizedTree = _react.forwardRef(
252
278
  );
253
279
  },
254
280
  );
281
+ function debounce(callback, delay) {
282
+ let timeoutId;
283
+ return (...args) => {
284
+ if (timeoutId) window.clearTimeout(timeoutId);
285
+ timeoutId = window.setTimeout(() => {
286
+ callback(...args);
287
+ }, delay);
288
+ };
289
+ }
@@ -13,6 +13,9 @@ _export(exports, {
13
13
  TreeContext: function () {
14
14
  return TreeContext;
15
15
  },
16
+ VirtualizedTreeContext: function () {
17
+ return VirtualizedTreeContext;
18
+ },
16
19
  useTreeContext: function () {
17
20
  return useTreeContext;
18
21
  },
@@ -26,3 +29,4 @@ const useTreeContext = () => {
26
29
  throw new Error('TreeContext must be used within a TreeContext.Provider');
27
30
  return context;
28
31
  };
32
+ const VirtualizedTreeContext = _react.createContext(void 0);
@@ -52,6 +52,8 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
52
52
  groupSize,
53
53
  indexInGroup,
54
54
  } = (0, _TreeContext.useTreeContext)();
55
+ let { virtualizer, onVirtualizerChange } =
56
+ _react.useContext(_TreeContext.VirtualizedTreeContext) ?? {};
55
57
  let [isFocused, setIsFocused] = _react.useState(false);
56
58
  let nodeRef = _react.useRef(null);
57
59
  let onKeyDown = (event) => {
@@ -64,6 +66,7 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
64
66
  if (isNodeFocused) {
65
67
  if (isExpanded) {
66
68
  onExpanded(nodeId, false);
69
+ onVirtualizerChange?.(virtualizer);
67
70
  break;
68
71
  }
69
72
  if (parentNodeId) scrollToParent?.();
@@ -87,6 +90,7 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
87
90
  if (isNodeFocused) {
88
91
  if (!isExpanded && hasSubNodes) {
89
92
  onExpanded(nodeId, true);
93
+ onVirtualizerChange?.(virtualizer);
90
94
  break;
91
95
  }
92
96
  focusableElements[0]?.focus();
@@ -113,9 +117,10 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
113
117
  let onExpanderClick = _react.useCallback(
114
118
  (event) => {
115
119
  onExpanded(nodeId, !isExpanded);
120
+ onVirtualizerChange?.(virtualizer);
116
121
  event.stopPropagation();
117
122
  },
118
- [isExpanded, nodeId, onExpanded],
123
+ [isExpanded, nodeId, onExpanded, onVirtualizerChange, virtualizer],
119
124
  );
120
125
  return _react.createElement(
121
126
  _index.Box,
package/DEV-cjs/styles.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
- const e = '3.19.3';
3
+ const e = '3.19.4';
4
4
  const u = new Proxy(
5
5
  {},
6
6
  {
@@ -162,6 +162,7 @@ export const Menu = React.forwardRef((props, ref) => {
162
162
  let reference = cloneElementWithRef(trigger, (triggerChild) =>
163
163
  getReferenceProps(
164
164
  popover.getReferenceProps({
165
+ 'aria-haspopup': 'menu',
165
166
  ...triggerChild.props,
166
167
  'aria-expanded': popover.open,
167
168
  ref: mergeRefs(triggerRef, popover.refs.setReference),
@@ -8,7 +8,7 @@ import {
8
8
  useMergedRefs,
9
9
  useLayoutEffect,
10
10
  } from '../../utils/index.js';
11
- import { TreeContext } from './TreeContext.js';
11
+ import { TreeContext, VirtualizedTreeContext } from './TreeContext.js';
12
12
  export const Tree = (props) => {
13
13
  let {
14
14
  data,
@@ -191,15 +191,32 @@ let TreeElement = polymorphic.div('iui-tree', {
191
191
  let VirtualizedTree = React.forwardRef(
192
192
  ({ flatNodesList, itemRenderer, scrollToIndex, ...rest }, ref) => {
193
193
  let parentRef = React.useRef(null);
194
+ let virtualizerRootRef = React.useRef(null);
194
195
  let getItemKey = React.useCallback(
195
196
  (index) => flatNodesList[index].nodeProps.nodeId,
196
197
  [flatNodesList],
197
198
  );
199
+ let onVirtualizerChange = React.useMemo(
200
+ () =>
201
+ debounce((virtualizer) => {
202
+ if (!virtualizer || !virtualizerRootRef.current) return;
203
+ virtualizerRootRef.current.style.width = '';
204
+ let widestNodeWidth = 0;
205
+ virtualizer.elementsCache.forEach((el) => {
206
+ if (el.clientWidth > widestNodeWidth)
207
+ widestNodeWidth = el.clientWidth;
208
+ });
209
+ if (widestNodeWidth)
210
+ virtualizerRootRef.current.style.width = `${widestNodeWidth}px`;
211
+ }, 100),
212
+ [],
213
+ );
198
214
  let { virtualizer, css: virtualizerCss } = useVirtualScroll({
199
215
  count: flatNodesList.length,
200
216
  getScrollElement: () => parentRef.current,
201
217
  estimateSize: () => 39,
202
218
  getItemKey,
219
+ onChange: onVirtualizerChange,
203
220
  });
204
221
  useLayoutEffect(() => {
205
222
  if (scrollToIndex) virtualizer.scrollToIndex(scrollToIndex);
@@ -229,13 +246,22 @@ let VirtualizedTree = React.forwardRef(
229
246
  style: {
230
247
  minBlockSize: virtualizer.getTotalSize(),
231
248
  },
249
+ ref: virtualizerRootRef,
232
250
  },
233
251
  React.createElement('slot', null),
234
252
  ),
235
253
  ),
236
254
  React.createElement(
237
- React.Fragment,
238
- null,
255
+ VirtualizedTreeContext.Provider,
256
+ {
257
+ value: React.useMemo(
258
+ () => ({
259
+ virtualizer,
260
+ onVirtualizerChange,
261
+ }),
262
+ [virtualizer, onVirtualizerChange],
263
+ ),
264
+ },
239
265
  virtualizer
240
266
  .getVirtualItems()
241
267
  .map((virtualItem) =>
@@ -246,3 +272,12 @@ let VirtualizedTree = React.forwardRef(
246
272
  );
247
273
  },
248
274
  );
275
+ function debounce(callback, delay) {
276
+ let timeoutId;
277
+ return (...args) => {
278
+ if (timeoutId) window.clearTimeout(timeoutId);
279
+ timeoutId = window.setTimeout(() => {
280
+ callback(...args);
281
+ }, delay);
282
+ };
283
+ }
@@ -6,3 +6,4 @@ export const useTreeContext = () => {
6
6
  throw new Error('TreeContext must be used within a TreeContext.Provider');
7
7
  return context;
8
8
  };
9
+ export const VirtualizedTreeContext = React.createContext(void 0);
@@ -7,7 +7,7 @@ import {
7
7
  } from '../../utils/index.js';
8
8
  import cx from 'classnames';
9
9
  import { TreeNodeExpander } from './TreeNodeExpander.js';
10
- import { useTreeContext } from './TreeContext.js';
10
+ import { useTreeContext, VirtualizedTreeContext } from './TreeContext.js';
11
11
  export const TreeNode = React.forwardRef((props, forwardedRef) => {
12
12
  let {
13
13
  nodeId,
@@ -43,6 +43,8 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
43
43
  groupSize,
44
44
  indexInGroup,
45
45
  } = useTreeContext();
46
+ let { virtualizer, onVirtualizerChange } =
47
+ React.useContext(VirtualizedTreeContext) ?? {};
46
48
  let [isFocused, setIsFocused] = React.useState(false);
47
49
  let nodeRef = React.useRef(null);
48
50
  let onKeyDown = (event) => {
@@ -55,6 +57,7 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
55
57
  if (isNodeFocused) {
56
58
  if (isExpanded) {
57
59
  onExpanded(nodeId, false);
60
+ onVirtualizerChange?.(virtualizer);
58
61
  break;
59
62
  }
60
63
  if (parentNodeId) scrollToParent?.();
@@ -74,6 +77,7 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
74
77
  if (isNodeFocused) {
75
78
  if (!isExpanded && hasSubNodes) {
76
79
  onExpanded(nodeId, true);
80
+ onVirtualizerChange?.(virtualizer);
77
81
  break;
78
82
  }
79
83
  focusableElements[0]?.focus();
@@ -100,9 +104,10 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
100
104
  let onExpanderClick = React.useCallback(
101
105
  (event) => {
102
106
  onExpanded(nodeId, !isExpanded);
107
+ onVirtualizerChange?.(virtualizer);
103
108
  event.stopPropagation();
104
109
  },
105
- [isExpanded, nodeId, onExpanded],
110
+ [isExpanded, nodeId, onExpanded, onVirtualizerChange, virtualizer],
106
111
  );
107
112
  return React.createElement(
108
113
  Box,
package/DEV-esm/styles.js CHANGED
@@ -1,4 +1,4 @@
1
- const t = '3.19.3';
1
+ const t = '3.19.4';
2
2
  const u = new Proxy(
3
3
  {},
4
4
  {
@@ -177,6 +177,7 @@ const Menu = _react.forwardRef((props, ref) => {
177
177
  let reference = (0, _index.cloneElementWithRef)(trigger, (triggerChild) =>
178
178
  getReferenceProps(
179
179
  popover.getReferenceProps({
180
+ 'aria-haspopup': 'menu',
180
181
  ...triggerChild.props,
181
182
  'aria-expanded': popover.open,
182
183
  ref: (0, _index.mergeRefs)(triggerRef, popover.refs.setReference),
@@ -197,15 +197,32 @@ const TreeElement = _index.polymorphic.div('iui-tree', {
197
197
  const VirtualizedTree = _react.forwardRef(
198
198
  ({ flatNodesList, itemRenderer, scrollToIndex, ...rest }, ref) => {
199
199
  let parentRef = _react.useRef(null);
200
+ let virtualizerRootRef = _react.useRef(null);
200
201
  let getItemKey = _react.useCallback(
201
202
  (index) => flatNodesList[index].nodeProps.nodeId,
202
203
  [flatNodesList],
203
204
  );
205
+ let onVirtualizerChange = _react.useMemo(
206
+ () =>
207
+ debounce((virtualizer) => {
208
+ if (!virtualizer || !virtualizerRootRef.current) return;
209
+ virtualizerRootRef.current.style.width = '';
210
+ let widestNodeWidth = 0;
211
+ virtualizer.elementsCache.forEach((el) => {
212
+ if (el.clientWidth > widestNodeWidth)
213
+ widestNodeWidth = el.clientWidth;
214
+ });
215
+ if (widestNodeWidth)
216
+ virtualizerRootRef.current.style.width = `${widestNodeWidth}px`;
217
+ }, 100),
218
+ [],
219
+ );
204
220
  let { virtualizer, css: virtualizerCss } = (0, _index.useVirtualScroll)({
205
221
  count: flatNodesList.length,
206
222
  getScrollElement: () => parentRef.current,
207
223
  estimateSize: () => 39,
208
224
  getItemKey,
225
+ onChange: onVirtualizerChange,
209
226
  });
210
227
  (0, _index.useLayoutEffect)(() => {
211
228
  if (scrollToIndex) virtualizer.scrollToIndex(scrollToIndex);
@@ -235,13 +252,22 @@ const VirtualizedTree = _react.forwardRef(
235
252
  style: {
236
253
  minBlockSize: virtualizer.getTotalSize(),
237
254
  },
255
+ ref: virtualizerRootRef,
238
256
  },
239
257
  _react.createElement('slot', null),
240
258
  ),
241
259
  ),
242
260
  _react.createElement(
243
- _react.Fragment,
244
- null,
261
+ _TreeContext.VirtualizedTreeContext.Provider,
262
+ {
263
+ value: _react.useMemo(
264
+ () => ({
265
+ virtualizer,
266
+ onVirtualizerChange,
267
+ }),
268
+ [virtualizer, onVirtualizerChange],
269
+ ),
270
+ },
245
271
  virtualizer
246
272
  .getVirtualItems()
247
273
  .map((virtualItem) =>
@@ -252,3 +278,12 @@ const VirtualizedTree = _react.forwardRef(
252
278
  );
253
279
  },
254
280
  );
281
+ function debounce(callback, delay) {
282
+ let timeoutId;
283
+ return (...args) => {
284
+ if (timeoutId) window.clearTimeout(timeoutId);
285
+ timeoutId = window.setTimeout(() => {
286
+ callback(...args);
287
+ }, delay);
288
+ };
289
+ }
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import type { Virtualizer } from '@tanstack/react-virtual';
2
3
  export type TreeContextProps = {
3
4
  /**
4
5
  * Depth of the node.
@@ -31,3 +32,7 @@ export type TreeContextProps = {
31
32
  };
32
33
  export declare const TreeContext: React.Context<TreeContextProps | undefined>;
33
34
  export declare const useTreeContext: () => TreeContextProps;
35
+ export declare const VirtualizedTreeContext: React.Context<{
36
+ virtualizer?: Virtualizer<Element, Element>;
37
+ onVirtualizerChange?: (virtualizer?: Virtualizer<Element, Element>) => void;
38
+ } | undefined>;
@@ -13,6 +13,9 @@ _export(exports, {
13
13
  TreeContext: function () {
14
14
  return TreeContext;
15
15
  },
16
+ VirtualizedTreeContext: function () {
17
+ return VirtualizedTreeContext;
18
+ },
16
19
  useTreeContext: function () {
17
20
  return useTreeContext;
18
21
  },
@@ -26,3 +29,4 @@ const useTreeContext = () => {
26
29
  throw new Error('TreeContext must be used within a TreeContext.Provider');
27
30
  return context;
28
31
  };
32
+ const VirtualizedTreeContext = _react.createContext(void 0);
@@ -52,6 +52,8 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
52
52
  groupSize,
53
53
  indexInGroup,
54
54
  } = (0, _TreeContext.useTreeContext)();
55
+ let { virtualizer, onVirtualizerChange } =
56
+ _react.useContext(_TreeContext.VirtualizedTreeContext) ?? {};
55
57
  let [isFocused, setIsFocused] = _react.useState(false);
56
58
  let nodeRef = _react.useRef(null);
57
59
  let onKeyDown = (event) => {
@@ -64,6 +66,7 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
64
66
  if (isNodeFocused) {
65
67
  if (isExpanded) {
66
68
  onExpanded(nodeId, false);
69
+ onVirtualizerChange?.(virtualizer);
67
70
  break;
68
71
  }
69
72
  if (parentNodeId) scrollToParent?.();
@@ -87,6 +90,7 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
87
90
  if (isNodeFocused) {
88
91
  if (!isExpanded && hasSubNodes) {
89
92
  onExpanded(nodeId, true);
93
+ onVirtualizerChange?.(virtualizer);
90
94
  break;
91
95
  }
92
96
  focusableElements[0]?.focus();
@@ -113,9 +117,10 @@ const TreeNode = _react.forwardRef((props, forwardedRef) => {
113
117
  let onExpanderClick = _react.useCallback(
114
118
  (event) => {
115
119
  onExpanded(nodeId, !isExpanded);
120
+ onVirtualizerChange?.(virtualizer);
116
121
  event.stopPropagation();
117
122
  },
118
- [isExpanded, nodeId, onExpanded],
123
+ [isExpanded, nodeId, onExpanded, onVirtualizerChange, virtualizer],
119
124
  );
120
125
  return _react.createElement(
121
126
  _index.Box,
package/cjs/styles.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
3
- const e = '3.19.3';
3
+ const e = '3.19.4';
4
4
  const u = new Proxy(
5
5
  {},
6
6
  {
@@ -162,6 +162,7 @@ export const Menu = React.forwardRef((props, ref) => {
162
162
  let reference = cloneElementWithRef(trigger, (triggerChild) =>
163
163
  getReferenceProps(
164
164
  popover.getReferenceProps({
165
+ 'aria-haspopup': 'menu',
165
166
  ...triggerChild.props,
166
167
  'aria-expanded': popover.open,
167
168
  ref: mergeRefs(triggerRef, popover.refs.setReference),
@@ -8,7 +8,7 @@ import {
8
8
  useMergedRefs,
9
9
  useLayoutEffect,
10
10
  } from '../../utils/index.js';
11
- import { TreeContext } from './TreeContext.js';
11
+ import { TreeContext, VirtualizedTreeContext } from './TreeContext.js';
12
12
  export const Tree = (props) => {
13
13
  let {
14
14
  data,
@@ -191,15 +191,32 @@ let TreeElement = polymorphic.div('iui-tree', {
191
191
  let VirtualizedTree = React.forwardRef(
192
192
  ({ flatNodesList, itemRenderer, scrollToIndex, ...rest }, ref) => {
193
193
  let parentRef = React.useRef(null);
194
+ let virtualizerRootRef = React.useRef(null);
194
195
  let getItemKey = React.useCallback(
195
196
  (index) => flatNodesList[index].nodeProps.nodeId,
196
197
  [flatNodesList],
197
198
  );
199
+ let onVirtualizerChange = React.useMemo(
200
+ () =>
201
+ debounce((virtualizer) => {
202
+ if (!virtualizer || !virtualizerRootRef.current) return;
203
+ virtualizerRootRef.current.style.width = '';
204
+ let widestNodeWidth = 0;
205
+ virtualizer.elementsCache.forEach((el) => {
206
+ if (el.clientWidth > widestNodeWidth)
207
+ widestNodeWidth = el.clientWidth;
208
+ });
209
+ if (widestNodeWidth)
210
+ virtualizerRootRef.current.style.width = `${widestNodeWidth}px`;
211
+ }, 100),
212
+ [],
213
+ );
198
214
  let { virtualizer, css: virtualizerCss } = useVirtualScroll({
199
215
  count: flatNodesList.length,
200
216
  getScrollElement: () => parentRef.current,
201
217
  estimateSize: () => 39,
202
218
  getItemKey,
219
+ onChange: onVirtualizerChange,
203
220
  });
204
221
  useLayoutEffect(() => {
205
222
  if (scrollToIndex) virtualizer.scrollToIndex(scrollToIndex);
@@ -229,13 +246,22 @@ let VirtualizedTree = React.forwardRef(
229
246
  style: {
230
247
  minBlockSize: virtualizer.getTotalSize(),
231
248
  },
249
+ ref: virtualizerRootRef,
232
250
  },
233
251
  React.createElement('slot', null),
234
252
  ),
235
253
  ),
236
254
  React.createElement(
237
- React.Fragment,
238
- null,
255
+ VirtualizedTreeContext.Provider,
256
+ {
257
+ value: React.useMemo(
258
+ () => ({
259
+ virtualizer,
260
+ onVirtualizerChange,
261
+ }),
262
+ [virtualizer, onVirtualizerChange],
263
+ ),
264
+ },
239
265
  virtualizer
240
266
  .getVirtualItems()
241
267
  .map((virtualItem) =>
@@ -246,3 +272,12 @@ let VirtualizedTree = React.forwardRef(
246
272
  );
247
273
  },
248
274
  );
275
+ function debounce(callback, delay) {
276
+ let timeoutId;
277
+ return (...args) => {
278
+ if (timeoutId) window.clearTimeout(timeoutId);
279
+ timeoutId = window.setTimeout(() => {
280
+ callback(...args);
281
+ }, delay);
282
+ };
283
+ }
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import type { Virtualizer } from '@tanstack/react-virtual';
2
3
  export type TreeContextProps = {
3
4
  /**
4
5
  * Depth of the node.
@@ -31,3 +32,7 @@ export type TreeContextProps = {
31
32
  };
32
33
  export declare const TreeContext: React.Context<TreeContextProps | undefined>;
33
34
  export declare const useTreeContext: () => TreeContextProps;
35
+ export declare const VirtualizedTreeContext: React.Context<{
36
+ virtualizer?: Virtualizer<Element, Element>;
37
+ onVirtualizerChange?: (virtualizer?: Virtualizer<Element, Element>) => void;
38
+ } | undefined>;
@@ -6,3 +6,4 @@ export const useTreeContext = () => {
6
6
  throw new Error('TreeContext must be used within a TreeContext.Provider');
7
7
  return context;
8
8
  };
9
+ export const VirtualizedTreeContext = React.createContext(void 0);
@@ -7,7 +7,7 @@ import {
7
7
  } from '../../utils/index.js';
8
8
  import cx from 'classnames';
9
9
  import { TreeNodeExpander } from './TreeNodeExpander.js';
10
- import { useTreeContext } from './TreeContext.js';
10
+ import { useTreeContext, VirtualizedTreeContext } from './TreeContext.js';
11
11
  export const TreeNode = React.forwardRef((props, forwardedRef) => {
12
12
  let {
13
13
  nodeId,
@@ -43,6 +43,8 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
43
43
  groupSize,
44
44
  indexInGroup,
45
45
  } = useTreeContext();
46
+ let { virtualizer, onVirtualizerChange } =
47
+ React.useContext(VirtualizedTreeContext) ?? {};
46
48
  let [isFocused, setIsFocused] = React.useState(false);
47
49
  let nodeRef = React.useRef(null);
48
50
  let onKeyDown = (event) => {
@@ -55,6 +57,7 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
55
57
  if (isNodeFocused) {
56
58
  if (isExpanded) {
57
59
  onExpanded(nodeId, false);
60
+ onVirtualizerChange?.(virtualizer);
58
61
  break;
59
62
  }
60
63
  if (parentNodeId) scrollToParent?.();
@@ -74,6 +77,7 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
74
77
  if (isNodeFocused) {
75
78
  if (!isExpanded && hasSubNodes) {
76
79
  onExpanded(nodeId, true);
80
+ onVirtualizerChange?.(virtualizer);
77
81
  break;
78
82
  }
79
83
  focusableElements[0]?.focus();
@@ -100,9 +104,10 @@ export const TreeNode = React.forwardRef((props, forwardedRef) => {
100
104
  let onExpanderClick = React.useCallback(
101
105
  (event) => {
102
106
  onExpanded(nodeId, !isExpanded);
107
+ onVirtualizerChange?.(virtualizer);
103
108
  event.stopPropagation();
104
109
  },
105
- [isExpanded, nodeId, onExpanded],
110
+ [isExpanded, nodeId, onExpanded, onVirtualizerChange, virtualizer],
106
111
  );
107
112
  return React.createElement(
108
113
  Box,
package/esm/styles.js CHANGED
@@ -1,4 +1,4 @@
1
- const t = '3.19.3';
1
+ const t = '3.19.4';
2
2
  const u = new Proxy(
3
3
  {},
4
4
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "3.19.3",
3
+ "version": "3.19.4",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "type": "module",