diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7dfd0d5fffe9538e41284fe9ee3509479dec402..f70ad237edb4058a3d56928f7603dc68e0220592 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
# CHANGELOG
+### v1.0.0-beta.2
+- change hovercard naming for popover
+
### v1.0.0-beta.1
- fix path helpers in hovercard templates
- fix call to clearHovercard in closing.js
diff --git a/README.md b/README.md
index 3c7fe15a3a62e2dd24c647750ecc38ebecc72ff7..c6a01b202466d743cc36d9404db15d1351501824 100644
--- a/README.md
+++ b/README.md
@@ -1,35 +1,35 @@
# Coupdoeil
[](https://badge.fury.io/rb/coupdoeil)
-A framework to easily handle hovercards.
+A framework to easily handle popovers.
## Documentation
See [coupdoeil.org](https://coupdoeil.org) for full documentation.
## Overview
-### What is a Coupdoeil::Hovercard?
+### What is a Coupdoeil::Popover?
-Hovercards are ruby objects used to easily build powerful popups (from basic tooltips to full dialog hovercards).
-They are mostly inspired by GitHub hovercards (like hovering on a link to a repo, or a username)
+Popovers are ruby objects used to easily build powerful popups (from basic tooltips to full dialog popovers).
+They are mostly inspired by GitHub popovers (like hovering on a link to a repo, or a username)
and Wikipedia popups (when hovering a link to another wikipedia article).
Click to toggle examples
A quick look on a contact details
-
+
A form in a popup
-
+
[See more use-cases](https://coupdoeil.org/case-studies.html)
The current implementation takes inspiration from both ViewComponent and ActionMailer, to make it as easy as possible to use while offering a wide range of possibilities.
```ruby
-# app/hovercards/contact_hovercard.rb
-class ContactHovercard < Coupdoeil::Hovercard
+# app/popovers/contact_popover.rb
+class ContactPopover < Coupdoeil::Popover
def details
@contact = params[:contact]
end
@@ -37,7 +37,7 @@ end
```
```erb
-<%# app/hovercards/contact_hovercard/details.html.erb %>
+<%# app/popovers/contact_popover/details.html.erb %>
<%= image_tag @contact.avatar %>
<%= @contact.first_name %> <%= @contact.last_name %>
@@ -51,40 +51,40 @@ Which is embedded by doing so:
<%# app/views/messages/show.html.erb %>
From:
- <%= coupdoeil_hovercard_tag ContactHovercard.with(contact: @contact).details do %>
+ <%= coupdoeil_popover_tag ContactPopover.with(contact: @contact).details do %>
<%= @contact.email %>
<% end %>
```
-### Why use Coupdoeil hovercards?
+### Why use Coupdoeil popovers?
-The concept of 'quick look' allowed by hovercards can really improve UX by avoiding the need to navigate to another page and back again just to check summary for a resource.
+The concept of 'quick look' allowed by popovers can really improve UX by avoiding the need to navigate to another page and back again just to check summary for a resource.
It also permits to hiding until use some parts of UI like small forms, or quick actions in a list of elements.
-The most common examples of such hovercard are on GitHub (when hovering over a link to a repo, user profile, a PR, etc.) or on
+The most common examples of such popover are on GitHub (when hovering over a link to a repo, user profile, a PR, etc.) or on
Wikipedia (when hovering over a link to another article).
While basic popups implementations can be made with simple helpers, data-attributes, and a bit of JavaScript,
it tends to get too complex over time and often not handle enough edge-cases to be used everywhere it could improve UX.
-`Coupdoeil::Hovercard` offers a way to easily encapsulate and power up hovercards rendering logic.
+`Coupdoeil::Popover` offers a way to easily encapsulate and power up popovers rendering logic.
It allows a lot of customization possibilities (see [options](https://coupdoeil.org/opts.html)) and promotes re-usability by using an API similar to
parameterized ActionMailer (see [Why does it look like a mailer?](https://coupdoeil.org/architectural-decisions.html#why-does-it-look-like-a-mailer)).
-This gem also tries to handle all known issues of such hovercards, such as
-the user's mouse quickly leaving and re-entering hovercard without closing it,
-preventing opening of an hovercard if mouse did not stop on it, etc.
+This gem also tries to handle all known issues of such popovers, such as
+the user's mouse quickly leaving and re-entering popover without closing it,
+preventing opening of an popover if mouse did not stop on it, etc.
### Performances
-By default, an hovercard content is not loaded until it is needed.
+By default, an popover content is not loaded until it is needed.
It means the DOM is not cluttered with 'maybe to be used' HTML, hidden in template tags or data-attributes.
-However, params have to be present in HTML so they are sent for rendering the hovercard (eg: a record id),
+However, params have to be present in HTML so they are sent for rendering the popover (eg: a record id),
so try passing as few as required to build it later during render.
-Also, hovercards are cached so the fetch happens only the first time an hovercard is open.
+Also, popovers are cached so the fetch happens only the first time an popover is open.
-When needed, hovercards can still be preloaded and included in DOM on initial page load. See [preload option](https://coupdoeil.org/options/loading.html).
+When needed, popovers can still be preloaded and included in DOM on initial page load. See [preload option](https://coupdoeil.org/options/loading.html).
## Licence
Coupdoeil is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT)
diff --git a/app/assets/javascripts/coupdoeil.js b/app/assets/javascripts/coupdoeil.js
index 47f0176cd423a6c8ac86cceab5f7f14d7ae84daf..29b07236c286c90e7bb576fa9466a064f669167e 100644
--- a/app/assets/javascripts/coupdoeil.js
+++ b/app/assets/javascripts/coupdoeil.js
@@ -1,4 +1,4 @@
-class HovercardController {
+class PopoverController {
constructor(coupdoeilElement) {
this.coupdoeilElement = coupdoeilElement;
this.card = null;
@@ -7,18 +7,18 @@ class HovercardController {
this.closingRequest = null;
}
get isOpen() {
- return !!this.coupdoeilElement.dataset.hovercardOpen;
+ return !!this.coupdoeilElement.dataset.popoverOpen;
}
get isClosed() {
return !this.isOpen;
}
}
-const HOVERCARD_CLASS_NAME = "coupdoeil--hovercard";
+const POPOVER_CLASS_NAME = "coupdoeil--popover";
-const HOVERCARD_SELECTOR = `.${HOVERCARD_CLASS_NAME}`;
+const POPOVER_SELECTOR = `.${POPOVER_CLASS_NAME}`;
-const HOVERCARD_CLOSE_BTN_SELECTOR = "[data-hovercard-close]";
+const POPOVER_CLOSE_BTN_SELECTOR = "[data-popover-close]";
const CLOSING_DELAY_MS = 75;
@@ -115,7 +115,7 @@ function getTrigger$1(optionsInt) {
return TRIGGERS[optionsInt & 1];
}
-const HovercardOptions = {
+const popoverOptions = {
animation: undefined,
cache: undefined,
loading: undefined,
@@ -126,8 +126,8 @@ const HovercardOptions = {
};
function extractOptionsFromElement(coupdoeilElement) {
- const optionsInt = coupdoeilElement.hovercardController.optionsInt ||= parseOtionsInt(coupdoeilElement);
- const options = Object.create(HovercardOptions);
+ const optionsInt = coupdoeilElement.popoverController.optionsInt ||= parseOtionsInt(coupdoeilElement);
+ const options = Object.create(popoverOptions);
for (const option of ORDERED_OPTIONS) {
options[option] = OPTIONS[option].getter(optionsInt);
}
@@ -135,21 +135,21 @@ function extractOptionsFromElement(coupdoeilElement) {
}
function parseOtionsInt(coupdoeilElement) {
- const optionsString = coupdoeilElement.getAttribute("hc");
+ const optionsString = coupdoeilElement.getAttribute("popover-options");
return parseInt(optionsString, 36);
}
function extractOptionFromElement(coupdoeilElement, optionName) {
- const optionsInt = coupdoeilElement.hovercardController.optionsInt ||= parseOtionsInt(coupdoeilElement);
+ const optionsInt = coupdoeilElement.popoverController.optionsInt ||= parseOtionsInt(coupdoeilElement);
return OPTIONS[optionName].getter(optionsInt);
}
function getType(controller) {
- return controller.coupdoeilElement.getAttribute("hc-type");
+ return controller.coupdoeilElement.getAttribute("popover-type");
}
function getParams(controller) {
- return controller.coupdoeilElement.getAttribute("hc-params");
+ return controller.coupdoeilElement.getAttribute("popover-params");
}
function getTrigger(controller) {
@@ -173,10 +173,10 @@ function notTriggeredOnHover(controller) {
}
function preloadedContentElement(controller) {
- return controller.coupdoeilElement.querySelector(".hovercard-content");
+ return controller.coupdoeilElement.querySelector(".popover-content");
}
-const hovercardContentHTMLMap = new Map;
+const popoverContentHTMLMap = new Map;
function cacheMapKey(controller) {
if (preloadedContentElement(controller)) {
@@ -185,16 +185,16 @@ function cacheMapKey(controller) {
return getType(controller) + getParams(controller);
}
-function getHovercardContentHTML(controller) {
- return hovercardContentHTMLMap.get(cacheMapKey(controller));
+function getPopoverContentHTML(controller) {
+ return popoverContentHTMLMap.get(cacheMapKey(controller));
}
-function setHovercardContentHTML(controller, value) {
- hovercardContentHTMLMap.set(cacheMapKey(controller), value);
+function setPopoverContentHTML(controller, value) {
+ popoverContentHTMLMap.set(cacheMapKey(controller), value);
}
-function clearHovercardContentCache() {
- hovercardContentHTMLMap.clear();
+function clearPopoverContentCache() {
+ popoverContentHTMLMap.clear();
}
const sides = [ "top", "right", "bottom", "left" ];
@@ -1771,10 +1771,10 @@ const computePosition = (reference, floating, options) => {
});
};
-async function positionHovercard(target, card, options) {
+async function positionPopover(target, card, options) {
let {placement: placements, offset: offsetValue} = options;
const placement = placements[0];
- const arrowElement = card.querySelector("[data-hovercard-arrow]");
+ const arrowElement = card.querySelector("[data-popover-arrow]");
const middleware = [ AutoPositioningWithFallbacks(placements) ];
if (arrowElement) {
const arrowSize = arrowElement.clientWidth;
@@ -1898,18 +1898,18 @@ function afterTransition(element) {
}));
}
-const CURRENT_HOVERCARDS_BY_ID = new Map;
+const CURRENT_POPOVERS_BY_ID = new Map;
-function currentHovercardsById() {
- return CURRENT_HOVERCARDS_BY_ID;
+function currentPopoversById() {
+ return CURRENT_POPOVERS_BY_ID;
}
function addToCurrents(coupdoeilElement) {
- CURRENT_HOVERCARDS_BY_ID.set(coupdoeilElement.uniqueId, coupdoeilElement);
+ CURRENT_POPOVERS_BY_ID.set(coupdoeilElement.uniqueId, coupdoeilElement);
}
function removeFromCurrents(coupdoeilElement) {
- CURRENT_HOVERCARDS_BY_ID.delete(coupdoeilElement.uniqueId);
+ CURRENT_POPOVERS_BY_ID.delete(coupdoeilElement.uniqueId);
}
function detachFromParent(controller) {
@@ -1925,7 +1925,7 @@ function cancelOpenCloseActions(controller) {
}
function cancelOpening(controller) {
- delete controller.coupdoeilElement.openingHovercard;
+ delete controller.coupdoeilElement.openingPopover;
}
function cancelCloseRequest(controller) {
@@ -1935,7 +1935,7 @@ function cancelCloseRequest(controller) {
}
function closeNow(controller, allowAnimation = true) {
- if (controller.closing || controller.isClosed && !controller.coupdoeilElement.openingHovercard) return;
+ if (controller.closing || controller.isClosed && !controller.coupdoeilElement.openingPopover) return;
controller.closing = true;
cancelOpenCloseActions(controller);
controller.children.forEach((childController => {
@@ -1950,7 +1950,7 @@ function closeNow(controller, allowAnimation = true) {
}
async function closeWithAnimation(controller) {
- await leave(controller.card, "hovercard");
+ await leave(controller.card, "popover");
closeWithoutAnimation(controller);
}
@@ -1960,7 +1960,7 @@ function closeWithoutAnimation(controller) {
controller.card = null;
}
delete controller.closing;
- delete controller.coupdoeilElement.dataset.hovercardOpen;
+ delete controller.coupdoeilElement.dataset.popoverOpen;
}
function clear(controller) {
@@ -1989,23 +1989,23 @@ function closeOnHoverChildrenLater(controller) {
}
function closeAllNow() {
- for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
- closeNow(coupdoeilElement.hovercardController);
+ for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
+ closeNow(coupdoeilElement.popoverController);
removeFromCurrents(coupdoeilElement);
}
}
function clearAll() {
- for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
- clear(coupdoeilElement.hovercardController);
+ for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
+ clear(coupdoeilElement.popoverController);
removeFromCurrents(coupdoeilElement);
}
}
function closeTriggeredOnHoverLater() {
- for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
- if (triggeredOnHover(coupdoeilElement.hovercardController)) {
- closeLater(coupdoeilElement.hovercardController);
+ for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
+ if (triggeredOnHover(coupdoeilElement.popoverController)) {
+ closeLater(coupdoeilElement.popoverController);
removeFromCurrents(coupdoeilElement);
}
}
@@ -2017,19 +2017,19 @@ function closeTriggeredOnHoverNowUnlessAncestor(controller) {
topMostParent = topMostParent.parent;
}
const idToSkip = topMostParent.coupdoeilElement.uniqueId;
- for (const coupdoeilElement of CURRENT_HOVERCARDS_BY_ID.values()) {
- if (coupdoeilElement.uniqueId !== idToSkip && triggeredOnHover(coupdoeilElement.hovercardController)) {
- closeNow(coupdoeilElement.hovercardController);
+ for (const coupdoeilElement of CURRENT_POPOVERS_BY_ID.values()) {
+ if (coupdoeilElement.uniqueId !== idToSkip && triggeredOnHover(coupdoeilElement.popoverController)) {
+ closeNow(coupdoeilElement.popoverController);
removeFromCurrents(coupdoeilElement);
}
}
}
-function fetchHovercardContent(controller) {
+function fetchPopoverContent(controller) {
const type = getType(controller);
const params = getParams(controller);
const authenticityToken = document.querySelector("meta[name=csrf-token]").content;
- let url = `/coupdoeil/hovercard`;
+ let url = `/coupdoeil/popover`;
const opts = {
method: "POST",
headers: {
@@ -2043,31 +2043,31 @@ function fetchHovercardContent(controller) {
};
return fetch(url, opts).then((response => {
if (response.status >= 400) {
- throw "error while fetching hovercard content";
+ throw "error while fetching popover content";
}
return response.text();
}));
}
-async function loadHovercardContentHTML(controller, options, delayOptions) {
+async function loadPopoverContentHTML(controller, options, delayOptions) {
return new Promise((resolve => {
setTimeout((async () => {
- if (!controller.coupdoeilElement.openingHovercard) return;
- if (options.cache === false || options.cache && !getHovercardContentHTML(controller)) {
+ if (!controller.coupdoeilElement.openingPopover) return;
+ if (options.cache === false || options.cache && !getPopoverContentHTML(controller)) {
let html;
if (options.loading === "preload") {
html = preloadedContentElement(controller).innerHTML;
} else {
- html = await fetchHovercardContent(controller);
+ html = await fetchPopoverContent(controller);
}
- setHovercardContentHTML(controller, html);
+ setPopoverContentHTML(controller, html);
}
resolve();
}), delayOptions.fetch);
}));
}
-async function openHovercard(controller, {parent: parent, beforeDisplay: beforeDisplay}) {
+async function openPopover(controller, {parent: parent, beforeDisplay: beforeDisplay}) {
if (controller.isOpen) {
return cancelCloseRequest(controller);
}
@@ -2078,10 +2078,10 @@ async function openHovercard(controller, {parent: parent, beforeDisplay: beforeD
const options = extractOptionsFromElement(controller.coupdoeilElement);
const delays = getDelayOptionsForController(controller, options);
const openingDelay = new Promise((resolve => setTimeout(resolve, delays.opening)));
- const fetchDelay = loadHovercardContentHTML(controller, options, delays);
+ const fetchDelay = loadPopoverContentHTML(controller, options, delays);
await Promise.all([ fetchDelay, openingDelay ]);
const parentIsClosedOrClosing = controller.parent && (controller.parent.isClosed || controller.parent.closingRequest);
- if (controller.coupdoeilElement.openingHovercard && !parentIsClosedOrClosing) {
+ if (controller.coupdoeilElement.openingPopover && !parentIsClosedOrClosing) {
await display(controller, options, beforeDisplay);
}
}
@@ -2089,13 +2089,13 @@ async function openHovercard(controller, {parent: parent, beforeDisplay: beforeD
async function display(controller, options, beforeDisplay) {
if (controller.isOpen) return;
cancelCloseRequest(controller);
- controller.card = buildHovercardElement(controller, options);
+ controller.card = buildPopoverElement(controller, options);
document.body.appendChild(controller.card);
if (options.animation) {
controller.card.dataset.animation = options.animation;
}
executeNextFrameIfStillOpening(controller, (async () => {
- await positionHovercard(controller.coupdoeilElement, controller.card, options);
+ await positionPopover(controller.coupdoeilElement, controller.card, options);
controller.card.classList.add("hidden");
controller.card.style.removeProperty("visibility");
executeNextFrameIfStillOpening(controller, (async () => {
@@ -2103,16 +2103,16 @@ async function display(controller, options, beforeDisplay) {
beforeDisplay(controller);
}
addToCurrents(controller.coupdoeilElement);
- delete controller.coupdoeilElement.openingHovercard;
- controller.coupdoeilElement.dataset.hovercardOpen = true;
- await enter(controller.card, "hovercard");
+ delete controller.coupdoeilElement.openingPopover;
+ controller.coupdoeilElement.dataset.popoverOpen = true;
+ await enter(controller.card, "popover");
}));
}));
}
function executeNextFrameIfStillOpening(controller, callback) {
requestAnimationFrame((() => {
- if (controller.coupdoeilElement.openingHovercard) {
+ if (controller.coupdoeilElement.openingPopover) {
callback.call();
} else {
clear(controller);
@@ -2133,12 +2133,12 @@ function getDelayOptionsForController(controller, options) {
};
}
-function buildHovercardElement(controller, options) {
+function buildPopoverElement(controller, options) {
const el = document.createElement("div");
el.setAttribute("role", "dialog");
- el.classList.add(HOVERCARD_CLASS_NAME);
+ el.classList.add(POPOVER_CLASS_NAME);
el.style.cssText = "position: absolute; left: 0; top: 0;";
- el.innerHTML = getHovercardContentHTML(controller);
+ el.innerHTML = getPopoverContentHTML(controller);
el.controller = controller;
el.dataset.placement = options.placement;
el.style.visibility = "hidden";
@@ -2155,20 +2155,20 @@ class CoupdoeilElement extends HTMLElement {
constructor() {
super();
this.uniqueId = generateUniqueId();
- this.hovercardController = new HovercardController(this);
+ this.popoverController = new PopoverController(this);
}
- openHovercard(triggerElement = null, callbacks) {
- if (this.openingHovercard || this.hovercardController.isOpen || this.disabled || triggerElement === this) return;
- this.openingHovercard = true;
- const parent = this.closest(HOVERCARD_SELECTOR)?.controller;
+ openPopover(triggerElement = null, callbacks) {
+ if (this.openingPopover || this.popoverController.isOpen || this.disabled || triggerElement === this) return;
+ this.openingPopover = true;
+ const parent = this.closest(POPOVER_SELECTOR)?.controller;
addToCurrents(this);
- return openHovercard(this.hovercardController, {
+ return openPopover(this.popoverController, {
parent: parent,
...callbacks
});
}
- closeHovercard() {
- closeNow(this.hovercardController);
+ closePopover() {
+ closeNow(this.popoverController);
}
get disabled() {
return !!this.getAttribute("disabled");
@@ -2182,119 +2182,119 @@ class CoupdoeilElement extends HTMLElement {
}
}
-function isElementCloseHovercardButton(element) {
- return element.closest(HOVERCARD_CLOSE_BTN_SELECTOR) || element.dataset.hasOwnProperty("hovercardClose");
+function isElementClosePopoverButton(element) {
+ return element.closest(POPOVER_CLOSE_BTN_SELECTOR) || element.dataset.hasOwnProperty("popoverClose");
}
-function isAnyHovercardOpened() {
- return currentHovercardsById().size > 0;
+function isAnyPopoverOpened() {
+ return currentPopoversById().size > 0;
}
const coupdoeilOnClickEvent = ({target: clickedElement}) => {
const coupdoeilElement = clickedElement.closest("coup-doeil");
- const hovercardElement = clickedElement.closest(HOVERCARD_SELECTOR);
- if (coupdoeilElement && hovercardElement) {
- handleClickedCoupdoeilWithinHovercard(coupdoeilElement, hovercardElement, clickedElement);
+ const popoverElement = clickedElement.closest(POPOVER_SELECTOR);
+ if (coupdoeilElement && popoverElement) {
+ handleClickedCoupdoeilWithinPopover(coupdoeilElement, popoverElement, clickedElement);
} else if (coupdoeilElement) {
- handleClickedCoupdoeilOutsideHovercard(coupdoeilElement, clickedElement);
- } else if (hovercardElement) {
- handleClickOutsideCoupdoeilButWithinHovercard(hovercardElement, clickedElement);
+ handleClickedCoupdoeilOutsidePopover(coupdoeilElement, clickedElement);
+ } else if (popoverElement) {
+ handleClickOutsideCoupdoeilButWithinPopover(popoverElement, clickedElement);
} else {
- handleClickOutsideCoupdoeilAndHovercard();
+ handleClickOutsideCoupdoeilAndPopover();
}
};
-function handleClickedCoupdoeilWithinHovercard(coupdoeilElement, _hovercardElement, clickedElement) {
- const hovercard = coupdoeilElement.hovercardController;
- if (noTriggeredOnClick(hovercard)) return;
- if (hovercard.isOpen) {
- closeNow(hovercard);
+function handleClickedCoupdoeilWithinPopover(coupdoeilElement, _popoverElement, clickedElement) {
+ const popover = coupdoeilElement.popoverController;
+ if (noTriggeredOnClick(popover)) return;
+ if (popover.isOpen) {
+ closeNow(popover);
} else {
- coupdoeilElement.openHovercard(clickedElement);
+ coupdoeilElement.openPopover(clickedElement);
}
}
-function handleClickedCoupdoeilOutsideHovercard(coupdoeilElement, clickedElement) {
- const hovercard = coupdoeilElement.hovercardController;
- if (noTriggeredOnClick(hovercard)) return;
- if (hovercard.isOpen) {
- closeNow(hovercard);
+function handleClickedCoupdoeilOutsidePopover(coupdoeilElement, clickedElement) {
+ const popover = coupdoeilElement.popoverController;
+ if (noTriggeredOnClick(popover)) return;
+ if (popover.isOpen) {
+ closeNow(popover);
} else {
closeAllNow();
- coupdoeilElement.openHovercard(clickedElement);
+ coupdoeilElement.openPopover(clickedElement);
}
}
-function handleClickOutsideCoupdoeilButWithinHovercard(hovercardElement, clickedElement) {
- const hovercard = hovercardElement.controller;
- if (isElementCloseHovercardButton(clickedElement)) {
- closeNow(hovercard);
- } else if (hovercard.children.size > 0) {
- closeChildrenNow(hovercard);
+function handleClickOutsideCoupdoeilButWithinPopover(popoverElement, clickedElement) {
+ const popover = popoverElement.controller;
+ if (isElementClosePopoverButton(clickedElement)) {
+ closeNow(popover);
+ } else if (popover.children.size > 0) {
+ closeChildrenNow(popover);
}
}
-function handleClickOutsideCoupdoeilAndHovercard() {
+function handleClickOutsideCoupdoeilAndPopover() {
closeAllNow();
}
const onMouseOver = ({target: hoveredElement}) => {
const coupdoeilElement = hoveredElement.closest("coup-doeil");
- const hovercardElement = hoveredElement.closest(HOVERCARD_SELECTOR);
- if (coupdoeilElement && hovercardElement) {
- handleMouseOverCoupdoeilWithinHovercard(coupdoeilElement, hovercardElement, hoveredElement);
+ const popoverElement = hoveredElement.closest(POPOVER_SELECTOR);
+ if (coupdoeilElement && popoverElement) {
+ handleMouseOverCoupdoeilWithinPopover(coupdoeilElement, popoverElement, hoveredElement);
} else if (coupdoeilElement) {
- handleMouseOverCoupdoeilOutsideHovercard(coupdoeilElement, hoveredElement);
- } else if (hovercardElement) {
- handleOverOutsideCoupdoeilButWithinHovercard(hovercardElement);
+ handleMouseOverCoupdoeilOutsidePopover(coupdoeilElement, hoveredElement);
+ } else if (popoverElement) {
+ handleOverOutsideCoupdoeilButWithinPopover(popoverElement);
} else {
- handleOverOutsideCoupdoeilAndHovercard();
+ handleOverOutsideCoupdoeilAndPopover();
}
};
-function handleMouseOverCoupdoeilWithinHovercard(coupdoeilElement, hovercardElement, hoveredElement) {
- const childHovercard = coupdoeilElement.hovercardController;
- const parentHovercard = hovercardElement.controller;
- if (notTriggeredOnHover(childHovercard)) return;
- if (childHovercard.isOpen) {
- closeChildrenNow(childHovercard);
+function handleMouseOverCoupdoeilWithinPopover(coupdoeilElement, popoverElement, hoveredElement) {
+ const childPopover = coupdoeilElement.popoverController;
+ const parentPopover = popoverElement.controller;
+ if (notTriggeredOnHover(childPopover)) return;
+ if (childPopover.isOpen) {
+ closeChildrenNow(childPopover);
} else {
- closeChildrenNow(parentHovercard);
- coupdoeilElement.openHovercard(hoveredElement);
+ closeChildrenNow(parentPopover);
+ coupdoeilElement.openPopover(hoveredElement);
}
}
-function handleMouseOverCoupdoeilOutsideHovercard(coupdoeilElement, hoveredElement) {
- const hovercard = coupdoeilElement.hovercardController;
- if (notTriggeredOnHover(hovercard)) return;
- if (hovercard.isClosed) {
- coupdoeilElement.openHovercard(hoveredElement, {
+function handleMouseOverCoupdoeilOutsidePopover(coupdoeilElement, hoveredElement) {
+ const popover = coupdoeilElement.popoverController;
+ if (notTriggeredOnHover(popover)) return;
+ if (popover.isClosed) {
+ coupdoeilElement.openPopover(hoveredElement, {
beforeDisplay: closeTriggeredOnHoverNowUnlessAncestor
});
- } else if (hovercard.closingRequest) {
- cancelCloseRequest(hovercard);
+ } else if (popover.closingRequest) {
+ cancelCloseRequest(popover);
addToCurrents(coupdoeilElement);
}
}
-function handleOverOutsideCoupdoeilAndHovercard() {
- if (isAnyHovercardOpened()) {
+function handleOverOutsideCoupdoeilAndPopover() {
+ if (isAnyPopoverOpened()) {
closeTriggeredOnHoverLater();
}
}
-function handleOverOutsideCoupdoeilButWithinHovercard(hovercardElement) {
- const hovercard = hovercardElement.controller;
- if (hovercard.closingRequest) {
- cancelCloseRequest(hovercard);
- addToCurrents(hovercard.coupdoeilElement);
- } else if (hovercard.children.size > 0) {
- closeOnHoverChildrenLater(hovercard);
+function handleOverOutsideCoupdoeilButWithinPopover(popoverElement) {
+ const popover = popoverElement.controller;
+ if (popover.closingRequest) {
+ cancelCloseRequest(popover);
+ addToCurrents(popover.coupdoeilElement);
+ } else if (popover.children.size > 0) {
+ closeOnHoverChildrenLater(popover);
}
}
document.addEventListener("DOMContentLoaded", (() => {
- clearHovercardContentCache();
+ clearPopoverContentCache();
document.addEventListener("click", coupdoeilOnClickEvent);
document.documentElement.addEventListener("mouseover", onMouseOver, {
passive: true
@@ -2305,7 +2305,7 @@ document.addEventListener("DOMContentLoaded", (() => {
}));
document.addEventListener("turbo:load", (_event => {
clearAll();
- clearHovercardContentCache();
+ clearPopoverContentCache();
}));
}
}));
diff --git a/app/assets/javascripts/coupdoeil.min.js b/app/assets/javascripts/coupdoeil.min.js
index 5f6d860950b245dd3fdf051a601fd428030b48d6..61fe7501dff386b39906fc4b37d339d9ce0768cf 100644
--- a/app/assets/javascripts/coupdoeil.min.js
+++ b/app/assets/javascripts/coupdoeil.min.js
@@ -1,2 +1,2 @@
-class t{constructor(t){this.coupdoeilElement=t,this.card=null,this.children=new Set,this.parent=null,this.closingRequest=null}get isOpen(){return!!this.coupdoeilElement.dataset.hovercardOpen}get isClosed(){return!this.isOpen}}const e="coupdoeil--hovercard",n=`.${e}`,o={animation:{getter:function(t){return c[t>>5&7]}},cache:{getter:function(t){return!(8&~t)}},loading:{getter:function(t){return a[t>>1&3]}},offset:{getter:function(t){const e=Number(BigInt(t)>>BigInt(24));if(0===e)return 0;return function(t){if("number"==typeof t)return t;if(/^(-?\d+\.?\d+)px$/.test(t))return parseFloat(t);if(/^(-?\d*\.?\d+)rem$/.test(t))return parseFloat(t)*parseFloat(getComputedStyle(document.documentElement).fontSize);return 0}(`${1&~e?"":"-"}${e>>13}.${e>>2&2047}${2&~e?"px":"rem"}`)}},openingDelay:{getter:function(t){return 1==(t>>4&1)}},placement:{getter:function(t){const e=t>>8&65535;let n=0,o=null;const r=[];for(;"auto"!==o&&n<16;)o=l[e>>n&15],r.push(o),n+=4;return r}},trigger:{getter:function(t){return i[1&t]}}},r=["trigger","loading","cache","openingDelay","animation","placement","offset"],i=["hover","click"],c=[!1,"slide-in","fade-in","slide-out","custom"],l=["auto","top","top-start","top-end","right","right-start","right-end","bottom","bottom-start","bottom-end","left","left-start","left-end"],a=["async","preload","lazy"];const s={animation:void 0,cache:void 0,loading:void 0,offset:void 0,openingDelay:void 0,placement:void 0,trigger:void 0};function u(t){const e=t.getAttribute("hc");return parseInt(e,36)}function f(t){return t.coupdoeilElement.getAttribute("hc-type")}function d(t){return t.coupdoeilElement.getAttribute("hc-params")}function p(t){return function(t,e){const n=t.hovercardController.optionsInt||=u(t);return o[e].getter(n)}(t.coupdoeilElement,"trigger")}function m(t){return"click"!==p(t)}function h(t){return"hover"===p(t)}function g(t){return"hover"!==p(t)}function y(t){return t.coupdoeilElement.querySelector(".hovercard-content")}const v=new Map;function w(t){return y(t)?t.coupdoeilElement.uniqueId:f(t)+d(t)}function x(t){return v.get(w(t))}function b(){v.clear()}const E=["top","right","bottom","left"],C=["start","end"],L=E.reduce(((t,e)=>t.concat(e,e+"-"+C[0],e+"-"+C[1])),[]),T=Math.min,R=Math.max,O=Math.round,A=t=>({x:t,y:t}),D={left:"right",right:"left",bottom:"top",top:"bottom"},H={start:"end",end:"start"};function P(t,e,n){return R(t,T(e,n))}function S(t,e){return"function"==typeof t?t(e):t}function $(t){return t.split("-")[0]}function q(t){return t.split("-")[1]}function k(t){return"x"===t?"y":"x"}function F(t){return"y"===t?"height":"width"}function W(t){return["top","bottom"].includes($(t))?"y":"x"}function M(t){return k(W(t))}function B(t,e,n){void 0===n&&(n=!1);const o=q(t),r=M(t),i=F(r);let c="x"===r?o===(n?"end":"start")?"right":"left":"start"===o?"bottom":"top";return e.reference[i]>e.floating[i]&&(c=V(c)),[c,V(c)]}function I(t){return t.replace(/start|end/g,(t=>H[t]))}function V(t){return t.replace(/left|right|bottom|top/g,(t=>D[t]))}function N(t){return"number"!=typeof t?function(t){return{top:0,right:0,bottom:0,left:0,...t}}(t):{top:t,right:t,bottom:t,left:t}}function j(t){const{x:e,y:n,width:o,height:r}=t;return{width:o,height:r,top:n,left:e,right:e+o,bottom:n+r,x:e,y:n}}function z(t,e,n){let{reference:o,floating:r}=t;const i=W(e),c=M(e),l=F(c),a=$(e),s="y"===i,u=o.x+o.width/2-r.width/2,f=o.y+o.height/2-r.height/2,d=o[l]/2-r[l]/2;let p;switch(a){case"top":p={x:u,y:o.y-r.height};break;case"bottom":p={x:u,y:o.y+o.height};break;case"right":p={x:o.x+o.width,y:f};break;case"left":p={x:o.x-r.width,y:f};break;default:p={x:o.x,y:o.y}}switch(q(e)){case"start":p[c]-=d*(n&&s?-1:1);break;case"end":p[c]+=d*(n&&s?-1:1)}return p}async function _(t,e){var n;void 0===e&&(e={});const{x:o,y:r,platform:i,rects:c,elements:l,strategy:a}=t,{boundary:s="clippingAncestors",rootBoundary:u="viewport",elementContext:f="floating",altBoundary:d=!1,padding:p=0}=S(e,t),m=N(p),h=l[d?"floating"===f?"reference":"floating":f],g=j(await i.getClippingRect({element:null==(n=await(null==i.isElement?void 0:i.isElement(h)))||n?h:h.contextElement||await(null==i.getDocumentElement?void 0:i.getDocumentElement(l.floating)),boundary:s,rootBoundary:u,strategy:a})),y="floating"===f?{x:o,y:r,width:c.floating.width,height:c.floating.height}:c.reference,v=await(null==i.getOffsetParent?void 0:i.getOffsetParent(l.floating)),w=await(null==i.isElement?void 0:i.isElement(v))&&await(null==i.getScale?void 0:i.getScale(v))||{x:1,y:1},x=j(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:l,rect:y,offsetParent:v,strategy:a}):y);return{top:(g.top-x.top+m.top)/w.y,bottom:(x.bottom-g.bottom+m.bottom)/w.y,left:(g.left-x.left+m.left)/w.x,right:(x.right-g.right+m.right)/w.x}}function U(){return"undefined"!=typeof window}function X(t){return G(t)?(t.nodeName||"").toLowerCase():"#document"}function Y(t){var e;return(null==t||null==(e=t.ownerDocument)?void 0:e.defaultView)||window}function J(t){var e;return null==(e=(G(t)?t.ownerDocument:t.document)||window.document)?void 0:e.documentElement}function G(t){return!!U()&&(t instanceof Node||t instanceof Y(t).Node)}function K(t){return!!U()&&(t instanceof Element||t instanceof Y(t).Element)}function Q(t){return!!U()&&(t instanceof HTMLElement||t instanceof Y(t).HTMLElement)}function Z(t){return!(!U()||"undefined"==typeof ShadowRoot)&&(t instanceof ShadowRoot||t instanceof Y(t).ShadowRoot)}function tt(t){const{overflow:e,overflowX:n,overflowY:o,display:r}=ct(t);return/auto|scroll|overlay|hidden|clip/.test(e+o+n)&&!["inline","contents"].includes(r)}function et(t){return["table","td","th"].includes(X(t))}function nt(t){return[":popover-open",":modal"].some((e=>{try{return t.matches(e)}catch(t){return!1}}))}function ot(t){const e=rt(),n=K(t)?ct(t):t;return"none"!==n.transform||"none"!==n.perspective||!!n.containerType&&"normal"!==n.containerType||!e&&!!n.backdropFilter&&"none"!==n.backdropFilter||!e&&!!n.filter&&"none"!==n.filter||["transform","perspective","filter"].some((t=>(n.willChange||"").includes(t)))||["paint","layout","strict","content"].some((t=>(n.contain||"").includes(t)))}function rt(){return!("undefined"==typeof CSS||!CSS.supports)&&CSS.supports("-webkit-backdrop-filter","none")}function it(t){return["html","body","#document"].includes(X(t))}function ct(t){return Y(t).getComputedStyle(t)}function lt(t){return K(t)?{scrollLeft:t.scrollLeft,scrollTop:t.scrollTop}:{scrollLeft:t.scrollX,scrollTop:t.scrollY}}function at(t){if("html"===X(t))return t;const e=t.assignedSlot||t.parentNode||Z(t)&&t.host||J(t);return Z(e)?e.host:e}function st(t){const e=at(t);return it(e)?t.ownerDocument?t.ownerDocument.body:t.body:Q(e)&&tt(e)?e:st(e)}function ut(t,e,n){var o;void 0===e&&(e=[]),void 0===n&&(n=!0);const r=st(t),i=r===(null==(o=t.ownerDocument)?void 0:o.body),c=Y(r);if(i){const t=ft(c);return e.concat(c,c.visualViewport||[],tt(r)?r:[],t&&n?ut(t):[])}return e.concat(r,ut(r,[],n))}function ft(t){return t.parent&&Object.getPrototypeOf(t.parent)?t.frameElement:null}function dt(t){const e=ct(t);let n=parseFloat(e.width)||0,o=parseFloat(e.height)||0;const r=Q(t),i=r?t.offsetWidth:n,c=r?t.offsetHeight:o,l=O(n)!==i||O(o)!==c;return l&&(n=i,o=c),{width:n,height:o,$:l}}function pt(t){return K(t)?t:t.contextElement}function mt(t){const e=pt(t);if(!Q(e))return A(1);const n=e.getBoundingClientRect(),{width:o,height:r,$:i}=dt(e);let c=(i?O(n.width):n.width)/o,l=(i?O(n.height):n.height)/r;return c&&Number.isFinite(c)||(c=1),l&&Number.isFinite(l)||(l=1),{x:c,y:l}}const ht=A(0);function gt(t){const e=Y(t);return rt()&&e.visualViewport?{x:e.visualViewport.offsetLeft,y:e.visualViewport.offsetTop}:ht}function yt(t,e,n,o){void 0===e&&(e=!1),void 0===n&&(n=!1);const r=t.getBoundingClientRect(),i=pt(t);let c=A(1);e&&(o?K(o)&&(c=mt(o)):c=mt(t));const l=function(t,e,n){return void 0===e&&(e=!1),!(!n||e&&n!==Y(t))&&e}(i,n,o)?gt(i):A(0);let a=(r.left+l.x)/c.x,s=(r.top+l.y)/c.y,u=r.width/c.x,f=r.height/c.y;if(i){const t=Y(i),e=o&&K(o)?Y(o):o;let n=t,r=ft(n);for(;r&&o&&e!==n;){const t=mt(r),e=r.getBoundingClientRect(),o=ct(r),i=e.left+(r.clientLeft+parseFloat(o.paddingLeft))*t.x,c=e.top+(r.clientTop+parseFloat(o.paddingTop))*t.y;a*=t.x,s*=t.y,u*=t.x,f*=t.y,a+=i,s+=c,n=Y(r),r=ft(n)}}return j({width:u,height:f,x:a,y:s})}function vt(t,e){const n=lt(t).scrollLeft;return e?e.left+n:yt(J(t)).left+n}function wt(t,e,n){void 0===n&&(n=!1);const o=t.getBoundingClientRect();return{x:o.left+e.scrollLeft-(n?0:vt(t,o)),y:o.top+e.scrollTop}}function xt(t,e,n){let o;if("viewport"===e)o=function(t,e){const n=Y(t),o=J(t),r=n.visualViewport;let i=o.clientWidth,c=o.clientHeight,l=0,a=0;if(r){i=r.width,c=r.height;const t=rt();(!t||t&&"fixed"===e)&&(l=r.offsetLeft,a=r.offsetTop)}return{width:i,height:c,x:l,y:a}}(t,n);else if("document"===e)o=function(t){const e=J(t),n=lt(t),o=t.ownerDocument.body,r=R(e.scrollWidth,e.clientWidth,o.scrollWidth,o.clientWidth),i=R(e.scrollHeight,e.clientHeight,o.scrollHeight,o.clientHeight);let c=-n.scrollLeft+vt(t);const l=-n.scrollTop;return"rtl"===ct(o).direction&&(c+=R(e.clientWidth,o.clientWidth)-r),{width:r,height:i,x:c,y:l}}(J(t));else if(K(e))o=function(t,e){const n=yt(t,!0,"fixed"===e),o=n.top+t.clientTop,r=n.left+t.clientLeft,i=Q(t)?mt(t):A(1);return{width:t.clientWidth*i.x,height:t.clientHeight*i.y,x:r*i.x,y:o*i.y}}(e,n);else{const n=gt(t);o={x:e.x-n.x,y:e.y-n.y,width:e.width,height:e.height}}return j(o)}function bt(t,e){const n=at(t);return!(n===e||!K(n)||it(n))&&("fixed"===ct(n).position||bt(n,e))}function Et(t,e,n){const o=Q(e),r=J(e),i="fixed"===n,c=yt(t,!0,i,e);let l={scrollLeft:0,scrollTop:0};const a=A(0);if(o||!o&&!i)if(("body"!==X(e)||tt(r))&&(l=lt(e)),o){const t=yt(e,!0,i,e);a.x=t.x+e.clientLeft,a.y=t.y+e.clientTop}else r&&(a.x=vt(r));const s=!r||o||i?A(0):wt(r,l);return{x:c.left+l.scrollLeft-a.x-s.x,y:c.top+l.scrollTop-a.y-s.y,width:c.width,height:c.height}}function Ct(t){return"static"===ct(t).position}function Lt(t,e){if(!Q(t)||"fixed"===ct(t).position)return null;if(e)return e(t);let n=t.offsetParent;return J(t)===n&&(n=n.ownerDocument.body),n}function Tt(t,e){const n=Y(t);if(nt(t))return n;if(!Q(t)){let e=at(t);for(;e&&!it(e);){if(K(e)&&!Ct(e))return e;e=at(e)}return n}let o=Lt(t,e);for(;o&&et(o)&&Ct(o);)o=Lt(o,e);return o&&it(o)&&Ct(o)&&!ot(o)?n:o||function(t){let e=at(t);for(;Q(e)&&!it(e);){if(ot(e))return e;if(nt(e))return null;e=at(e)}return null}(t)||n}const Rt={convertOffsetParentRelativeRectToViewportRelativeRect:function(t){let{elements:e,rect:n,offsetParent:o,strategy:r}=t;const i="fixed"===r,c=J(o),l=!!e&&nt(e.floating);if(o===c||l&&i)return n;let a={scrollLeft:0,scrollTop:0},s=A(1);const u=A(0),f=Q(o);if((f||!f&&!i)&&(("body"!==X(o)||tt(c))&&(a=lt(o)),Q(o))){const t=yt(o);s=mt(o),u.x=t.x+o.clientLeft,u.y=t.y+o.clientTop}const d=!c||f||i?A(0):wt(c,a,!0);return{width:n.width*s.x,height:n.height*s.y,x:n.x*s.x-a.scrollLeft*s.x+u.x+d.x,y:n.y*s.y-a.scrollTop*s.y+u.y+d.y}},getDocumentElement:J,getClippingRect:function(t){let{element:e,boundary:n,rootBoundary:o,strategy:r}=t;const i=[..."clippingAncestors"===n?nt(e)?[]:function(t,e){const n=e.get(t);if(n)return n;let o=ut(t,[],!1).filter((t=>K(t)&&"body"!==X(t))),r=null;const i="fixed"===ct(t).position;let c=i?at(t):t;for(;K(c)&&!it(c);){const e=ct(c),n=ot(c);n||"fixed"!==e.position||(r=null),(i?!n&&!r:!n&&"static"===e.position&&r&&["absolute","fixed"].includes(r.position)||tt(c)&&!n&&bt(t,c))?o=o.filter((t=>t!==c)):r=e,c=at(c)}return e.set(t,o),o}(e,this._c):[].concat(n),o],c=i[0],l=i.reduce(((t,n)=>{const o=xt(e,n,r);return t.top=R(o.top,t.top),t.right=T(o.right,t.right),t.bottom=T(o.bottom,t.bottom),t.left=R(o.left,t.left),t}),xt(e,c,r));return{width:l.right-l.left,height:l.bottom-l.top,x:l.left,y:l.top}},getOffsetParent:Tt,getElementRects:async function(t){const e=this.getOffsetParent||Tt,n=this.getDimensions,o=await n(t.floating);return{reference:Et(t.reference,await e(t.floating),t.strategy),floating:{x:0,y:0,width:o.width,height:o.height}}},getClientRects:function(t){return Array.from(t.getClientRects())},getDimensions:function(t){const{width:e,height:n}=dt(t);return{width:e,height:n}},getScale:mt,isElement:K,isRTL:function(t){return"rtl"===ct(t).direction}},Ot=_,At=function(t){return void 0===t&&(t=0),{name:"offset",options:t,async fn(e){var n,o;const{x:r,y:i,placement:c,middlewareData:l}=e,a=await async function(t,e){const{placement:n,platform:o,elements:r}=t,i=await(null==o.isRTL?void 0:o.isRTL(r.floating)),c=$(n),l=q(n),a="y"===W(n),s=["left","top"].includes(c)?-1:1,u=i&&a?-1:1,f=S(e,t);let{mainAxis:d,crossAxis:p,alignmentAxis:m}="number"==typeof f?{mainAxis:f,crossAxis:0,alignmentAxis:null}:{mainAxis:f.mainAxis||0,crossAxis:f.crossAxis||0,alignmentAxis:f.alignmentAxis};return l&&"number"==typeof m&&(p="end"===l?-1*m:m),a?{x:p*u,y:d*s}:{x:d*s,y:p*u}}(e,t);return c===(null==(n=l.offset)?void 0:n.placement)&&null!=(o=l.arrow)&&o.alignmentOffset?{}:{x:r+a.x,y:i+a.y,data:{...a,placement:c}}}}},Dt=function(t){return void 0===t&&(t={}),{name:"autoPlacement",options:t,async fn(e){var n,o,r;const{rects:i,middlewareData:c,placement:l,platform:a,elements:s}=e,{crossAxis:u=!1,alignment:f,allowedPlacements:d=L,autoAlignment:p=!0,...m}=S(t,e),h=void 0!==f||d===L?function(t,e,n){return(t?[...n.filter((e=>q(e)===t)),...n.filter((e=>q(e)!==t))]:n.filter((t=>$(t)===t))).filter((n=>!t||q(n)===t||!!e&&I(n)!==n))}(f||null,p,d):d,g=await _(e,m),y=(null==(n=c.autoPlacement)?void 0:n.index)||0,v=h[y];if(null==v)return{};const w=B(v,i,await(null==a.isRTL?void 0:a.isRTL(s.floating)));if(l!==v)return{reset:{placement:h[0]}};const x=[g[$(v)],g[w[0]],g[w[1]]],b=[...(null==(o=c.autoPlacement)?void 0:o.overflows)||[],{placement:v,overflows:x}],E=h[y+1];if(E)return{data:{index:y+1,overflows:b},reset:{placement:E}};const C=b.map((t=>{const e=q(t.placement);return[t.placement,e&&u?t.overflows.slice(0,2).reduce(((t,e)=>t+e),0):t.overflows[0],t.overflows]})).sort(((t,e)=>t[1]-e[1])),T=(null==(r=C.filter((t=>t[2].slice(0,q(t[0])?2:3).every((t=>t<=0))))[0])?void 0:r[0])||C[0][0];return T!==l?{data:{index:y+1,overflows:b},reset:{placement:T}}:{}}}},Ht=t=>({name:"arrow",options:t,async fn(e){const{x:n,y:o,placement:r,rects:i,platform:c,elements:l,middlewareData:a}=e,{element:s,padding:u=0}=S(t,e)||{};if(null==s)return{};const f=N(u),d={x:n,y:o},p=M(r),m=F(p),h=await c.getDimensions(s),g="y"===p,y=g?"top":"left",v=g?"bottom":"right",w=g?"clientHeight":"clientWidth",x=i.reference[m]+i.reference[p]-d[p]-i.floating[m],b=d[p]-i.reference[p],E=await(null==c.getOffsetParent?void 0:c.getOffsetParent(s));let C=E?E[w]:0;C&&await(null==c.isElement?void 0:c.isElement(E))||(C=l.floating[w]||i.floating[m]);const L=x/2-b/2,R=C/2-h[m]/2-1,O=T(f[y],R),A=T(f[v],R),D=O,H=C-h[m]-A,$=C/2-h[m]/2+L,k=P(D,$,H),W=!a.arrow&&null!=q(r)&&$!==k&&i.reference[m]/2-($
{const o=new Map,r={platform:Rt,...n},i={...r.platform,_c:o};return(async(t,e,n)=>{const{placement:o="bottom",strategy:r="absolute",middleware:i=[],platform:c}=n,l=i.filter(Boolean),a=await(null==c.isRTL?void 0:c.isRTL(e));let s=await c.getElementRects({reference:t,floating:e,strategy:r}),{x:u,y:f}=z(s,o,a),d=o,p={},m=0;for(let n=0;n{let e=0;return{name:"autoPlacement",async fn(n){if("auto"===n.placement)return Dt().fn(n);const{top:o,bottom:r,left:i,right:c}=await Ot(n),l=o>0||r>0||i>0||c>0;return"auto"!==t[e]&&l?(e++,{reset:{placement:t[e]||"auto"}}):l?Dt().fn(n):{}}}},qt={right:"left",left:"right",top:"bottom",bottom:"top"};async function kt(t,e,n){const o=e.dataset,r=n?`${n}-${t}`:t;let i=`transition${t.charAt(0).toUpperCase()+t.slice(1)}`;const c=o[i]?o[i].split(" "):[r],l=o[`${i}Start`]?o[`${i}Start`].split(" "):[`${r}-start`],a=o[`${i}End`]?o[`${i}End`].split(" "):[`${r}-end`];Ft(e,c),Ft(e,l),await new Promise((t=>{requestAnimationFrame((()=>{requestAnimationFrame(t)}))})),Wt(e,l),Ft(e,a),await function(t){return new Promise((e=>{const n=getComputedStyle(t).transitionDuration.split(",")[0],o=1e3*Number(n.replace("s",""));setTimeout((()=>{e()}),o)}))}(e),Wt(e,a),Wt(e,c)}function Ft(t,e){t.classList.add(...e)}function Wt(t,e){t.classList.remove(...e)}const Mt=new Map;function Bt(t){Mt.set(t.uniqueId,t)}function It(t){Mt.delete(t.uniqueId)}function Vt(t){!function(t){delete t.coupdoeilElement.openingHovercard}(t),Nt(t)}function Nt(t){clearTimeout(t.closingRequest),t.closingRequest=null,Bt(t.coupdoeilElement)}function jt(t,e=!0){t.closing||t.isClosed&&!t.coupdoeilElement.openingHovercard||(t.closing=!0,Vt(t),t.children.forEach((t=>{jt(t)})),function(t){t.parent&&(t.parent.children.delete(t),t.parent=null)}(t),e&&t.card&&t.card.dataset.animation?async function(t){await async function(t,e=null){await kt("leave",t,e),t.classList.add("hidden")}(t.card,"hovercard"),zt(t)}(t):zt(t))}function zt(t){t.card&&(t.card.remove(),t.card=null),delete t.closing,delete t.coupdoeilElement.dataset.hovercardOpen}function _t(t){jt(t,!1)}function Ut(t){Vt(t),t.closingRequest=setTimeout((()=>{jt(t)}),75)}function Xt(t){t.children.forEach((t=>{jt(t)}))}function Yt(){for(const t of Mt.values())jt(t.hovercardController),It(t)}function Jt(){for(const t of Mt.values())_t(t.hovercardController),It(t)}function Gt(t){let e=t;for(;e.parent;)e=e.parent;const n=e.coupdoeilElement.uniqueId;for(const t of Mt.values())t.uniqueId!==n&&h(t.hovercardController)&&(jt(t.hovercardController),It(t))}async function Kt(t,e,n){return new Promise((o=>{setTimeout((async()=>{if(t.coupdoeilElement.openingHovercard){if(!1===e.cache||e.cache&&!x(t)){let n;n="preload"===e.loading?y(t).innerHTML:await function(t){const e=f(t),n=d(t),o=document.querySelector("meta[name=csrf-token]").content,r={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({params:n,action_name:e,authenticity_token:o})};return fetch("/coupdoeil/hovercard",r).then((t=>{if(t.status>=400)throw"error while fetching hovercard content";return t.text()}))}(t),function(t,e){v.set(w(t),e)}(t,n)}o()}}),n.fetch)}))}async function Qt(t,{parent:n,beforeDisplay:i}){if(t.isOpen)return Nt(t);n&&(t.parent=n,n.children.add(t));const c=function(t){const e=t.hovercardController.optionsInt||=u(t),n=Object.create(s);for(const t of r)n[t]=o[t].getter(e);return n}(t.coupdoeilElement),l=function(t,e){if(!1===e.openingDelay||function(t){return"click"===p(t)}(t))return{fetch:0,opening:0};return{fetch:100,opening:200}}(t,c),a=new Promise((t=>setTimeout(t,l.opening))),f=Kt(t,c,l);await Promise.all([f,a]);const d=t.parent&&(t.parent.isClosed||t.parent.closingRequest);t.coupdoeilElement.openingHovercard&&!d&&await async function(t,n,o){if(t.isOpen)return;Nt(t),t.card=function(t,n){const o=document.createElement("div");return o.setAttribute("role","dialog"),o.classList.add(e),o.style.cssText="position: absolute; left: 0; top: 0;",o.innerHTML=x(t),o.controller=t,o.dataset.placement=n.placement,o.style.visibility="hidden",o}(t,n),document.body.appendChild(t.card),n.animation&&(t.card.dataset.animation=n.animation);Zt(t,(async()=>{await St(t.coupdoeilElement,t.card,n),t.card.classList.add("hidden"),t.card.style.removeProperty("visibility"),Zt(t,(async()=>{o&&o(t),Bt(t.coupdoeilElement),delete t.coupdoeilElement.openingHovercard,t.coupdoeilElement.dataset.hovercardOpen=!0,await async function(t,e=null){t.classList.remove("hidden"),await kt("enter",t,e)}(t.card,"hovercard")}))}))}(t,c,i)}function Zt(t,e){requestAnimationFrame((()=>{t.coupdoeilElement.openingHovercard?e.call():_t(t)}))}class te extends HTMLElement{constructor(){super(),this.uniqueId=function(){const t=new Uint32Array(1);return window.crypto.getRandomValues(t),t[0]}(),this.hovercardController=new t(this)}openHovercard(t=null,e){if(this.openingHovercard||this.hovercardController.isOpen||this.disabled||t===this)return;this.openingHovercard=!0;const o=this.closest(n)?.controller;return Bt(this),Qt(this.hovercardController,{parent:o,...e})}closeHovercard(){jt(this.hovercardController)}get disabled(){return!!this.getAttribute("disabled")}set disabled(t){t?this.setAttribute("disabled",!0):this.removeAttribute("disabled")}}function ee(){return Mt.size>0}const ne=({target:t})=>{const e=t.closest("coup-doeil"),o=t.closest(n);e&&o?function(t,e,n){const o=t.hovercardController;if(m(o))return;o.isOpen?jt(o):t.openHovercard(n)}(e,0,t):e?function(t,e){const n=t.hovercardController;if(m(n))return;n.isOpen?jt(n):(Yt(),t.openHovercard(e))}(e,t):o?function(t,e){const n=t.controller;o=e,o.closest("[data-hovercard-close]")||o.dataset.hasOwnProperty("hovercardClose")?jt(n):n.children.size>0&&Xt(n);var o}(o,t):Yt()};const oe=({target:t})=>{const e=t.closest("coup-doeil"),o=t.closest(n);e&&o?function(t,e,n){const o=t.hovercardController,r=e.controller;if(g(o))return;o.isOpen?Xt(o):(Xt(r),t.openHovercard(n))}(e,o,t):e?function(t,e){const n=t.hovercardController;if(g(n))return;n.isClosed?t.openHovercard(e,{beforeDisplay:Gt}):n.closingRequest&&(Nt(n),Bt(t))}(e,t):o?function(t){const e=t.controller;e.closingRequest?(Nt(e),Bt(e.coupdoeilElement)):e.children.size>0&&e.children.forEach((t=>{h(t)&&Ut(t)}))}(o):ee()&&function(){for(const t of Mt.values())h(t.hovercardController)&&(Ut(t.hovercardController),It(t))}()};document.addEventListener("DOMContentLoaded",(()=>{b(),document.addEventListener("click",ne),document.documentElement.addEventListener("mouseover",oe,{passive:!0}),window.Turbo&&(document.addEventListener("turbo:before-cache",(t=>{Jt()})),document.addEventListener("turbo:load",(t=>{Jt(),b()})))})),void 0===customElements.get("coup-doeil")&&customElements.define("coup-doeil",te);
+class t{constructor(t){this.coupdoeilElement=t,this.card=null,this.children=new Set,this.parent=null,this.closingRequest=null}get isOpen(){return!!this.coupdoeilElement.dataset.popoverOpen}get isClosed(){return!this.isOpen}}const e="coupdoeil--popover",n=`.${e}`,o={animation:{getter:function(t){return l[t>>5&7]}},cache:{getter:function(t){return!(8&~t)}},loading:{getter:function(t){return s[t>>1&3]}},offset:{getter:function(t){const e=Number(BigInt(t)>>BigInt(24));if(0===e)return 0;return function(t){if("number"==typeof t)return t;if(/^(-?\d+\.?\d+)px$/.test(t))return parseFloat(t);if(/^(-?\d*\.?\d+)rem$/.test(t))return parseFloat(t)*parseFloat(getComputedStyle(document.documentElement).fontSize);return 0}(`${1&~e?"":"-"}${e>>13}.${e>>2&2047}${2&~e?"px":"rem"}`)}},openingDelay:{getter:function(t){return 1==(t>>4&1)}},placement:{getter:function(t){const e=t>>8&65535;let n=0,o=null;const i=[];for(;"auto"!==o&&n<16;)o=c[e>>n&15],i.push(o),n+=4;return i}},trigger:{getter:function(t){return r[1&t]}}},i=["trigger","loading","cache","openingDelay","animation","placement","offset"],r=["hover","click"],l=[!1,"slide-in","fade-in","slide-out","custom"],c=["auto","top","top-start","top-end","right","right-start","right-end","bottom","bottom-start","bottom-end","left","left-start","left-end"],s=["async","preload","lazy"];const a={animation:void 0,cache:void 0,loading:void 0,offset:void 0,openingDelay:void 0,placement:void 0,trigger:void 0};function u(t){const e=t.getAttribute("popover-options");return parseInt(e,36)}function f(t){return t.coupdoeilElement.getAttribute("popover-type")}function d(t){return t.coupdoeilElement.getAttribute("popover-params")}function p(t){return function(t,e){const n=t.popoverController.optionsInt||=u(t);return o[e].getter(n)}(t.coupdoeilElement,"trigger")}function m(t){return"click"!==p(t)}function h(t){return"hover"===p(t)}function g(t){return"hover"!==p(t)}function y(t){return t.coupdoeilElement.querySelector(".popover-content")}const v=new Map;function w(t){return y(t)?t.coupdoeilElement.uniqueId:f(t)+d(t)}function x(t){return v.get(w(t))}function b(){v.clear()}const E=["top","right","bottom","left"],C=["start","end"],L=E.reduce(((t,e)=>t.concat(e,e+"-"+C[0],e+"-"+C[1])),[]),T=Math.min,P=Math.max,R=Math.round,O=t=>({x:t,y:t}),A={left:"right",right:"left",bottom:"top",top:"bottom"},D={start:"end",end:"start"};function S(t,e,n){return P(t,T(e,n))}function $(t,e){return"function"==typeof t?t(e):t}function q(t){return t.split("-")[0]}function k(t){return t.split("-")[1]}function F(t){return"x"===t?"y":"x"}function H(t){return"y"===t?"height":"width"}function W(t){return["top","bottom"].includes(q(t))?"y":"x"}function M(t){return F(W(t))}function B(t,e,n){void 0===n&&(n=!1);const o=k(t),i=M(t),r=H(i);let l="x"===i?o===(n?"end":"start")?"right":"left":"start"===o?"bottom":"top";return e.reference[r]>e.floating[r]&&(l=V(l)),[l,V(l)]}function I(t){return t.replace(/start|end/g,(t=>D[t]))}function V(t){return t.replace(/left|right|bottom|top/g,(t=>A[t]))}function N(t){return"number"!=typeof t?function(t){return{top:0,right:0,bottom:0,left:0,...t}}(t):{top:t,right:t,bottom:t,left:t}}function j(t){const{x:e,y:n,width:o,height:i}=t;return{width:o,height:i,top:n,left:e,right:e+o,bottom:n+i,x:e,y:n}}function z(t,e,n){let{reference:o,floating:i}=t;const r=W(e),l=M(e),c=H(l),s=q(e),a="y"===r,u=o.x+o.width/2-i.width/2,f=o.y+o.height/2-i.height/2,d=o[c]/2-i[c]/2;let p;switch(s){case"top":p={x:u,y:o.y-i.height};break;case"bottom":p={x:u,y:o.y+o.height};break;case"right":p={x:o.x+o.width,y:f};break;case"left":p={x:o.x-i.width,y:f};break;default:p={x:o.x,y:o.y}}switch(k(e)){case"start":p[l]-=d*(n&&a?-1:1);break;case"end":p[l]+=d*(n&&a?-1:1)}return p}async function _(t,e){var n;void 0===e&&(e={});const{x:o,y:i,platform:r,rects:l,elements:c,strategy:s}=t,{boundary:a="clippingAncestors",rootBoundary:u="viewport",elementContext:f="floating",altBoundary:d=!1,padding:p=0}=$(e,t),m=N(p),h=c[d?"floating"===f?"reference":"floating":f],g=j(await r.getClippingRect({element:null==(n=await(null==r.isElement?void 0:r.isElement(h)))||n?h:h.contextElement||await(null==r.getDocumentElement?void 0:r.getDocumentElement(c.floating)),boundary:a,rootBoundary:u,strategy:s})),y="floating"===f?{x:o,y:i,width:l.floating.width,height:l.floating.height}:l.reference,v=await(null==r.getOffsetParent?void 0:r.getOffsetParent(c.floating)),w=await(null==r.isElement?void 0:r.isElement(v))&&await(null==r.getScale?void 0:r.getScale(v))||{x:1,y:1},x=j(r.convertOffsetParentRelativeRectToViewportRelativeRect?await r.convertOffsetParentRelativeRectToViewportRelativeRect({elements:c,rect:y,offsetParent:v,strategy:s}):y);return{top:(g.top-x.top+m.top)/w.y,bottom:(x.bottom-g.bottom+m.bottom)/w.y,left:(g.left-x.left+m.left)/w.x,right:(x.right-g.right+m.right)/w.x}}function U(){return"undefined"!=typeof window}function X(t){return G(t)?(t.nodeName||"").toLowerCase():"#document"}function Y(t){var e;return(null==t||null==(e=t.ownerDocument)?void 0:e.defaultView)||window}function J(t){var e;return null==(e=(G(t)?t.ownerDocument:t.document)||window.document)?void 0:e.documentElement}function G(t){return!!U()&&(t instanceof Node||t instanceof Y(t).Node)}function K(t){return!!U()&&(t instanceof Element||t instanceof Y(t).Element)}function Q(t){return!!U()&&(t instanceof HTMLElement||t instanceof Y(t).HTMLElement)}function Z(t){return!(!U()||"undefined"==typeof ShadowRoot)&&(t instanceof ShadowRoot||t instanceof Y(t).ShadowRoot)}function tt(t){const{overflow:e,overflowX:n,overflowY:o,display:i}=lt(t);return/auto|scroll|overlay|hidden|clip/.test(e+o+n)&&!["inline","contents"].includes(i)}function et(t){return["table","td","th"].includes(X(t))}function nt(t){return[":popover-open",":modal"].some((e=>{try{return t.matches(e)}catch(t){return!1}}))}function ot(t){const e=it(),n=K(t)?lt(t):t;return"none"!==n.transform||"none"!==n.perspective||!!n.containerType&&"normal"!==n.containerType||!e&&!!n.backdropFilter&&"none"!==n.backdropFilter||!e&&!!n.filter&&"none"!==n.filter||["transform","perspective","filter"].some((t=>(n.willChange||"").includes(t)))||["paint","layout","strict","content"].some((t=>(n.contain||"").includes(t)))}function it(){return!("undefined"==typeof CSS||!CSS.supports)&&CSS.supports("-webkit-backdrop-filter","none")}function rt(t){return["html","body","#document"].includes(X(t))}function lt(t){return Y(t).getComputedStyle(t)}function ct(t){return K(t)?{scrollLeft:t.scrollLeft,scrollTop:t.scrollTop}:{scrollLeft:t.scrollX,scrollTop:t.scrollY}}function st(t){if("html"===X(t))return t;const e=t.assignedSlot||t.parentNode||Z(t)&&t.host||J(t);return Z(e)?e.host:e}function at(t){const e=st(t);return rt(e)?t.ownerDocument?t.ownerDocument.body:t.body:Q(e)&&tt(e)?e:at(e)}function ut(t,e,n){var o;void 0===e&&(e=[]),void 0===n&&(n=!0);const i=at(t),r=i===(null==(o=t.ownerDocument)?void 0:o.body),l=Y(i);if(r){const t=ft(l);return e.concat(l,l.visualViewport||[],tt(i)?i:[],t&&n?ut(t):[])}return e.concat(i,ut(i,[],n))}function ft(t){return t.parent&&Object.getPrototypeOf(t.parent)?t.frameElement:null}function dt(t){const e=lt(t);let n=parseFloat(e.width)||0,o=parseFloat(e.height)||0;const i=Q(t),r=i?t.offsetWidth:n,l=i?t.offsetHeight:o,c=R(n)!==r||R(o)!==l;return c&&(n=r,o=l),{width:n,height:o,$:c}}function pt(t){return K(t)?t:t.contextElement}function mt(t){const e=pt(t);if(!Q(e))return O(1);const n=e.getBoundingClientRect(),{width:o,height:i,$:r}=dt(e);let l=(r?R(n.width):n.width)/o,c=(r?R(n.height):n.height)/i;return l&&Number.isFinite(l)||(l=1),c&&Number.isFinite(c)||(c=1),{x:l,y:c}}const ht=O(0);function gt(t){const e=Y(t);return it()&&e.visualViewport?{x:e.visualViewport.offsetLeft,y:e.visualViewport.offsetTop}:ht}function yt(t,e,n,o){void 0===e&&(e=!1),void 0===n&&(n=!1);const i=t.getBoundingClientRect(),r=pt(t);let l=O(1);e&&(o?K(o)&&(l=mt(o)):l=mt(t));const c=function(t,e,n){return void 0===e&&(e=!1),!(!n||e&&n!==Y(t))&&e}(r,n,o)?gt(r):O(0);let s=(i.left+c.x)/l.x,a=(i.top+c.y)/l.y,u=i.width/l.x,f=i.height/l.y;if(r){const t=Y(r),e=o&&K(o)?Y(o):o;let n=t,i=ft(n);for(;i&&o&&e!==n;){const t=mt(i),e=i.getBoundingClientRect(),o=lt(i),r=e.left+(i.clientLeft+parseFloat(o.paddingLeft))*t.x,l=e.top+(i.clientTop+parseFloat(o.paddingTop))*t.y;s*=t.x,a*=t.y,u*=t.x,f*=t.y,s+=r,a+=l,n=Y(i),i=ft(n)}}return j({width:u,height:f,x:s,y:a})}function vt(t,e){const n=ct(t).scrollLeft;return e?e.left+n:yt(J(t)).left+n}function wt(t,e,n){void 0===n&&(n=!1);const o=t.getBoundingClientRect();return{x:o.left+e.scrollLeft-(n?0:vt(t,o)),y:o.top+e.scrollTop}}function xt(t,e,n){let o;if("viewport"===e)o=function(t,e){const n=Y(t),o=J(t),i=n.visualViewport;let r=o.clientWidth,l=o.clientHeight,c=0,s=0;if(i){r=i.width,l=i.height;const t=it();(!t||t&&"fixed"===e)&&(c=i.offsetLeft,s=i.offsetTop)}return{width:r,height:l,x:c,y:s}}(t,n);else if("document"===e)o=function(t){const e=J(t),n=ct(t),o=t.ownerDocument.body,i=P(e.scrollWidth,e.clientWidth,o.scrollWidth,o.clientWidth),r=P(e.scrollHeight,e.clientHeight,o.scrollHeight,o.clientHeight);let l=-n.scrollLeft+vt(t);const c=-n.scrollTop;return"rtl"===lt(o).direction&&(l+=P(e.clientWidth,o.clientWidth)-i),{width:i,height:r,x:l,y:c}}(J(t));else if(K(e))o=function(t,e){const n=yt(t,!0,"fixed"===e),o=n.top+t.clientTop,i=n.left+t.clientLeft,r=Q(t)?mt(t):O(1);return{width:t.clientWidth*r.x,height:t.clientHeight*r.y,x:i*r.x,y:o*r.y}}(e,n);else{const n=gt(t);o={x:e.x-n.x,y:e.y-n.y,width:e.width,height:e.height}}return j(o)}function bt(t,e){const n=st(t);return!(n===e||!K(n)||rt(n))&&("fixed"===lt(n).position||bt(n,e))}function Et(t,e,n){const o=Q(e),i=J(e),r="fixed"===n,l=yt(t,!0,r,e);let c={scrollLeft:0,scrollTop:0};const s=O(0);if(o||!o&&!r)if(("body"!==X(e)||tt(i))&&(c=ct(e)),o){const t=yt(e,!0,r,e);s.x=t.x+e.clientLeft,s.y=t.y+e.clientTop}else i&&(s.x=vt(i));const a=!i||o||r?O(0):wt(i,c);return{x:l.left+c.scrollLeft-s.x-a.x,y:l.top+c.scrollTop-s.y-a.y,width:l.width,height:l.height}}function Ct(t){return"static"===lt(t).position}function Lt(t,e){if(!Q(t)||"fixed"===lt(t).position)return null;if(e)return e(t);let n=t.offsetParent;return J(t)===n&&(n=n.ownerDocument.body),n}function Tt(t,e){const n=Y(t);if(nt(t))return n;if(!Q(t)){let e=st(t);for(;e&&!rt(e);){if(K(e)&&!Ct(e))return e;e=st(e)}return n}let o=Lt(t,e);for(;o&&et(o)&&Ct(o);)o=Lt(o,e);return o&&rt(o)&&Ct(o)&&!ot(o)?n:o||function(t){let e=st(t);for(;Q(e)&&!rt(e);){if(ot(e))return e;if(nt(e))return null;e=st(e)}return null}(t)||n}const Pt={convertOffsetParentRelativeRectToViewportRelativeRect:function(t){let{elements:e,rect:n,offsetParent:o,strategy:i}=t;const r="fixed"===i,l=J(o),c=!!e&&nt(e.floating);if(o===l||c&&r)return n;let s={scrollLeft:0,scrollTop:0},a=O(1);const u=O(0),f=Q(o);if((f||!f&&!r)&&(("body"!==X(o)||tt(l))&&(s=ct(o)),Q(o))){const t=yt(o);a=mt(o),u.x=t.x+o.clientLeft,u.y=t.y+o.clientTop}const d=!l||f||r?O(0):wt(l,s,!0);return{width:n.width*a.x,height:n.height*a.y,x:n.x*a.x-s.scrollLeft*a.x+u.x+d.x,y:n.y*a.y-s.scrollTop*a.y+u.y+d.y}},getDocumentElement:J,getClippingRect:function(t){let{element:e,boundary:n,rootBoundary:o,strategy:i}=t;const r=[..."clippingAncestors"===n?nt(e)?[]:function(t,e){const n=e.get(t);if(n)return n;let o=ut(t,[],!1).filter((t=>K(t)&&"body"!==X(t))),i=null;const r="fixed"===lt(t).position;let l=r?st(t):t;for(;K(l)&&!rt(l);){const e=lt(l),n=ot(l);n||"fixed"!==e.position||(i=null),(r?!n&&!i:!n&&"static"===e.position&&i&&["absolute","fixed"].includes(i.position)||tt(l)&&!n&&bt(t,l))?o=o.filter((t=>t!==l)):i=e,l=st(l)}return e.set(t,o),o}(e,this._c):[].concat(n),o],l=r[0],c=r.reduce(((t,n)=>{const o=xt(e,n,i);return t.top=P(o.top,t.top),t.right=T(o.right,t.right),t.bottom=T(o.bottom,t.bottom),t.left=P(o.left,t.left),t}),xt(e,l,i));return{width:c.right-c.left,height:c.bottom-c.top,x:c.left,y:c.top}},getOffsetParent:Tt,getElementRects:async function(t){const e=this.getOffsetParent||Tt,n=this.getDimensions,o=await n(t.floating);return{reference:Et(t.reference,await e(t.floating),t.strategy),floating:{x:0,y:0,width:o.width,height:o.height}}},getClientRects:function(t){return Array.from(t.getClientRects())},getDimensions:function(t){const{width:e,height:n}=dt(t);return{width:e,height:n}},getScale:mt,isElement:K,isRTL:function(t){return"rtl"===lt(t).direction}},Rt=_,Ot=function(t){return void 0===t&&(t=0),{name:"offset",options:t,async fn(e){var n,o;const{x:i,y:r,placement:l,middlewareData:c}=e,s=await async function(t,e){const{placement:n,platform:o,elements:i}=t,r=await(null==o.isRTL?void 0:o.isRTL(i.floating)),l=q(n),c=k(n),s="y"===W(n),a=["left","top"].includes(l)?-1:1,u=r&&s?-1:1,f=$(e,t);let{mainAxis:d,crossAxis:p,alignmentAxis:m}="number"==typeof f?{mainAxis:f,crossAxis:0,alignmentAxis:null}:{mainAxis:f.mainAxis||0,crossAxis:f.crossAxis||0,alignmentAxis:f.alignmentAxis};return c&&"number"==typeof m&&(p="end"===c?-1*m:m),s?{x:p*u,y:d*a}:{x:d*a,y:p*u}}(e,t);return l===(null==(n=c.offset)?void 0:n.placement)&&null!=(o=c.arrow)&&o.alignmentOffset?{}:{x:i+s.x,y:r+s.y,data:{...s,placement:l}}}}},At=function(t){return void 0===t&&(t={}),{name:"autoPlacement",options:t,async fn(e){var n,o,i;const{rects:r,middlewareData:l,placement:c,platform:s,elements:a}=e,{crossAxis:u=!1,alignment:f,allowedPlacements:d=L,autoAlignment:p=!0,...m}=$(t,e),h=void 0!==f||d===L?function(t,e,n){return(t?[...n.filter((e=>k(e)===t)),...n.filter((e=>k(e)!==t))]:n.filter((t=>q(t)===t))).filter((n=>!t||k(n)===t||!!e&&I(n)!==n))}(f||null,p,d):d,g=await _(e,m),y=(null==(n=l.autoPlacement)?void 0:n.index)||0,v=h[y];if(null==v)return{};const w=B(v,r,await(null==s.isRTL?void 0:s.isRTL(a.floating)));if(c!==v)return{reset:{placement:h[0]}};const x=[g[q(v)],g[w[0]],g[w[1]]],b=[...(null==(o=l.autoPlacement)?void 0:o.overflows)||[],{placement:v,overflows:x}],E=h[y+1];if(E)return{data:{index:y+1,overflows:b},reset:{placement:E}};const C=b.map((t=>{const e=k(t.placement);return[t.placement,e&&u?t.overflows.slice(0,2).reduce(((t,e)=>t+e),0):t.overflows[0],t.overflows]})).sort(((t,e)=>t[1]-e[1])),T=(null==(i=C.filter((t=>t[2].slice(0,k(t[0])?2:3).every((t=>t<=0))))[0])?void 0:i[0])||C[0][0];return T!==c?{data:{index:y+1,overflows:b},reset:{placement:T}}:{}}}},Dt=t=>({name:"arrow",options:t,async fn(e){const{x:n,y:o,placement:i,rects:r,platform:l,elements:c,middlewareData:s}=e,{element:a,padding:u=0}=$(t,e)||{};if(null==a)return{};const f=N(u),d={x:n,y:o},p=M(i),m=H(p),h=await l.getDimensions(a),g="y"===p,y=g?"top":"left",v=g?"bottom":"right",w=g?"clientHeight":"clientWidth",x=r.reference[m]+r.reference[p]-d[p]-r.floating[m],b=d[p]-r.reference[p],E=await(null==l.getOffsetParent?void 0:l.getOffsetParent(a));let C=E?E[w]:0;C&&await(null==l.isElement?void 0:l.isElement(E))||(C=c.floating[w]||r.floating[m]);const L=x/2-b/2,P=C/2-h[m]/2-1,R=T(f[y],P),O=T(f[v],P),A=R,D=C-h[m]-O,q=C/2-h[m]/2+L,F=S(A,q,D),W=!s.arrow&&null!=k(i)&&q!==F&&r.reference[m]/2-(q{const o=new Map,i={platform:Pt,...n},r={...i.platform,_c:o};return(async(t,e,n)=>{const{placement:o="bottom",strategy:i="absolute",middleware:r=[],platform:l}=n,c=r.filter(Boolean),s=await(null==l.isRTL?void 0:l.isRTL(e));let a=await l.getElementRects({reference:t,floating:e,strategy:i}),{x:u,y:f}=z(a,o,s),d=o,p={},m=0;for(let n=0;n{let e=0;return{name:"autoPlacement",async fn(n){if("auto"===n.placement)return At().fn(n);const{top:o,bottom:i,left:r,right:l}=await Rt(n),c=o>0||i>0||r>0||l>0;return"auto"!==t[e]&&c?(e++,{reset:{placement:t[e]||"auto"}}):c?At().fn(n):{}}}},kt={right:"left",left:"right",top:"bottom",bottom:"top"};async function Ft(t,e,n){const o=e.dataset,i=n?`${n}-${t}`:t;let r=`transition${t.charAt(0).toUpperCase()+t.slice(1)}`;const l=o[r]?o[r].split(" "):[i],c=o[`${r}Start`]?o[`${r}Start`].split(" "):[`${i}-start`],s=o[`${r}End`]?o[`${r}End`].split(" "):[`${i}-end`];Ht(e,l),Ht(e,c),await new Promise((t=>{requestAnimationFrame((()=>{requestAnimationFrame(t)}))})),Wt(e,c),Ht(e,s),await function(t){return new Promise((e=>{const n=getComputedStyle(t).transitionDuration.split(",")[0],o=1e3*Number(n.replace("s",""));setTimeout((()=>{e()}),o)}))}(e),Wt(e,s),Wt(e,l)}function Ht(t,e){t.classList.add(...e)}function Wt(t,e){t.classList.remove(...e)}const Mt=new Map;function Bt(t){Mt.set(t.uniqueId,t)}function It(t){Mt.delete(t.uniqueId)}function Vt(t){!function(t){delete t.coupdoeilElement.openingPopover}(t),Nt(t)}function Nt(t){clearTimeout(t.closingRequest),t.closingRequest=null,Bt(t.coupdoeilElement)}function jt(t,e=!0){t.closing||t.isClosed&&!t.coupdoeilElement.openingPopover||(t.closing=!0,Vt(t),t.children.forEach((t=>{jt(t)})),function(t){t.parent&&(t.parent.children.delete(t),t.parent=null)}(t),e&&t.card&&t.card.dataset.animation?async function(t){await async function(t,e=null){await Ft("leave",t,e),t.classList.add("hidden")}(t.card,"popover"),zt(t)}(t):zt(t))}function zt(t){t.card&&(t.card.remove(),t.card=null),delete t.closing,delete t.coupdoeilElement.dataset.popoverOpen}function _t(t){jt(t,!1)}function Ut(t){Vt(t),t.closingRequest=setTimeout((()=>{jt(t)}),75)}function Xt(t){t.children.forEach((t=>{jt(t)}))}function Yt(){for(const t of Mt.values())jt(t.popoverController),It(t)}function Jt(){for(const t of Mt.values())_t(t.popoverController),It(t)}function Gt(t){let e=t;for(;e.parent;)e=e.parent;const n=e.coupdoeilElement.uniqueId;for(const t of Mt.values())t.uniqueId!==n&&h(t.popoverController)&&(jt(t.popoverController),It(t))}async function Kt(t,e,n){return new Promise((o=>{setTimeout((async()=>{if(t.coupdoeilElement.openingPopover){if(!1===e.cache||e.cache&&!x(t)){let n;n="preload"===e.loading?y(t).innerHTML:await function(t){const e=f(t),n=d(t),o=document.querySelector("meta[name=csrf-token]").content,i={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({params:n,action_name:e,authenticity_token:o})};return fetch("/coupdoeil/popover",i).then((t=>{if(t.status>=400)throw"error while fetching popover content";return t.text()}))}(t),function(t,e){v.set(w(t),e)}(t,n)}o()}}),n.fetch)}))}async function Qt(t,{parent:n,beforeDisplay:r}){if(t.isOpen)return Nt(t);n&&(t.parent=n,n.children.add(t));const l=function(t){const e=t.popoverController.optionsInt||=u(t),n=Object.create(a);for(const t of i)n[t]=o[t].getter(e);return n}(t.coupdoeilElement),c=function(t,e){if(!1===e.openingDelay||function(t){return"click"===p(t)}(t))return{fetch:0,opening:0};return{fetch:100,opening:200}}(t,l),s=new Promise((t=>setTimeout(t,c.opening))),f=Kt(t,l,c);await Promise.all([f,s]);const d=t.parent&&(t.parent.isClosed||t.parent.closingRequest);t.coupdoeilElement.openingPopover&&!d&&await async function(t,n,o){if(t.isOpen)return;Nt(t),t.card=function(t,n){const o=document.createElement("div");return o.setAttribute("role","dialog"),o.classList.add(e),o.style.cssText="position: absolute; left: 0; top: 0;",o.innerHTML=x(t),o.controller=t,o.dataset.placement=n.placement,o.style.visibility="hidden",o}(t,n),document.body.appendChild(t.card),n.animation&&(t.card.dataset.animation=n.animation);Zt(t,(async()=>{await $t(t.coupdoeilElement,t.card,n),t.card.classList.add("hidden"),t.card.style.removeProperty("visibility"),Zt(t,(async()=>{o&&o(t),Bt(t.coupdoeilElement),delete t.coupdoeilElement.openingPopover,t.coupdoeilElement.dataset.popoverOpen=!0,await async function(t,e=null){t.classList.remove("hidden"),await Ft("enter",t,e)}(t.card,"popover")}))}))}(t,l,r)}function Zt(t,e){requestAnimationFrame((()=>{t.coupdoeilElement.openingPopover?e.call():_t(t)}))}class te extends HTMLElement{constructor(){super(),this.uniqueId=function(){const t=new Uint32Array(1);return window.crypto.getRandomValues(t),t[0]}(),this.popoverController=new t(this)}openPopover(t=null,e){if(this.openingPopover||this.popoverController.isOpen||this.disabled||t===this)return;this.openingPopover=!0;const o=this.closest(n)?.controller;return Bt(this),Qt(this.popoverController,{parent:o,...e})}closePopover(){jt(this.popoverController)}get disabled(){return!!this.getAttribute("disabled")}set disabled(t){t?this.setAttribute("disabled",!0):this.removeAttribute("disabled")}}function ee(){return Mt.size>0}const ne=({target:t})=>{const e=t.closest("coup-doeil"),o=t.closest(n);e&&o?function(t,e,n){const o=t.popoverController;if(m(o))return;o.isOpen?jt(o):t.openPopover(n)}(e,0,t):e?function(t,e){const n=t.popoverController;if(m(n))return;n.isOpen?jt(n):(Yt(),t.openPopover(e))}(e,t):o?function(t,e){const n=t.controller;o=e,o.closest("[data-popover-close]")||o.dataset.hasOwnProperty("popoverClose")?jt(n):n.children.size>0&&Xt(n);var o}(o,t):Yt()};const oe=({target:t})=>{const e=t.closest("coup-doeil"),o=t.closest(n);e&&o?function(t,e,n){const o=t.popoverController,i=e.controller;if(g(o))return;o.isOpen?Xt(o):(Xt(i),t.openPopover(n))}(e,o,t):e?function(t,e){const n=t.popoverController;if(g(n))return;n.isClosed?t.openPopover(e,{beforeDisplay:Gt}):n.closingRequest&&(Nt(n),Bt(t))}(e,t):o?function(t){const e=t.controller;e.closingRequest?(Nt(e),Bt(e.coupdoeilElement)):e.children.size>0&&e.children.forEach((t=>{h(t)&&Ut(t)}))}(o):ee()&&function(){for(const t of Mt.values())h(t.popoverController)&&(Ut(t.popoverController),It(t))}()};document.addEventListener("DOMContentLoaded",(()=>{b(),document.addEventListener("click",ne),document.documentElement.addEventListener("mouseover",oe,{passive:!0}),window.Turbo&&(document.addEventListener("turbo:before-cache",(t=>{Jt()})),document.addEventListener("turbo:load",(t=>{Jt(),b()})))})),void 0===customElements.get("coup-doeil")&&customElements.define("coup-doeil",te);
//# sourceMappingURL=coupdoeil.min.js.map
diff --git a/app/assets/javascripts/coupdoeil.min.js.map b/app/assets/javascripts/coupdoeil.min.js.map
index 3c4a0f1740ef762f621f7bcfda1acc0c57edf784..5efc1b8db62680e6f71c9ae3da75ada40073b957 100644
--- a/app/assets/javascripts/coupdoeil.min.js.map
+++ b/app/assets/javascripts/coupdoeil.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"coupdoeil.min.js","sources":["../../javascript/coupdoeil/hovercard/controller.js","../../javascript/coupdoeil/hovercard/config.js","../../javascript/coupdoeil/hovercard/optionsParser.js","../../javascript/coupdoeil/hovercard/attributes.js","../../javascript/coupdoeil/hovercard/cache.js","../../../node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs","../../../node_modules/@floating-ui/core/dist/floating-ui.core.mjs","../../../node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs","../../../node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs","../../javascript/coupdoeil/hovercard/positioning.js","../../../node_modules/el-transition/index.js","../../javascript/coupdoeil/hovercard/current.js","../../javascript/coupdoeil/hovercard/closing.js","../../javascript/coupdoeil/hovercard/opening.js","../../javascript/coupdoeil/elements/coupdoeil_element.js","../../javascript/coupdoeil/hovercard/state_check.js","../../javascript/coupdoeil/events/onclick.js","../../javascript/coupdoeil/events/onmouseover.js","../../javascript/coupdoeil/events.js","../../javascript/coupdoeil/hovercard.js"],"sourcesContent":["export class HovercardController {\n constructor(coupdoeilElement) {\n this.coupdoeilElement = coupdoeilElement\n\n this.card = null // can go on coupdoeil element, renamed 'hovercardElement'\n\n this.children = new Set() // can go on hovercardElement\n this.parent = null // can go on hovercardElement\n\n this.closingRequest = null // can go on coupdoeil element\n }\n\n get isOpen() {\n return !!this.coupdoeilElement.dataset.hovercardOpen\n }\n\n get isClosed() {\n return !this.isOpen\n }\n}\n","export const HOVERCARD_CLASS_NAME = 'coupdoeil--hovercard'\nexport const HOVERCARD_SELECTOR = `.${HOVERCARD_CLASS_NAME}`\nexport const HOVERCARD_CLOSE_BTN_SELECTOR = '[data-hovercard-close]'\n\n// the time (ms) to wait before closing the hovercard,\n// to avoid flickering if the user hovers out and in quickly,\n// or if the user moves the mouse from the target to the hovercard\nexport const CLOSING_DELAY_MS = 75\n\n// the time (ms) to wait before starting to fetch the content,\n// to avoid fetching too soon if the user hovers in and out the target quickly\nexport const FETCH_DELAY_MS = 100\n\n// the minimum time (ms) the user should wait before seeing the hovercard\nexport const OPENING_DELAY_MS = 200\n","const OPTIONS = {\n animation: { getter: getAnimation },\n cache: { getter: getCache },\n loading: { getter: getLoading },\n offset: { getter: getOffset },\n openingDelay: { getter: getOpeningDelay },\n placement: { getter: getPlacement },\n trigger: { getter: getTrigger },\n}\n\nconst ORDERED_OPTIONS = [\n \"trigger\", // bit size: 1 shift: 0\n \"loading\", // bit size: 2 shift: 1\n \"cache\", // bit size: 1 shift: 3\n \"openingDelay\", // bit size: 1 shift: 4\n \"animation\", // bit size: 3 shift: 5\n \"placement\", // bit size: 16 shift: 8\n \"offset\" // bit size: 21 shift: 24\n]\n\nconst TRIGGERS = [\"hover\", \"click\"]\nconst ANIMATIONS = [false, \"slide-in\", \"fade-in\", \"slide-out\", \"custom\"]\nconst PLACEMENTS = [\n 'auto',\n 'top', 'top-start', 'top-end',\n 'right', 'right-start', 'right-end',\n 'bottom', 'bottom-start', 'bottom-end',\n 'left', 'left-start', 'left-end'\n]\nconst LOADINGS = [\"async\", \"preload\", \"lazy\"]\n\nfunction parseCSSSize(value) {\n if (typeof value === 'number') {\n return value\n } else if ((/^(-?\\d+\\.?\\d+)px$/).test(value)) {\n return parseFloat(value)\n } else if ((/^(-?\\d*\\.?\\d+)rem$/).test(value)) {\n return parseFloat(value) * parseFloat(getComputedStyle(document.documentElement).fontSize)\n }\n return 0\n}\n\nfunction getOffset(optionsInt) {\n // shift is BigInt(16 + 3 + 1 + 1 + 2 + 1)\n const offsetBits = Number(BigInt(optionsInt) >> BigInt(24))\n if (offsetBits === 0)\n return 0\n\n const isNegative = (offsetBits & 1) === 1\n const isREM = (offsetBits & 2) === 2\n // decimals mask is 2 ** 11 - 1\n const decimals = (offsetBits >> 2) & 2047\n const integer = (offsetBits >> (2 + 11))\n\n const CSSSize = `${isNegative ? '-' : ''}${integer}.${decimals}${isREM ? 'rem' : 'px'}`\n return parseCSSSize(CSSSize)\n}\n\nfunction getPlacement(optionsInt) {\n // shift is 3 + 1 + 1 + 2 + 1, mask is 2 ** 16 - 1\n const placementBits = (optionsInt >> 8) & 65535\n let shift = 0\n let lastPlacement = null\n const placements = []\n while (lastPlacement !== \"auto\" && shift < 16) {\n // mask is 2 ** 4 - 1\n lastPlacement = PLACEMENTS[(placementBits >> shift) & 15]\n placements.push(lastPlacement)\n shift += 4\n }\n return placements\n}\n\nfunction getAnimation(optionsInt) {\n // return ANIMATIONS[(optionsInt & 56) >> 5]\n return ANIMATIONS[(optionsInt >> 5) & 7]\n}\n\nfunction getOpeningDelay(optionsInt) {\n return ((optionsInt >> 4) & 1) === 1\n}\n\nfunction getCache(optionsInt) {\n return (optionsInt & 8) === 8\n}\n\nfunction getLoading(optionsInt) {\n // Shift right 1 time to remove trigger bit, mask with 3 (0b11).\n return LOADINGS[(optionsInt >> 1) & 3]\n}\n\nfunction getTrigger(optionsInt) {\n return TRIGGERS[optionsInt & 1]\n}\n\nconst HovercardOptions = {\n animation: undefined,\n cache: undefined,\n loading: undefined,\n offset: undefined,\n openingDelay: undefined,\n placement: undefined,\n trigger: undefined,\n}\n\nexport function extractOptionsFromElement(coupdoeilElement) {\n const optionsInt = coupdoeilElement.hovercardController.optionsInt ||= parseOtionsInt((coupdoeilElement))\n const options = Object.create(HovercardOptions)\n\n for (const option of ORDERED_OPTIONS) {\n options[option] = OPTIONS[option].getter(optionsInt)\n }\n\n return options\n}\n\nfunction parseOtionsInt(coupdoeilElement) {\n const optionsString = coupdoeilElement.getAttribute(\"hc\")\n return parseInt(optionsString, 36)\n}\n\nexport function extractOptionFromElement(coupdoeilElement, optionName) {\n const optionsInt = coupdoeilElement.hovercardController.optionsInt ||= parseOtionsInt((coupdoeilElement))\n\n return OPTIONS[optionName].getter(optionsInt)\n}\n","import {extractOptionFromElement} from \"./optionsParser\";\n\nexport function getType(controller) {\n return controller.coupdoeilElement.getAttribute('hc-type')\n}\n\nexport function getParams(controller) {\n return controller.coupdoeilElement.getAttribute('hc-params')\n}\n\nexport function getTrigger(controller) {\n return extractOptionFromElement(controller.coupdoeilElement, 'trigger')\n}\n\nexport function triggeredOnClick(controller) {\n return getTrigger(controller) === 'click'\n}\n\nexport function noTriggeredOnClick(controller) {\n return getTrigger(controller) !== 'click'\n}\n\nexport function triggeredOnHover(controller) {\n return getTrigger(controller) === 'hover'\n}\n\nexport function notTriggeredOnHover(controller) {\n return getTrigger(controller) !== 'hover'\n}\n\nexport function preloadedContentElement(controller) {\n return controller.coupdoeilElement.querySelector('.hovercard-content')\n}\n","import {getParams, getType, preloadedContentElement} from './attributes'\n\nexport const hovercardContentHTMLMap = new Map()\n\nfunction cacheMapKey(controller) {\n if (preloadedContentElement(controller)) {\n return controller.coupdoeilElement.uniqueId\n }\n return getType(controller) + getParams(controller)\n}\n\nexport function getHovercardContentHTML(controller) {\n return hovercardContentHTMLMap.get(cacheMapKey(controller))\n}\n\nexport function setHovercardContentHTML(controller, value) {\n hovercardContentHTMLMap.set(cacheMapKey(controller), value)\n}\n\nexport function clearHovercardContentCache() {\n hovercardContentHTMLMap.clear()\n}\n","/**\n * Custom positioning reference element.\n * @see https://floating-ui.com/docs/virtual-elements\n */\n\nconst sides = ['top', 'right', 'bottom', 'left'];\nconst alignments = ['start', 'end'];\nconst placements = /*#__PURE__*/sides.reduce((acc, side) => acc.concat(side, side + \"-\" + alignments[0], side + \"-\" + alignments[1]), []);\nconst min = Math.min;\nconst max = Math.max;\nconst round = Math.round;\nconst floor = Math.floor;\nconst createCoords = v => ({\n x: v,\n y: v\n});\nconst oppositeSideMap = {\n left: 'right',\n right: 'left',\n bottom: 'top',\n top: 'bottom'\n};\nconst oppositeAlignmentMap = {\n start: 'end',\n end: 'start'\n};\nfunction clamp(start, value, end) {\n return max(start, min(value, end));\n}\nfunction evaluate(value, param) {\n return typeof value === 'function' ? value(param) : value;\n}\nfunction getSide(placement) {\n return placement.split('-')[0];\n}\nfunction getAlignment(placement) {\n return placement.split('-')[1];\n}\nfunction getOppositeAxis(axis) {\n return axis === 'x' ? 'y' : 'x';\n}\nfunction getAxisLength(axis) {\n return axis === 'y' ? 'height' : 'width';\n}\nfunction getSideAxis(placement) {\n return ['top', 'bottom'].includes(getSide(placement)) ? 'y' : 'x';\n}\nfunction getAlignmentAxis(placement) {\n return getOppositeAxis(getSideAxis(placement));\n}\nfunction getAlignmentSides(placement, rects, rtl) {\n if (rtl === void 0) {\n rtl = false;\n }\n const alignment = getAlignment(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const length = getAxisLength(alignmentAxis);\n let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top';\n if (rects.reference[length] > rects.floating[length]) {\n mainAlignmentSide = getOppositePlacement(mainAlignmentSide);\n }\n return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];\n}\nfunction getExpandedPlacements(placement) {\n const oppositePlacement = getOppositePlacement(placement);\n return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];\n}\nfunction getOppositeAlignmentPlacement(placement) {\n return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]);\n}\nfunction getSideList(side, isStart, rtl) {\n const lr = ['left', 'right'];\n const rl = ['right', 'left'];\n const tb = ['top', 'bottom'];\n const bt = ['bottom', 'top'];\n switch (side) {\n case 'top':\n case 'bottom':\n if (rtl) return isStart ? rl : lr;\n return isStart ? lr : rl;\n case 'left':\n case 'right':\n return isStart ? tb : bt;\n default:\n return [];\n }\n}\nfunction getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {\n const alignment = getAlignment(placement);\n let list = getSideList(getSide(placement), direction === 'start', rtl);\n if (alignment) {\n list = list.map(side => side + \"-\" + alignment);\n if (flipAlignment) {\n list = list.concat(list.map(getOppositeAlignmentPlacement));\n }\n }\n return list;\n}\nfunction getOppositePlacement(placement) {\n return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]);\n}\nfunction expandPaddingObject(padding) {\n return {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0,\n ...padding\n };\n}\nfunction getPaddingObject(padding) {\n return typeof padding !== 'number' ? expandPaddingObject(padding) : {\n top: padding,\n right: padding,\n bottom: padding,\n left: padding\n };\n}\nfunction rectToClientRect(rect) {\n const {\n x,\n y,\n width,\n height\n } = rect;\n return {\n width,\n height,\n top: y,\n left: x,\n right: x + width,\n bottom: y + height,\n x,\n y\n };\n}\n\nexport { alignments, clamp, createCoords, evaluate, expandPaddingObject, floor, getAlignment, getAlignmentAxis, getAlignmentSides, getAxisLength, getExpandedPlacements, getOppositeAlignmentPlacement, getOppositeAxis, getOppositeAxisPlacements, getOppositePlacement, getPaddingObject, getSide, getSideAxis, max, min, placements, rectToClientRect, round, sides };\n","import { getSideAxis, getAlignmentAxis, getAxisLength, getSide, getAlignment, evaluate, getPaddingObject, rectToClientRect, min, clamp, placements, getAlignmentSides, getOppositeAlignmentPlacement, getOppositePlacement, getExpandedPlacements, getOppositeAxisPlacements, sides, max, getOppositeAxis } from '@floating-ui/utils';\nexport { rectToClientRect } from '@floating-ui/utils';\n\nfunction computeCoordsFromPlacement(_ref, placement, rtl) {\n let {\n reference,\n floating\n } = _ref;\n const sideAxis = getSideAxis(placement);\n const alignmentAxis = getAlignmentAxis(placement);\n const alignLength = getAxisLength(alignmentAxis);\n const side = getSide(placement);\n const isVertical = sideAxis === 'y';\n const commonX = reference.x + reference.width / 2 - floating.width / 2;\n const commonY = reference.y + reference.height / 2 - floating.height / 2;\n const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;\n let coords;\n switch (side) {\n case 'top':\n coords = {\n x: commonX,\n y: reference.y - floating.height\n };\n break;\n case 'bottom':\n coords = {\n x: commonX,\n y: reference.y + reference.height\n };\n break;\n case 'right':\n coords = {\n x: reference.x + reference.width,\n y: commonY\n };\n break;\n case 'left':\n coords = {\n x: reference.x - floating.width,\n y: commonY\n };\n break;\n default:\n coords = {\n x: reference.x,\n y: reference.y\n };\n }\n switch (getAlignment(placement)) {\n case 'start':\n coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);\n break;\n case 'end':\n coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);\n break;\n }\n return coords;\n}\n\n/**\n * Computes the `x` and `y` coordinates that will place the floating element\n * next to a given reference element.\n *\n * This export does not have any `platform` interface logic. You will need to\n * write one for the platform you are using Floating UI with.\n */\nconst computePosition = async (reference, floating, config) => {\n const {\n placement = 'bottom',\n strategy = 'absolute',\n middleware = [],\n platform\n } = config;\n const validMiddleware = middleware.filter(Boolean);\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating));\n let rects = await platform.getElementRects({\n reference,\n floating,\n strategy\n });\n let {\n x,\n y\n } = computeCoordsFromPlacement(rects, placement, rtl);\n let statefulPlacement = placement;\n let middlewareData = {};\n let resetCount = 0;\n for (let i = 0; i < validMiddleware.length; i++) {\n const {\n name,\n fn\n } = validMiddleware[i];\n const {\n x: nextX,\n y: nextY,\n data,\n reset\n } = await fn({\n x,\n y,\n initialPlacement: placement,\n placement: statefulPlacement,\n strategy,\n middlewareData,\n rects,\n platform,\n elements: {\n reference,\n floating\n }\n });\n x = nextX != null ? nextX : x;\n y = nextY != null ? nextY : y;\n middlewareData = {\n ...middlewareData,\n [name]: {\n ...middlewareData[name],\n ...data\n }\n };\n if (reset && resetCount <= 50) {\n resetCount++;\n if (typeof reset === 'object') {\n if (reset.placement) {\n statefulPlacement = reset.placement;\n }\n if (reset.rects) {\n rects = reset.rects === true ? await platform.getElementRects({\n reference,\n floating,\n strategy\n }) : reset.rects;\n }\n ({\n x,\n y\n } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));\n }\n i = -1;\n }\n }\n return {\n x,\n y,\n placement: statefulPlacement,\n strategy,\n middlewareData\n };\n};\n\n/**\n * Resolves with an object of overflow side offsets that determine how much the\n * element is overflowing a given clipping boundary on each side.\n * - positive = overflowing the boundary by that number of pixels\n * - negative = how many pixels left before it will overflow\n * - 0 = lies flush with the boundary\n * @see https://floating-ui.com/docs/detectOverflow\n */\nasync function detectOverflow(state, options) {\n var _await$platform$isEle;\n if (options === void 0) {\n options = {};\n }\n const {\n x,\n y,\n platform,\n rects,\n elements,\n strategy\n } = state;\n const {\n boundary = 'clippingAncestors',\n rootBoundary = 'viewport',\n elementContext = 'floating',\n altBoundary = false,\n padding = 0\n } = evaluate(options, state);\n const paddingObject = getPaddingObject(padding);\n const altContext = elementContext === 'floating' ? 'reference' : 'floating';\n const element = elements[altBoundary ? altContext : elementContext];\n const clippingClientRect = rectToClientRect(await platform.getClippingRect({\n element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))),\n boundary,\n rootBoundary,\n strategy\n }));\n const rect = elementContext === 'floating' ? {\n x,\n y,\n width: rects.floating.width,\n height: rects.floating.height\n } : rects.reference;\n const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating));\n const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || {\n x: 1,\n y: 1\n } : {\n x: 1,\n y: 1\n };\n const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({\n elements,\n rect,\n offsetParent,\n strategy\n }) : rect);\n return {\n top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,\n bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,\n left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,\n right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x\n };\n}\n\n/**\n * Provides data to position an inner element of the floating element so that it\n * appears centered to the reference element.\n * @see https://floating-ui.com/docs/arrow\n */\nconst arrow = options => ({\n name: 'arrow',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement,\n rects,\n platform,\n elements,\n middlewareData\n } = state;\n // Since `element` is required, we don't Partial<> the type.\n const {\n element,\n padding = 0\n } = evaluate(options, state) || {};\n if (element == null) {\n return {};\n }\n const paddingObject = getPaddingObject(padding);\n const coords = {\n x,\n y\n };\n const axis = getAlignmentAxis(placement);\n const length = getAxisLength(axis);\n const arrowDimensions = await platform.getDimensions(element);\n const isYAxis = axis === 'y';\n const minProp = isYAxis ? 'top' : 'left';\n const maxProp = isYAxis ? 'bottom' : 'right';\n const clientProp = isYAxis ? 'clientHeight' : 'clientWidth';\n const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length];\n const startDiff = coords[axis] - rects.reference[axis];\n const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element));\n let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0;\n\n // DOM platform can return `window` as the `offsetParent`.\n if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) {\n clientSize = elements.floating[clientProp] || rects.floating[length];\n }\n const centerToReference = endDiff / 2 - startDiff / 2;\n\n // If the padding is large enough that it causes the arrow to no longer be\n // centered, modify the padding so that it is centered.\n const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1;\n const minPadding = min(paddingObject[minProp], largestPossiblePadding);\n const maxPadding = min(paddingObject[maxProp], largestPossiblePadding);\n\n // Make sure the arrow doesn't overflow the floating element if the center\n // point is outside the floating element's bounds.\n const min$1 = minPadding;\n const max = clientSize - arrowDimensions[length] - maxPadding;\n const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;\n const offset = clamp(min$1, center, max);\n\n // If the reference is small enough that the arrow's padding causes it to\n // to point to nothing for an aligned placement, adjust the offset of the\n // floating element itself. To ensure `shift()` continues to take action,\n // a single reset is performed when this is true.\n const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;\n const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;\n return {\n [axis]: coords[axis] + alignmentOffset,\n data: {\n [axis]: offset,\n centerOffset: center - offset - alignmentOffset,\n ...(shouldAddOffset && {\n alignmentOffset\n })\n },\n reset: shouldAddOffset\n };\n }\n});\n\nfunction getPlacementList(alignment, autoAlignment, allowedPlacements) {\n const allowedPlacementsSortedByAlignment = alignment ? [...allowedPlacements.filter(placement => getAlignment(placement) === alignment), ...allowedPlacements.filter(placement => getAlignment(placement) !== alignment)] : allowedPlacements.filter(placement => getSide(placement) === placement);\n return allowedPlacementsSortedByAlignment.filter(placement => {\n if (alignment) {\n return getAlignment(placement) === alignment || (autoAlignment ? getOppositeAlignmentPlacement(placement) !== placement : false);\n }\n return true;\n });\n}\n/**\n * Optimizes the visibility of the floating element by choosing the placement\n * that has the most space available automatically, without needing to specify a\n * preferred placement. Alternative to `flip`.\n * @see https://floating-ui.com/docs/autoPlacement\n */\nconst autoPlacement = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'autoPlacement',\n options,\n async fn(state) {\n var _middlewareData$autoP, _middlewareData$autoP2, _placementsThatFitOnE;\n const {\n rects,\n middlewareData,\n placement,\n platform,\n elements\n } = state;\n const {\n crossAxis = false,\n alignment,\n allowedPlacements = placements,\n autoAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements;\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0;\n const currentPlacement = placements$1[currentIndex];\n if (currentPlacement == null) {\n return {};\n }\n const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)));\n\n // Make `computeCoords` start from the right place.\n if (placement !== currentPlacement) {\n return {\n reset: {\n placement: placements$1[0]\n }\n };\n }\n const currentOverflows = [overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]]];\n const allOverflows = [...(((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || []), {\n placement: currentPlacement,\n overflows: currentOverflows\n }];\n const nextPlacement = placements$1[currentIndex + 1];\n\n // There are more placements to check.\n if (nextPlacement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n const placementsSortedByMostSpace = allOverflows.map(d => {\n const alignment = getAlignment(d.placement);\n return [d.placement, alignment && crossAxis ?\n // Check along the mainAxis and main crossAxis side.\n d.overflows.slice(0, 2).reduce((acc, v) => acc + v, 0) :\n // Check only the mainAxis.\n d.overflows[0], d.overflows];\n }).sort((a, b) => a[1] - b[1]);\n const placementsThatFitOnEachSide = placementsSortedByMostSpace.filter(d => d[2].slice(0,\n // Aligned placements should not check their opposite crossAxis\n // side.\n getAlignment(d[0]) ? 2 : 3).every(v => v <= 0));\n const resetPlacement = ((_placementsThatFitOnE = placementsThatFitOnEachSide[0]) == null ? void 0 : _placementsThatFitOnE[0]) || placementsSortedByMostSpace[0][0];\n if (resetPlacement !== placement) {\n return {\n data: {\n index: currentIndex + 1,\n overflows: allOverflows\n },\n reset: {\n placement: resetPlacement\n }\n };\n }\n return {};\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by flipping the `placement`\n * in order to keep it in view when the preferred placement(s) will overflow the\n * clipping boundary. Alternative to `autoPlacement`.\n * @see https://floating-ui.com/docs/flip\n */\nconst flip = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'flip',\n options,\n async fn(state) {\n var _middlewareData$arrow, _middlewareData$flip;\n const {\n placement,\n middlewareData,\n rects,\n initialPlacement,\n platform,\n elements\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true,\n fallbackPlacements: specifiedFallbackPlacements,\n fallbackStrategy = 'bestFit',\n fallbackAxisSideDirection = 'none',\n flipAlignment = true,\n ...detectOverflowOptions\n } = evaluate(options, state);\n\n // If a reset by the arrow was caused due to an alignment offset being\n // added, we should skip any logic now since `flip()` has already done its\n // work.\n // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643\n if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n const side = getSide(placement);\n const initialSideAxis = getSideAxis(initialPlacement);\n const isBasePlacement = getSide(initialPlacement) === initialPlacement;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));\n const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none';\n if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {\n fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));\n }\n const placements = [initialPlacement, ...fallbackPlacements];\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const overflows = [];\n let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];\n if (checkMainAxis) {\n overflows.push(overflow[side]);\n }\n if (checkCrossAxis) {\n const sides = getAlignmentSides(placement, rects, rtl);\n overflows.push(overflow[sides[0]], overflow[sides[1]]);\n }\n overflowsData = [...overflowsData, {\n placement,\n overflows\n }];\n\n // One or more sides is overflowing.\n if (!overflows.every(side => side <= 0)) {\n var _middlewareData$flip2, _overflowsData$filter;\n const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;\n const nextPlacement = placements[nextIndex];\n if (nextPlacement) {\n // Try next placement and re-run the lifecycle.\n return {\n data: {\n index: nextIndex,\n overflows: overflowsData\n },\n reset: {\n placement: nextPlacement\n }\n };\n }\n\n // First, find the candidates that fit on the mainAxis side of overflow,\n // then find the placement that fits the best on the main crossAxis side.\n let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;\n\n // Otherwise fallback.\n if (!resetPlacement) {\n switch (fallbackStrategy) {\n case 'bestFit':\n {\n var _overflowsData$filter2;\n const placement = (_overflowsData$filter2 = overflowsData.filter(d => {\n if (hasFallbackAxisSideDirection) {\n const currentSideAxis = getSideAxis(d.placement);\n return currentSideAxis === initialSideAxis ||\n // Create a bias to the `y` side axis due to horizontal\n // reading directions favoring greater width.\n currentSideAxis === 'y';\n }\n return true;\n }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0];\n if (placement) {\n resetPlacement = placement;\n }\n break;\n }\n case 'initialPlacement':\n resetPlacement = initialPlacement;\n break;\n }\n }\n if (placement !== resetPlacement) {\n return {\n reset: {\n placement: resetPlacement\n }\n };\n }\n }\n return {};\n }\n };\n};\n\nfunction getSideOffsets(overflow, rect) {\n return {\n top: overflow.top - rect.height,\n right: overflow.right - rect.width,\n bottom: overflow.bottom - rect.height,\n left: overflow.left - rect.width\n };\n}\nfunction isAnySideFullyClipped(overflow) {\n return sides.some(side => overflow[side] >= 0);\n}\n/**\n * Provides data to hide the floating element in applicable situations, such as\n * when it is not in the same clipping context as the reference element.\n * @see https://floating-ui.com/docs/hide\n */\nconst hide = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'hide',\n options,\n async fn(state) {\n const {\n rects\n } = state;\n const {\n strategy = 'referenceHidden',\n ...detectOverflowOptions\n } = evaluate(options, state);\n switch (strategy) {\n case 'referenceHidden':\n {\n const overflow = await detectOverflow(state, {\n ...detectOverflowOptions,\n elementContext: 'reference'\n });\n const offsets = getSideOffsets(overflow, rects.reference);\n return {\n data: {\n referenceHiddenOffsets: offsets,\n referenceHidden: isAnySideFullyClipped(offsets)\n }\n };\n }\n case 'escaped':\n {\n const overflow = await detectOverflow(state, {\n ...detectOverflowOptions,\n altBoundary: true\n });\n const offsets = getSideOffsets(overflow, rects.floating);\n return {\n data: {\n escapedOffsets: offsets,\n escaped: isAnySideFullyClipped(offsets)\n }\n };\n }\n default:\n {\n return {};\n }\n }\n }\n };\n};\n\nfunction getBoundingRect(rects) {\n const minX = min(...rects.map(rect => rect.left));\n const minY = min(...rects.map(rect => rect.top));\n const maxX = max(...rects.map(rect => rect.right));\n const maxY = max(...rects.map(rect => rect.bottom));\n return {\n x: minX,\n y: minY,\n width: maxX - minX,\n height: maxY - minY\n };\n}\nfunction getRectsByLine(rects) {\n const sortedRects = rects.slice().sort((a, b) => a.y - b.y);\n const groups = [];\n let prevRect = null;\n for (let i = 0; i < sortedRects.length; i++) {\n const rect = sortedRects[i];\n if (!prevRect || rect.y - prevRect.y > prevRect.height / 2) {\n groups.push([rect]);\n } else {\n groups[groups.length - 1].push(rect);\n }\n prevRect = rect;\n }\n return groups.map(rect => rectToClientRect(getBoundingRect(rect)));\n}\n/**\n * Provides improved positioning for inline reference elements that can span\n * over multiple lines, such as hyperlinks or range selections.\n * @see https://floating-ui.com/docs/inline\n */\nconst inline = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'inline',\n options,\n async fn(state) {\n const {\n placement,\n elements,\n rects,\n platform,\n strategy\n } = state;\n // A MouseEvent's client{X,Y} coords can be up to 2 pixels off a\n // ClientRect's bounds, despite the event listener being triggered. A\n // padding of 2 seems to handle this issue.\n const {\n padding = 2,\n x,\n y\n } = evaluate(options, state);\n const nativeClientRects = Array.from((await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference))) || []);\n const clientRects = getRectsByLine(nativeClientRects);\n const fallback = rectToClientRect(getBoundingRect(nativeClientRects));\n const paddingObject = getPaddingObject(padding);\n function getBoundingClientRect() {\n // There are two rects and they are disjoined.\n if (clientRects.length === 2 && clientRects[0].left > clientRects[1].right && x != null && y != null) {\n // Find the first rect in which the point is fully inside.\n return clientRects.find(rect => x > rect.left - paddingObject.left && x < rect.right + paddingObject.right && y > rect.top - paddingObject.top && y < rect.bottom + paddingObject.bottom) || fallback;\n }\n\n // There are 2 or more connected rects.\n if (clientRects.length >= 2) {\n if (getSideAxis(placement) === 'y') {\n const firstRect = clientRects[0];\n const lastRect = clientRects[clientRects.length - 1];\n const isTop = getSide(placement) === 'top';\n const top = firstRect.top;\n const bottom = lastRect.bottom;\n const left = isTop ? firstRect.left : lastRect.left;\n const right = isTop ? firstRect.right : lastRect.right;\n const width = right - left;\n const height = bottom - top;\n return {\n top,\n bottom,\n left,\n right,\n width,\n height,\n x: left,\n y: top\n };\n }\n const isLeftSide = getSide(placement) === 'left';\n const maxRight = max(...clientRects.map(rect => rect.right));\n const minLeft = min(...clientRects.map(rect => rect.left));\n const measureRects = clientRects.filter(rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight);\n const top = measureRects[0].top;\n const bottom = measureRects[measureRects.length - 1].bottom;\n const left = minLeft;\n const right = maxRight;\n const width = right - left;\n const height = bottom - top;\n return {\n top,\n bottom,\n left,\n right,\n width,\n height,\n x: left,\n y: top\n };\n }\n return fallback;\n }\n const resetRects = await platform.getElementRects({\n reference: {\n getBoundingClientRect\n },\n floating: elements.floating,\n strategy\n });\n if (rects.reference.x !== resetRects.reference.x || rects.reference.y !== resetRects.reference.y || rects.reference.width !== resetRects.reference.width || rects.reference.height !== resetRects.reference.height) {\n return {\n reset: {\n rects: resetRects\n }\n };\n }\n return {};\n }\n };\n};\n\n// For type backwards-compatibility, the `OffsetOptions` type was also\n// Derivable.\n\nasync function convertValueToCoords(state, options) {\n const {\n placement,\n platform,\n elements\n } = state;\n const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating));\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isVertical = getSideAxis(placement) === 'y';\n const mainAxisMulti = ['left', 'top'].includes(side) ? -1 : 1;\n const crossAxisMulti = rtl && isVertical ? -1 : 1;\n const rawValue = evaluate(options, state);\n\n // eslint-disable-next-line prefer-const\n let {\n mainAxis,\n crossAxis,\n alignmentAxis\n } = typeof rawValue === 'number' ? {\n mainAxis: rawValue,\n crossAxis: 0,\n alignmentAxis: null\n } : {\n mainAxis: rawValue.mainAxis || 0,\n crossAxis: rawValue.crossAxis || 0,\n alignmentAxis: rawValue.alignmentAxis\n };\n if (alignment && typeof alignmentAxis === 'number') {\n crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis;\n }\n return isVertical ? {\n x: crossAxis * crossAxisMulti,\n y: mainAxis * mainAxisMulti\n } : {\n x: mainAxis * mainAxisMulti,\n y: crossAxis * crossAxisMulti\n };\n}\n\n/**\n * Modifies the placement by translating the floating element along the\n * specified axes.\n * A number (shorthand for `mainAxis` or distance), or an axes configuration\n * object may be passed.\n * @see https://floating-ui.com/docs/offset\n */\nconst offset = function (options) {\n if (options === void 0) {\n options = 0;\n }\n return {\n name: 'offset',\n options,\n async fn(state) {\n var _middlewareData$offse, _middlewareData$arrow;\n const {\n x,\n y,\n placement,\n middlewareData\n } = state;\n const diffCoords = await convertValueToCoords(state, options);\n\n // If the placement is the same and the arrow caused an alignment offset\n // then we don't need to change the positioning coordinates.\n if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {\n return {};\n }\n return {\n x: x + diffCoords.x,\n y: y + diffCoords.y,\n data: {\n ...diffCoords,\n placement\n }\n };\n }\n };\n};\n\n/**\n * Optimizes the visibility of the floating element by shifting it in order to\n * keep it in view when it will overflow the clipping boundary.\n * @see https://floating-ui.com/docs/shift\n */\nconst shift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'shift',\n options,\n async fn(state) {\n const {\n x,\n y,\n placement\n } = state;\n const {\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = false,\n limiter = {\n fn: _ref => {\n let {\n x,\n y\n } = _ref;\n return {\n x,\n y\n };\n }\n },\n ...detectOverflowOptions\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const crossAxis = getSideAxis(getSide(placement));\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n if (checkMainAxis) {\n const minSide = mainAxis === 'y' ? 'top' : 'left';\n const maxSide = mainAxis === 'y' ? 'bottom' : 'right';\n const min = mainAxisCoord + overflow[minSide];\n const max = mainAxisCoord - overflow[maxSide];\n mainAxisCoord = clamp(min, mainAxisCoord, max);\n }\n if (checkCrossAxis) {\n const minSide = crossAxis === 'y' ? 'top' : 'left';\n const maxSide = crossAxis === 'y' ? 'bottom' : 'right';\n const min = crossAxisCoord + overflow[minSide];\n const max = crossAxisCoord - overflow[maxSide];\n crossAxisCoord = clamp(min, crossAxisCoord, max);\n }\n const limitedCoords = limiter.fn({\n ...state,\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n });\n return {\n ...limitedCoords,\n data: {\n x: limitedCoords.x - x,\n y: limitedCoords.y - y,\n enabled: {\n [mainAxis]: checkMainAxis,\n [crossAxis]: checkCrossAxis\n }\n }\n };\n }\n };\n};\n/**\n * Built-in `limiter` that will stop `shift()` at a certain point.\n */\nconst limitShift = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n options,\n fn(state) {\n const {\n x,\n y,\n placement,\n rects,\n middlewareData\n } = state;\n const {\n offset = 0,\n mainAxis: checkMainAxis = true,\n crossAxis: checkCrossAxis = true\n } = evaluate(options, state);\n const coords = {\n x,\n y\n };\n const crossAxis = getSideAxis(placement);\n const mainAxis = getOppositeAxis(crossAxis);\n let mainAxisCoord = coords[mainAxis];\n let crossAxisCoord = coords[crossAxis];\n const rawOffset = evaluate(offset, state);\n const computedOffset = typeof rawOffset === 'number' ? {\n mainAxis: rawOffset,\n crossAxis: 0\n } : {\n mainAxis: 0,\n crossAxis: 0,\n ...rawOffset\n };\n if (checkMainAxis) {\n const len = mainAxis === 'y' ? 'height' : 'width';\n const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis;\n const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis;\n if (mainAxisCoord < limitMin) {\n mainAxisCoord = limitMin;\n } else if (mainAxisCoord > limitMax) {\n mainAxisCoord = limitMax;\n }\n }\n if (checkCrossAxis) {\n var _middlewareData$offse, _middlewareData$offse2;\n const len = mainAxis === 'y' ? 'width' : 'height';\n const isOriginSide = ['top', 'left'].includes(getSide(placement));\n const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis);\n const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0);\n if (crossAxisCoord < limitMin) {\n crossAxisCoord = limitMin;\n } else if (crossAxisCoord > limitMax) {\n crossAxisCoord = limitMax;\n }\n }\n return {\n [mainAxis]: mainAxisCoord,\n [crossAxis]: crossAxisCoord\n };\n }\n };\n};\n\n/**\n * Provides data that allows you to change the size of the floating element —\n * for instance, prevent it from overflowing the clipping boundary or match the\n * width of the reference element.\n * @see https://floating-ui.com/docs/size\n */\nconst size = function (options) {\n if (options === void 0) {\n options = {};\n }\n return {\n name: 'size',\n options,\n async fn(state) {\n var _state$middlewareData, _state$middlewareData2;\n const {\n placement,\n rects,\n platform,\n elements\n } = state;\n const {\n apply = () => {},\n ...detectOverflowOptions\n } = evaluate(options, state);\n const overflow = await detectOverflow(state, detectOverflowOptions);\n const side = getSide(placement);\n const alignment = getAlignment(placement);\n const isYAxis = getSideAxis(placement) === 'y';\n const {\n width,\n height\n } = rects.floating;\n let heightSide;\n let widthSide;\n if (side === 'top' || side === 'bottom') {\n heightSide = side;\n widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right';\n } else {\n widthSide = side;\n heightSide = alignment === 'end' ? 'top' : 'bottom';\n }\n const maximumClippingHeight = height - overflow.top - overflow.bottom;\n const maximumClippingWidth = width - overflow.left - overflow.right;\n const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight);\n const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth);\n const noShift = !state.middlewareData.shift;\n let availableHeight = overflowAvailableHeight;\n let availableWidth = overflowAvailableWidth;\n if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) {\n availableWidth = maximumClippingWidth;\n }\n if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) {\n availableHeight = maximumClippingHeight;\n }\n if (noShift && !alignment) {\n const xMin = max(overflow.left, 0);\n const xMax = max(overflow.right, 0);\n const yMin = max(overflow.top, 0);\n const yMax = max(overflow.bottom, 0);\n if (isYAxis) {\n availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right));\n } else {\n availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom));\n }\n }\n await apply({\n ...state,\n availableWidth,\n availableHeight\n });\n const nextDimensions = await platform.getDimensions(elements.floating);\n if (width !== nextDimensions.width || height !== nextDimensions.height) {\n return {\n reset: {\n rects: true\n }\n };\n }\n return {};\n }\n };\n};\n\nexport { arrow, autoPlacement, computePosition, detectOverflow, flip, hide, inline, limitShift, offset, shift, size };\n","function hasWindow() {\n return typeof window !== 'undefined';\n}\nfunction getNodeName(node) {\n if (isNode(node)) {\n return (node.nodeName || '').toLowerCase();\n }\n // Mocked nodes in testing environments may not be instances of Node. By\n // returning `#document` an infinite loop won't occur.\n // https://github.com/floating-ui/floating-ui/issues/2317\n return '#document';\n}\nfunction getWindow(node) {\n var _node$ownerDocument;\n return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;\n}\nfunction getDocumentElement(node) {\n var _ref;\n return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;\n}\nfunction isNode(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof Node || value instanceof getWindow(value).Node;\n}\nfunction isElement(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof Element || value instanceof getWindow(value).Element;\n}\nfunction isHTMLElement(value) {\n if (!hasWindow()) {\n return false;\n }\n return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;\n}\nfunction isShadowRoot(value) {\n if (!hasWindow() || typeof ShadowRoot === 'undefined') {\n return false;\n }\n return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;\n}\nfunction isOverflowElement(element) {\n const {\n overflow,\n overflowX,\n overflowY,\n display\n } = getComputedStyle(element);\n return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display);\n}\nfunction isTableElement(element) {\n return ['table', 'td', 'th'].includes(getNodeName(element));\n}\nfunction isTopLayer(element) {\n return [':popover-open', ':modal'].some(selector => {\n try {\n return element.matches(selector);\n } catch (e) {\n return false;\n }\n });\n}\nfunction isContainingBlock(elementOrCss) {\n const webkit = isWebKit();\n const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n return css.transform !== 'none' || css.perspective !== 'none' || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));\n}\nfunction getContainingBlock(element) {\n let currentNode = getParentNode(element);\n while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {\n if (isContainingBlock(currentNode)) {\n return currentNode;\n } else if (isTopLayer(currentNode)) {\n return null;\n }\n currentNode = getParentNode(currentNode);\n }\n return null;\n}\nfunction isWebKit() {\n if (typeof CSS === 'undefined' || !CSS.supports) return false;\n return CSS.supports('-webkit-backdrop-filter', 'none');\n}\nfunction isLastTraversableNode(node) {\n return ['html', 'body', '#document'].includes(getNodeName(node));\n}\nfunction getComputedStyle(element) {\n return getWindow(element).getComputedStyle(element);\n}\nfunction getNodeScroll(element) {\n if (isElement(element)) {\n return {\n scrollLeft: element.scrollLeft,\n scrollTop: element.scrollTop\n };\n }\n return {\n scrollLeft: element.scrollX,\n scrollTop: element.scrollY\n };\n}\nfunction getParentNode(node) {\n if (getNodeName(node) === 'html') {\n return node;\n }\n const result =\n // Step into the shadow DOM of the parent of a slotted node.\n node.assignedSlot ||\n // DOM Element detected.\n node.parentNode ||\n // ShadowRoot detected.\n isShadowRoot(node) && node.host ||\n // Fallback.\n getDocumentElement(node);\n return isShadowRoot(result) ? result.host : result;\n}\nfunction getNearestOverflowAncestor(node) {\n const parentNode = getParentNode(node);\n if (isLastTraversableNode(parentNode)) {\n return node.ownerDocument ? node.ownerDocument.body : node.body;\n }\n if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {\n return parentNode;\n }\n return getNearestOverflowAncestor(parentNode);\n}\nfunction getOverflowAncestors(node, list, traverseIframes) {\n var _node$ownerDocument2;\n if (list === void 0) {\n list = [];\n }\n if (traverseIframes === void 0) {\n traverseIframes = true;\n }\n const scrollableAncestor = getNearestOverflowAncestor(node);\n const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);\n const win = getWindow(scrollableAncestor);\n if (isBody) {\n const frameElement = getFrameElement(win);\n return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);\n }\n return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));\n}\nfunction getFrameElement(win) {\n return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;\n}\n\nexport { getComputedStyle, getContainingBlock, getDocumentElement, getFrameElement, getNearestOverflowAncestor, getNodeName, getNodeScroll, getOverflowAncestors, getParentNode, getWindow, isContainingBlock, isElement, isHTMLElement, isLastTraversableNode, isNode, isOverflowElement, isShadowRoot, isTableElement, isTopLayer, isWebKit };\n","import { rectToClientRect, detectOverflow as detectOverflow$1, offset as offset$1, autoPlacement as autoPlacement$1, shift as shift$1, flip as flip$1, size as size$1, hide as hide$1, arrow as arrow$1, inline as inline$1, limitShift as limitShift$1, computePosition as computePosition$1 } from '@floating-ui/core';\nimport { round, createCoords, max, min, floor } from '@floating-ui/utils';\nimport { getComputedStyle, isHTMLElement, isElement, getWindow, isWebKit, getFrameElement, getNodeScroll, getDocumentElement, isTopLayer, getNodeName, isOverflowElement, getOverflowAncestors, getParentNode, isLastTraversableNode, isContainingBlock, isTableElement, getContainingBlock } from '@floating-ui/utils/dom';\nexport { getOverflowAncestors } from '@floating-ui/utils/dom';\n\nfunction getCssDimensions(element) {\n const css = getComputedStyle(element);\n // In testing environments, the `width` and `height` properties are empty\n // strings for SVG elements, returning NaN. Fallback to `0` in this case.\n let width = parseFloat(css.width) || 0;\n let height = parseFloat(css.height) || 0;\n const hasOffset = isHTMLElement(element);\n const offsetWidth = hasOffset ? element.offsetWidth : width;\n const offsetHeight = hasOffset ? element.offsetHeight : height;\n const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;\n if (shouldFallback) {\n width = offsetWidth;\n height = offsetHeight;\n }\n return {\n width,\n height,\n $: shouldFallback\n };\n}\n\nfunction unwrapElement(element) {\n return !isElement(element) ? element.contextElement : element;\n}\n\nfunction getScale(element) {\n const domElement = unwrapElement(element);\n if (!isHTMLElement(domElement)) {\n return createCoords(1);\n }\n const rect = domElement.getBoundingClientRect();\n const {\n width,\n height,\n $\n } = getCssDimensions(domElement);\n let x = ($ ? round(rect.width) : rect.width) / width;\n let y = ($ ? round(rect.height) : rect.height) / height;\n\n // 0, NaN, or Infinity should always fallback to 1.\n\n if (!x || !Number.isFinite(x)) {\n x = 1;\n }\n if (!y || !Number.isFinite(y)) {\n y = 1;\n }\n return {\n x,\n y\n };\n}\n\nconst noOffsets = /*#__PURE__*/createCoords(0);\nfunction getVisualOffsets(element) {\n const win = getWindow(element);\n if (!isWebKit() || !win.visualViewport) {\n return noOffsets;\n }\n return {\n x: win.visualViewport.offsetLeft,\n y: win.visualViewport.offsetTop\n };\n}\nfunction shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {\n if (isFixed === void 0) {\n isFixed = false;\n }\n if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {\n return false;\n }\n return isFixed;\n}\n\nfunction getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {\n if (includeScale === void 0) {\n includeScale = false;\n }\n if (isFixedStrategy === void 0) {\n isFixedStrategy = false;\n }\n const clientRect = element.getBoundingClientRect();\n const domElement = unwrapElement(element);\n let scale = createCoords(1);\n if (includeScale) {\n if (offsetParent) {\n if (isElement(offsetParent)) {\n scale = getScale(offsetParent);\n }\n } else {\n scale = getScale(element);\n }\n }\n const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);\n let x = (clientRect.left + visualOffsets.x) / scale.x;\n let y = (clientRect.top + visualOffsets.y) / scale.y;\n let width = clientRect.width / scale.x;\n let height = clientRect.height / scale.y;\n if (domElement) {\n const win = getWindow(domElement);\n const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;\n let currentWin = win;\n let currentIFrame = getFrameElement(currentWin);\n while (currentIFrame && offsetParent && offsetWin !== currentWin) {\n const iframeScale = getScale(currentIFrame);\n const iframeRect = currentIFrame.getBoundingClientRect();\n const css = getComputedStyle(currentIFrame);\n const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;\n const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;\n x *= iframeScale.x;\n y *= iframeScale.y;\n width *= iframeScale.x;\n height *= iframeScale.y;\n x += left;\n y += top;\n currentWin = getWindow(currentIFrame);\n currentIFrame = getFrameElement(currentWin);\n }\n }\n return rectToClientRect({\n width,\n height,\n x,\n y\n });\n}\n\n// If has a CSS width greater than the viewport, then this will be\n// incorrect for RTL.\nfunction getWindowScrollBarX(element, rect) {\n const leftScroll = getNodeScroll(element).scrollLeft;\n if (!rect) {\n return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;\n }\n return rect.left + leftScroll;\n}\n\nfunction getHTMLOffset(documentElement, scroll, ignoreScrollbarX) {\n if (ignoreScrollbarX === void 0) {\n ignoreScrollbarX = false;\n }\n const htmlRect = documentElement.getBoundingClientRect();\n const x = htmlRect.left + scroll.scrollLeft - (ignoreScrollbarX ? 0 :\n // RTL scrollbar.\n getWindowScrollBarX(documentElement, htmlRect));\n const y = htmlRect.top + scroll.scrollTop;\n return {\n x,\n y\n };\n}\n\nfunction convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {\n let {\n elements,\n rect,\n offsetParent,\n strategy\n } = _ref;\n const isFixed = strategy === 'fixed';\n const documentElement = getDocumentElement(offsetParent);\n const topLayer = elements ? isTopLayer(elements.floating) : false;\n if (offsetParent === documentElement || topLayer && isFixed) {\n return rect;\n }\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n let scale = createCoords(1);\n const offsets = createCoords(0);\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isHTMLElement(offsetParent)) {\n const offsetRect = getBoundingClientRect(offsetParent);\n scale = getScale(offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n }\n }\n const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll, true) : createCoords(0);\n return {\n width: rect.width * scale.x,\n height: rect.height * scale.y,\n x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,\n y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y\n };\n}\n\nfunction getClientRects(element) {\n return Array.from(element.getClientRects());\n}\n\n// Gets the entire size of the scrollable document area, even extending outside\n// of the `` and `` rect bounds if horizontally scrollable.\nfunction getDocumentRect(element) {\n const html = getDocumentElement(element);\n const scroll = getNodeScroll(element);\n const body = element.ownerDocument.body;\n const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);\n const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);\n let x = -scroll.scrollLeft + getWindowScrollBarX(element);\n const y = -scroll.scrollTop;\n if (getComputedStyle(body).direction === 'rtl') {\n x += max(html.clientWidth, body.clientWidth) - width;\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\nfunction getViewportRect(element, strategy) {\n const win = getWindow(element);\n const html = getDocumentElement(element);\n const visualViewport = win.visualViewport;\n let width = html.clientWidth;\n let height = html.clientHeight;\n let x = 0;\n let y = 0;\n if (visualViewport) {\n width = visualViewport.width;\n height = visualViewport.height;\n const visualViewportBased = isWebKit();\n if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {\n x = visualViewport.offsetLeft;\n y = visualViewport.offsetTop;\n }\n }\n return {\n width,\n height,\n x,\n y\n };\n}\n\n// Returns the inner client rect, subtracting scrollbars if present.\nfunction getInnerBoundingClientRect(element, strategy) {\n const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');\n const top = clientRect.top + element.clientTop;\n const left = clientRect.left + element.clientLeft;\n const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);\n const width = element.clientWidth * scale.x;\n const height = element.clientHeight * scale.y;\n const x = left * scale.x;\n const y = top * scale.y;\n return {\n width,\n height,\n x,\n y\n };\n}\nfunction getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {\n let rect;\n if (clippingAncestor === 'viewport') {\n rect = getViewportRect(element, strategy);\n } else if (clippingAncestor === 'document') {\n rect = getDocumentRect(getDocumentElement(element));\n } else if (isElement(clippingAncestor)) {\n rect = getInnerBoundingClientRect(clippingAncestor, strategy);\n } else {\n const visualOffsets = getVisualOffsets(element);\n rect = {\n x: clippingAncestor.x - visualOffsets.x,\n y: clippingAncestor.y - visualOffsets.y,\n width: clippingAncestor.width,\n height: clippingAncestor.height\n };\n }\n return rectToClientRect(rect);\n}\nfunction hasFixedPositionAncestor(element, stopNode) {\n const parentNode = getParentNode(element);\n if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {\n return false;\n }\n return getComputedStyle(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);\n}\n\n// A \"clipping ancestor\" is an `overflow` element with the characteristic of\n// clipping (or hiding) child elements. This returns all clipping ancestors\n// of the given element up the tree.\nfunction getClippingElementAncestors(element, cache) {\n const cachedResult = cache.get(element);\n if (cachedResult) {\n return cachedResult;\n }\n let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');\n let currentContainingBlockComputedStyle = null;\n const elementIsFixed = getComputedStyle(element).position === 'fixed';\n let currentNode = elementIsFixed ? getParentNode(element) : element;\n\n // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block\n while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {\n const computedStyle = getComputedStyle(currentNode);\n const currentNodeIsContaining = isContainingBlock(currentNode);\n if (!currentNodeIsContaining && computedStyle.position === 'fixed') {\n currentContainingBlockComputedStyle = null;\n }\n const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);\n if (shouldDropCurrentNode) {\n // Drop non-containing blocks.\n result = result.filter(ancestor => ancestor !== currentNode);\n } else {\n // Record last containing block for next iteration.\n currentContainingBlockComputedStyle = computedStyle;\n }\n currentNode = getParentNode(currentNode);\n }\n cache.set(element, result);\n return result;\n}\n\n// Gets the maximum area that the element is visible in due to any number of\n// clipping ancestors.\nfunction getClippingRect(_ref) {\n let {\n element,\n boundary,\n rootBoundary,\n strategy\n } = _ref;\n const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);\n const clippingAncestors = [...elementClippingAncestors, rootBoundary];\n const firstClippingAncestor = clippingAncestors[0];\n const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {\n const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);\n accRect.top = max(rect.top, accRect.top);\n accRect.right = min(rect.right, accRect.right);\n accRect.bottom = min(rect.bottom, accRect.bottom);\n accRect.left = max(rect.left, accRect.left);\n return accRect;\n }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));\n return {\n width: clippingRect.right - clippingRect.left,\n height: clippingRect.bottom - clippingRect.top,\n x: clippingRect.left,\n y: clippingRect.top\n };\n}\n\nfunction getDimensions(element) {\n const {\n width,\n height\n } = getCssDimensions(element);\n return {\n width,\n height\n };\n}\n\nfunction getRectRelativeToOffsetParent(element, offsetParent, strategy) {\n const isOffsetParentAnElement = isHTMLElement(offsetParent);\n const documentElement = getDocumentElement(offsetParent);\n const isFixed = strategy === 'fixed';\n const rect = getBoundingClientRect(element, true, isFixed, offsetParent);\n let scroll = {\n scrollLeft: 0,\n scrollTop: 0\n };\n const offsets = createCoords(0);\n if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {\n if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {\n scroll = getNodeScroll(offsetParent);\n }\n if (isOffsetParentAnElement) {\n const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);\n offsets.x = offsetRect.x + offsetParent.clientLeft;\n offsets.y = offsetRect.y + offsetParent.clientTop;\n } else if (documentElement) {\n // If the scrollbar appears on the left (e.g. RTL systems). Use\n // Firefox with layout.scrollbar.side = 3 in about:config to test this.\n offsets.x = getWindowScrollBarX(documentElement);\n }\n }\n const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);\n const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;\n const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;\n return {\n x,\n y,\n width: rect.width,\n height: rect.height\n };\n}\n\nfunction isStaticPositioned(element) {\n return getComputedStyle(element).position === 'static';\n}\n\nfunction getTrueOffsetParent(element, polyfill) {\n if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') {\n return null;\n }\n if (polyfill) {\n return polyfill(element);\n }\n let rawOffsetParent = element.offsetParent;\n\n // Firefox returns the element as the offsetParent if it's non-static,\n // while Chrome and Safari return the element. The element must\n // be used to perform the correct calculations even if the element is\n // non-static.\n if (getDocumentElement(element) === rawOffsetParent) {\n rawOffsetParent = rawOffsetParent.ownerDocument.body;\n }\n return rawOffsetParent;\n}\n\n// Gets the closest ancestor positioned element. Handles some edge cases,\n// such as table ancestors and cross browser bugs.\nfunction getOffsetParent(element, polyfill) {\n const win = getWindow(element);\n if (isTopLayer(element)) {\n return win;\n }\n if (!isHTMLElement(element)) {\n let svgOffsetParent = getParentNode(element);\n while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {\n if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {\n return svgOffsetParent;\n }\n svgOffsetParent = getParentNode(svgOffsetParent);\n }\n return win;\n }\n let offsetParent = getTrueOffsetParent(element, polyfill);\n while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {\n offsetParent = getTrueOffsetParent(offsetParent, polyfill);\n }\n if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {\n return win;\n }\n return offsetParent || getContainingBlock(element) || win;\n}\n\nconst getElementRects = async function (data) {\n const getOffsetParentFn = this.getOffsetParent || getOffsetParent;\n const getDimensionsFn = this.getDimensions;\n const floatingDimensions = await getDimensionsFn(data.floating);\n return {\n reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),\n floating: {\n x: 0,\n y: 0,\n width: floatingDimensions.width,\n height: floatingDimensions.height\n }\n };\n};\n\nfunction isRTL(element) {\n return getComputedStyle(element).direction === 'rtl';\n}\n\nconst platform = {\n convertOffsetParentRelativeRectToViewportRelativeRect,\n getDocumentElement,\n getClippingRect,\n getOffsetParent,\n getElementRects,\n getClientRects,\n getDimensions,\n getScale,\n isElement,\n isRTL\n};\n\n// https://samthor.au/2021/observing-dom/\nfunction observeMove(element, onMove) {\n let io = null;\n let timeoutId;\n const root = getDocumentElement(element);\n function cleanup() {\n var _io;\n clearTimeout(timeoutId);\n (_io = io) == null || _io.disconnect();\n io = null;\n }\n function refresh(skip, threshold) {\n if (skip === void 0) {\n skip = false;\n }\n if (threshold === void 0) {\n threshold = 1;\n }\n cleanup();\n const {\n left,\n top,\n width,\n height\n } = element.getBoundingClientRect();\n if (!skip) {\n onMove();\n }\n if (!width || !height) {\n return;\n }\n const insetTop = floor(top);\n const insetRight = floor(root.clientWidth - (left + width));\n const insetBottom = floor(root.clientHeight - (top + height));\n const insetLeft = floor(left);\n const rootMargin = -insetTop + \"px \" + -insetRight + \"px \" + -insetBottom + \"px \" + -insetLeft + \"px\";\n const options = {\n rootMargin,\n threshold: max(0, min(1, threshold)) || 1\n };\n let isFirstUpdate = true;\n function handleObserve(entries) {\n const ratio = entries[0].intersectionRatio;\n if (ratio !== threshold) {\n if (!isFirstUpdate) {\n return refresh();\n }\n if (!ratio) {\n // If the reference is clipped, the ratio is 0. Throttle the refresh\n // to prevent an infinite loop of updates.\n timeoutId = setTimeout(() => {\n refresh(false, 1e-7);\n }, 1000);\n } else {\n refresh(false, ratio);\n }\n }\n isFirstUpdate = false;\n }\n\n // Older browsers don't support a `document` as the root and will throw an\n // error.\n try {\n io = new IntersectionObserver(handleObserve, {\n ...options,\n // Handle