@itwin/itwinui-react 3.17.0-dev.1 → 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 (82) hide show
  1. package/CHANGELOG.md +21 -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 +1 -2
  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 +1 -2
  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/ThemeProvider.d.ts +2 -0
  45. package/cjs/core/ThemeProvider/ThemeProvider.js +1 -2
  46. package/cjs/core/Toast/Toast.d.ts +1 -1
  47. package/cjs/core/Toast/Toast.js +132 -77
  48. package/cjs/core/Toast/Toaster.d.ts +1 -1
  49. package/cjs/core/Toast/Toaster.js +11 -3
  50. package/cjs/styles.js +1 -1
  51. package/cjs/utils/components/index.d.ts +0 -1
  52. package/cjs/utils/components/index.js +0 -1
  53. package/esm/core/Dialog/Dialog.d.ts +1 -1
  54. package/esm/core/Dialog/Dialog.js +32 -42
  55. package/esm/core/Dialog/DialogBackdrop.d.ts +1 -1
  56. package/esm/core/Dialog/DialogBackdrop.js +6 -1
  57. package/esm/core/Dialog/DialogMain.js +42 -34
  58. package/esm/core/Dialog/DialogMainContext.d.ts +7 -0
  59. package/esm/core/Dialog/DialogMainContext.js +3 -0
  60. package/esm/core/Dialog/DialogTitleBar.js +10 -1
  61. package/esm/core/Panels/Panels.js +2 -1
  62. package/esm/core/SideNavigation/SideNavigation.d.ts +2 -2
  63. package/esm/core/SideNavigation/SideNavigation.js +2 -17
  64. package/esm/core/Table/actionHandlers/selectHandler.js +7 -8
  65. package/esm/core/Tabs/Tabs.js +9 -1
  66. package/esm/core/ThemeProvider/ThemeProvider.d.ts +2 -0
  67. package/esm/core/ThemeProvider/ThemeProvider.js +1 -2
  68. package/esm/core/Toast/Toast.d.ts +1 -1
  69. package/esm/core/Toast/Toast.js +131 -75
  70. package/esm/core/Toast/Toaster.d.ts +1 -1
  71. package/esm/core/Toast/Toaster.js +11 -3
  72. package/esm/styles.js +1 -1
  73. package/esm/utils/components/index.d.ts +0 -1
  74. package/esm/utils/components/index.js +0 -1
  75. package/package.json +3 -5
  76. package/styles.css +10 -10
  77. package/DEV-cjs/utils/components/WithCSSTransition.js +0 -60
  78. package/DEV-esm/utils/components/WithCSSTransition.js +0 -49
  79. package/cjs/utils/components/WithCSSTransition.d.ts +0 -6
  80. package/cjs/utils/components/WithCSSTransition.js +0 -60
  81. package/esm/utils/components/WithCSSTransition.d.ts +0 -6
  82. package/esm/utils/components/WithCSSTransition.js +0 -49
@@ -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 ?? []);
@@ -9,6 +9,8 @@ export type ThemeOptions = {
9
9
  };
10
10
  export type FutureOptions = {
11
11
  /**
12
+ * @alpha
13
+ *
12
14
  * If enabled, the theme resembles the future iTwinUI version's theme (including alphas) *whenever possible*.
13
15
  *
14
16
  * This is useful in making apps looks like future versions of iTwinUI to help with incremental adoption.
@@ -43,8 +43,7 @@ export const ThemeProvider = React.forwardRef((props, forwardedRef) => {
43
43
  (_themeOptions1.highContrast =
44
44
  'inherit' === themeProp ? parent.highContrast : void 0);
45
45
  (_future = future).themeBridge ??
46
- (_future.themeBridge =
47
- 'inherit' === themeProp ? parent.context?.future?.themeBridge : void 0);
46
+ (_future.themeBridge = parent.context?.future?.themeBridge);
48
47
  let [portalContainerFromParent] = useScopedAtom(portalContainerAtom);
49
48
  let contextValue = React.useMemo(
50
49
  () => ({
@@ -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'>;
@@ -1,5 +1,4 @@
1
1
  import * as React from 'react';
2
- import { Transition } from 'react-transition-group';
3
2
  import cx from 'classnames';
4
3
  import {
5
4
  getWindow,
@@ -9,6 +8,7 @@ import {
9
8
  useSafeContext,
10
9
  ButtonBase,
11
10
  useMediaQuery,
11
+ useLatestRef,
12
12
  } from '../../utils/index.js';
13
13
  import { IconButton } from '../Buttons/IconButton.js';
14
14
  import { ToasterStateContext } from './Toaster.js';
@@ -33,7 +33,6 @@ export const Toast = (props) => {
33
33
  let [height, setHeight] = React.useState(0);
34
34
  let thisElement = React.useRef(null);
35
35
  let [margin, setMargin] = React.useState(0);
36
- let motionOk = useMediaQuery('(prefers-reduced-motion: no-preference)');
37
36
  let marginStyle = () => {
38
37
  if ('top' === placementPosition)
39
38
  return {
@@ -73,81 +72,41 @@ export const Toast = (props) => {
73
72
  setHeight(height);
74
73
  }
75
74
  };
76
- let calculateOutAnimation = (node) => {
77
- let translateX = 0;
78
- let translateY = 0;
79
- if (animateOutTo && node) {
80
- let { x: startX, y: startY } = node.getBoundingClientRect();
81
- let { x: endX, y: endY } = animateOutTo.getBoundingClientRect();
82
- translateX = endX - startX;
83
- translateY = endY - startY;
84
- }
85
- return {
86
- translateX,
87
- translateY,
88
- };
89
- };
90
- return React.createElement(
91
- Transition,
92
- {
93
- timeout: {
94
- enter: 240,
95
- exit: animateOutTo ? 400 : 120,
96
- },
97
- in: isVisible,
98
- appear: true,
99
- unmountOnExit: true,
100
- onEnter: (node) => {
101
- if (motionOk) {
102
- node.style.transform = 'translateY(15%)';
103
- node.style.transitionTimingFunction = 'ease';
104
- }
105
- },
106
- onEntered: (node) => {
107
- if (motionOk) node.style.transform = 'translateY(0)';
108
- },
109
- onExiting: (node) => {
110
- if (motionOk) {
111
- let { translateX, translateY } = calculateOutAnimation(node);
112
- node.style.transform = animateOutTo
113
- ? `scale(0.9) translate(${translateX}px,${translateY}px)`
114
- : 'scale(0.9)';
115
- node.style.opacity = '0';
116
- node.style.transitionDuration = animateOutTo ? '400ms' : '120ms';
117
- node.style.transitionTimingFunction = 'cubic-bezier(0.4, 0, 1, 1)';
118
- }
119
- },
120
- onExited: onRemove,
121
- },
122
- React.createElement(
123
- Box,
124
- {
125
- ref: thisElement,
126
- className: 'iui-toast-all',
127
- style: {
128
- height,
129
- ...marginStyle(),
130
- },
131
- },
132
- React.createElement(
133
- 'div',
75
+ let shouldBeMounted = useAnimateToastBasedOnVisibility(isVisible, {
76
+ thisElement,
77
+ animateOutTo,
78
+ onRemove,
79
+ });
80
+ return shouldBeMounted
81
+ ? React.createElement(
82
+ Box,
134
83
  {
135
- ref: onRef,
84
+ ref: thisElement,
85
+ className: 'iui-toast-all',
86
+ style: {
87
+ height,
88
+ ...marginStyle(),
89
+ },
136
90
  },
137
- React.createElement(ToastPresentation, {
138
- as: 'div',
139
- category: category,
140
- content: content,
141
- link: link,
142
- type: type,
143
- hasCloseButton: hasCloseButton,
144
- onClose: close,
145
- ...domProps?.toastProps,
146
- contentProps: domProps?.contentProps,
147
- }),
148
- ),
149
- ),
150
- );
91
+ React.createElement(
92
+ 'div',
93
+ {
94
+ ref: onRef,
95
+ },
96
+ React.createElement(ToastPresentation, {
97
+ as: 'div',
98
+ category: category,
99
+ content: content,
100
+ link: link,
101
+ type: type,
102
+ hasCloseButton: hasCloseButton,
103
+ onClose: close,
104
+ ...domProps?.toastProps,
105
+ contentProps: domProps?.contentProps,
106
+ }),
107
+ ),
108
+ )
109
+ : null;
151
110
  };
152
111
  export const ToastPresentation = React.forwardRef((props, forwardedRef) => {
153
112
  let {
@@ -212,3 +171,100 @@ export const ToastPresentation = React.forwardRef((props, forwardedRef) => {
212
171
  ),
213
172
  );
214
173
  });
174
+ let useAnimateToastBasedOnVisibility = (isVisible, args) => {
175
+ let { thisElement, animateOutTo, onRemove } = args;
176
+ let [shouldBeMounted, setShouldBeMounted] = React.useState(isVisible);
177
+ let motionOk = useMediaQuery('(prefers-reduced-motion: no-preference)');
178
+ let onRemoveRef = useLatestRef(onRemove);
179
+ let [prevIsVisible, setPrevIsVisible] = React.useState(void 0);
180
+ React.useEffect(() => {
181
+ if (prevIsVisible !== isVisible) {
182
+ setPrevIsVisible(isVisible);
183
+ if (isVisible) safeAnimateIn();
184
+ else safeAnimateOut();
185
+ }
186
+ function calculateOutAnimation(node) {
187
+ let translateX = 0;
188
+ let translateY = 0;
189
+ if (animateOutTo && node) {
190
+ let { x: startX, y: startY } = node.getBoundingClientRect();
191
+ let { x: endX, y: endY } = animateOutTo.getBoundingClientRect();
192
+ translateX = endX - startX;
193
+ translateY = endY - startY;
194
+ }
195
+ return {
196
+ translateX,
197
+ translateY,
198
+ };
199
+ }
200
+ function safeAnimateIn() {
201
+ setShouldBeMounted(true);
202
+ queueMicrotask(() => {
203
+ animateIn();
204
+ });
205
+ }
206
+ function safeAnimateOut() {
207
+ if (motionOk) {
208
+ let animation = animateOut();
209
+ animation?.addEventListener('finish', () => {
210
+ setShouldBeMounted(false);
211
+ onRemoveRef.current?.();
212
+ });
213
+ } else {
214
+ setShouldBeMounted(false);
215
+ onRemoveRef.current?.();
216
+ }
217
+ }
218
+ function animateIn() {
219
+ if (!motionOk) return;
220
+ thisElement.current?.animate?.(
221
+ [
222
+ {
223
+ transform: 'translateY(15%)',
224
+ },
225
+ {
226
+ transform: 'translateY(0)',
227
+ },
228
+ ],
229
+ {
230
+ duration: 240,
231
+ fill: 'forwards',
232
+ },
233
+ );
234
+ }
235
+ function animateOut() {
236
+ if (null == thisElement.current || !motionOk) return;
237
+ let { translateX, translateY } = calculateOutAnimation(
238
+ thisElement.current,
239
+ );
240
+ let animationDuration = animateOutTo ? 400 : 120;
241
+ let animation = thisElement.current?.animate?.(
242
+ [
243
+ {
244
+ transform: animateOutTo
245
+ ? `scale(0.9) translate(${translateX}px,${translateY}px)`
246
+ : 'scale(0.9)',
247
+ opacity: 0,
248
+ transitionDuration: `${animationDuration}ms`,
249
+ transitionTimingFunction: 'cubic-bezier(0.4, 0, 1, 1)',
250
+ },
251
+ ],
252
+ {
253
+ duration: animationDuration,
254
+ iterations: 1,
255
+ fill: 'forwards',
256
+ },
257
+ );
258
+ return animation;
259
+ }
260
+ }, [
261
+ isVisible,
262
+ prevIsVisible,
263
+ animateOutTo,
264
+ motionOk,
265
+ thisElement,
266
+ setShouldBeMounted,
267
+ onRemoveRef,
268
+ ]);
269
+ return shouldBeMounted;
270
+ };
@@ -38,7 +38,7 @@ export declare const Toaster: () => React.JSX.Element;
38
38
  export declare const ToastProvider: ({ children, inherit, }: {
39
39
  children: React.ReactNode;
40
40
  inherit?: boolean;
41
- }) => string | number | boolean | Iterable<React.ReactNode> | React.JSX.Element | null | undefined;
41
+ }) => React.JSX.Element;
42
42
  export declare const ToasterStateContext: React.Context<ToasterState | undefined>;
43
43
  type ToasterState = {
44
44
  toasts: ToastProps[];
@@ -66,16 +66,24 @@ export const ToastProvider = ({ children, inherit = false }) => {
66
66
  placement: 'top',
67
67
  },
68
68
  });
69
- if (React.useContext(ToasterStateContext) && inherit) return children;
69
+ let toasterDispatchContext = React.useContext(ToasterDispatchContext);
70
+ let toasterStateContext = React.useContext(ToasterStateContext);
71
+ let shouldReuse = toasterStateContext && inherit;
72
+ let toasterDispatchContextValue = shouldReuse
73
+ ? toasterDispatchContext
74
+ : dispatch;
75
+ let toasterStateContextValue = shouldReuse
76
+ ? toasterStateContext
77
+ : toasterState;
70
78
  return React.createElement(
71
79
  ToasterDispatchContext.Provider,
72
80
  {
73
- value: dispatch,
81
+ value: toasterDispatchContextValue,
74
82
  },
75
83
  React.createElement(
76
84
  ToasterStateContext.Provider,
77
85
  {
78
- value: toasterState,
86
+ value: toasterStateContextValue,
79
87
  },
80
88
  children,
81
89
  ),
package/esm/styles.js CHANGED
@@ -1,4 +1,4 @@
1
- const t = '3.17.0-dev.1';
1
+ const t = '3.17.0-dev.2';
2
2
  const u = new Proxy(
3
3
  {},
4
4
  {
@@ -3,7 +3,6 @@ export * from './FocusTrap.js';
3
3
  export * from './InputContainer.js';
4
4
  export * from './InputFlexContainer.js';
5
5
  export * from './InputWithIcon.js';
6
- export * from './WithCSSTransition.js';
7
6
  export * from './MiddleTextTruncation.js';
8
7
  export * from './AutoclearingHiddenLiveRegion.js';
9
8
  export * from './Box.js';
@@ -3,7 +3,6 @@ export * from './FocusTrap.js';
3
3
  export * from './InputContainer.js';
4
4
  export * from './InputFlexContainer.js';
5
5
  export * from './InputWithIcon.js';
6
- export * from './WithCSSTransition.js';
7
6
  export * from './MiddleTextTruncation.js';
8
7
  export * from './AutoclearingHiddenLiveRegion.js';
9
8
  export * from './Box.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "3.17.0-dev.1",
3
+ "version": "3.17.0-dev.2",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -109,8 +109,7 @@
109
109
  "@tanstack/react-virtual": "^3.8.2",
110
110
  "classnames": "^2.3.2",
111
111
  "jotai": "^2.8.0",
112
- "react-table": "^7.8.0",
113
- "react-transition-group": "^4.4.5"
112
+ "react-table": "^7.8.0"
114
113
  },
115
114
  "devDependencies": {
116
115
  "@swc/cli": "^0.5.1",
@@ -121,7 +120,6 @@
121
120
  "@types/node": "*",
122
121
  "@types/react": "*",
123
122
  "@types/react-dom": "*",
124
- "@types/react-transition-group": "^4.4.10",
125
123
  "@vitest/coverage-v8": "^1.2.1",
126
124
  "eslint": "^8",
127
125
  "eslint-config-prettier": "^8.8.0",
@@ -130,7 +128,7 @@
130
128
  "react": "^18.0.0",
131
129
  "react-dom": "^18.0.0",
132
130
  "typescript": "5",
133
- "vite": "~5.1.8",
131
+ "vite": "~5.4.14",
134
132
  "vitest": "^1.2.1"
135
133
  },
136
134
  "peerDependencies": {