You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
349 lines
10 KiB
JavaScript
349 lines
10 KiB
JavaScript
(function (global, factory) {
|
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@floating-ui/dom'), require('react'), require('react-dom')) :
|
|
typeof define === 'function' && define.amd ? define(['exports', '@floating-ui/dom', 'react', 'react-dom'], factory) :
|
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FloatingUIReactDOM = {}, global.FloatingUIDOM, global.React, global.ReactDOM));
|
|
})(this, (function (exports, dom, React, ReactDOM) { 'use strict';
|
|
|
|
function _interopNamespaceDefault(e) {
|
|
var n = Object.create(null);
|
|
if (e) {
|
|
Object.keys(e).forEach(function (k) {
|
|
if (k !== 'default') {
|
|
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
Object.defineProperty(n, k, d.get ? d : {
|
|
enumerable: true,
|
|
get: function () { return e[k]; }
|
|
});
|
|
}
|
|
});
|
|
}
|
|
n.default = e;
|
|
return Object.freeze(n);
|
|
}
|
|
|
|
var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceDefault(ReactDOM);
|
|
|
|
/**
|
|
* Provides data to position an inner element of the floating element so that it
|
|
* appears centered to the reference element.
|
|
* This wraps the core `arrow` middleware to allow React refs as the element.
|
|
* @see https://floating-ui.com/docs/arrow
|
|
*/
|
|
const arrow = 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 dom.arrow({
|
|
element: element.current,
|
|
padding
|
|
}).fn(state);
|
|
}
|
|
return {};
|
|
}
|
|
if (element) {
|
|
return dom.arrow({
|
|
element,
|
|
padding
|
|
}).fn(state);
|
|
}
|
|
return {};
|
|
}
|
|
};
|
|
};
|
|
|
|
var index = typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
|
|
// Fork of `fast-deep-equal` that only does the comparisons we need and compares
|
|
// functions
|
|
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;
|
|
}
|
|
|
|
// biome-ignore lint/suspicious/noSelfCompare: in source
|
|
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__namespace.useRef(value);
|
|
index(() => {
|
|
ref.current = value;
|
|
});
|
|
return ref;
|
|
}
|
|
|
|
/**
|
|
* Provides data to position a floating element.
|
|
* @see https://floating-ui.com/docs/useFloating
|
|
*/
|
|
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__namespace.useState({
|
|
x: 0,
|
|
y: 0,
|
|
strategy,
|
|
placement,
|
|
middlewareData: {},
|
|
isPositioned: false
|
|
});
|
|
const [latestMiddleware, setLatestMiddleware] = React__namespace.useState(middleware);
|
|
if (!deepEqual(latestMiddleware, middleware)) {
|
|
setLatestMiddleware(middleware);
|
|
}
|
|
const [_reference, _setReference] = React__namespace.useState(null);
|
|
const [_floating, _setFloating] = React__namespace.useState(null);
|
|
const setReference = React__namespace.useCallback(node => {
|
|
if (node !== referenceRef.current) {
|
|
referenceRef.current = node;
|
|
_setReference(node);
|
|
}
|
|
}, []);
|
|
const setFloating = React__namespace.useCallback(node => {
|
|
if (node !== floatingRef.current) {
|
|
floatingRef.current = node;
|
|
_setFloating(node);
|
|
}
|
|
}, []);
|
|
const referenceEl = externalReference || _reference;
|
|
const floatingEl = externalFloating || _floating;
|
|
const referenceRef = React__namespace.useRef(null);
|
|
const floatingRef = React__namespace.useRef(null);
|
|
const dataRef = React__namespace.useRef(data);
|
|
const hasWhileElementsMounted = whileElementsMounted != null;
|
|
const whileElementsMountedRef = useLatestRef(whileElementsMounted);
|
|
const platformRef = useLatestRef(platform);
|
|
const update = React__namespace.useCallback(() => {
|
|
if (!referenceRef.current || !floatingRef.current) {
|
|
return;
|
|
}
|
|
const config = {
|
|
placement,
|
|
strategy,
|
|
middleware: latestMiddleware
|
|
};
|
|
if (platformRef.current) {
|
|
config.platform = platformRef.current;
|
|
}
|
|
dom.computePosition(referenceRef.current, floatingRef.current, config).then(data => {
|
|
const fullData = {
|
|
...data,
|
|
isPositioned: true
|
|
};
|
|
if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {
|
|
dataRef.current = fullData;
|
|
ReactDOM__namespace.flushSync(() => {
|
|
setData(fullData);
|
|
});
|
|
}
|
|
});
|
|
}, [latestMiddleware, placement, strategy, platformRef]);
|
|
index(() => {
|
|
if (open === false && dataRef.current.isPositioned) {
|
|
dataRef.current.isPositioned = false;
|
|
setData(data => ({
|
|
...data,
|
|
isPositioned: false
|
|
}));
|
|
}
|
|
}, [open]);
|
|
const isMountedRef = React__namespace.useRef(false);
|
|
index(() => {
|
|
isMountedRef.current = true;
|
|
return () => {
|
|
isMountedRef.current = false;
|
|
};
|
|
}, []);
|
|
|
|
// biome-ignore lint/correctness/useExhaustiveDependencies: `hasWhileElementsMounted` is intentionally included.
|
|
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__namespace.useMemo(() => ({
|
|
reference: referenceRef,
|
|
floating: floatingRef,
|
|
setReference,
|
|
setFloating
|
|
}), [setReference, setFloating]);
|
|
const elements = React__namespace.useMemo(() => ({
|
|
reference: referenceEl,
|
|
floating: floatingEl
|
|
}), [referenceEl, floatingEl]);
|
|
const floatingStyles = React__namespace.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__namespace.useMemo(() => ({
|
|
...data,
|
|
update,
|
|
refs,
|
|
elements,
|
|
floatingStyles
|
|
}), [data, update, refs, elements, floatingStyles]);
|
|
}
|
|
|
|
Object.defineProperty(exports, "autoPlacement", {
|
|
enumerable: true,
|
|
get: function () { return dom.autoPlacement; }
|
|
});
|
|
Object.defineProperty(exports, "autoUpdate", {
|
|
enumerable: true,
|
|
get: function () { return dom.autoUpdate; }
|
|
});
|
|
Object.defineProperty(exports, "computePosition", {
|
|
enumerable: true,
|
|
get: function () { return dom.computePosition; }
|
|
});
|
|
Object.defineProperty(exports, "detectOverflow", {
|
|
enumerable: true,
|
|
get: function () { return dom.detectOverflow; }
|
|
});
|
|
Object.defineProperty(exports, "flip", {
|
|
enumerable: true,
|
|
get: function () { return dom.flip; }
|
|
});
|
|
Object.defineProperty(exports, "getOverflowAncestors", {
|
|
enumerable: true,
|
|
get: function () { return dom.getOverflowAncestors; }
|
|
});
|
|
Object.defineProperty(exports, "hide", {
|
|
enumerable: true,
|
|
get: function () { return dom.hide; }
|
|
});
|
|
Object.defineProperty(exports, "inline", {
|
|
enumerable: true,
|
|
get: function () { return dom.inline; }
|
|
});
|
|
Object.defineProperty(exports, "limitShift", {
|
|
enumerable: true,
|
|
get: function () { return dom.limitShift; }
|
|
});
|
|
Object.defineProperty(exports, "offset", {
|
|
enumerable: true,
|
|
get: function () { return dom.offset; }
|
|
});
|
|
Object.defineProperty(exports, "platform", {
|
|
enumerable: true,
|
|
get: function () { return dom.platform; }
|
|
});
|
|
Object.defineProperty(exports, "shift", {
|
|
enumerable: true,
|
|
get: function () { return dom.shift; }
|
|
});
|
|
Object.defineProperty(exports, "size", {
|
|
enumerable: true,
|
|
get: function () { return dom.size; }
|
|
});
|
|
exports.arrow = arrow;
|
|
exports.useFloating = useFloating;
|
|
|
|
}));
|