@itwin/itwinui-react 1.38.1 → 1.39.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 (48) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/cjs/core/Carousel/Carousel.js +21 -12
  3. package/cjs/core/Carousel/CarouselContext.d.ts +4 -2
  4. package/cjs/core/Carousel/CarouselDotsList.js +1 -0
  5. package/cjs/core/Carousel/CarouselNavigation.js +8 -10
  6. package/cjs/core/Carousel/CarouselSlide.js +3 -7
  7. package/cjs/core/Carousel/CarouselSlider.js +23 -28
  8. package/cjs/core/ColorPicker/ColorPickerContext.d.ts +2 -2
  9. package/cjs/core/ComboBox/ComboBox.js +9 -7
  10. package/cjs/core/ComboBox/ComboBoxDropdown.d.ts +5 -6
  11. package/cjs/core/ComboBox/ComboBoxInput.js +27 -9
  12. package/cjs/core/ComboBox/ComboBoxMenu.js +10 -2
  13. package/cjs/core/ComboBox/helpers.d.ts +1 -1
  14. package/cjs/core/DatePicker/DatePicker.d.ts +1 -1
  15. package/cjs/core/Table/Table.js +32 -22
  16. package/cjs/core/Table/TablePaginator.js +1 -1
  17. package/cjs/core/Table/filters/tableFilters.d.ts +3 -3
  18. package/cjs/core/Table/hooks/useExpanderCell.js +11 -1
  19. package/cjs/core/Toast/Toaster.js +97 -18
  20. package/cjs/core/utils/components/Popover.d.ts +1 -18
  21. package/cjs/core/utils/components/WithCSSTransition.d.ts +1 -2
  22. package/cjs/core/utils/components/icons.d.ts +4 -4
  23. package/cjs/core/utils/hooks/useOverflow.js +4 -2
  24. package/cjs/core/utils/hooks/useTheme.d.ts +1 -1
  25. package/esm/core/Carousel/Carousel.js +21 -12
  26. package/esm/core/Carousel/CarouselContext.d.ts +4 -2
  27. package/esm/core/Carousel/CarouselDotsList.js +1 -0
  28. package/esm/core/Carousel/CarouselNavigation.js +8 -10
  29. package/esm/core/Carousel/CarouselSlide.js +3 -7
  30. package/esm/core/Carousel/CarouselSlider.js +24 -29
  31. package/esm/core/ColorPicker/ColorPickerContext.d.ts +2 -2
  32. package/esm/core/ComboBox/ComboBox.js +9 -7
  33. package/esm/core/ComboBox/ComboBoxDropdown.d.ts +5 -6
  34. package/esm/core/ComboBox/ComboBoxInput.js +27 -9
  35. package/esm/core/ComboBox/ComboBoxMenu.js +10 -2
  36. package/esm/core/ComboBox/helpers.d.ts +1 -1
  37. package/esm/core/DatePicker/DatePicker.d.ts +1 -1
  38. package/esm/core/Table/Table.js +32 -22
  39. package/esm/core/Table/TablePaginator.js +1 -1
  40. package/esm/core/Table/filters/tableFilters.d.ts +3 -3
  41. package/esm/core/Table/hooks/useExpanderCell.js +8 -1
  42. package/esm/core/Toast/Toaster.js +75 -19
  43. package/esm/core/utils/components/Popover.d.ts +1 -18
  44. package/esm/core/utils/components/WithCSSTransition.d.ts +1 -2
  45. package/esm/core/utils/components/icons.d.ts +4 -4
  46. package/esm/core/utils/hooks/useOverflow.js +4 -2
  47. package/esm/core/utils/hooks/useTheme.d.ts +1 -1
  48. package/package.json +24 -39
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.39.0](https://www.github.com/iTwin/iTwinUI-react/compare/v1.38.0...v1.39.0) (2022-06-03)
4
+
5
+ ### What's new
6
+
7
+ * Add support of react 18 ([#656](https://www.github.com/iTwin/iTwinUI-react/issues/656)) ([b7a4c7b](https://www.github.com/iTwin/iTwinUI-react/commit/b7a4c7ba1e26445308dcb7f1fd5a374743de4e6f))
8
+ * **Combobox:** Virtualization ([#539](https://www.github.com/iTwin/iTwinUI-react/issues/539)) ([9e93871](https://www.github.com/iTwin/iTwinUI-react/commit/9e93871c59935a39f6ee1d633d96df04b78f33a1))
9
+
10
+ ### Fixes
11
+
12
+ * **Carousel:** Use event handler instead of useEffect for scroll ([#683](https://www.github.com/iTwin/iTwinUI-react/issues/683)) ([bcf125b](https://www.github.com/iTwin/iTwinUI-react/commit/bcf125be76495352a06c063bc7a0d5d2a884c860))
13
+ * **Toaster:** Fix inital position setting ([#687](https://www.github.com/iTwin/iTwinUI-react/issues/687)) ([c58b747](https://www.github.com/iTwin/iTwinUI-react/commit/c58b74786bf90a165993afb2eec926f74b37a1eb))
14
+
3
15
  ### [1.38.1](https://www.github.com/iTwin/iTwinUI-react/compare/v1.38.0...v1.38.1) (2022-05-23)
4
16
 
5
17
  ### Fixes
@@ -64,19 +64,24 @@ exports.Carousel = Object.assign(react_1.default.forwardRef(function (props, ref
64
64
  var id = react_1.default.useState(function () { var _a; return (_a = props.id) !== null && _a !== void 0 ? _a : "iui-carousel-".concat((0, utils_1.getRandomValue)(10)); })[0];
65
65
  (0, utils_1.useTheme)();
66
66
  var isManuallyUpdating = react_1.default.useRef(false);
67
- var scrollInstantly = react_1.default.useRef(false);
68
67
  var carouselRef = react_1.default.useRef(null);
69
68
  var refs = (0, utils_1.useMergedRefs)(carouselRef, ref);
70
- var _b = react_1.default.useState(userActiveIndex), currentIndex = _b[0], _setCurrentIndex = _b[1];
69
+ var _b = react_1.default.useState(userActiveIndex), currentIndex = _b[0], setCurrentIndex = _b[1];
70
+ var scrollToSlide = react_1.default.useRef(function () { }); // stub function populated in CarouselSlider
71
+ var justMounted = react_1.default.useRef(true);
71
72
  react_1.default.useEffect(function () {
72
- _setCurrentIndex(userActiveIndex);
73
- }, [userActiveIndex]);
74
- var setCurrentIndex = react_1.default.useCallback(function (index) {
75
73
  var _a;
76
- _setCurrentIndex(index);
77
- isManuallyUpdating.current = true;
78
- (_a = carouselRef.current) === null || _a === void 0 ? void 0 : _a.focus();
79
- }, []);
74
+ setCurrentIndex(userActiveIndex);
75
+ scrollToSlide.current(userActiveIndex, {
76
+ instant: justMounted.current,
77
+ });
78
+ // re-focus the carousel for keyboard nav, but not on first mount
79
+ // because it shows outline and might interfere with other components
80
+ if (!justMounted.current) {
81
+ (_a = carouselRef.current) === null || _a === void 0 ? void 0 : _a.focus({ preventScroll: true });
82
+ }
83
+ justMounted.current = false;
84
+ }, [userActiveIndex]);
80
85
  var _c = react_1.default.useState(0), slideCount = _c[0], setSlideCount = _c[1];
81
86
  var _d = react_1.default.useState({}), keysPressed = _d[0], setKeysPressed = _d[1];
82
87
  var handleKeyDown = function (event) {
@@ -94,12 +99,16 @@ exports.Carousel = Object.assign(react_1.default.forwardRef(function (props, ref
94
99
  switch (event.key) {
95
100
  case 'ArrowLeft': {
96
101
  setKeysPressed(function (old) { return (__assign(__assign({}, old), { ArrowLeft: false })); });
97
- setCurrentIndex(function (old) { return (slideCount + old - 1) % slideCount; });
102
+ var prevIndex = (slideCount + currentIndex - 1) % slideCount;
103
+ scrollToSlide.current(prevIndex);
104
+ setCurrentIndex(prevIndex);
98
105
  break;
99
106
  }
100
107
  case 'ArrowRight': {
101
108
  setKeysPressed(function (old) { return (__assign(__assign({}, old), { ArrowRight: false })); });
102
- setCurrentIndex(function (old) { return (slideCount + old + 1) % slideCount; });
109
+ var nextIndex = (slideCount + currentIndex + 1) % slideCount;
110
+ scrollToSlide.current(nextIndex);
111
+ setCurrentIndex(nextIndex);
103
112
  break;
104
113
  }
105
114
  }
@@ -118,7 +127,7 @@ exports.Carousel = Object.assign(react_1.default.forwardRef(function (props, ref
118
127
  keysPressed: keysPressed,
119
128
  idPrefix: id,
120
129
  isManuallyUpdating: isManuallyUpdating,
121
- scrollInstantly: scrollInstantly,
130
+ scrollToSlide: scrollToSlide,
122
131
  } }, children)));
123
132
  }), {
124
133
  Slider: CarouselSlider_1.CarouselSlider,
@@ -31,7 +31,9 @@ export declare const CarouselContext: React.Context<{
31
31
  */
32
32
  isManuallyUpdating: React.MutableRefObject<boolean>;
33
33
  /**
34
- * Ref object used to skip smooth scrolling when button is clicked too many times.
34
+ * Function that scrolls to the current slide. Should be called on all managed events (clicks and keydowns).
35
35
  */
36
- scrollInstantly: React.MutableRefObject<boolean>;
36
+ scrollToSlide: React.MutableRefObject<(slideIndex: number, options?: {
37
+ instant?: boolean;
38
+ }) => void>;
37
39
  } | undefined>;
@@ -69,6 +69,7 @@ exports.CarouselDotsList = react_1.default.forwardRef(function (props, ref) {
69
69
  var handleSlideChange = react_1.default.useCallback(function (index) {
70
70
  if (context) {
71
71
  context.setCurrentIndex(index);
72
+ context.scrollToSlide.current(index);
72
73
  }
73
74
  onSlideChange === null || onSlideChange === void 0 ? void 0 : onSlideChange(index);
74
75
  }, [context, onSlideChange]);
@@ -43,13 +43,12 @@ var PreviousButton = react_1.default.forwardRef(function (props, ref) {
43
43
  if (!context) {
44
44
  throw new Error('CarouselNavigation should be used inside Carousel');
45
45
  }
46
- var slideCount = context.slideCount, setCurrentIndex = context.setCurrentIndex, keysPressed = context.keysPressed, scrollInstantly = context.scrollInstantly;
46
+ var slideCount = context.slideCount, currentIndex = context.currentIndex, setCurrentIndex = context.setCurrentIndex, keysPressed = context.keysPressed, scrollToSlide = context.scrollToSlide;
47
47
  return (react_1.default.createElement(Buttons_1.IconButton, __assign({ styleType: 'borderless', size: 'small', tabIndex: -1, "data-pressed": keysPressed['ArrowLeft'] || undefined, ref: ref }, props, { onClick: function (e) {
48
48
  var _a;
49
- if (e.detail > 3) {
50
- scrollInstantly.current = true;
51
- }
52
- setCurrentIndex(function (old) { return (slideCount + old - 1) % slideCount; });
49
+ var prevIndex = (slideCount + currentIndex - 1) % slideCount;
50
+ setCurrentIndex(prevIndex);
51
+ scrollToSlide.current(prevIndex, { instant: e.detail > 3 });
53
52
  (_a = props === null || props === void 0 ? void 0 : props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
54
53
  } }),
55
54
  react_1.default.createElement(ChevronLeft_1.default, null)));
@@ -60,13 +59,12 @@ var NextButton = react_1.default.forwardRef(function (props, ref) {
60
59
  if (!context) {
61
60
  throw new Error('CarouselNavigation should be used inside Carousel');
62
61
  }
63
- var slideCount = context.slideCount, setCurrentIndex = context.setCurrentIndex, keysPressed = context.keysPressed, scrollInstantly = context.scrollInstantly;
62
+ var slideCount = context.slideCount, currentIndex = context.currentIndex, setCurrentIndex = context.setCurrentIndex, keysPressed = context.keysPressed, scrollToSlide = context.scrollToSlide;
64
63
  return (react_1.default.createElement(Buttons_1.IconButton, __assign({ styleType: 'borderless', size: 'small', tabIndex: -1, "data-pressed": keysPressed['ArrowRight'] || undefined, ref: ref }, props, { onClick: function (e) {
65
64
  var _a;
66
- if (e.detail > 3) {
67
- scrollInstantly.current = true;
68
- }
69
- setCurrentIndex(function (old) { return (slideCount + old + 1) % slideCount; });
65
+ var nextIndex = (slideCount + currentIndex + 1) % slideCount;
66
+ setCurrentIndex(nextIndex);
67
+ scrollToSlide.current(nextIndex, { instant: e.detail > 3 });
70
68
  (_a = props === null || props === void 0 ? void 0 : props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, e);
71
69
  } }),
72
70
  react_1.default.createElement(ChevronRight_1.default, null)));
@@ -46,17 +46,13 @@ exports.CarouselSlide = react_1.default.forwardRef(function (props, ref) {
46
46
  if (!context || index == null) {
47
47
  throw new Error('CarouselSlide must be used within Carousel');
48
48
  }
49
- var currentIndex = context.currentIndex, isManuallyUpdating = context.isManuallyUpdating, setCurrentIndex = context.setCurrentIndex;
49
+ var isManuallyUpdating = context.isManuallyUpdating, setCurrentIndex = context.setCurrentIndex;
50
50
  var updateActiveIndexOnScroll = react_1.default.useCallback(function () {
51
51
  // only update index if scroll was triggered by browser
52
- if (!isManuallyUpdating.current && currentIndex !== index) {
52
+ if (!isManuallyUpdating.current) {
53
53
  setCurrentIndex(index);
54
54
  }
55
- // when manual scroll completes, reset the state of `isManuallyUpdating` so that it's ready for future actions
56
- if (currentIndex === index) {
57
- isManuallyUpdating.current = false;
58
- }
59
- }, [currentIndex, index, isManuallyUpdating, setCurrentIndex]);
55
+ }, [index, isManuallyUpdating, setCurrentIndex]);
60
56
  var intersectionRef = (0, utils_1.useIntersection)(updateActiveIndexOnScroll, { threshold: 0.5 }, false);
61
57
  var refs = (0, utils_1.useMergedRefs)(intersectionRef, ref);
62
58
  return (react_1.default.createElement("li", __assign({ className: (0, classnames_1.default)('iui-carousel-slider-item', className), role: 'tabpanel', "aria-roledescription": 'slide', ref: refs }, rest), children));
@@ -43,7 +43,7 @@ exports.CarouselSlider = react_1.default.forwardRef(function (props, ref) {
43
43
  if (!context) {
44
44
  throw new Error('CarouselSlider must be used within Carousel');
45
45
  }
46
- var currentIndex = context.currentIndex, setSlideCount = context.setSlideCount, idPrefix = context.idPrefix, isManuallyUpdating = context.isManuallyUpdating, scrollInstantly = context.scrollInstantly;
46
+ var setSlideCount = context.setSlideCount, idPrefix = context.idPrefix, scrollToSlide = context.scrollToSlide, isManuallyUpdating = context.isManuallyUpdating;
47
47
  var items = react_1.default.useMemo(function () {
48
48
  var _a;
49
49
  return (_a = react_1.default.Children.map(children, function (child, index) {
@@ -58,37 +58,32 @@ exports.CarouselSlider = react_1.default.forwardRef(function (props, ref) {
58
58
  react_1.default.useLayoutEffect(function () {
59
59
  setSlideCount(items.length);
60
60
  }, [items.length, setSlideCount]);
61
- var _a = react_1.default.useState(), width = _a[0], setWidth = _a[1];
62
- var resizeRef = (0, utils_1.useResizeObserver)(function (_a) {
63
- var width = _a.width;
64
- return setWidth(width);
65
- })[0];
66
61
  var sliderRef = react_1.default.useRef(null);
67
- var refs = (0, utils_1.useMergedRefs)(sliderRef, resizeRef, ref);
68
- var justMounted = react_1.default.useRef(true);
69
- var previousWidth = react_1.default.useRef();
70
- react_1.default.useLayoutEffect(function () {
71
- var _a, _b, _c;
72
- var slideToShow = (_a = sliderRef.current) === null || _a === void 0 ? void 0 : _a.children.item(currentIndex);
73
- if (!sliderRef.current ||
74
- !slideToShow ||
75
- (!isManuallyUpdating.current && previousWidth.current === width)) {
62
+ var refs = (0, utils_1.useMergedRefs)(sliderRef, ref);
63
+ scrollToSlide.current = function (slideIndex, _a) {
64
+ var _b, _c, _d;
65
+ var _e = _a === void 0 ? {} : _a, instant = _e.instant;
66
+ isManuallyUpdating.current = true; // start manual update
67
+ var slideToShow = (_b = sliderRef.current) === null || _b === void 0 ? void 0 : _b.children.item(slideIndex);
68
+ if (!sliderRef.current || !slideToShow) {
76
69
  return;
77
70
  }
78
- // instant scroll on first mount
79
- if (justMounted.current) {
80
- scrollInstantly.current = true;
81
- justMounted.current = false;
82
- }
83
- var motionOk = (_c = (_b = (0, utils_1.getWindow)()) === null || _b === void 0 ? void 0 : _b.matchMedia('(prefers-reduced-motion: no-preference)')) === null || _c === void 0 ? void 0 : _c.matches;
71
+ var motionOk = (_d = (_c = (0, utils_1.getWindow)()) === null || _c === void 0 ? void 0 : _c.matchMedia('(prefers-reduced-motion: no-preference)')) === null || _d === void 0 ? void 0 : _d.matches;
84
72
  sliderRef.current.scrollTo({
85
73
  left: slideToShow.offsetLeft - sliderRef.current.offsetLeft,
86
- behavior: (scrollInstantly.current || !motionOk
87
- ? 'instant'
88
- : 'smooth'), // scrollTo accepts 'instant' but ScrollBehavior type is wrong
74
+ behavior: (instant || !motionOk ? 'instant' : 'smooth'), // scrollTo accepts 'instant' but ScrollBehavior type is wrong
89
75
  });
90
- scrollInstantly.current = false;
91
- previousWidth.current = width;
92
- }, [currentIndex, isManuallyUpdating, scrollInstantly, width]);
93
- return (react_1.default.createElement("ol", __assign({ "aria-live": 'polite', className: (0, classnames_1.default)('iui-carousel-slider', className), ref: refs }, rest), items));
76
+ };
77
+ var scrollTimeout = react_1.default.useRef();
78
+ // reset isManuallyUpdating.current to false after the last scroll event
79
+ var handleOnScroll = react_1.default.useCallback(function () {
80
+ var _a, _b;
81
+ if (scrollTimeout.current) {
82
+ (_a = (0, utils_1.getWindow)()) === null || _a === void 0 ? void 0 : _a.clearTimeout(scrollTimeout.current);
83
+ }
84
+ scrollTimeout.current = (_b = (0, utils_1.getWindow)()) === null || _b === void 0 ? void 0 : _b.setTimeout(function () {
85
+ isManuallyUpdating.current = false;
86
+ }, 100);
87
+ }, [isManuallyUpdating]);
88
+ return (react_1.default.createElement("ol", __assign({ "aria-live": 'polite', className: (0, classnames_1.default)('iui-carousel-slider', className), ref: refs, onScroll: handleOnScroll }, rest), items));
94
89
  });
@@ -5,7 +5,7 @@ export declare const ColorPickerContext: React.Context<{
5
5
  setActiveColor: (color: ColorValue | ((prevColor: ColorValue) => ColorValue)) => void;
6
6
  hsvColor: HsvColor;
7
7
  onChangeComplete?: ((color: ColorValue) => void) | undefined;
8
- applyHsvColorChange: (newColor: HsvColor, selectionChanged: boolean, newColorValue?: ColorValue | undefined) => void;
8
+ applyHsvColorChange: (newColor: HsvColor, selectionChanged: boolean, newColorValue?: ColorValue) => void;
9
9
  showAlpha: boolean;
10
10
  } | undefined>;
11
11
  export declare const useColorPickerContext: () => {
@@ -13,6 +13,6 @@ export declare const useColorPickerContext: () => {
13
13
  setActiveColor: (color: ColorValue | ((prevColor: ColorValue) => ColorValue)) => void;
14
14
  hsvColor: HsvColor;
15
15
  onChangeComplete?: ((color: ColorValue) => void) | undefined;
16
- applyHsvColorChange: (newColor: HsvColor, selectionChanged: boolean, newColorValue?: ColorValue | undefined) => void;
16
+ applyHsvColorChange: (newColor: HsvColor, selectionChanged: boolean, newColorValue?: ColorValue) => void;
17
17
  showAlpha: boolean;
18
18
  };
@@ -106,6 +106,7 @@ var ComboBox = function (props) {
106
106
  if (isOpen) {
107
107
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); // Focus the input
108
108
  setFilteredOptions(options); // Reset the filtered list
109
+ dispatch(['focus']);
109
110
  }
110
111
  // When the dropdown closes
111
112
  else {
@@ -128,6 +129,7 @@ var ComboBox = function (props) {
128
129
  var _g = react_1.default.useState(options), filteredOptions = _g[0], setFilteredOptions = _g[1];
129
130
  react_1.default.useEffect(function () {
130
131
  setFilteredOptions(options);
132
+ dispatch(['focus']);
131
133
  }, [options]);
132
134
  // Filter options based on input value
133
135
  var _h = react_1.default.useState((_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.value) !== null && _a !== void 0 ? _a : ''), inputValue = _h[0], setInputValue = _h[1];
@@ -139,12 +141,11 @@ var ComboBox = function (props) {
139
141
  setFilteredOptions((_a = filterFunction === null || filterFunction === void 0 ? void 0 : filterFunction(options, value)) !== null && _a !== void 0 ? _a : options.filter(function (option) {
140
142
  return option.label.toLowerCase().includes(value.toLowerCase());
141
143
  }));
144
+ if (focusedIndex != -1) {
145
+ dispatch(['focus', -1]);
146
+ }
142
147
  (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onChange) === null || _b === void 0 ? void 0 : _b.call(inputProps, event);
143
- }, [filterFunction, inputProps, options]);
144
- // Reset focused item when filteredOptions change
145
- react_1.default.useEffect(function () {
146
- dispatch(['focus']);
147
- }, [filteredOptions]);
148
+ }, [filterFunction, focusedIndex, inputProps, options]);
148
149
  // When the value prop changes, update the selectedIndex
149
150
  react_1.default.useEffect(function () {
150
151
  dispatch([
@@ -163,7 +164,7 @@ var ComboBox = function (props) {
163
164
  (_b = onChangeProp.current) === null || _b === void 0 ? void 0 : _b.call(onChangeProp, value);
164
165
  }
165
166
  }, [options, selectedIndex, valueProp]);
166
- var getMenuItem = react_1.default.useCallback(function (option) {
167
+ var getMenuItem = react_1.default.useCallback(function (option, filteredIndex) {
167
168
  var optionId = getOptionId(option, id);
168
169
  var __originalIndex = optionsExtraInfoRef.current[optionId].__originalIndex;
169
170
  var customItem = itemRenderer
@@ -186,12 +187,13 @@ var ComboBox = function (props) {
186
187
  'iui-focused': focusedIndex === __originalIndex,
187
188
  }),
188
189
  'data-iui-index': __originalIndex,
190
+ 'data-iui-filtered-index': filteredIndex,
189
191
  ref: (0, utils_1.mergeRefs)(customItem.props.ref, function (el) {
190
192
  if (!enableVirtualization && focusedIndex === __originalIndex) {
191
193
  el === null || el === void 0 ? void 0 : el.scrollIntoView({ block: 'nearest' });
192
194
  }
193
195
  }),
194
- })) : (react_1.default.createElement(ComboBoxMenuItem_1.ComboBoxMenuItem, __assign({ key: optionId, id: optionId }, option, { isSelected: selectedIndex === __originalIndex, onClick: function () { return dispatch(['select', __originalIndex]); }, index: __originalIndex }), option.label));
196
+ })) : (react_1.default.createElement(ComboBoxMenuItem_1.ComboBoxMenuItem, __assign({ key: optionId, id: optionId }, option, { isSelected: selectedIndex === __originalIndex, onClick: function () { return dispatch(['select', __originalIndex]); }, index: __originalIndex, "data-iui-filtered-index": filteredIndex }), option.label));
195
197
  }, [enableVirtualization, focusedIndex, id, itemRenderer, selectedIndex]);
196
198
  return (react_1.default.createElement(helpers_1.ComboBoxRefsContext.Provider, { value: { inputRef: inputRef, menuRef: menuRef, toggleButtonRef: toggleButtonRef, optionsExtraInfoRef: optionsExtraInfoRef } },
197
199
  react_1.default.createElement(helpers_1.ComboBoxActionContext.Provider, { value: dispatch },
@@ -1,8 +1,7 @@
1
1
  import React from 'react';
2
- export declare const ComboBoxDropdown: React.ForwardRefExoticComponent<Pick<{
3
- visible?: boolean | undefined;
4
- trigger?: string | undefined;
5
- placement?: import("@popperjs/core").Placement | undefined;
6
- } & Omit<import("@tippyjs/react").TippyProps, "placement" | "trigger" | "visible"> & {
2
+ import { PopoverProps } from '../utils';
3
+ declare type ComboBoxDropdownProps = PopoverProps & {
7
4
  children: JSX.Element;
8
- }, "disabled" | "children" | "placement" | "trigger" | "visible" | "content" | "render" | "animateFill" | "appendTo" | "aria" | "delay" | "duration" | "followCursor" | "getReferenceClientRect" | "hideOnClick" | "ignoreAttributes" | "inlinePositioning" | "interactive" | "interactiveBorder" | "interactiveDebounce" | "moveTransition" | "offset" | "plugins" | "popperOptions" | "showOnCreate" | "sticky" | "touch" | "triggerTarget" | "onAfterUpdate" | "onBeforeUpdate" | "onCreate" | "onDestroy" | "onHidden" | "onHide" | "onMount" | "onShow" | "onShown" | "onTrigger" | "onUntrigger" | "onClickOutside" | "allowHTML" | "animation" | "arrow" | "inertia" | "maxWidth" | "role" | "theme" | "zIndex" | "className" | "singleton" | "reference"> & React.RefAttributes<Element>>;
5
+ };
6
+ export declare const ComboBoxDropdown: React.ForwardRefExoticComponent<Pick<ComboBoxDropdownProps, "disabled" | "children" | "placement" | "trigger" | "visible" | "content" | "render" | "animateFill" | "appendTo" | "aria" | "delay" | "duration" | "followCursor" | "getReferenceClientRect" | "hideOnClick" | "ignoreAttributes" | "inlinePositioning" | "interactive" | "interactiveBorder" | "interactiveDebounce" | "moveTransition" | "offset" | "plugins" | "popperOptions" | "showOnCreate" | "sticky" | "touch" | "triggerTarget" | "onAfterUpdate" | "onBeforeUpdate" | "onCreate" | "onDestroy" | "onHidden" | "onHide" | "onMount" | "onShow" | "onShown" | "onTrigger" | "onUntrigger" | "onClickOutside" | "allowHTML" | "animation" | "arrow" | "inertia" | "maxWidth" | "role" | "theme" | "zIndex" | "className" | "singleton" | "reference"> & React.RefAttributes<Element>>;
7
+ export {};
@@ -36,7 +36,7 @@ var utils_1 = require("../utils");
36
36
  var helpers_1 = require("./helpers");
37
37
  exports.ComboBoxInput = react_1.default.forwardRef(function (props, forwardedRef) {
38
38
  var onKeyDownProp = props.onKeyDown, onFocusProp = props.onFocus, rest = __rest(props, ["onKeyDown", "onFocus"]);
39
- var _a = (0, utils_1.useSafeContext)(helpers_1.ComboBoxStateContext), isOpen = _a.isOpen, id = _a.id, focusedIndex = _a.focusedIndex;
39
+ var _a = (0, utils_1.useSafeContext)(helpers_1.ComboBoxStateContext), isOpen = _a.isOpen, id = _a.id, focusedIndex = _a.focusedIndex, enableVirtualization = _a.enableVirtualization;
40
40
  var dispatch = (0, utils_1.useSafeContext)(helpers_1.ComboBoxActionContext);
41
41
  var _b = (0, utils_1.useSafeContext)(helpers_1.ComboBoxRefsContext), inputRef = _b.inputRef, menuRef = _b.menuRef, optionsExtraInfoRef = _b.optionsExtraInfoRef;
42
42
  var refs = (0, utils_1.useMergedRefs)(inputRef, forwardedRef);
@@ -49,7 +49,7 @@ exports.ComboBoxInput = react_1.default.forwardRef(function (props, forwardedRef
49
49
  return ((_c = (_b = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-iui-index=\"".concat(index, "\"]"))) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : '');
50
50
  };
51
51
  var handleKeyDown = react_1.default.useCallback(function (event) {
52
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
52
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
53
53
  onKeyDownProp === null || onKeyDownProp === void 0 ? void 0 : onKeyDownProp(event);
54
54
  var length = (_a = Object.keys(optionsExtraInfoRef.current).length) !== null && _a !== void 0 ? _a : 0;
55
55
  switch (event.key) {
@@ -62,15 +62,21 @@ exports.ComboBoxInput = react_1.default.forwardRef(function (props, forwardedRef
62
62
  return;
63
63
  }
64
64
  if (focusedIndexRef.current === -1) {
65
+ var currentElement = (_b = menuRef.current) === null || _b === void 0 ? void 0 : _b.querySelector('[data-iui-index]');
65
66
  return dispatch([
66
67
  'focus',
67
- (_c = (_b = Object.values(optionsExtraInfoRef.current)) === null || _b === void 0 ? void 0 : _b[0].__originalIndex) !== null && _c !== void 0 ? _c : -1,
68
+ Number((_c = currentElement === null || currentElement === void 0 ? void 0 : currentElement.getAttribute('data-iui-index')) !== null && _c !== void 0 ? _c : 0),
68
69
  ]);
69
70
  }
71
+ // If virtualization is enabled, dont let round scrolling
72
+ if (enableVirtualization &&
73
+ !((_e = (_d = menuRef.current) === null || _d === void 0 ? void 0 : _d.querySelector("[data-iui-index=\"".concat(focusedIndexRef.current, "\"]"))) === null || _e === void 0 ? void 0 : _e.nextElementSibling)) {
74
+ return;
75
+ }
70
76
  var nextIndex = focusedIndexRef.current;
71
77
  do {
72
- var currentElement = (_d = menuRef.current) === null || _d === void 0 ? void 0 : _d.querySelector("[data-iui-index=\"".concat(nextIndex, "\"]"));
73
- var nextElement = (_e = currentElement === null || currentElement === void 0 ? void 0 : currentElement.nextElementSibling) !== null && _e !== void 0 ? _e : (_f = menuRef.current) === null || _f === void 0 ? void 0 : _f.querySelector('[data-iui-index]');
78
+ var currentElement = (_f = menuRef.current) === null || _f === void 0 ? void 0 : _f.querySelector("[data-iui-index=\"".concat(nextIndex, "\"]"));
79
+ var nextElement = (_g = currentElement === null || currentElement === void 0 ? void 0 : currentElement.nextElementSibling) !== null && _g !== void 0 ? _g : (_h = menuRef.current) === null || _h === void 0 ? void 0 : _h.querySelector('[data-iui-index]');
74
80
  nextIndex = Number(nextElement === null || nextElement === void 0 ? void 0 : nextElement.getAttribute('data-iui-index'));
75
81
  if ((nextElement === null || nextElement === void 0 ? void 0 : nextElement.ariaDisabled) !== 'true') {
76
82
  return dispatch(['focus', nextIndex]);
@@ -86,16 +92,21 @@ exports.ComboBoxInput = react_1.default.forwardRef(function (props, forwardedRef
86
92
  if (length === 0) {
87
93
  return;
88
94
  }
95
+ // If virtualization is enabled, dont let round scrolling
96
+ if (enableVirtualization &&
97
+ !((_k = (_j = menuRef.current) === null || _j === void 0 ? void 0 : _j.querySelector("[data-iui-index=\"".concat(focusedIndexRef.current, "\"]"))) === null || _k === void 0 ? void 0 : _k.previousElementSibling)) {
98
+ return;
99
+ }
89
100
  if (focusedIndexRef.current === -1) {
90
101
  return dispatch([
91
102
  'focus',
92
- (_h = (_g = Object.values(optionsExtraInfoRef.current)) === null || _g === void 0 ? void 0 : _g[length - 1].__originalIndex) !== null && _h !== void 0 ? _h : -1,
103
+ (_m = (_l = Object.values(optionsExtraInfoRef.current)) === null || _l === void 0 ? void 0 : _l[length - 1].__originalIndex) !== null && _m !== void 0 ? _m : -1,
93
104
  ]);
94
105
  }
95
106
  var prevIndex = focusedIndexRef.current;
96
107
  do {
97
- var currentElement = (_j = menuRef.current) === null || _j === void 0 ? void 0 : _j.querySelector("[data-iui-index=\"".concat(prevIndex, "\"]"));
98
- var prevElement = (_k = currentElement === null || currentElement === void 0 ? void 0 : currentElement.previousElementSibling) !== null && _k !== void 0 ? _k : (_l = menuRef.current) === null || _l === void 0 ? void 0 : _l.querySelector('[data-iui-index]:last-of-type');
108
+ var currentElement = (_o = menuRef.current) === null || _o === void 0 ? void 0 : _o.querySelector("[data-iui-index=\"".concat(prevIndex, "\"]"));
109
+ var prevElement = (_p = currentElement === null || currentElement === void 0 ? void 0 : currentElement.previousElementSibling) !== null && _p !== void 0 ? _p : (_q = menuRef.current) === null || _q === void 0 ? void 0 : _q.querySelector('[data-iui-index]:last-of-type');
99
110
  prevIndex = Number(prevElement === null || prevElement === void 0 ? void 0 : prevElement.getAttribute('data-iui-index'));
100
111
  if ((prevElement === null || prevElement === void 0 ? void 0 : prevElement.ariaDisabled) !== 'true') {
101
112
  return dispatch(['focus', prevIndex]);
@@ -122,7 +133,14 @@ exports.ComboBoxInput = react_1.default.forwardRef(function (props, forwardedRef
122
133
  dispatch(['close']);
123
134
  break;
124
135
  }
125
- }, [dispatch, isOpen, menuRef, onKeyDownProp, optionsExtraInfoRef]);
136
+ }, [
137
+ dispatch,
138
+ enableVirtualization,
139
+ isOpen,
140
+ menuRef,
141
+ onKeyDownProp,
142
+ optionsExtraInfoRef,
143
+ ]);
126
144
  var handleFocus = react_1.default.useCallback(function (event) {
127
145
  dispatch(['open']);
128
146
  onFocusProp === null || onFocusProp === void 0 ? void 0 : onFocusProp(event);
@@ -43,16 +43,24 @@ var VirtualizedComboBoxMenu = react_1.default.forwardRef(function (_a, forwarded
43
43
  var menuRef = (0, utils_1.useSafeContext)(helpers_1.ComboBoxRefsContext).menuRef;
44
44
  var virtualItemRenderer = react_1.default.useCallback(function (index) {
45
45
  return filteredOptions.length > 0
46
- ? getMenuItem(filteredOptions[index])
46
+ ? getMenuItem(filteredOptions[index], index)
47
47
  : children;
48
48
  }, // Here is expected empty state content
49
49
  [filteredOptions, getMenuItem, children]);
50
+ var focusedVisibleIndex = react_1.default.useMemo(function () {
51
+ var _a, _b;
52
+ var currentElement = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-iui-index=\"".concat(focusedIndex, "\"]"));
53
+ if (!currentElement) {
54
+ return focusedIndex;
55
+ }
56
+ return Number((_b = currentElement.getAttribute('data-iui-filtered-index')) !== null && _b !== void 0 ? _b : focusedIndex);
57
+ }, [focusedIndex, menuRef]);
50
58
  var _f = (0, utils_1.useVirtualization)({
51
59
  // 'Fool' VirtualScroll by passing length 1
52
60
  // whenever there is no elements, to show empty state message
53
61
  itemsLength: filteredOptions.length || 1,
54
62
  itemRenderer: virtualItemRenderer,
55
- scrollToIndex: focusedIndex,
63
+ scrollToIndex: focusedVisibleIndex,
56
64
  }), outerProps = _f.outerProps, innerProps = _f.innerProps, visibleChildren = _f.visibleChildren;
57
65
  var overflowY = ((_d = (_c = (_b = (0, utils_1.getWindow)()) === null || _b === void 0 ? void 0 : _b.CSS) === null || _c === void 0 ? void 0 : _c.supports) === null || _d === void 0 ? void 0 : _d.call(_c, 'overflow-x: overlay'))
58
66
  ? { overflowY: 'overlay' }
@@ -24,7 +24,7 @@ declare type ComboBoxStateContextProps<T = unknown> = {
24
24
  minWidth: number;
25
25
  enableVirtualization: boolean;
26
26
  filteredOptions: SelectOption<T>[];
27
- getMenuItem: (option: SelectOption<T>) => JSX.Element;
27
+ getMenuItem: (option: SelectOption<T>, filteredIndex?: number) => JSX.Element;
28
28
  focusedIndex?: number;
29
29
  };
30
30
  export declare const ComboBoxStateContext: React.Context<ComboBoxStateContextProps<unknown> | undefined>;
@@ -5,7 +5,7 @@ import { TimePickerProps } from '../TimePicker';
5
5
  * Generate localized months and days strings using `Intl.DateTimeFormat` for passed locale to use in DatePicker component.
6
6
  * If locale is not passed, browser locale will be used.
7
7
  */
8
- export declare const generateLocalizedStrings: (locale?: string | undefined) => {
8
+ export declare const generateLocalizedStrings: (locale?: string) => {
9
9
  months: string[];
10
10
  shortDays: string[];
11
11
  days: string[];
@@ -187,6 +187,12 @@ var Table = function (props) {
187
187
  return result;
188
188
  }, {});
189
189
  var areFiltersSet = allColumns.some(function (column) { return column.filterValue != null && column.filterValue !== ''; });
190
+ var showFilterButton = function (column) {
191
+ return (data.length !== 0 || areFiltersSet) && column.canFilter;
192
+ };
193
+ var showSortButton = function (column) {
194
+ return data.length !== 0 && column.canSort;
195
+ };
190
196
  var onRowClickHandler = react_1.default.useCallback(function (event, row) {
191
197
  var isDisabled = isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original);
192
198
  if (!isDisabled) {
@@ -297,28 +303,32 @@ var Table = function (props) {
297
303
  className: (0, classnames_1.default)('iui-table', (_a = {}, _a["iui-".concat(density)] = density !== 'default', _a), className),
298
304
  style: style,
299
305
  }), ariaDataAttributes),
300
- react_1.default.createElement("div", { className: 'iui-table-header', ref: headerRef }, headerGroups.slice(1).map(function (headerGroup) {
301
- var headerGroupProps = headerGroup.getHeaderGroupProps({
302
- className: 'iui-row',
303
- });
304
- return (react_1.default.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
305
- 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(__assign({}, (0, utils_2.getCellStyle)(column, !!state.isTableResizing)), { flexWrap: 'unset' }) }));
306
- return (react_1.default.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
307
- if (el && isResizable) {
308
- columnRefs.current[column.id] = el;
309
- column.resizeWidth = el.getBoundingClientRect().width;
310
- }
311
- } }),
312
- column.render('Header'),
313
- (data.length !== 0 || areFiltersSet) && (react_1.default.createElement(filters_1.FilterToggle, { column: column, ownerDocument: ownerDocument })),
314
- data.length !== 0 && column.canSort && (react_1.default.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (react_1.default.createElement(SortDown_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (react_1.default.createElement(SortUp_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true })))),
315
- isResizable &&
316
- column.isResizerVisible &&
317
- index !== headerGroup.headers.length - 1 && (react_1.default.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
318
- react_1.default.createElement("div", { className: 'iui-resizer-bar' }))),
319
- enableColumnReordering && !column.disableReordering && (react_1.default.createElement("div", { className: 'iui-reorder-bar' }))));
320
- })));
321
- })),
306
+ react_1.default.createElement("div", { className: 'iui-table-header-wrapper', ref: headerRef },
307
+ react_1.default.createElement("div", { className: 'iui-table-header' }, headerGroups.slice(1).map(function (headerGroup) {
308
+ var headerGroupProps = headerGroup.getHeaderGroupProps({
309
+ className: 'iui-row',
310
+ });
311
+ return (react_1.default.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
312
+ 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: (0, utils_2.getCellStyle)(column, !!state.isTableResizing) }));
313
+ return (react_1.default.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
314
+ if (el && isResizable) {
315
+ columnRefs.current[column.id] = el;
316
+ column.resizeWidth = el.getBoundingClientRect().width;
317
+ }
318
+ } }),
319
+ column.render('Header'),
320
+ (showFilterButton(column) ||
321
+ showSortButton(column)) && (react_1.default.createElement("div", { className: 'iui-table-header-actions-container' },
322
+ showFilterButton(column) && (react_1.default.createElement(filters_1.FilterToggle, { column: column, ownerDocument: ownerDocument })),
323
+ showSortButton(column) && (react_1.default.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (react_1.default.createElement(SortDown_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (react_1.default.createElement(SortUp_1.default, { className: 'iui-icon iui-sort', "aria-hidden": true })))))),
324
+ isResizable &&
325
+ column.isResizerVisible &&
326
+ index !== headerGroup.headers.length - 1 && (react_1.default.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
327
+ react_1.default.createElement("div", { className: 'iui-resizer-bar' }))),
328
+ enableColumnReordering &&
329
+ !column.disableReordering && (react_1.default.createElement("div", { className: 'iui-reorder-bar' }))));
330
+ })));
331
+ }))),
322
332
  react_1.default.createElement("div", __assign({}, getTableBodyProps({
323
333
  className: (0, classnames_1.default)('iui-table-body', {
324
334
  'iui-zebra-striping': styleType === 'zebra-rows',
@@ -149,7 +149,7 @@ var TablePaginator = function (props) {
149
149
  }
150
150
  var hasNoRows = totalPagesCount === 0;
151
151
  var showPagesList = totalPagesCount > 1 || isLoading;
152
- var showPageSizeList = pageSizeList && onPageSizeChange && !!totalRowsCount;
152
+ var showPageSizeList = pageSizeList && !!onPageSizeChange && !!totalRowsCount;
153
153
  var ellipsis = (react_1.default.createElement("span", { className: (0, classnames_1.default)('iui-paginator-ellipsis', {
154
154
  'iui-paginator-ellipsis-small': size === 'small',
155
155
  }) }, "\u2026"));
@@ -28,7 +28,7 @@ export declare const tableFilters: {
28
28
  * Basic filter with a single input field.
29
29
  * @param translatedLabels Translated filter labels.
30
30
  */
31
- TextFilter: (translatedLabels?: FilterButtonBarTranslation | undefined) => <T extends Record<string, unknown>>(props: TableFilterProps<T>) => JSX.Element;
31
+ TextFilter: (translatedLabels?: FilterButtonBarTranslation) => <T extends Record<string, unknown>>(props: TableFilterProps<T>) => JSX.Element;
32
32
  /**
33
33
  * Date range filter.
34
34
  *
@@ -39,7 +39,7 @@ export declare const tableFilters: {
39
39
  * If your data is different type e.g. `string`, you can use `accessor` property in column description:
40
40
  * `accessor: (rowData) => new Date(rowData.date)`.
41
41
  */
42
- DateRangeFilter: (options?: DateRangeFilterOptions | undefined) => <T_1 extends Record<string, unknown>>(props: TableFilterProps<T_1>) => JSX.Element;
42
+ DateRangeFilter: (options?: DateRangeFilterOptions) => <T_1 extends Record<string, unknown>>(props: TableFilterProps<T_1>) => JSX.Element;
43
43
  /**
44
44
  * Number range filter.
45
45
  *
@@ -48,5 +48,5 @@ export declare const tableFilters: {
48
48
  * `accessor: (rowData) => Number(rowData.numberProp)`.
49
49
  * @param translatedLabels Translated filter labels.
50
50
  */
51
- NumberRangeFilter: (translatedLabels?: (NumberRangeTranslation & FilterButtonBarTranslation) | undefined) => <T_2 extends Record<string, unknown>>(props: NumberRangeFilterProps<T_2>) => JSX.Element;
51
+ NumberRangeFilter: (translatedLabels?: NumberRangeTranslation & FilterButtonBarTranslation) => <T_2 extends Record<string, unknown>>(props: NumberRangeFilterProps<T_2>) => JSX.Element;
52
52
  };
@@ -19,8 +19,16 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
19
19
  }
20
20
  return to.concat(ar || Array.prototype.slice.call(from));
21
21
  };
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
22
25
  Object.defineProperty(exports, "__esModule", { value: true });
23
26
  exports.useExpanderCell = void 0;
27
+ /*---------------------------------------------------------------------------------------------
28
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
29
+ * See LICENSE.md in the project root for license terms and full copyright notice.
30
+ *--------------------------------------------------------------------------------------------*/
31
+ var react_1 = __importDefault(require("react"));
24
32
  var columns_1 = require("../columns");
25
33
  var useExpanderCell = function (subComponent, expanderCell, isRowDisabled) { return function (hooks) {
26
34
  if (!subComponent) {
@@ -36,7 +44,9 @@ var useExpanderCell = function (subComponent, expanderCell, isRowDisabled) { ret
36
44
  isDisabled: isRowDisabled,
37
45
  });
38
46
  return __spreadArray([
39
- __assign(__assign({}, expanderColumn), { Cell: expanderCell !== null && expanderCell !== void 0 ? expanderCell : expanderColumn.Cell })
47
+ __assign(__assign({}, expanderColumn), { Cell: expanderCell
48
+ ? function (cellProps) { return react_1.default.createElement(react_1.default.Fragment, null, expanderCell(cellProps)); }
49
+ : expanderColumn.Cell })
40
50
  ], columns, true);
41
51
  });
42
52
  }; };