@flipdish/ui-library 0.44.0 → 0.45.1
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/dist/components/organisms/SidePanel/components/SidePanelRegion.cjs +8 -0
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.cjs.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.d.ts.map +1 -1
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.js +8 -0
- package/dist/components/organisms/SidePanel/components/SidePanelRegion.js.map +1 -1
- package/dist/components/organisms/SlideoutMenu/components/SlideoutShell.cjs +27 -60
- package/dist/components/organisms/SlideoutMenu/components/SlideoutShell.cjs.map +1 -1
- package/dist/components/organisms/SlideoutMenu/components/SlideoutShell.d.ts +2 -3
- package/dist/components/organisms/SlideoutMenu/components/SlideoutShell.d.ts.map +1 -1
- package/dist/components/organisms/SlideoutMenu/components/SlideoutShell.js +27 -60
- package/dist/components/organisms/SlideoutMenu/components/SlideoutShell.js.map +1 -1
- package/dist/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.cjs +31 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.cjs.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.d.ts +15 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.d.ts.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.js +29 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.js.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useDialogFocusSettle.cjs +41 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useDialogFocusSettle.cjs.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useDialogFocusSettle.d.ts +19 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useDialogFocusSettle.d.ts.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useDialogFocusSettle.js +39 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useDialogFocusSettle.js.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/usePageEscapeDismiss.cjs +36 -0
- package/dist/components/organisms/SlideoutMenu/hooks/usePageEscapeDismiss.cjs.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/usePageEscapeDismiss.d.ts +21 -0
- package/dist/components/organisms/SlideoutMenu/hooks/usePageEscapeDismiss.d.ts.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/usePageEscapeDismiss.js +34 -0
- package/dist/components/organisms/SlideoutMenu/hooks/usePageEscapeDismiss.js.map +1 -0
- package/dist/components/organisms/SlideoutMenu/hooks/useSlideoutState.cjs +3 -2
- package/dist/components/organisms/SlideoutMenu/hooks/useSlideoutState.cjs.map +1 -1
- package/dist/components/organisms/SlideoutMenu/hooks/useSlideoutState.d.ts.map +1 -1
- package/dist/components/organisms/SlideoutMenu/hooks/useSlideoutState.js +4 -3
- package/dist/components/organisms/SlideoutMenu/hooks/useSlideoutState.js.map +1 -1
- package/dist/components/organisms/SlideoutMenu/index.cjs +5 -0
- package/dist/components/organisms/SlideoutMenu/index.cjs.map +1 -1
- package/dist/components/organisms/SlideoutMenu/index.d.ts +16 -9
- package/dist/components/organisms/SlideoutMenu/index.d.ts.map +1 -1
- package/dist/components/organisms/SlideoutMenu/index.js +5 -0
- package/dist/components/organisms/SlideoutMenu/index.js.map +1 -1
- package/dist/components/organisms/SlideoutMenu/providers/PageArea.context.cjs +4 -4
- package/dist/components/organisms/SlideoutMenu/providers/PageArea.context.d.ts +4 -4
- package/dist/components/organisms/SlideoutMenu/providers/PageArea.context.js +4 -4
- package/dist/hooks/__internal__/usePanelFocus/usePanelFocus.cjs +24 -8
- package/dist/hooks/__internal__/usePanelFocus/usePanelFocus.cjs.map +1 -1
- package/dist/hooks/__internal__/usePanelFocus/usePanelFocus.d.ts +3 -2
- package/dist/hooks/__internal__/usePanelFocus/usePanelFocus.d.ts.map +1 -1
- package/dist/hooks/__internal__/usePanelFocus/usePanelFocus.js +25 -9
- package/dist/hooks/__internal__/usePanelFocus/usePanelFocus.js.map +1 -1
- package/dist/providers/ThemeProvider/Theme.context.cjs +17 -0
- package/dist/providers/ThemeProvider/Theme.context.cjs.map +1 -0
- package/dist/providers/ThemeProvider/Theme.context.d.ts +16 -0
- package/dist/providers/ThemeProvider/Theme.context.d.ts.map +1 -0
- package/dist/providers/ThemeProvider/Theme.context.js +14 -0
- package/dist/providers/ThemeProvider/Theme.context.js.map +1 -0
- package/dist/providers/ThemeProvider/index.cjs +3 -11
- package/dist/providers/ThemeProvider/index.cjs.map +1 -1
- package/dist/providers/ThemeProvider/index.d.ts +1 -14
- package/dist/providers/ThemeProvider/index.d.ts.map +1 -1
- package/dist/providers/ThemeProvider/index.js +3 -10
- package/dist/providers/ThemeProvider/index.js.map +1 -1
- package/dist/utilities/__internal__/pageCoverUtils/pageCover.utils.cjs +30 -0
- package/dist/utilities/__internal__/pageCoverUtils/pageCover.utils.cjs.map +1 -0
- package/dist/utilities/__internal__/pageCoverUtils/pageCover.utils.d.ts +19 -0
- package/dist/utilities/__internal__/pageCoverUtils/pageCover.utils.d.ts.map +1 -0
- package/dist/utilities/__internal__/pageCoverUtils/pageCover.utils.js +26 -0
- package/dist/utilities/__internal__/pageCoverUtils/pageCover.utils.js.map +1 -0
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ var cx = require('@flipdish/ui-library/utilities/cx');
|
|
|
5
5
|
var react = require('motion/react');
|
|
6
6
|
var React = require('react');
|
|
7
7
|
var usePanelFocus = require('../../../../hooks/__internal__/usePanelFocus/usePanelFocus.cjs');
|
|
8
|
+
var pageCover_utils = require('../../../../utilities/__internal__/pageCoverUtils/pageCover.utils.cjs');
|
|
8
9
|
|
|
9
10
|
/** Width of the panel from `lg` in pixels. Matches `w-100`. Below `lg` the panel is as wide as the page. */
|
|
10
11
|
const SIDE_PANEL_WIDTH = 400;
|
|
@@ -23,6 +24,13 @@ const SidePanelRegion = ({ 'aria-label': ariaLabel, children, className, content
|
|
|
23
24
|
const panelRef = React.useRef(null);
|
|
24
25
|
const isPresent = react.useIsPresent();
|
|
25
26
|
const shouldReduceMotion = react.useReducedMotion();
|
|
27
|
+
// Starting to cover the page, on open below `lg` or on narrowing, is announced so a slideout over the page can close. Declared
|
|
28
|
+
// before the focus hook, so a slideout lifts its cover before this panel's focus call, which the cover would refuse.
|
|
29
|
+
const isCovering = isPresent && !isDesktop;
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
if (isCovering && panelRef.current)
|
|
32
|
+
pageCover_utils.dispatchPageCover(panelRef.current);
|
|
33
|
+
}, [isCovering]);
|
|
26
34
|
const { onFocusCapture } = usePanelFocus.usePanelFocus({ panelRef, isPresent, isDesktop, shouldFocusOnMount, contentKey });
|
|
27
35
|
// The first content arrives with the panel's own opening animation; only a later swap fades in.
|
|
28
36
|
const firstContentKey = React.useRef(contentKey);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelRegion.cjs","sources":["../../../../../src/components/organisms/SidePanel/components/SidePanelRegion.tsx"],"sourcesContent":[null],"names":["useRef","useIsPresent","useReducedMotion","
|
|
1
|
+
{"version":3,"file":"SidePanelRegion.cjs","sources":["../../../../../src/components/organisms/SidePanel/components/SidePanelRegion.tsx"],"sourcesContent":[null],"names":["useRef","useIsPresent","useReducedMotion","useEffect","dispatchPageCover","usePanelFocus","_jsx","motion","cx"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelRegion.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SidePanel/components/SidePanelRegion.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"SidePanelRegion.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SidePanel/components/SidePanelRegion.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,4GAA4G;AAC5G,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAepC,UAAU,oBAAoB;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED,2GAA2G;AAC3G,eAAO,MAAM,eAAe,GAAI,sGAQ7B,oBAAoB,gCA4DtB,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { cx } from '@flipdish/ui-library/utilities/cx';
|
|
|
3
3
|
import { useIsPresent, useReducedMotion, motion } from 'motion/react';
|
|
4
4
|
import { useRef, useEffect } from 'react';
|
|
5
5
|
import { usePanelFocus } from '../../../../hooks/__internal__/usePanelFocus/usePanelFocus.js';
|
|
6
|
+
import { dispatchPageCover } from '../../../../utilities/__internal__/pageCoverUtils/pageCover.utils.js';
|
|
6
7
|
|
|
7
8
|
/** Width of the panel from `lg` in pixels. Matches `w-100`. Below `lg` the panel is as wide as the page. */
|
|
8
9
|
const SIDE_PANEL_WIDTH = 400;
|
|
@@ -21,6 +22,13 @@ const SidePanelRegion = ({ 'aria-label': ariaLabel, children, className, content
|
|
|
21
22
|
const panelRef = useRef(null);
|
|
22
23
|
const isPresent = useIsPresent();
|
|
23
24
|
const shouldReduceMotion = useReducedMotion();
|
|
25
|
+
// Starting to cover the page, on open below `lg` or on narrowing, is announced so a slideout over the page can close. Declared
|
|
26
|
+
// before the focus hook, so a slideout lifts its cover before this panel's focus call, which the cover would refuse.
|
|
27
|
+
const isCovering = isPresent && !isDesktop;
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (isCovering && panelRef.current)
|
|
30
|
+
dispatchPageCover(panelRef.current);
|
|
31
|
+
}, [isCovering]);
|
|
24
32
|
const { onFocusCapture } = usePanelFocus({ panelRef, isPresent, isDesktop, shouldFocusOnMount, contentKey });
|
|
25
33
|
// The first content arrives with the panel's own opening animation; only a later swap fades in.
|
|
26
34
|
const firstContentKey = useRef(contentKey);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SidePanelRegion.js","sources":["../../../../../src/components/organisms/SidePanel/components/SidePanelRegion.tsx"],"sourcesContent":[null],"names":["_jsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"SidePanelRegion.js","sources":["../../../../../src/components/organisms/SidePanel/components/SidePanelRegion.tsx"],"sourcesContent":[null],"names":["_jsx"],"mappings":"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"}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
4
|
var useBreakpoints = require('@flipdish/ui-library/hooks/useBreakpoints');
|
|
5
|
-
var ThemeProvider = require('@flipdish/ui-library/providers/ThemeProvider');
|
|
6
5
|
var cx = require('@flipdish/ui-library/utilities/cx');
|
|
7
6
|
var testIdUtils = require('@flipdish/ui-library/utilities/testIdUtils');
|
|
8
7
|
var react = require('motion/react');
|
|
@@ -11,7 +10,10 @@ var reactAria = require('react-aria');
|
|
|
11
10
|
var reactAriaComponents = require('react-aria-components');
|
|
12
11
|
var usePanelFocus = require('../../../../hooks/__internal__/usePanelFocus/usePanelFocus.cjs');
|
|
13
12
|
var focus_utils = require('../../../../utilities/__internal__/focusUtils/focus.utils.cjs');
|
|
14
|
-
var
|
|
13
|
+
var Theme_context = require('../../../../providers/ThemeProvider/Theme.context.cjs');
|
|
14
|
+
var useCloseWhenCovered = require('../hooks/useCloseWhenCovered.cjs');
|
|
15
|
+
var useDialogFocusSettle = require('../hooks/useDialogFocusSettle.cjs');
|
|
16
|
+
var usePageEscapeDismiss = require('../hooks/usePageEscapeDismiss.cjs');
|
|
15
17
|
var useSlideoutState = require('../hooks/useSlideoutState.cjs');
|
|
16
18
|
var OverlayBounds_context = require('../providers/OverlayBounds.context.cjs');
|
|
17
19
|
var PageArea_context = require('../providers/PageArea.context.cjs');
|
|
@@ -19,77 +21,42 @@ var SlideoutMenu_context = require('../providers/SlideoutMenu.context.cjs');
|
|
|
19
21
|
var slideoutMenu_utils = require('../utilities/slideoutMenu.utils.cjs');
|
|
20
22
|
|
|
21
23
|
const SLIDE = { type: 'tween', duration: 0.3, ease: 'easeOut' };
|
|
22
|
-
|
|
24
|
+
// Leaves faster than it arrives, as `Modal` and the navigation drawer do.
|
|
25
|
+
const SLIDE_OUT = { type: 'tween', duration: 0.2, ease: 'easeIn' };
|
|
23
26
|
/** The panel itself. A component of its own so it can tell, while animating out, that it is leaving. */
|
|
24
|
-
const SlideoutPanel = ({ openState, label, labelledBy, boundsStyle, rootTestId, isDesktop, isKeyboardDismissDisabled,
|
|
27
|
+
const SlideoutPanel = ({ openState, label, labelledBy, boundsStyle, rootTestId, isDesktop, isKeyboardDismissDisabled, children, className, dialogClassName, }) => {
|
|
25
28
|
const panelRef = React.useRef(null);
|
|
26
29
|
const dialogRef = React.useRef(null);
|
|
27
30
|
const isPresent = react.useIsPresent();
|
|
28
31
|
const shouldReduceMotion = react.useReducedMotion();
|
|
29
|
-
const
|
|
30
|
-
//
|
|
31
|
-
// chrome, and with `scopeId` overlays portal outside it. The hook leaves a root the panel sits
|
|
32
|
-
// portals into its root
|
|
33
|
-
const themeRoot =
|
|
32
|
+
const pageAreaRef = React.useContext(PageArea_context.PageAreaContext);
|
|
33
|
+
// Without `AppShell` or `SlideoutMenu.PageArea` the panel covers the app itself: in a micro-frontend the themed root is the
|
|
34
|
+
// page area under the host's chrome, and with `scopeId` overlays portal outside it. The hook leaves a root the panel sits
|
|
35
|
+
// inside alone, so an app that portals into its root names its page area instead.
|
|
36
|
+
const themeRoot = Theme_context.useThemeRoot();
|
|
34
37
|
const themeRootRef = React.useMemo(() => ({ current: themeRoot }), [themeRoot]);
|
|
35
38
|
// Escape inside the panel; nothing outside is listened to for clicks, so the page stays usable and a click there never closes it.
|
|
36
39
|
const { overlayProps } = reactAria.useOverlay({ isOpen: isPresent, onClose: openState.close, isDismissable: false, shouldCloseOnBlur: false, isKeyboardDismissDisabled }, panelRef);
|
|
37
|
-
|
|
38
|
-
// took the key first (they prevent default on their own Escape and run before a document listener), and not from a field
|
|
39
|
-
// outside the panel, where Escape belongs to the field. Focus is left where the user put it.
|
|
40
|
-
const closeRef = React.useRef(openState.close);
|
|
41
|
-
closeRef.current = openState.close;
|
|
42
|
-
React.useEffect(() => {
|
|
43
|
-
if (!isPresent || isKeyboardDismissDisabled)
|
|
44
|
-
return;
|
|
45
|
-
const onKeyDown = (event) => {
|
|
46
|
-
if (event.key !== 'Escape' || event.defaultPrevented || event.isComposing)
|
|
47
|
-
return;
|
|
48
|
-
if (event.target instanceof Node && panelRef.current?.contains(event.target))
|
|
49
|
-
return;
|
|
50
|
-
if (hotkeys_utils.isTypingInField(event))
|
|
51
|
-
return;
|
|
52
|
-
closeRef.current();
|
|
53
|
-
};
|
|
54
|
-
document.addEventListener('keydown', onKeyDown);
|
|
55
|
-
return () => document.removeEventListener('keydown', onKeyDown);
|
|
56
|
-
}, [isPresent, isKeyboardDismissDisabled]);
|
|
40
|
+
usePageEscapeDismiss.usePageEscapeDismiss({ panelRef, enabled: isPresent && !isKeyboardDismissDisabled, onClose: openState.close });
|
|
57
41
|
// react-aria's `useDialog` already focuses the dialog on mount; this hook is here for the hand-back on close, the inert exit,
|
|
58
42
|
// and below `lg` the page area under the panel, which it takes out of reach: keyboard and screen reader skip what nobody can
|
|
59
|
-
// see.
|
|
60
|
-
|
|
61
|
-
const { onFocusCapture, setOpener } = usePanelFocus.usePanelFocus({
|
|
43
|
+
// see. A named page area wins over the app root. `shouldFocusOnMount` is what makes the hook record the opener.
|
|
44
|
+
const coveredRef = pageAreaRef ?? themeRootRef;
|
|
45
|
+
const { onFocusCapture, setOpener, liftCover } = usePanelFocus.usePanelFocus({
|
|
62
46
|
panelRef: dialogRef,
|
|
63
47
|
isPresent,
|
|
64
48
|
isDesktop,
|
|
65
|
-
coveredRef
|
|
49
|
+
coveredRef,
|
|
66
50
|
shouldFocusOnMount: true,
|
|
67
51
|
});
|
|
68
|
-
// A
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
document.removeEventListener('keydown', cancel, true);
|
|
77
|
-
};
|
|
78
|
-
const frame = requestAnimationFrame(() => {
|
|
79
|
-
stopWatching();
|
|
80
|
-
const dialog = dialogRef.current;
|
|
81
|
-
const focused = focus_utils.getFocusedElement();
|
|
82
|
-
if (dialog && !(focused && dialog.contains(focused)))
|
|
83
|
-
dialog.focus({ preventScroll: true });
|
|
84
|
-
});
|
|
85
|
-
const cancel = () => {
|
|
86
|
-
cancelAnimationFrame(frame);
|
|
87
|
-
stopWatching();
|
|
88
|
-
};
|
|
89
|
-
document.addEventListener('pointerdown', cancel, true);
|
|
90
|
-
document.addEventListener('keydown', cancel, true);
|
|
91
|
-
return cancel;
|
|
92
|
-
}, [isPresent]);
|
|
52
|
+
// A side panel starting to cover the page below `lg`, the shell's or a host's, closes the panel: it would otherwise sit over
|
|
53
|
+
// what the user just opened. The cover lifts at once, so that panel, mounting under it, can take focus in the same pass.
|
|
54
|
+
const closeForCoveringPanel = React.useCallback(() => {
|
|
55
|
+
liftCover();
|
|
56
|
+
openState.close();
|
|
57
|
+
}, [liftCover, openState.close]);
|
|
58
|
+
useCloseWhenCovered.useCloseWhenCovered({ isOpen: isPresent, onClose: closeForCoveringPanel });
|
|
59
|
+
useDialogFocusSettle.useDialogFocusSettle({ dialogRef, isPresent });
|
|
93
60
|
// A content swap leaves focus on the row the user clicked, so the new title is spoken instead; with focus inside, the user
|
|
94
61
|
// is already reading the panel and hears the change as they move. The last title lives here, not in `Header`, since a swap
|
|
95
62
|
// between loading and loaded content remounts the header; the first title is the open, which the dialog announces itself.
|
|
@@ -120,7 +87,7 @@ const SlideoutPanel = ({ openState, label, labelledBy, boundsStyle, rootTestId,
|
|
|
120
87
|
* and shares the open state with a surrounding `SlideoutMenu.Trigger`. Nothing is dimmed or locked; from
|
|
121
88
|
* `lg` the page beside the panel stays usable, and below `lg` only the page area it covers goes inert.
|
|
122
89
|
*/
|
|
123
|
-
const SlideoutShell = ({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDisabled, bounds,
|
|
90
|
+
const SlideoutShell = ({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDisabled, bounds, 'aria-label': ariaLabel, 'aria-labelledby': labelledBy, children, className, dialogClassName, 'data-testid': dataTestId, }) => {
|
|
124
91
|
const rootTestId = testIdUtils.useResolvedTestId({ testId: dataTestId, segment: 'slideout-menu', rootName: 'slideout-menu' });
|
|
125
92
|
const triggerState = React.useContext(reactAriaComponents.OverlayTriggerStateContext);
|
|
126
93
|
const local = useSlideoutState.useSlideoutState({ isOpen, defaultOpen, onOpenChange });
|
|
@@ -131,7 +98,7 @@ const SlideoutShell = ({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDis
|
|
|
131
98
|
const isDesktop = useBreakpoints.useBreakpoints('lg');
|
|
132
99
|
// A heading named through `aria-labelledby` replaces the default name; an explicit `aria-label` still wins.
|
|
133
100
|
const label = ariaLabel ?? (labelledBy ? undefined : 'Slideout menu');
|
|
134
|
-
return (jsxRuntime.jsx(testIdUtils.TestIdProvider, { value: rootTestId, children: jsxRuntime.jsx(react.AnimatePresence, { children: openState.isOpen && (jsxRuntime.jsx(reactAria.Overlay, { disableFocusManagement: true, children: jsxRuntime.jsx(reactAriaComponents.OverlayTriggerStateContext.Provider, { value: openState, children: jsxRuntime.jsx(SlideoutPanel, { openState: openState, label: label, labelledBy: labelledBy, boundsStyle: boundsStyle, rootTestId: rootTestId, isDesktop: isDesktop, isKeyboardDismissDisabled: isKeyboardDismissDisabled,
|
|
101
|
+
return (jsxRuntime.jsx(testIdUtils.TestIdProvider, { value: rootTestId, children: jsxRuntime.jsx(react.AnimatePresence, { children: openState.isOpen && (jsxRuntime.jsx(reactAria.Overlay, { disableFocusManagement: true, children: jsxRuntime.jsx(reactAriaComponents.OverlayTriggerStateContext.Provider, { value: openState, children: jsxRuntime.jsx(SlideoutPanel, { openState: openState, label: label, labelledBy: labelledBy, boundsStyle: boundsStyle, rootTestId: rootTestId, isDesktop: isDesktop, isKeyboardDismissDisabled: isKeyboardDismissDisabled, className: className, dialogClassName: dialogClassName, children: children }) }) }, "slideout-menu")) }) }));
|
|
135
102
|
};
|
|
136
103
|
SlideoutShell.displayName = 'SlideoutShell';
|
|
137
104
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlideoutShell.cjs","sources":["../../../../../src/components/organisms/SlideoutMenu/components/SlideoutShell.tsx"],"sourcesContent":[null],"names":["useRef","useIsPresent","useReducedMotion","useContext","PageAreaContext","useThemeRoot","useMemo","useOverlay","
|
|
1
|
+
{"version":3,"file":"SlideoutShell.cjs","sources":["../../../../../src/components/organisms/SlideoutMenu/components/SlideoutShell.tsx"],"sourcesContent":[null],"names":["useRef","useIsPresent","useReducedMotion","useContext","PageAreaContext","useThemeRoot","useMemo","useOverlay","usePageEscapeDismiss","usePanelFocus","useCallback","useCloseWhenCovered","useDialogFocusSettle","useState","getFocusedElement","_jsx","_jsxs","motion","cx","SlideoutMenuContext","FocusScope","AriaDialog","useResolvedTestId","OverlayTriggerStateContext","useSlideoutState","OverlayBoundsContext","resolveSlideoutBounds","useBreakpoints","TestIdProvider","AnimatePresence","Overlay"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ReactNode
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
2
|
import type { SlideoutBounds } from '../utilities/slideoutMenu.utils';
|
|
3
3
|
/** What the render-prop form of `children` receives. */
|
|
4
4
|
export interface SlideoutRenderProps {
|
|
@@ -11,7 +11,6 @@ export interface SlideoutShellProps {
|
|
|
11
11
|
onOpenChange?: (isOpen: boolean) => void;
|
|
12
12
|
isKeyboardDismissDisabled?: boolean;
|
|
13
13
|
bounds?: SlideoutBounds;
|
|
14
|
-
pageAreaRef?: RefObject<HTMLElement | null>;
|
|
15
14
|
'aria-label'?: string;
|
|
16
15
|
'aria-labelledby'?: string;
|
|
17
16
|
children: ReactNode | ((state: SlideoutRenderProps) => ReactNode);
|
|
@@ -25,7 +24,7 @@ export interface SlideoutShellProps {
|
|
|
25
24
|
* `lg` the page beside the panel stays usable, and below `lg` only the page area it covers goes inert.
|
|
26
25
|
*/
|
|
27
26
|
export declare const SlideoutShell: {
|
|
28
|
-
({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDisabled, bounds,
|
|
27
|
+
({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDisabled, bounds, "aria-label": ariaLabel, "aria-labelledby": labelledBy, children, className, dialogClassName, "data-testid": dataTestId, }: SlideoutShellProps): import("react").JSX.Element;
|
|
29
28
|
displayName: string;
|
|
30
29
|
};
|
|
31
30
|
//# sourceMappingURL=SlideoutShell.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlideoutShell.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SlideoutMenu/components/SlideoutShell.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SlideoutShell.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SlideoutMenu/components/SlideoutShell.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAC;AAetD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAGtE,wDAAwD;AACxD,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,mBAAmB,KAAK,SAAS,CAAC,CAAC;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA8HD;;;;GAIG;AACH,eAAO,MAAM,aAAa;yMAYvB,kBAAkB;;CAqCpB,CAAC"}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { useBreakpoints } from '@flipdish/ui-library/hooks/useBreakpoints';
|
|
3
|
-
import { useThemeRoot } from '@flipdish/ui-library/providers/ThemeProvider';
|
|
4
3
|
import { cx } from '@flipdish/ui-library/utilities/cx';
|
|
5
4
|
import { useResolvedTestId, TestIdProvider } from '@flipdish/ui-library/utilities/testIdUtils';
|
|
6
5
|
import { AnimatePresence, useIsPresent, useReducedMotion, motion } from 'motion/react';
|
|
7
|
-
import { useContext, useRef, useMemo,
|
|
6
|
+
import { useContext, useRef, useMemo, useCallback, useState } from 'react';
|
|
8
7
|
import { Overlay, useOverlay, FocusScope } from 'react-aria';
|
|
9
8
|
import { OverlayTriggerStateContext, Dialog } from 'react-aria-components';
|
|
10
9
|
import { usePanelFocus } from '../../../../hooks/__internal__/usePanelFocus/usePanelFocus.js';
|
|
11
10
|
import { getFocusedElement } from '../../../../utilities/__internal__/focusUtils/focus.utils.js';
|
|
12
|
-
import {
|
|
11
|
+
import { useThemeRoot } from '../../../../providers/ThemeProvider/Theme.context.js';
|
|
12
|
+
import { useCloseWhenCovered } from '../hooks/useCloseWhenCovered.js';
|
|
13
|
+
import { useDialogFocusSettle } from '../hooks/useDialogFocusSettle.js';
|
|
14
|
+
import { usePageEscapeDismiss } from '../hooks/usePageEscapeDismiss.js';
|
|
13
15
|
import { useSlideoutState } from '../hooks/useSlideoutState.js';
|
|
14
16
|
import { OverlayBoundsContext } from '../providers/OverlayBounds.context.js';
|
|
15
17
|
import { PageAreaContext } from '../providers/PageArea.context.js';
|
|
@@ -17,77 +19,42 @@ import { SlideoutMenuContext } from '../providers/SlideoutMenu.context.js';
|
|
|
17
19
|
import { resolveSlideoutBounds } from '../utilities/slideoutMenu.utils.js';
|
|
18
20
|
|
|
19
21
|
const SLIDE = { type: 'tween', duration: 0.3, ease: 'easeOut' };
|
|
20
|
-
|
|
22
|
+
// Leaves faster than it arrives, as `Modal` and the navigation drawer do.
|
|
23
|
+
const SLIDE_OUT = { type: 'tween', duration: 0.2, ease: 'easeIn' };
|
|
21
24
|
/** The panel itself. A component of its own so it can tell, while animating out, that it is leaving. */
|
|
22
|
-
const SlideoutPanel = ({ openState, label, labelledBy, boundsStyle, rootTestId, isDesktop, isKeyboardDismissDisabled,
|
|
25
|
+
const SlideoutPanel = ({ openState, label, labelledBy, boundsStyle, rootTestId, isDesktop, isKeyboardDismissDisabled, children, className, dialogClassName, }) => {
|
|
23
26
|
const panelRef = useRef(null);
|
|
24
27
|
const dialogRef = useRef(null);
|
|
25
28
|
const isPresent = useIsPresent();
|
|
26
29
|
const shouldReduceMotion = useReducedMotion();
|
|
27
|
-
const
|
|
28
|
-
//
|
|
29
|
-
// chrome, and with `scopeId` overlays portal outside it. The hook leaves a root the panel sits
|
|
30
|
-
// portals into its root
|
|
30
|
+
const pageAreaRef = useContext(PageAreaContext);
|
|
31
|
+
// Without `AppShell` or `SlideoutMenu.PageArea` the panel covers the app itself: in a micro-frontend the themed root is the
|
|
32
|
+
// page area under the host's chrome, and with `scopeId` overlays portal outside it. The hook leaves a root the panel sits
|
|
33
|
+
// inside alone, so an app that portals into its root names its page area instead.
|
|
31
34
|
const themeRoot = useThemeRoot();
|
|
32
35
|
const themeRootRef = useMemo(() => ({ current: themeRoot }), [themeRoot]);
|
|
33
36
|
// Escape inside the panel; nothing outside is listened to for clicks, so the page stays usable and a click there never closes it.
|
|
34
37
|
const { overlayProps } = useOverlay({ isOpen: isPresent, onClose: openState.close, isDismissable: false, shouldCloseOnBlur: false, isKeyboardDismissDisabled }, panelRef);
|
|
35
|
-
|
|
36
|
-
// took the key first (they prevent default on their own Escape and run before a document listener), and not from a field
|
|
37
|
-
// outside the panel, where Escape belongs to the field. Focus is left where the user put it.
|
|
38
|
-
const closeRef = useRef(openState.close);
|
|
39
|
-
closeRef.current = openState.close;
|
|
40
|
-
useEffect(() => {
|
|
41
|
-
if (!isPresent || isKeyboardDismissDisabled)
|
|
42
|
-
return;
|
|
43
|
-
const onKeyDown = (event) => {
|
|
44
|
-
if (event.key !== 'Escape' || event.defaultPrevented || event.isComposing)
|
|
45
|
-
return;
|
|
46
|
-
if (event.target instanceof Node && panelRef.current?.contains(event.target))
|
|
47
|
-
return;
|
|
48
|
-
if (isTypingInField(event))
|
|
49
|
-
return;
|
|
50
|
-
closeRef.current();
|
|
51
|
-
};
|
|
52
|
-
document.addEventListener('keydown', onKeyDown);
|
|
53
|
-
return () => document.removeEventListener('keydown', onKeyDown);
|
|
54
|
-
}, [isPresent, isKeyboardDismissDisabled]);
|
|
38
|
+
usePageEscapeDismiss({ panelRef, enabled: isPresent && !isKeyboardDismissDisabled, onClose: openState.close });
|
|
55
39
|
// react-aria's `useDialog` already focuses the dialog on mount; this hook is here for the hand-back on close, the inert exit,
|
|
56
40
|
// and below `lg` the page area under the panel, which it takes out of reach: keyboard and screen reader skip what nobody can
|
|
57
|
-
// see.
|
|
58
|
-
|
|
59
|
-
const { onFocusCapture, setOpener } = usePanelFocus({
|
|
41
|
+
// see. A named page area wins over the app root. `shouldFocusOnMount` is what makes the hook record the opener.
|
|
42
|
+
const coveredRef = pageAreaRef ?? themeRootRef;
|
|
43
|
+
const { onFocusCapture, setOpener, liftCover } = usePanelFocus({
|
|
60
44
|
panelRef: dialogRef,
|
|
61
45
|
isPresent,
|
|
62
46
|
isDesktop,
|
|
63
|
-
coveredRef
|
|
47
|
+
coveredRef,
|
|
64
48
|
shouldFocusOnMount: true,
|
|
65
49
|
});
|
|
66
|
-
// A
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
document.removeEventListener('keydown', cancel, true);
|
|
75
|
-
};
|
|
76
|
-
const frame = requestAnimationFrame(() => {
|
|
77
|
-
stopWatching();
|
|
78
|
-
const dialog = dialogRef.current;
|
|
79
|
-
const focused = getFocusedElement();
|
|
80
|
-
if (dialog && !(focused && dialog.contains(focused)))
|
|
81
|
-
dialog.focus({ preventScroll: true });
|
|
82
|
-
});
|
|
83
|
-
const cancel = () => {
|
|
84
|
-
cancelAnimationFrame(frame);
|
|
85
|
-
stopWatching();
|
|
86
|
-
};
|
|
87
|
-
document.addEventListener('pointerdown', cancel, true);
|
|
88
|
-
document.addEventListener('keydown', cancel, true);
|
|
89
|
-
return cancel;
|
|
90
|
-
}, [isPresent]);
|
|
50
|
+
// A side panel starting to cover the page below `lg`, the shell's or a host's, closes the panel: it would otherwise sit over
|
|
51
|
+
// what the user just opened. The cover lifts at once, so that panel, mounting under it, can take focus in the same pass.
|
|
52
|
+
const closeForCoveringPanel = useCallback(() => {
|
|
53
|
+
liftCover();
|
|
54
|
+
openState.close();
|
|
55
|
+
}, [liftCover, openState.close]);
|
|
56
|
+
useCloseWhenCovered({ isOpen: isPresent, onClose: closeForCoveringPanel });
|
|
57
|
+
useDialogFocusSettle({ dialogRef, isPresent });
|
|
91
58
|
// A content swap leaves focus on the row the user clicked, so the new title is spoken instead; with focus inside, the user
|
|
92
59
|
// is already reading the panel and hears the change as they move. The last title lives here, not in `Header`, since a swap
|
|
93
60
|
// between loading and loaded content remounts the header; the first title is the open, which the dialog announces itself.
|
|
@@ -118,7 +85,7 @@ const SlideoutPanel = ({ openState, label, labelledBy, boundsStyle, rootTestId,
|
|
|
118
85
|
* and shares the open state with a surrounding `SlideoutMenu.Trigger`. Nothing is dimmed or locked; from
|
|
119
86
|
* `lg` the page beside the panel stays usable, and below `lg` only the page area it covers goes inert.
|
|
120
87
|
*/
|
|
121
|
-
const SlideoutShell = ({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDisabled, bounds,
|
|
88
|
+
const SlideoutShell = ({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDisabled, bounds, 'aria-label': ariaLabel, 'aria-labelledby': labelledBy, children, className, dialogClassName, 'data-testid': dataTestId, }) => {
|
|
122
89
|
const rootTestId = useResolvedTestId({ testId: dataTestId, segment: 'slideout-menu', rootName: 'slideout-menu' });
|
|
123
90
|
const triggerState = useContext(OverlayTriggerStateContext);
|
|
124
91
|
const local = useSlideoutState({ isOpen, defaultOpen, onOpenChange });
|
|
@@ -129,7 +96,7 @@ const SlideoutShell = ({ isOpen, defaultOpen, onOpenChange, isKeyboardDismissDis
|
|
|
129
96
|
const isDesktop = useBreakpoints('lg');
|
|
130
97
|
// A heading named through `aria-labelledby` replaces the default name; an explicit `aria-label` still wins.
|
|
131
98
|
const label = ariaLabel ?? (labelledBy ? undefined : 'Slideout menu');
|
|
132
|
-
return (jsx(TestIdProvider, { value: rootTestId, children: jsx(AnimatePresence, { children: openState.isOpen && (jsx(Overlay, { disableFocusManagement: true, children: jsx(OverlayTriggerStateContext.Provider, { value: openState, children: jsx(SlideoutPanel, { openState: openState, label: label, labelledBy: labelledBy, boundsStyle: boundsStyle, rootTestId: rootTestId, isDesktop: isDesktop, isKeyboardDismissDisabled: isKeyboardDismissDisabled,
|
|
99
|
+
return (jsx(TestIdProvider, { value: rootTestId, children: jsx(AnimatePresence, { children: openState.isOpen && (jsx(Overlay, { disableFocusManagement: true, children: jsx(OverlayTriggerStateContext.Provider, { value: openState, children: jsx(SlideoutPanel, { openState: openState, label: label, labelledBy: labelledBy, boundsStyle: boundsStyle, rootTestId: rootTestId, isDesktop: isDesktop, isKeyboardDismissDisabled: isKeyboardDismissDisabled, className: className, dialogClassName: dialogClassName, children: children }) }) }, "slideout-menu")) }) }));
|
|
133
100
|
};
|
|
134
101
|
SlideoutShell.displayName = 'SlideoutShell';
|
|
135
102
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlideoutShell.js","sources":["../../../../../src/components/organisms/SlideoutMenu/components/SlideoutShell.tsx"],"sourcesContent":[null],"names":["_jsx","_jsxs","AriaDialog"],"mappings":"
|
|
1
|
+
{"version":3,"file":"SlideoutShell.js","sources":["../../../../../src/components/organisms/SlideoutMenu/components/SlideoutShell.tsx"],"sourcesContent":[null],"names":["_jsx","_jsxs","AriaDialog"],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var pageCover_utils = require('../../../../utilities/__internal__/pageCoverUtils/pageCover.utils.cjs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Closes the panel when a side panel starts covering the page, in the shell or in a host such as the Portal. The panel is
|
|
8
|
+
* the transient thing the user opened, and left open it would sit over what they just asked for.
|
|
9
|
+
*
|
|
10
|
+
* @param options Whether the panel is open, and how to close it.
|
|
11
|
+
*/
|
|
12
|
+
const useCloseWhenCovered = ({ isOpen, onClose }) => {
|
|
13
|
+
// Written in an effect, so a render React discards never leaves the listener a callback from a state it threw away; a
|
|
14
|
+
// layout effect, declared first, so the listener below calls the committed one even in the commit that opened the panel.
|
|
15
|
+
const closeRef = React.useRef(onClose);
|
|
16
|
+
React.useLayoutEffect(() => {
|
|
17
|
+
closeRef.current = onClose;
|
|
18
|
+
});
|
|
19
|
+
// Listening for as long as the panel is open, not only once it covers the page itself: narrowing flips the side panel and
|
|
20
|
+
// this panel at once, and a host's panel in another React root may announce before this one has re-rendered. The event
|
|
21
|
+
// only fires below `lg`, where a side panel covers the page, so it never closes a panel docked beside one. A layout
|
|
22
|
+
// effect, so a listener mounting in the same commit as the announcement is in place before passive effects run.
|
|
23
|
+
React.useLayoutEffect(() => {
|
|
24
|
+
if (!isOpen)
|
|
25
|
+
return;
|
|
26
|
+
return pageCover_utils.subscribePageCover(() => closeRef.current());
|
|
27
|
+
}, [isOpen]);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
exports.useCloseWhenCovered = useCloseWhenCovered;
|
|
31
|
+
//# sourceMappingURL=useCloseWhenCovered.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCloseWhenCovered.cjs","sources":["../../../../../src/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.ts"],"sourcesContent":[null],"names":["useRef","useLayoutEffect","subscribePageCover"],"mappings":";;;;;AAYA;;;;;AAKG;AACI,MAAM,mBAAmB,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAA8B,KAAU;;;AAG3F,IAAA,MAAM,QAAQ,GAAGA,YAAM,CAAC,OAAO,CAAC;IAChCC,qBAAe,CAAC,MAAK;AACnB,QAAA,QAAQ,CAAC,OAAO,GAAG,OAAO;AAC5B,IAAA,CAAC,CAAC;;;;;IAMFA,qBAAe,CAAC,MAAK;AACnB,QAAA,IAAI,CAAC,MAAM;YAAE;QACb,OAAOC,kCAAkB,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;AACrD,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;AACd;;"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface UseCloseWhenCoveredOptions {
|
|
2
|
+
/** True while the panel is open, until it starts to leave. */
|
|
3
|
+
isOpen: boolean;
|
|
4
|
+
/** Closes the panel. */
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Closes the panel when a side panel starts covering the page, in the shell or in a host such as the Portal. The panel is
|
|
9
|
+
* the transient thing the user opened, and left open it would sit over what they just asked for.
|
|
10
|
+
*
|
|
11
|
+
* @param options Whether the panel is open, and how to close it.
|
|
12
|
+
*/
|
|
13
|
+
export declare const useCloseWhenCovered: ({ isOpen, onClose }: UseCloseWhenCoveredOptions) => void;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=useCloseWhenCovered.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCloseWhenCovered.d.ts","sourceRoot":"","sources":["../../../../../src/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.ts"],"names":[],"mappings":"AAKA,UAAU,0BAA0B;IAClC,8DAA8D;IAC9D,MAAM,EAAE,OAAO,CAAC;IAChB,wBAAwB;IACxB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAAI,qBAAqB,0BAA0B,KAAG,IAgBrF,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useRef, useLayoutEffect } from 'react';
|
|
2
|
+
import { subscribePageCover } from '../../../../utilities/__internal__/pageCoverUtils/pageCover.utils.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Closes the panel when a side panel starts covering the page, in the shell or in a host such as the Portal. The panel is
|
|
6
|
+
* the transient thing the user opened, and left open it would sit over what they just asked for.
|
|
7
|
+
*
|
|
8
|
+
* @param options Whether the panel is open, and how to close it.
|
|
9
|
+
*/
|
|
10
|
+
const useCloseWhenCovered = ({ isOpen, onClose }) => {
|
|
11
|
+
// Written in an effect, so a render React discards never leaves the listener a callback from a state it threw away; a
|
|
12
|
+
// layout effect, declared first, so the listener below calls the committed one even in the commit that opened the panel.
|
|
13
|
+
const closeRef = useRef(onClose);
|
|
14
|
+
useLayoutEffect(() => {
|
|
15
|
+
closeRef.current = onClose;
|
|
16
|
+
});
|
|
17
|
+
// Listening for as long as the panel is open, not only once it covers the page itself: narrowing flips the side panel and
|
|
18
|
+
// this panel at once, and a host's panel in another React root may announce before this one has re-rendered. The event
|
|
19
|
+
// only fires below `lg`, where a side panel covers the page, so it never closes a panel docked beside one. A layout
|
|
20
|
+
// effect, so a listener mounting in the same commit as the announcement is in place before passive effects run.
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
if (!isOpen)
|
|
23
|
+
return;
|
|
24
|
+
return subscribePageCover(() => closeRef.current());
|
|
25
|
+
}, [isOpen]);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export { useCloseWhenCovered };
|
|
29
|
+
//# sourceMappingURL=useCloseWhenCovered.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCloseWhenCovered.js","sources":["../../../../../src/components/organisms/SlideoutMenu/hooks/useCloseWhenCovered.ts"],"sourcesContent":[null],"names":[],"mappings":";;;AAYA;;;;;AAKG;AACI,MAAM,mBAAmB,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAA8B,KAAU;;;AAG3F,IAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC;IAChC,eAAe,CAAC,MAAK;AACnB,QAAA,QAAQ,CAAC,OAAO,GAAG,OAAO;AAC5B,IAAA,CAAC,CAAC;;;;;IAMF,eAAe,CAAC,MAAK;AACnB,QAAA,IAAI,CAAC,MAAM;YAAE;QACb,OAAO,kBAAkB,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;AACrD,IAAA,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;AACd;;"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var focus_utils = require('../../../../utilities/__internal__/focusUtils/focus.utils.cjs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Focuses the dialog one frame after the panel opens, when a row opened by mouse selects on
|
|
8
|
+
* pointerdown and the browser then lands focus back on that row. If nothing inside holds focus
|
|
9
|
+
* by that frame, the dialog takes it. A pointer or key before the frame means the user has moved
|
|
10
|
+
* on, such as to the next row, and the frame is dropped so focus is not pulled back.
|
|
11
|
+
*
|
|
12
|
+
* @param options The dialog element and whether the panel is still present.
|
|
13
|
+
* @returns Nothing. Focus is moved on the dialog element.
|
|
14
|
+
*/
|
|
15
|
+
const useDialogFocusSettle = ({ dialogRef, isPresent }) => {
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
if (!isPresent)
|
|
18
|
+
return;
|
|
19
|
+
const stopWatching = () => {
|
|
20
|
+
document.removeEventListener('pointerdown', cancel, true);
|
|
21
|
+
document.removeEventListener('keydown', cancel, true);
|
|
22
|
+
};
|
|
23
|
+
const frame = requestAnimationFrame(() => {
|
|
24
|
+
stopWatching();
|
|
25
|
+
const dialog = dialogRef.current;
|
|
26
|
+
const focused = focus_utils.getFocusedElement();
|
|
27
|
+
if (dialog && !(focused && dialog.contains(focused)))
|
|
28
|
+
dialog.focus({ preventScroll: true });
|
|
29
|
+
});
|
|
30
|
+
const cancel = () => {
|
|
31
|
+
cancelAnimationFrame(frame);
|
|
32
|
+
stopWatching();
|
|
33
|
+
};
|
|
34
|
+
document.addEventListener('pointerdown', cancel, true);
|
|
35
|
+
document.addEventListener('keydown', cancel, true);
|
|
36
|
+
return cancel;
|
|
37
|
+
}, [dialogRef, isPresent]);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
exports.useDialogFocusSettle = useDialogFocusSettle;
|
|
41
|
+
//# sourceMappingURL=useDialogFocusSettle.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDialogFocusSettle.cjs","sources":["../../../../../src/components/organisms/SlideoutMenu/hooks/useDialogFocusSettle.ts"],"sourcesContent":[null],"names":["useEffect","getFocusedElement"],"mappings":";;;;;AAaA;;;;;;;;AAQG;AACI,MAAM,oBAAoB,GAAG,CAAC,EAAE,SAAS,EAAE,SAAS,EAA+B,KAAU;IAClGA,eAAS,CAAC,MAAK;AACb,QAAA,IAAI,CAAC,SAAS;YAAE;QAChB,MAAM,YAAY,GAAG,MAAK;YACxB,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC;YACzD,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC;AACvD,QAAA,CAAC;AACD,QAAA,MAAM,KAAK,GAAG,qBAAqB,CAAC,MAAK;AACvC,YAAA,YAAY,EAAE;AACd,YAAA,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO;AAChC,YAAA,MAAM,OAAO,GAAGC,6BAAiB,EAAE;AACnC,YAAA,IAAI,MAAM,IAAI,EAAE,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAAE,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;AAC7F,QAAA,CAAC,CAAC;QACF,MAAM,MAAM,GAAG,MAAK;YAClB,oBAAoB,CAAC,KAAK,CAAC;AAC3B,YAAA,YAAY,EAAE;AAChB,QAAA,CAAC;QACD,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC;QACtD,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC;AAClD,QAAA,OAAO,MAAM;AACf,IAAA,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;AAC5B;;"}
|