@itwin/itwinui-react 1.29.1 → 1.31.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 (44) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/cjs/core/Badge/Badge.js +2 -2
  3. package/cjs/core/ButtonGroup/ButtonGroup.d.ts +10 -3
  4. package/cjs/core/ButtonGroup/ButtonGroup.js +4 -3
  5. package/cjs/core/ColorPicker/ColorBuilder.js +19 -11
  6. package/cjs/core/ColorPicker/ColorSwatch.js +2 -2
  7. package/cjs/core/ComboBox/ComboBox.js +41 -36
  8. package/cjs/core/Modal/Modal.js +4 -1
  9. package/cjs/core/Radio/Radio.js +1 -1
  10. package/cjs/core/Select/Select.js +23 -8
  11. package/cjs/core/Slider/Slider.js +8 -2
  12. package/cjs/core/Table/Table.d.ts +10 -0
  13. package/cjs/core/Table/Table.js +23 -8
  14. package/cjs/core/Table/TablePaginator.js +7 -9
  15. package/cjs/core/Tile/Tile.js +16 -20
  16. package/cjs/core/utils/components/Popover.d.ts +2 -1
  17. package/cjs/core/utils/components/Popover.js +9 -6
  18. package/cjs/core/utils/components/VirtualScroll.d.ts +42 -0
  19. package/cjs/core/utils/components/VirtualScroll.js +174 -0
  20. package/cjs/core/utils/components/index.d.ts +1 -0
  21. package/cjs/core/utils/components/index.js +1 -0
  22. package/cjs/core/utils/props.d.ts +2 -2
  23. package/esm/core/Badge/Badge.js +2 -2
  24. package/esm/core/ButtonGroup/ButtonGroup.d.ts +10 -3
  25. package/esm/core/ButtonGroup/ButtonGroup.js +4 -3
  26. package/esm/core/ColorPicker/ColorBuilder.js +19 -11
  27. package/esm/core/ColorPicker/ColorSwatch.js +2 -2
  28. package/esm/core/ComboBox/ComboBox.js +41 -36
  29. package/esm/core/Modal/Modal.js +4 -1
  30. package/esm/core/Radio/Radio.js +1 -1
  31. package/esm/core/Select/Select.js +23 -8
  32. package/esm/core/Slider/Slider.js +8 -2
  33. package/esm/core/Table/Table.d.ts +10 -0
  34. package/esm/core/Table/Table.js +23 -8
  35. package/esm/core/Table/TablePaginator.js +7 -9
  36. package/esm/core/Tile/Tile.js +16 -20
  37. package/esm/core/utils/components/Popover.d.ts +2 -1
  38. package/esm/core/utils/components/Popover.js +9 -6
  39. package/esm/core/utils/components/VirtualScroll.d.ts +42 -0
  40. package/esm/core/utils/components/VirtualScroll.js +168 -0
  41. package/esm/core/utils/components/index.d.ts +1 -0
  42. package/esm/core/utils/components/index.js +1 -0
  43. package/esm/core/utils/props.d.ts +2 -2
  44. package/package.json +4 -3
@@ -29,15 +29,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.hideOnEscOrTab = exports.Popover = void 0;
31
31
  var react_1 = __importDefault(require("react"));
32
+ var classnames_1 = __importDefault(require("classnames"));
32
33
  var react_2 = __importDefault(require("@tippyjs/react"));
33
34
  var useMergedRefs_1 = require("../hooks/useMergedRefs");
35
+ require("@itwin/itwinui-css/css/popover.css");
34
36
  /**
35
37
  * Wrapper around [tippy.js](https://atomiks.github.io/tippyjs)
36
38
  * with pre-configured props and plugins (e.g. lazy mounting, focus, etc).
37
39
  * @private
38
40
  */
39
41
  exports.Popover = react_1.default.forwardRef(function (props, ref) {
40
- var _a = react_1.default.useState(false), mounted = _a[0], setMounted = _a[1];
42
+ var _a;
43
+ var _b = react_1.default.useState(false), mounted = _b[0], setMounted = _b[1];
41
44
  var tippyRef = react_1.default.useRef(null);
42
45
  var refs = (0, useMergedRefs_1.useMergedRefs)(tippyRef, ref);
43
46
  // Plugin to allow lazy mounting. See https://github.com/atomiks/tippyjs-react#lazy-mounting
@@ -56,14 +59,14 @@ exports.Popover = react_1.default.forwardRef(function (props, ref) {
56
59
  },
57
60
  }); },
58
61
  };
59
- var computedProps = __assign(__assign({ allowHTML: true, animation: false, appendTo: 'parent', arrow: false, duration: 0, interactive: true, popperOptions: {
60
- strategy: 'fixed',
61
- modifiers: [{ name: 'flip' }],
62
- }, role: undefined, offset: [0, 0], maxWidth: '' }, props), { plugins: __spreadArray([
62
+ var computedProps = __assign(__assign({ allowHTML: true, animation: false, appendTo: 'parent', arrow: false, duration: 0, interactive: true, role: undefined, offset: [0, 0], maxWidth: '' }, props), { className: (0, classnames_1.default)('iui-popover', props.className), plugins: __spreadArray([
63
63
  lazyLoad,
64
64
  removeTabIndex,
65
65
  exports.hideOnEscOrTab
66
- ], (props.plugins || []), true) });
66
+ ], (props.plugins || []), true), popperOptions: __assign(__assign({ strategy: 'fixed' }, props.popperOptions), { modifiers: __spreadArray([
67
+ { name: 'flip' },
68
+ { name: 'preventOverflow', options: { padding: 0 } }
69
+ ], (((_a = props.popperOptions) === null || _a === void 0 ? void 0 : _a.modifiers) || []), true) }) });
67
70
  if (props.render) {
68
71
  var render_1 = props.render;
69
72
  computedProps.render = function () {
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ export declare type VirtualScrollProps = {
3
+ /**
4
+ * Length of the items to virtualize.
5
+ */
6
+ itemsLength: number;
7
+ /**
8
+ * Single item render function, which gives index of the item (0 based) in the data array
9
+ * and expects to get the JSX of that element to render.
10
+ * Recommended to memoize the reference of the function.
11
+ */
12
+ itemRenderer: (index: number) => JSX.Element;
13
+ /**
14
+ * Number of items to be rendered at the start and the end.
15
+ * Not recommended to go lower than the visible items in viewport.
16
+ * @default 10
17
+ */
18
+ bufferSize?: number;
19
+ } & React.ComponentPropsWithRef<'div'>;
20
+ /**
21
+ * `VirtualScroll` component is used to render a huge amount of items in the DOM. It renders only the ones which are visible
22
+ * and the amount provided through `bufferSize` prop at the start and the end. Can be used inside other components like `Table`.
23
+ *
24
+ * It has two wrapper elements, so DOM will be changed. One is used for setting full expected height in the scrollable container
25
+ * and other is for transformation (translateY) to show the correct part of the list.
26
+ *
27
+ * Currently it works only with the direct vertically scrollable parent element. It does not work with body scroll.
28
+ * It supports only static (same) height rows virtualization. Expect some issues, if list consists of different height elements.
29
+ * @example
30
+ * const itemRenderer = React.useCallback(() => (
31
+ * <div key={index}>
32
+ * This is my item #{index}
33
+ * </div>
34
+ * ), [])
35
+ * <VirtualScroll
36
+ * itemsLength={1000}
37
+ * itemRenderer={itemRenderer}
38
+ * />
39
+ * @private
40
+ */
41
+ export declare const VirtualScroll: React.ForwardRefExoticComponent<Pick<VirtualScrollProps, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "itemsLength" | "itemRenderer" | "bufferSize"> & React.RefAttributes<HTMLDivElement>>;
42
+ export default VirtualScroll;
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __rest = (this && this.__rest) || function (s, e) {
14
+ var t = {};
15
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
+ t[p] = s[p];
17
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
+ t[p[i]] = s[p[i]];
21
+ }
22
+ return t;
23
+ };
24
+ var __importDefault = (this && this.__importDefault) || function (mod) {
25
+ return (mod && mod.__esModule) ? mod : { "default": mod };
26
+ };
27
+ Object.defineProperty(exports, "__esModule", { value: true });
28
+ exports.VirtualScroll = void 0;
29
+ /*---------------------------------------------------------------------------------------------
30
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
31
+ * See LICENSE.md in the project root for license terms and full copyright notice.
32
+ *--------------------------------------------------------------------------------------------*/
33
+ var react_1 = __importDefault(require("react"));
34
+ var useResizeObserver_1 = require("../hooks/useResizeObserver");
35
+ var getScrollableParent = function (element, ownerDocument) {
36
+ if (ownerDocument === void 0) { ownerDocument = document; }
37
+ if (!element || element === ownerDocument.body) {
38
+ return ownerDocument.body;
39
+ }
40
+ return isElementScrollable(element)
41
+ ? element
42
+ : getScrollableParent(element.parentElement, ownerDocument);
43
+ };
44
+ var isElementScrollable = function (element) {
45
+ return /(auto|scroll|overlay)/.test(getElementStyle(element, 'overflow') +
46
+ getElementStyle(element, 'overflow-y'));
47
+ };
48
+ var getElementStyle = function (element, prop) {
49
+ return getComputedStyle(element, null).getPropertyValue(prop);
50
+ };
51
+ var getElementHeight = function (element) {
52
+ var _a;
53
+ return (_a = element === null || element === void 0 ? void 0 : element.getBoundingClientRect().height) !== null && _a !== void 0 ? _a : 0;
54
+ };
55
+ var getNumberOfNodesInHeight = function (childHeight, totalHeight) {
56
+ if (!childHeight) {
57
+ return 0;
58
+ }
59
+ return Math.floor(totalHeight / childHeight);
60
+ };
61
+ var getTranslateValue = function (childHeight, startIndex) {
62
+ return childHeight * startIndex;
63
+ };
64
+ var getVisibleNodeCount = function (childHeight, startIndex, childrenLength, scrollContainer) {
65
+ return Math.min(childrenLength - startIndex, getNumberOfNodesInHeight(childHeight, getElementHeight(scrollContainer)));
66
+ };
67
+ /**
68
+ * `VirtualScroll` component is used to render a huge amount of items in the DOM. It renders only the ones which are visible
69
+ * and the amount provided through `bufferSize` prop at the start and the end. Can be used inside other components like `Table`.
70
+ *
71
+ * It has two wrapper elements, so DOM will be changed. One is used for setting full expected height in the scrollable container
72
+ * and other is for transformation (translateY) to show the correct part of the list.
73
+ *
74
+ * Currently it works only with the direct vertically scrollable parent element. It does not work with body scroll.
75
+ * It supports only static (same) height rows virtualization. Expect some issues, if list consists of different height elements.
76
+ * @example
77
+ * const itemRenderer = React.useCallback(() => (
78
+ * <div key={index}>
79
+ * This is my item #{index}
80
+ * </div>
81
+ * ), [])
82
+ * <VirtualScroll
83
+ * itemsLength={1000}
84
+ * itemRenderer={itemRenderer}
85
+ * />
86
+ * @private
87
+ */
88
+ exports.VirtualScroll = react_1.default.forwardRef(function (_a, ref) {
89
+ var itemsLength = _a.itemsLength, itemRenderer = _a.itemRenderer, _b = _a.bufferSize, bufferSize = _b === void 0 ? 10 : _b, style = _a.style, rest = __rest(_a, ["itemsLength", "itemRenderer", "bufferSize", "style"]);
90
+ var _c = react_1.default.useState(0), startNode = _c[0], setStartNode = _c[1];
91
+ var _d = react_1.default.useState(0), visibleNodeCount = _d[0], setVisibleNodeCount = _d[1];
92
+ var scrollContainer = react_1.default.useRef();
93
+ var parentRef = react_1.default.useRef(null);
94
+ var childHeight = react_1.default.useRef(0);
95
+ var onScrollRef = react_1.default.useRef();
96
+ // Used only to recalculate on resize
97
+ var _e = react_1.default.useState(0), scrollContainerHeight = _e[0], setScrollContainerHeight = _e[1];
98
+ var onResize = react_1.default.useCallback(function (_a) {
99
+ var height = _a.height;
100
+ setScrollContainerHeight(height);
101
+ }, []);
102
+ var resizeRef = (0, useResizeObserver_1.useResizeObserver)(onResize)[0];
103
+ // Find scrollable parent
104
+ // Needed only on init
105
+ react_1.default.useLayoutEffect(function () {
106
+ var _a;
107
+ var scrollableParent = getScrollableParent(parentRef.current, (_a = parentRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument);
108
+ scrollContainer.current = scrollableParent;
109
+ resizeRef(scrollableParent);
110
+ }, [resizeRef]);
111
+ var visibleChildren = react_1.default.useMemo(function () {
112
+ var arr = [];
113
+ var endIndex = Math.min(itemsLength, startNode + visibleNodeCount + bufferSize * 2);
114
+ for (var i = startNode; i < endIndex; i++) {
115
+ arr.push(itemRenderer(i));
116
+ }
117
+ return arr;
118
+ }, [itemsLength, itemRenderer, bufferSize, startNode, visibleNodeCount]);
119
+ // Get child height when children available
120
+ react_1.default.useLayoutEffect(function () {
121
+ if (!parentRef.current || !visibleChildren.length) {
122
+ return;
123
+ }
124
+ var firstChild = parentRef.current.children.item(0);
125
+ childHeight.current = Number(getElementHeight(firstChild).toFixed(2));
126
+ }, [visibleChildren.length]);
127
+ var updateVirtualScroll = react_1.default.useCallback(function () {
128
+ var _a, _b;
129
+ var scrollableContainer = (_a = scrollContainer.current) !== null && _a !== void 0 ? _a : (_b = parentRef.current) === null || _b === void 0 ? void 0 : _b.ownerDocument.scrollingElement;
130
+ if (!scrollableContainer) {
131
+ return;
132
+ }
133
+ var start = getNumberOfNodesInHeight(childHeight.current, scrollableContainer.scrollTop);
134
+ var startIndex = Math.max(0, start - bufferSize);
135
+ setStartNode(startIndex);
136
+ setVisibleNodeCount(getVisibleNodeCount(childHeight.current, start, itemsLength, scrollableContainer));
137
+ if (!parentRef.current) {
138
+ return;
139
+ }
140
+ parentRef.current.style.transform = "translateY(" + getTranslateValue(childHeight.current, startIndex) + "px)";
141
+ }, [bufferSize, itemsLength]);
142
+ var removeScrollListener = react_1.default.useCallback(function () {
143
+ var _a, _b;
144
+ if (!onScrollRef.current) {
145
+ return;
146
+ }
147
+ !scrollContainer.current ||
148
+ scrollContainer.current === ((_a = parentRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument.body)
149
+ ? (_b = parentRef.current) === null || _b === void 0 ? void 0 : _b.ownerDocument.removeEventListener('scroll', onScrollRef.current)
150
+ : scrollContainer.current.removeEventListener('scroll', onScrollRef.current);
151
+ }, []);
152
+ // Add event listener to the scrollable container.
153
+ react_1.default.useLayoutEffect(function () {
154
+ var _a, _b;
155
+ removeScrollListener();
156
+ onScrollRef.current = updateVirtualScroll;
157
+ if (!scrollContainer.current ||
158
+ scrollContainer.current === ((_a = parentRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument.body)) {
159
+ (_b = parentRef.current) === null || _b === void 0 ? void 0 : _b.ownerDocument.addEventListener('scroll', updateVirtualScroll);
160
+ }
161
+ else {
162
+ scrollContainer.current.addEventListener('scroll', updateVirtualScroll);
163
+ }
164
+ return removeScrollListener;
165
+ }, [updateVirtualScroll, removeScrollListener]);
166
+ react_1.default.useLayoutEffect(function () {
167
+ updateVirtualScroll();
168
+ }, [scrollContainerHeight, itemsLength, updateVirtualScroll]);
169
+ return (react_1.default.createElement("div", __assign({ style: __assign({ overflow: 'hidden', minHeight: itemsLength * childHeight.current, width: '100%' }, style), ref: ref }, rest),
170
+ react_1.default.createElement("div", { style: {
171
+ willChange: 'transform',
172
+ }, ref: parentRef }, visibleChildren)));
173
+ });
174
+ exports.default = exports.VirtualScroll;
@@ -4,3 +4,4 @@ export * from './InputContainer';
4
4
  export * from './icons';
5
5
  export * from './WithCSSTransition';
6
6
  export * from './MiddleTextTruncation';
7
+ export * from './VirtualScroll';
@@ -20,3 +20,4 @@ __exportStar(require("./InputContainer"), exports);
20
20
  __exportStar(require("./icons"), exports);
21
21
  __exportStar(require("./WithCSSTransition"), exports);
22
22
  __exportStar(require("./MiddleTextTruncation"), exports);
23
+ __exportStar(require("./VirtualScroll"), exports);
@@ -42,9 +42,9 @@ export interface PolymorphicForwardRefComponent<T, OwnProps = Record<string, unk
42
42
  as?: T;
43
43
  }>> {
44
44
  <As = T>(props: As extends keyof JSX.IntrinsicElements ? Merge<JSX.IntrinsicElements[As], OwnProps & {
45
- as?: As;
45
+ as: As;
46
46
  }> : As extends React.ComponentType<infer P> ? Merge<P, OwnProps & {
47
- as?: As;
47
+ as: As;
48
48
  }> : never): React.ReactElement | null;
49
49
  }
50
50
  declare type Merge<P1, P2> = Omit<P1, keyof P2> & P2;
@@ -60,8 +60,8 @@ export var Badge = function (props) {
60
60
  var backgroundColor = props.backgroundColor, style = props.style, className = props.className, children = props.children, rest = __rest(props, ["backgroundColor", "style", "className", "children"]);
61
61
  useTheme();
62
62
  var _style = backgroundColor &&
63
- ((_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, "--badge-color: " + backgroundColor))
64
- ? __assign({ '--badge-color': getBadgeColorValue(backgroundColor) }, style) : __assign({ backgroundColor: getBadgeColorValue(backgroundColor) }, style);
63
+ ((_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, "--iui-badge-background-color: " + backgroundColor))
64
+ ? __assign({ '--iui-badge-background-color': getBadgeColorValue(backgroundColor) }, style) : __assign({ backgroundColor: getBadgeColorValue(backgroundColor) }, style);
65
65
  return (React.createElement("span", __assign({ className: cx('iui-badge', className), style: _style }, rest), children));
66
66
  };
67
67
  export default Badge;
@@ -6,13 +6,20 @@ export declare type ButtonGroupProps = {
6
6
  */
7
7
  children: React.ReactNode;
8
8
  /**
9
- * If specified, this prop will be used to show a custom button as the last button
10
- * when overflow happens, i.e. when there is not enough space to fit all the buttons.
9
+ * If specified, this prop will be used to show a custom button when overflow happens,
10
+ * i.e. when there is not enough space to fit all the buttons.
11
11
  *
12
12
  * Expects a function that takes the index of the first button that is overflowing (i.e. hidden)
13
13
  * and returns the `ReactNode` to render.
14
+ *
15
+ * The placement of this button can be controlled using the `overflowPlacement` prop.
14
16
  */
15
17
  overflowButton?: (firstOverflowingIndex: number) => React.ReactNode;
18
+ /**
19
+ * If `overflowButton` is specified, should it placed at the start or the end?
20
+ * @default 'end'
21
+ */
22
+ overflowPlacement?: 'start' | 'end';
16
23
  } & React.ComponentPropsWithRef<'div'>;
17
24
  /**
18
25
  * Group buttons together for common actions.
@@ -42,5 +49,5 @@ export declare type ButtonGroupProps = {
42
49
  * {buttons}
43
50
  * </ButtonGroup>
44
51
  */
45
- export declare const ButtonGroup: React.ForwardRefExoticComponent<Pick<ButtonGroupProps, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "overflowButton"> & React.RefAttributes<HTMLDivElement>>;
52
+ export declare const ButtonGroup: React.ForwardRefExoticComponent<Pick<ButtonGroupProps, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "overflowButton" | "overflowPlacement"> & React.RefAttributes<HTMLDivElement>>;
46
53
  export default ButtonGroup;
@@ -57,13 +57,14 @@ 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, rest = __rest(props, ["children", "className", "style", "overflowButton"]);
60
+ var children = props.children, className = props.className, style = props.style, overflowButton = props.overflowButton, _a = props.overflowPlacement, overflowPlacement = _a === void 0 ? 'end' : _a, rest = __rest(props, ["children", "className", "style", "overflowButton", "overflowPlacement"]);
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 _a = useOverflow(items, !overflowButton), overflowRef = _a[0], visibleCount = _a[1];
63
+ var _b = useOverflow(items, !overflowButton), overflowRef = _b[0], visibleCount = _b[1];
64
64
  var refs = useMergedRefs(overflowRef, ref);
65
65
  return (React.createElement("div", __assign({ className: cx('iui-button-group', className), style: __assign(__assign({}, (!!overflowButton && { width: '100%' })), style), ref: refs }, rest), !!overflowButton && visibleCount < items.length ? (React.createElement(React.Fragment, null,
66
+ overflowButton && overflowPlacement === 'start' && (React.createElement("div", null, overflowButton(visibleCount))),
66
67
  items.slice(0, visibleCount - 1),
67
- overflowButton(visibleCount))) : (items)));
68
+ overflowButton && overflowPlacement === 'end' && (React.createElement("div", null, overflowButton(visibleCount))))) : (items)));
68
69
  });
69
70
  export default ButtonGroup;
@@ -63,21 +63,20 @@ export var ColorBuilder = React.forwardRef(function (props, ref) {
63
63
  ]);
64
64
  var _p = React.useState(false), colorDotActive = _p[0], setColorDotActive = _p[1];
65
65
  var hueColorString = hueSliderColor.toHexString();
66
- var colorSquareStyle = ((_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, "--hue:\u00A0" + hueColorString))
66
+ var colorSquareStyle = ((_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, "--iui-color-field-hue: " + hueColorString))
67
67
  ? {
68
- '--hue': hueColorString,
69
- '--selected-color': dotColorString,
68
+ '--iui-color-field-hue': hueColorString,
69
+ '--iui-color-picker-selected-color': dotColorString,
70
70
  }
71
71
  : { backgroundColor: hueColorString };
72
- var opacitySliderStyle = ((_f = (_e = (_d = getWindow()) === null || _d === void 0 ? void 0 : _d.CSS) === null || _e === void 0 ? void 0 : _e.supports) === null || _f === void 0 ? void 0 : _f.call(_e, "--selected-color:\u00A0" + hueColorString))
73
- ? { '--selected-color': hueColorString }
72
+ var opacitySliderStyle = ((_f = (_e = (_d = getWindow()) === null || _d === void 0 ? void 0 : _d.CSS) === null || _e === void 0 ? void 0 : _e.supports) === null || _f === void 0 ? void 0 : _f.call(_e, "--iui-color-picker-selected-color: " + hueColorString))
73
+ ? { '--iui-color-picker-selected-color': hueColorString }
74
74
  : { backgroundColor: hueColorString };
75
75
  var squareTop = 100 - hsvColor.v;
76
76
  var squareLeft = hsvColor.s;
77
- var colorDotStyle = ((_j = (_h = (_g = getWindow()) === null || _g === void 0 ? void 0 : _g.CSS) === null || _h === void 0 ? void 0 : _h.supports) === null || _j === void 0 ? void 0 : _j.call(_h, "--top:\u00A0" + squareTop.toString() + "%"))
77
+ var colorDotStyle = ((_j = (_h = (_g = getWindow()) === null || _g === void 0 ? void 0 : _g.CSS) === null || _h === void 0 ? void 0 : _h.supports) === null || _j === void 0 ? void 0 : _j.call(_h, "--iui-color-dot-inset: 0"))
78
78
  ? {
79
- '--top': squareTop.toString() + '%',
80
- '--left': squareLeft.toString() + '%',
79
+ '--iui-color-dot-inset': squareTop.toString() + "% auto auto " + squareLeft.toString() + "%",
81
80
  }
82
81
  : {
83
82
  backgroundColor: dotColorString,
@@ -132,22 +131,31 @@ export var ColorBuilder = React.forwardRef(function (props, ref) {
132
131
  }
133
132
  }, [colorDotActive, updateColorDot]);
134
133
  var handleSquarePointerUp = React.useCallback(function (event) {
134
+ if (!colorDotActive) {
135
+ return;
136
+ }
135
137
  updateSquareValue(event, 'onChange');
136
138
  setColorDotActive(false);
137
139
  event.preventDefault();
138
140
  event.stopPropagation();
139
- }, [updateSquareValue]);
141
+ }, [colorDotActive, updateSquareValue]);
140
142
  useEventListener('pointerup', handleSquarePointerUp, (_k = builderRef.current) === null || _k === void 0 ? void 0 : _k.ownerDocument);
141
143
  var handleSquarePointerMove = React.useCallback(function (event) {
144
+ if (!colorDotActive) {
145
+ return;
146
+ }
142
147
  event.preventDefault();
143
148
  event.stopPropagation();
144
149
  updateSquareValue(event, 'onUpdate');
145
- }, [updateSquareValue]);
150
+ }, [colorDotActive, updateSquareValue]);
146
151
  useEventListener('pointermove', handleSquarePointerMove, (_l = builderRef.current) === null || _l === void 0 ? void 0 : _l.ownerDocument);
147
152
  var handleSquarePointerLeave = React.useCallback(function (event) {
153
+ if (!colorDotActive) {
154
+ return;
155
+ }
148
156
  updateSquareValue(event, 'onChange');
149
157
  setColorDotActive(false);
150
- }, [updateSquareValue]);
158
+ }, [colorDotActive, updateSquareValue]);
151
159
  useEventListener('pointerleave', handleSquarePointerLeave, (_m = builderRef.current) === null || _m === void 0 ? void 0 : _m.ownerDocument);
152
160
  var keysPressed = React.useRef({}); // keep track of which keys are currently pressed
153
161
  // Arrow key navigation for color dot
@@ -45,8 +45,8 @@ export var ColorSwatch = React.forwardRef(function (props, ref) {
45
45
  }, [color]);
46
46
  var _style = React.useMemo(function () {
47
47
  var _a, _b, _c;
48
- return ((_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, "--swatch-color: " + colorString))
49
- ? __assign({ '--swatch-color': colorString }, style) : __assign({ backgroundColor: colorString }, style);
48
+ return ((_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, "--iui-color-swatch-background: " + colorString))
49
+ ? __assign({ '--iui-color-swatch-background': colorString }, style) : __assign({ backgroundColor: colorString }, style);
50
50
  }, [colorString, style]);
51
51
  return (React.createElement("div", __assign({ className: cx('iui-color-swatch', { 'iui-active': isActive }, className), style: _style, onClick: onClick, tabIndex: isActive ? 0 : -1, "aria-selected": isActive, ref: ref }, rest)));
52
52
  });
@@ -235,41 +235,46 @@ export var ComboBox = function (props) {
235
235
  selectedValue,
236
236
  memoizedItems,
237
237
  ]);
238
- return (React.createElement(InputContainer, __assign({ className: className, isIconInline: true, icon: React.useMemo(function () { return (React.createElement("span", { ref: toggleButtonRef, className: cx({
239
- 'iui-actionable': !(inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled),
240
- 'iui-open': isOpen,
241
- }), onClick: function () {
242
- var _a;
243
- if (isOpen) {
244
- setIsOpen(false);
245
- }
246
- else {
247
- (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
248
- }
249
- } },
250
- React.createElement(SvgCaretDownSmall, { "aria-hidden": true }))); }, [inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled, isOpen]) }, rest, { id: id }),
251
- React.createElement(Popover, __assign({ placement: 'bottom-start', visible: isOpen, onClickOutside: function (_, _a) {
252
- var _b;
253
- var target = _a.target;
254
- if (!((_b = toggleButtonRef.current) === null || _b === void 0 ? void 0 : _b.contains(target))) {
255
- setIsOpen(false);
256
- }
257
- }, animation: 'shift-away', duration: 200 }, dropdownMenuProps, { content: React.createElement(Menu, { id: id + "-list", className: 'iui-scroll', style: {
258
- minWidth: minWidth,
259
- maxWidth: "min(" + minWidth * 2 + "px, 90vw)",
260
- maxHeight: 300,
261
- }, setFocus: false, role: 'listbox', ref: menuRef }, menuItems), onHide: function (instance) {
262
- var _a;
263
- var selectedIndex = options.findIndex(function (_a) {
264
- var value = _a.value;
265
- return value === selectedValue;
266
- });
267
- setFocusedIndex(selectedIndex);
268
- if (selectedIndex > -1) {
269
- setInputValue(options[selectedIndex].label); // update input value to be same as selected value
270
- }
271
- (_a = dropdownMenuProps === null || dropdownMenuProps === void 0 ? void 0 : dropdownMenuProps.onHide) === null || _a === void 0 ? void 0 : _a.call(dropdownMenuProps, instance);
272
- } }),
273
- React.createElement(Input, __assign({ ref: inputRef, onKeyDown: onKeyDown, onFocus: function () { return setIsOpen(true); }, onChange: onInput, value: inputValue, "aria-activedescendant": isOpen && focusedIndex > -1 ? getOptionId(focusedIndex) : undefined, role: 'combobox', "aria-controls": isOpen ? id + "-list" : undefined, "aria-autocomplete": 'list', spellCheck: false, autoCapitalize: 'none', autoCorrect: 'off' }, inputProps)))));
238
+ return (React.createElement(InputContainer, __assign({ className: className, isIconInline: true }, rest, { id: id }),
239
+ React.createElement("div", { className: 'iui-input-with-icon' },
240
+ React.createElement(Popover, __assign({ placement: 'bottom-start', visible: isOpen, onClickOutside: function (_, _a) {
241
+ var _b;
242
+ var target = _a.target;
243
+ if (!((_b = toggleButtonRef.current) === null || _b === void 0 ? void 0 : _b.contains(target))) {
244
+ setIsOpen(false);
245
+ }
246
+ }, animation: 'shift-away', duration: 200 }, dropdownMenuProps, { content: React.createElement(Menu, { id: id + "-list", className: 'iui-scroll', style: {
247
+ minWidth: minWidth,
248
+ maxWidth: "min(" + minWidth * 2 + "px, 90vw)",
249
+ maxHeight: 300,
250
+ }, setFocus: false, role: 'listbox', ref: menuRef }, menuItems), onHide: function (instance) {
251
+ var _a;
252
+ var selectedIndex = options.findIndex(function (_a) {
253
+ var value = _a.value;
254
+ return value === selectedValue;
255
+ });
256
+ setFocusedIndex(selectedIndex);
257
+ if (selectedIndex > -1) {
258
+ setInputValue(options[selectedIndex].label); // update input value to be same as selected value
259
+ }
260
+ (_a = dropdownMenuProps === null || dropdownMenuProps === void 0 ? void 0 : dropdownMenuProps.onHide) === null || _a === void 0 ? void 0 : _a.call(dropdownMenuProps, instance);
261
+ } }),
262
+ React.createElement(Input, __assign({ ref: inputRef, onKeyDown: onKeyDown, onFocus: function () { return setIsOpen(true); }, onChange: onInput, value: inputValue, "aria-activedescendant": isOpen && focusedIndex > -1
263
+ ? getOptionId(focusedIndex)
264
+ : undefined, role: 'combobox', "aria-controls": isOpen ? id + "-list" : undefined, "aria-autocomplete": 'list', spellCheck: false, autoCapitalize: 'none', autoCorrect: 'off' }, inputProps))),
265
+ React.createElement("span", { ref: toggleButtonRef, className: cx('iui-end-icon', {
266
+ 'iui-actionable': !(inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled),
267
+ 'iui-disabled': inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled,
268
+ 'iui-open': isOpen,
269
+ }), onClick: function () {
270
+ var _a;
271
+ if (isOpen) {
272
+ setIsOpen(false);
273
+ }
274
+ else {
275
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
276
+ }
277
+ } },
278
+ React.createElement(SvgCaretDownSmall, { "aria-hidden": true })))));
274
279
  };
275
280
  export default ComboBox;
@@ -104,13 +104,16 @@ export var Modal = function (props) {
104
104
  var handleMouseDown = function (event) {
105
105
  // Prevents React from resetting its properties
106
106
  event.persist();
107
+ if (event.target !== overlayRef.current) {
108
+ return;
109
+ }
107
110
  if (isDismissible && closeOnExternalClick && onClose) {
108
111
  onClose(event);
109
112
  }
110
113
  };
111
114
  return !!container ? (ReactDOM.createPortal(isOpen && (React.createElement(FocusTrap, null,
112
115
  React.createElement("div", __assign({ className: cx('iui-modal', 'iui-modal-visible', className), tabIndex: -1, onKeyDown: handleKeyDown, ref: overlayRef, onMouseDown: handleMouseDown }, rest),
113
- React.createElement("div", { className: 'iui-modal-dialog', id: id, style: style, role: 'dialog', "aria-modal": 'true', onMouseDown: function (event) { return event.stopPropagation(); } },
116
+ React.createElement("div", { className: 'iui-modal-dialog', id: id, style: style, role: 'dialog', "aria-modal": 'true' },
114
117
  React.createElement("div", { className: 'iui-title-bar' },
115
118
  React.createElement("div", { className: 'iui-title' }, title),
116
119
  isDismissible && (React.createElement(IconButton, { size: 'small', styleType: 'borderless', onClick: onClose, "aria-label": 'Close' },
@@ -52,7 +52,7 @@ export var Radio = React.forwardRef(function (props, ref) {
52
52
  React.createElement("input", __assign({ disabled: disabled, type: 'radio', ref: refs }, rest)),
53
53
  React.createElement("span", { className: cx('iui-radio-dot', checkmarkClassName), style: checkmarkStyle },
54
54
  React.createElement("svg", { viewBox: '0 0 16 16', "aria-hidden": 'true', focusable: 'false' },
55
- React.createElement("circle", { cx: '8', cy: '8', r: '6' }))),
55
+ React.createElement("circle", { cx: '8', cy: '8', r: '4' }))),
56
56
  label && React.createElement("span", { className: 'iui-label' }, label)));
57
57
  });
58
58
  export default Radio;
@@ -30,6 +30,7 @@ import { DropdownMenu } from '../DropdownMenu';
30
30
  import { MenuItem } from '../Menu/MenuItem';
31
31
  import { useTheme } from '../utils';
32
32
  import '@itwin/itwinui-css/css/inputs.css';
33
+ import SvgCaretDownSmall from '@itwin/itwinui-icons-react/cjs/icons/CaretDownSmall';
33
34
  /**
34
35
  * Select component to select value from options.
35
36
  * Generic type is used for value. It prevents you from mistakenly using other types in `options`, `value` and `onChange`.
@@ -91,6 +92,7 @@ export var Select = function (props) {
91
92
  var _f = React.useState(0), minWidth = _f[0], setMinWidth = _f[1];
92
93
  var toggle = function () { return setIsOpen(function (open) { return !open; }); };
93
94
  var selectRef = React.useRef(null);
95
+ var toggleButtonRef = React.useRef(null);
94
96
  var onShowHandler = React.useCallback(function (instance) {
95
97
  setIsOpen(true);
96
98
  onShow === null || onShow === void 0 ? void 0 : onShow(instance);
@@ -137,13 +139,20 @@ export var Select = function (props) {
137
139
  }
138
140
  return options.find(function (option) { return option.value === value; });
139
141
  }, [options, value]);
140
- return (React.createElement("div", __assign({ className: cx('iui-select', (_a = {}, _a["iui-" + size] = !!size, _a), className), "aria-expanded": isOpen, "aria-haspopup": 'listbox', style: style }, rest),
141
- React.createElement(DropdownMenu, __assign({ menuItems: menuItems, placement: 'bottom-start', className: cx('iui-scroll', menuClassName), style: __assign({ minWidth: minWidth, maxWidth: "min(" + minWidth * 2 + "px, 90vw)", maxHeight: "300px" }, menuStyle), role: 'listbox', onShow: onShowHandler, onHide: onHideHandler, disabled: disabled }, popoverProps, { visible: isOpen }),
142
- React.createElement("div", { ref: selectRef, className: cx('iui-select-button', {
143
- 'iui-placeholder': !selectedItem && !!placeholder,
144
- 'iui-disabled': disabled,
145
- 'iui-active': isOpen,
146
- }), onClick: function () { return !disabled && toggle(); }, onKeyDown: function (e) { return !disabled && onKeyDown(e, toggle); }, tabIndex: !disabled ? 0 : undefined },
142
+ return (React.createElement("div", __assign({ className: cx('iui-input-with-icon', className), "aria-expanded": isOpen, "aria-haspopup": 'listbox', style: style }, rest),
143
+ React.createElement(DropdownMenu, __assign({ menuItems: menuItems, placement: 'bottom-start', className: cx('iui-scroll', menuClassName), style: __assign({ minWidth: minWidth, maxWidth: "min(" + minWidth * 2 + "px, 90vw)", maxHeight: "300px" }, menuStyle), role: 'listbox', onShow: onShowHandler, onHide: onHideHandler, disabled: disabled }, popoverProps, { visible: isOpen, onClickOutside: function (_, _a) {
144
+ var _b;
145
+ var target = _a.target;
146
+ if (!((_b = toggleButtonRef.current) === null || _b === void 0 ? void 0 : _b.contains(target))) {
147
+ setIsOpen(false);
148
+ }
149
+ } }),
150
+ React.createElement("div", { ref: selectRef, className: cx('iui-select-button', (_a = {
151
+ 'iui-placeholder': !selectedItem && !!placeholder,
152
+ 'iui-disabled': disabled
153
+ },
154
+ _a["iui-" + size] = !!size,
155
+ _a)), onClick: function () { return !disabled && toggle(); }, onKeyDown: function (e) { return !disabled && onKeyDown(e, toggle); }, tabIndex: !disabled ? 0 : undefined },
147
156
  !selectedItem && React.createElement("span", { className: 'iui-content' }, placeholder),
148
157
  selectedItem &&
149
158
  selectedItemRenderer &&
@@ -153,6 +162,12 @@ export var Select = function (props) {
153
162
  React.cloneElement(selectedItem.icon, {
154
163
  className: cx(selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.icon.props.className, 'iui-icon'),
155
164
  }),
156
- React.createElement("span", { className: 'iui-content' }, selectedItem.label)))))));
165
+ React.createElement("span", { className: 'iui-content' }, selectedItem.label))))),
166
+ React.createElement("span", { ref: toggleButtonRef, className: cx('iui-end-icon', {
167
+ 'iui-actionable': !disabled,
168
+ 'iui-disabled': disabled,
169
+ 'iui-open': isOpen,
170
+ }), onClick: function () { return !disabled && toggle(); } },
171
+ React.createElement(SvgCaretDownSmall, { "aria-hidden": true }))));
157
172
  };
158
173
  export default Select;
@@ -158,10 +158,13 @@ export var Slider = React.forwardRef(function (props, ref) {
158
158
  onChange,
159
159
  ]);
160
160
  var handlePointerMove = React.useCallback(function (event) {
161
+ if (activeThumbIndex === undefined) {
162
+ return;
163
+ }
161
164
  event.preventDefault();
162
165
  event.stopPropagation();
163
166
  updateThumbValue(event, 'onUpdate');
164
- }, [updateThumbValue]);
167
+ }, [activeThumbIndex, updateThumbValue]);
165
168
  // function called by Thumb keyboard processing
166
169
  var onThumbValueChanged = React.useCallback(function (index, value) {
167
170
  if (currentValues[index] === value) {
@@ -176,11 +179,14 @@ export var Slider = React.forwardRef(function (props, ref) {
176
179
  setActiveThumbIndex(index);
177
180
  }, []);
178
181
  var handlePointerUp = React.useCallback(function (event) {
182
+ if (activeThumbIndex === undefined) {
183
+ return;
184
+ }
179
185
  updateThumbValue(event, 'onChange');
180
186
  setActiveThumbIndex(undefined);
181
187
  event.preventDefault();
182
188
  event.stopPropagation();
183
- }, [updateThumbValue]);
189
+ }, [activeThumbIndex, updateThumbValue]);
184
190
  var handlePointerDownOnSlider = React.useCallback(function (event) {
185
191
  if (containerRef.current) {
186
192
  var percent = getPercentageOfRectangle(containerRef.current.getBoundingClientRect(), event.clientX);