@react-aria/overlays 3.22.1 → 3.23.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/types.d.ts +10 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/useCloseOnScroll.main.js +4 -0
- package/dist/useCloseOnScroll.main.js.map +1 -1
- package/dist/useCloseOnScroll.mjs +4 -0
- package/dist/useCloseOnScroll.module.js +4 -0
- package/dist/useCloseOnScroll.module.js.map +1 -1
- package/dist/useModalOverlay.main.js.map +1 -1
- package/dist/useModalOverlay.module.js.map +1 -1
- package/dist/useOverlay.main.js.map +1 -1
- package/dist/useOverlay.module.js.map +1 -1
- package/dist/useOverlayPosition.main.js +37 -3
- package/dist/useOverlayPosition.main.js.map +1 -1
- package/dist/useOverlayPosition.mjs +37 -3
- package/dist/useOverlayPosition.module.js +37 -3
- package/dist/useOverlayPosition.module.js.map +1 -1
- package/dist/useOverlayTrigger.main.js.map +1 -1
- package/dist/useOverlayTrigger.module.js.map +1 -1
- package/dist/usePopover.main.js.map +1 -1
- package/dist/usePopover.module.js.map +1 -1
- package/package.json +14 -14
- package/src/useCloseOnScroll.ts +10 -2
- package/src/useModalOverlay.ts +3 -3
- package/src/useOverlay.ts +4 -4
- package/src/useOverlayPosition.ts +50 -8
- package/src/useOverlayTrigger.ts +3 -3
- package/src/usePopover.ts +3 -4
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { DOMAttributes, DOMProps, AriaLabelingProps } from "@react-types/shared";
|
|
1
|
+
import { DOMAttributes, RefObject, DOMProps, AriaLabelingProps } from "@react-types/shared";
|
|
2
2
|
import { PlacementAxis, PositionProps } from "@react-types/overlays";
|
|
3
|
-
import React, { RefObject, AriaAttributes, ReactNode } from "react";
|
|
4
3
|
import { AriaButtonProps } from "@react-types/button";
|
|
5
4
|
import { OverlayTriggerState } from "@react-stately/overlays";
|
|
5
|
+
import React, { AriaAttributes, ReactNode } from "react";
|
|
6
6
|
export interface AriaPositionProps extends PositionProps {
|
|
7
7
|
/**
|
|
8
8
|
* Cross size of the overlay arrow in pixels.
|
|
@@ -17,16 +17,16 @@ export interface AriaPositionProps extends PositionProps {
|
|
|
17
17
|
/**
|
|
18
18
|
* The ref for the element which the overlay positions itself with respect to.
|
|
19
19
|
*/
|
|
20
|
-
targetRef: RefObject<Element>;
|
|
20
|
+
targetRef: RefObject<Element | null>;
|
|
21
21
|
/**
|
|
22
22
|
* The ref for the overlay element.
|
|
23
23
|
*/
|
|
24
|
-
overlayRef: RefObject<Element>;
|
|
24
|
+
overlayRef: RefObject<Element | null>;
|
|
25
25
|
/**
|
|
26
26
|
* A ref for the scrollable region within the overlay.
|
|
27
27
|
* @default overlayRef
|
|
28
28
|
*/
|
|
29
|
-
scrollRef?: RefObject<Element>;
|
|
29
|
+
scrollRef?: RefObject<Element | null>;
|
|
30
30
|
/**
|
|
31
31
|
* Whether the overlay should update its position automatically.
|
|
32
32
|
* @default true
|
|
@@ -96,7 +96,7 @@ export interface OverlayAria {
|
|
|
96
96
|
* Hides the overlay when the user interacts outside it, when the Escape key is pressed,
|
|
97
97
|
* or optionally, on blur. Only the top-most overlay will close at once.
|
|
98
98
|
*/
|
|
99
|
-
export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element>): OverlayAria;
|
|
99
|
+
export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | null>): OverlayAria;
|
|
100
100
|
export interface OverlayTriggerProps {
|
|
101
101
|
/** Type of overlay that is opened by the trigger. */
|
|
102
102
|
type: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid';
|
|
@@ -111,7 +111,7 @@ export interface OverlayTriggerAria {
|
|
|
111
111
|
* Handles the behavior and accessibility for an overlay trigger, e.g. a button
|
|
112
112
|
* that opens a popover, menu, or other overlay that is positioned relative to the trigger.
|
|
113
113
|
*/
|
|
114
|
-
export function useOverlayTrigger(props: OverlayTriggerProps, state: OverlayTriggerState, ref?: RefObject<Element>): OverlayTriggerAria;
|
|
114
|
+
export function useOverlayTrigger(props: OverlayTriggerProps, state: OverlayTriggerState, ref?: RefObject<Element | null>): OverlayTriggerAria;
|
|
115
115
|
interface PreventScrollOptions {
|
|
116
116
|
/** Whether the scroll lock is disabled. */
|
|
117
117
|
isDisabled?: boolean;
|
|
@@ -210,11 +210,11 @@ export interface AriaPopoverProps extends Omit<AriaPositionProps, 'isOpen' | 'on
|
|
|
210
210
|
/**
|
|
211
211
|
* The ref for the element which the popover positions itself with respect to.
|
|
212
212
|
*/
|
|
213
|
-
triggerRef: RefObject<Element>;
|
|
213
|
+
triggerRef: RefObject<Element | null>;
|
|
214
214
|
/**
|
|
215
215
|
* The ref for the popover element.
|
|
216
216
|
*/
|
|
217
|
-
popoverRef: RefObject<Element>;
|
|
217
|
+
popoverRef: RefObject<Element | null>;
|
|
218
218
|
/**
|
|
219
219
|
* Whether the popover is non-modal, i.e. elements outside the popover may be
|
|
220
220
|
* interacted with by assistive technologies.
|
|
@@ -312,7 +312,7 @@ export interface ModalOverlayAria {
|
|
|
312
312
|
* Provides the behavior and accessibility implementation for a modal component.
|
|
313
313
|
* A modal is an overlay element which blocks interaction with elements outside it.
|
|
314
314
|
*/
|
|
315
|
-
export function useModalOverlay(props: AriaModalOverlayProps, state: OverlayTriggerState, ref: RefObject<HTMLElement>): ModalOverlayAria;
|
|
315
|
+
export function useModalOverlay(props: AriaModalOverlayProps, state: OverlayTriggerState, ref: RefObject<HTMLElement | null>): ModalOverlayAria;
|
|
316
316
|
export type { Placement, PlacementAxis, PositionProps } from '@react-types/overlays';
|
|
317
317
|
|
|
318
318
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;AEoBA,kCAAmC,SAAQ,aAAa;IACtD;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;OAEG;IACH,SAAS,EAAE,UAAU,OAAO,CAAC,CAAC;
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/calculatePosition.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/useCloseOnScroll.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/useOverlayPosition.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/useOverlay.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/useOverlayTrigger.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/usePreventScroll.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/useModal.tsx","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/DismissButton.tsx","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/ariaHideOutside.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/usePopover.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/PortalProvider.tsx","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/Overlay.tsx","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/useModalOverlay.ts","packages/@react-aria/overlays/src/packages/@react-aria/overlays/src/index.ts","packages/@react-aria/overlays/src/index.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\nexport {useOverlayPosition} from './useOverlayPosition';\nexport {useOverlay} from './useOverlay';\nexport {useOverlayTrigger} from './useOverlayTrigger';\nexport {usePreventScroll} from './usePreventScroll';\nexport {ModalProvider, useModalProvider, OverlayProvider, OverlayContainer, useModal} from './useModal';\nexport {DismissButton} from './DismissButton';\nexport {ariaHideOutside} from './ariaHideOutside';\nexport {usePopover} from './usePopover';\nexport {useModalOverlay} from './useModalOverlay';\nexport {Overlay, useOverlayFocusContain} from './Overlay';\nexport {UNSTABLE_PortalProvider, useUNSTABLE_PortalContext} from './PortalProvider';\n\nexport type {AriaPositionProps, PositionAria} from './useOverlayPosition';\nexport type {AriaOverlayProps, OverlayAria} from './useOverlay';\nexport type {OverlayTriggerAria, OverlayTriggerProps} from './useOverlayTrigger';\nexport type {AriaModalOptions, ModalAria, ModalProviderAria, ModalProviderProps, OverlayContainerProps} from './useModal';\nexport type {DismissButtonProps} from './DismissButton';\nexport type {AriaPopoverProps, PopoverAria} from './usePopover';\nexport type {AriaModalOverlayProps, ModalOverlayAria} from './useModalOverlay';\nexport type {OverlayProps} from './Overlay';\nexport type {Placement, PlacementAxis, PositionProps} from '@react-types/overlays';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
|
|
@@ -28,6 +28,10 @@ function $9a8aa1b0b336ea3a$export$18fc8428861184da(opts) {
|
|
|
28
28
|
let target = e.target;
|
|
29
29
|
// window is not a Node and doesn't have contain, but window contains everything
|
|
30
30
|
if (!triggerRef.current || target instanceof Node && !target.contains(triggerRef.current)) return;
|
|
31
|
+
// Ignore scroll events on any input or textarea as the cursor position can cause it to scroll
|
|
32
|
+
// such as in a combobox. Clicking the dropdown button places focus on the input, and if the
|
|
33
|
+
// text inside the input extends beyond the 'end', then it will scroll so the cursor is visible at the end.
|
|
34
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
|
|
31
35
|
let onCloseHandler = onClose || $9a8aa1b0b336ea3a$export$f6211563215e3b37.get(triggerRef.current);
|
|
32
36
|
if (onCloseHandler) onCloseHandler();
|
|
33
37
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;AAAA;;;;;;;;;;CAUC;
|
|
1
|
+
{"mappings":";;;;;;;;;AAAA;;;;;;;;;;CAUC;AAUM,MAAM,4CAA2C,IAAI;AASrD,SAAS,0CAAiB,IAA0B;IACzD,IAAI,cAAC,UAAU,UAAE,MAAM,WAAE,OAAO,EAAC,GAAG;IAEpC,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,CAAC,UAAU,YAAY,MACzB;QAGF,IAAI,WAAW,CAAC;YACd,uEAAuE;YACvE,IAAI,SAAS,EAAE,MAAM;YACrB,gFAAgF;YAChF,IAAI,CAAC,WAAW,OAAO,IAAK,AAAC,kBAAkB,QAAS,CAAC,OAAO,QAAQ,CAAC,WAAW,OAAO,GACzF;YAGF,8FAA8F;YAC9F,4FAA4F;YAC5F,2GAA2G;YAC3G,IAAI,EAAE,MAAM,YAAY,oBAAoB,EAAE,MAAM,YAAY,qBAC9D;YAGF,IAAI,iBAAiB,WAAW,0CAAW,GAAG,CAAC,WAAW,OAAO;YACjE,IAAI,gBACF;QAEJ;QAEA,OAAO,gBAAgB,CAAC,UAAU,UAAU;QAC5C,OAAO;YACL,OAAO,mBAAmB,CAAC,UAAU,UAAU;QACjD;IACF,GAAG;QAAC;QAAQ;QAAS;KAAW;AAClC","sources":["packages/@react-aria/overlays/src/useCloseOnScroll.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {RefObject} from '@react-types/shared';\nimport {useEffect} from 'react';\n\n// This behavior moved from useOverlayTrigger to useOverlayPosition.\n// For backward compatibility, where useOverlayTrigger handled hiding the popover on close,\n// it sets a close function here mapped from the trigger element. This way we can avoid\n// forcing users to pass an onClose function to useOverlayPosition which could be considered\n// a breaking change.\nexport const onCloseMap: WeakMap<Element, () => void> = new WeakMap();\n\ninterface CloseOnScrollOptions {\n triggerRef: RefObject<Element | null>,\n isOpen?: boolean,\n onClose?: () => void\n}\n\n/** @private */\nexport function useCloseOnScroll(opts: CloseOnScrollOptions) {\n let {triggerRef, isOpen, onClose} = opts;\n\n useEffect(() => {\n if (!isOpen || onClose === null) {\n return;\n }\n\n let onScroll = (e: MouseEvent) => {\n // Ignore if scrolling an scrollable region outside the trigger's tree.\n let target = e.target;\n // window is not a Node and doesn't have contain, but window contains everything\n if (!triggerRef.current || ((target instanceof Node) && !target.contains(triggerRef.current))) {\n return;\n }\n\n // Ignore scroll events on any input or textarea as the cursor position can cause it to scroll\n // such as in a combobox. Clicking the dropdown button places focus on the input, and if the\n // text inside the input extends beyond the 'end', then it will scroll so the cursor is visible at the end.\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {\n return;\n }\n\n let onCloseHandler = onClose || onCloseMap.get(triggerRef.current);\n if (onCloseHandler) {\n onCloseHandler();\n }\n };\n\n window.addEventListener('scroll', onScroll, true);\n return () => {\n window.removeEventListener('scroll', onScroll, true);\n };\n }, [isOpen, onClose, triggerRef]);\n}\n"],"names":[],"version":3,"file":"useCloseOnScroll.main.js.map"}
|
|
@@ -21,6 +21,10 @@ function $dd149f63282afbbf$export$18fc8428861184da(opts) {
|
|
|
21
21
|
let target = e.target;
|
|
22
22
|
// window is not a Node and doesn't have contain, but window contains everything
|
|
23
23
|
if (!triggerRef.current || target instanceof Node && !target.contains(triggerRef.current)) return;
|
|
24
|
+
// Ignore scroll events on any input or textarea as the cursor position can cause it to scroll
|
|
25
|
+
// such as in a combobox. Clicking the dropdown button places focus on the input, and if the
|
|
26
|
+
// text inside the input extends beyond the 'end', then it will scroll so the cursor is visible at the end.
|
|
27
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
|
|
24
28
|
let onCloseHandler = onClose || $dd149f63282afbbf$export$f6211563215e3b37.get(triggerRef.current);
|
|
25
29
|
if (onCloseHandler) onCloseHandler();
|
|
26
30
|
};
|
|
@@ -21,6 +21,10 @@ function $dd149f63282afbbf$export$18fc8428861184da(opts) {
|
|
|
21
21
|
let target = e.target;
|
|
22
22
|
// window is not a Node and doesn't have contain, but window contains everything
|
|
23
23
|
if (!triggerRef.current || target instanceof Node && !target.contains(triggerRef.current)) return;
|
|
24
|
+
// Ignore scroll events on any input or textarea as the cursor position can cause it to scroll
|
|
25
|
+
// such as in a combobox. Clicking the dropdown button places focus on the input, and if the
|
|
26
|
+
// text inside the input extends beyond the 'end', then it will scroll so the cursor is visible at the end.
|
|
27
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
|
|
24
28
|
let onCloseHandler = onClose || $dd149f63282afbbf$export$f6211563215e3b37.get(triggerRef.current);
|
|
25
29
|
if (onCloseHandler) onCloseHandler();
|
|
26
30
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;AAAA;;;;;;;;;;CAUC;
|
|
1
|
+
{"mappings":";;AAAA;;;;;;;;;;CAUC;AAUM,MAAM,4CAA2C,IAAI;AASrD,SAAS,0CAAiB,IAA0B;IACzD,IAAI,cAAC,UAAU,UAAE,MAAM,WAAE,OAAO,EAAC,GAAG;IAEpC,CAAA,GAAA,gBAAQ,EAAE;QACR,IAAI,CAAC,UAAU,YAAY,MACzB;QAGF,IAAI,WAAW,CAAC;YACd,uEAAuE;YACvE,IAAI,SAAS,EAAE,MAAM;YACrB,gFAAgF;YAChF,IAAI,CAAC,WAAW,OAAO,IAAK,AAAC,kBAAkB,QAAS,CAAC,OAAO,QAAQ,CAAC,WAAW,OAAO,GACzF;YAGF,8FAA8F;YAC9F,4FAA4F;YAC5F,2GAA2G;YAC3G,IAAI,EAAE,MAAM,YAAY,oBAAoB,EAAE,MAAM,YAAY,qBAC9D;YAGF,IAAI,iBAAiB,WAAW,0CAAW,GAAG,CAAC,WAAW,OAAO;YACjE,IAAI,gBACF;QAEJ;QAEA,OAAO,gBAAgB,CAAC,UAAU,UAAU;QAC5C,OAAO;YACL,OAAO,mBAAmB,CAAC,UAAU,UAAU;QACjD;IACF,GAAG;QAAC;QAAQ;QAAS;KAAW;AAClC","sources":["packages/@react-aria/overlays/src/useCloseOnScroll.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {RefObject} from '@react-types/shared';\nimport {useEffect} from 'react';\n\n// This behavior moved from useOverlayTrigger to useOverlayPosition.\n// For backward compatibility, where useOverlayTrigger handled hiding the popover on close,\n// it sets a close function here mapped from the trigger element. This way we can avoid\n// forcing users to pass an onClose function to useOverlayPosition which could be considered\n// a breaking change.\nexport const onCloseMap: WeakMap<Element, () => void> = new WeakMap();\n\ninterface CloseOnScrollOptions {\n triggerRef: RefObject<Element | null>,\n isOpen?: boolean,\n onClose?: () => void\n}\n\n/** @private */\nexport function useCloseOnScroll(opts: CloseOnScrollOptions) {\n let {triggerRef, isOpen, onClose} = opts;\n\n useEffect(() => {\n if (!isOpen || onClose === null) {\n return;\n }\n\n let onScroll = (e: MouseEvent) => {\n // Ignore if scrolling an scrollable region outside the trigger's tree.\n let target = e.target;\n // window is not a Node and doesn't have contain, but window contains everything\n if (!triggerRef.current || ((target instanceof Node) && !target.contains(triggerRef.current))) {\n return;\n }\n\n // Ignore scroll events on any input or textarea as the cursor position can cause it to scroll\n // such as in a combobox. Clicking the dropdown button places focus on the input, and if the\n // text inside the input extends beyond the 'end', then it will scroll so the cursor is visible at the end.\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {\n return;\n }\n\n let onCloseHandler = onClose || onCloseMap.get(triggerRef.current);\n if (onCloseHandler) {\n onCloseHandler();\n }\n };\n\n window.addEventListener('scroll', onScroll, true);\n return () => {\n window.removeEventListener('scroll', onScroll, true);\n };\n }, [isOpen, onClose, triggerRef]);\n}\n"],"names":[],"version":3,"file":"useCloseOnScroll.module.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;AAmCM,SAAS,0CAAgB,KAA4B,EAAE,KAA0B,EAAE,
|
|
1
|
+
{"mappings":";;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;AAmCM,SAAS,0CAAgB,KAA4B,EAAE,KAA0B,EAAE,GAAkC;IAC1H,IAAI,gBAAC,YAAY,iBAAE,aAAa,EAAC,GAAG,CAAA,GAAA,oCAAS,EAAE;QAC7C,GAAG,KAAK;QACR,QAAQ,MAAM,MAAM;QACpB,SAAS,MAAM,KAAK;IACtB,GAAG;IAEH,CAAA,GAAA,0CAAe,EAAE;QACf,YAAY,CAAC,MAAM,MAAM;IAC3B;IAEA,CAAA,GAAA,gDAAqB;IAErB,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,MAAM,MAAM,EACd,OAAO,CAAA,GAAA,yCAAc,EAAE;YAAC,IAAI,OAAO;SAAC;IAExC,GAAG;QAAC,MAAM,MAAM;QAAE;KAAI;IAEtB,OAAO;QACL,YAAY,CAAA,GAAA,gCAAS,EAAE;uBACvB;IACF;AACF","sources":["packages/@react-aria/overlays/src/useModalOverlay.ts"],"sourcesContent":["/*\n * Copyright 2022 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {ariaHideOutside} from './ariaHideOutside';\nimport {AriaOverlayProps, useOverlay} from './useOverlay';\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {mergeProps} from '@react-aria/utils';\nimport {OverlayTriggerState} from '@react-stately/overlays';\nimport {useEffect} from 'react';\nimport {useOverlayFocusContain} from './Overlay';\nimport {usePreventScroll} from './usePreventScroll';\n\nexport interface AriaModalOverlayProps extends Pick<AriaOverlayProps, 'shouldCloseOnInteractOutside'> {\n /**\n * Whether to close the modal when the user interacts outside it.\n * @default false\n */\n isDismissable?: boolean,\n /**\n * Whether pressing the escape key to close the modal should be disabled.\n * @default false\n */\n isKeyboardDismissDisabled?: boolean\n}\n\nexport interface ModalOverlayAria {\n /** Props for the modal element. */\n modalProps: DOMAttributes,\n /** Props for the underlay element. */\n underlayProps: DOMAttributes\n}\n\n/**\n * Provides the behavior and accessibility implementation for a modal component.\n * A modal is an overlay element which blocks interaction with elements outside it.\n */\nexport function useModalOverlay(props: AriaModalOverlayProps, state: OverlayTriggerState, ref: RefObject<HTMLElement | null>): ModalOverlayAria {\n let {overlayProps, underlayProps} = useOverlay({\n ...props,\n isOpen: state.isOpen,\n onClose: state.close\n }, ref);\n\n usePreventScroll({\n isDisabled: !state.isOpen\n });\n\n useOverlayFocusContain();\n\n useEffect(() => {\n if (state.isOpen) {\n return ariaHideOutside([ref.current]);\n }\n }, [state.isOpen, ref]);\n\n return {\n modalProps: mergeProps(overlayProps),\n underlayProps\n };\n}\n"],"names":[],"version":3,"file":"useModalOverlay.main.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;AAmCM,SAAS,0CAAgB,KAA4B,EAAE,KAA0B,EAAE,
|
|
1
|
+
{"mappings":";;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;AAmCM,SAAS,0CAAgB,KAA4B,EAAE,KAA0B,EAAE,GAAkC;IAC1H,IAAI,gBAAC,YAAY,iBAAE,aAAa,EAAC,GAAG,CAAA,GAAA,yCAAS,EAAE;QAC7C,GAAG,KAAK;QACR,QAAQ,MAAM,MAAM;QACpB,SAAS,MAAM,KAAK;IACtB,GAAG;IAEH,CAAA,GAAA,yCAAe,EAAE;QACf,YAAY,CAAC,MAAM,MAAM;IAC3B;IAEA,CAAA,GAAA,yCAAqB;IAErB,CAAA,GAAA,gBAAQ,EAAE;QACR,IAAI,MAAM,MAAM,EACd,OAAO,CAAA,GAAA,yCAAc,EAAE;YAAC,IAAI,OAAO;SAAC;IAExC,GAAG;QAAC,MAAM,MAAM;QAAE;KAAI;IAEtB,OAAO;QACL,YAAY,CAAA,GAAA,iBAAS,EAAE;uBACvB;IACF;AACF","sources":["packages/@react-aria/overlays/src/useModalOverlay.ts"],"sourcesContent":["/*\n * Copyright 2022 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {ariaHideOutside} from './ariaHideOutside';\nimport {AriaOverlayProps, useOverlay} from './useOverlay';\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {mergeProps} from '@react-aria/utils';\nimport {OverlayTriggerState} from '@react-stately/overlays';\nimport {useEffect} from 'react';\nimport {useOverlayFocusContain} from './Overlay';\nimport {usePreventScroll} from './usePreventScroll';\n\nexport interface AriaModalOverlayProps extends Pick<AriaOverlayProps, 'shouldCloseOnInteractOutside'> {\n /**\n * Whether to close the modal when the user interacts outside it.\n * @default false\n */\n isDismissable?: boolean,\n /**\n * Whether pressing the escape key to close the modal should be disabled.\n * @default false\n */\n isKeyboardDismissDisabled?: boolean\n}\n\nexport interface ModalOverlayAria {\n /** Props for the modal element. */\n modalProps: DOMAttributes,\n /** Props for the underlay element. */\n underlayProps: DOMAttributes\n}\n\n/**\n * Provides the behavior and accessibility implementation for a modal component.\n * A modal is an overlay element which blocks interaction with elements outside it.\n */\nexport function useModalOverlay(props: AriaModalOverlayProps, state: OverlayTriggerState, ref: RefObject<HTMLElement | null>): ModalOverlayAria {\n let {overlayProps, underlayProps} = useOverlay({\n ...props,\n isOpen: state.isOpen,\n onClose: state.close\n }, ref);\n\n usePreventScroll({\n isDisabled: !state.isOpen\n });\n\n useOverlayFocusContain();\n\n useEffect(() => {\n if (state.isOpen) {\n return ariaHideOutside([ref.current]);\n }\n }, [state.isOpen, ref]);\n\n return {\n modalProps: mergeProps(overlayProps),\n underlayProps\n };\n}\n"],"names":[],"version":3,"file":"useModalOverlay.module.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;AA6CD,MAAM,
|
|
1
|
+
{"mappings":";;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;AA6CD,MAAM,wCAA+C,EAAE;AAOhD,SAAS,0CAAW,KAAuB,EAAE,GAA8B;IAChF,IAAI,WACF,OAAO,qBACP,iBAAiB,UACjB,MAAM,iBACN,gBAAgB,kCAChB,4BAA4B,qCAC5B,4BAA4B,EAC7B,GAAG;IAEJ,wFAAwF;IACxF,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,QACF,sCAAgB,IAAI,CAAC;QAGvB,OAAO;YACL,IAAI,QAAQ,sCAAgB,OAAO,CAAC;YACpC,IAAI,SAAS,GACX,sCAAgB,MAAM,CAAC,OAAO;QAElC;IACF,GAAG;QAAC;QAAQ;KAAI;IAEhB,4EAA4E;IAC5E,IAAI,SAAS;QACX,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,OAAO,SACzD;IAEJ;IAEA,IAAI,yBAAyB,CAAC;QAC5B,IAAI,CAAC,gCAAgC,6BAA6B,EAAE,MAAM,GACxE;YAAA,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,KAAK;gBACvD,EAAE,eAAe;gBACjB,EAAE,cAAc;YAClB;QAAA;IAEJ;IAEA,IAAI,oBAAoB,CAAC;QACvB,IAAI,CAAC,gCAAgC,6BAA6B,EAAE,MAAM,GAAc;YACtF,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,KAAK;gBACvD,EAAE,eAAe;gBACjB,EAAE,cAAc;YAClB;YACA;QACF;IACF;IAEA,wBAAwB;IACxB,IAAI,YAAY,CAAC;QACf,IAAI,EAAE,GAAG,KAAK,YAAY,CAAC,6BAA6B,CAAC,EAAE,WAAW,CAAC,WAAW,EAAE;YAClF,EAAE,eAAe;YACjB,EAAE,cAAc;YAChB;QACF;IACF;IAEA,kDAAkD;IAClD,CAAA,GAAA,+CAAiB,EAAE;aAAC;QAAK,mBAAmB,iBAAiB,SAAS,oBAAoB;gCAAM;IAAsB;IAEtH,IAAI,oBAAC,gBAAgB,EAAC,GAAG,CAAA,GAAA,2CAAa,EAAE;QACtC,YAAY,CAAC;QACb,cAAc,CAAC;YACb,gFAAgF;YAChF,8GAA8G;YAC9G,6FAA6F;YAC7F,sDAAsD;YACtD,sDAAsD;YACtD,EAAE;YACF,2EAA2E;YAC3E,yEAAyE;YACzE,kEAAkE;YAClE,IAAI,CAAC,EAAE,aAAa,IAAI,CAAA,GAAA,mDAA4B,EAAE,EAAE,aAAa,GACnE;YAGF,IAAI,CAAC,gCAAgC,6BAA6B,EAAE,aAAa,GAC/E;QAEJ;IACF;IAEA,IAAI,wBAAwB,CAAA;QAC1B,wGAAwG;QACxG,IAAI,EAAE,MAAM,KAAK,EAAE,aAAa,EAC9B,EAAE,cAAc;IAEpB;IAEA,OAAO;QACL,cAAc;uBACZ;YACA,GAAG,gBAAgB;QACrB;QACA,eAAe;YACb,eAAe;QACjB;IACF;AACF","sources":["packages/@react-aria/overlays/src/useOverlay.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {isElementInChildOfActiveScope} from '@react-aria/focus';\nimport {useEffect} from 'react';\nimport {useFocusWithin, useInteractOutside} from '@react-aria/interactions';\n\nexport interface AriaOverlayProps {\n /** Whether the overlay is currently open. */\n isOpen?: boolean,\n\n /** Handler that is called when the overlay should close. */\n onClose?: () => void,\n\n /**\n * Whether to close the overlay when the user interacts outside it.\n * @default false\n */\n isDismissable?: boolean,\n\n /** Whether the overlay should close when focus is lost or moves outside it. */\n shouldCloseOnBlur?: boolean,\n\n /**\n * Whether pressing the escape key to close the overlay should be disabled.\n * @default false\n */\n isKeyboardDismissDisabled?: boolean,\n\n /**\n * When user interacts with the argument element outside of the overlay ref,\n * return true if onClose should be called. This gives you a chance to filter\n * out interaction with elements that should not dismiss the overlay.\n * By default, onClose will always be called on interaction outside the overlay ref.\n */\n shouldCloseOnInteractOutside?: (element: Element) => boolean\n}\n\nexport interface OverlayAria {\n /** Props to apply to the overlay container element. */\n overlayProps: DOMAttributes,\n /** Props to apply to the underlay element, if any. */\n underlayProps: DOMAttributes\n}\n\nconst visibleOverlays: RefObject<Element | null>[] = [];\n\n/**\n * Provides the behavior for overlays such as dialogs, popovers, and menus.\n * Hides the overlay when the user interacts outside it, when the Escape key is pressed,\n * or optionally, on blur. Only the top-most overlay will close at once.\n */\nexport function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | null>): OverlayAria {\n let {\n onClose,\n shouldCloseOnBlur,\n isOpen,\n isDismissable = false,\n isKeyboardDismissDisabled = false,\n shouldCloseOnInteractOutside\n } = props;\n\n // Add the overlay ref to the stack of visible overlays on mount, and remove on unmount.\n useEffect(() => {\n if (isOpen) {\n visibleOverlays.push(ref);\n }\n\n return () => {\n let index = visibleOverlays.indexOf(ref);\n if (index >= 0) {\n visibleOverlays.splice(index, 1);\n }\n };\n }, [isOpen, ref]);\n\n // Only hide the overlay when it is the topmost visible overlay in the stack\n let onHide = () => {\n if (visibleOverlays[visibleOverlays.length - 1] === ref && onClose) {\n onClose();\n }\n };\n\n let onInteractOutsideStart = (e: PointerEvent) => {\n if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(e.target as Element)) {\n if (visibleOverlays[visibleOverlays.length - 1] === ref) {\n e.stopPropagation();\n e.preventDefault();\n }\n }\n };\n\n let onInteractOutside = (e: PointerEvent) => {\n if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(e.target as Element)) {\n if (visibleOverlays[visibleOverlays.length - 1] === ref) {\n e.stopPropagation();\n e.preventDefault();\n }\n onHide();\n }\n };\n\n // Handle the escape key\n let onKeyDown = (e) => {\n if (e.key === 'Escape' && !isKeyboardDismissDisabled && !e.nativeEvent.isComposing) {\n e.stopPropagation();\n e.preventDefault();\n onHide();\n }\n };\n\n // Handle clicking outside the overlay to close it\n useInteractOutside({ref, onInteractOutside: isDismissable && isOpen ? onInteractOutside : null, onInteractOutsideStart});\n\n let {focusWithinProps} = useFocusWithin({\n isDisabled: !shouldCloseOnBlur,\n onBlurWithin: (e) => {\n // Do not close if relatedTarget is null, which means focus is lost to the body.\n // That can happen when switching tabs, or due to a VoiceOver/Chrome bug with Control+Option+Arrow navigation.\n // Clicking on the body to close the overlay should already be handled by useInteractOutside.\n // https://github.com/adobe/react-spectrum/issues/4130\n // https://github.com/adobe/react-spectrum/issues/4922\n //\n // If focus is moving into a child focus scope (e.g. menu inside a dialog),\n // do not close the outer overlay. At this point, the active scope should\n // still be the outer overlay, since blur events run before focus.\n if (!e.relatedTarget || isElementInChildOfActiveScope(e.relatedTarget)) {\n return;\n }\n\n if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(e.relatedTarget as Element)) {\n onClose();\n }\n }\n });\n\n let onPointerDownUnderlay = e => {\n // fixes a firefox issue that starts text selection https://bugzilla.mozilla.org/show_bug.cgi?id=1675846\n if (e.target === e.currentTarget) {\n e.preventDefault();\n }\n };\n\n return {\n overlayProps: {\n onKeyDown,\n ...focusWithinProps\n },\n underlayProps: {\n onPointerDown: onPointerDownUnderlay\n }\n };\n}\n"],"names":[],"version":3,"file":"useOverlay.main.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;AAAA;;;;;;;;;;CAUC;;;AA6CD,MAAM,
|
|
1
|
+
{"mappings":";;;;AAAA;;;;;;;;;;CAUC;;;AA6CD,MAAM,wCAA+C,EAAE;AAOhD,SAAS,0CAAW,KAAuB,EAAE,GAA8B;IAChF,IAAI,WACF,OAAO,qBACP,iBAAiB,UACjB,MAAM,iBACN,gBAAgB,kCAChB,4BAA4B,qCAC5B,4BAA4B,EAC7B,GAAG;IAEJ,wFAAwF;IACxF,CAAA,GAAA,gBAAQ,EAAE;QACR,IAAI,QACF,sCAAgB,IAAI,CAAC;QAGvB,OAAO;YACL,IAAI,QAAQ,sCAAgB,OAAO,CAAC;YACpC,IAAI,SAAS,GACX,sCAAgB,MAAM,CAAC,OAAO;QAElC;IACF,GAAG;QAAC;QAAQ;KAAI;IAEhB,4EAA4E;IAC5E,IAAI,SAAS;QACX,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,OAAO,SACzD;IAEJ;IAEA,IAAI,yBAAyB,CAAC;QAC5B,IAAI,CAAC,gCAAgC,6BAA6B,EAAE,MAAM,GACxE;YAAA,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,KAAK;gBACvD,EAAE,eAAe;gBACjB,EAAE,cAAc;YAClB;QAAA;IAEJ;IAEA,IAAI,oBAAoB,CAAC;QACvB,IAAI,CAAC,gCAAgC,6BAA6B,EAAE,MAAM,GAAc;YACtF,IAAI,qCAAe,CAAC,sCAAgB,MAAM,GAAG,EAAE,KAAK,KAAK;gBACvD,EAAE,eAAe;gBACjB,EAAE,cAAc;YAClB;YACA;QACF;IACF;IAEA,wBAAwB;IACxB,IAAI,YAAY,CAAC;QACf,IAAI,EAAE,GAAG,KAAK,YAAY,CAAC,6BAA6B,CAAC,EAAE,WAAW,CAAC,WAAW,EAAE;YAClF,EAAE,eAAe;YACjB,EAAE,cAAc;YAChB;QACF;IACF;IAEA,kDAAkD;IAClD,CAAA,GAAA,yBAAiB,EAAE;aAAC;QAAK,mBAAmB,iBAAiB,SAAS,oBAAoB;gCAAM;IAAsB;IAEtH,IAAI,oBAAC,gBAAgB,EAAC,GAAG,CAAA,GAAA,qBAAa,EAAE;QACtC,YAAY,CAAC;QACb,cAAc,CAAC;YACb,gFAAgF;YAChF,8GAA8G;YAC9G,6FAA6F;YAC7F,sDAAsD;YACtD,sDAAsD;YACtD,EAAE;YACF,2EAA2E;YAC3E,yEAAyE;YACzE,kEAAkE;YAClE,IAAI,CAAC,EAAE,aAAa,IAAI,CAAA,GAAA,oCAA4B,EAAE,EAAE,aAAa,GACnE;YAGF,IAAI,CAAC,gCAAgC,6BAA6B,EAAE,aAAa,GAC/E;QAEJ;IACF;IAEA,IAAI,wBAAwB,CAAA;QAC1B,wGAAwG;QACxG,IAAI,EAAE,MAAM,KAAK,EAAE,aAAa,EAC9B,EAAE,cAAc;IAEpB;IAEA,OAAO;QACL,cAAc;uBACZ;YACA,GAAG,gBAAgB;QACrB;QACA,eAAe;YACb,eAAe;QACjB;IACF;AACF","sources":["packages/@react-aria/overlays/src/useOverlay.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {isElementInChildOfActiveScope} from '@react-aria/focus';\nimport {useEffect} from 'react';\nimport {useFocusWithin, useInteractOutside} from '@react-aria/interactions';\n\nexport interface AriaOverlayProps {\n /** Whether the overlay is currently open. */\n isOpen?: boolean,\n\n /** Handler that is called when the overlay should close. */\n onClose?: () => void,\n\n /**\n * Whether to close the overlay when the user interacts outside it.\n * @default false\n */\n isDismissable?: boolean,\n\n /** Whether the overlay should close when focus is lost or moves outside it. */\n shouldCloseOnBlur?: boolean,\n\n /**\n * Whether pressing the escape key to close the overlay should be disabled.\n * @default false\n */\n isKeyboardDismissDisabled?: boolean,\n\n /**\n * When user interacts with the argument element outside of the overlay ref,\n * return true if onClose should be called. This gives you a chance to filter\n * out interaction with elements that should not dismiss the overlay.\n * By default, onClose will always be called on interaction outside the overlay ref.\n */\n shouldCloseOnInteractOutside?: (element: Element) => boolean\n}\n\nexport interface OverlayAria {\n /** Props to apply to the overlay container element. */\n overlayProps: DOMAttributes,\n /** Props to apply to the underlay element, if any. */\n underlayProps: DOMAttributes\n}\n\nconst visibleOverlays: RefObject<Element | null>[] = [];\n\n/**\n * Provides the behavior for overlays such as dialogs, popovers, and menus.\n * Hides the overlay when the user interacts outside it, when the Escape key is pressed,\n * or optionally, on blur. Only the top-most overlay will close at once.\n */\nexport function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | null>): OverlayAria {\n let {\n onClose,\n shouldCloseOnBlur,\n isOpen,\n isDismissable = false,\n isKeyboardDismissDisabled = false,\n shouldCloseOnInteractOutside\n } = props;\n\n // Add the overlay ref to the stack of visible overlays on mount, and remove on unmount.\n useEffect(() => {\n if (isOpen) {\n visibleOverlays.push(ref);\n }\n\n return () => {\n let index = visibleOverlays.indexOf(ref);\n if (index >= 0) {\n visibleOverlays.splice(index, 1);\n }\n };\n }, [isOpen, ref]);\n\n // Only hide the overlay when it is the topmost visible overlay in the stack\n let onHide = () => {\n if (visibleOverlays[visibleOverlays.length - 1] === ref && onClose) {\n onClose();\n }\n };\n\n let onInteractOutsideStart = (e: PointerEvent) => {\n if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(e.target as Element)) {\n if (visibleOverlays[visibleOverlays.length - 1] === ref) {\n e.stopPropagation();\n e.preventDefault();\n }\n }\n };\n\n let onInteractOutside = (e: PointerEvent) => {\n if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(e.target as Element)) {\n if (visibleOverlays[visibleOverlays.length - 1] === ref) {\n e.stopPropagation();\n e.preventDefault();\n }\n onHide();\n }\n };\n\n // Handle the escape key\n let onKeyDown = (e) => {\n if (e.key === 'Escape' && !isKeyboardDismissDisabled && !e.nativeEvent.isComposing) {\n e.stopPropagation();\n e.preventDefault();\n onHide();\n }\n };\n\n // Handle clicking outside the overlay to close it\n useInteractOutside({ref, onInteractOutside: isDismissable && isOpen ? onInteractOutside : null, onInteractOutsideStart});\n\n let {focusWithinProps} = useFocusWithin({\n isDisabled: !shouldCloseOnBlur,\n onBlurWithin: (e) => {\n // Do not close if relatedTarget is null, which means focus is lost to the body.\n // That can happen when switching tabs, or due to a VoiceOver/Chrome bug with Control+Option+Arrow navigation.\n // Clicking on the body to close the overlay should already be handled by useInteractOutside.\n // https://github.com/adobe/react-spectrum/issues/4130\n // https://github.com/adobe/react-spectrum/issues/4922\n //\n // If focus is moving into a child focus scope (e.g. menu inside a dialog),\n // do not close the outer overlay. At this point, the active scope should\n // still be the outer overlay, since blur events run before focus.\n if (!e.relatedTarget || isElementInChildOfActiveScope(e.relatedTarget)) {\n return;\n }\n\n if (!shouldCloseOnInteractOutside || shouldCloseOnInteractOutside(e.relatedTarget as Element)) {\n onClose();\n }\n }\n });\n\n let onPointerDownUnderlay = e => {\n // fixes a firefox issue that starts text selection https://bugzilla.mozilla.org/show_bug.cgi?id=1675846\n if (e.target === e.currentTarget) {\n e.preventDefault();\n }\n };\n\n return {\n overlayProps: {\n onKeyDown,\n ...focusWithinProps\n },\n underlayProps: {\n onPointerDown: onPointerDownUnderlay\n }\n };\n}\n"],"names":[],"version":3,"file":"useOverlay.module.js.map"}
|
|
@@ -64,8 +64,27 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
|
|
|
64
64
|
isOpen
|
|
65
65
|
]);
|
|
66
66
|
let updatePosition = (0, $6TXnl$react.useCallback)(()=>{
|
|
67
|
-
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !
|
|
67
|
+
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !boundaryElement) return;
|
|
68
68
|
if (($cd94b4896dd97759$var$visualViewport === null || $cd94b4896dd97759$var$visualViewport === void 0 ? void 0 : $cd94b4896dd97759$var$visualViewport.scale) !== lastScale.current) return;
|
|
69
|
+
// Determine a scroll anchor based on the focused element.
|
|
70
|
+
// This stores the offset of the anchor element from the scroll container
|
|
71
|
+
// so it can be restored after repositioning. This way if the overlay height
|
|
72
|
+
// changes, the focused element appears to stay in the same position.
|
|
73
|
+
let anchor = null;
|
|
74
|
+
if (scrollRef.current && scrollRef.current.contains(document.activeElement)) {
|
|
75
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
76
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
77
|
+
// Anchor from the top if the offset is in the top half of the scrollable element,
|
|
78
|
+
// otherwise anchor from the bottom.
|
|
79
|
+
anchor = {
|
|
80
|
+
type: 'top',
|
|
81
|
+
offset: anchorRect.top - scrollRect.top
|
|
82
|
+
};
|
|
83
|
+
if (anchor.offset > scrollRect.height / 2) {
|
|
84
|
+
anchor.type = 'bottom';
|
|
85
|
+
anchor.offset = anchorRect.bottom - scrollRect.bottom;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
69
88
|
// Always reset the overlay's previous max height if not defined by the user so that we can compensate for
|
|
70
89
|
// RAC collections populating after a second render and properly set a correct max height + positioning when it populates.
|
|
71
90
|
let overlay = overlayRef.current;
|
|
@@ -80,7 +99,7 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
|
|
|
80
99
|
placement: $cd94b4896dd97759$var$translateRTL(placement, direction),
|
|
81
100
|
overlayNode: overlayRef.current,
|
|
82
101
|
targetNode: targetRef.current,
|
|
83
|
-
scrollNode: scrollRef.current,
|
|
102
|
+
scrollNode: scrollRef.current || overlayRef.current,
|
|
84
103
|
padding: containerPadding,
|
|
85
104
|
shouldFlip: shouldFlip,
|
|
86
105
|
boundaryElement: boundaryElement,
|
|
@@ -94,8 +113,17 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
|
|
|
94
113
|
// This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers
|
|
95
114
|
overlay.style.top = '';
|
|
96
115
|
overlay.style.bottom = '';
|
|
116
|
+
overlay.style.left = '';
|
|
117
|
+
overlay.style.right = '';
|
|
97
118
|
Object.keys(position.position).forEach((key)=>overlay.style[key] = position.position[key] + 'px');
|
|
98
119
|
overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;
|
|
120
|
+
// Restore scroll position relative to anchor element.
|
|
121
|
+
if (anchor) {
|
|
122
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
123
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
124
|
+
let newOffset = anchorRect[anchor.type] - scrollRect[anchor.type];
|
|
125
|
+
scrollRef.current.scrollTop += newOffset - anchor.offset;
|
|
126
|
+
}
|
|
99
127
|
// Trigger a set state for a second render anyway for arrow positioning
|
|
100
128
|
setPosition(position);
|
|
101
129
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -110,6 +138,11 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
|
|
|
110
138
|
ref: overlayRef,
|
|
111
139
|
onResize: updatePosition
|
|
112
140
|
});
|
|
141
|
+
// Update position when the target changes size (might need to flip).
|
|
142
|
+
(0, $6TXnl$reactariautils.useResizeObserver)({
|
|
143
|
+
ref: targetRef,
|
|
144
|
+
onResize: updatePosition
|
|
145
|
+
});
|
|
113
146
|
// Reposition the overlay and do not close on scroll while the visual viewport is resizing.
|
|
114
147
|
// This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.
|
|
115
148
|
let isResizing = (0, $6TXnl$react.useRef)(false);
|
|
@@ -150,13 +183,14 @@ function $cd94b4896dd97759$export$d39e1813b3bdd0e1(props) {
|
|
|
150
183
|
isOpen: isOpen,
|
|
151
184
|
onClose: onClose && close
|
|
152
185
|
});
|
|
186
|
+
var _position_maxHeight;
|
|
153
187
|
return {
|
|
154
188
|
overlayProps: {
|
|
155
189
|
style: {
|
|
156
190
|
position: 'absolute',
|
|
157
191
|
zIndex: 100000,
|
|
158
192
|
...position.position,
|
|
159
|
-
maxHeight: position.maxHeight
|
|
193
|
+
maxHeight: (_position_maxHeight = position.maxHeight) !== null && _position_maxHeight !== void 0 ? _position_maxHeight : '100vh'
|
|
160
194
|
}
|
|
161
195
|
},
|
|
162
196
|
placement: position.placement,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/@react-aria/overlays/src/useOverlayPosition.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {calculatePosition, PositionResult} from './calculatePosition';\nimport {DOMAttributes} from '@react-types/shared';\nimport {Placement, PlacementAxis, PositionProps} from '@react-types/overlays';\nimport {RefObject, useCallback, useEffect, useRef, useState} from 'react';\nimport {useCloseOnScroll} from './useCloseOnScroll';\nimport {useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface AriaPositionProps extends PositionProps {\n /**\n * Cross size of the overlay arrow in pixels.\n * @default 0\n */\n arrowSize?: number,\n /**\n * Element that that serves as the positioning boundary.\n * @default document.body\n */\n boundaryElement?: Element,\n /**\n * The ref for the element which the overlay positions itself with respect to.\n */\n targetRef: RefObject<Element>,\n /**\n * The ref for the overlay element.\n */\n overlayRef: RefObject<Element>,\n /**\n * A ref for the scrollable region within the overlay.\n * @default overlayRef\n */\n scrollRef?: RefObject<Element>,\n /**\n * Whether the overlay should update its position automatically.\n * @default true\n */\n shouldUpdatePosition?: boolean,\n /** Handler that is called when the overlay should close. */\n onClose?: () => void,\n /**\n * The maxHeight specified for the overlay element.\n * By default, it will take all space up to the current viewport height.\n */\n maxHeight?: number,\n /**\n * The minimum distance the arrow's edge should be from the edge of the overlay element.\n * @default 0\n */\n arrowBoundaryOffset?: number\n}\n\nexport interface PositionAria {\n /** Props for the overlay container element. */\n overlayProps: DOMAttributes,\n /** Props for the overlay tip arrow if any. */\n arrowProps: DOMAttributes,\n /** Placement of the overlay with respect to the overlay trigger. */\n placement: PlacementAxis,\n /** Updates the position of the overlay. */\n updatePosition(): void\n}\n\n// @ts-ignore\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\n/**\n * Handles positioning overlays like popovers and menus relative to a trigger\n * element, and updating the position when the window resizes.\n */\nexport function useOverlayPosition(props: AriaPositionProps): PositionAria {\n let {direction} = useLocale();\n let {\n arrowSize = 0,\n targetRef,\n overlayRef,\n scrollRef = overlayRef,\n placement = 'bottom' as Placement,\n containerPadding = 12,\n shouldFlip = true,\n boundaryElement = typeof document !== 'undefined' ? document.body : null,\n offset = 0,\n crossOffset = 0,\n shouldUpdatePosition = true,\n isOpen = true,\n onClose,\n maxHeight,\n arrowBoundaryOffset = 0\n } = props;\n let [position, setPosition] = useState<PositionResult>({\n position: {},\n arrowOffsetLeft: undefined,\n arrowOffsetTop: undefined,\n maxHeight: undefined,\n placement: undefined\n });\n\n let deps = [\n shouldUpdatePosition,\n placement,\n overlayRef.current,\n targetRef.current,\n scrollRef.current,\n containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n isOpen,\n direction,\n maxHeight,\n arrowBoundaryOffset,\n arrowSize\n ];\n\n // Note, the position freezing breaks if body sizes itself dynamicly with the visual viewport but that might\n // just be a non-realistic use case\n // Upon opening a overlay, record the current visual viewport scale so we can freeze the overlay styles\n let lastScale = useRef(visualViewport?.scale);\n useEffect(() => {\n if (isOpen) {\n lastScale.current = visualViewport?.scale;\n }\n }, [isOpen]);\n\n let updatePosition = useCallback(() => {\n if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current || !boundaryElement) {\n return;\n }\n\n if (visualViewport?.scale !== lastScale.current) {\n return;\n }\n\n // Always reset the overlay's previous max height if not defined by the user so that we can compensate for\n // RAC collections populating after a second render and properly set a correct max height + positioning when it populates.\n let overlay = (overlayRef.current as HTMLElement);\n if (!maxHeight && overlayRef.current) {\n overlay.style.top = '0px';\n overlay.style.bottom = '';\n overlay.style.maxHeight = (window.visualViewport?.height ?? window.innerHeight) + 'px';\n }\n\n let position = calculatePosition({\n placement: translateRTL(placement, direction),\n overlayNode: overlayRef.current,\n targetNode: targetRef.current,\n scrollNode: scrollRef.current,\n padding: containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n maxHeight,\n arrowSize,\n arrowBoundaryOffset\n });\n\n // Modify overlay styles directly so positioning happens immediately without the need of a second render\n // This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers\n overlay.style.top = '';\n overlay.style.bottom = '';\n Object.keys(position.position).forEach(key => overlay.style[key] = position.position[key] + 'px');\n overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;\n\n // Trigger a set state for a second render anyway for arrow positioning\n setPosition(position);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n // Update position when anything changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(updatePosition, deps);\n\n // Update position on window resize\n useResize(updatePosition);\n\n // Update position when the overlay changes size (might need to flip).\n useResizeObserver({\n ref: overlayRef,\n onResize: updatePosition\n });\n\n // Reposition the overlay and do not close on scroll while the visual viewport is resizing.\n // This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.\n let isResizing = useRef(false);\n useLayoutEffect(() => {\n let timeout: ReturnType<typeof setTimeout>;\n let onResize = () => {\n isResizing.current = true;\n clearTimeout(timeout);\n\n timeout = setTimeout(() => {\n isResizing.current = false;\n }, 500);\n\n updatePosition();\n };\n\n // Only reposition the overlay if a scroll event happens immediately as a result of resize (aka the virtual keyboard has appears)\n // We don't want to reposition the overlay if the user has pinch zoomed in and is scrolling the viewport around.\n let onScroll = () => {\n if (isResizing.current) {\n onResize();\n }\n };\n\n visualViewport?.addEventListener('resize', onResize);\n visualViewport?.addEventListener('scroll', onScroll);\n return () => {\n visualViewport?.removeEventListener('resize', onResize);\n visualViewport?.removeEventListener('scroll', onScroll);\n };\n }, [updatePosition]);\n\n let close = useCallback(() => {\n if (!isResizing.current) {\n onClose();\n }\n }, [onClose, isResizing]);\n\n // When scrolling a parent scrollable region of the trigger (other than the body),\n // we hide the popover. Otherwise, its position would be incorrect.\n useCloseOnScroll({\n triggerRef: targetRef,\n isOpen,\n onClose: onClose && close\n });\n\n return {\n overlayProps: {\n style: {\n position: 'absolute',\n zIndex: 100000, // should match the z-index in ModalTrigger\n ...position.position,\n maxHeight: position.maxHeight\n }\n },\n placement: position.placement,\n arrowProps: {\n 'aria-hidden': 'true',\n role: 'presentation',\n style: {\n left: position.arrowOffsetLeft,\n top: position.arrowOffsetTop\n }\n },\n updatePosition\n };\n}\n\nfunction useResize(onResize) {\n useLayoutEffect(() => {\n window.addEventListener('resize', onResize, false);\n return () => {\n window.removeEventListener('resize', onResize, false);\n };\n }, [onResize]);\n}\n\nfunction translateRTL(position, direction) {\n if (direction === 'rtl') {\n return position.replace('start', 'right').replace('end', 'left');\n }\n return position.replace('start', 'left').replace('end', 'right');\n}\n"],"names":[],"version":3,"file":"useOverlayPosition.main.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/overlays/src/useOverlayPosition.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {calculatePosition, PositionResult} from './calculatePosition';\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {Placement, PlacementAxis, PositionProps} from '@react-types/overlays';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {useCloseOnScroll} from './useCloseOnScroll';\nimport {useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface AriaPositionProps extends PositionProps {\n /**\n * Cross size of the overlay arrow in pixels.\n * @default 0\n */\n arrowSize?: number,\n /**\n * Element that that serves as the positioning boundary.\n * @default document.body\n */\n boundaryElement?: Element,\n /**\n * The ref for the element which the overlay positions itself with respect to.\n */\n targetRef: RefObject<Element | null>,\n /**\n * The ref for the overlay element.\n */\n overlayRef: RefObject<Element | null>,\n /**\n * A ref for the scrollable region within the overlay.\n * @default overlayRef\n */\n scrollRef?: RefObject<Element | null>,\n /**\n * Whether the overlay should update its position automatically.\n * @default true\n */\n shouldUpdatePosition?: boolean,\n /** Handler that is called when the overlay should close. */\n onClose?: () => void,\n /**\n * The maxHeight specified for the overlay element.\n * By default, it will take all space up to the current viewport height.\n */\n maxHeight?: number,\n /**\n * The minimum distance the arrow's edge should be from the edge of the overlay element.\n * @default 0\n */\n arrowBoundaryOffset?: number\n}\n\nexport interface PositionAria {\n /** Props for the overlay container element. */\n overlayProps: DOMAttributes,\n /** Props for the overlay tip arrow if any. */\n arrowProps: DOMAttributes,\n /** Placement of the overlay with respect to the overlay trigger. */\n placement: PlacementAxis,\n /** Updates the position of the overlay. */\n updatePosition(): void\n}\n\ninterface ScrollAnchor {\n type: 'top' | 'bottom',\n offset: number\n}\n\n// @ts-ignore\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\n/**\n * Handles positioning overlays like popovers and menus relative to a trigger\n * element, and updating the position when the window resizes.\n */\nexport function useOverlayPosition(props: AriaPositionProps): PositionAria {\n let {direction} = useLocale();\n let {\n arrowSize = 0,\n targetRef,\n overlayRef,\n scrollRef = overlayRef,\n placement = 'bottom' as Placement,\n containerPadding = 12,\n shouldFlip = true,\n boundaryElement = typeof document !== 'undefined' ? document.body : null,\n offset = 0,\n crossOffset = 0,\n shouldUpdatePosition = true,\n isOpen = true,\n onClose,\n maxHeight,\n arrowBoundaryOffset = 0\n } = props;\n let [position, setPosition] = useState<PositionResult>({\n position: {},\n arrowOffsetLeft: undefined,\n arrowOffsetTop: undefined,\n maxHeight: undefined,\n placement: undefined\n });\n\n let deps = [\n shouldUpdatePosition,\n placement,\n overlayRef.current,\n targetRef.current,\n scrollRef.current,\n containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n isOpen,\n direction,\n maxHeight,\n arrowBoundaryOffset,\n arrowSize\n ];\n\n // Note, the position freezing breaks if body sizes itself dynamicly with the visual viewport but that might\n // just be a non-realistic use case\n // Upon opening a overlay, record the current visual viewport scale so we can freeze the overlay styles\n let lastScale = useRef(visualViewport?.scale);\n useEffect(() => {\n if (isOpen) {\n lastScale.current = visualViewport?.scale;\n }\n }, [isOpen]);\n\n let updatePosition = useCallback(() => {\n if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !boundaryElement) {\n return;\n }\n\n if (visualViewport?.scale !== lastScale.current) {\n return;\n }\n\n // Determine a scroll anchor based on the focused element.\n // This stores the offset of the anchor element from the scroll container\n // so it can be restored after repositioning. This way if the overlay height\n // changes, the focused element appears to stay in the same position.\n let anchor: ScrollAnchor | null = null;\n if (scrollRef.current && scrollRef.current.contains(document.activeElement)) {\n let anchorRect = document.activeElement.getBoundingClientRect();\n let scrollRect = scrollRef.current.getBoundingClientRect();\n // Anchor from the top if the offset is in the top half of the scrollable element,\n // otherwise anchor from the bottom.\n anchor = {\n type: 'top',\n offset: anchorRect.top - scrollRect.top\n };\n if (anchor.offset > scrollRect.height / 2) {\n anchor.type = 'bottom';\n anchor.offset = anchorRect.bottom - scrollRect.bottom;\n }\n }\n\n // Always reset the overlay's previous max height if not defined by the user so that we can compensate for\n // RAC collections populating after a second render and properly set a correct max height + positioning when it populates.\n let overlay = (overlayRef.current as HTMLElement);\n if (!maxHeight && overlayRef.current) {\n overlay.style.top = '0px';\n overlay.style.bottom = '';\n overlay.style.maxHeight = (window.visualViewport?.height ?? window.innerHeight) + 'px';\n }\n\n let position = calculatePosition({\n placement: translateRTL(placement, direction),\n overlayNode: overlayRef.current,\n targetNode: targetRef.current,\n scrollNode: scrollRef.current || overlayRef.current,\n padding: containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n maxHeight,\n arrowSize,\n arrowBoundaryOffset\n });\n\n // Modify overlay styles directly so positioning happens immediately without the need of a second render\n // This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers\n overlay.style.top = '';\n overlay.style.bottom = '';\n overlay.style.left = '';\n overlay.style.right = '';\n\n Object.keys(position.position).forEach(key => overlay.style[key] = position.position[key] + 'px');\n overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;\n\n // Restore scroll position relative to anchor element.\n if (anchor) {\n let anchorRect = document.activeElement.getBoundingClientRect();\n let scrollRect = scrollRef.current.getBoundingClientRect();\n let newOffset = anchorRect[anchor.type] - scrollRect[anchor.type];\n scrollRef.current.scrollTop += newOffset - anchor.offset;\n }\n\n // Trigger a set state for a second render anyway for arrow positioning\n setPosition(position);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n // Update position when anything changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(updatePosition, deps);\n\n // Update position on window resize\n useResize(updatePosition);\n\n // Update position when the overlay changes size (might need to flip).\n useResizeObserver({\n ref: overlayRef,\n onResize: updatePosition\n });\n\n // Update position when the target changes size (might need to flip).\n useResizeObserver({\n ref: targetRef,\n onResize: updatePosition\n });\n\n // Reposition the overlay and do not close on scroll while the visual viewport is resizing.\n // This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.\n let isResizing = useRef(false);\n useLayoutEffect(() => {\n let timeout: ReturnType<typeof setTimeout>;\n let onResize = () => {\n isResizing.current = true;\n clearTimeout(timeout);\n\n timeout = setTimeout(() => {\n isResizing.current = false;\n }, 500);\n\n updatePosition();\n };\n\n // Only reposition the overlay if a scroll event happens immediately as a result of resize (aka the virtual keyboard has appears)\n // We don't want to reposition the overlay if the user has pinch zoomed in and is scrolling the viewport around.\n let onScroll = () => {\n if (isResizing.current) {\n onResize();\n }\n };\n\n visualViewport?.addEventListener('resize', onResize);\n visualViewport?.addEventListener('scroll', onScroll);\n return () => {\n visualViewport?.removeEventListener('resize', onResize);\n visualViewport?.removeEventListener('scroll', onScroll);\n };\n }, [updatePosition]);\n\n let close = useCallback(() => {\n if (!isResizing.current) {\n onClose();\n }\n }, [onClose, isResizing]);\n\n // When scrolling a parent scrollable region of the trigger (other than the body),\n // we hide the popover. Otherwise, its position would be incorrect.\n useCloseOnScroll({\n triggerRef: targetRef,\n isOpen,\n onClose: onClose && close\n });\n\n return {\n overlayProps: {\n style: {\n position: 'absolute',\n zIndex: 100000, // should match the z-index in ModalTrigger\n ...position.position,\n maxHeight: position.maxHeight ?? '100vh'\n }\n },\n placement: position.placement,\n arrowProps: {\n 'aria-hidden': 'true',\n role: 'presentation',\n style: {\n left: position.arrowOffsetLeft,\n top: position.arrowOffsetTop\n }\n },\n updatePosition\n };\n}\n\nfunction useResize(onResize) {\n useLayoutEffect(() => {\n window.addEventListener('resize', onResize, false);\n return () => {\n window.removeEventListener('resize', onResize, false);\n };\n }, [onResize]);\n}\n\nfunction translateRTL(position, direction) {\n if (direction === 'rtl') {\n return position.replace('start', 'right').replace('end', 'left');\n }\n return position.replace('start', 'left').replace('end', 'right');\n}\n"],"names":[],"version":3,"file":"useOverlayPosition.main.js.map"}
|
|
@@ -58,8 +58,27 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
58
58
|
isOpen
|
|
59
59
|
]);
|
|
60
60
|
let updatePosition = (0, $39EOa$useCallback)(()=>{
|
|
61
|
-
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !
|
|
61
|
+
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !boundaryElement) return;
|
|
62
62
|
if (($2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.scale) !== lastScale.current) return;
|
|
63
|
+
// Determine a scroll anchor based on the focused element.
|
|
64
|
+
// This stores the offset of the anchor element from the scroll container
|
|
65
|
+
// so it can be restored after repositioning. This way if the overlay height
|
|
66
|
+
// changes, the focused element appears to stay in the same position.
|
|
67
|
+
let anchor = null;
|
|
68
|
+
if (scrollRef.current && scrollRef.current.contains(document.activeElement)) {
|
|
69
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
70
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
71
|
+
// Anchor from the top if the offset is in the top half of the scrollable element,
|
|
72
|
+
// otherwise anchor from the bottom.
|
|
73
|
+
anchor = {
|
|
74
|
+
type: 'top',
|
|
75
|
+
offset: anchorRect.top - scrollRect.top
|
|
76
|
+
};
|
|
77
|
+
if (anchor.offset > scrollRect.height / 2) {
|
|
78
|
+
anchor.type = 'bottom';
|
|
79
|
+
anchor.offset = anchorRect.bottom - scrollRect.bottom;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
63
82
|
// Always reset the overlay's previous max height if not defined by the user so that we can compensate for
|
|
64
83
|
// RAC collections populating after a second render and properly set a correct max height + positioning when it populates.
|
|
65
84
|
let overlay = overlayRef.current;
|
|
@@ -74,7 +93,7 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
74
93
|
placement: $2a41e45df1593e64$var$translateRTL(placement, direction),
|
|
75
94
|
overlayNode: overlayRef.current,
|
|
76
95
|
targetNode: targetRef.current,
|
|
77
|
-
scrollNode: scrollRef.current,
|
|
96
|
+
scrollNode: scrollRef.current || overlayRef.current,
|
|
78
97
|
padding: containerPadding,
|
|
79
98
|
shouldFlip: shouldFlip,
|
|
80
99
|
boundaryElement: boundaryElement,
|
|
@@ -88,8 +107,17 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
88
107
|
// This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers
|
|
89
108
|
overlay.style.top = '';
|
|
90
109
|
overlay.style.bottom = '';
|
|
110
|
+
overlay.style.left = '';
|
|
111
|
+
overlay.style.right = '';
|
|
91
112
|
Object.keys(position.position).forEach((key)=>overlay.style[key] = position.position[key] + 'px');
|
|
92
113
|
overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;
|
|
114
|
+
// Restore scroll position relative to anchor element.
|
|
115
|
+
if (anchor) {
|
|
116
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
117
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
118
|
+
let newOffset = anchorRect[anchor.type] - scrollRect[anchor.type];
|
|
119
|
+
scrollRef.current.scrollTop += newOffset - anchor.offset;
|
|
120
|
+
}
|
|
93
121
|
// Trigger a set state for a second render anyway for arrow positioning
|
|
94
122
|
setPosition(position);
|
|
95
123
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -104,6 +132,11 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
104
132
|
ref: overlayRef,
|
|
105
133
|
onResize: updatePosition
|
|
106
134
|
});
|
|
135
|
+
// Update position when the target changes size (might need to flip).
|
|
136
|
+
(0, $39EOa$useResizeObserver)({
|
|
137
|
+
ref: targetRef,
|
|
138
|
+
onResize: updatePosition
|
|
139
|
+
});
|
|
107
140
|
// Reposition the overlay and do not close on scroll while the visual viewport is resizing.
|
|
108
141
|
// This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.
|
|
109
142
|
let isResizing = (0, $39EOa$useRef)(false);
|
|
@@ -144,13 +177,14 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
144
177
|
isOpen: isOpen,
|
|
145
178
|
onClose: onClose && close
|
|
146
179
|
});
|
|
180
|
+
var _position_maxHeight;
|
|
147
181
|
return {
|
|
148
182
|
overlayProps: {
|
|
149
183
|
style: {
|
|
150
184
|
position: 'absolute',
|
|
151
185
|
zIndex: 100000,
|
|
152
186
|
...position.position,
|
|
153
|
-
maxHeight: position.maxHeight
|
|
187
|
+
maxHeight: (_position_maxHeight = position.maxHeight) !== null && _position_maxHeight !== void 0 ? _position_maxHeight : '100vh'
|
|
154
188
|
}
|
|
155
189
|
},
|
|
156
190
|
placement: position.placement,
|
|
@@ -58,8 +58,27 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
58
58
|
isOpen
|
|
59
59
|
]);
|
|
60
60
|
let updatePosition = (0, $39EOa$useCallback)(()=>{
|
|
61
|
-
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !
|
|
61
|
+
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !boundaryElement) return;
|
|
62
62
|
if (($2a41e45df1593e64$var$visualViewport === null || $2a41e45df1593e64$var$visualViewport === void 0 ? void 0 : $2a41e45df1593e64$var$visualViewport.scale) !== lastScale.current) return;
|
|
63
|
+
// Determine a scroll anchor based on the focused element.
|
|
64
|
+
// This stores the offset of the anchor element from the scroll container
|
|
65
|
+
// so it can be restored after repositioning. This way if the overlay height
|
|
66
|
+
// changes, the focused element appears to stay in the same position.
|
|
67
|
+
let anchor = null;
|
|
68
|
+
if (scrollRef.current && scrollRef.current.contains(document.activeElement)) {
|
|
69
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
70
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
71
|
+
// Anchor from the top if the offset is in the top half of the scrollable element,
|
|
72
|
+
// otherwise anchor from the bottom.
|
|
73
|
+
anchor = {
|
|
74
|
+
type: 'top',
|
|
75
|
+
offset: anchorRect.top - scrollRect.top
|
|
76
|
+
};
|
|
77
|
+
if (anchor.offset > scrollRect.height / 2) {
|
|
78
|
+
anchor.type = 'bottom';
|
|
79
|
+
anchor.offset = anchorRect.bottom - scrollRect.bottom;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
63
82
|
// Always reset the overlay's previous max height if not defined by the user so that we can compensate for
|
|
64
83
|
// RAC collections populating after a second render and properly set a correct max height + positioning when it populates.
|
|
65
84
|
let overlay = overlayRef.current;
|
|
@@ -74,7 +93,7 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
74
93
|
placement: $2a41e45df1593e64$var$translateRTL(placement, direction),
|
|
75
94
|
overlayNode: overlayRef.current,
|
|
76
95
|
targetNode: targetRef.current,
|
|
77
|
-
scrollNode: scrollRef.current,
|
|
96
|
+
scrollNode: scrollRef.current || overlayRef.current,
|
|
78
97
|
padding: containerPadding,
|
|
79
98
|
shouldFlip: shouldFlip,
|
|
80
99
|
boundaryElement: boundaryElement,
|
|
@@ -88,8 +107,17 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
88
107
|
// This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers
|
|
89
108
|
overlay.style.top = '';
|
|
90
109
|
overlay.style.bottom = '';
|
|
110
|
+
overlay.style.left = '';
|
|
111
|
+
overlay.style.right = '';
|
|
91
112
|
Object.keys(position.position).forEach((key)=>overlay.style[key] = position.position[key] + 'px');
|
|
92
113
|
overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;
|
|
114
|
+
// Restore scroll position relative to anchor element.
|
|
115
|
+
if (anchor) {
|
|
116
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
117
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
118
|
+
let newOffset = anchorRect[anchor.type] - scrollRect[anchor.type];
|
|
119
|
+
scrollRef.current.scrollTop += newOffset - anchor.offset;
|
|
120
|
+
}
|
|
93
121
|
// Trigger a set state for a second render anyway for arrow positioning
|
|
94
122
|
setPosition(position);
|
|
95
123
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -104,6 +132,11 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
104
132
|
ref: overlayRef,
|
|
105
133
|
onResize: updatePosition
|
|
106
134
|
});
|
|
135
|
+
// Update position when the target changes size (might need to flip).
|
|
136
|
+
(0, $39EOa$useResizeObserver)({
|
|
137
|
+
ref: targetRef,
|
|
138
|
+
onResize: updatePosition
|
|
139
|
+
});
|
|
107
140
|
// Reposition the overlay and do not close on scroll while the visual viewport is resizing.
|
|
108
141
|
// This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.
|
|
109
142
|
let isResizing = (0, $39EOa$useRef)(false);
|
|
@@ -144,13 +177,14 @@ function $2a41e45df1593e64$export$d39e1813b3bdd0e1(props) {
|
|
|
144
177
|
isOpen: isOpen,
|
|
145
178
|
onClose: onClose && close
|
|
146
179
|
});
|
|
180
|
+
var _position_maxHeight;
|
|
147
181
|
return {
|
|
148
182
|
overlayProps: {
|
|
149
183
|
style: {
|
|
150
184
|
position: 'absolute',
|
|
151
185
|
zIndex: 100000,
|
|
152
186
|
...position.position,
|
|
153
|
-
maxHeight: position.maxHeight
|
|
187
|
+
maxHeight: (_position_maxHeight = position.maxHeight) !== null && _position_maxHeight !== void 0 ? _position_maxHeight : '100vh'
|
|
154
188
|
}
|
|
155
189
|
},
|
|
156
190
|
placement: position.placement,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"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","sources":["packages/@react-aria/overlays/src/useOverlayPosition.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {calculatePosition, PositionResult} from './calculatePosition';\nimport {DOMAttributes} from '@react-types/shared';\nimport {Placement, PlacementAxis, PositionProps} from '@react-types/overlays';\nimport {RefObject, useCallback, useEffect, useRef, useState} from 'react';\nimport {useCloseOnScroll} from './useCloseOnScroll';\nimport {useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface AriaPositionProps extends PositionProps {\n /**\n * Cross size of the overlay arrow in pixels.\n * @default 0\n */\n arrowSize?: number,\n /**\n * Element that that serves as the positioning boundary.\n * @default document.body\n */\n boundaryElement?: Element,\n /**\n * The ref for the element which the overlay positions itself with respect to.\n */\n targetRef: RefObject<Element>,\n /**\n * The ref for the overlay element.\n */\n overlayRef: RefObject<Element>,\n /**\n * A ref for the scrollable region within the overlay.\n * @default overlayRef\n */\n scrollRef?: RefObject<Element>,\n /**\n * Whether the overlay should update its position automatically.\n * @default true\n */\n shouldUpdatePosition?: boolean,\n /** Handler that is called when the overlay should close. */\n onClose?: () => void,\n /**\n * The maxHeight specified for the overlay element.\n * By default, it will take all space up to the current viewport height.\n */\n maxHeight?: number,\n /**\n * The minimum distance the arrow's edge should be from the edge of the overlay element.\n * @default 0\n */\n arrowBoundaryOffset?: number\n}\n\nexport interface PositionAria {\n /** Props for the overlay container element. */\n overlayProps: DOMAttributes,\n /** Props for the overlay tip arrow if any. */\n arrowProps: DOMAttributes,\n /** Placement of the overlay with respect to the overlay trigger. */\n placement: PlacementAxis,\n /** Updates the position of the overlay. */\n updatePosition(): void\n}\n\n// @ts-ignore\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\n/**\n * Handles positioning overlays like popovers and menus relative to a trigger\n * element, and updating the position when the window resizes.\n */\nexport function useOverlayPosition(props: AriaPositionProps): PositionAria {\n let {direction} = useLocale();\n let {\n arrowSize = 0,\n targetRef,\n overlayRef,\n scrollRef = overlayRef,\n placement = 'bottom' as Placement,\n containerPadding = 12,\n shouldFlip = true,\n boundaryElement = typeof document !== 'undefined' ? document.body : null,\n offset = 0,\n crossOffset = 0,\n shouldUpdatePosition = true,\n isOpen = true,\n onClose,\n maxHeight,\n arrowBoundaryOffset = 0\n } = props;\n let [position, setPosition] = useState<PositionResult>({\n position: {},\n arrowOffsetLeft: undefined,\n arrowOffsetTop: undefined,\n maxHeight: undefined,\n placement: undefined\n });\n\n let deps = [\n shouldUpdatePosition,\n placement,\n overlayRef.current,\n targetRef.current,\n scrollRef.current,\n containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n isOpen,\n direction,\n maxHeight,\n arrowBoundaryOffset,\n arrowSize\n ];\n\n // Note, the position freezing breaks if body sizes itself dynamicly with the visual viewport but that might\n // just be a non-realistic use case\n // Upon opening a overlay, record the current visual viewport scale so we can freeze the overlay styles\n let lastScale = useRef(visualViewport?.scale);\n useEffect(() => {\n if (isOpen) {\n lastScale.current = visualViewport?.scale;\n }\n }, [isOpen]);\n\n let updatePosition = useCallback(() => {\n if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !scrollRef.current || !boundaryElement) {\n return;\n }\n\n if (visualViewport?.scale !== lastScale.current) {\n return;\n }\n\n // Always reset the overlay's previous max height if not defined by the user so that we can compensate for\n // RAC collections populating after a second render and properly set a correct max height + positioning when it populates.\n let overlay = (overlayRef.current as HTMLElement);\n if (!maxHeight && overlayRef.current) {\n overlay.style.top = '0px';\n overlay.style.bottom = '';\n overlay.style.maxHeight = (window.visualViewport?.height ?? window.innerHeight) + 'px';\n }\n\n let position = calculatePosition({\n placement: translateRTL(placement, direction),\n overlayNode: overlayRef.current,\n targetNode: targetRef.current,\n scrollNode: scrollRef.current,\n padding: containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n maxHeight,\n arrowSize,\n arrowBoundaryOffset\n });\n\n // Modify overlay styles directly so positioning happens immediately without the need of a second render\n // This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers\n overlay.style.top = '';\n overlay.style.bottom = '';\n Object.keys(position.position).forEach(key => overlay.style[key] = position.position[key] + 'px');\n overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;\n\n // Trigger a set state for a second render anyway for arrow positioning\n setPosition(position);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n // Update position when anything changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(updatePosition, deps);\n\n // Update position on window resize\n useResize(updatePosition);\n\n // Update position when the overlay changes size (might need to flip).\n useResizeObserver({\n ref: overlayRef,\n onResize: updatePosition\n });\n\n // Reposition the overlay and do not close on scroll while the visual viewport is resizing.\n // This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.\n let isResizing = useRef(false);\n useLayoutEffect(() => {\n let timeout: ReturnType<typeof setTimeout>;\n let onResize = () => {\n isResizing.current = true;\n clearTimeout(timeout);\n\n timeout = setTimeout(() => {\n isResizing.current = false;\n }, 500);\n\n updatePosition();\n };\n\n // Only reposition the overlay if a scroll event happens immediately as a result of resize (aka the virtual keyboard has appears)\n // We don't want to reposition the overlay if the user has pinch zoomed in and is scrolling the viewport around.\n let onScroll = () => {\n if (isResizing.current) {\n onResize();\n }\n };\n\n visualViewport?.addEventListener('resize', onResize);\n visualViewport?.addEventListener('scroll', onScroll);\n return () => {\n visualViewport?.removeEventListener('resize', onResize);\n visualViewport?.removeEventListener('scroll', onScroll);\n };\n }, [updatePosition]);\n\n let close = useCallback(() => {\n if (!isResizing.current) {\n onClose();\n }\n }, [onClose, isResizing]);\n\n // When scrolling a parent scrollable region of the trigger (other than the body),\n // we hide the popover. Otherwise, its position would be incorrect.\n useCloseOnScroll({\n triggerRef: targetRef,\n isOpen,\n onClose: onClose && close\n });\n\n return {\n overlayProps: {\n style: {\n position: 'absolute',\n zIndex: 100000, // should match the z-index in ModalTrigger\n ...position.position,\n maxHeight: position.maxHeight\n }\n },\n placement: position.placement,\n arrowProps: {\n 'aria-hidden': 'true',\n role: 'presentation',\n style: {\n left: position.arrowOffsetLeft,\n top: position.arrowOffsetTop\n }\n },\n updatePosition\n };\n}\n\nfunction useResize(onResize) {\n useLayoutEffect(() => {\n window.addEventListener('resize', onResize, false);\n return () => {\n window.removeEventListener('resize', onResize, false);\n };\n }, [onResize]);\n}\n\nfunction translateRTL(position, direction) {\n if (direction === 'rtl') {\n return position.replace('start', 'right').replace('end', 'left');\n }\n return position.replace('start', 'left').replace('end', 'right');\n}\n"],"names":[],"version":3,"file":"useOverlayPosition.module.js.map"}
|
|
1
|
+
{"mappings":"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","sources":["packages/@react-aria/overlays/src/useOverlayPosition.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {calculatePosition, PositionResult} from './calculatePosition';\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {Placement, PlacementAxis, PositionProps} from '@react-types/overlays';\nimport {useCallback, useEffect, useRef, useState} from 'react';\nimport {useCloseOnScroll} from './useCloseOnScroll';\nimport {useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale} from '@react-aria/i18n';\n\nexport interface AriaPositionProps extends PositionProps {\n /**\n * Cross size of the overlay arrow in pixels.\n * @default 0\n */\n arrowSize?: number,\n /**\n * Element that that serves as the positioning boundary.\n * @default document.body\n */\n boundaryElement?: Element,\n /**\n * The ref for the element which the overlay positions itself with respect to.\n */\n targetRef: RefObject<Element | null>,\n /**\n * The ref for the overlay element.\n */\n overlayRef: RefObject<Element | null>,\n /**\n * A ref for the scrollable region within the overlay.\n * @default overlayRef\n */\n scrollRef?: RefObject<Element | null>,\n /**\n * Whether the overlay should update its position automatically.\n * @default true\n */\n shouldUpdatePosition?: boolean,\n /** Handler that is called when the overlay should close. */\n onClose?: () => void,\n /**\n * The maxHeight specified for the overlay element.\n * By default, it will take all space up to the current viewport height.\n */\n maxHeight?: number,\n /**\n * The minimum distance the arrow's edge should be from the edge of the overlay element.\n * @default 0\n */\n arrowBoundaryOffset?: number\n}\n\nexport interface PositionAria {\n /** Props for the overlay container element. */\n overlayProps: DOMAttributes,\n /** Props for the overlay tip arrow if any. */\n arrowProps: DOMAttributes,\n /** Placement of the overlay with respect to the overlay trigger. */\n placement: PlacementAxis,\n /** Updates the position of the overlay. */\n updatePosition(): void\n}\n\ninterface ScrollAnchor {\n type: 'top' | 'bottom',\n offset: number\n}\n\n// @ts-ignore\nlet visualViewport = typeof document !== 'undefined' && window.visualViewport;\n\n/**\n * Handles positioning overlays like popovers and menus relative to a trigger\n * element, and updating the position when the window resizes.\n */\nexport function useOverlayPosition(props: AriaPositionProps): PositionAria {\n let {direction} = useLocale();\n let {\n arrowSize = 0,\n targetRef,\n overlayRef,\n scrollRef = overlayRef,\n placement = 'bottom' as Placement,\n containerPadding = 12,\n shouldFlip = true,\n boundaryElement = typeof document !== 'undefined' ? document.body : null,\n offset = 0,\n crossOffset = 0,\n shouldUpdatePosition = true,\n isOpen = true,\n onClose,\n maxHeight,\n arrowBoundaryOffset = 0\n } = props;\n let [position, setPosition] = useState<PositionResult>({\n position: {},\n arrowOffsetLeft: undefined,\n arrowOffsetTop: undefined,\n maxHeight: undefined,\n placement: undefined\n });\n\n let deps = [\n shouldUpdatePosition,\n placement,\n overlayRef.current,\n targetRef.current,\n scrollRef.current,\n containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n isOpen,\n direction,\n maxHeight,\n arrowBoundaryOffset,\n arrowSize\n ];\n\n // Note, the position freezing breaks if body sizes itself dynamicly with the visual viewport but that might\n // just be a non-realistic use case\n // Upon opening a overlay, record the current visual viewport scale so we can freeze the overlay styles\n let lastScale = useRef(visualViewport?.scale);\n useEffect(() => {\n if (isOpen) {\n lastScale.current = visualViewport?.scale;\n }\n }, [isOpen]);\n\n let updatePosition = useCallback(() => {\n if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !boundaryElement) {\n return;\n }\n\n if (visualViewport?.scale !== lastScale.current) {\n return;\n }\n\n // Determine a scroll anchor based on the focused element.\n // This stores the offset of the anchor element from the scroll container\n // so it can be restored after repositioning. This way if the overlay height\n // changes, the focused element appears to stay in the same position.\n let anchor: ScrollAnchor | null = null;\n if (scrollRef.current && scrollRef.current.contains(document.activeElement)) {\n let anchorRect = document.activeElement.getBoundingClientRect();\n let scrollRect = scrollRef.current.getBoundingClientRect();\n // Anchor from the top if the offset is in the top half of the scrollable element,\n // otherwise anchor from the bottom.\n anchor = {\n type: 'top',\n offset: anchorRect.top - scrollRect.top\n };\n if (anchor.offset > scrollRect.height / 2) {\n anchor.type = 'bottom';\n anchor.offset = anchorRect.bottom - scrollRect.bottom;\n }\n }\n\n // Always reset the overlay's previous max height if not defined by the user so that we can compensate for\n // RAC collections populating after a second render and properly set a correct max height + positioning when it populates.\n let overlay = (overlayRef.current as HTMLElement);\n if (!maxHeight && overlayRef.current) {\n overlay.style.top = '0px';\n overlay.style.bottom = '';\n overlay.style.maxHeight = (window.visualViewport?.height ?? window.innerHeight) + 'px';\n }\n\n let position = calculatePosition({\n placement: translateRTL(placement, direction),\n overlayNode: overlayRef.current,\n targetNode: targetRef.current,\n scrollNode: scrollRef.current || overlayRef.current,\n padding: containerPadding,\n shouldFlip,\n boundaryElement,\n offset,\n crossOffset,\n maxHeight,\n arrowSize,\n arrowBoundaryOffset\n });\n\n // Modify overlay styles directly so positioning happens immediately without the need of a second render\n // This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers\n overlay.style.top = '';\n overlay.style.bottom = '';\n overlay.style.left = '';\n overlay.style.right = '';\n\n Object.keys(position.position).forEach(key => overlay.style[key] = position.position[key] + 'px');\n overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;\n\n // Restore scroll position relative to anchor element.\n if (anchor) {\n let anchorRect = document.activeElement.getBoundingClientRect();\n let scrollRect = scrollRef.current.getBoundingClientRect();\n let newOffset = anchorRect[anchor.type] - scrollRect[anchor.type];\n scrollRef.current.scrollTop += newOffset - anchor.offset;\n }\n\n // Trigger a set state for a second render anyway for arrow positioning\n setPosition(position);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps);\n\n // Update position when anything changes\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useLayoutEffect(updatePosition, deps);\n\n // Update position on window resize\n useResize(updatePosition);\n\n // Update position when the overlay changes size (might need to flip).\n useResizeObserver({\n ref: overlayRef,\n onResize: updatePosition\n });\n\n // Update position when the target changes size (might need to flip).\n useResizeObserver({\n ref: targetRef,\n onResize: updatePosition\n });\n\n // Reposition the overlay and do not close on scroll while the visual viewport is resizing.\n // This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.\n let isResizing = useRef(false);\n useLayoutEffect(() => {\n let timeout: ReturnType<typeof setTimeout>;\n let onResize = () => {\n isResizing.current = true;\n clearTimeout(timeout);\n\n timeout = setTimeout(() => {\n isResizing.current = false;\n }, 500);\n\n updatePosition();\n };\n\n // Only reposition the overlay if a scroll event happens immediately as a result of resize (aka the virtual keyboard has appears)\n // We don't want to reposition the overlay if the user has pinch zoomed in and is scrolling the viewport around.\n let onScroll = () => {\n if (isResizing.current) {\n onResize();\n }\n };\n\n visualViewport?.addEventListener('resize', onResize);\n visualViewport?.addEventListener('scroll', onScroll);\n return () => {\n visualViewport?.removeEventListener('resize', onResize);\n visualViewport?.removeEventListener('scroll', onScroll);\n };\n }, [updatePosition]);\n\n let close = useCallback(() => {\n if (!isResizing.current) {\n onClose();\n }\n }, [onClose, isResizing]);\n\n // When scrolling a parent scrollable region of the trigger (other than the body),\n // we hide the popover. Otherwise, its position would be incorrect.\n useCloseOnScroll({\n triggerRef: targetRef,\n isOpen,\n onClose: onClose && close\n });\n\n return {\n overlayProps: {\n style: {\n position: 'absolute',\n zIndex: 100000, // should match the z-index in ModalTrigger\n ...position.position,\n maxHeight: position.maxHeight ?? '100vh'\n }\n },\n placement: position.placement,\n arrowProps: {\n 'aria-hidden': 'true',\n role: 'presentation',\n style: {\n left: position.arrowOffsetLeft,\n top: position.arrowOffsetTop\n }\n },\n updatePosition\n };\n}\n\nfunction useResize(onResize) {\n useLayoutEffect(() => {\n window.addEventListener('resize', onResize, false);\n return () => {\n window.removeEventListener('resize', onResize, false);\n };\n }, [onResize]);\n}\n\nfunction translateRTL(position, direction) {\n if (direction === 'rtl') {\n return position.replace('start', 'right').replace('end', 'left');\n }\n return position.replace('start', 'left').replace('end', 'right');\n}\n"],"names":[],"version":3,"file":"useOverlayPosition.module.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;AA0BM,SAAS,0CAAkB,KAA0B,EAAE,KAA0B,EAAE,
|
|
1
|
+
{"mappings":";;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;AA0BM,SAAS,0CAAkB,KAA0B,EAAE,KAA0B,EAAE,GAA+B;IACvH,IAAI,QAAC,IAAI,EAAC,GAAG;IACb,IAAI,UAAC,MAAM,EAAC,GAAG;IAEf,uGAAuG;IACvG,yCAAyC;IACzC,CAAA,GAAA,sBAAQ,EAAE;QACR,IAAI,OAAO,IAAI,OAAO,EACpB,CAAA,GAAA,oCAAS,EAAE,GAAG,CAAC,IAAI,OAAO,EAAE,MAAM,KAAK;IAE3C;IAEA,6EAA6E;IAC7E,oDAAoD;IACpD,yEAAyE;IACzE,+CAA+C;IAC/C,IAAI,eAAe;IACnB,IAAI,SAAS,QACX,eAAe;SACV,IAAI,SAAS,WAClB,eAAe;IAGjB,IAAI,YAAY,CAAA,GAAA,2BAAI;IACpB,OAAO;QACL,cAAc;YACZ,iBAAiB;YACjB,iBAAiB;YACjB,iBAAiB,SAAS,YAAY;YACtC,SAAS,MAAM,MAAM;QACvB;QACA,cAAc;YACZ,IAAI;QACN;IACF;AACF","sources":["packages/@react-aria/overlays/src/useOverlayTrigger.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaButtonProps} from '@react-types/button';\nimport {DOMProps, RefObject} from '@react-types/shared';\nimport {onCloseMap} from './useCloseOnScroll';\nimport {OverlayTriggerState} from '@react-stately/overlays';\nimport {useEffect} from 'react';\nimport {useId} from '@react-aria/utils';\n\nexport interface OverlayTriggerProps {\n /** Type of overlay that is opened by the trigger. */\n type: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid'\n}\n\nexport interface OverlayTriggerAria {\n /** Props for the trigger element. */\n triggerProps: AriaButtonProps,\n\n /** Props for the overlay container element. */\n overlayProps: DOMProps\n}\n\n/**\n * Handles the behavior and accessibility for an overlay trigger, e.g. a button\n * that opens a popover, menu, or other overlay that is positioned relative to the trigger.\n */\nexport function useOverlayTrigger(props: OverlayTriggerProps, state: OverlayTriggerState, ref?: RefObject<Element | null>): OverlayTriggerAria {\n let {type} = props;\n let {isOpen} = state;\n\n // Backward compatibility. Share state close function with useOverlayPosition so it can close on scroll\n // without forcing users to pass onClose.\n useEffect(() => {\n if (ref && ref.current) {\n onCloseMap.set(ref.current, state.close);\n }\n });\n\n // Aria 1.1 supports multiple values for aria-haspopup other than just menus.\n // https://www.w3.org/TR/wai-aria-1.1/#aria-haspopup\n // However, we only add it for menus for now because screen readers often\n // announce it as a menu even for other values.\n let ariaHasPopup = undefined;\n if (type === 'menu') {\n ariaHasPopup = true;\n } else if (type === 'listbox') {\n ariaHasPopup = 'listbox';\n }\n\n let overlayId = useId();\n return {\n triggerProps: {\n 'aria-haspopup': ariaHasPopup,\n 'aria-expanded': isOpen,\n 'aria-controls': isOpen ? overlayId : null,\n onPress: state.toggle\n },\n overlayProps: {\n id: overlayId\n }\n };\n}\n"],"names":[],"version":3,"file":"useOverlayTrigger.main.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;AAAA;;;;;;;;;;CAUC;;;AA0BM,SAAS,0CAAkB,KAA0B,EAAE,KAA0B,EAAE,
|
|
1
|
+
{"mappings":";;;;AAAA;;;;;;;;;;CAUC;;;AA0BM,SAAS,0CAAkB,KAA0B,EAAE,KAA0B,EAAE,GAA+B;IACvH,IAAI,QAAC,IAAI,EAAC,GAAG;IACb,IAAI,UAAC,MAAM,EAAC,GAAG;IAEf,uGAAuG;IACvG,yCAAyC;IACzC,CAAA,GAAA,gBAAQ,EAAE;QACR,IAAI,OAAO,IAAI,OAAO,EACpB,CAAA,GAAA,yCAAS,EAAE,GAAG,CAAC,IAAI,OAAO,EAAE,MAAM,KAAK;IAE3C;IAEA,6EAA6E;IAC7E,oDAAoD;IACpD,yEAAyE;IACzE,+CAA+C;IAC/C,IAAI,eAAe;IACnB,IAAI,SAAS,QACX,eAAe;SACV,IAAI,SAAS,WAClB,eAAe;IAGjB,IAAI,YAAY,CAAA,GAAA,YAAI;IACpB,OAAO;QACL,cAAc;YACZ,iBAAiB;YACjB,iBAAiB;YACjB,iBAAiB,SAAS,YAAY;YACtC,SAAS,MAAM,MAAM;QACvB;QACA,cAAc;YACZ,IAAI;QACN;IACF;AACF","sources":["packages/@react-aria/overlays/src/useOverlayTrigger.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {AriaButtonProps} from '@react-types/button';\nimport {DOMProps, RefObject} from '@react-types/shared';\nimport {onCloseMap} from './useCloseOnScroll';\nimport {OverlayTriggerState} from '@react-stately/overlays';\nimport {useEffect} from 'react';\nimport {useId} from '@react-aria/utils';\n\nexport interface OverlayTriggerProps {\n /** Type of overlay that is opened by the trigger. */\n type: 'dialog' | 'menu' | 'listbox' | 'tree' | 'grid'\n}\n\nexport interface OverlayTriggerAria {\n /** Props for the trigger element. */\n triggerProps: AriaButtonProps,\n\n /** Props for the overlay container element. */\n overlayProps: DOMProps\n}\n\n/**\n * Handles the behavior and accessibility for an overlay trigger, e.g. a button\n * that opens a popover, menu, or other overlay that is positioned relative to the trigger.\n */\nexport function useOverlayTrigger(props: OverlayTriggerProps, state: OverlayTriggerState, ref?: RefObject<Element | null>): OverlayTriggerAria {\n let {type} = props;\n let {isOpen} = state;\n\n // Backward compatibility. Share state close function with useOverlayPosition so it can close on scroll\n // without forcing users to pass onClose.\n useEffect(() => {\n if (ref && ref.current) {\n onCloseMap.set(ref.current, state.close);\n }\n });\n\n // Aria 1.1 supports multiple values for aria-haspopup other than just menus.\n // https://www.w3.org/TR/wai-aria-1.1/#aria-haspopup\n // However, we only add it for menus for now because screen readers often\n // announce it as a menu even for other values.\n let ariaHasPopup = undefined;\n if (type === 'menu') {\n ariaHasPopup = true;\n } else if (type === 'listbox') {\n ariaHasPopup = 'listbox';\n }\n\n let overlayId = useId();\n return {\n triggerProps: {\n 'aria-haspopup': ariaHasPopup,\n 'aria-expanded': isOpen,\n 'aria-controls': isOpen ? overlayId : null,\n onPress: state.toggle\n },\n overlayProps: {\n id: overlayId\n }\n };\n}\n"],"names":[],"version":3,"file":"useOverlayTrigger.module.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;
|
|
1
|
+
{"mappings":";;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;AA8DM,SAAS,0CAAW,KAAuB,EAAE,KAA0B;IAC5E,IAAI,cACF,UAAU,cACV,UAAU,cACV,UAAU,6BACV,yBAAyB,gCACzB,4BAA4B,EAC5B,GAAG,YACJ,GAAG;IAEJ,IAAI,gBAAC,YAAY,iBAAE,aAAa,EAAC,GAAG,CAAA,GAAA,oCAAS,EAC3C;QACE,QAAQ,MAAM,MAAM;QACpB,SAAS,MAAM,KAAK;QACpB,mBAAmB;QACnB,eAAe,CAAC;mCAChB;sCACA;IACF,GACA;IAGF,IAAI,EAAC,cAAc,aAAa,cAAE,UAAU,aAAE,SAAS,EAAC,GAAG,CAAA,GAAA,4CAAiB,EAAE;QAC5E,GAAG,UAAU;QACb,WAAW;QACX,YAAY;QACZ,QAAQ,MAAM,MAAM;QACpB,SAAS,aAAa,MAAM,KAAK,GAAG;IACtC;IAEA,CAAA,GAAA,0CAAe,EAAE;QACf,YAAY,cAAc,CAAC,MAAM,MAAM;IACzC;IAEA,CAAA,GAAA,qCAAc,EAAE;QACd,IAAI,MAAM,MAAM,IAAI,CAAC,cAAc,WAAW,OAAO,EACnD,OAAO,CAAA,GAAA,yCAAc,EAAE;YAAC,WAAW,OAAO;SAAC;IAE/C,GAAG;QAAC;QAAY,MAAM,MAAM;QAAE;KAAW;IAEzC,OAAO;QACL,cAAc,CAAA,GAAA,gCAAS,EAAE,cAAc;oBACvC;uBACA;mBACA;IACF;AACF","sources":["packages/@react-aria/overlays/src/usePopover.ts"],"sourcesContent":["/*\n * Copyright 2022 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {ariaHideOutside} from './ariaHideOutside';\nimport {AriaPositionProps, useOverlayPosition} from './useOverlayPosition';\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {mergeProps, useLayoutEffect} from '@react-aria/utils';\nimport {OverlayTriggerState} from '@react-stately/overlays';\nimport {PlacementAxis} from '@react-types/overlays';\nimport {useOverlay} from './useOverlay';\nimport {usePreventScroll} from './usePreventScroll';\n\nexport interface AriaPopoverProps extends Omit<AriaPositionProps, 'isOpen' | 'onClose' | 'targetRef' | 'overlayRef'> {\n /**\n * The ref for the element which the popover positions itself with respect to.\n */\n triggerRef: RefObject<Element | null>,\n /**\n * The ref for the popover element.\n */\n popoverRef: RefObject<Element | null>,\n /**\n * Whether the popover is non-modal, i.e. elements outside the popover may be\n * interacted with by assistive technologies.\n *\n * Most popovers should not use this option as it may negatively impact the screen\n * reader experience. Only use with components such as combobox, which are designed\n * to handle this situation carefully.\n */\n isNonModal?: boolean,\n /**\n * Whether pressing the escape key to close the popover should be disabled.\n *\n * Most popovers should not use this option. When set to true, an alternative\n * way to close the popover with a keyboard must be provided.\n *\n * @default false\n */\n isKeyboardDismissDisabled?: boolean,\n /**\n * When user interacts with the argument element outside of the popover ref,\n * return true if onClose should be called. This gives you a chance to filter\n * out interaction with elements that should not dismiss the popover.\n * By default, onClose will always be called on interaction outside the popover ref.\n */\n shouldCloseOnInteractOutside?: (element: Element) => boolean\n}\n\nexport interface PopoverAria {\n /** Props for the popover element. */\n popoverProps: DOMAttributes,\n /** Props for the popover tip arrow if any. */\n arrowProps: DOMAttributes,\n /** Props to apply to the underlay element, if any. */\n underlayProps: DOMAttributes,\n /** Placement of the popover with respect to the trigger. */\n placement: PlacementAxis\n}\n\n/**\n * Provides the behavior and accessibility implementation for a popover component.\n * A popover is an overlay element positioned relative to a trigger.\n */\nexport function usePopover(props: AriaPopoverProps, state: OverlayTriggerState): PopoverAria {\n let {\n triggerRef,\n popoverRef,\n isNonModal,\n isKeyboardDismissDisabled,\n shouldCloseOnInteractOutside,\n ...otherProps\n } = props;\n\n let {overlayProps, underlayProps} = useOverlay(\n {\n isOpen: state.isOpen,\n onClose: state.close,\n shouldCloseOnBlur: true,\n isDismissable: !isNonModal,\n isKeyboardDismissDisabled,\n shouldCloseOnInteractOutside\n },\n popoverRef\n );\n\n let {overlayProps: positionProps, arrowProps, placement} = useOverlayPosition({\n ...otherProps,\n targetRef: triggerRef,\n overlayRef: popoverRef,\n isOpen: state.isOpen,\n onClose: isNonModal ? state.close : null\n });\n\n usePreventScroll({\n isDisabled: isNonModal || !state.isOpen\n });\n\n useLayoutEffect(() => {\n if (state.isOpen && !isNonModal && popoverRef.current) {\n return ariaHideOutside([popoverRef.current]);\n }\n }, [isNonModal, state.isOpen, popoverRef]);\n\n return {\n popoverProps: mergeProps(overlayProps, positionProps),\n arrowProps,\n underlayProps,\n placement\n };\n}\n"],"names":[],"version":3,"file":"usePopover.main.js.map"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":";;;;;;AAAA;;;;;;;;;;CAUC;;;;;
|
|
1
|
+
{"mappings":";;;;;;AAAA;;;;;;;;;;CAUC;;;;;AA8DM,SAAS,0CAAW,KAAuB,EAAE,KAA0B;IAC5E,IAAI,cACF,UAAU,cACV,UAAU,cACV,UAAU,6BACV,yBAAyB,gCACzB,4BAA4B,EAC5B,GAAG,YACJ,GAAG;IAEJ,IAAI,gBAAC,YAAY,iBAAE,aAAa,EAAC,GAAG,CAAA,GAAA,yCAAS,EAC3C;QACE,QAAQ,MAAM,MAAM;QACpB,SAAS,MAAM,KAAK;QACpB,mBAAmB;QACnB,eAAe,CAAC;mCAChB;sCACA;IACF,GACA;IAGF,IAAI,EAAC,cAAc,aAAa,cAAE,UAAU,aAAE,SAAS,EAAC,GAAG,CAAA,GAAA,yCAAiB,EAAE;QAC5E,GAAG,UAAU;QACb,WAAW;QACX,YAAY;QACZ,QAAQ,MAAM,MAAM;QACpB,SAAS,aAAa,MAAM,KAAK,GAAG;IACtC;IAEA,CAAA,GAAA,yCAAe,EAAE;QACf,YAAY,cAAc,CAAC,MAAM,MAAM;IACzC;IAEA,CAAA,GAAA,sBAAc,EAAE;QACd,IAAI,MAAM,MAAM,IAAI,CAAC,cAAc,WAAW,OAAO,EACnD,OAAO,CAAA,GAAA,yCAAc,EAAE;YAAC,WAAW,OAAO;SAAC;IAE/C,GAAG;QAAC;QAAY,MAAM,MAAM;QAAE;KAAW;IAEzC,OAAO;QACL,cAAc,CAAA,GAAA,iBAAS,EAAE,cAAc;oBACvC;uBACA;mBACA;IACF;AACF","sources":["packages/@react-aria/overlays/src/usePopover.ts"],"sourcesContent":["/*\n * Copyright 2022 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {ariaHideOutside} from './ariaHideOutside';\nimport {AriaPositionProps, useOverlayPosition} from './useOverlayPosition';\nimport {DOMAttributes, RefObject} from '@react-types/shared';\nimport {mergeProps, useLayoutEffect} from '@react-aria/utils';\nimport {OverlayTriggerState} from '@react-stately/overlays';\nimport {PlacementAxis} from '@react-types/overlays';\nimport {useOverlay} from './useOverlay';\nimport {usePreventScroll} from './usePreventScroll';\n\nexport interface AriaPopoverProps extends Omit<AriaPositionProps, 'isOpen' | 'onClose' | 'targetRef' | 'overlayRef'> {\n /**\n * The ref for the element which the popover positions itself with respect to.\n */\n triggerRef: RefObject<Element | null>,\n /**\n * The ref for the popover element.\n */\n popoverRef: RefObject<Element | null>,\n /**\n * Whether the popover is non-modal, i.e. elements outside the popover may be\n * interacted with by assistive technologies.\n *\n * Most popovers should not use this option as it may negatively impact the screen\n * reader experience. Only use with components such as combobox, which are designed\n * to handle this situation carefully.\n */\n isNonModal?: boolean,\n /**\n * Whether pressing the escape key to close the popover should be disabled.\n *\n * Most popovers should not use this option. When set to true, an alternative\n * way to close the popover with a keyboard must be provided.\n *\n * @default false\n */\n isKeyboardDismissDisabled?: boolean,\n /**\n * When user interacts with the argument element outside of the popover ref,\n * return true if onClose should be called. This gives you a chance to filter\n * out interaction with elements that should not dismiss the popover.\n * By default, onClose will always be called on interaction outside the popover ref.\n */\n shouldCloseOnInteractOutside?: (element: Element) => boolean\n}\n\nexport interface PopoverAria {\n /** Props for the popover element. */\n popoverProps: DOMAttributes,\n /** Props for the popover tip arrow if any. */\n arrowProps: DOMAttributes,\n /** Props to apply to the underlay element, if any. */\n underlayProps: DOMAttributes,\n /** Placement of the popover with respect to the trigger. */\n placement: PlacementAxis\n}\n\n/**\n * Provides the behavior and accessibility implementation for a popover component.\n * A popover is an overlay element positioned relative to a trigger.\n */\nexport function usePopover(props: AriaPopoverProps, state: OverlayTriggerState): PopoverAria {\n let {\n triggerRef,\n popoverRef,\n isNonModal,\n isKeyboardDismissDisabled,\n shouldCloseOnInteractOutside,\n ...otherProps\n } = props;\n\n let {overlayProps, underlayProps} = useOverlay(\n {\n isOpen: state.isOpen,\n onClose: state.close,\n shouldCloseOnBlur: true,\n isDismissable: !isNonModal,\n isKeyboardDismissDisabled,\n shouldCloseOnInteractOutside\n },\n popoverRef\n );\n\n let {overlayProps: positionProps, arrowProps, placement} = useOverlayPosition({\n ...otherProps,\n targetRef: triggerRef,\n overlayRef: popoverRef,\n isOpen: state.isOpen,\n onClose: isNonModal ? state.close : null\n });\n\n usePreventScroll({\n isDisabled: isNonModal || !state.isOpen\n });\n\n useLayoutEffect(() => {\n if (state.isOpen && !isNonModal && popoverRef.current) {\n return ariaHideOutside([popoverRef.current]);\n }\n }, [isNonModal, state.isOpen, popoverRef]);\n\n return {\n popoverProps: mergeProps(overlayProps, positionProps),\n arrowProps,\n underlayProps,\n placement\n };\n}\n"],"names":[],"version":3,"file":"usePopover.module.js.map"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-aria/overlays",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.23.1",
|
|
4
4
|
"description": "Spectrum UI components in React",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -22,24 +22,24 @@
|
|
|
22
22
|
"url": "https://github.com/adobe/react-spectrum"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@react-aria/focus": "^3.
|
|
26
|
-
"@react-aria/i18n": "^3.
|
|
27
|
-
"@react-aria/interactions": "^3.
|
|
28
|
-
"@react-aria/ssr": "^3.9.
|
|
29
|
-
"@react-aria/utils": "^3.
|
|
30
|
-
"@react-aria/visually-hidden": "^3.8.
|
|
31
|
-
"@react-stately/overlays": "^3.6.
|
|
32
|
-
"@react-types/button": "^3.9.
|
|
33
|
-
"@react-types/overlays": "^3.8.
|
|
34
|
-
"@react-types/shared": "^3.
|
|
25
|
+
"@react-aria/focus": "^3.18.1",
|
|
26
|
+
"@react-aria/i18n": "^3.12.1",
|
|
27
|
+
"@react-aria/interactions": "^3.22.1",
|
|
28
|
+
"@react-aria/ssr": "^3.9.5",
|
|
29
|
+
"@react-aria/utils": "^3.25.1",
|
|
30
|
+
"@react-aria/visually-hidden": "^3.8.14",
|
|
31
|
+
"@react-stately/overlays": "^3.6.9",
|
|
32
|
+
"@react-types/button": "^3.9.6",
|
|
33
|
+
"@react-types/overlays": "^3.8.9",
|
|
34
|
+
"@react-types/shared": "^3.24.1",
|
|
35
35
|
"@swc/helpers": "^0.5.0"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0",
|
|
39
|
-
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
|
|
38
|
+
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0",
|
|
39
|
+
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "f0aa6aacee60af265dc8994b9274ccf072a850aa"
|
|
45
45
|
}
|
package/src/useCloseOnScroll.ts
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {RefObject
|
|
13
|
+
import {RefObject} from '@react-types/shared';
|
|
14
|
+
import {useEffect} from 'react';
|
|
14
15
|
|
|
15
16
|
// This behavior moved from useOverlayTrigger to useOverlayPosition.
|
|
16
17
|
// For backward compatibility, where useOverlayTrigger handled hiding the popover on close,
|
|
@@ -20,7 +21,7 @@ import {RefObject, useEffect} from 'react';
|
|
|
20
21
|
export const onCloseMap: WeakMap<Element, () => void> = new WeakMap();
|
|
21
22
|
|
|
22
23
|
interface CloseOnScrollOptions {
|
|
23
|
-
triggerRef: RefObject<Element>,
|
|
24
|
+
triggerRef: RefObject<Element | null>,
|
|
24
25
|
isOpen?: boolean,
|
|
25
26
|
onClose?: () => void
|
|
26
27
|
}
|
|
@@ -42,6 +43,13 @@ export function useCloseOnScroll(opts: CloseOnScrollOptions) {
|
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
// Ignore scroll events on any input or textarea as the cursor position can cause it to scroll
|
|
47
|
+
// such as in a combobox. Clicking the dropdown button places focus on the input, and if the
|
|
48
|
+
// text inside the input extends beyond the 'end', then it will scroll so the cursor is visible at the end.
|
|
49
|
+
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
45
53
|
let onCloseHandler = onClose || onCloseMap.get(triggerRef.current);
|
|
46
54
|
if (onCloseHandler) {
|
|
47
55
|
onCloseHandler();
|
package/src/useModalOverlay.ts
CHANGED
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
import {ariaHideOutside} from './ariaHideOutside';
|
|
14
14
|
import {AriaOverlayProps, useOverlay} from './useOverlay';
|
|
15
|
-
import {DOMAttributes} from '@react-types/shared';
|
|
15
|
+
import {DOMAttributes, RefObject} from '@react-types/shared';
|
|
16
16
|
import {mergeProps} from '@react-aria/utils';
|
|
17
17
|
import {OverlayTriggerState} from '@react-stately/overlays';
|
|
18
|
-
import {
|
|
18
|
+
import {useEffect} from 'react';
|
|
19
19
|
import {useOverlayFocusContain} from './Overlay';
|
|
20
20
|
import {usePreventScroll} from './usePreventScroll';
|
|
21
21
|
|
|
@@ -43,7 +43,7 @@ export interface ModalOverlayAria {
|
|
|
43
43
|
* Provides the behavior and accessibility implementation for a modal component.
|
|
44
44
|
* A modal is an overlay element which blocks interaction with elements outside it.
|
|
45
45
|
*/
|
|
46
|
-
export function useModalOverlay(props: AriaModalOverlayProps, state: OverlayTriggerState, ref: RefObject<HTMLElement>): ModalOverlayAria {
|
|
46
|
+
export function useModalOverlay(props: AriaModalOverlayProps, state: OverlayTriggerState, ref: RefObject<HTMLElement | null>): ModalOverlayAria {
|
|
47
47
|
let {overlayProps, underlayProps} = useOverlay({
|
|
48
48
|
...props,
|
|
49
49
|
isOpen: state.isOpen,
|
package/src/useOverlay.ts
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
* governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {DOMAttributes} from '@react-types/shared';
|
|
13
|
+
import {DOMAttributes, RefObject} from '@react-types/shared';
|
|
14
14
|
import {isElementInChildOfActiveScope} from '@react-aria/focus';
|
|
15
|
-
import {
|
|
15
|
+
import {useEffect} from 'react';
|
|
16
16
|
import {useFocusWithin, useInteractOutside} from '@react-aria/interactions';
|
|
17
17
|
|
|
18
18
|
export interface AriaOverlayProps {
|
|
@@ -53,14 +53,14 @@ export interface OverlayAria {
|
|
|
53
53
|
underlayProps: DOMAttributes
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
const visibleOverlays: RefObject<Element>[] = [];
|
|
56
|
+
const visibleOverlays: RefObject<Element | null>[] = [];
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* Provides the behavior for overlays such as dialogs, popovers, and menus.
|
|
60
60
|
* Hides the overlay when the user interacts outside it, when the Escape key is pressed,
|
|
61
61
|
* or optionally, on blur. Only the top-most overlay will close at once.
|
|
62
62
|
*/
|
|
63
|
-
export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element>): OverlayAria {
|
|
63
|
+
export function useOverlay(props: AriaOverlayProps, ref: RefObject<Element | null>): OverlayAria {
|
|
64
64
|
let {
|
|
65
65
|
onClose,
|
|
66
66
|
shouldCloseOnBlur,
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {calculatePosition, PositionResult} from './calculatePosition';
|
|
14
|
-
import {DOMAttributes} from '@react-types/shared';
|
|
14
|
+
import {DOMAttributes, RefObject} from '@react-types/shared';
|
|
15
15
|
import {Placement, PlacementAxis, PositionProps} from '@react-types/overlays';
|
|
16
|
-
import {
|
|
16
|
+
import {useCallback, useEffect, useRef, useState} from 'react';
|
|
17
17
|
import {useCloseOnScroll} from './useCloseOnScroll';
|
|
18
18
|
import {useLayoutEffect, useResizeObserver} from '@react-aria/utils';
|
|
19
19
|
import {useLocale} from '@react-aria/i18n';
|
|
@@ -32,16 +32,16 @@ export interface AriaPositionProps extends PositionProps {
|
|
|
32
32
|
/**
|
|
33
33
|
* The ref for the element which the overlay positions itself with respect to.
|
|
34
34
|
*/
|
|
35
|
-
targetRef: RefObject<Element>,
|
|
35
|
+
targetRef: RefObject<Element | null>,
|
|
36
36
|
/**
|
|
37
37
|
* The ref for the overlay element.
|
|
38
38
|
*/
|
|
39
|
-
overlayRef: RefObject<Element>,
|
|
39
|
+
overlayRef: RefObject<Element | null>,
|
|
40
40
|
/**
|
|
41
41
|
* A ref for the scrollable region within the overlay.
|
|
42
42
|
* @default overlayRef
|
|
43
43
|
*/
|
|
44
|
-
scrollRef?: RefObject<Element>,
|
|
44
|
+
scrollRef?: RefObject<Element | null>,
|
|
45
45
|
/**
|
|
46
46
|
* Whether the overlay should update its position automatically.
|
|
47
47
|
* @default true
|
|
@@ -72,6 +72,11 @@ export interface PositionAria {
|
|
|
72
72
|
updatePosition(): void
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
interface ScrollAnchor {
|
|
76
|
+
type: 'top' | 'bottom',
|
|
77
|
+
offset: number
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
// @ts-ignore
|
|
76
81
|
let visualViewport = typeof document !== 'undefined' && window.visualViewport;
|
|
77
82
|
|
|
@@ -135,7 +140,7 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
|
|
|
135
140
|
}, [isOpen]);
|
|
136
141
|
|
|
137
142
|
let updatePosition = useCallback(() => {
|
|
138
|
-
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !
|
|
143
|
+
if (shouldUpdatePosition === false || !isOpen || !overlayRef.current || !targetRef.current || !boundaryElement) {
|
|
139
144
|
return;
|
|
140
145
|
}
|
|
141
146
|
|
|
@@ -143,6 +148,26 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
|
|
|
143
148
|
return;
|
|
144
149
|
}
|
|
145
150
|
|
|
151
|
+
// Determine a scroll anchor based on the focused element.
|
|
152
|
+
// This stores the offset of the anchor element from the scroll container
|
|
153
|
+
// so it can be restored after repositioning. This way if the overlay height
|
|
154
|
+
// changes, the focused element appears to stay in the same position.
|
|
155
|
+
let anchor: ScrollAnchor | null = null;
|
|
156
|
+
if (scrollRef.current && scrollRef.current.contains(document.activeElement)) {
|
|
157
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
158
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
159
|
+
// Anchor from the top if the offset is in the top half of the scrollable element,
|
|
160
|
+
// otherwise anchor from the bottom.
|
|
161
|
+
anchor = {
|
|
162
|
+
type: 'top',
|
|
163
|
+
offset: anchorRect.top - scrollRect.top
|
|
164
|
+
};
|
|
165
|
+
if (anchor.offset > scrollRect.height / 2) {
|
|
166
|
+
anchor.type = 'bottom';
|
|
167
|
+
anchor.offset = anchorRect.bottom - scrollRect.bottom;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
146
171
|
// Always reset the overlay's previous max height if not defined by the user so that we can compensate for
|
|
147
172
|
// RAC collections populating after a second render and properly set a correct max height + positioning when it populates.
|
|
148
173
|
let overlay = (overlayRef.current as HTMLElement);
|
|
@@ -156,7 +181,7 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
|
|
|
156
181
|
placement: translateRTL(placement, direction),
|
|
157
182
|
overlayNode: overlayRef.current,
|
|
158
183
|
targetNode: targetRef.current,
|
|
159
|
-
scrollNode: scrollRef.current,
|
|
184
|
+
scrollNode: scrollRef.current || overlayRef.current,
|
|
160
185
|
padding: containerPadding,
|
|
161
186
|
shouldFlip,
|
|
162
187
|
boundaryElement,
|
|
@@ -171,9 +196,20 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
|
|
|
171
196
|
// This is so we don't have to delay autoFocus scrolling or delay applying preventScroll for popovers
|
|
172
197
|
overlay.style.top = '';
|
|
173
198
|
overlay.style.bottom = '';
|
|
199
|
+
overlay.style.left = '';
|
|
200
|
+
overlay.style.right = '';
|
|
201
|
+
|
|
174
202
|
Object.keys(position.position).forEach(key => overlay.style[key] = position.position[key] + 'px');
|
|
175
203
|
overlay.style.maxHeight = position.maxHeight != null ? position.maxHeight + 'px' : undefined;
|
|
176
204
|
|
|
205
|
+
// Restore scroll position relative to anchor element.
|
|
206
|
+
if (anchor) {
|
|
207
|
+
let anchorRect = document.activeElement.getBoundingClientRect();
|
|
208
|
+
let scrollRect = scrollRef.current.getBoundingClientRect();
|
|
209
|
+
let newOffset = anchorRect[anchor.type] - scrollRect[anchor.type];
|
|
210
|
+
scrollRef.current.scrollTop += newOffset - anchor.offset;
|
|
211
|
+
}
|
|
212
|
+
|
|
177
213
|
// Trigger a set state for a second render anyway for arrow positioning
|
|
178
214
|
setPosition(position);
|
|
179
215
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -192,6 +228,12 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
|
|
|
192
228
|
onResize: updatePosition
|
|
193
229
|
});
|
|
194
230
|
|
|
231
|
+
// Update position when the target changes size (might need to flip).
|
|
232
|
+
useResizeObserver({
|
|
233
|
+
ref: targetRef,
|
|
234
|
+
onResize: updatePosition
|
|
235
|
+
});
|
|
236
|
+
|
|
195
237
|
// Reposition the overlay and do not close on scroll while the visual viewport is resizing.
|
|
196
238
|
// This will ensure that overlays adjust their positioning when the iOS virtual keyboard appears.
|
|
197
239
|
let isResizing = useRef(false);
|
|
@@ -244,7 +286,7 @@ export function useOverlayPosition(props: AriaPositionProps): PositionAria {
|
|
|
244
286
|
position: 'absolute',
|
|
245
287
|
zIndex: 100000, // should match the z-index in ModalTrigger
|
|
246
288
|
...position.position,
|
|
247
|
-
maxHeight: position.maxHeight
|
|
289
|
+
maxHeight: position.maxHeight ?? '100vh'
|
|
248
290
|
}
|
|
249
291
|
},
|
|
250
292
|
placement: position.placement,
|
package/src/useOverlayTrigger.ts
CHANGED
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import {AriaButtonProps} from '@react-types/button';
|
|
14
|
-
import {DOMProps} from '@react-types/shared';
|
|
14
|
+
import {DOMProps, RefObject} from '@react-types/shared';
|
|
15
15
|
import {onCloseMap} from './useCloseOnScroll';
|
|
16
16
|
import {OverlayTriggerState} from '@react-stately/overlays';
|
|
17
|
-
import {
|
|
17
|
+
import {useEffect} from 'react';
|
|
18
18
|
import {useId} from '@react-aria/utils';
|
|
19
19
|
|
|
20
20
|
export interface OverlayTriggerProps {
|
|
@@ -34,7 +34,7 @@ export interface OverlayTriggerAria {
|
|
|
34
34
|
* Handles the behavior and accessibility for an overlay trigger, e.g. a button
|
|
35
35
|
* that opens a popover, menu, or other overlay that is positioned relative to the trigger.
|
|
36
36
|
*/
|
|
37
|
-
export function useOverlayTrigger(props: OverlayTriggerProps, state: OverlayTriggerState, ref?: RefObject<Element>): OverlayTriggerAria {
|
|
37
|
+
export function useOverlayTrigger(props: OverlayTriggerProps, state: OverlayTriggerState, ref?: RefObject<Element | null>): OverlayTriggerAria {
|
|
38
38
|
let {type} = props;
|
|
39
39
|
let {isOpen} = state;
|
|
40
40
|
|
package/src/usePopover.ts
CHANGED
|
@@ -12,11 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
import {ariaHideOutside} from './ariaHideOutside';
|
|
14
14
|
import {AriaPositionProps, useOverlayPosition} from './useOverlayPosition';
|
|
15
|
-
import {DOMAttributes} from '@react-types/shared';
|
|
15
|
+
import {DOMAttributes, RefObject} from '@react-types/shared';
|
|
16
16
|
import {mergeProps, useLayoutEffect} from '@react-aria/utils';
|
|
17
17
|
import {OverlayTriggerState} from '@react-stately/overlays';
|
|
18
18
|
import {PlacementAxis} from '@react-types/overlays';
|
|
19
|
-
import {RefObject} from 'react';
|
|
20
19
|
import {useOverlay} from './useOverlay';
|
|
21
20
|
import {usePreventScroll} from './usePreventScroll';
|
|
22
21
|
|
|
@@ -24,11 +23,11 @@ export interface AriaPopoverProps extends Omit<AriaPositionProps, 'isOpen' | 'on
|
|
|
24
23
|
/**
|
|
25
24
|
* The ref for the element which the popover positions itself with respect to.
|
|
26
25
|
*/
|
|
27
|
-
triggerRef: RefObject<Element>,
|
|
26
|
+
triggerRef: RefObject<Element | null>,
|
|
28
27
|
/**
|
|
29
28
|
* The ref for the popover element.
|
|
30
29
|
*/
|
|
31
|
-
popoverRef: RefObject<Element>,
|
|
30
|
+
popoverRef: RefObject<Element | null>,
|
|
32
31
|
/**
|
|
33
32
|
* Whether the popover is non-modal, i.e. elements outside the popover may be
|
|
34
33
|
* interacted with by assistive technologies.
|