@itwin/itwinui-react 3.17.0-dev.0 → 3.17.0-dev.2

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 (86) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/DEV-cjs/core/Dialog/Dialog.js +35 -42
  3. package/DEV-cjs/core/Dialog/DialogBackdrop.js +6 -1
  4. package/DEV-cjs/core/Dialog/DialogMain.js +42 -34
  5. package/DEV-cjs/core/Dialog/DialogMainContext.js +23 -0
  6. package/DEV-cjs/core/Dialog/DialogTitleBar.js +10 -1
  7. package/DEV-cjs/core/Panels/Panels.js +1 -1
  8. package/DEV-cjs/core/SideNavigation/SideNavigation.js +1 -11
  9. package/DEV-cjs/core/Table/actionHandlers/selectHandler.js +7 -8
  10. package/DEV-cjs/core/Tabs/Tabs.js +9 -1
  11. package/DEV-cjs/core/ThemeProvider/ThemeProvider.js +12 -9
  12. package/DEV-cjs/core/Toast/Toast.js +132 -77
  13. package/DEV-cjs/core/Toast/Toaster.js +11 -3
  14. package/DEV-cjs/styles.js +1 -1
  15. package/DEV-cjs/utils/components/index.js +0 -1
  16. package/DEV-esm/core/Dialog/Dialog.js +32 -42
  17. package/DEV-esm/core/Dialog/DialogBackdrop.js +6 -1
  18. package/DEV-esm/core/Dialog/DialogMain.js +42 -34
  19. package/DEV-esm/core/Dialog/DialogMainContext.js +3 -0
  20. package/DEV-esm/core/Dialog/DialogTitleBar.js +10 -1
  21. package/DEV-esm/core/Panels/Panels.js +2 -1
  22. package/DEV-esm/core/SideNavigation/SideNavigation.js +2 -17
  23. package/DEV-esm/core/Table/actionHandlers/selectHandler.js +7 -8
  24. package/DEV-esm/core/Tabs/Tabs.js +9 -1
  25. package/DEV-esm/core/ThemeProvider/ThemeProvider.js +12 -9
  26. package/DEV-esm/core/Toast/Toast.js +131 -75
  27. package/DEV-esm/core/Toast/Toaster.js +11 -3
  28. package/DEV-esm/styles.js +1 -1
  29. package/DEV-esm/utils/components/index.js +0 -1
  30. package/LICENSE.md +1 -1
  31. package/cjs/core/Dialog/Dialog.d.ts +1 -1
  32. package/cjs/core/Dialog/Dialog.js +35 -42
  33. package/cjs/core/Dialog/DialogBackdrop.d.ts +1 -1
  34. package/cjs/core/Dialog/DialogBackdrop.js +6 -1
  35. package/cjs/core/Dialog/DialogMain.js +42 -34
  36. package/cjs/core/Dialog/DialogMainContext.d.ts +7 -0
  37. package/cjs/core/Dialog/DialogMainContext.js +23 -0
  38. package/cjs/core/Dialog/DialogTitleBar.js +10 -1
  39. package/cjs/core/Panels/Panels.js +1 -1
  40. package/cjs/core/SideNavigation/SideNavigation.d.ts +2 -2
  41. package/cjs/core/SideNavigation/SideNavigation.js +1 -11
  42. package/cjs/core/Table/actionHandlers/selectHandler.js +7 -8
  43. package/cjs/core/Tabs/Tabs.js +9 -1
  44. package/cjs/core/ThemeProvider/ThemeContext.d.ts +2 -1
  45. package/cjs/core/ThemeProvider/ThemeProvider.d.ts +13 -5
  46. package/cjs/core/ThemeProvider/ThemeProvider.js +12 -9
  47. package/cjs/core/Toast/Toast.d.ts +1 -1
  48. package/cjs/core/Toast/Toast.js +132 -77
  49. package/cjs/core/Toast/Toaster.d.ts +1 -1
  50. package/cjs/core/Toast/Toaster.js +11 -3
  51. package/cjs/styles.js +1 -1
  52. package/cjs/utils/components/index.d.ts +0 -1
  53. package/cjs/utils/components/index.js +0 -1
  54. package/cjs/utils/hooks/useGlobals.d.ts +1 -0
  55. package/esm/core/Dialog/Dialog.d.ts +1 -1
  56. package/esm/core/Dialog/Dialog.js +32 -42
  57. package/esm/core/Dialog/DialogBackdrop.d.ts +1 -1
  58. package/esm/core/Dialog/DialogBackdrop.js +6 -1
  59. package/esm/core/Dialog/DialogMain.js +42 -34
  60. package/esm/core/Dialog/DialogMainContext.d.ts +7 -0
  61. package/esm/core/Dialog/DialogMainContext.js +3 -0
  62. package/esm/core/Dialog/DialogTitleBar.js +10 -1
  63. package/esm/core/Panels/Panels.js +2 -1
  64. package/esm/core/SideNavigation/SideNavigation.d.ts +2 -2
  65. package/esm/core/SideNavigation/SideNavigation.js +2 -17
  66. package/esm/core/Table/actionHandlers/selectHandler.js +7 -8
  67. package/esm/core/Tabs/Tabs.js +9 -1
  68. package/esm/core/ThemeProvider/ThemeContext.d.ts +2 -1
  69. package/esm/core/ThemeProvider/ThemeProvider.d.ts +13 -5
  70. package/esm/core/ThemeProvider/ThemeProvider.js +12 -9
  71. package/esm/core/Toast/Toast.d.ts +1 -1
  72. package/esm/core/Toast/Toast.js +131 -75
  73. package/esm/core/Toast/Toaster.d.ts +1 -1
  74. package/esm/core/Toast/Toaster.js +11 -3
  75. package/esm/styles.js +1 -1
  76. package/esm/utils/components/index.d.ts +0 -1
  77. package/esm/utils/components/index.js +0 -1
  78. package/esm/utils/hooks/useGlobals.d.ts +1 -0
  79. package/package.json +5 -7
  80. package/styles.css +10 -10
  81. package/DEV-cjs/utils/components/WithCSSTransition.js +0 -60
  82. package/DEV-esm/utils/components/WithCSSTransition.js +0 -49
  83. package/cjs/utils/components/WithCSSTransition.d.ts +0 -6
  84. package/cjs/utils/components/WithCSSTransition.js +0 -60
  85. package/esm/utils/components/WithCSSTransition.d.ts +0 -6
  86. package/esm/utils/components/WithCSSTransition.js +0 -49
@@ -7,7 +7,6 @@ import { DialogContext } from './DialogContext.js';
7
7
  import { DialogButtonBar } from './DialogButtonBar.js';
8
8
  import { DialogMain } from './DialogMain.js';
9
9
  import { useMergedRefs, Box, Portal } from '../../utils/index.js';
10
- import { Transition } from 'react-transition-group';
11
10
  let DialogComponent = React.forwardRef((props, ref) => {
12
11
  let {
13
12
  trapFocus = false,
@@ -27,49 +26,40 @@ let DialogComponent = React.forwardRef((props, ref) => {
27
26
  ...rest
28
27
  } = props;
29
28
  let dialogRootRef = React.useRef(null);
30
- return React.createElement(
31
- Transition,
32
- {
33
- in: isOpen,
34
- timeout: {
35
- exit: 600,
36
- },
37
- mountOnEnter: true,
38
- unmountOnExit: true,
39
- },
40
- React.createElement(
41
- DialogContext.Provider,
42
- {
43
- value: {
44
- isOpen,
45
- onClose,
46
- closeOnEsc,
47
- closeOnExternalClick,
48
- isDismissible,
49
- preventDocumentScroll,
50
- trapFocus,
51
- setFocus,
52
- isDraggable,
53
- isResizable,
54
- relativeTo,
55
- dialogRootRef,
56
- placement,
57
- },
58
- },
59
- React.createElement(
60
- Portal,
29
+ let mergedRefs = useMergedRefs(ref, dialogRootRef);
30
+ return isOpen
31
+ ? React.createElement(
32
+ DialogContext.Provider,
61
33
  {
62
- portal: portal,
34
+ value: {
35
+ isOpen,
36
+ onClose,
37
+ closeOnEsc,
38
+ closeOnExternalClick,
39
+ isDismissible,
40
+ preventDocumentScroll,
41
+ trapFocus,
42
+ setFocus,
43
+ isDraggable,
44
+ isResizable,
45
+ relativeTo,
46
+ placement,
47
+ },
63
48
  },
64
- React.createElement(Box, {
65
- className: cx('iui-dialog-wrapper', className),
66
- 'data-iui-relative': 'container' === relativeTo,
67
- ref: useMergedRefs(ref, dialogRootRef),
68
- ...rest,
69
- }),
70
- ),
71
- ),
72
- );
49
+ React.createElement(
50
+ Portal,
51
+ {
52
+ portal: portal,
53
+ },
54
+ React.createElement(Box, {
55
+ className: cx('iui-dialog-wrapper', className),
56
+ 'data-iui-relative': 'container' === relativeTo,
57
+ ref: mergedRefs,
58
+ ...rest,
59
+ }),
60
+ ),
61
+ )
62
+ : null;
73
63
  });
74
64
  export const Dialog = Object.assign(DialogComponent, {
75
65
  Backdrop: DialogBackdrop,
@@ -1,6 +1,6 @@
1
1
  import type { BackdropProps } from '../Backdrop/Backdrop.js';
2
2
  import type { PolymorphicForwardRefComponent } from '../../utils/index.js';
3
- import type { DialogContextProps } from './DialogContext.js';
3
+ import { type DialogContextProps } from './DialogContext.js';
4
4
  type DialogBackdropProps = BackdropProps & Pick<DialogContextProps, 'onClose' | 'isDismissible' | 'closeOnExternalClick' | 'relativeTo'>;
5
5
  /**
6
6
  * Backdrop component for dialog. Recommended to be used with `Dialog`
@@ -2,9 +2,11 @@ import * as React from 'react';
2
2
  import { Backdrop } from '../Backdrop/Backdrop.js';
3
3
  import { useMergedRefs } from '../../utils/index.js';
4
4
  import { useDialogContext } from './DialogContext.js';
5
+ import { useDialogMainContext } from './DialogMainContext.js';
5
6
  import cx from 'classnames';
6
7
  export const DialogBackdrop = React.forwardRef((props, ref) => {
7
8
  let dialogContext = useDialogContext();
9
+ let dialogMainContext = useDialogMainContext();
8
10
  let {
9
11
  isVisible = dialogContext.isOpen,
10
12
  isDismissible = dialogContext.isDismissible,
@@ -21,7 +23,10 @@ export const DialogBackdrop = React.forwardRef((props, ref) => {
21
23
  let handleMouseDown = (event) => {
22
24
  event.persist();
23
25
  if (event.target !== backdropRef.current) return;
24
- if (isDismissible && closeOnExternalClick && onClose) onClose(event);
26
+ if (isDismissible && closeOnExternalClick && onClose) {
27
+ dialogMainContext?.beforeClose();
28
+ onClose(event);
29
+ }
25
30
  onMouseDown?.(event);
26
31
  };
27
32
  return React.createElement(Backdrop, {
@@ -10,9 +10,9 @@ import {
10
10
  ShadowRoot,
11
11
  } from '../../utils/index.js';
12
12
  import { useDialogContext } from './DialogContext.js';
13
- import { Transition } from 'react-transition-group';
14
13
  import { DialogDragContext } from './DialogDragContext.js';
15
14
  import { useDragAndDrop } from '../../utils/hooks/useDragAndDrop.js';
15
+ import { DialogMainContext } from './DialogMainContext.js';
16
16
  export const DialogMain = React.forwardRef((props, ref) => {
17
17
  let dialogContext = useDialogContext();
18
18
  let {
@@ -33,12 +33,13 @@ export const DialogMain = React.forwardRef((props, ref) => {
33
33
  placement = dialogContext.placement,
34
34
  ...rest
35
35
  } = props;
36
- let [style, setStyle] = React.useState();
36
+ let { dialogRootRef } = dialogContext;
37
37
  let dialogRef = React.useRef(null);
38
- let hasBeenResized = React.useRef(false);
39
38
  let previousFocusedElement = React.useRef();
39
+ let [style, setStyle] = React.useState();
40
+ let hasBeenResized = React.useRef(false);
40
41
  let originalBodyOverflow = React.useRef('');
41
- React.useEffect(() => {
42
+ useLayoutEffect(() => {
42
43
  if (isOpen) originalBodyOverflow.current = document.body.style.overflow;
43
44
  }, [isOpen]);
44
45
  React.useEffect(() => {
@@ -54,17 +55,19 @@ export const DialogMain = React.forwardRef((props, ref) => {
54
55
  return () => {
55
56
  ownerDocument.body.style.overflow = originalBodyOverflow.current;
56
57
  };
57
- }, [isOpen, preventDocumentScroll]);
58
+ }, [dialogRef, isOpen, preventDocumentScroll]);
58
59
  let handleKeyDown = (event) => {
59
60
  if (event.altKey) return;
60
61
  event.persist();
61
- if (isDismissible && closeOnEsc && 'Escape' === event.key && onClose)
62
+ if (isDismissible && closeOnEsc && 'Escape' === event.key && onClose) {
63
+ beforeClose();
62
64
  onClose(event);
65
+ }
63
66
  onKeyDown?.(event);
64
67
  };
65
68
  let { onPointerDown, transform } = useDragAndDrop(
66
69
  dialogRef,
67
- dialogContext.dialogRootRef,
70
+ dialogRootRef,
68
71
  isDraggable,
69
72
  );
70
73
  let handlePointerDown = React.useCallback(
@@ -84,13 +87,35 @@ export const DialogMain = React.forwardRef((props, ref) => {
84
87
  insetBlockStart: dialogRef.current?.offsetTop,
85
88
  transform: `translate(${translateX}px,${translateY}px)`,
86
89
  }));
87
- }, [isDraggable, isOpen]);
90
+ }, [dialogRef, isDraggable, isOpen]);
88
91
  let setResizeStyle = React.useCallback((newStyle) => {
89
92
  setStyle((oldStyle) => ({
90
93
  ...oldStyle,
91
94
  ...newStyle,
92
95
  }));
93
96
  }, []);
97
+ let onEnter = React.useCallback(() => {
98
+ previousFocusedElement.current =
99
+ dialogRef.current?.ownerDocument.activeElement;
100
+ if (setFocus)
101
+ dialogRef.current?.focus({
102
+ preventScroll: true,
103
+ });
104
+ }, [dialogRef, previousFocusedElement, setFocus]);
105
+ let beforeClose = React.useCallback(() => {
106
+ if (
107
+ dialogRef.current?.contains(
108
+ dialogRef.current?.ownerDocument.activeElement,
109
+ )
110
+ )
111
+ previousFocusedElement.current?.focus();
112
+ }, [dialogRef, previousFocusedElement]);
113
+ let mountRef = React.useCallback(
114
+ (element) => {
115
+ if (element) onEnter();
116
+ },
117
+ [onEnter],
118
+ );
94
119
  let content = React.createElement(
95
120
  Box,
96
121
  {
@@ -105,7 +130,7 @@ export const DialogMain = React.forwardRef((props, ref) => {
105
130
  className,
106
131
  ),
107
132
  role: 'dialog',
108
- ref: useMergedRefs(dialogRef, ref),
133
+ ref: useMergedRefs(dialogRef, mountRef, ref),
109
134
  onKeyDown: handleKeyDown,
110
135
  tabIndex: -1,
111
136
  'data-iui-placement': placement,
@@ -123,7 +148,7 @@ export const DialogMain = React.forwardRef((props, ref) => {
123
148
  isResizable &&
124
149
  React.createElement(Resizer, {
125
150
  elementRef: dialogRef,
126
- containerRef: dialogContext.dialogRootRef,
151
+ containerRef: dialogRootRef,
127
152
  onResizeStart: () => {
128
153
  if (!hasBeenResized.current) {
129
154
  hasBeenResized.current = true;
@@ -138,31 +163,14 @@ export const DialogMain = React.forwardRef((props, ref) => {
138
163
  children,
139
164
  );
140
165
  return React.createElement(
141
- Transition,
166
+ DialogMainContext.Provider,
142
167
  {
143
- in: isOpen,
144
- appear: true,
145
- timeout: {
146
- exit: 600,
147
- },
148
- onEntered: () => {
149
- previousFocusedElement.current =
150
- dialogRef.current?.ownerDocument.activeElement;
151
- setFocus &&
152
- dialogRef.current?.focus({
153
- preventScroll: true,
154
- });
155
- },
156
- onExit: () => {
157
- if (
158
- dialogRef.current?.contains(
159
- dialogRef.current?.ownerDocument.activeElement,
160
- )
161
- )
162
- previousFocusedElement.current?.focus();
163
- },
164
- unmountOnExit: true,
165
- nodeRef: dialogRef,
168
+ value: React.useMemo(
169
+ () => ({
170
+ beforeClose,
171
+ }),
172
+ [beforeClose],
173
+ ),
166
174
  },
167
175
  React.createElement(
168
176
  DialogDragContext.Provider,
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+ type DialogMainContextProps = {
3
+ beforeClose: () => void;
4
+ };
5
+ export declare const DialogMainContext: React.Context<DialogMainContextProps | null>;
6
+ export declare const useDialogMainContext: () => DialogMainContextProps | null;
7
+ export {};
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ export const DialogMainContext = React.createContext(null);
3
+ export const useDialogMainContext = () => React.useContext(DialogMainContext);
@@ -3,11 +3,13 @@ import cx from 'classnames';
3
3
  import { SvgClose, mergeEventHandlers, Box } from '../../utils/index.js';
4
4
  import { IconButton } from '../Buttons/IconButton.js';
5
5
  import { useDialogContext } from './DialogContext.js';
6
+ import { useDialogMainContext } from './DialogMainContext.js';
6
7
  import { DialogTitleBarTitle } from './DialogTitleBarTitle.js';
7
8
  import { useDialogDragContext } from './DialogDragContext.js';
8
9
  export const DialogTitleBar = Object.assign(
9
10
  React.forwardRef((props, ref) => {
10
11
  let dialogContext = useDialogContext();
12
+ let dialogMainContext = useDialogMainContext();
11
13
  let {
12
14
  children,
13
15
  titleText,
@@ -19,6 +21,13 @@ export const DialogTitleBar = Object.assign(
19
21
  ...rest
20
22
  } = props;
21
23
  let { onPointerDown } = useDialogDragContext();
24
+ let onClick = React.useCallback(
25
+ (e) => {
26
+ dialogMainContext?.beforeClose();
27
+ onClose?.(e);
28
+ },
29
+ [dialogMainContext, onClose],
30
+ );
22
31
  return React.createElement(
23
32
  Box,
24
33
  {
@@ -41,7 +50,7 @@ export const DialogTitleBar = Object.assign(
41
50
  {
42
51
  size: 'small',
43
52
  styleType: 'borderless',
44
- onClick: onClose,
53
+ onClick: onClick,
45
54
  'aria-label': 'Close',
46
55
  'data-iui-shift': 'right',
47
56
  },
@@ -12,6 +12,7 @@ import {
12
12
  useWarningLogger,
13
13
  useLayoutEffect,
14
14
  useLatestRef,
15
+ useId,
15
16
  } from '../../utils/index.js';
16
17
  import { IconButton } from '../Buttons/IconButton.js';
17
18
  import { Flex } from '../Flex/Flex.js';
@@ -152,7 +153,7 @@ let PanelTrigger = (props) => {
152
153
  panels,
153
154
  } = useSafeContext(PanelsWrapperContext);
154
155
  let { id: panelId } = useSafeContext(PanelContext);
155
- let fallbackId = React.useId();
156
+ let fallbackId = useId();
156
157
  let triggerId = children.props.id || fallbackId;
157
158
  let onClick = React.useCallback(() => {
158
159
  if (null == activePanel) return;
@@ -25,12 +25,12 @@ type SideNavigationProps = {
25
25
  */
26
26
  onExpanderClick?: () => void;
27
27
  /**
28
- * Submenu to show supplemental info assicated to the main item.
28
+ * Submenu to show supplemental info associated to the main item.
29
29
  *
30
30
  * Should be used with the `isSubmenuOpen` props from both `SideNavigation` and `SidenavButton`.
31
31
  * @example
32
32
  * <SideNavigation
33
- * // ...
33
+ * //
34
34
  * submenu={(
35
35
  * <SidenavSubmenu>
36
36
  * <SidenavSubmenuHeader>Documents</SidenavSubmenuHeader>
@@ -1,11 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import cx from 'classnames';
3
- import {
4
- WithCSSTransition,
5
- SvgChevronRight,
6
- Box,
7
- useControlledState,
8
- } from '../../utils/index.js';
3
+ import { SvgChevronRight, Box, useControlledState } from '../../utils/index.js';
9
4
  import { IconButton } from '../Buttons/IconButton.js';
10
5
  export const SidenavExpandedContext = React.createContext(void 0);
11
6
  export const SideNavigation = React.forwardRef((props, forwardedRef) => {
@@ -94,17 +89,7 @@ export const SideNavigation = React.forwardRef((props, forwardedRef) => {
94
89
  ),
95
90
  'bottom' === expanderPlacement && ExpandButton,
96
91
  ),
97
- submenu &&
98
- React.createElement(
99
- WithCSSTransition,
100
- {
101
- in: isSubmenuOpen,
102
- dimension: 'width',
103
- timeout: 200,
104
- classNames: 'iui',
105
- },
106
- submenu,
107
- ),
92
+ submenu && isSubmenuOpen ? submenu : null,
108
93
  ),
109
94
  );
110
95
  });
@@ -7,19 +7,18 @@ let onSelectHandler = (newState, instance, onSelect, isRowDisabled) => {
7
7
  let newSelectedRowIds = {};
8
8
  let handleRow = (row) => {
9
9
  if (isRowDisabled?.(row.original)) return false;
10
+ let hasSubComponents = !!row.initialSubRows[0]?.original[iuiId];
11
+ let hasSubRows = row.subRows.length > 0 && !hasSubComponents;
10
12
  let isAllSubSelected = true;
11
- if (row.initialSubRows[0]?.original[iuiId] === void 0)
13
+ if (hasSubRows)
12
14
  row.initialSubRows.forEach((subRow) => {
13
15
  let result = handleRow(subRow);
14
16
  if (!result) isAllSubSelected = false;
15
17
  });
16
- if (
17
- newState.selectedRowIds[row.id] &&
18
- (!instance.selectSubRows ||
19
- !row.initialSubRows.length ||
20
- isAllSubSelected)
21
- )
22
- newSelectedRowIds[row.id] = true;
18
+ let isRowSelected = newState.selectedRowIds[row.id];
19
+ let case1 = isRowSelected && (!instance.selectSubRows || !hasSubRows);
20
+ let case2 = hasSubRows && isAllSubSelected;
21
+ if (case1 || case2) newSelectedRowIds[row.id] = true;
23
22
  return !!newSelectedRowIds[row.id];
24
23
  };
25
24
  instance.initialRows.forEach((row) => handleRow(row));
@@ -160,7 +160,15 @@ let Tab = React.forwardRef((props, forwardedRef) => {
160
160
  });
161
161
  };
162
162
  if ('default' !== type && isActive) updateStripe();
163
- }, [type, orientation, isActive, tabsWidth, setStripeProperties, tablistRef]);
163
+ }, [
164
+ type,
165
+ orientation,
166
+ isActive,
167
+ tabsWidth,
168
+ setStripeProperties,
169
+ tablistRef,
170
+ value,
171
+ ]);
164
172
  let onKeyDown = (event) => {
165
173
  if (event.altKey) return;
166
174
  let allTabs = Array.from(event.currentTarget.parentElement?.children ?? []);
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react';
2
- import type { ThemeOptions, ThemeType } from './ThemeProvider.js';
2
+ import type { FutureOptions, ThemeOptions, ThemeType } from './ThemeProvider.js';
3
3
  export declare const ThemeContext: React.Context<{
4
4
  theme?: ThemeType;
5
5
  themeOptions?: ThemeOptions;
6
6
  portalContainer?: HTMLElement | null;
7
+ future?: FutureOptions;
7
8
  } | undefined>;
@@ -6,14 +6,18 @@ export type ThemeOptions = {
6
6
  * Will default to user preference if browser supports it.
7
7
  */
8
8
  highContrast?: boolean;
9
+ };
10
+ export type FutureOptions = {
9
11
  /**
12
+ * @alpha
13
+ *
10
14
  * If enabled, the theme resembles the future iTwinUI version's theme (including alphas) *whenever possible*.
11
15
  *
12
16
  * This is useful in making apps looks like future versions of iTwinUI to help with incremental adoption.
13
17
  *
14
18
  * **NOTE**: Since this is a theme bridge to *future* versions, the theme could have breaking changes.
15
19
  */
16
- bridgeToFutureVersions?: boolean;
20
+ themeBridge?: boolean;
17
21
  };
18
22
  export type ThemeType = 'light' | 'dark' | 'os';
19
23
  type RootProps = {
@@ -26,13 +30,13 @@ type RootProps = {
26
30
  *
27
31
  * The 'inherit' option is intended to be used by packages, to enable incremental adoption
28
32
  * of iTwinUI while respecting the theme set by the consuming app. It will fall back to 'light'
29
- * if no parent theme is found. Additionally, it will attempt to inherit `themeOptions.highContrast`
30
- * and `portalContainer` (if possible).
33
+ * if no parent theme is found. Additionally, it will attempt to inherit `themeOptions.highContrast`,
34
+ * `portalContainer`, and `future.themeBridge` (if possible).
31
35
  *
32
36
  * @default 'inherit'
33
37
  */
34
38
  theme?: ThemeType | 'inherit';
35
- themeOptions?: Pick<ThemeOptions, 'highContrast' | 'bridgeToFutureVersions'> & {
39
+ themeOptions?: Pick<ThemeOptions, 'highContrast'> & {
36
40
  /**
37
41
  * Whether or not the element should apply the recommended `background-color` on itself.
38
42
  *
@@ -46,8 +50,12 @@ type RootProps = {
46
50
  */
47
51
  applyBackground?: boolean;
48
52
  };
53
+ /**
54
+ * Options to help with early adoption of features from future versions.
55
+ */
56
+ future?: FutureOptions;
49
57
  };
50
- type ThemeProviderOwnProps = Pick<RootProps, 'theme'> & {
58
+ type ThemeProviderOwnProps = Pick<RootProps, 'theme' | 'future'> & {
51
59
  themeOptions?: RootProps['themeOptions'];
52
60
  children: Required<React.ReactNode>;
53
61
  /**
@@ -23,13 +23,14 @@ import { meta } from '../../utils/meta.js';
23
23
  let versionWithoutDots = meta.version.replace(/\./g, '');
24
24
  let ownerDocumentAtom = atom(void 0);
25
25
  export const ThemeProvider = React.forwardRef((props, forwardedRef) => {
26
- var _themeOptions, _themeOptions1, _themeOptions2;
26
+ var _themeOptions, _themeOptions1, _future;
27
27
  let {
28
28
  theme: themeProp = 'inherit',
29
29
  children,
30
30
  themeOptions = {},
31
31
  portalContainer: portalContainerProp,
32
32
  includeCss = 'inherit' === themeProp,
33
+ future = {},
33
34
  ...rest
34
35
  } = props;
35
36
  useInertPolyfill();
@@ -41,18 +42,16 @@ export const ThemeProvider = React.forwardRef((props, forwardedRef) => {
41
42
  (_themeOptions1 = themeOptions).highContrast ??
42
43
  (_themeOptions1.highContrast =
43
44
  'inherit' === themeProp ? parent.highContrast : void 0);
44
- (_themeOptions2 = themeOptions).bridgeToFutureVersions ??
45
- (_themeOptions2.bridgeToFutureVersions =
46
- 'inherit' === themeProp
47
- ? parent.context?.themeOptions?.bridgeToFutureVersions
48
- : void 0);
45
+ (_future = future).themeBridge ??
46
+ (_future.themeBridge = parent.context?.future?.themeBridge);
49
47
  let [portalContainerFromParent] = useScopedAtom(portalContainerAtom);
50
48
  let contextValue = React.useMemo(
51
49
  () => ({
52
50
  theme,
53
51
  themeOptions,
52
+ future,
54
53
  }),
55
- [theme, JSON.stringify(themeOptions)],
54
+ [theme, JSON.stringify(themeOptions), JSON.stringify(future)],
56
55
  );
57
56
  return React.createElement(
58
57
  ScopeProvider,
@@ -80,6 +79,7 @@ export const ThemeProvider = React.forwardRef((props, forwardedRef) => {
80
79
  {
81
80
  theme: theme,
82
81
  themeOptions: themeOptions,
82
+ future: future,
83
83
  ref: useMergedRefs(forwardedRef, setRootElement, useIuiDebugRef),
84
84
  ...rest,
85
85
  },
@@ -87,6 +87,7 @@ export const ThemeProvider = React.forwardRef((props, forwardedRef) => {
87
87
  React.createElement(PortalContainer, {
88
88
  theme: theme,
89
89
  themeOptions: themeOptions,
90
+ future: future,
90
91
  portalContainerProp: portalContainerProp,
91
92
  portalContainerFromParent: portalContainerFromParent,
92
93
  isInheritingTheme: 'inherit' === themeProp,
@@ -112,7 +113,7 @@ let MainRoot = React.forwardRef((props, forwardedRef) => {
112
113
  });
113
114
  });
114
115
  let Root = React.forwardRef((props, forwardedRef) => {
115
- let { theme, children, themeOptions, className, ...rest } = props;
116
+ let { theme, children, themeOptions, className, future, ...rest } = props;
116
117
  let prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
117
118
  let prefersHighContrast = useMediaQuery('(prefers-contrast: more)');
118
119
  let shouldApplyDark = 'dark' === theme || ('os' === theme && prefersDark);
@@ -130,7 +131,7 @@ let Root = React.forwardRef((props, forwardedRef) => {
130
131
  ),
131
132
  'data-iui-theme': shouldApplyDark ? 'dark' : 'light',
132
133
  'data-iui-contrast': shouldApplyHC ? 'high' : 'default',
133
- 'data-iui-bridge': !!themeOptions?.bridgeToFutureVersions || void 0,
134
+ 'data-iui-bridge': !!future?.themeBridge || void 0,
134
135
  ref: forwardedRef,
135
136
  ...rest,
136
137
  },
@@ -178,6 +179,7 @@ let PortalContainer = React.memo(
178
179
  isInheritingTheme,
179
180
  theme,
180
181
  themeOptions,
182
+ future,
181
183
  }) => {
182
184
  let [ownerDocument] = useScopedAtom(ownerDocumentAtom);
183
185
  let [portalContainer, setPortalContainer] =
@@ -207,6 +209,7 @@ let PortalContainer = React.memo(
207
209
  ...themeOptions,
208
210
  applyBackground: false,
209
211
  },
212
+ future: future,
210
213
  'data-iui-portal': true,
211
214
  style: {
212
215
  display: 'contents',
@@ -66,7 +66,7 @@ export type ToastProps = {
66
66
  * <Toast type='temporary' content='26 files are available for synchronization.' category='informational' />
67
67
  * <Toast type='persisting' content='Job processing error.' category='negative' />
68
68
  */
69
- export declare const Toast: (props: ToastProps) => React.JSX.Element;
69
+ export declare const Toast: (props: ToastProps) => React.JSX.Element | null;
70
70
  export type ToastPresentationProps = Omit<ToastProps, 'duration' | 'id' | 'isVisible' | 'onRemove' | 'domProps'> & {
71
71
  onClose?: () => void;
72
72
  contentProps?: React.ComponentProps<'div'>;