@react-native-aria/overlays 0.3.5 → 0.3.7

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["useCloseOnScroll.ts"],"names":["useEffect","onCloseMap","WeakMap","useCloseOnScroll","opts","triggerRef","isOpen","onClose","onScroll","e","target","current","contains","onCloseHandler","get","window","addEventListener","removeEventListener"],"mappings":"AAAA;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA,SAAmBA,SAAnB,QAAmC,OAAnC,C,CAEA;AACA;AACA;AACA;AACA;;AACA,OAAO,MAAMC,UAA4C,GAAG,IAAIC,OAAJ,EAArD;;AAQP;AACA,OAAO,SAASC,gBAAT,CAA0BC,IAA1B,EAAsD;AAC3D,MAAI;AAACC,IAAAA,UAAD;AAAaC,IAAAA,MAAb;AAAqBC,IAAAA;AAArB,MAAgCH,IAApC;AAEAJ,EAAAA,SAAS,CAAC,MAAM;AACd,QAAI,CAACM,MAAL,EAAa;AACX;AACD;;AAED,QAAIE,QAAQ,GAAIC,CAAD,IAAmB;AAChC;AACA,UAAIC,MAAM,GAAGD,CAAC,CAACC,MAAf;;AACA,UAAI,CAACL,UAAU,CAACM,OAAZ,IAAuB,CAACD,MAAM,CAACE,QAAP,CAAgBP,UAAU,CAACM,OAA3B,CAA5B,EAAiE;AAC/D;AACD;;AAED,UAAIE,cAAc,GAAGN,OAAO,IAAIN,UAAU,CAACa,GAAX,CAAeT,UAAU,CAACM,OAA1B,CAAhC;;AACA,UAAIE,cAAJ,EAAoB;AAClBA,QAAAA,cAAc;AACf;AACF,KAXD;;AAaAE,IAAAA,MAAM,CAACC,gBAAP,CAAwB,QAAxB,EAAkCR,QAAlC,EAA4C,IAA5C;AACA,WAAO,MAAM;AACXO,MAAAA,MAAM,CAACE,mBAAP,CAA2B,QAA3B,EAAqCT,QAArC,EAA+C,IAA/C;AACD,KAFD;AAGD,GAtBQ,EAsBN,CAACF,MAAD,EAASC,OAAT,EAAkBF,UAAlB,CAtBM,CAAT;AAuBD","sourcesContent":["//@ts-nocheck\n/*\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, 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<HTMLElement, () => void> = new WeakMap();\n\ninterface CloseOnScrollOptions {\n triggerRef: RefObject<HTMLElement>,\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) {\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 as HTMLElement;\n if (!triggerRef.current || !target.contains(triggerRef.current)) {\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"]}
1
+ {"version":3,"sources":["useCloseOnScroll.ts"],"names":["useEffect","onCloseMap","WeakMap","useCloseOnScroll","opts","triggerRef","isOpen","onClose","onScroll","e","target","current","contains","onCloseHandler","get","window","addEventListener","removeEventListener"],"mappings":"AAAA;;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA,SAAoBA,SAApB,QAAqC,OAArC,C,CAEA;AACA;AACA;AACA;AACA;;AACA,OAAO,MAAMC,UAA4C,GAAG,IAAIC,OAAJ,EAArD;;AAQP;AACA,OAAO,SAASC,gBAAT,CAA0BC,IAA1B,EAAsD;AAC3D,MAAI;AAAEC,IAAAA,UAAF;AAAcC,IAAAA,MAAd;AAAsBC,IAAAA;AAAtB,MAAkCH,IAAtC;AAEAJ,EAAAA,SAAS,CAAC,MAAM;AACd,QAAI,CAACM,MAAL,EAAa;AACX;AACD;;AAED,QAAIE,QAAQ,GAAIC,CAAD,IAAmB;AAChC;AACA,UAAIC,MAAM,GAAGD,CAAC,CAACC,MAAf;;AACA,UAAI,CAACL,UAAU,CAACM,OAAZ,IAAuB,CAACD,MAAM,CAACE,QAAP,CAAgBP,UAAU,CAACM,OAA3B,CAA5B,EAAiE;AAC/D;AACD;;AAED,UAAIE,cAAc,GAAGN,OAAO,IAAIN,UAAU,CAACa,GAAX,CAAeT,UAAU,CAACM,OAA1B,CAAhC;;AACA,UAAIE,cAAJ,EAAoB;AAClBA,QAAAA,cAAc;AACf;AACF,KAXD;;AAaAE,IAAAA,MAAM,CAACC,gBAAP,CAAwB,QAAxB,EAAkCR,QAAlC,EAA4C,IAA5C;AACA,WAAO,MAAM;AACXO,MAAAA,MAAM,CAACE,mBAAP,CAA2B,QAA3B,EAAqCT,QAArC,EAA+C,IAA/C;AACD,KAFD;AAGD,GAtBQ,EAsBN,CAACF,MAAD,EAASC,OAAT,EAAkBF,UAAlB,CAtBM,CAAT;AAuBD","sourcesContent":["//@ts-nocheck\n/*\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, 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<HTMLElement, () => void> = new WeakMap();\n\ninterface CloseOnScrollOptions {\n triggerRef: RefObject<HTMLElement>;\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) {\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 as HTMLElement;\n if (!triggerRef.current || !target.contains(triggerRef.current)) {\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"]}
@@ -100,7 +100,27 @@ export function useOverlayPosition(props) {
100
100
  triggerRef: targetRef,
101
101
  isOpen,
102
102
  onClose: onClose ? close : undefined
103
- });
103
+ }); // useLayoutEffect(() => {
104
+ // const mutationObserver = new MutationObserver((mutations) => {
105
+ // updatePosition();
106
+ // mutations.forEach((mutation) => {
107
+ // // if (mutation.attributeName === 'style') {
108
+ // // const transform = mutation.target.style.transform;
109
+ // // if (transform) {
110
+ // // const match = transform.match(/scale\((.+)\)/);
111
+ // // if (match) {
112
+ // // const scale = parseFloat(match[1]);
113
+ // // console.log(`Scale: ${scale}`);
114
+ // // // updatePosition();
115
+ // // }
116
+ // // }
117
+ // // }
118
+ // });
119
+ // });
120
+ // mutationObserver.observe(overlayRef?.current, { attributes: true });
121
+ // return () => mutationObserver.disconnect();
122
+ // }, [overlayRef, updatePosition]);
123
+
104
124
  return {
105
125
  rendered: true,
106
126
  overlayProps: {
@@ -1 +1 @@
1
- {"version":3,"sources":["useOverlayPosition.ts"],"names":["calculatePosition","useCallback","useRef","useState","useCloseOnScroll","isRTL","useLayoutEffect","visualViewport","window","useOverlayPosition","props","direction","undefined","targetRef","overlayRef","scrollRef","placement","containerPadding","shouldFlip","boundaryElement","document","body","offset","crossOffset","shouldUpdatePosition","isOpen","shouldOverlapWithTrigger","onClose","position","setPosition","arrowOffsetLeft","arrowOffsetTop","maxHeight","deps","current","updatePosition","translateRTL","overlayNode","targetNode","scrollNode","padding","useResize","isResizing","timeout","onResize","clearTimeout","setTimeout","addEventListener","removeEventListener","close","triggerRef","rendered","overlayProps","style","zIndex","arrowProps","left","top","replace"],"mappings":"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","sourcesContent":["//@ts-nocheck\n/*\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 {\n HTMLAttributes,\n RefObject,\n useCallback,\n useRef,\n useState,\n} from 'react';\nimport { Placement, PlacementAxis, PositionProps } from '@react-types/overlays';\nimport { useCloseOnScroll } from './useCloseOnScroll';\nimport { isRTL, useLayoutEffect } from '@react-native-aria/utils';\n\ninterface AriaPositionProps extends PositionProps {\n /**\n * Element that that serves as the positioning boundary.\n * @default document.body\n */\n boundaryElement?: HTMLElement;\n /**\n * The ref for the element which the overlay positions itself with respect to.\n */\n targetRef: RefObject<HTMLElement>;\n /**\n * The ref for the overlay element.\n */\n overlayRef: RefObject<HTMLElement>;\n /**\n * A ref for the scrollable region within the overlay.\n * @default overlayRef\n */\n scrollRef?: RefObject<HTMLElement>;\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 /** Determines whether the overlay should overlap with the trigger */\n shouldOverlapWithTrigger?: boolean;\n}\n\ninterface PositionAria {\n /** Props for the overlay container element. */\n overlayProps: HTMLAttributes<Element>;\n /** Props for the overlay tip arrow if any. */\n arrowProps: HTMLAttributes<Element>;\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 window !== '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 const direction = isRTL() ? 'rtl' : undefined;\n let {\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 shouldOverlapWithTrigger = false,\n onClose,\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 shouldOverlapWithTrigger\n ];\n\n let updatePosition = useCallback(() => {\n if (\n shouldUpdatePosition === false ||\n !isOpen ||\n !overlayRef.current ||\n !targetRef.current ||\n !scrollRef.current ||\n !boundaryElement\n ) {\n return;\n }\n\n setPosition(\n 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 shouldOverlapWithTrigger,\n })\n );\n }, deps);\n\n // Update position when anything changes\n useLayoutEffect(updatePosition, deps);\n\n // Update position on window resize\n useResize(updatePosition);\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: NodeJS.Timeout;\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 visualViewport?.addEventListener('resize', onResize);\n\n return () => {\n visualViewport?.removeEventListener('resize', onResize);\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 : undefined,\n });\n\n return {\n rendered: true,\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 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"]}
1
+ {"version":3,"sources":["useOverlayPosition.ts"],"names":["calculatePosition","useCallback","useRef","useState","useCloseOnScroll","isRTL","useLayoutEffect","visualViewport","window","useOverlayPosition","props","direction","undefined","targetRef","overlayRef","scrollRef","placement","containerPadding","shouldFlip","boundaryElement","document","body","offset","crossOffset","shouldUpdatePosition","isOpen","shouldOverlapWithTrigger","onClose","position","setPosition","arrowOffsetLeft","arrowOffsetTop","maxHeight","deps","current","updatePosition","translateRTL","overlayNode","targetNode","scrollNode","padding","useResize","isResizing","timeout","onResize","clearTimeout","setTimeout","addEventListener","removeEventListener","close","triggerRef","rendered","overlayProps","style","zIndex","arrowProps","left","top","replace"],"mappings":"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","sourcesContent":["//@ts-nocheck\n/*\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 {\n HTMLAttributes,\n RefObject,\n useCallback,\n useRef,\n useState,\n} from 'react';\nimport { Placement, PlacementAxis, PositionProps } from '@react-types/overlays';\nimport { useCloseOnScroll } from './useCloseOnScroll';\nimport { isRTL, useLayoutEffect } from '@react-native-aria/utils';\n\ninterface AriaPositionProps extends PositionProps {\n /**\n * Element that that serves as the positioning boundary.\n * @default document.body\n */\n boundaryElement?: HTMLElement;\n /**\n * The ref for the element which the overlay positions itself with respect to.\n */\n targetRef: RefObject<HTMLElement>;\n /**\n * The ref for the overlay element.\n */\n overlayRef: RefObject<HTMLElement>;\n /**\n * A ref for the scrollable region within the overlay.\n * @default overlayRef\n */\n scrollRef?: RefObject<HTMLElement>;\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 /** Determines whether the overlay should overlap with the trigger */\n shouldOverlapWithTrigger?: boolean;\n}\n\ninterface PositionAria {\n /** Props for the overlay container element. */\n overlayProps: HTMLAttributes<Element>;\n /** Props for the overlay tip arrow if any. */\n arrowProps: HTMLAttributes<Element>;\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 window !== '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 const direction = isRTL() ? 'rtl' : undefined;\n let {\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 shouldOverlapWithTrigger = false,\n onClose,\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 shouldOverlapWithTrigger,\n ];\n\n let updatePosition = useCallback(() => {\n if (\n shouldUpdatePosition === false ||\n !isOpen ||\n !overlayRef.current ||\n !targetRef.current ||\n !scrollRef.current ||\n !boundaryElement\n ) {\n return;\n }\n\n setPosition(\n 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 shouldOverlapWithTrigger,\n })\n );\n }, deps);\n\n // Update position when anything changes\n useLayoutEffect(updatePosition, deps);\n\n // Update position on window resize\n useResize(updatePosition);\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: NodeJS.Timeout;\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 visualViewport?.addEventListener('resize', onResize);\n\n return () => {\n visualViewport?.removeEventListener('resize', onResize);\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 : undefined,\n });\n\n // useLayoutEffect(() => {\n // const mutationObserver = new MutationObserver((mutations) => {\n // updatePosition();\n // mutations.forEach((mutation) => {\n // // if (mutation.attributeName === 'style') {\n // // const transform = mutation.target.style.transform;\n // // if (transform) {\n // // const match = transform.match(/scale\\((.+)\\)/);\n // // if (match) {\n // // const scale = parseFloat(match[1]);\n // // console.log(`Scale: ${scale}`);\n // // // updatePosition();\n // // }\n // // }\n // // }\n // });\n // });\n\n // mutationObserver.observe(overlayRef?.current, { attributes: true });\n\n // return () => mutationObserver.disconnect();\n // }, [overlayRef, updatePosition]);\n\n return {\n rendered: true,\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 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-native-aria/overlays",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Overlay utilities. Part of react-native-aria",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -11,88 +11,94 @@
11
11
  * governing permissions and limitations under the License.
12
12
  */
13
13
 
14
- import {Axis, Placement, PlacementAxis, SizeAxis} from '@react-types/overlays';
14
+ import {
15
+ Axis,
16
+ Placement,
17
+ PlacementAxis,
18
+ SizeAxis,
19
+ } from '@react-types/overlays';
15
20
  import getCss from 'dom-helpers/css';
16
21
  import getOffset from 'dom-helpers/offset';
17
22
  import getPosition from 'dom-helpers/position';
18
23
  import getScrollLeft from 'dom-helpers/scrollLeft';
19
24
  import getScrollTop from 'dom-helpers/scrollTop';
20
25
  import ownerDocument from 'dom-helpers/ownerDocument';
26
+ import getComputedStyle from 'dom-helpers/getComputedStyle';
21
27
 
22
28
  interface Position {
23
- top?: number,
24
- left?: number,
25
- bottom?: number,
26
- right?: number
29
+ top?: number;
30
+ left?: number;
31
+ bottom?: number;
32
+ right?: number;
27
33
  }
28
34
 
29
35
  interface Dimensions {
30
- width: number,
31
- height: number,
32
- top: number,
33
- left: number,
34
- scroll: Position
36
+ width: number;
37
+ height: number;
38
+ top: number;
39
+ left: number;
40
+ scroll: Position;
35
41
  }
36
42
 
37
43
  interface ParsedPlacement {
38
- placement: PlacementAxis,
39
- crossPlacement: PlacementAxis,
40
- axis: Axis,
41
- crossAxis: Axis,
42
- size: SizeAxis,
43
- crossSize: SizeAxis
44
+ placement: PlacementAxis;
45
+ crossPlacement: PlacementAxis;
46
+ axis: Axis;
47
+ crossAxis: Axis;
48
+ size: SizeAxis;
49
+ crossSize: SizeAxis;
44
50
  }
45
51
 
46
52
  interface Offset {
47
- top: number,
48
- left: number,
49
- width: number,
50
- height: number
53
+ top: number;
54
+ left: number;
55
+ width: number;
56
+ height: number;
51
57
  }
52
58
 
53
59
  interface PositionOpts {
54
- placement: Placement,
55
- targetNode: HTMLElement,
56
- overlayNode: HTMLElement,
57
- scrollNode: HTMLElement,
58
- padding: number,
59
- shouldFlip: boolean,
60
- boundaryElement: HTMLElement,
61
- offset: number,
62
- crossOffset: number,
63
- shouldOverlapWithTrigger: boolean
60
+ placement: Placement;
61
+ targetNode: HTMLElement;
62
+ overlayNode: HTMLElement;
63
+ scrollNode: HTMLElement;
64
+ padding: number;
65
+ shouldFlip: boolean;
66
+ boundaryElement: HTMLElement;
67
+ offset: number;
68
+ crossOffset: number;
69
+ shouldOverlapWithTrigger: boolean;
64
70
  }
65
71
 
66
72
  export interface PositionResult {
67
- position?: Position,
68
- arrowOffsetLeft?: number,
69
- arrowOffsetTop?: number,
70
- maxHeight?: number,
71
- placement: PlacementAxis
73
+ position?: Position;
74
+ arrowOffsetLeft?: number;
75
+ arrowOffsetTop?: number;
76
+ maxHeight?: number;
77
+ placement: PlacementAxis;
72
78
  }
73
79
 
74
80
  const AXIS = {
75
81
  top: 'top',
76
82
  bottom: 'top',
77
83
  left: 'left',
78
- right: 'left'
84
+ right: 'left',
79
85
  };
80
86
 
81
87
  const FLIPPED_DIRECTION = {
82
88
  top: 'bottom',
83
89
  bottom: 'top',
84
90
  left: 'right',
85
- right: 'left'
91
+ right: 'left',
86
92
  };
87
93
 
88
94
  const CROSS_AXIS = {
89
95
  top: 'left',
90
- left: 'top'
96
+ left: 'top',
91
97
  };
92
98
 
93
99
  const AXIS_SIZE = {
94
100
  top: 'height',
95
- left: 'width'
101
+ left: 'width',
96
102
  };
97
103
 
98
104
  const PARSED_PLACEMENT_CACHE = {};
@@ -101,7 +107,10 @@ const PARSED_PLACEMENT_CACHE = {};
101
107
  let visualViewport = typeof window !== 'undefined' && window.visualViewport;
102
108
 
103
109
  function getContainerDimensions(containerNode: Element): Dimensions {
104
- let width = 0, height = 0, top = 0, left = 0;
110
+ let width = 0,
111
+ height = 0,
112
+ top = 0,
113
+ left = 0;
105
114
  let scroll: Position = {};
106
115
 
107
116
  if (containerNode.tagName === 'BODY') {
@@ -115,12 +124,12 @@ function getContainerDimensions(containerNode: Element): Dimensions {
115
124
  getScrollLeft(ownerDocument(containerNode).documentElement) ||
116
125
  getScrollLeft(containerNode);
117
126
  } else {
118
- ({width, height, top, left} = getOffset(containerNode));
127
+ ({ width, height, top, left } = getOffset(containerNode));
119
128
  scroll.top = getScrollTop(containerNode);
120
129
  scroll.left = getScrollLeft(containerNode);
121
130
  }
122
131
 
123
- return {width, height, scroll, top, left};
132
+ return { width, height, scroll, top, left };
124
133
  }
125
134
 
126
135
  function getScroll(node: HTMLElement): Offset {
@@ -128,7 +137,7 @@ function getScroll(node: HTMLElement): Offset {
128
137
  top: node.scrollTop,
129
138
  left: node.scrollLeft,
130
139
  width: node.scrollWidth,
131
- height: node.scrollHeight
140
+ height: node.scrollHeight,
132
141
  };
133
142
  }
134
143
 
@@ -160,7 +169,7 @@ function getMargins(node: HTMLElement): Position {
160
169
  top: parseInt(style.marginTop, 10) || 0,
161
170
  bottom: parseInt(style.marginBottom, 10) || 0,
162
171
  left: parseInt(style.marginLeft, 10) || 0,
163
- right: parseInt(style.marginRight, 10) || 0
172
+ right: parseInt(style.marginRight, 10) || 0,
164
173
  };
165
174
  }
166
175
 
@@ -179,7 +188,14 @@ function parsePlacement(input: Placement): ParsedPlacement {
179
188
 
180
189
  let size = AXIS_SIZE[axis];
181
190
  let crossSize = AXIS_SIZE[crossAxis];
182
- PARSED_PLACEMENT_CACHE[input] = {placement, crossPlacement, axis, crossAxis, size, crossSize};
191
+ PARSED_PLACEMENT_CACHE[input] = {
192
+ placement,
193
+ crossPlacement,
194
+ axis,
195
+ crossAxis,
196
+ size,
197
+ crossSize,
198
+ };
183
199
  return PARSED_PLACEMENT_CACHE[input];
184
200
  }
185
201
 
@@ -193,32 +209,47 @@ function computePosition(
193
209
  containerOffsetWithBoundary: Offset,
194
210
  isContainerPositioned: boolean
195
211
  ) {
196
- let {placement, crossPlacement, axis, crossAxis, size, crossSize} = placementInfo;
212
+ let {
213
+ placement,
214
+ crossPlacement,
215
+ axis,
216
+ crossAxis,
217
+ size,
218
+ crossSize,
219
+ } = placementInfo;
197
220
  let position: Position = {};
198
221
 
199
222
  // button position
200
223
  position[crossAxis] = childOffset[crossAxis];
224
+
201
225
  if (crossPlacement === 'center') {
202
226
  // + (button size / 2) - (overlay size / 2)
203
227
  // at this point the overlay center should match the button center
204
- position[crossAxis] += (childOffset[crossSize] - overlaySize[crossSize]) / 2;
228
+ position[crossAxis] +=
229
+ (childOffset[crossSize] - overlaySize[crossSize]) / 2;
205
230
  } else if (crossPlacement !== crossAxis) {
206
231
  // + (button size) - (overlay size)
207
232
  // at this point the overlay bottom should match the button bottom
208
- position[crossAxis] += (childOffset[crossSize] - overlaySize[crossSize]);
209
- }/* else {
233
+ position[crossAxis] += childOffset[crossSize] - overlaySize[crossSize];
234
+ } /* else {
210
235
  the overlay top should match the button top
211
236
  } */
212
237
  // add the crossOffset from props
213
238
  position[crossAxis] += crossOffset;
214
239
 
215
- // this is button center position - the overlay size + half of the button to align bottom of overlay with button center
216
- let minViablePosition = childOffset[crossAxis] + (childOffset[crossSize] / 2) - overlaySize[crossSize];
217
- // this is button position of center, aligns top of overlay with button center
218
- let maxViablePosition = childOffset[crossAxis] + (childOffset[crossSize] / 2);
240
+ // // this is button center position - the overlay size + half of the button to align bottom of overlay with button center
241
+ // let minViablePosition =
242
+ // childOffset[crossAxis] +
243
+ // childOffset[crossSize] / 2 -
244
+ // overlaySize[crossSize];
245
+ // // this is button position of center, aligns top of overlay with button center
246
+ // let maxViablePosition = childOffset[crossAxis] + childOffset[crossSize] / 2;
219
247
 
220
- // clamp it into the range of the min/max positions
221
- position[crossAxis] = Math.min(Math.max(minViablePosition, position[crossAxis]), maxViablePosition);
248
+ // // clamp it into the range of the min/max positions
249
+ // position[crossAxis] = Math.min(
250
+ // Math.max(minViablePosition, position[crossAxis]),
251
+ // maxViablePosition
252
+ // );
222
253
 
223
254
  // Floor these so the position isn't placed on a partial pixel, only whole pixels. Shouldn't matter if it was floored or ceiled, so chose one.
224
255
  if (placement === axis) {
@@ -226,8 +257,12 @@ function computePosition(
226
257
  // height, as `bottom` will be relative to this height. But if the container is static,
227
258
  // then it can only be the `document.body`, and `bottom` will be relative to _its_
228
259
  // container, which should be as large as boundaryDimensions.
229
- const containerHeight = (isContainerPositioned ? containerOffsetWithBoundary[size] : boundaryDimensions[size]);
230
- position[FLIPPED_DIRECTION[axis]] = Math.floor(containerHeight - childOffset[axis] + offset);
260
+ const containerHeight = isContainerPositioned
261
+ ? containerOffsetWithBoundary[size]
262
+ : boundaryDimensions[size];
263
+ position[FLIPPED_DIRECTION[axis]] = Math.floor(
264
+ containerHeight - childOffset[axis] + offset
265
+ );
231
266
  } else {
232
267
  position[axis] = Math.floor(childOffset[axis] + childOffset[size] + offset);
233
268
  }
@@ -244,17 +279,22 @@ function getMaxHeight(
244
279
  padding: number
245
280
  ) {
246
281
  return position.top != null
247
- // We want the distance between the top of the overlay to the bottom of the boundary
248
- ? Math.max(0,
249
- (boundaryDimensions.height + boundaryDimensions.top + boundaryDimensions.scroll.top) // this is the bottom of the boundary
250
- - (containerOffsetWithBoundary.top + position.top) // this is the top of the overlay
251
- - (margins.top + margins.bottom + padding) // save additional space for margin and padding
282
+ ? // We want the distance between the top of the overlay to the bottom of the boundary
283
+ Math.max(
284
+ 0,
285
+ boundaryDimensions.height +
286
+ boundaryDimensions.top +
287
+ boundaryDimensions.scroll.top - // this is the bottom of the boundary
288
+ (containerOffsetWithBoundary.top + position.top) - // this is the top of the overlay
289
+ (margins.top + margins.bottom + padding) // save additional space for margin and padding
252
290
  )
253
- // We want the distance between the top of the trigger to the top of the boundary
254
- : Math.max(0,
255
- (childOffset.top + containerOffsetWithBoundary.top) // this is the top of the trigger
256
- - (boundaryDimensions.top + boundaryDimensions.scroll.top) // this is the top of the boundary
257
- - (margins.top + margins.bottom + padding) // save additional space for margin and padding
291
+ : // We want the distance between the top of the trigger to the top of the boundary
292
+ Math.max(
293
+ 0,
294
+ childOffset.top +
295
+ containerOffsetWithBoundary.top - // this is the top of the trigger
296
+ (boundaryDimensions.top + boundaryDimensions.scroll.top) - // this is the top of the boundary
297
+ (margins.top + margins.bottom + padding) // save additional space for margin and padding
258
298
  );
259
299
  }
260
300
 
@@ -266,12 +306,32 @@ function getAvailableSpace(
266
306
  padding: number,
267
307
  placementInfo: ParsedPlacement
268
308
  ) {
269
- let {placement, axis, size} = placementInfo;
309
+ let { placement, axis, size } = placementInfo;
270
310
  if (placement === axis) {
271
- return Math.max(0, childOffset[axis] - boundaryDimensions[axis] - boundaryDimensions.scroll[axis] + containerOffsetWithBoundary[axis] - margins[axis] - margins[FLIPPED_DIRECTION[axis]] - padding);
311
+ return Math.max(
312
+ 0,
313
+ childOffset[axis] -
314
+ boundaryDimensions[axis] -
315
+ boundaryDimensions.scroll[axis] +
316
+ containerOffsetWithBoundary[axis] -
317
+ margins[axis] -
318
+ margins[FLIPPED_DIRECTION[axis]] -
319
+ padding
320
+ );
272
321
  }
273
322
 
274
- return Math.max(0, boundaryDimensions[size] + boundaryDimensions[axis] + boundaryDimensions.scroll[axis] - containerOffsetWithBoundary[axis] - childOffset[axis] - childOffset[size] - margins[axis] - margins[FLIPPED_DIRECTION[axis]] - padding);
323
+ return Math.max(
324
+ 0,
325
+ boundaryDimensions[size] +
326
+ boundaryDimensions[axis] +
327
+ boundaryDimensions.scroll[axis] -
328
+ containerOffsetWithBoundary[axis] -
329
+ childOffset[axis] -
330
+ childOffset[size] -
331
+ margins[axis] -
332
+ margins[FLIPPED_DIRECTION[axis]] -
333
+ padding
334
+ );
275
335
  }
276
336
 
277
337
  export function calculatePositionInternal(
@@ -290,8 +350,25 @@ export function calculatePositionInternal(
290
350
  shouldOverlapWithTrigger: boolean
291
351
  ): PositionResult {
292
352
  let placementInfo = parsePlacement(placementInput);
293
- let {size, crossAxis, crossSize, placement, crossPlacement, axis} = placementInfo;
294
- let position = computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
353
+ let {
354
+ size,
355
+ crossAxis,
356
+ crossSize,
357
+ placement,
358
+ crossPlacement,
359
+ axis,
360
+ } = placementInfo;
361
+ let position = computePosition(
362
+ childOffset,
363
+ boundaryDimensions,
364
+ overlaySize,
365
+ placementInfo,
366
+ offset,
367
+ crossOffset,
368
+ containerOffsetWithBoundary,
369
+ isContainerPositioned
370
+ );
371
+
295
372
  let normalizedOffset = offset;
296
373
  let space = getAvailableSpace(
297
374
  boundaryDimensions,
@@ -304,8 +381,19 @@ export function calculatePositionInternal(
304
381
 
305
382
  // Check if the scroll size of the overlay is greater than the available space to determine if we need to flip
306
383
  if (flip && scrollSize[size] > space) {
307
- let flippedPlacementInfo = parsePlacement(`${FLIPPED_DIRECTION[placement]} ${crossPlacement}` as Placement);
308
- let flippedPosition = computePosition(childOffset, boundaryDimensions, overlaySize, flippedPlacementInfo, offset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
384
+ let flippedPlacementInfo = parsePlacement(
385
+ `${FLIPPED_DIRECTION[placement]} ${crossPlacement}` as Placement
386
+ );
387
+ let flippedPosition = computePosition(
388
+ childOffset,
389
+ boundaryDimensions,
390
+ overlaySize,
391
+ flippedPlacementInfo,
392
+ offset,
393
+ crossOffset,
394
+ containerOffsetWithBoundary,
395
+ isContainerPositioned
396
+ );
309
397
  let flippedSpace = getAvailableSpace(
310
398
  boundaryDimensions,
311
399
  containerOffsetWithBoundary,
@@ -323,7 +411,13 @@ export function calculatePositionInternal(
323
411
  }
324
412
  }
325
413
 
326
- let delta = getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, padding);
414
+ let delta = getDelta(
415
+ crossAxis,
416
+ position[crossAxis],
417
+ overlaySize[crossSize],
418
+ boundaryDimensions,
419
+ padding
420
+ );
327
421
  position[crossAxis] += delta;
328
422
 
329
423
  let maxHeight = getMaxHeight(
@@ -337,15 +431,32 @@ export function calculatePositionInternal(
337
431
 
338
432
  overlaySize.height = Math.min(overlaySize.height, maxHeight);
339
433
 
340
- position = computePosition(childOffset, boundaryDimensions, overlaySize, placementInfo, normalizedOffset, crossOffset, containerOffsetWithBoundary, isContainerPositioned);
341
- delta = getDelta(crossAxis, position[crossAxis], overlaySize[crossSize], boundaryDimensions, padding);
434
+ position = computePosition(
435
+ childOffset,
436
+ boundaryDimensions,
437
+ overlaySize,
438
+ placementInfo,
439
+ normalizedOffset,
440
+ crossOffset,
441
+ containerOffsetWithBoundary,
442
+ isContainerPositioned
443
+ );
444
+ delta = getDelta(
445
+ crossAxis,
446
+ position[crossAxis],
447
+ overlaySize[crossSize],
448
+ boundaryDimensions,
449
+ padding
450
+ );
342
451
  position[crossAxis] += delta;
343
452
 
344
453
  let arrowPosition: Position = {};
345
- arrowPosition[crossAxis] = (childOffset[crossAxis] - position[crossAxis] + childOffset[crossSize] / 2);
454
+ arrowPosition[crossAxis] =
455
+ childOffset[crossAxis] - position[crossAxis] + childOffset[crossSize] / 2;
346
456
 
347
457
  if (shouldOverlapWithTrigger) {
348
- position[FLIPPED_DIRECTION[placementInfo.placement]] = position[FLIPPED_DIRECTION[placementInfo.placement]] - childOffset[size];
458
+ position[FLIPPED_DIRECTION[placementInfo.placement]] =
459
+ position[FLIPPED_DIRECTION[placementInfo.placement]] - childOffset[size];
349
460
  }
350
461
 
351
462
  return {
@@ -353,7 +464,7 @@ export function calculatePositionInternal(
353
464
  maxHeight: maxHeight,
354
465
  arrowOffsetLeft: arrowPosition.left,
355
466
  arrowOffsetTop: arrowPosition.top,
356
- placement: placementInfo.placement
467
+ placement: placementInfo.placement,
357
468
  };
358
469
  }
359
470
 
@@ -371,14 +482,17 @@ export function calculatePosition(opts: PositionOpts): PositionResult {
371
482
  boundaryElement,
372
483
  offset,
373
484
  crossOffset,
374
- shouldOverlapWithTrigger
485
+ shouldOverlapWithTrigger,
375
486
  } = opts;
376
487
 
377
488
  let container = overlayNode.offsetParent || document.body;
378
489
  let isBodyContainer = container.tagName === 'BODY';
379
490
  const containerPositionStyle = window.getComputedStyle(container).position;
380
- let isContainerPositioned = !!containerPositionStyle && containerPositionStyle !== 'static';
381
- let childOffset: Offset = isBodyContainer ? getOffset(targetNode) : getPosition(targetNode, container);
491
+ let isContainerPositioned =
492
+ !!containerPositionStyle && containerPositionStyle !== 'static';
493
+ let childOffset: Offset = isBodyContainer
494
+ ? getOffset(targetNode)
495
+ : getPosition(targetNode, container);
382
496
 
383
497
  if (!isBodyContainer) {
384
498
  childOffset.top += parseInt(getCss(targetNode, 'marginTop'), 10) || 0;
@@ -386,14 +500,42 @@ export function calculatePosition(opts: PositionOpts): PositionResult {
386
500
  }
387
501
 
388
502
  let overlaySize: Offset = getOffset(overlayNode);
503
+ const matrix = getComputedStyle(overlayNode).getPropertyValue('transform');
504
+ const transform = matrix;
505
+ const regex = /matrix\((-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+),\s*(-?\d*\.?\d+)\)/;
506
+ const matches = transform.match(regex);
507
+ let scaleX = 1;
508
+ let scaleY = 1;
509
+
510
+ if (matches) {
511
+ scaleX = parseFloat(matches[1]);
512
+ scaleY = parseFloat(matches[4]);
513
+ if (!scaleX || !Number.isFinite(scaleX)) {
514
+ scaleX = 1;
515
+ }
516
+
517
+ if (!scaleY || !Number.isFinite(scaleY)) {
518
+ scaleY = 1;
519
+ }
520
+ }
521
+
389
522
  let margins = getMargins(overlayNode);
390
523
  overlaySize.width += margins.left + margins.right;
391
524
  overlaySize.height += margins.top + margins.bottom;
392
525
 
526
+ if (scaleX) {
527
+ overlaySize.width = overlaySize.width / scaleX;
528
+ }
529
+ if (scaleY) {
530
+ overlaySize.height = overlaySize.height / scaleY;
531
+ }
532
+
393
533
  let scrollSize = getScroll(scrollNode);
394
534
  let boundaryDimensions = getContainerDimensions(boundaryElement);
395
- let containerOffsetWithBoundary: Offset = boundaryElement.tagName === 'BODY' ? getOffset(container) : getPosition(container, boundaryElement);
396
-
535
+ let containerOffsetWithBoundary: Offset =
536
+ boundaryElement.tagName === 'BODY'
537
+ ? getOffset(container)
538
+ : getPosition(container, boundaryElement);
397
539
 
398
540
  return calculatePositionInternal(
399
541
  placement,
@@ -11,7 +11,7 @@
11
11
  * governing permissions and limitations under the License.
12
12
  */
13
13
 
14
- import {RefObject, useEffect} from 'react';
14
+ import { RefObject, useEffect } from 'react';
15
15
 
16
16
  // This behavior moved from useOverlayTrigger to useOverlayPosition.
17
17
  // For backward compatibility, where useOverlayTrigger handled hiding the popover on close,
@@ -21,14 +21,14 @@ import {RefObject, useEffect} from 'react';
21
21
  export const onCloseMap: WeakMap<HTMLElement, () => void> = new WeakMap();
22
22
 
23
23
  interface CloseOnScrollOptions {
24
- triggerRef: RefObject<HTMLElement>,
25
- isOpen?: boolean,
26
- onClose?: () => void
24
+ triggerRef: RefObject<HTMLElement>;
25
+ isOpen?: boolean;
26
+ onClose?: () => void;
27
27
  }
28
28
 
29
29
  /** @private */
30
30
  export function useCloseOnScroll(opts: CloseOnScrollOptions) {
31
- let {triggerRef, isOpen, onClose} = opts;
31
+ let { triggerRef, isOpen, onClose } = opts;
32
32
 
33
33
  useEffect(() => {
34
34
  if (!isOpen) {