|
|
import { computePosition, arrow as arrow$2, offset as offset$1, shift as shift$1, limitShift as limitShift$1, flip as flip$1, size as size$1, autoPlacement as autoPlacement$1, hide as hide$1, inline as inline$1 } from '@floating-ui/dom'; |
|
|
export { autoUpdate, computePosition, detectOverflow, getOverflowAncestors, platform } from '@floating-ui/dom'; |
|
|
import * as React from 'react'; |
|
|
import { useLayoutEffect, useEffect } from 'react'; |
|
|
import * as ReactDOM from 'react-dom'; |
|
|
|
|
|
var index = typeof document !== 'undefined' ? useLayoutEffect : useEffect; |
|
|
|
|
|
|
|
|
|
|
|
function deepEqual(a, b) { |
|
|
if (a === b) { |
|
|
return true; |
|
|
} |
|
|
if (typeof a !== typeof b) { |
|
|
return false; |
|
|
} |
|
|
if (typeof a === 'function' && a.toString() === b.toString()) { |
|
|
return true; |
|
|
} |
|
|
let length; |
|
|
let i; |
|
|
let keys; |
|
|
if (a && b && typeof a === 'object') { |
|
|
if (Array.isArray(a)) { |
|
|
length = a.length; |
|
|
if (length !== b.length) return false; |
|
|
for (i = length; i-- !== 0;) { |
|
|
if (!deepEqual(a[i], b[i])) { |
|
|
return false; |
|
|
} |
|
|
} |
|
|
return true; |
|
|
} |
|
|
keys = Object.keys(a); |
|
|
length = keys.length; |
|
|
if (length !== Object.keys(b).length) { |
|
|
return false; |
|
|
} |
|
|
for (i = length; i-- !== 0;) { |
|
|
if (!{}.hasOwnProperty.call(b, keys[i])) { |
|
|
return false; |
|
|
} |
|
|
} |
|
|
for (i = length; i-- !== 0;) { |
|
|
const key = keys[i]; |
|
|
if (key === '_owner' && a.$$typeof) { |
|
|
continue; |
|
|
} |
|
|
if (!deepEqual(a[key], b[key])) { |
|
|
return false; |
|
|
} |
|
|
} |
|
|
return true; |
|
|
} |
|
|
return a !== a && b !== b; |
|
|
} |
|
|
|
|
|
function getDPR(element) { |
|
|
if (typeof window === 'undefined') { |
|
|
return 1; |
|
|
} |
|
|
const win = element.ownerDocument.defaultView || window; |
|
|
return win.devicePixelRatio || 1; |
|
|
} |
|
|
|
|
|
function roundByDPR(element, value) { |
|
|
const dpr = getDPR(element); |
|
|
return Math.round(value * dpr) / dpr; |
|
|
} |
|
|
|
|
|
function useLatestRef(value) { |
|
|
const ref = React.useRef(value); |
|
|
index(() => { |
|
|
ref.current = value; |
|
|
}); |
|
|
return ref; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function useFloating(options) { |
|
|
if (options === void 0) { |
|
|
options = {}; |
|
|
} |
|
|
const { |
|
|
placement = 'bottom', |
|
|
strategy = 'absolute', |
|
|
middleware = [], |
|
|
platform, |
|
|
elements: { |
|
|
reference: externalReference, |
|
|
floating: externalFloating |
|
|
} = {}, |
|
|
transform = true, |
|
|
whileElementsMounted, |
|
|
open |
|
|
} = options; |
|
|
const [data, setData] = React.useState({ |
|
|
x: 0, |
|
|
y: 0, |
|
|
strategy, |
|
|
placement, |
|
|
middlewareData: {}, |
|
|
isPositioned: false |
|
|
}); |
|
|
const [latestMiddleware, setLatestMiddleware] = React.useState(middleware); |
|
|
if (!deepEqual(latestMiddleware, middleware)) { |
|
|
setLatestMiddleware(middleware); |
|
|
} |
|
|
const [_reference, _setReference] = React.useState(null); |
|
|
const [_floating, _setFloating] = React.useState(null); |
|
|
const setReference = React.useCallback(node => { |
|
|
if (node !== referenceRef.current) { |
|
|
referenceRef.current = node; |
|
|
_setReference(node); |
|
|
} |
|
|
}, []); |
|
|
const setFloating = React.useCallback(node => { |
|
|
if (node !== floatingRef.current) { |
|
|
floatingRef.current = node; |
|
|
_setFloating(node); |
|
|
} |
|
|
}, []); |
|
|
const referenceEl = externalReference || _reference; |
|
|
const floatingEl = externalFloating || _floating; |
|
|
const referenceRef = React.useRef(null); |
|
|
const floatingRef = React.useRef(null); |
|
|
const dataRef = React.useRef(data); |
|
|
const hasWhileElementsMounted = whileElementsMounted != null; |
|
|
const whileElementsMountedRef = useLatestRef(whileElementsMounted); |
|
|
const platformRef = useLatestRef(platform); |
|
|
const openRef = useLatestRef(open); |
|
|
const update = React.useCallback(() => { |
|
|
if (!referenceRef.current || !floatingRef.current) { |
|
|
return; |
|
|
} |
|
|
const config = { |
|
|
placement, |
|
|
strategy, |
|
|
middleware: latestMiddleware |
|
|
}; |
|
|
if (platformRef.current) { |
|
|
config.platform = platformRef.current; |
|
|
} |
|
|
computePosition(referenceRef.current, floatingRef.current, config).then(data => { |
|
|
const fullData = { |
|
|
...data, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isPositioned: openRef.current !== false |
|
|
}; |
|
|
if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) { |
|
|
dataRef.current = fullData; |
|
|
ReactDOM.flushSync(() => { |
|
|
setData(fullData); |
|
|
}); |
|
|
} |
|
|
}); |
|
|
}, [latestMiddleware, placement, strategy, platformRef, openRef]); |
|
|
index(() => { |
|
|
if (open === false && dataRef.current.isPositioned) { |
|
|
dataRef.current.isPositioned = false; |
|
|
setData(data => ({ |
|
|
...data, |
|
|
isPositioned: false |
|
|
})); |
|
|
} |
|
|
}, [open]); |
|
|
const isMountedRef = React.useRef(false); |
|
|
index(() => { |
|
|
isMountedRef.current = true; |
|
|
return () => { |
|
|
isMountedRef.current = false; |
|
|
}; |
|
|
}, []); |
|
|
index(() => { |
|
|
if (referenceEl) referenceRef.current = referenceEl; |
|
|
if (floatingEl) floatingRef.current = floatingEl; |
|
|
if (referenceEl && floatingEl) { |
|
|
if (whileElementsMountedRef.current) { |
|
|
return whileElementsMountedRef.current(referenceEl, floatingEl, update); |
|
|
} |
|
|
update(); |
|
|
} |
|
|
}, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]); |
|
|
const refs = React.useMemo(() => ({ |
|
|
reference: referenceRef, |
|
|
floating: floatingRef, |
|
|
setReference, |
|
|
setFloating |
|
|
}), [setReference, setFloating]); |
|
|
const elements = React.useMemo(() => ({ |
|
|
reference: referenceEl, |
|
|
floating: floatingEl |
|
|
}), [referenceEl, floatingEl]); |
|
|
const floatingStyles = React.useMemo(() => { |
|
|
const initialStyles = { |
|
|
position: strategy, |
|
|
left: 0, |
|
|
top: 0 |
|
|
}; |
|
|
if (!elements.floating) { |
|
|
return initialStyles; |
|
|
} |
|
|
const x = roundByDPR(elements.floating, data.x); |
|
|
const y = roundByDPR(elements.floating, data.y); |
|
|
if (transform) { |
|
|
return { |
|
|
...initialStyles, |
|
|
transform: "translate(" + x + "px, " + y + "px)", |
|
|
...(getDPR(elements.floating) >= 1.5 && { |
|
|
willChange: 'transform' |
|
|
}) |
|
|
}; |
|
|
} |
|
|
return { |
|
|
position: strategy, |
|
|
left: x, |
|
|
top: y |
|
|
}; |
|
|
}, [strategy, transform, elements.floating, data.x, data.y]); |
|
|
return React.useMemo(() => ({ |
|
|
...data, |
|
|
update, |
|
|
refs, |
|
|
elements, |
|
|
floatingStyles |
|
|
}), [data, update, refs, elements, floatingStyles]); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const arrow$1 = options => { |
|
|
function isRef(value) { |
|
|
return {}.hasOwnProperty.call(value, 'current'); |
|
|
} |
|
|
return { |
|
|
name: 'arrow', |
|
|
options, |
|
|
fn(state) { |
|
|
const { |
|
|
element, |
|
|
padding |
|
|
} = typeof options === 'function' ? options(state) : options; |
|
|
if (element && isRef(element)) { |
|
|
if (element.current != null) { |
|
|
return arrow$2({ |
|
|
element: element.current, |
|
|
padding |
|
|
}).fn(state); |
|
|
} |
|
|
return {}; |
|
|
} |
|
|
if (element) { |
|
|
return arrow$2({ |
|
|
element, |
|
|
padding |
|
|
}).fn(state); |
|
|
} |
|
|
return {}; |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const offset = (options, deps) => ({ |
|
|
...offset$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const shift = (options, deps) => ({ |
|
|
...shift$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const limitShift = (options, deps) => ({ |
|
|
...limitShift$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const flip = (options, deps) => ({ |
|
|
...flip$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const size = (options, deps) => ({ |
|
|
...size$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const autoPlacement = (options, deps) => ({ |
|
|
...autoPlacement$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const hide = (options, deps) => ({ |
|
|
...hide$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const inline = (options, deps) => ({ |
|
|
...inline$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const arrow = (options, deps) => ({ |
|
|
...arrow$1(options), |
|
|
options: [options, deps] |
|
|
}); |
|
|
|
|
|
export { arrow, autoPlacement, flip, hide, inline, limitShift, offset, shift, size, useFloating }; |
|
|
|