@itwin/itwinui-react 3.10.0 → 3.11.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 (53) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/cjs/core/Alert/Alert.d.ts +1 -1
  3. package/cjs/core/Buttons/Button.d.ts +4 -0
  4. package/cjs/core/Buttons/Button.js +6 -4
  5. package/cjs/core/Carousel/Carousel.d.ts +2 -2
  6. package/cjs/core/Carousel/CarouselNavigation.d.ts +2 -2
  7. package/cjs/core/ComboBox/ComboBoxInput.js +2 -4
  8. package/cjs/core/ComboBox/ComboBoxMenu.js +7 -3
  9. package/cjs/core/ExpandableBlock/ExpandableBlock.d.ts +1 -1
  10. package/cjs/core/InputWithDecorations/InputWithDecorations.d.ts +1 -1
  11. package/cjs/core/LabeledSelect/LabeledSelect.d.ts +9 -9
  12. package/cjs/core/Menu/MenuItem.js +11 -2
  13. package/cjs/core/Popover/Popover.js +4 -1
  14. package/cjs/core/Select/Select.js +28 -2
  15. package/cjs/core/SideNavigation/SideNavigation.d.ts +1 -0
  16. package/cjs/core/SideNavigation/SideNavigation.js +20 -21
  17. package/cjs/core/SideNavigation/SidenavButton.js +5 -1
  18. package/cjs/core/Surface/Surface.js +2 -2
  19. package/cjs/core/Table/Table.js +4 -7
  20. package/cjs/core/Tabs/Tabs.d.ts +1 -1
  21. package/cjs/core/Tile/Tile.d.ts +17 -1
  22. package/cjs/core/Tooltip/Tooltip.js +28 -6
  23. package/cjs/core/Tree/TreeNode.d.ts +39 -0
  24. package/cjs/core/Tree/TreeNode.js +11 -11
  25. package/cjs/core/Tree/TreeNodeExpander.d.ts +2 -0
  26. package/cjs/core/Tree/TreeNodeExpander.js +2 -2
  27. package/esm/core/Alert/Alert.d.ts +1 -1
  28. package/esm/core/Buttons/Button.d.ts +4 -0
  29. package/esm/core/Buttons/Button.js +6 -4
  30. package/esm/core/Carousel/Carousel.d.ts +2 -2
  31. package/esm/core/Carousel/CarouselNavigation.d.ts +2 -2
  32. package/esm/core/ComboBox/ComboBoxInput.js +3 -5
  33. package/esm/core/ComboBox/ComboBoxMenu.js +4 -2
  34. package/esm/core/ExpandableBlock/ExpandableBlock.d.ts +1 -1
  35. package/esm/core/InputWithDecorations/InputWithDecorations.d.ts +1 -1
  36. package/esm/core/LabeledSelect/LabeledSelect.d.ts +9 -9
  37. package/esm/core/Menu/MenuItem.js +11 -2
  38. package/esm/core/Popover/Popover.js +4 -1
  39. package/esm/core/Select/Select.js +28 -2
  40. package/esm/core/SideNavigation/SideNavigation.d.ts +1 -0
  41. package/esm/core/SideNavigation/SideNavigation.js +20 -21
  42. package/esm/core/SideNavigation/SidenavButton.js +5 -1
  43. package/esm/core/Surface/Surface.js +2 -2
  44. package/esm/core/Table/Table.js +5 -8
  45. package/esm/core/Tabs/Tabs.d.ts +1 -1
  46. package/esm/core/Tile/Tile.d.ts +17 -1
  47. package/esm/core/Tooltip/Tooltip.js +28 -6
  48. package/esm/core/Tree/TreeNode.d.ts +39 -0
  49. package/esm/core/Tree/TreeNode.js +11 -11
  50. package/esm/core/Tree/TreeNodeExpander.d.ts +2 -0
  51. package/esm/core/Tree/TreeNodeExpander.js +2 -2
  52. package/package.json +1 -1
  53. package/styles.css +21 -21
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#2058](https://github.com/iTwin/iTwinUI/pull/2058): Added new `loading` prop to `Button`. This is useful when you want to display a brief loading state after the user clicks the button.
8
+
9
+ ```jsx
10
+ <Button loading={isProcessing}>Click me</Button>
11
+ ```
12
+
13
+ - [#2057](https://github.com/iTwin/iTwinUI/pull/2057): Updated warning and negative background colors to better match the rest of the color palette.
14
+ - [#2060](https://github.com/iTwin/iTwinUI/pull/2060): Updated `Tooltip` to automatically use the [`popover` API](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API) in supported browsers. This ensures that tooltips appear in the top layer, avoiding stacking context issues.
15
+ - [#2022](https://github.com/iTwin/iTwinUI/pull/2022): Added optional props to `TreeNode` for customization: `nodeProps`, `contentProps`, `labelProps`, `titleProps`, `sublabelProps`, `checkboxProps`, `iconProps`, `expanderProps` and `subTreeProps`.
16
+
17
+ ### Patch Changes
18
+
19
+ - [#2042](https://github.com/iTwin/iTwinUI/pull/2042): Fixed `Table` empty state horizontal alignment when table is very narrow.
20
+ - [#2054](https://github.com/iTwin/iTwinUI/pull/2054): Removed unnecessary gap below the inline `<InputGrid>` when no secondary line (`StatusMessage`) is present. Some other affected components: `LabeledInput`, `LabeledSelect`, `LabeledTextarea`.
21
+ - [#2049](https://github.com/iTwin/iTwinUI/pull/2049): Adjusted disabled controls' borders to slightly increase color contrast.
22
+ - [#2043](https://github.com/iTwin/iTwinUI/pull/2043): Adjusted the behavior of buttons so that double tapping them doesn't zoom the viewport on iOS.
23
+ - [#2044](https://github.com/iTwin/iTwinUI/pull/2044): Fixed a rare hydration error in `Surface` caused by using an empty string inside the `style` attribute.
24
+
25
+ ## 3.10.1
26
+
27
+ ### Patch Changes
28
+
29
+ - [#2031](https://github.com/iTwin/iTwinUI/pull/2031): Fixed an issue where popovers and dropdown menus used with `SidenavButton` were showing up inside a tooltip.
30
+ - [#2030](https://github.com/iTwin/iTwinUI/pull/2030): Fixed a visual bug where items in a `ButtonGroup` were displaying a double border when an associated `Popover` was opened.
31
+ - [#2026](https://github.com/iTwin/iTwinUI/pull/2026): Submenus within a `DropdownMenu` will now consistently require less precision when moving the mouse between the parent item and the submenu.
32
+
3
33
  ## 3.10.0
4
34
 
5
35
  ### Minor Changes
@@ -60,7 +60,7 @@ export declare const Alert: PolymorphicForwardRefComponent<"div", AlertOwnProps
60
60
  * Type of the alert.
61
61
  * @default 'informational'
62
62
  */
63
- fill?: "default" | import("../../utils/types.js").AnyString | "informational" | "negative" | "positive" | "warning" | undefined;
63
+ fill?: "default" | "positive" | "negative" | "warning" | import("../../utils/types.js").AnyString | "informational" | undefined;
64
64
  padded?: boolean | undefined;
65
65
  } & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
66
66
  as?: "span" | undefined;
@@ -38,6 +38,10 @@ export type ButtonProps = {
38
38
  * This is useful on narrow containers and mobile views.
39
39
  */
40
40
  stretched?: boolean;
41
+ /**
42
+ * Specify a loading state for the button.
43
+ */
44
+ loading?: boolean;
41
45
  } & Pick<React.ComponentProps<typeof ButtonBase>, 'htmlDisabled'>;
42
46
  /**
43
47
  * Generic button component
@@ -34,6 +34,7 @@ exports.Button = void 0;
34
34
  const classnames_1 = __importDefault(require("classnames"));
35
35
  const React = __importStar(require("react"));
36
36
  const index_js_1 = require("../../utils/index.js");
37
+ const ProgressRadial_js_1 = require("../ProgressIndicators/ProgressRadial.js");
37
38
  /**
38
39
  * Generic button component
39
40
  * @example
@@ -44,12 +45,13 @@ const index_js_1 = require("../../utils/index.js");
44
45
  * <Button startIcon={<SvgAdd />}>New</Button>
45
46
  */
46
47
  exports.Button = React.forwardRef((props, ref) => {
47
- const { children, className, size, styleType = 'default', startIcon, endIcon, labelProps, startIconProps, endIconProps, stretched, ...rest } = props;
48
- return (React.createElement(index_js_1.ButtonBase, { ref: ref, className: (0, classnames_1.default)('iui-button', 'iui-field', className), "data-iui-variant": styleType !== 'default' ? styleType : undefined, "data-iui-size": size, ...rest, style: {
48
+ const { children, className, size, styleType = 'default', startIcon, endIcon, labelProps, startIconProps, endIconProps, stretched, loading: loading, disabled: disabledProp, ...rest } = props;
49
+ return (React.createElement(index_js_1.ButtonBase, { ref: ref, className: (0, classnames_1.default)('iui-button', 'iui-field', className), "data-iui-variant": styleType !== 'default' ? styleType : undefined, "data-iui-size": size, "data-iui-loading": loading ? 'true' : undefined, disabled: disabledProp || loading, ...rest, style: {
49
50
  '--_iui-width': stretched ? '100%' : undefined,
50
51
  ...props.style,
51
52
  } },
52
53
  startIcon && (React.createElement(index_js_1.Box, { as: 'span', "aria-hidden": true, ...startIconProps, className: (0, classnames_1.default)('iui-button-icon', startIconProps?.className) }, startIcon)),
53
- children && React.createElement("span", { ...labelProps }, children),
54
- endIcon && (React.createElement(index_js_1.Box, { as: 'span', "aria-hidden": true, ...endIconProps, className: (0, classnames_1.default)('iui-button-icon', endIconProps?.className) }, endIcon))));
54
+ children && (React.createElement(index_js_1.Box, { as: 'span', ...labelProps, className: (0, classnames_1.default)('iui-button-label', labelProps?.className) }, children)),
55
+ endIcon && (React.createElement(index_js_1.Box, { as: 'span', "aria-hidden": true, ...endIconProps, className: (0, classnames_1.default)('iui-button-icon', endIconProps?.className) }, endIcon)),
56
+ loading && (React.createElement(ProgressRadial_js_1.ProgressRadial, { size: size === 'small' ? 'x-small' : 'small', className: 'iui-button-spinner', "aria-hidden": true }))));
55
57
  });
@@ -42,7 +42,7 @@ export declare const Carousel: PolymorphicForwardRefComponent<"section", Carouse
42
42
  Navigation: PolymorphicForwardRefComponent<"div", {}> & {
43
43
  PreviousButton: PolymorphicForwardRefComponent<"button", Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
44
44
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
45
- }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
45
+ }, "label" | "as" | "loading" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
46
46
  isActive?: boolean | undefined;
47
47
  label?: React.ReactNode;
48
48
  labelProps?: Omit<Omit<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
@@ -105,7 +105,7 @@ export declare const Carousel: PolymorphicForwardRefComponent<"section", Carouse
105
105
  }>;
106
106
  NextButton: PolymorphicForwardRefComponent<"button", Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
107
107
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
108
- }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
108
+ }, "label" | "as" | "loading" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
109
109
  isActive?: boolean | undefined;
110
110
  label?: React.ReactNode;
111
111
  labelProps?: Omit<Omit<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
@@ -9,7 +9,7 @@ import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
9
9
  export declare const CarouselNavigation: PolymorphicForwardRefComponent<"div", {}> & {
10
10
  PreviousButton: PolymorphicForwardRefComponent<"button", Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
11
11
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
12
- }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
12
+ }, "label" | "as" | "loading" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
13
13
  isActive?: boolean | undefined;
14
14
  label?: React.ReactNode;
15
15
  labelProps?: Omit<Omit<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
@@ -72,7 +72,7 @@ export declare const CarouselNavigation: PolymorphicForwardRefComponent<"div", {
72
72
  }>;
73
73
  NextButton: PolymorphicForwardRefComponent<"button", Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
74
74
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
75
- }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
75
+ }, "label" | "as" | "loading" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
76
76
  isActive?: boolean | undefined;
77
77
  label?: React.ReactNode;
78
78
  labelProps?: Omit<Omit<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
@@ -39,10 +39,7 @@ exports.ComboBoxInput = React.forwardRef((props, forwardedRef) => {
39
39
  const dispatch = (0, index_js_1.useSafeContext)(helpers_js_1.ComboBoxActionContext);
40
40
  const { inputRef, menuRef, optionsExtraInfoRef } = (0, index_js_1.useSafeContext)(helpers_js_1.ComboBoxRefsContext);
41
41
  const refs = (0, index_js_1.useMergedRefs)(inputRef, popover.refs.setReference, forwardedRef);
42
- const focusedIndexRef = React.useRef(focusedIndex ?? -1);
43
- React.useEffect(() => {
44
- focusedIndexRef.current = focusedIndex ?? -1;
45
- }, [focusedIndex]);
42
+ const focusedIndexRef = (0, index_js_1.useLatestRef)(focusedIndex ?? -1);
46
43
  const getIdFromIndex = (index) => {
47
44
  return (menuRef.current?.querySelector(`[data-iui-index="${index}"]`)?.id ?? '');
48
45
  };
@@ -140,6 +137,7 @@ exports.ComboBoxInput = React.forwardRef((props, forwardedRef) => {
140
137
  }, [
141
138
  dispatch,
142
139
  enableVirtualization,
140
+ focusedIndexRef,
143
141
  isOpen,
144
142
  menuRef,
145
143
  onClickHandler,
@@ -22,6 +22,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
29
  exports.ComboBoxMenu = void 0;
27
30
  /*---------------------------------------------------------------------------------------------
@@ -29,9 +32,10 @@ exports.ComboBoxMenu = void 0;
29
32
  * See LICENSE.md in the project root for license terms and full copyright notice.
30
33
  *--------------------------------------------------------------------------------------------*/
31
34
  const React = __importStar(require("react"));
32
- const Menu_js_1 = require("../Menu/Menu.js");
35
+ const classnames_1 = __importDefault(require("classnames"));
33
36
  const index_js_1 = require("../../utils/index.js");
34
37
  const helpers_js_1 = require("./helpers.js");
38
+ const List_js_1 = require("../List/List.js");
35
39
  const VirtualizedComboBoxMenu = (props) => {
36
40
  const { children, ...rest } = props;
37
41
  const { filteredOptions, getMenuItem, focusedIndex } = (0, index_js_1.useSafeContext)(helpers_js_1.ComboBoxStateContext);
@@ -58,12 +62,12 @@ const VirtualizedComboBoxMenu = (props) => {
58
62
  React.createElement("div", { ...innerProps, ref: innerProps.ref }, visibleChildren)));
59
63
  };
60
64
  exports.ComboBoxMenu = React.forwardRef((props, forwardedRef) => {
61
- const { children, style, ...rest } = props;
65
+ const { className, children, style, ...rest } = props;
62
66
  const { id, enableVirtualization, popover } = (0, index_js_1.useSafeContext)(helpers_js_1.ComboBoxStateContext);
63
67
  const { menuRef } = (0, index_js_1.useSafeContext)(helpers_js_1.ComboBoxRefsContext);
64
68
  const refs = (0, index_js_1.useMergedRefs)(popover.refs.setFloating, forwardedRef, menuRef);
65
69
  return (popover.open && (React.createElement(index_js_1.Portal, { portal: true },
66
- React.createElement(Menu_js_1.Menu, { id: `${id}-list`, setFocus: false, role: 'listbox', ref: refs, ...popover.getFloatingProps({
70
+ React.createElement(List_js_1.List, { as: 'div', className: (0, classnames_1.default)('iui-menu', className), id: `${id}-list`, role: 'listbox', ref: refs, ...popover.getFloatingProps({
67
71
  style: !enableVirtualization
68
72
  ? style
69
73
  : {
@@ -107,7 +107,7 @@ export declare const ExpandableBlock: PolymorphicForwardRefComponent<"div", Expa
107
107
  ref?: ((instance: HTMLSpanElement | null) => void) | React.RefObject<HTMLSpanElement> | null | undefined;
108
108
  }, "fill" | "as" | "key" | "size" | keyof React.HTMLAttributes<HTMLSpanElement> | "padded"> & {
109
109
  size?: "small" | "auto" | "medium" | "large" | import("../../utils/types.js").AnyString | undefined;
110
- fill?: "default" | import("../../utils/types.js").AnyString | "informational" | "negative" | "positive" | "warning" | undefined;
110
+ fill?: "default" | "positive" | "negative" | "warning" | import("../../utils/types.js").AnyString | "informational" | undefined;
111
111
  padded?: boolean | undefined;
112
112
  } & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
113
113
  as?: "span" | undefined;
@@ -32,7 +32,7 @@ export declare const InputWithDecorations: PolymorphicForwardRefComponent<"div",
32
32
  */
33
33
  Button: PolymorphicForwardRefComponent<"button", Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
34
34
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
35
- }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & Omit<import("../Buttons/IconButton.js").IconButtonProps, "styleType"> & {
35
+ }, "label" | "as" | "loading" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & Omit<import("../Buttons/IconButton.js").IconButtonProps, "styleType"> & {
36
36
  styleType?: "default" | "cta" | "high-visibility" | "borderless" | undefined;
37
37
  } & {
38
38
  as?: "button" | undefined;
@@ -131,7 +131,7 @@ export declare const LabeledSelect: <T>(props: ({
131
131
  * Status of the select.
132
132
  * @default ''
133
133
  */
134
- status?: "negative" | "positive" | "warning" | undefined;
134
+ status?: "positive" | "negative" | "warning" | undefined;
135
135
  /**
136
136
  * @deprecated Pass a `<StatusMessage startIcon={svgIcon} />` to the `message` prop instead.
137
137
  *
@@ -173,7 +173,7 @@ export declare const LabeledSelect: <T>(props: ({
173
173
  ref?: ((instance: HTMLSpanElement | null) => void) | React.RefObject<HTMLSpanElement> | null | undefined;
174
174
  }, "fill" | "as" | "key" | "size" | keyof React.HTMLAttributes<HTMLSpanElement> | "padded"> & {
175
175
  size?: "small" | "auto" | "medium" | "large" | import("../../utils/types.js").AnyString | undefined;
176
- fill?: "default" | import("../../utils/types.js").AnyString | "informational" | "negative" | "positive" | "warning" | undefined;
176
+ fill?: "default" | "positive" | "negative" | "warning" | import("../../utils/types.js").AnyString | "informational" | undefined;
177
177
  padded?: boolean | undefined;
178
178
  } & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
179
179
  as?: "span" | undefined;
@@ -183,7 +183,7 @@ export declare const LabeledSelect: <T>(props: ({
183
183
  } & {
184
184
  disabled?: boolean | undefined;
185
185
  size?: "small" | "large" | undefined;
186
- status?: "negative" | "positive" | "warning" | undefined;
186
+ status?: "positive" | "negative" | "warning" | undefined;
187
187
  } & {
188
188
  value?: string | null | undefined;
189
189
  onChange?: ((value: string, event: React.ChangeEvent<HTMLSelectElement>) => void) | undefined;
@@ -237,7 +237,7 @@ export declare const LabeledSelect: <T>(props: ({
237
237
  * Status of the select.
238
238
  * @default ''
239
239
  */
240
- status?: "negative" | "positive" | "warning" | undefined;
240
+ status?: "positive" | "negative" | "warning" | undefined;
241
241
  /**
242
242
  * @deprecated Pass a `<StatusMessage startIcon={svgIcon} />` to the `message` prop instead.
243
243
  *
@@ -279,7 +279,7 @@ export declare const LabeledSelect: <T>(props: ({
279
279
  ref?: ((instance: HTMLSpanElement | null) => void) | React.RefObject<HTMLSpanElement> | null | undefined;
280
280
  }, "fill" | "as" | "key" | "size" | keyof React.HTMLAttributes<HTMLSpanElement> | "padded"> & {
281
281
  size?: "small" | "auto" | "medium" | "large" | import("../../utils/types.js").AnyString | undefined;
282
- fill?: "default" | import("../../utils/types.js").AnyString | "informational" | "negative" | "positive" | "warning" | undefined;
282
+ fill?: "default" | "positive" | "negative" | "warning" | import("../../utils/types.js").AnyString | "informational" | undefined;
283
283
  padded?: boolean | undefined;
284
284
  } & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
285
285
  as?: "span" | undefined;
@@ -289,7 +289,7 @@ export declare const LabeledSelect: <T>(props: ({
289
289
  } & {
290
290
  disabled?: boolean | undefined;
291
291
  size?: "small" | "large" | undefined;
292
- status?: "negative" | "positive" | "warning" | undefined;
292
+ status?: "positive" | "negative" | "warning" | undefined;
293
293
  } & {
294
294
  placeholder?: React.ReactNode;
295
295
  options: import("../Select/Select.js").SelectOption<T>[];
@@ -378,7 +378,7 @@ export declare const LabeledSelect: <T>(props: ({
378
378
  * Status of the select.
379
379
  * @default ''
380
380
  */
381
- status?: "negative" | "positive" | "warning" | undefined;
381
+ status?: "positive" | "negative" | "warning" | undefined;
382
382
  /**
383
383
  * @deprecated Pass a `<StatusMessage startIcon={svgIcon} />` to the `message` prop instead.
384
384
  *
@@ -420,7 +420,7 @@ export declare const LabeledSelect: <T>(props: ({
420
420
  ref?: ((instance: HTMLSpanElement | null) => void) | React.RefObject<HTMLSpanElement> | null | undefined;
421
421
  }, "fill" | "as" | "key" | "size" | keyof React.HTMLAttributes<HTMLSpanElement> | "padded"> & {
422
422
  size?: "small" | "auto" | "medium" | "large" | import("../../utils/types.js").AnyString | undefined;
423
- fill?: "default" | import("../../utils/types.js").AnyString | "informational" | "negative" | "positive" | "warning" | undefined;
423
+ fill?: "default" | "positive" | "negative" | "warning" | import("../../utils/types.js").AnyString | "informational" | undefined;
424
424
  padded?: boolean | undefined;
425
425
  } & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
426
426
  as?: "span" | undefined;
@@ -430,7 +430,7 @@ export declare const LabeledSelect: <T>(props: ({
430
430
  } & {
431
431
  disabled?: boolean | undefined;
432
432
  size?: "small" | "large" | undefined;
433
- status?: "negative" | "positive" | "warning" | undefined;
433
+ status?: "positive" | "negative" | "warning" | undefined;
434
434
  } & {
435
435
  placeholder?: React.ReactNode;
436
436
  options: import("../Select/Select.js").SelectOption<T>[];
@@ -83,7 +83,12 @@ exports.MenuItem = React.forwardRef((props, forwardedRef) => {
83
83
  const popover = (0, Popover_js_1.usePopover)({
84
84
  nodeId,
85
85
  visible: isSubmenuVisible,
86
- onVisibleChange: setIsSubmenuVisible,
86
+ onVisibleChange: React.useCallback((visible) => {
87
+ if (!visible) {
88
+ setHasFocusedNodeInSubmenu(false);
89
+ }
90
+ setIsSubmenuVisible(visible);
91
+ }, []),
87
92
  placement: 'right-start',
88
93
  interactions: !disabled
89
94
  ? {
@@ -128,7 +133,11 @@ exports.MenuItem = React.forwardRef((props, forwardedRef) => {
128
133
  }
129
134
  };
130
135
  const onFocus = () => {
131
- parent.setHasFocusedNodeInSubmenu?.(true);
136
+ // Set hasFocusedNodeInSubmenu in a microtask to ensure the submenu stays open reliably.
137
+ // E.g. Even when hovering into it rapidly.
138
+ queueMicrotask(() => {
139
+ parent.setHasFocusedNodeInSubmenu?.(true);
140
+ });
132
141
  tree?.events.emit('onNodeFocused', {
133
142
  nodeId,
134
143
  parentId,
@@ -90,7 +90,10 @@ const usePopover = (options) => {
90
90
  (0, react_1.useHover)(floating.context, {
91
91
  enabled: !!mergedInteractions.hover,
92
92
  delay: 100,
93
- handleClose: (0, react_1.safePolygon)({ buffer: 1, requireIntent: false }),
93
+ handleClose: (0, react_1.safePolygon)({
94
+ buffer: 1,
95
+ blockPointerEvents: true,
96
+ }),
94
97
  move: false,
95
98
  ...mergedInteractions.hover,
96
99
  }),
@@ -33,13 +33,14 @@ exports.Select = void 0;
33
33
  *--------------------------------------------------------------------------------------------*/
34
34
  const React = __importStar(require("react"));
35
35
  const classnames_1 = __importDefault(require("classnames"));
36
- const Menu_js_1 = require("../Menu/Menu.js");
37
36
  const MenuItem_js_1 = require("../Menu/MenuItem.js");
38
37
  const index_js_1 = require("../../utils/index.js");
39
38
  const SelectTag_js_1 = require("./SelectTag.js");
40
39
  const SelectTagContainer_js_1 = require("./SelectTagContainer.js");
41
40
  const Icon_js_1 = require("../Icon/Icon.js");
42
41
  const Popover_js_1 = require("../Popover/Popover.js");
42
+ const List_js_1 = require("../List/List.js");
43
+ const react_1 = require("@floating-ui/react");
43
44
  // ----------------------------------------------------------------------------
44
45
  /**
45
46
  * Select component to select value from options.
@@ -216,6 +217,16 @@ const CustomSelect = React.forwardRef((props, forwardedRef) => {
216
217
  ? options.filter((option) => value.some((val) => val === option.value))
217
218
  : options.find((option) => option.value === value);
218
219
  }, [multiple, options, value]);
220
+ const defaultFocusedIndex = React.useMemo(() => {
221
+ let index = 0;
222
+ if (Array.isArray(value) && value.length > 0) {
223
+ index = options.findIndex((option) => option.value === value[0]);
224
+ }
225
+ else if (value) {
226
+ index = options.findIndex((option) => option.value === value);
227
+ }
228
+ return index >= 0 ? index : 0;
229
+ }, [options, value]);
219
230
  const tagRenderer = React.useCallback((item) => {
220
231
  return React.createElement(SelectTag_js_1.SelectTag, { key: item.label, label: item.label });
221
232
  }, []);
@@ -236,7 +247,7 @@ const CustomSelect = React.forwardRef((props, forwardedRef) => {
236
247
  React.createElement(SelectEndIcon, { disabled: disabled, isOpen: isOpen }),
237
248
  multiple ? (React.createElement(index_js_1.AutoclearingHiddenLiveRegion, { text: liveRegionSelection })) : null),
238
249
  popover.open && (React.createElement(index_js_1.Portal, null,
239
- React.createElement(Menu_js_1.Menu, { role: 'listbox', className: menuClassName, id: `${uid}-menu`, key: `${uid}-menu`, ...popover.getFloatingProps({
250
+ React.createElement(SelectListbox, { defaultFocusedIndex: defaultFocusedIndex, className: menuClassName, id: `${uid}-menu`, key: `${uid}-menu`, ...popover.getFloatingProps({
240
251
  style: menuStyle,
241
252
  onKeyDown: ({ key }) => {
242
253
  if (key === 'Tab') {
@@ -291,3 +302,18 @@ const MultipleSelectButton = ({ selectedItems, selectedItemsRenderer, tagRendere
291
302
  selectedItems && !selectedItemsRenderer && (React.createElement(index_js_1.Box, { as: 'span', className: 'iui-content' },
292
303
  React.createElement(SelectTagContainer_js_1.SelectTagContainer, { tags: selectedItemsElements })))));
293
304
  };
305
+ // ----------------------------------------------------------------------------
306
+ const SelectListbox = React.forwardRef((props, forwardedRef) => {
307
+ const { defaultFocusedIndex = 0, autoFocus = true, children: childrenProp, className, ...rest } = props;
308
+ const [focusedIndex, setFocusedIndex] = React.useState(defaultFocusedIndex);
309
+ const autoFocusRef = React.useCallback((element) => {
310
+ queueMicrotask(() => {
311
+ const firstFocusable = element?.querySelector('[tabindex="0"]');
312
+ firstFocusable?.focus();
313
+ });
314
+ }, []);
315
+ const children = React.useMemo(() => {
316
+ return React.Children.map(childrenProp, (child, index) => React.isValidElement(child) ? (React.createElement(react_1.CompositeItem, { key: index, render: child, ref: child.props.ref || child.ref })) : (child));
317
+ }, [childrenProp]);
318
+ return (React.createElement(react_1.Composite, { render: React.createElement(List_js_1.List, { as: 'div', className: (0, classnames_1.default)('iui-menu', className) }), orientation: 'vertical', role: 'listbox', activeIndex: focusedIndex, onNavigate: setFocusedIndex, ref: (0, index_js_1.useMergedRefs)(forwardedRef, autoFocus ? autoFocusRef : undefined), ...rest }, children));
319
+ });
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
3
+ export declare const SidenavExpandedContext: React.Context<boolean | undefined>;
3
4
  type SideNavigationProps = {
4
5
  /**
5
6
  * Buttons shown in the top portion of sidenav.
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.SideNavigation = void 0;
29
+ exports.SideNavigation = exports.SidenavExpandedContext = void 0;
30
30
  /*---------------------------------------------------------------------------------------------
31
31
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
32
32
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -35,7 +35,8 @@ const React = __importStar(require("react"));
35
35
  const classnames_1 = __importDefault(require("classnames"));
36
36
  const index_js_1 = require("../../utils/index.js");
37
37
  const IconButton_js_1 = require("../Buttons/IconButton.js");
38
- const Tooltip_js_1 = require("../Tooltip/Tooltip.js");
38
+ // ----------------------------------------------------------------------------
39
+ exports.SidenavExpandedContext = React.createContext(undefined);
39
40
  /**
40
41
  * Left side navigation menu component.
41
42
  * @example
@@ -51,25 +52,23 @@ const Tooltip_js_1 = require("../Tooltip/Tooltip.js");
51
52
  * />
52
53
  */
53
54
  exports.SideNavigation = React.forwardRef((props, forwardedRef) => {
54
- const { items, secondaryItems, expanderPlacement = 'top', className, isExpanded = false, onExpanderClick, submenu, isSubmenuOpen = false, wrapperProps, contentProps, topProps, bottomProps, ...rest } = props;
55
- const [_isExpanded, _setIsExpanded] = React.useState(isExpanded);
56
- React.useEffect(() => {
57
- _setIsExpanded(isExpanded);
58
- }, [isExpanded]);
59
- const ExpandButton = (React.createElement(IconButton_js_1.IconButton, { label: 'Toggle icon labels', "aria-expanded": _isExpanded, className: 'iui-sidenav-button iui-expand', size: 'small', onClick: React.useCallback(() => {
60
- _setIsExpanded((expanded) => !expanded);
55
+ const { items, secondaryItems, expanderPlacement = 'top', className, isExpanded: isExpandedProp, onExpanderClick, submenu, isSubmenuOpen = false, wrapperProps, contentProps, topProps, bottomProps, ...rest } = props;
56
+ const [isExpanded, setIsExpanded] = (0, index_js_1.useControlledState)(false, isExpandedProp);
57
+ const ExpandButton = (React.createElement(IconButton_js_1.IconButton, { label: 'Toggle icon labels', "aria-expanded": isExpanded, className: 'iui-sidenav-button iui-expand', size: 'small', onClick: React.useCallback(() => {
58
+ setIsExpanded((expanded) => !expanded);
61
59
  onExpanderClick?.();
62
- }, [onExpanderClick]) },
60
+ }, [onExpanderClick, setIsExpanded]) },
63
61
  React.createElement(index_js_1.SvgChevronRight, null)));
64
- return (React.createElement(index_js_1.Box, { ...wrapperProps, className: (0, classnames_1.default)('iui-side-navigation-wrapper', wrapperProps?.className), ref: forwardedRef },
65
- React.createElement(index_js_1.Box, { as: 'div', className: (0, classnames_1.default)('iui-side-navigation', {
66
- 'iui-expanded': _isExpanded,
67
- 'iui-collapsed': !_isExpanded,
68
- }, className), ...rest },
69
- expanderPlacement === 'top' && ExpandButton,
70
- React.createElement(index_js_1.Box, { as: 'div', ...contentProps, className: (0, classnames_1.default)('iui-sidenav-content', contentProps?.className) },
71
- React.createElement(index_js_1.Box, { as: 'div', ...topProps, className: (0, classnames_1.default)('iui-top', topProps?.className) }, items.map((sidenavButton, index) => !_isExpanded ? (React.createElement(Tooltip_js_1.Tooltip, { content: sidenavButton.props.children, placement: 'right', key: index }, sidenavButton)) : (sidenavButton))),
72
- React.createElement(index_js_1.Box, { as: 'div', ...bottomProps, className: (0, classnames_1.default)('iui-bottom', bottomProps?.className) }, secondaryItems?.map((sidenavButton, index) => !_isExpanded ? (React.createElement(Tooltip_js_1.Tooltip, { content: sidenavButton.props.children, placement: 'right', key: index }, sidenavButton)) : (sidenavButton)))),
73
- expanderPlacement === 'bottom' && ExpandButton),
74
- submenu && (React.createElement(index_js_1.WithCSSTransition, { in: isSubmenuOpen, dimension: 'width', timeout: 200, classNames: 'iui' }, submenu))));
62
+ return (React.createElement(exports.SidenavExpandedContext.Provider, { value: isExpanded },
63
+ React.createElement(index_js_1.Box, { ...wrapperProps, className: (0, classnames_1.default)('iui-side-navigation-wrapper', wrapperProps?.className), ref: forwardedRef },
64
+ React.createElement(index_js_1.Box, { as: 'div', className: (0, classnames_1.default)('iui-side-navigation', {
65
+ 'iui-expanded': isExpanded,
66
+ 'iui-collapsed': !isExpanded,
67
+ }, className), ...rest },
68
+ expanderPlacement === 'top' && ExpandButton,
69
+ React.createElement(index_js_1.Box, { as: 'div', ...contentProps, className: (0, classnames_1.default)('iui-sidenav-content', contentProps?.className) },
70
+ React.createElement(index_js_1.Box, { as: 'div', ...topProps, className: (0, classnames_1.default)('iui-top', topProps?.className) }, items),
71
+ React.createElement(index_js_1.Box, { as: 'div', ...bottomProps, className: (0, classnames_1.default)('iui-bottom', bottomProps?.className) }, secondaryItems)),
72
+ expanderPlacement === 'bottom' && ExpandButton),
73
+ submenu && (React.createElement(index_js_1.WithCSSTransition, { in: isSubmenuOpen, dimension: 'width', timeout: 200, classNames: 'iui' }, submenu)))));
75
74
  });
@@ -34,11 +34,15 @@ exports.SidenavButton = void 0;
34
34
  const classnames_1 = __importDefault(require("classnames"));
35
35
  const React = __importStar(require("react"));
36
36
  const Button_js_1 = require("../Buttons/Button.js");
37
+ const Tooltip_js_1 = require("../Tooltip/Tooltip.js");
38
+ const SideNavigation_js_1 = require("./SideNavigation.js");
37
39
  /**
38
40
  * Wrapper around Button to be used as SideNavigation items.
39
41
  * Label is hidden when sidenav is collapsed.
40
42
  */
41
43
  exports.SidenavButton = React.forwardRef((props, ref) => {
42
44
  const { className, children, isActive = false, disabled = false, isSubmenuOpen = false, ...rest } = props;
43
- return (React.createElement(Button_js_1.Button, { className: (0, classnames_1.default)('iui-sidenav-button', { 'iui-submenu-open': isSubmenuOpen }, className), "data-iui-active": isActive, size: 'large', disabled: disabled, ref: ref, ...rest }, children));
45
+ const isExpanded = React.useContext(SideNavigation_js_1.SidenavExpandedContext) === true;
46
+ const sidenavButton = (React.createElement(Button_js_1.Button, { className: (0, classnames_1.default)('iui-sidenav-button', { 'iui-submenu-open': isSubmenuOpen }, className), "data-iui-active": isActive, size: 'large', disabled: disabled, ref: ref, ...rest }, children));
47
+ return !isExpanded ? (React.createElement(Tooltip_js_1.Tooltip, { content: children, placement: 'right', ariaStrategy: 'none' }, sidenavButton)) : (sidenavButton);
44
48
  });
@@ -52,7 +52,7 @@ const getSurfaceElevationValue = (elevation) => {
52
52
  case 5:
53
53
  return 'var(--iui-shadow-5)';
54
54
  default:
55
- return '';
55
+ return undefined;
56
56
  }
57
57
  };
58
58
  /** Returns correct border value based on prop */
@@ -63,7 +63,7 @@ const getBorderValue = (border) => {
63
63
  if (border === false) {
64
64
  return 'none';
65
65
  }
66
- return '';
66
+ return undefined;
67
67
  };
68
68
  // ----------------------------------------------------------------------------
69
69
  // Surface.Header component
@@ -110,13 +110,8 @@ const Table = (props) => {
110
110
  minWidth: 0,
111
111
  width: 0,
112
112
  }), []);
113
- // useRef prevents from rerendering when one of these callbacks changes
114
- const onBottomReachedRef = React.useRef(onBottomReached);
115
- const onRowInViewportRef = React.useRef(onRowInViewport);
116
- React.useEffect(() => {
117
- onBottomReachedRef.current = onBottomReached;
118
- onRowInViewportRef.current = onRowInViewport;
119
- }, [onBottomReached, onRowInViewport]);
113
+ const onBottomReachedRef = (0, index_js_1.useLatestRef)(onBottomReached);
114
+ const onRowInViewportRef = (0, index_js_1.useLatestRef)(onRowInViewport);
120
115
  const hasManualSelectionColumn = React.useMemo(() => {
121
116
  const flatColumns = flattenColumns(columns);
122
117
  return flatColumns.some((column) => column.id === index_js_5.SELECTION_CELL_ID);
@@ -386,6 +381,8 @@ const Table = (props) => {
386
381
  enableVirtualization,
387
382
  tableRowRef,
388
383
  density,
384
+ onBottomReachedRef,
385
+ onRowInViewportRef,
389
386
  ]);
390
387
  const virtualizedItemRenderer = React.useCallback((index) => getPreparedRow(index), [getPreparedRow]);
391
388
  const updateStickyState = () => {
@@ -269,7 +269,7 @@ export declare const Tabs: PolymorphicForwardRefComponent<"div", TabsLegacyProps
269
269
  ref?: ((instance: HTMLSpanElement | null) => void) | React.RefObject<HTMLSpanElement> | null | undefined;
270
270
  }, "fill" | "as" | "key" | "size" | keyof React.HTMLAttributes<HTMLSpanElement> | "padded"> & {
271
271
  size?: "small" | "auto" | "medium" | "large" | import("../../utils/types.js").AnyString | undefined;
272
- fill?: "default" | import("../../utils/types.js").AnyString | "informational" | "negative" | "positive" | "warning" | undefined;
272
+ fill?: "default" | "positive" | "negative" | "warning" | import("../../utils/types.js").AnyString | "informational" | undefined;
273
273
  padded?: boolean | undefined;
274
274
  } & Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & {
275
275
  as?: "span" | undefined;
@@ -249,7 +249,7 @@ export declare const Tile: PolymorphicForwardRefComponent<"div", TileLegacyProps
249
249
  */
250
250
  IconButton: PolymorphicForwardRefComponent<"button", Omit<Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
251
251
  ref?: ((instance: HTMLButtonElement | null) => void) | React.RefObject<HTMLButtonElement> | null | undefined;
252
- }, "label" | "as" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
252
+ }, "label" | "as" | "loading" | "size" | "htmlDisabled" | "styleType" | "labelProps" | "stretched" | "isActive" | "iconProps"> & {
253
253
  isActive?: boolean | undefined;
254
254
  label?: React.ReactNode;
255
255
  labelProps?: Omit<Omit<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
@@ -262,6 +262,14 @@ export declare const Tile: PolymorphicForwardRefComponent<"div", TileLegacyProps
262
262
  ancestorScroll?: boolean | undefined;
263
263
  ancestorResize?: boolean | undefined;
264
264
  elementResize?: boolean | undefined;
265
+ /**
266
+ * Flag whether the tile is disabled.
267
+ *
268
+ * Note: This only affects the tile. You need to manually disable
269
+ * the buttons and other interactive elements inside the tile.
270
+ *
271
+ * @default false
272
+ */
265
273
  animationFrame?: boolean | undefined;
266
274
  layoutShift?: boolean | undefined;
267
275
  } | undefined;
@@ -288,6 +296,14 @@ export declare const Tile: PolymorphicForwardRefComponent<"div", TileLegacyProps
288
296
  ancestorScroll?: boolean | undefined;
289
297
  ancestorResize?: boolean | undefined;
290
298
  elementResize?: boolean | undefined;
299
+ /**
300
+ * Flag whether the tile is disabled.
301
+ *
302
+ * Note: This only affects the tile. You need to manually disable
303
+ * the buttons and other interactive elements inside the tile.
304
+ *
305
+ * @default false
306
+ */
291
307
  animationFrame?: boolean | undefined;
292
308
  layoutShift?: boolean | undefined;
293
309
  } | undefined;