floating-ui.react-dom.umd.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@floating-ui/dom'), require('react'), require('react-dom')) :
  3. typeof define === 'function' && define.amd ? define(['exports', '@floating-ui/dom', 'react', 'react-dom'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FloatingUIReactDOM = {}, global.FloatingUIDOM, global.React, global.ReactDOM));
  5. })(this, (function (exports, dom, React, ReactDOM) { 'use strict';
  6. function _interopNamespaceDefault(e) {
  7. var n = Object.create(null);
  8. if (e) {
  9. Object.keys(e).forEach(function (k) {
  10. if (k !== 'default') {
  11. var d = Object.getOwnPropertyDescriptor(e, k);
  12. Object.defineProperty(n, k, d.get ? d : {
  13. enumerable: true,
  14. get: function () { return e[k]; }
  15. });
  16. }
  17. });
  18. }
  19. n.default = e;
  20. return Object.freeze(n);
  21. }
  22. var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
  23. var ReactDOM__namespace = /*#__PURE__*/_interopNamespaceDefault(ReactDOM);
  24. /**
  25. * Provides data to position an inner element of the floating element so that it
  26. * appears centered to the reference element.
  27. * This wraps the core `arrow` middleware to allow React refs as the element.
  28. * @see https://floating-ui.com/docs/arrow
  29. */
  30. const arrow = options => {
  31. function isRef(value) {
  32. return {}.hasOwnProperty.call(value, 'current');
  33. }
  34. return {
  35. name: 'arrow',
  36. options,
  37. fn(state) {
  38. const {
  39. element,
  40. padding
  41. } = typeof options === 'function' ? options(state) : options;
  42. if (element && isRef(element)) {
  43. if (element.current != null) {
  44. return dom.arrow({
  45. element: element.current,
  46. padding
  47. }).fn(state);
  48. }
  49. return {};
  50. }
  51. if (element) {
  52. return dom.arrow({
  53. element,
  54. padding
  55. }).fn(state);
  56. }
  57. return {};
  58. }
  59. };
  60. };
  61. var index = typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect;
  62. // Fork of `fast-deep-equal` that only does the comparisons we need and compares
  63. // functions
  64. function deepEqual(a, b) {
  65. if (a === b) {
  66. return true;
  67. }
  68. if (typeof a !== typeof b) {
  69. return false;
  70. }
  71. if (typeof a === 'function' && a.toString() === b.toString()) {
  72. return true;
  73. }
  74. let length;
  75. let i;
  76. let keys;
  77. if (a && b && typeof a === 'object') {
  78. if (Array.isArray(a)) {
  79. length = a.length;
  80. if (length !== b.length) return false;
  81. for (i = length; i-- !== 0;) {
  82. if (!deepEqual(a[i], b[i])) {
  83. return false;
  84. }
  85. }
  86. return true;
  87. }
  88. keys = Object.keys(a);
  89. length = keys.length;
  90. if (length !== Object.keys(b).length) {
  91. return false;
  92. }
  93. for (i = length; i-- !== 0;) {
  94. if (!{}.hasOwnProperty.call(b, keys[i])) {
  95. return false;
  96. }
  97. }
  98. for (i = length; i-- !== 0;) {
  99. const key = keys[i];
  100. if (key === '_owner' && a.$$typeof) {
  101. continue;
  102. }
  103. if (!deepEqual(a[key], b[key])) {
  104. return false;
  105. }
  106. }
  107. return true;
  108. }
  109. // biome-ignore lint/suspicious/noSelfCompare: in source
  110. return a !== a && b !== b;
  111. }
  112. function getDPR(element) {
  113. if (typeof window === 'undefined') {
  114. return 1;
  115. }
  116. const win = element.ownerDocument.defaultView || window;
  117. return win.devicePixelRatio || 1;
  118. }
  119. function roundByDPR(element, value) {
  120. const dpr = getDPR(element);
  121. return Math.round(value * dpr) / dpr;
  122. }
  123. function useLatestRef(value) {
  124. const ref = React__namespace.useRef(value);
  125. index(() => {
  126. ref.current = value;
  127. });
  128. return ref;
  129. }
  130. /**
  131. * Provides data to position a floating element.
  132. * @see https://floating-ui.com/docs/useFloating
  133. */
  134. function useFloating(options) {
  135. if (options === void 0) {
  136. options = {};
  137. }
  138. const {
  139. placement = 'bottom',
  140. strategy = 'absolute',
  141. middleware = [],
  142. platform,
  143. elements: {
  144. reference: externalReference,
  145. floating: externalFloating
  146. } = {},
  147. transform = true,
  148. whileElementsMounted,
  149. open
  150. } = options;
  151. const [data, setData] = React__namespace.useState({
  152. x: 0,
  153. y: 0,
  154. strategy,
  155. placement,
  156. middlewareData: {},
  157. isPositioned: false
  158. });
  159. const [latestMiddleware, setLatestMiddleware] = React__namespace.useState(middleware);
  160. if (!deepEqual(latestMiddleware, middleware)) {
  161. setLatestMiddleware(middleware);
  162. }
  163. const [_reference, _setReference] = React__namespace.useState(null);
  164. const [_floating, _setFloating] = React__namespace.useState(null);
  165. const setReference = React__namespace.useCallback(node => {
  166. if (node !== referenceRef.current) {
  167. referenceRef.current = node;
  168. _setReference(node);
  169. }
  170. }, []);
  171. const setFloating = React__namespace.useCallback(node => {
  172. if (node !== floatingRef.current) {
  173. floatingRef.current = node;
  174. _setFloating(node);
  175. }
  176. }, []);
  177. const referenceEl = externalReference || _reference;
  178. const floatingEl = externalFloating || _floating;
  179. const referenceRef = React__namespace.useRef(null);
  180. const floatingRef = React__namespace.useRef(null);
  181. const dataRef = React__namespace.useRef(data);
  182. const hasWhileElementsMounted = whileElementsMounted != null;
  183. const whileElementsMountedRef = useLatestRef(whileElementsMounted);
  184. const platformRef = useLatestRef(platform);
  185. const update = React__namespace.useCallback(() => {
  186. if (!referenceRef.current || !floatingRef.current) {
  187. return;
  188. }
  189. const config = {
  190. placement,
  191. strategy,
  192. middleware: latestMiddleware
  193. };
  194. if (platformRef.current) {
  195. config.platform = platformRef.current;
  196. }
  197. dom.computePosition(referenceRef.current, floatingRef.current, config).then(data => {
  198. const fullData = {
  199. ...data,
  200. isPositioned: true
  201. };
  202. if (isMountedRef.current && !deepEqual(dataRef.current, fullData)) {
  203. dataRef.current = fullData;
  204. ReactDOM__namespace.flushSync(() => {
  205. setData(fullData);
  206. });
  207. }
  208. });
  209. }, [latestMiddleware, placement, strategy, platformRef]);
  210. index(() => {
  211. if (open === false && dataRef.current.isPositioned) {
  212. dataRef.current.isPositioned = false;
  213. setData(data => ({
  214. ...data,
  215. isPositioned: false
  216. }));
  217. }
  218. }, [open]);
  219. const isMountedRef = React__namespace.useRef(false);
  220. index(() => {
  221. isMountedRef.current = true;
  222. return () => {
  223. isMountedRef.current = false;
  224. };
  225. }, []);
  226. // biome-ignore lint/correctness/useExhaustiveDependencies: `hasWhileElementsMounted` is intentionally included.
  227. index(() => {
  228. if (referenceEl) referenceRef.current = referenceEl;
  229. if (floatingEl) floatingRef.current = floatingEl;
  230. if (referenceEl && floatingEl) {
  231. if (whileElementsMountedRef.current) {
  232. return whileElementsMountedRef.current(referenceEl, floatingEl, update);
  233. }
  234. update();
  235. }
  236. }, [referenceEl, floatingEl, update, whileElementsMountedRef, hasWhileElementsMounted]);
  237. const refs = React__namespace.useMemo(() => ({
  238. reference: referenceRef,
  239. floating: floatingRef,
  240. setReference,
  241. setFloating
  242. }), [setReference, setFloating]);
  243. const elements = React__namespace.useMemo(() => ({
  244. reference: referenceEl,
  245. floating: floatingEl
  246. }), [referenceEl, floatingEl]);
  247. const floatingStyles = React__namespace.useMemo(() => {
  248. const initialStyles = {
  249. position: strategy,
  250. left: 0,
  251. top: 0
  252. };
  253. if (!elements.floating) {
  254. return initialStyles;
  255. }
  256. const x = roundByDPR(elements.floating, data.x);
  257. const y = roundByDPR(elements.floating, data.y);
  258. if (transform) {
  259. return {
  260. ...initialStyles,
  261. transform: "translate(" + x + "px, " + y + "px)",
  262. ...(getDPR(elements.floating) >= 1.5 && {
  263. willChange: 'transform'
  264. })
  265. };
  266. }
  267. return {
  268. position: strategy,
  269. left: x,
  270. top: y
  271. };
  272. }, [strategy, transform, elements.floating, data.x, data.y]);
  273. return React__namespace.useMemo(() => ({
  274. ...data,
  275. update,
  276. refs,
  277. elements,
  278. floatingStyles
  279. }), [data, update, refs, elements, floatingStyles]);
  280. }
  281. Object.defineProperty(exports, "autoPlacement", {
  282. enumerable: true,
  283. get: function () { return dom.autoPlacement; }
  284. });
  285. Object.defineProperty(exports, "autoUpdate", {
  286. enumerable: true,
  287. get: function () { return dom.autoUpdate; }
  288. });
  289. Object.defineProperty(exports, "computePosition", {
  290. enumerable: true,
  291. get: function () { return dom.computePosition; }
  292. });
  293. Object.defineProperty(exports, "detectOverflow", {
  294. enumerable: true,
  295. get: function () { return dom.detectOverflow; }
  296. });
  297. Object.defineProperty(exports, "flip", {
  298. enumerable: true,
  299. get: function () { return dom.flip; }
  300. });
  301. Object.defineProperty(exports, "getOverflowAncestors", {
  302. enumerable: true,
  303. get: function () { return dom.getOverflowAncestors; }
  304. });
  305. Object.defineProperty(exports, "hide", {
  306. enumerable: true,
  307. get: function () { return dom.hide; }
  308. });
  309. Object.defineProperty(exports, "inline", {
  310. enumerable: true,
  311. get: function () { return dom.inline; }
  312. });
  313. Object.defineProperty(exports, "limitShift", {
  314. enumerable: true,
  315. get: function () { return dom.limitShift; }
  316. });
  317. Object.defineProperty(exports, "offset", {
  318. enumerable: true,
  319. get: function () { return dom.offset; }
  320. });
  321. Object.defineProperty(exports, "platform", {
  322. enumerable: true,
  323. get: function () { return dom.platform; }
  324. });
  325. Object.defineProperty(exports, "shift", {
  326. enumerable: true,
  327. get: function () { return dom.shift; }
  328. });
  329. Object.defineProperty(exports, "size", {
  330. enumerable: true,
  331. get: function () { return dom.size; }
  332. });
  333. exports.arrow = arrow;
  334. exports.useFloating = useFloating;
  335. }));