@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.
- package/CHANGELOG.md +21 -0
- package/DEV-cjs/core/Dialog/Dialog.js +35 -42
- package/DEV-cjs/core/Dialog/DialogBackdrop.js +6 -1
- package/DEV-cjs/core/Dialog/DialogMain.js +42 -34
- package/DEV-cjs/core/Dialog/DialogMainContext.js +23 -0
- package/DEV-cjs/core/Dialog/DialogTitleBar.js +10 -1
- package/DEV-cjs/core/Panels/Panels.js +1 -1
- package/DEV-cjs/core/SideNavigation/SideNavigation.js +1 -11
- package/DEV-cjs/core/Table/actionHandlers/selectHandler.js +7 -8
- package/DEV-cjs/core/Tabs/Tabs.js +9 -1
- package/DEV-cjs/core/ThemeProvider/ThemeProvider.js +1 -2
- package/DEV-cjs/core/Toast/Toast.js +132 -77
- package/DEV-cjs/core/Toast/Toaster.js +11 -3
- package/DEV-cjs/styles.js +1 -1
- package/DEV-cjs/utils/components/index.js +0 -1
- package/DEV-esm/core/Dialog/Dialog.js +32 -42
- package/DEV-esm/core/Dialog/DialogBackdrop.js +6 -1
- package/DEV-esm/core/Dialog/DialogMain.js +42 -34
- package/DEV-esm/core/Dialog/DialogMainContext.js +3 -0
- package/DEV-esm/core/Dialog/DialogTitleBar.js +10 -1
- package/DEV-esm/core/Panels/Panels.js +2 -1
- package/DEV-esm/core/SideNavigation/SideNavigation.js +2 -17
- package/DEV-esm/core/Table/actionHandlers/selectHandler.js +7 -8
- package/DEV-esm/core/Tabs/Tabs.js +9 -1
- package/DEV-esm/core/ThemeProvider/ThemeProvider.js +1 -2
- package/DEV-esm/core/Toast/Toast.js +131 -75
- package/DEV-esm/core/Toast/Toaster.js +11 -3
- package/DEV-esm/styles.js +1 -1
- package/DEV-esm/utils/components/index.js +0 -1
- package/LICENSE.md +1 -1
- package/cjs/core/Dialog/Dialog.d.ts +1 -1
- package/cjs/core/Dialog/Dialog.js +35 -42
- package/cjs/core/Dialog/DialogBackdrop.d.ts +1 -1
- package/cjs/core/Dialog/DialogBackdrop.js +6 -1
- package/cjs/core/Dialog/DialogMain.js +42 -34
- package/cjs/core/Dialog/DialogMainContext.d.ts +7 -0
- package/cjs/core/Dialog/DialogMainContext.js +23 -0
- package/cjs/core/Dialog/DialogTitleBar.js +10 -1
- package/cjs/core/Panels/Panels.js +1 -1
- package/cjs/core/SideNavigation/SideNavigation.d.ts +2 -2
- package/cjs/core/SideNavigation/SideNavigation.js +1 -11
- package/cjs/core/Table/actionHandlers/selectHandler.js +7 -8
- package/cjs/core/Tabs/Tabs.js +9 -1
- package/cjs/core/ThemeProvider/ThemeProvider.d.ts +2 -0
- package/cjs/core/ThemeProvider/ThemeProvider.js +1 -2
- package/cjs/core/Toast/Toast.d.ts +1 -1
- package/cjs/core/Toast/Toast.js +132 -77
- package/cjs/core/Toast/Toaster.d.ts +1 -1
- package/cjs/core/Toast/Toaster.js +11 -3
- package/cjs/styles.js +1 -1
- package/cjs/utils/components/index.d.ts +0 -1
- package/cjs/utils/components/index.js +0 -1
- package/esm/core/Dialog/Dialog.d.ts +1 -1
- package/esm/core/Dialog/Dialog.js +32 -42
- package/esm/core/Dialog/DialogBackdrop.d.ts +1 -1
- package/esm/core/Dialog/DialogBackdrop.js +6 -1
- package/esm/core/Dialog/DialogMain.js +42 -34
- package/esm/core/Dialog/DialogMainContext.d.ts +7 -0
- package/esm/core/Dialog/DialogMainContext.js +3 -0
- package/esm/core/Dialog/DialogTitleBar.js +10 -1
- package/esm/core/Panels/Panels.js +2 -1
- package/esm/core/SideNavigation/SideNavigation.d.ts +2 -2
- package/esm/core/SideNavigation/SideNavigation.js +2 -17
- package/esm/core/Table/actionHandlers/selectHandler.js +7 -8
- package/esm/core/Tabs/Tabs.js +9 -1
- package/esm/core/ThemeProvider/ThemeProvider.d.ts +2 -0
- package/esm/core/ThemeProvider/ThemeProvider.js +1 -2
- package/esm/core/Toast/Toast.d.ts +1 -1
- package/esm/core/Toast/Toast.js +131 -75
- package/esm/core/Toast/Toaster.d.ts +1 -1
- package/esm/core/Toast/Toaster.js +11 -3
- package/esm/styles.js +1 -1
- package/esm/utils/components/index.d.ts +0 -1
- package/esm/utils/components/index.js +0 -1
- package/package.json +3 -5
- package/styles.css +10 -10
- package/DEV-cjs/utils/components/WithCSSTransition.js +0 -60
- package/DEV-esm/utils/components/WithCSSTransition.js +0 -49
- package/cjs/utils/components/WithCSSTransition.d.ts +0 -6
- package/cjs/utils/components/WithCSSTransition.js +0 -60
- package/esm/utils/components/WithCSSTransition.d.ts +0 -6
- package/esm/utils/components/WithCSSTransition.js +0 -49
package/cjs/core/Toast/Toast.js
CHANGED
|
@@ -20,7 +20,6 @@ _export(exports, {
|
|
|
20
20
|
const _interop_require_default = require('@swc/helpers/_/_interop_require_default');
|
|
21
21
|
const _interop_require_wildcard = require('@swc/helpers/_/_interop_require_wildcard');
|
|
22
22
|
const _react = _interop_require_wildcard._(require('react'));
|
|
23
|
-
const _reacttransitiongroup = require('react-transition-group');
|
|
24
23
|
const _classnames = _interop_require_default._(require('classnames'));
|
|
25
24
|
const _index = require('../../utils/index.js');
|
|
26
25
|
const _IconButton = require('../Buttons/IconButton.js');
|
|
@@ -48,9 +47,6 @@ const Toast = (props) => {
|
|
|
48
47
|
let [height, setHeight] = _react.useState(0);
|
|
49
48
|
let thisElement = _react.useRef(null);
|
|
50
49
|
let [margin, setMargin] = _react.useState(0);
|
|
51
|
-
let motionOk = (0, _index.useMediaQuery)(
|
|
52
|
-
'(prefers-reduced-motion: no-preference)',
|
|
53
|
-
);
|
|
54
50
|
let marginStyle = () => {
|
|
55
51
|
if ('top' === placementPosition)
|
|
56
52
|
return {
|
|
@@ -90,81 +86,41 @@ const Toast = (props) => {
|
|
|
90
86
|
setHeight(height);
|
|
91
87
|
}
|
|
92
88
|
};
|
|
93
|
-
let
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
translateX,
|
|
104
|
-
translateY,
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
return _react.createElement(
|
|
108
|
-
_reacttransitiongroup.Transition,
|
|
109
|
-
{
|
|
110
|
-
timeout: {
|
|
111
|
-
enter: 240,
|
|
112
|
-
exit: animateOutTo ? 400 : 120,
|
|
113
|
-
},
|
|
114
|
-
in: isVisible,
|
|
115
|
-
appear: true,
|
|
116
|
-
unmountOnExit: true,
|
|
117
|
-
onEnter: (node) => {
|
|
118
|
-
if (motionOk) {
|
|
119
|
-
node.style.transform = 'translateY(15%)';
|
|
120
|
-
node.style.transitionTimingFunction = 'ease';
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
onEntered: (node) => {
|
|
124
|
-
if (motionOk) node.style.transform = 'translateY(0)';
|
|
125
|
-
},
|
|
126
|
-
onExiting: (node) => {
|
|
127
|
-
if (motionOk) {
|
|
128
|
-
let { translateX, translateY } = calculateOutAnimation(node);
|
|
129
|
-
node.style.transform = animateOutTo
|
|
130
|
-
? `scale(0.9) translate(${translateX}px,${translateY}px)`
|
|
131
|
-
: 'scale(0.9)';
|
|
132
|
-
node.style.opacity = '0';
|
|
133
|
-
node.style.transitionDuration = animateOutTo ? '400ms' : '120ms';
|
|
134
|
-
node.style.transitionTimingFunction = 'cubic-bezier(0.4, 0, 1, 1)';
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
onExited: onRemove,
|
|
138
|
-
},
|
|
139
|
-
_react.createElement(
|
|
140
|
-
_index.Box,
|
|
141
|
-
{
|
|
142
|
-
ref: thisElement,
|
|
143
|
-
className: 'iui-toast-all',
|
|
144
|
-
style: {
|
|
145
|
-
height,
|
|
146
|
-
...marginStyle(),
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
_react.createElement(
|
|
150
|
-
'div',
|
|
89
|
+
let shouldBeMounted = useAnimateToastBasedOnVisibility(isVisible, {
|
|
90
|
+
thisElement,
|
|
91
|
+
animateOutTo,
|
|
92
|
+
onRemove,
|
|
93
|
+
});
|
|
94
|
+
return shouldBeMounted
|
|
95
|
+
? _react.createElement(
|
|
96
|
+
_index.Box,
|
|
151
97
|
{
|
|
152
|
-
ref:
|
|
98
|
+
ref: thisElement,
|
|
99
|
+
className: 'iui-toast-all',
|
|
100
|
+
style: {
|
|
101
|
+
height,
|
|
102
|
+
...marginStyle(),
|
|
103
|
+
},
|
|
153
104
|
},
|
|
154
|
-
_react.createElement(
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
105
|
+
_react.createElement(
|
|
106
|
+
'div',
|
|
107
|
+
{
|
|
108
|
+
ref: onRef,
|
|
109
|
+
},
|
|
110
|
+
_react.createElement(ToastPresentation, {
|
|
111
|
+
as: 'div',
|
|
112
|
+
category: category,
|
|
113
|
+
content: content,
|
|
114
|
+
link: link,
|
|
115
|
+
type: type,
|
|
116
|
+
hasCloseButton: hasCloseButton,
|
|
117
|
+
onClose: close,
|
|
118
|
+
...domProps?.toastProps,
|
|
119
|
+
contentProps: domProps?.contentProps,
|
|
120
|
+
}),
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
: null;
|
|
168
124
|
};
|
|
169
125
|
const ToastPresentation = _react.forwardRef((props, forwardedRef) => {
|
|
170
126
|
let {
|
|
@@ -239,3 +195,102 @@ const ToastPresentation = _react.forwardRef((props, forwardedRef) => {
|
|
|
239
195
|
),
|
|
240
196
|
);
|
|
241
197
|
});
|
|
198
|
+
const useAnimateToastBasedOnVisibility = (isVisible, args) => {
|
|
199
|
+
let { thisElement, animateOutTo, onRemove } = args;
|
|
200
|
+
let [shouldBeMounted, setShouldBeMounted] = _react.useState(isVisible);
|
|
201
|
+
let motionOk = (0, _index.useMediaQuery)(
|
|
202
|
+
'(prefers-reduced-motion: no-preference)',
|
|
203
|
+
);
|
|
204
|
+
let onRemoveRef = (0, _index.useLatestRef)(onRemove);
|
|
205
|
+
let [prevIsVisible, setPrevIsVisible] = _react.useState(void 0);
|
|
206
|
+
_react.useEffect(() => {
|
|
207
|
+
if (prevIsVisible !== isVisible) {
|
|
208
|
+
setPrevIsVisible(isVisible);
|
|
209
|
+
if (isVisible) safeAnimateIn();
|
|
210
|
+
else safeAnimateOut();
|
|
211
|
+
}
|
|
212
|
+
function calculateOutAnimation(node) {
|
|
213
|
+
let translateX = 0;
|
|
214
|
+
let translateY = 0;
|
|
215
|
+
if (animateOutTo && node) {
|
|
216
|
+
let { x: startX, y: startY } = node.getBoundingClientRect();
|
|
217
|
+
let { x: endX, y: endY } = animateOutTo.getBoundingClientRect();
|
|
218
|
+
translateX = endX - startX;
|
|
219
|
+
translateY = endY - startY;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
translateX,
|
|
223
|
+
translateY,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function safeAnimateIn() {
|
|
227
|
+
setShouldBeMounted(true);
|
|
228
|
+
queueMicrotask(() => {
|
|
229
|
+
animateIn();
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function safeAnimateOut() {
|
|
233
|
+
if (motionOk) {
|
|
234
|
+
let animation = animateOut();
|
|
235
|
+
animation?.addEventListener('finish', () => {
|
|
236
|
+
setShouldBeMounted(false);
|
|
237
|
+
onRemoveRef.current?.();
|
|
238
|
+
});
|
|
239
|
+
} else {
|
|
240
|
+
setShouldBeMounted(false);
|
|
241
|
+
onRemoveRef.current?.();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function animateIn() {
|
|
245
|
+
if (!motionOk) return;
|
|
246
|
+
thisElement.current?.animate?.(
|
|
247
|
+
[
|
|
248
|
+
{
|
|
249
|
+
transform: 'translateY(15%)',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
transform: 'translateY(0)',
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
{
|
|
256
|
+
duration: 240,
|
|
257
|
+
fill: 'forwards',
|
|
258
|
+
},
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
function animateOut() {
|
|
262
|
+
if (null == thisElement.current || !motionOk) return;
|
|
263
|
+
let { translateX, translateY } = calculateOutAnimation(
|
|
264
|
+
thisElement.current,
|
|
265
|
+
);
|
|
266
|
+
let animationDuration = animateOutTo ? 400 : 120;
|
|
267
|
+
let animation = thisElement.current?.animate?.(
|
|
268
|
+
[
|
|
269
|
+
{
|
|
270
|
+
transform: animateOutTo
|
|
271
|
+
? `scale(0.9) translate(${translateX}px,${translateY}px)`
|
|
272
|
+
: 'scale(0.9)',
|
|
273
|
+
opacity: 0,
|
|
274
|
+
transitionDuration: `${animationDuration}ms`,
|
|
275
|
+
transitionTimingFunction: 'cubic-bezier(0.4, 0, 1, 1)',
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
{
|
|
279
|
+
duration: animationDuration,
|
|
280
|
+
iterations: 1,
|
|
281
|
+
fill: 'forwards',
|
|
282
|
+
},
|
|
283
|
+
);
|
|
284
|
+
return animation;
|
|
285
|
+
}
|
|
286
|
+
}, [
|
|
287
|
+
isVisible,
|
|
288
|
+
prevIsVisible,
|
|
289
|
+
animateOutTo,
|
|
290
|
+
motionOk,
|
|
291
|
+
thisElement,
|
|
292
|
+
setShouldBeMounted,
|
|
293
|
+
onRemoveRef,
|
|
294
|
+
]);
|
|
295
|
+
return shouldBeMounted;
|
|
296
|
+
};
|
|
@@ -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
|
-
}) =>
|
|
41
|
+
}) => React.JSX.Element;
|
|
42
42
|
export declare const ToasterStateContext: React.Context<ToasterState | undefined>;
|
|
43
43
|
type ToasterState = {
|
|
44
44
|
toasts: ToastProps[];
|
|
@@ -96,16 +96,24 @@ const ToastProvider = ({ children, inherit = false }) => {
|
|
|
96
96
|
placement: 'top',
|
|
97
97
|
},
|
|
98
98
|
});
|
|
99
|
-
|
|
99
|
+
let toasterDispatchContext = _react.useContext(ToasterDispatchContext);
|
|
100
|
+
let toasterStateContext = _react.useContext(ToasterStateContext);
|
|
101
|
+
let shouldReuse = toasterStateContext && inherit;
|
|
102
|
+
let toasterDispatchContextValue = shouldReuse
|
|
103
|
+
? toasterDispatchContext
|
|
104
|
+
: dispatch;
|
|
105
|
+
let toasterStateContextValue = shouldReuse
|
|
106
|
+
? toasterStateContext
|
|
107
|
+
: toasterState;
|
|
100
108
|
return _react.createElement(
|
|
101
109
|
ToasterDispatchContext.Provider,
|
|
102
110
|
{
|
|
103
|
-
value:
|
|
111
|
+
value: toasterDispatchContextValue,
|
|
104
112
|
},
|
|
105
113
|
_react.createElement(
|
|
106
114
|
ToasterStateContext.Provider,
|
|
107
115
|
{
|
|
108
|
-
value:
|
|
116
|
+
value: toasterStateContextValue,
|
|
109
117
|
},
|
|
110
118
|
children,
|
|
111
119
|
),
|
package/cjs/styles.js
CHANGED
|
@@ -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';
|
|
@@ -8,7 +8,6 @@ _export_star._(require('./FocusTrap.js'), exports);
|
|
|
8
8
|
_export_star._(require('./InputContainer.js'), exports);
|
|
9
9
|
_export_star._(require('./InputFlexContainer.js'), exports);
|
|
10
10
|
_export_star._(require('./InputWithIcon.js'), exports);
|
|
11
|
-
_export_star._(require('./WithCSSTransition.js'), exports);
|
|
12
11
|
_export_star._(require('./MiddleTextTruncation.js'), exports);
|
|
13
12
|
_export_star._(require('./AutoclearingHiddenLiveRegion.js'), exports);
|
|
14
13
|
_export_star._(require('./Box.js'), exports);
|
|
@@ -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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
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(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
|
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)
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
166
|
+
DialogMainContext.Provider,
|
|
142
167
|
{
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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 {};
|
|
@@ -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:
|
|
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 =
|
|
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
|
|
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>
|