@itwin/itwinui-react 1.33.0 → 1.33.1

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
+ ### [1.33.1](https://www.github.com/iTwin/iTwinUI-react/compare/v1.33.0...v1.33.1) (2022-03-18)
4
+
5
+ ### Fixes
6
+
7
+ * **ButtonGroup:** Add vertical support to `overflowButton` ([#579](https://www.github.com/iTwin/iTwinUI-react/issues/579)) ([aad619b](https://www.github.com/iTwin/iTwinUI-react/commit/aad619b6dc7d65ffd79c8d33111489b1b8d27680))
8
+ * **Slider:** Fixed to call onUpdate on rail click ([#587](https://www.github.com/iTwin/iTwinUI-react/issues/587)) ([e7cc679](https://www.github.com/iTwin/iTwinUI-react/commit/e7cc6796308928230f2d2c7c79b6ee35286595a7))
9
+ * **Table:** Removed wrapper span from checkbox ([#583](https://www.github.com/iTwin/iTwinUI-react/issues/583)) ([996377b](https://www.github.com/iTwin/iTwinUI-react/commit/996377bf44cdacd9f42361f2199c2a83420ca15b))
10
+
3
11
  ## [1.33.0](https://www.github.com/iTwin/iTwinUI-react/compare/v1.32.0...v1.33.0) (2022-03-07)
4
12
 
5
13
  ### What's new
@@ -13,8 +13,6 @@ export declare type ButtonGroupProps = {
13
13
  * and returns the `ReactNode` to render.
14
14
  *
15
15
  * The placement of this button can be controlled using the `overflowPlacement` prop.
16
- *
17
- * *Note: this will not work with `orientation='vertical'`.*
18
16
  */
19
17
  overflowButton?: (firstOverflowingIndex: number) => React.ReactNode;
20
18
  /**
@@ -63,16 +63,15 @@ require("@itwin/itwinui-css/css/button.css");
63
63
  * </ButtonGroup>
64
64
  */
65
65
  exports.ButtonGroup = react_1.default.forwardRef(function (props, ref) {
66
- var children = props.children, className = props.className, style = props.style, overflowButton = props.overflowButton, _a = props.overflowPlacement, overflowPlacement = _a === void 0 ? 'end' : _a, _b = props.orientation, orientation = _b === void 0 ? 'horizontal' : _b, rest = __rest(props, ["children", "className", "style", "overflowButton", "overflowPlacement", "orientation"]);
66
+ var children = props.children, className = props.className, overflowButton = props.overflowButton, _a = props.overflowPlacement, overflowPlacement = _a === void 0 ? 'end' : _a, _b = props.orientation, orientation = _b === void 0 ? 'horizontal' : _b, rest = __rest(props, ["children", "className", "overflowButton", "overflowPlacement", "orientation"]);
67
67
  var items = react_1.default.useMemo(function () { var _a; return (_a = react_1.default.Children.map(children, function (child) { return react_1.default.createElement("div", null, child); })) !== null && _a !== void 0 ? _a : []; }, [children]);
68
68
  (0, utils_1.useTheme)();
69
- var _c = (0, utils_1.useOverflow)(items, !overflowButton), overflowRef = _c[0], visibleCount = _c[1];
69
+ var _c = (0, utils_1.useOverflow)(items, !overflowButton, orientation), overflowRef = _c[0], visibleCount = _c[1];
70
70
  var refs = (0, utils_1.useMergedRefs)(overflowRef, ref);
71
71
  return (react_1.default.createElement("div", __assign({ className: (0, classnames_1.default)({
72
72
  'iui-button-group': orientation === 'horizontal',
73
73
  'iui-button-group-vertical': orientation === 'vertical',
74
- }, className), style: __assign(__assign({}, (!!overflowButton &&
75
- orientation === 'horizontal' && { width: '100%' })), style), "aria-orientation": orientation, ref: refs }, rest), !!overflowButton && visibleCount < items.length ? (react_1.default.createElement(react_1.default.Fragment, null,
74
+ }, className), "aria-orientation": orientation, ref: refs }, rest), !!overflowButton && visibleCount < items.length ? (react_1.default.createElement(react_1.default.Fragment, null,
76
75
  overflowButton && overflowPlacement === 'start' && (react_1.default.createElement("div", null, overflowButton(visibleCount))),
77
76
  items.slice(0, visibleCount - 1),
78
77
  overflowButton && overflowPlacement === 'end' && (react_1.default.createElement("div", null, overflowButton(visibleCount))))) : (items)));
@@ -208,11 +208,20 @@ exports.Slider = react_1.default.forwardRef(function (props, ref) {
208
208
  newValues[closestValueIndex] = pointerValue;
209
209
  setCurrentValues(newValues);
210
210
  onChange === null || onChange === void 0 ? void 0 : onChange(newValues);
211
+ onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(newValues);
211
212
  focusThumb(containerRef.current, closestValueIndex);
212
213
  event.preventDefault();
213
214
  event.stopPropagation();
214
215
  }
215
- }, [min, max, step, currentValues, getAllowableThumbRange, onChange]);
216
+ }, [
217
+ min,
218
+ max,
219
+ step,
220
+ currentValues,
221
+ getAllowableThumbRange,
222
+ onChange,
223
+ onUpdate,
224
+ ]);
216
225
  (0, utils_1.useEventListener)('pointermove', handlePointerMove, (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument);
217
226
  (0, utils_1.useEventListener)('pointerup', handlePointerUp, (_b = containerRef.current) === null || _b === void 0 ? void 0 : _b.ownerDocument);
218
227
  var tickMarkArea = react_1.default.useMemo(function () {
@@ -55,8 +55,7 @@ var useSelectionCell = function (isSelectable, isRowDisabled) { return function
55
55
  },
56
56
  Cell: function (_a) {
57
57
  var row = _a.row;
58
- return (react_1.default.createElement("span", { onClick: function (e) { return e.stopPropagation(); } },
59
- react_1.default.createElement(Checkbox_1.Checkbox, __assign({}, row.getToggleRowSelectedProps(), { disabled: isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original) }))));
58
+ return (react_1.default.createElement(Checkbox_1.Checkbox, __assign({}, row.getToggleRowSelectedProps(), { disabled: isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original), onClick: function (e) { return e.stopPropagation(); } })));
60
59
  },
61
60
  }
62
61
  ], columns, true); });
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Hook that uses `IntersectionObserver` to trigger `onIntersect` callback when element is in viewport.
3
- * Callback is called only once.
4
- * Hook returns a function that you need to use to set a reference of the element you want to observe.
3
+ * Callback is called only once by default (can be changed using the `once` parameter).
4
+ * @returns a callback ref that needs to be set on the element you want to observe.
5
+ * @private
5
6
  * @example
6
7
  * const onIntersection = React.useCallback(() => {
7
8
  * console.log('Element is in viewport!');
@@ -9,4 +10,4 @@
9
10
  * const ref = useIntersection(onIntersection);
10
11
  * return (<div ref={ref}>One of many elements</div>);
11
12
  */
12
- export declare const useIntersection: (onIntersect: () => void, options?: IntersectionObserverInit) => (node: HTMLElement | null) => void;
13
+ export declare const useIntersection: (onIntersect: () => void, options?: IntersectionObserverInit, once?: boolean) => (node: HTMLElement | null) => void;
@@ -12,8 +12,9 @@ var react_1 = __importDefault(require("react"));
12
12
  var dom_1 = require("../functions/dom");
13
13
  /**
14
14
  * Hook that uses `IntersectionObserver` to trigger `onIntersect` callback when element is in viewport.
15
- * Callback is called only once.
16
- * Hook returns a function that you need to use to set a reference of the element you want to observe.
15
+ * Callback is called only once by default (can be changed using the `once` parameter).
16
+ * @returns a callback ref that needs to be set on the element you want to observe.
17
+ * @private
17
18
  * @example
18
19
  * const onIntersection = React.useCallback(() => {
19
20
  * console.log('Element is in viewport!');
@@ -21,8 +22,9 @@ var dom_1 = require("../functions/dom");
21
22
  * const ref = useIntersection(onIntersection);
22
23
  * return (<div ref={ref}>One of many elements</div>);
23
24
  */
24
- var useIntersection = function (onIntersect, options) {
25
+ var useIntersection = function (onIntersect, options, once) {
25
26
  if (options === void 0) { options = {}; }
27
+ if (once === void 0) { once = true; }
26
28
  var root = options.root, rootMargin = options.rootMargin, threshold = options.threshold;
27
29
  var observer = react_1.default.useRef();
28
30
  var setRef = react_1.default.useCallback(function (node) {
@@ -39,12 +41,15 @@ var useIntersection = function (onIntersect, options) {
39
41
  observer.current = new IntersectionObserver(function (_a, obs) {
40
42
  var entry = _a[0];
41
43
  if (entry.isIntersecting) {
42
- obs.disconnect();
44
+ if (once) {
45
+ obs.disconnect();
46
+ }
43
47
  onIntersect();
44
48
  }
45
49
  }, { root: root, rootMargin: rootMargin, threshold: threshold });
46
50
  observer.current.observe(node);
47
- }, [onIntersect, root, rootMargin, threshold]);
51
+ }, [onIntersect, once, root, rootMargin, threshold]);
52
+ react_1.default.useEffect(function () { return function () { var _a; return (_a = observer.current) === null || _a === void 0 ? void 0 : _a.disconnect(); }; }, []);
48
53
  return setRef;
49
54
  };
50
55
  exports.useIntersection = useIntersection;
@@ -1,13 +1,14 @@
1
1
  import React from 'react';
2
2
  /**
3
3
  * Hook that observes the size of an element and returns the number of items
4
- * that should be visible based on the width of the container element.
4
+ * that should be visible based on the size of the container element.
5
5
  *
6
6
  * The returned number should be used to render the element with fewer items.
7
7
  *
8
8
  * @private
9
9
  * @param items Items that this element contains.
10
10
  * @param disabled Set to true to disconnect the observer.
11
+ * @param dimension 'horizontal' (default) or 'vertical'
11
12
  * @returns [callback ref to set on container, stateful count of visible items]
12
13
  *
13
14
  * @example
@@ -20,4 +21,4 @@ import React from 'react';
20
21
  * </div>
21
22
  * );
22
23
  */
23
- export declare const useOverflow: <T extends HTMLElement>(items: React.ReactNode[] | string, disabled?: boolean) => readonly [(instance: T | null) => void, number];
24
+ export declare const useOverflow: <T extends HTMLElement>(items: React.ReactNode[] | string, disabled?: boolean, orientation?: 'horizontal' | 'vertical') => readonly [(instance: T | null) => void, number];
@@ -14,13 +14,14 @@ var useResizeObserver_1 = require("./useResizeObserver");
14
14
  var STARTING_MAX_ITEMS_COUNT = 20;
15
15
  /**
16
16
  * Hook that observes the size of an element and returns the number of items
17
- * that should be visible based on the width of the container element.
17
+ * that should be visible based on the size of the container element.
18
18
  *
19
19
  * The returned number should be used to render the element with fewer items.
20
20
  *
21
21
  * @private
22
22
  * @param items Items that this element contains.
23
23
  * @param disabled Set to true to disconnect the observer.
24
+ * @param dimension 'horizontal' (default) or 'vertical'
24
25
  * @returns [callback ref to set on container, stateful count of visible items]
25
26
  *
26
27
  * @example
@@ -33,20 +34,21 @@ var STARTING_MAX_ITEMS_COUNT = 20;
33
34
  * </div>
34
35
  * );
35
36
  */
36
- var useOverflow = function (items, disabled) {
37
+ var useOverflow = function (items, disabled, orientation) {
37
38
  if (disabled === void 0) { disabled = false; }
39
+ if (orientation === void 0) { orientation = 'horizontal'; }
38
40
  var containerRef = react_1.default.useRef(null);
39
41
  var _a = react_1.default.useState(function () {
40
42
  return disabled ? items.length : Math.min(items.length, STARTING_MAX_ITEMS_COUNT);
41
43
  }), visibleCount = _a[0], setVisibleCount = _a[1];
42
44
  var needsFullRerender = react_1.default.useRef(true);
43
- var _b = react_1.default.useState(0), containerWidth = _b[0], setContainerWidth = _b[1];
44
- var previousContainerWidth = react_1.default.useRef(0);
45
- var updateContainerWidth = react_1.default.useCallback(function (_a) {
46
- var width = _a.width;
47
- return setContainerWidth(width);
48
- }, []);
49
- var _c = (0, useResizeObserver_1.useResizeObserver)(updateContainerWidth), resizeRef = _c[0], observer = _c[1];
45
+ var _b = react_1.default.useState(0), containerSize = _b[0], setContainerSize = _b[1];
46
+ var previousContainerSize = react_1.default.useRef(0);
47
+ var updateContainerSize = react_1.default.useCallback(function (_a) {
48
+ var width = _a.width, height = _a.height;
49
+ return setContainerSize(orientation === 'horizontal' ? width : height);
50
+ }, [orientation]);
51
+ var _c = (0, useResizeObserver_1.useResizeObserver)(updateContainerSize), resizeRef = _c[0], observer = _c[1];
50
52
  var resizeObserverRef = react_1.default.useRef(observer);
51
53
  react_1.default.useLayoutEffect(function () {
52
54
  if (disabled) {
@@ -56,7 +58,7 @@ var useOverflow = function (items, disabled) {
56
58
  setVisibleCount(Math.min(items.length, STARTING_MAX_ITEMS_COUNT));
57
59
  needsFullRerender.current = true;
58
60
  }
59
- }, [containerWidth, disabled, items]);
61
+ }, [containerSize, disabled, items]);
60
62
  var mergedRefs = (0, useMergedRefs_1.useMergedRefs)(containerRef, resizeRef);
61
63
  react_1.default.useLayoutEffect(function () {
62
64
  var _a;
@@ -64,25 +66,26 @@ var useOverflow = function (items, disabled) {
64
66
  (_a = resizeObserverRef.current) === null || _a === void 0 ? void 0 : _a.disconnect();
65
67
  return;
66
68
  }
67
- var availableWidth = containerRef.current.offsetWidth;
68
- var requiredWidth = containerRef.current.scrollWidth;
69
- if (availableWidth < requiredWidth) {
70
- var avgItemWidth = requiredWidth / visibleCount;
71
- var visibleItems = Math.floor(availableWidth / avgItemWidth);
69
+ var dimension = orientation === 'horizontal' ? 'Width' : 'Height';
70
+ var availableSize = containerRef.current["offset" + dimension];
71
+ var requiredSize = containerRef.current["scroll" + dimension];
72
+ if (availableSize < requiredSize) {
73
+ var avgItemSize = requiredSize / visibleCount;
74
+ var visibleItems = Math.floor(availableSize / avgItemSize);
72
75
  setVisibleCount(visibleItems);
73
76
  }
74
77
  else if (needsFullRerender.current) {
75
- var childrenWidth = Array.from(containerRef.current.children).reduce(function (sum, child) { return sum + child.offsetWidth; }, 0);
76
- var avgItemWidth = childrenWidth / visibleCount;
77
- var visibleItems = Math.floor(availableWidth / avgItemWidth);
78
+ var childrenSize = Array.from(containerRef.current.children).reduce(function (sum, child) { return sum + child["offset" + dimension]; }, 0);
79
+ var avgItemSize = childrenSize / visibleCount;
80
+ var visibleItems = Math.floor(availableSize / avgItemSize);
78
81
  // Doubling the visible items to overflow the container. Just to be safe.
79
82
  setVisibleCount(Math.min(items.length, visibleItems * 2));
80
83
  }
81
84
  needsFullRerender.current = false;
82
- }, [containerWidth, visibleCount, disabled, items.length]);
85
+ }, [containerSize, visibleCount, disabled, items.length, orientation]);
83
86
  react_1.default.useLayoutEffect(function () {
84
- previousContainerWidth.current = containerWidth;
85
- }, [containerWidth]);
87
+ previousContainerSize.current = containerSize;
88
+ }, [containerSize]);
86
89
  return [mergedRefs, visibleCount];
87
90
  };
88
91
  exports.useOverflow = useOverflow;
@@ -13,8 +13,6 @@ export declare type ButtonGroupProps = {
13
13
  * and returns the `ReactNode` to render.
14
14
  *
15
15
  * The placement of this button can be controlled using the `overflowPlacement` prop.
16
- *
17
- * *Note: this will not work with `orientation='vertical'`.*
18
16
  */
19
17
  overflowButton?: (firstOverflowingIndex: number) => React.ReactNode;
20
18
  /**
@@ -57,16 +57,15 @@ import '@itwin/itwinui-css/css/button.css';
57
57
  * </ButtonGroup>
58
58
  */
59
59
  export var ButtonGroup = React.forwardRef(function (props, ref) {
60
- var children = props.children, className = props.className, style = props.style, overflowButton = props.overflowButton, _a = props.overflowPlacement, overflowPlacement = _a === void 0 ? 'end' : _a, _b = props.orientation, orientation = _b === void 0 ? 'horizontal' : _b, rest = __rest(props, ["children", "className", "style", "overflowButton", "overflowPlacement", "orientation"]);
60
+ var children = props.children, className = props.className, overflowButton = props.overflowButton, _a = props.overflowPlacement, overflowPlacement = _a === void 0 ? 'end' : _a, _b = props.orientation, orientation = _b === void 0 ? 'horizontal' : _b, rest = __rest(props, ["children", "className", "overflowButton", "overflowPlacement", "orientation"]);
61
61
  var items = React.useMemo(function () { var _a; return (_a = React.Children.map(children, function (child) { return React.createElement("div", null, child); })) !== null && _a !== void 0 ? _a : []; }, [children]);
62
62
  useTheme();
63
- var _c = useOverflow(items, !overflowButton), overflowRef = _c[0], visibleCount = _c[1];
63
+ var _c = useOverflow(items, !overflowButton, orientation), overflowRef = _c[0], visibleCount = _c[1];
64
64
  var refs = useMergedRefs(overflowRef, ref);
65
65
  return (React.createElement("div", __assign({ className: cx({
66
66
  'iui-button-group': orientation === 'horizontal',
67
67
  'iui-button-group-vertical': orientation === 'vertical',
68
- }, className), style: __assign(__assign({}, (!!overflowButton &&
69
- orientation === 'horizontal' && { width: '100%' })), style), "aria-orientation": orientation, ref: refs }, rest), !!overflowButton && visibleCount < items.length ? (React.createElement(React.Fragment, null,
68
+ }, className), "aria-orientation": orientation, ref: refs }, rest), !!overflowButton && visibleCount < items.length ? (React.createElement(React.Fragment, null,
70
69
  overflowButton && overflowPlacement === 'start' && (React.createElement("div", null, overflowButton(visibleCount))),
71
70
  items.slice(0, visibleCount - 1),
72
71
  overflowButton && overflowPlacement === 'end' && (React.createElement("div", null, overflowButton(visibleCount))))) : (items)));
@@ -202,11 +202,20 @@ export var Slider = React.forwardRef(function (props, ref) {
202
202
  newValues[closestValueIndex] = pointerValue;
203
203
  setCurrentValues(newValues);
204
204
  onChange === null || onChange === void 0 ? void 0 : onChange(newValues);
205
+ onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(newValues);
205
206
  focusThumb(containerRef.current, closestValueIndex);
206
207
  event.preventDefault();
207
208
  event.stopPropagation();
208
209
  }
209
- }, [min, max, step, currentValues, getAllowableThumbRange, onChange]);
210
+ }, [
211
+ min,
212
+ max,
213
+ step,
214
+ currentValues,
215
+ getAllowableThumbRange,
216
+ onChange,
217
+ onUpdate,
218
+ ]);
210
219
  useEventListener('pointermove', handlePointerMove, (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument);
211
220
  useEventListener('pointerup', handlePointerUp, (_b = containerRef.current) === null || _b === void 0 ? void 0 : _b.ownerDocument);
212
221
  var tickMarkArea = React.useMemo(function () {
@@ -49,8 +49,7 @@ export var useSelectionCell = function (isSelectable, isRowDisabled) { return fu
49
49
  },
50
50
  Cell: function (_a) {
51
51
  var row = _a.row;
52
- return (React.createElement("span", { onClick: function (e) { return e.stopPropagation(); } },
53
- React.createElement(Checkbox, __assign({}, row.getToggleRowSelectedProps(), { disabled: isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original) }))));
52
+ return (React.createElement(Checkbox, __assign({}, row.getToggleRowSelectedProps(), { disabled: isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original), onClick: function (e) { return e.stopPropagation(); } })));
54
53
  },
55
54
  }
56
55
  ], columns, true); });
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Hook that uses `IntersectionObserver` to trigger `onIntersect` callback when element is in viewport.
3
- * Callback is called only once.
4
- * Hook returns a function that you need to use to set a reference of the element you want to observe.
3
+ * Callback is called only once by default (can be changed using the `once` parameter).
4
+ * @returns a callback ref that needs to be set on the element you want to observe.
5
+ * @private
5
6
  * @example
6
7
  * const onIntersection = React.useCallback(() => {
7
8
  * console.log('Element is in viewport!');
@@ -9,4 +10,4 @@
9
10
  * const ref = useIntersection(onIntersection);
10
11
  * return (<div ref={ref}>One of many elements</div>);
11
12
  */
12
- export declare const useIntersection: (onIntersect: () => void, options?: IntersectionObserverInit) => (node: HTMLElement | null) => void;
13
+ export declare const useIntersection: (onIntersect: () => void, options?: IntersectionObserverInit, once?: boolean) => (node: HTMLElement | null) => void;
@@ -6,8 +6,9 @@ import React from 'react';
6
6
  import { getWindow } from '../functions/dom';
7
7
  /**
8
8
  * Hook that uses `IntersectionObserver` to trigger `onIntersect` callback when element is in viewport.
9
- * Callback is called only once.
10
- * Hook returns a function that you need to use to set a reference of the element you want to observe.
9
+ * Callback is called only once by default (can be changed using the `once` parameter).
10
+ * @returns a callback ref that needs to be set on the element you want to observe.
11
+ * @private
11
12
  * @example
12
13
  * const onIntersection = React.useCallback(() => {
13
14
  * console.log('Element is in viewport!');
@@ -15,8 +16,9 @@ import { getWindow } from '../functions/dom';
15
16
  * const ref = useIntersection(onIntersection);
16
17
  * return (<div ref={ref}>One of many elements</div>);
17
18
  */
18
- export var useIntersection = function (onIntersect, options) {
19
+ export var useIntersection = function (onIntersect, options, once) {
19
20
  if (options === void 0) { options = {}; }
21
+ if (once === void 0) { once = true; }
20
22
  var root = options.root, rootMargin = options.rootMargin, threshold = options.threshold;
21
23
  var observer = React.useRef();
22
24
  var setRef = React.useCallback(function (node) {
@@ -33,11 +35,14 @@ export var useIntersection = function (onIntersect, options) {
33
35
  observer.current = new IntersectionObserver(function (_a, obs) {
34
36
  var entry = _a[0];
35
37
  if (entry.isIntersecting) {
36
- obs.disconnect();
38
+ if (once) {
39
+ obs.disconnect();
40
+ }
37
41
  onIntersect();
38
42
  }
39
43
  }, { root: root, rootMargin: rootMargin, threshold: threshold });
40
44
  observer.current.observe(node);
41
- }, [onIntersect, root, rootMargin, threshold]);
45
+ }, [onIntersect, once, root, rootMargin, threshold]);
46
+ React.useEffect(function () { return function () { var _a; return (_a = observer.current) === null || _a === void 0 ? void 0 : _a.disconnect(); }; }, []);
42
47
  return setRef;
43
48
  };
@@ -1,13 +1,14 @@
1
1
  import React from 'react';
2
2
  /**
3
3
  * Hook that observes the size of an element and returns the number of items
4
- * that should be visible based on the width of the container element.
4
+ * that should be visible based on the size of the container element.
5
5
  *
6
6
  * The returned number should be used to render the element with fewer items.
7
7
  *
8
8
  * @private
9
9
  * @param items Items that this element contains.
10
10
  * @param disabled Set to true to disconnect the observer.
11
+ * @param dimension 'horizontal' (default) or 'vertical'
11
12
  * @returns [callback ref to set on container, stateful count of visible items]
12
13
  *
13
14
  * @example
@@ -20,4 +21,4 @@ import React from 'react';
20
21
  * </div>
21
22
  * );
22
23
  */
23
- export declare const useOverflow: <T extends HTMLElement>(items: React.ReactNode[] | string, disabled?: boolean) => readonly [(instance: T | null) => void, number];
24
+ export declare const useOverflow: <T extends HTMLElement>(items: React.ReactNode[] | string, disabled?: boolean, orientation?: 'horizontal' | 'vertical') => readonly [(instance: T | null) => void, number];
@@ -8,13 +8,14 @@ import { useResizeObserver } from './useResizeObserver';
8
8
  var STARTING_MAX_ITEMS_COUNT = 20;
9
9
  /**
10
10
  * Hook that observes the size of an element and returns the number of items
11
- * that should be visible based on the width of the container element.
11
+ * that should be visible based on the size of the container element.
12
12
  *
13
13
  * The returned number should be used to render the element with fewer items.
14
14
  *
15
15
  * @private
16
16
  * @param items Items that this element contains.
17
17
  * @param disabled Set to true to disconnect the observer.
18
+ * @param dimension 'horizontal' (default) or 'vertical'
18
19
  * @returns [callback ref to set on container, stateful count of visible items]
19
20
  *
20
21
  * @example
@@ -27,20 +28,21 @@ var STARTING_MAX_ITEMS_COUNT = 20;
27
28
  * </div>
28
29
  * );
29
30
  */
30
- export var useOverflow = function (items, disabled) {
31
+ export var useOverflow = function (items, disabled, orientation) {
31
32
  if (disabled === void 0) { disabled = false; }
33
+ if (orientation === void 0) { orientation = 'horizontal'; }
32
34
  var containerRef = React.useRef(null);
33
35
  var _a = React.useState(function () {
34
36
  return disabled ? items.length : Math.min(items.length, STARTING_MAX_ITEMS_COUNT);
35
37
  }), visibleCount = _a[0], setVisibleCount = _a[1];
36
38
  var needsFullRerender = React.useRef(true);
37
- var _b = React.useState(0), containerWidth = _b[0], setContainerWidth = _b[1];
38
- var previousContainerWidth = React.useRef(0);
39
- var updateContainerWidth = React.useCallback(function (_a) {
40
- var width = _a.width;
41
- return setContainerWidth(width);
42
- }, []);
43
- var _c = useResizeObserver(updateContainerWidth), resizeRef = _c[0], observer = _c[1];
39
+ var _b = React.useState(0), containerSize = _b[0], setContainerSize = _b[1];
40
+ var previousContainerSize = React.useRef(0);
41
+ var updateContainerSize = React.useCallback(function (_a) {
42
+ var width = _a.width, height = _a.height;
43
+ return setContainerSize(orientation === 'horizontal' ? width : height);
44
+ }, [orientation]);
45
+ var _c = useResizeObserver(updateContainerSize), resizeRef = _c[0], observer = _c[1];
44
46
  var resizeObserverRef = React.useRef(observer);
45
47
  React.useLayoutEffect(function () {
46
48
  if (disabled) {
@@ -50,7 +52,7 @@ export var useOverflow = function (items, disabled) {
50
52
  setVisibleCount(Math.min(items.length, STARTING_MAX_ITEMS_COUNT));
51
53
  needsFullRerender.current = true;
52
54
  }
53
- }, [containerWidth, disabled, items]);
55
+ }, [containerSize, disabled, items]);
54
56
  var mergedRefs = useMergedRefs(containerRef, resizeRef);
55
57
  React.useLayoutEffect(function () {
56
58
  var _a;
@@ -58,24 +60,25 @@ export var useOverflow = function (items, disabled) {
58
60
  (_a = resizeObserverRef.current) === null || _a === void 0 ? void 0 : _a.disconnect();
59
61
  return;
60
62
  }
61
- var availableWidth = containerRef.current.offsetWidth;
62
- var requiredWidth = containerRef.current.scrollWidth;
63
- if (availableWidth < requiredWidth) {
64
- var avgItemWidth = requiredWidth / visibleCount;
65
- var visibleItems = Math.floor(availableWidth / avgItemWidth);
63
+ var dimension = orientation === 'horizontal' ? 'Width' : 'Height';
64
+ var availableSize = containerRef.current["offset" + dimension];
65
+ var requiredSize = containerRef.current["scroll" + dimension];
66
+ if (availableSize < requiredSize) {
67
+ var avgItemSize = requiredSize / visibleCount;
68
+ var visibleItems = Math.floor(availableSize / avgItemSize);
66
69
  setVisibleCount(visibleItems);
67
70
  }
68
71
  else if (needsFullRerender.current) {
69
- var childrenWidth = Array.from(containerRef.current.children).reduce(function (sum, child) { return sum + child.offsetWidth; }, 0);
70
- var avgItemWidth = childrenWidth / visibleCount;
71
- var visibleItems = Math.floor(availableWidth / avgItemWidth);
72
+ var childrenSize = Array.from(containerRef.current.children).reduce(function (sum, child) { return sum + child["offset" + dimension]; }, 0);
73
+ var avgItemSize = childrenSize / visibleCount;
74
+ var visibleItems = Math.floor(availableSize / avgItemSize);
72
75
  // Doubling the visible items to overflow the container. Just to be safe.
73
76
  setVisibleCount(Math.min(items.length, visibleItems * 2));
74
77
  }
75
78
  needsFullRerender.current = false;
76
- }, [containerWidth, visibleCount, disabled, items.length]);
79
+ }, [containerSize, visibleCount, disabled, items.length, orientation]);
77
80
  React.useLayoutEffect(function () {
78
- previousContainerWidth.current = containerWidth;
79
- }, [containerWidth]);
81
+ previousContainerSize.current = containerSize;
82
+ }, [containerSize]);
80
83
  return [mergedRefs, visibleCount];
81
84
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "1.33.0",
3
+ "version": "1.33.1",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "main": "cjs/index.js",
@@ -40,7 +40,7 @@
40
40
  "build-storybook": "build-storybook"
41
41
  },
42
42
  "dependencies": {
43
- "@itwin/itwinui-css": "^0.50.0",
43
+ "@itwin/itwinui-css": "^0.50.1",
44
44
  "@itwin/itwinui-icons-react": "^1.5.0",
45
45
  "@itwin/itwinui-illustrations-react": "^1.0.1",
46
46
  "@tippyjs/react": "^4.2.5",
@@ -51,17 +51,17 @@
51
51
  },
52
52
  "devDependencies": {
53
53
  "@babel/core": "^7.12.10",
54
- "@storybook/addon-essentials": "~6.3.6",
55
- "@storybook/addon-storysource": "~6.3.6",
56
- "@storybook/addons": "~6.3.6",
57
- "@storybook/api": "~6.3.6",
58
- "@storybook/builder-webpack5": "~6.3.6",
59
- "@storybook/components": "~6.3.6",
60
- "@storybook/core-events": "~6.3.6",
61
- "@storybook/manager-webpack5": "~6.3.6",
54
+ "@storybook/addon-essentials": "~6.4.19",
55
+ "@storybook/addon-storysource": "~6.4.19",
56
+ "@storybook/addons": "~6.4.19",
57
+ "@storybook/api": "~6.4.19",
58
+ "@storybook/builder-webpack5": "~6.4.19",
59
+ "@storybook/components": "~6.4.19",
60
+ "@storybook/core-events": "~6.4.19",
61
+ "@storybook/manager-webpack5": "~6.4.19",
62
62
  "@storybook/preset-typescript": "^3.0.0",
63
- "@storybook/react": "~6.3.6",
64
- "@storybook/theming": "~6.3.6",
63
+ "@storybook/react": "~6.4.19",
64
+ "@storybook/theming": "~6.4.19",
65
65
  "@testing-library/jest-dom": "^5.14.1",
66
66
  "@testing-library/react": "^12.0.0",
67
67
  "@testing-library/react-hooks": "^7.0.1",
@@ -77,12 +77,13 @@
77
77
  "babel-loader": "^8.2.2",
78
78
  "concurrently": "^5.3.0",
79
79
  "cpx": "^1.5.0",
80
- "creevey": "^0.7.36",
80
+ "creevey": "^0.8.0-beta.0",
81
81
  "eslint": "^7.32.0",
82
82
  "eslint-config-prettier": "^8.3.0",
83
83
  "eslint-plugin-prettier": "^4.0.0",
84
84
  "eslint-plugin-react": "^7.25.1",
85
85
  "eslint-plugin-react-hooks": "^4.2.0",
86
+ "eslint-plugin-storybook": "^0.5.7",
86
87
  "fast-glob": "^3.2.5",
87
88
  "husky": "^4.0.0",
88
89
  "inquirer": "^6.2.2",
@@ -96,7 +97,7 @@
96
97
  "react": "^17.0.2",
97
98
  "react-dom": "^17.0.2",
98
99
  "rimraf": "^2.6.2",
99
- "storybook-dark-mode": "^1.0.8",
100
+ "storybook-dark-mode": "^1.0.9",
100
101
  "tippy.js": "^6.3.1",
101
102
  "ts-jest": "^27.0.4",
102
103
  "ts-loader": "^8.0.1",