/*
given a DOM element, return the list of all scroll parents, up the list of ancesors
until we get to the top window object. This list is what we attach scroll listeners
to, because if any of these parent elements scroll, we'll need to re-calculate the
reference element's position.
*/

/* eslint-disable no-bitwise, no-cond-assign */

/* harmony default export */

/* harmony export (binding) */

/* harmony import */

/* harmony reexport (safe) */

/*#__PURE__*/

/**
 * A convenience hook around `useState` designed to be paired with
 * the component [callback ref](https://reactjs.org/docs/refs-and-the-dom.html#callback-refs) api.
 * Callback refs are useful over `useRef()` when you need to respond to the ref being set
 * instead of lazily accessing it in an effect.
 *
 * ```ts
 * const [element, attachRef] = useCallbackRef<HTMLDivElement>()
 *
 * useEffect(() => {
 *   if (!element) return
 *
 *   const calendar = new FullCalendar.Calendar(element)
 *
 *   return () => {
 *     calendar.destroy()
 *   }
 * }, [element])
 *
 * return <div ref={attachRef} />
 * ```
 *
 * @category refs
 */

/**
 * Create and returns a single callback ref composed from two other Refs.
 *
 * ```tsx
 * const Button = React.forwardRef((props, ref) => {
 *   const [element, attachRef] = useCallbackRef<HTMLButtonElement>();
 *   const mergedRef = useMergedRefs(ref, attachRef);
 *
 *   return <button ref={mergedRef} {...props}/>
 * })
 * ```
 *
 * @param refA A Callback or mutable Ref
 * @param refB A Callback or mutable Ref
 * @category refs
 */

/**
 * Position an element relative some reference element using Popper.js
 *
 * @param referenceElement
 * @param popperElement
 * @param {object}      options
 * @param {object=}     options.modifiers Popper.js modifiers
 * @param {boolean=}    options.enabled toggle the popper functionality on/off
 * @param {string=}     options.placement The popper element placement relative to the reference element
 * @param {string=}     options.strategy the positioning strategy
 * @param {boolean=}    options.eventsEnabled have Popper listen on window resize events to reposition the element
 * @param {function=}   options.onCreate called when the popper is created
 * @param {function=}   options.onUpdate called when the popper is updated
 *
 * @returns {UsePopperState} The popper state
 */

/**
 * The `useRootClose` hook registers your callback on the document
 * when rendered. Powers the `<Overlay/>` component. This is used achieve modal
 * style behavior where your callback is triggered when the user tries to
 * interact with the rest of the document or hits the `esc` key.
 *
 * @param {Ref<HTMLElement>| HTMLElement} ref  The element boundary
 * @param {function} onRootClose
 * @param {object=}  options
 * @param {boolean=} options.disabled
 * @param {string=}  options.clickTrigger The DOM event name (click, mousedown, etc) to attach listeners on
 */

/**
 * Track whether a component is current mounted. Generally less preferable than
 * properlly canceling effects so they don't run after a component is unmounted,
 * but helpful in cases where that isn't feasible, such as a `Promise` resolution.
 *
 * @returns a function that returns the current isMounted state of the component
 *
 * ```ts
 * const [data, setData] = useState(null)
 * const isMounted = useMounted()
 *
 * useEffect(() => {
 *   fetchdata().then((newData) => {
 *      if (isMounted()) {
 *        setData(newData);
 *      }
 *   })
 * })
 * ```
 */

/***/

/*:: declare function getWindow(node: Node | Window): Window; */

/*:: declare function isElement(node: mixed): boolean %checks(node instanceof
  Element); */

/*:: declare function isHTMLElement(node: mixed): boolean %checks(node instanceof
  HTMLElement); */

/*:: declare function isShadowRoot(node: mixed): boolean %checks(node instanceof
  ShadowRoot); */

/*:: import type { Window } from '../types'; */

/*:: offsetParent = (offsetParent: Element); */

/*:: type OverflowsMap = { [ComputedPlacement]: number }; */

/*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */

// $FlowFixMe[incompatible-call]: HTMLElement is a Node

// $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here

// $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it

// $FlowFixMe[incompatible-return]

// $FlowFixMe[incompatible-return]: assume body is always available

// $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414

// $FlowFixMe[incompatible-return]: need a better way to handle this...

// $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...

// $FlowFixMe[prop-missing]

// $FlowFixMe[prop-missing]: need a better way to handle this...

// 0.001

// A "clipping parent" is an overflowable container with the characteristic of

// Also, `html.clientHeight` adds the bottom bar height in Safari iOS, even

// Async and optimistically optimized update – it will not be executed if

// Browsers where the left scrollbar doesn't cause an issue report `0` for

// CSS selector

// Composite means it takes into account transforms as well as layout.

// DOM Element detected

// Don't proceed if `reference` or `popper` are not valid elements

// Fallback here: "Not Safari" userAgent

// Feature detection fails in mobile emulation mode in Chrome.

// Firefox wants us to check `-x` and `-y` variations as well

// First, attempt with faster native method

// For high frequency updates (e.g. `resize` and `scroll` events), always

// For the common JS build we will turn this file into a bundle with no imports.

// Gets the closest ancestor positioned element. Handles some edge cases,

// Gets the entire size of the scrollable document area, even extending outside

// Gets the maximum area that the element is visible in due to any number of

// Give up, the result is false

// HTML DOM and SVG DOM may have different support levels,

// IE11 does not support Object.values

// If <html> has a CSS width greater than the viewport, then this will be

// In Chrome, it returns a value very close to 0 (+/-) but contains rounding

// Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) <

// Modifiers have the ability to reset the current update cycle. The

// NB: This isn't supported on iOS <= 12. If the keyboard is open, the popper

// Offsets are the actual position the popper needs to have to be

// Offsets can be applied only to the popper element

// On each update cycle, the `modifiersData` property for each modifier

// On visiting object, check for its dependencies and visit them recursively

// Orders the modifiers based on their dependencies and `phase`

// Popper 1 is broken in this case and never had a bug report so let's assume

// Returns the composite rect of an element relative to its offsetParent.

// Returns the layout rect of an element relative to its offsetParent. Layout

// Round the offsets to the nearest suitable subpixel based on the DPR.

// Safari returns a number <= 0, usually < -1 when pinch-zoomed

// ShadowRoot detected

// Store the current event to avoid triggering handlers immediately

// Store the reference and popper rects to be read by modifiers

// Strip out disabled modifiers

// Sync update – it will always be executed, even if not necessary. This

// This is b/c the Popper lib is all esm files, and would break in a common js only environment

// This is non-exhaustive but covers the most common CSS properties that

// This is only run once to _create_ the popper

// This is the most basic placement, and will be adjusted by

// To ensure persistent data, use `${name}#persistent`

// Uses Layout Viewport (like Chrome; Safari does not currently)

// Zooming can change the DPR, but it seems to report a value that will

// `.offsetParent` reports `null` for fixed elements, while absolute elements

// `2` may be desired in some cases – research later

// `initial`

// anymore

// anyway.

// can be obscured underneath it.

// check for visited object

// cleanly divide the values into the appropriate subpixels.

// clipping (or hiding) overflowing elements with a position different from

// clipping parents

// create a containing block.

// errors due to floating point numbers, so we need to check precision.

// eslint-disable-next-line import/no-unused-modules

// eslint-disable-next-line no-unused-expressions

// eslint-disable-next-line react-hooks/exhaustive-deps

// https://github.com/facebook/react/issues/20074

// https://github.com/popperjs/popper-core/issues/1078

// https://github.com/popperjs/popper-core/issues/837

// if it isn't open, so if this isn't available, the popper will be detected

// incorrect for RTL.

// is filled with the initial data specified by the modifier. This means

// is useful for low frequency updates where sync behavior simplifies the

// it doesn't persist and is fresh on each update.

// it's not an issue. I don't think anyone ever specifies width on <html>

// logic was previously ran for the previous placement and is therefore

// logic.

// means it doesn't take into account transforms.

// most common use case for this is the `flip` modifier changing the

// not necessary (debounced to run at most once-per-tick)

// of the `<html>` and `<body>` rect bounds if horizontally scrollable

// order based on dependencies

// order based on phase

// placement, which then needs to re-run all the modifiers, because the

// prefer the async Popper#update method

// properly positioned near its reference element

// properties

// return the containing block

// skip if this event is the same as the one running when we added the handlers

// so we need to check on context instead of a document root element.

// source: https://stackoverflow.com/questions/49875255

// stale/incorrect

// step into the shadow DOM of the parent of a slotted node

// such as table ancestors and cross browser bugs.

// the modifiers in the next step

// this (e.g. Edge 2019, IE11, Safari)

// this is a quicker (but less type safe) way to save quite some bytes from the bundle

// to overflow the bottom of the screen too early.
