UNPKG

coupdoeil

Version:

Javascript for Ruby on Rails Coupdoeil gem

1,476 lines (1,354 loc) 77.2 kB
class PopoverController { constructor(coupdoeilElement) { this.coupdoeilElement = coupdoeilElement; 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 POPOVER_CLASS_NAME = "coupdoeil--popover"; const POPOVER_SELECTOR = `.${POPOVER_CLASS_NAME}`; const POPOVER_CLOSE_BTN_SELECTOR = "[data-popover-close]"; const CLOSING_DELAY_MS = 75; const FETCH_DELAY_MS = 100; const OPENING_DELAY_MS = 200; const OPTIONS = { animation: { getter: getAnimation }, cache: { getter: getCache }, loading: { getter: getLoading }, offset: { getter: getOffset }, openingDelay: { getter: getOpeningDelay }, placement: { getter: getPlacement }, trigger: { getter: getTrigger$1 } }; const ORDERED_OPTIONS = [ "trigger", "loading", "cache", "openingDelay", "animation", "placement", "offset" ]; const TRIGGERS = [ "hover", "click" ]; const ANIMATIONS = [ false, "slide-in", "fade-in", "slide-out", "custom" ]; const PLACEMENTS = [ "auto", "top", "top-start", "top-end", "right", "right-start", "right-end", "bottom", "bottom-start", "bottom-end", "left", "left-start", "left-end" ]; const LOADINGS = [ "async", "preload", "lazy" ]; function parseCSSSize(value) { if (typeof value === "number") { return value; } else if (/^(-?\d+\.?\d+)px$/.test(value)) { return parseFloat(value); } else if (/^(-?\d*\.?\d+)rem$/.test(value)) { return parseFloat(value) * parseFloat(getComputedStyle(document.documentElement).fontSize); } return 0; } function getOffset(optionsInt) { const offsetBits = Number(BigInt(optionsInt) >> BigInt(24)); if (offsetBits === 0) return 0; const isNegative = (offsetBits & 1) === 1; const isREM = (offsetBits & 2) === 2; const decimals = offsetBits >> 2 & 1023; const integer = offsetBits >> 12; const CSSSize = `${isNegative ? "-" : ""}${integer}.${decimals}${isREM ? "rem" : "px"}`; return parseCSSSize(CSSSize); } function getPlacement(optionsInt) { const placementBits = optionsInt >> 8 & 65535; let shift = 0; let lastPlacement = null; const placements = []; while (lastPlacement !== "auto" && shift < 16) { lastPlacement = PLACEMENTS[placementBits >> shift & 15]; placements.push(lastPlacement); shift += 4; } return placements; } function getAnimation(optionsInt) { return ANIMATIONS[optionsInt >> 5 & 7]; } function getOpeningDelay(optionsInt) { return (optionsInt >> 4 & 1) === 1; } function getCache(optionsInt) { return (optionsInt & 8) === 8; } function getLoading(optionsInt) { return LOADINGS[optionsInt >> 1 & 3]; } function getTrigger$1(optionsInt) { return TRIGGERS[optionsInt & 1]; } const popoverOptions = { animation: undefined, cache: undefined, loading: undefined, offset: undefined, openingDelay: undefined, placement: undefined, trigger: undefined }; function extractOptionsFromElement(coupdoeilElement) { const optionsInt = coupdoeilElement.popoverController.optionsInt ||= parseOtionsInt(coupdoeilElement); const options = Object.create(popoverOptions); for (const option of ORDERED_OPTIONS) { options[option] = OPTIONS[option].getter(optionsInt); } return options; } function parseOtionsInt(coupdoeilElement) { const optionsString = coupdoeilElement.getAttribute("popover-options"); return parseInt(optionsString, 36); } function extractOptionFromElement(coupdoeilElement, optionName) { const optionsInt = coupdoeilElement.popoverController.optionsInt ||= parseOtionsInt(coupdoeilElement); return OPTIONS[optionName].getter(optionsInt); } function getType(controller) { return controller.coupdoeilElement.getAttribute("popover-type"); } function getParams(controller) { return controller.coupdoeilElement.getAttribute("popover-params"); } function getTrigger(controller) { return extractOptionFromElement(controller.coupdoeilElement, "trigger"); } function triggeredOnClick(controller) { return getTrigger(controller) === "click"; } function noTriggeredOnClick(controller) { return getTrigger(controller) !== "click"; } function triggeredOnHover(controller) { return getTrigger(controller) === "hover"; } function notTriggeredOnHover(controller) { return getTrigger(controller) !== "hover"; } function preloadedContentElement(controller) { return controller.coupdoeilElement.querySelector(".popover-content"); } const popoverContentHTMLMap = new Map; function cacheMapKey(controller) { if (preloadedContentElement(controller)) { return controller.coupdoeilElement.uniqueId; } return getType(controller) + getParams(controller); } function getPopoverContentHTML(controller) { return popoverContentHTMLMap.get(cacheMapKey(controller)); } function setPopoverContentHTML(controller, value) { popoverContentHTMLMap.set(cacheMapKey(controller), value); } function clearPopoverContentCache() { popoverContentHTMLMap.clear(); } const sides = [ "top", "right", "bottom", "left" ]; const alignments = [ "start", "end" ]; const placements = sides.reduce(((acc, side) => acc.concat(side, side + "-" + alignments[0], side + "-" + alignments[1])), []); const min = Math.min; const max = Math.max; const round = Math.round; const createCoords = v => ({ x: v, y: v }); const oppositeSideMap = { left: "right", right: "left", bottom: "top", top: "bottom" }; const oppositeAlignmentMap = { start: "end", end: "start" }; function clamp(start, value, end) { return max(start, min(value, end)); } function evaluate(value, param) { return typeof value === "function" ? value(param) : value; } function getSide(placement) { return placement.split("-")[0]; } function getAlignment(placement) { return placement.split("-")[1]; } function getOppositeAxis(axis) { return axis === "x" ? "y" : "x"; } function getAxisLength(axis) { return axis === "y" ? "height" : "width"; } function getSideAxis(placement) { return [ "top", "bottom" ].includes(getSide(placement)) ? "y" : "x"; } function getAlignmentAxis(placement) { return getOppositeAxis(getSideAxis(placement)); } function getAlignmentSides(placement, rects, rtl) { if (rtl === void 0) { rtl = false; } const alignment = getAlignment(placement); const alignmentAxis = getAlignmentAxis(placement); const length = getAxisLength(alignmentAxis); let mainAlignmentSide = alignmentAxis === "x" ? alignment === (rtl ? "end" : "start") ? "right" : "left" : alignment === "start" ? "bottom" : "top"; if (rects.reference[length] > rects.floating[length]) { mainAlignmentSide = getOppositePlacement(mainAlignmentSide); } return [ mainAlignmentSide, getOppositePlacement(mainAlignmentSide) ]; } function getExpandedPlacements(placement) { const oppositePlacement = getOppositePlacement(placement); return [ getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement) ]; } function getOppositeAlignmentPlacement(placement) { return placement.replace(/start|end/g, (alignment => oppositeAlignmentMap[alignment])); } function getSideList(side, isStart, rtl) { const lr = [ "left", "right" ]; const rl = [ "right", "left" ]; const tb = [ "top", "bottom" ]; const bt = [ "bottom", "top" ]; switch (side) { case "top": case "bottom": if (rtl) return isStart ? rl : lr; return isStart ? lr : rl; case "left": case "right": return isStart ? tb : bt; default: return []; } } function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) { const alignment = getAlignment(placement); let list = getSideList(getSide(placement), direction === "start", rtl); if (alignment) { list = list.map((side => side + "-" + alignment)); if (flipAlignment) { list = list.concat(list.map(getOppositeAlignmentPlacement)); } } return list; } function getOppositePlacement(placement) { return placement.replace(/left|right|bottom|top/g, (side => oppositeSideMap[side])); } function expandPaddingObject(padding) { return { top: 0, right: 0, bottom: 0, left: 0, ...padding }; } function getPaddingObject(padding) { return typeof padding !== "number" ? expandPaddingObject(padding) : { top: padding, right: padding, bottom: padding, left: padding }; } function rectToClientRect(rect) { const {x: x, y: y, width: width, height: height} = rect; return { width: width, height: height, top: y, left: x, right: x + width, bottom: y + height, x: x, y: y }; } function computeCoordsFromPlacement(_ref, placement, rtl) { let {reference: reference, floating: floating} = _ref; const sideAxis = getSideAxis(placement); const alignmentAxis = getAlignmentAxis(placement); const alignLength = getAxisLength(alignmentAxis); const side = getSide(placement); const isVertical = sideAxis === "y"; const commonX = reference.x + reference.width / 2 - floating.width / 2; const commonY = reference.y + reference.height / 2 - floating.height / 2; const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2; let coords; switch (side) { case "top": coords = { x: commonX, y: reference.y - floating.height }; break; case "bottom": coords = { x: commonX, y: reference.y + reference.height }; break; case "right": coords = { x: reference.x + reference.width, y: commonY }; break; case "left": coords = { x: reference.x - floating.width, y: commonY }; break; default: coords = { x: reference.x, y: reference.y }; } switch (getAlignment(placement)) { case "start": coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1); break; case "end": coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1); break; } return coords; } const computePosition$1 = async (reference, floating, config) => { const {placement: placement = "bottom", strategy: strategy = "absolute", middleware: middleware = [], platform: platform} = config; const validMiddleware = middleware.filter(Boolean); const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating)); let rects = await platform.getElementRects({ reference: reference, floating: floating, strategy: strategy }); let {x: x, y: y} = computeCoordsFromPlacement(rects, placement, rtl); let statefulPlacement = placement; let middlewareData = {}; let resetCount = 0; for (let i = 0; i < validMiddleware.length; i++) { const {name: name, fn: fn} = validMiddleware[i]; const {x: nextX, y: nextY, data: data, reset: reset} = await fn({ x: x, y: y, initialPlacement: placement, placement: statefulPlacement, strategy: strategy, middlewareData: middlewareData, rects: rects, platform: platform, elements: { reference: reference, floating: floating } }); x = nextX != null ? nextX : x; y = nextY != null ? nextY : y; middlewareData = { ...middlewareData, [name]: { ...middlewareData[name], ...data } }; if (reset && resetCount <= 50) { resetCount++; if (typeof reset === "object") { if (reset.placement) { statefulPlacement = reset.placement; } if (reset.rects) { rects = reset.rects === true ? await platform.getElementRects({ reference: reference, floating: floating, strategy: strategy }) : reset.rects; } ({x: x, y: y} = computeCoordsFromPlacement(rects, statefulPlacement, rtl)); } i = -1; } } return { x: x, y: y, placement: statefulPlacement, strategy: strategy, middlewareData: middlewareData }; }; async function detectOverflow$1(state, options) { var _await$platform$isEle; if (options === void 0) { options = {}; } const {x: x, y: y, platform: platform, rects: rects, elements: elements, strategy: strategy} = state; const {boundary: boundary = "clippingAncestors", rootBoundary: rootBoundary = "viewport", elementContext: elementContext = "floating", altBoundary: altBoundary = false, padding: padding = 0} = evaluate(options, state); const paddingObject = getPaddingObject(padding); const altContext = elementContext === "floating" ? "reference" : "floating"; const element = elements[altBoundary ? altContext : elementContext]; const clippingClientRect = rectToClientRect(await platform.getClippingRect({ 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)), boundary: boundary, rootBoundary: rootBoundary, strategy: strategy })); const rect = elementContext === "floating" ? { x: x, y: y, width: rects.floating.width, height: rects.floating.height } : rects.reference; const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating)); const offsetScale = await (platform.isElement == null ? void 0 : platform.isElement(offsetParent)) ? await (platform.getScale == null ? void 0 : platform.getScale(offsetParent)) || { x: 1, y: 1 } : { x: 1, y: 1 }; const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({ elements: elements, rect: rect, offsetParent: offsetParent, strategy: strategy }) : rect); return { top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y, bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y, left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x, right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x }; } const arrow$1 = options => ({ name: "arrow", options: options, async fn(state) { const {x: x, y: y, placement: placement, rects: rects, platform: platform, elements: elements, middlewareData: middlewareData} = state; const {element: element, padding: padding = 0} = evaluate(options, state) || {}; if (element == null) { return {}; } const paddingObject = getPaddingObject(padding); const coords = { x: x, y: y }; const axis = getAlignmentAxis(placement); const length = getAxisLength(axis); const arrowDimensions = await platform.getDimensions(element); const isYAxis = axis === "y"; const minProp = isYAxis ? "top" : "left"; const maxProp = isYAxis ? "bottom" : "right"; const clientProp = isYAxis ? "clientHeight" : "clientWidth"; const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length]; const startDiff = coords[axis] - rects.reference[axis]; const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element)); let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0; if (!clientSize || !await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent))) { clientSize = elements.floating[clientProp] || rects.floating[length]; } const centerToReference = endDiff / 2 - startDiff / 2; const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1; const minPadding = min(paddingObject[minProp], largestPossiblePadding); const maxPadding = min(paddingObject[maxProp], largestPossiblePadding); const min$1 = minPadding; const max = clientSize - arrowDimensions[length] - maxPadding; const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference; const offset = clamp(min$1, center, max); const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0; const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0; return { [axis]: coords[axis] + alignmentOffset, data: { [axis]: offset, centerOffset: center - offset - alignmentOffset, ...shouldAddOffset && { alignmentOffset: alignmentOffset } }, reset: shouldAddOffset }; } }); function getPlacementList(alignment, autoAlignment, allowedPlacements) { const allowedPlacementsSortedByAlignment = alignment ? [ ...allowedPlacements.filter((placement => getAlignment(placement) === alignment)), ...allowedPlacements.filter((placement => getAlignment(placement) !== alignment)) ] : allowedPlacements.filter((placement => getSide(placement) === placement)); return allowedPlacementsSortedByAlignment.filter((placement => { if (alignment) { return getAlignment(placement) === alignment || (autoAlignment ? getOppositeAlignmentPlacement(placement) !== placement : false); } return true; })); } const autoPlacement$1 = function(options) { if (options === void 0) { options = {}; } return { name: "autoPlacement", options: options, async fn(state) { var _middlewareData$autoP, _middlewareData$autoP2, _placementsThatFitOnE; const {rects: rects, middlewareData: middlewareData, placement: placement, platform: platform, elements: elements} = state; const {crossAxis: crossAxis = false, alignment: alignment, allowedPlacements: allowedPlacements = placements, autoAlignment: autoAlignment = true, ...detectOverflowOptions} = evaluate(options, state); const placements$1 = alignment !== undefined || allowedPlacements === placements ? getPlacementList(alignment || null, autoAlignment, allowedPlacements) : allowedPlacements; const overflow = await detectOverflow$1(state, detectOverflowOptions); const currentIndex = ((_middlewareData$autoP = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP.index) || 0; const currentPlacement = placements$1[currentIndex]; if (currentPlacement == null) { return {}; } const alignmentSides = getAlignmentSides(currentPlacement, rects, await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))); if (placement !== currentPlacement) { return { reset: { placement: placements$1[0] } }; } const currentOverflows = [ overflow[getSide(currentPlacement)], overflow[alignmentSides[0]], overflow[alignmentSides[1]] ]; const allOverflows = [ ...((_middlewareData$autoP2 = middlewareData.autoPlacement) == null ? void 0 : _middlewareData$autoP2.overflows) || [], { placement: currentPlacement, overflows: currentOverflows } ]; const nextPlacement = placements$1[currentIndex + 1]; if (nextPlacement) { return { data: { index: currentIndex + 1, overflows: allOverflows }, reset: { placement: nextPlacement } }; } const placementsSortedByMostSpace = allOverflows.map((d => { const alignment = getAlignment(d.placement); return [ d.placement, alignment && crossAxis ? d.overflows.slice(0, 2).reduce(((acc, v) => acc + v), 0) : d.overflows[0], d.overflows ]; })).sort(((a, b) => a[1] - b[1])); const placementsThatFitOnEachSide = placementsSortedByMostSpace.filter((d => d[2].slice(0, getAlignment(d[0]) ? 2 : 3).every((v => v <= 0)))); const resetPlacement = ((_placementsThatFitOnE = placementsThatFitOnEachSide[0]) == null ? void 0 : _placementsThatFitOnE[0]) || placementsSortedByMostSpace[0][0]; if (resetPlacement !== placement) { return { data: { index: currentIndex + 1, overflows: allOverflows }, reset: { placement: resetPlacement } }; } return {}; } }; }; const flip = function(options) { if (options === void 0) { options = {}; } return { name: "flip", options: options, async fn(state) { var _middlewareData$arrow, _middlewareData$flip; const {placement: placement, middlewareData: middlewareData, rects: rects, initialPlacement: initialPlacement, platform: platform, elements: elements} = state; const {mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = true, fallbackPlacements: specifiedFallbackPlacements, fallbackStrategy: fallbackStrategy = "bestFit", fallbackAxisSideDirection: fallbackAxisSideDirection = "none", flipAlignment: flipAlignment = true, ...detectOverflowOptions} = evaluate(options, state); if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) { return {}; } const side = getSide(placement); const initialSideAxis = getSideAxis(initialPlacement); const isBasePlacement = getSide(initialPlacement) === initialPlacement; const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [ getOppositePlacement(initialPlacement) ] : getExpandedPlacements(initialPlacement)); const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== "none"; if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) { fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl)); } const placements = [ initialPlacement, ...fallbackPlacements ]; const overflow = await detectOverflow$1(state, detectOverflowOptions); const overflows = []; let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || []; if (checkMainAxis) { overflows.push(overflow[side]); } if (checkCrossAxis) { const sides = getAlignmentSides(placement, rects, rtl); overflows.push(overflow[sides[0]], overflow[sides[1]]); } overflowsData = [ ...overflowsData, { placement: placement, overflows: overflows } ]; if (!overflows.every((side => side <= 0))) { var _middlewareData$flip2, _overflowsData$filter; const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1; const nextPlacement = placements[nextIndex]; if (nextPlacement) { return { data: { index: nextIndex, overflows: overflowsData }, reset: { placement: nextPlacement } }; } 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; if (!resetPlacement) { switch (fallbackStrategy) { case "bestFit": { var _overflowsData$filter2; const placement = (_overflowsData$filter2 = overflowsData.filter((d => { if (hasFallbackAxisSideDirection) { const currentSideAxis = getSideAxis(d.placement); return currentSideAxis === initialSideAxis || currentSideAxis === "y"; } return true; })).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]; if (placement) { resetPlacement = placement; } break; } case "initialPlacement": resetPlacement = initialPlacement; break; } } if (placement !== resetPlacement) { return { reset: { placement: resetPlacement } }; } } return {}; } }; }; function getSideOffsets(overflow, rect) { return { top: overflow.top - rect.height, right: overflow.right - rect.width, bottom: overflow.bottom - rect.height, left: overflow.left - rect.width }; } function isAnySideFullyClipped(overflow) { return sides.some((side => overflow[side] >= 0)); } const hide = function(options) { if (options === void 0) { options = {}; } return { name: "hide", options: options, async fn(state) { const {rects: rects} = state; const {strategy: strategy = "referenceHidden", ...detectOverflowOptions} = evaluate(options, state); switch (strategy) { case "referenceHidden": { const overflow = await detectOverflow$1(state, { ...detectOverflowOptions, elementContext: "reference" }); const offsets = getSideOffsets(overflow, rects.reference); return { data: { referenceHiddenOffsets: offsets, referenceHidden: isAnySideFullyClipped(offsets) } }; } case "escaped": { const overflow = await detectOverflow$1(state, { ...detectOverflowOptions, altBoundary: true }); const offsets = getSideOffsets(overflow, rects.floating); return { data: { escapedOffsets: offsets, escaped: isAnySideFullyClipped(offsets) } }; } default: { return {}; } } } }; }; function getBoundingRect(rects) { const minX = min(...rects.map((rect => rect.left))); const minY = min(...rects.map((rect => rect.top))); const maxX = max(...rects.map((rect => rect.right))); const maxY = max(...rects.map((rect => rect.bottom))); return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }; } function getRectsByLine(rects) { const sortedRects = rects.slice().sort(((a, b) => a.y - b.y)); const groups = []; let prevRect = null; for (let i = 0; i < sortedRects.length; i++) { const rect = sortedRects[i]; if (!prevRect || rect.y - prevRect.y > prevRect.height / 2) { groups.push([ rect ]); } else { groups[groups.length - 1].push(rect); } prevRect = rect; } return groups.map((rect => rectToClientRect(getBoundingRect(rect)))); } const inline = function(options) { if (options === void 0) { options = {}; } return { name: "inline", options: options, async fn(state) { const {placement: placement, elements: elements, rects: rects, platform: platform, strategy: strategy} = state; const {padding: padding = 2, x: x, y: y} = evaluate(options, state); const nativeClientRects = Array.from(await (platform.getClientRects == null ? void 0 : platform.getClientRects(elements.reference)) || []); const clientRects = getRectsByLine(nativeClientRects); const fallback = rectToClientRect(getBoundingRect(nativeClientRects)); const paddingObject = getPaddingObject(padding); function getBoundingClientRect() { if (clientRects.length === 2 && clientRects[0].left > clientRects[1].right && x != null && y != null) { 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; } if (clientRects.length >= 2) { if (getSideAxis(placement) === "y") { const firstRect = clientRects[0]; const lastRect = clientRects[clientRects.length - 1]; const isTop = getSide(placement) === "top"; const top = firstRect.top; const bottom = lastRect.bottom; const left = isTop ? firstRect.left : lastRect.left; const right = isTop ? firstRect.right : lastRect.right; const width = right - left; const height = bottom - top; return { top: top, bottom: bottom, left: left, right: right, width: width, height: height, x: left, y: top }; } const isLeftSide = getSide(placement) === "left"; const maxRight = max(...clientRects.map((rect => rect.right))); const minLeft = min(...clientRects.map((rect => rect.left))); const measureRects = clientRects.filter((rect => isLeftSide ? rect.left === minLeft : rect.right === maxRight)); const top = measureRects[0].top; const bottom = measureRects[measureRects.length - 1].bottom; const left = minLeft; const right = maxRight; const width = right - left; const height = bottom - top; return { top: top, bottom: bottom, left: left, right: right, width: width, height: height, x: left, y: top }; } return fallback; } const resetRects = await platform.getElementRects({ reference: { getBoundingClientRect: getBoundingClientRect }, floating: elements.floating, strategy: strategy }); 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) { return { reset: { rects: resetRects } }; } return {}; } }; }; async function convertValueToCoords(state, options) { const {placement: placement, platform: platform, elements: elements} = state; const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); const side = getSide(placement); const alignment = getAlignment(placement); const isVertical = getSideAxis(placement) === "y"; const mainAxisMulti = [ "left", "top" ].includes(side) ? -1 : 1; const crossAxisMulti = rtl && isVertical ? -1 : 1; const rawValue = evaluate(options, state); let {mainAxis: mainAxis, crossAxis: crossAxis, alignmentAxis: alignmentAxis} = typeof rawValue === "number" ? { mainAxis: rawValue, crossAxis: 0, alignmentAxis: null } : { mainAxis: rawValue.mainAxis || 0, crossAxis: rawValue.crossAxis || 0, alignmentAxis: rawValue.alignmentAxis }; if (alignment && typeof alignmentAxis === "number") { crossAxis = alignment === "end" ? alignmentAxis * -1 : alignmentAxis; } return isVertical ? { x: crossAxis * crossAxisMulti, y: mainAxis * mainAxisMulti } : { x: mainAxis * mainAxisMulti, y: crossAxis * crossAxisMulti }; } const offset$1 = function(options) { if (options === void 0) { options = 0; } return { name: "offset", options: options, async fn(state) { var _middlewareData$offse, _middlewareData$arrow; const {x: x, y: y, placement: placement, middlewareData: middlewareData} = state; const diffCoords = await convertValueToCoords(state, options); if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) { return {}; } return { x: x + diffCoords.x, y: y + diffCoords.y, data: { ...diffCoords, placement: placement } }; } }; }; const shift = function(options) { if (options === void 0) { options = {}; } return { name: "shift", options: options, async fn(state) { const {x: x, y: y, placement: placement} = state; const {mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = false, limiter: limiter = { fn: _ref => { let {x: x, y: y} = _ref; return { x: x, y: y }; } }, ...detectOverflowOptions} = evaluate(options, state); const coords = { x: x, y: y }; const overflow = await detectOverflow$1(state, detectOverflowOptions); const crossAxis = getSideAxis(getSide(placement)); const mainAxis = getOppositeAxis(crossAxis); let mainAxisCoord = coords[mainAxis]; let crossAxisCoord = coords[crossAxis]; if (checkMainAxis) { const minSide = mainAxis === "y" ? "top" : "left"; const maxSide = mainAxis === "y" ? "bottom" : "right"; const min = mainAxisCoord + overflow[minSide]; const max = mainAxisCoord - overflow[maxSide]; mainAxisCoord = clamp(min, mainAxisCoord, max); } if (checkCrossAxis) { const minSide = crossAxis === "y" ? "top" : "left"; const maxSide = crossAxis === "y" ? "bottom" : "right"; const min = crossAxisCoord + overflow[minSide]; const max = crossAxisCoord - overflow[maxSide]; crossAxisCoord = clamp(min, crossAxisCoord, max); } const limitedCoords = limiter.fn({ ...state, [mainAxis]: mainAxisCoord, [crossAxis]: crossAxisCoord }); return { ...limitedCoords, data: { x: limitedCoords.x - x, y: limitedCoords.y - y, enabled: { [mainAxis]: checkMainAxis, [crossAxis]: checkCrossAxis } } }; } }; }; const limitShift = function(options) { if (options === void 0) { options = {}; } return { options: options, fn(state) { const {x: x, y: y, placement: placement, rects: rects, middlewareData: middlewareData} = state; const {offset: offset = 0, mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = true} = evaluate(options, state); const coords = { x: x, y: y }; const crossAxis = getSideAxis(placement); const mainAxis = getOppositeAxis(crossAxis); let mainAxisCoord = coords[mainAxis]; let crossAxisCoord = coords[crossAxis]; const rawOffset = evaluate(offset, state); const computedOffset = typeof rawOffset === "number" ? { mainAxis: rawOffset, crossAxis: 0 } : { mainAxis: 0, crossAxis: 0, ...rawOffset }; if (checkMainAxis) { const len = mainAxis === "y" ? "height" : "width"; const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis; const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis; if (mainAxisCoord < limitMin) { mainAxisCoord = limitMin; } else if (mainAxisCoord > limitMax) { mainAxisCoord = limitMax; } } if (checkCrossAxis) { var _middlewareData$offse, _middlewareData$offse2; const len = mainAxis === "y" ? "width" : "height"; const isOriginSide = [ "top", "left" ].includes(getSide(placement)); 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); 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); if (crossAxisCoord < limitMin) { crossAxisCoord = limitMin; } else if (crossAxisCoord > limitMax) { crossAxisCoord = limitMax; } } return { [mainAxis]: mainAxisCoord, [crossAxis]: crossAxisCoord }; } }; }; const size = function(options) { if (options === void 0) { options = {}; } return { name: "size", options: options, async fn(state) { var _state$middlewareData, _state$middlewareData2; const {placement: placement, rects: rects, platform: platform, elements: elements} = state; const {apply: apply = () => {}, ...detectOverflowOptions} = evaluate(options, state); const overflow = await detectOverflow$1(state, detectOverflowOptions); const side = getSide(placement); const alignment = getAlignment(placement); const isYAxis = getSideAxis(placement) === "y"; const {width: width, height: height} = rects.floating; let heightSide; let widthSide; if (side === "top" || side === "bottom") { heightSide = side; widthSide = alignment === (await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)) ? "start" : "end") ? "left" : "right"; } else { widthSide = side; heightSide = alignment === "end" ? "top" : "bottom"; } const maximumClippingHeight = height - overflow.top - overflow.bottom; const maximumClippingWidth = width - overflow.left - overflow.right; const overflowAvailableHeight = min(height - overflow[heightSide], maximumClippingHeight); const overflowAvailableWidth = min(width - overflow[widthSide], maximumClippingWidth); const noShift = !state.middlewareData.shift; let availableHeight = overflowAvailableHeight; let availableWidth = overflowAvailableWidth; if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) { availableWidth = maximumClippingWidth; } if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) { availableHeight = maximumClippingHeight; } if (noShift && !alignment) { const xMin = max(overflow.left, 0); const xMax = max(overflow.right, 0); const yMin = max(overflow.top, 0); const yMax = max(overflow.bottom, 0); if (isYAxis) { availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max(overflow.left, overflow.right)); } else { availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max(overflow.top, overflow.bottom)); } } await apply({ ...state, availableWidth: availableWidth, availableHeight: availableHeight }); const nextDimensions = await platform.getDimensions(elements.floating); if (width !== nextDimensions.width || height !== nextDimensions.height) { return { reset: { rects: true } }; } return {}; } }; }; function hasWindow() { return typeof window !== "undefined"; } function getNodeName(node) { if (isNode(node)) { return (node.nodeName || "").toLowerCase(); } return "#document"; } function getWindow(node) { var _node$ownerDocument; return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window; } function getDocumentElement(node) { var _ref; return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement; } function isNode(value) { if (!hasWindow()) { return false; } return value instanceof Node || value instanceof getWindow(value).Node; } function isElement(value) { if (!hasWindow()) { return false; } return value instanceof Element || value instanceof getWindow(value).Element; } function isHTMLElement(value) { if (!hasWindow()) { return false; } return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement; } function isShadowRoot(value) { if (!hasWindow() || typeof ShadowRoot === "undefined") { return false; } return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot; } function isOverflowElement(element) { const {overflow: overflow, overflowX: overflowX, overflowY: overflowY, display: display} = getComputedStyle$1(element); return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && ![ "inline", "contents" ].includes(display); } function isTableElement(element) { return [ "table", "td", "th" ].includes(getNodeName(element)); } function isTopLayer(element) { return [ ":popover-open", ":modal" ].some((selector => { try { return element.matches(selector); } catch (e) { return false; } })); } function isContainingBlock(elementOrCss) { const webkit = isWebKit(); const css = isElement(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss; 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))); } function getContainingBlock(element) { let currentNode = getParentNode(element); while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) { if (isContainingBlock(currentNode)) { return currentNode; } else if (isTopLayer(currentNode)) { return null; } currentNode = getParentNode(currentNode); } return null; } function isWebKit() { if (typeof CSS === "undefined" || !CSS.supports) return false; return CSS.supports("-webkit-backdrop-filter", "none"); } function isLastTraversableNode(node) { return [ "html", "body", "#document" ].includes(getNodeName(node)); } function getComputedStyle$1(element) { return getWindow(element).getComputedStyle(element); } function getNodeScroll(element) { if (isElement(element)) { return { scrollLeft: element.scrollLeft, scrollTop: element.scrollTop }; } return { scrollLeft: element.scrollX, scrollTop: element.scrollY }; } function getParentNode(node) { if (getNodeName(node) === "html") { return node; } const result = node.assignedSlot || node.parentNode || isShadowRoot(node) && node.host || getDocumentElement(node); return isShadowRoot(result) ? result.host : result; } function getNearestOverflowAncestor(node) { const parentNode = getParentNode(node); if (isLastTraversableNode(parentNode)) { return node.ownerDocument ? node.ownerDocument.body : node.body; } if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) { return parentNode; } return getNearestOverflowAncestor(parentNode); } function getOverflowAncestors(node, list, traverseIframes) { var _node$ownerDocument2; if (list === void 0) { list = []; } if (traverseIframes === void 0) { traverseIframes = true; } const scrollableAncestor = getNearestOverflowAncestor(node); const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body); const win = getWindow(scrollableAncestor); if (isBody) { const frameElement = getFrameElement(win); return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []); } return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes)); } function getFrameElement(win) { return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null; } function getCssDimensions(element) { const css = getComputedStyle$1(element); let width = parseFloat(css.width) || 0; let height = parseFloat(css.height) || 0; const hasOffset = isHTMLElement(element); const offsetWidth = hasOffset ? element.offsetWidth : width; const offsetHeight = hasOffset ? element.offsetHeight : height; const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight; if (shouldFallback) { width = offsetWidth; height = offsetHeight; } return { width: width, height: height, $: shouldFallback }; } function unwrapElement(element) { return !isElement(element) ? element.contextElement : element; } function getScale(element) { const domElement = unwrapElement(element); if (!isHTMLElement(domElement)) { return createCoords(1); } const rect = domElement.getBoundingClientRect(); const {width: width, height: height, $: $} = getCssDimensions(domElement); let x = ($ ? round(rect.width) : rect.width) / width; let y = ($ ? round(rect.height) : rect.height) / height; if (!x || !Number.isFinite(x)) { x = 1; } if (!y || !Number.isFinite(y)) { y = 1; } return { x: x, y: y }; } const noOffsets = createCoords(0); function getVisualOffsets(element) { const win = getWindow(element); if (!isWebKit() || !win.visualViewport) { return noOffsets; } return { x: win.visualViewport.offsetLeft, y: win.visualViewport.offsetTop }; } function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) { if (isFixed === void 0) { isFixed = false; } if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) { return false; } return isFixed; } function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) { if (includeScale === void 0) { includeScale = false; } if (isFixedStrategy === void 0) { isFixedStrategy = false; } const clientRect = element.getBoundingClientRect(); const domElement = unwrapElement(element); let scale = createCoords(1); if (includeScale) { if (offsetParent) { if (isElement(offsetParent)) { scale = getScale(offsetParent); } } else { scale = getScale(element); } } const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0); let x = (clientRect.left + visualOffsets.x) / scale.x; let y = (clientRect.top + visualOffsets.y) / scale.y; let width = clientRect.width / scale.x; let height = clientRect.height / scale.y; if (domElement) { const win = getWindow(domElement); const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent; let currentWin = win; let currentIFrame = getFrameElement(currentWin); while (currentIFrame && offsetParent && offsetWin !== currentWin) { const iframeScale = getScale(currentIFrame); const iframeRect = currentIFrame.getBoundingClientRect(); const css = getComputedStyle$1(currentIFrame); const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x; const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y; x *= iframeScale.x; y *= iframeScale.y; width *= iframeScale.x; height *= iframeScale.y; x += left; y += top; currentWin = getWindow(currentIFrame); currentIFrame = getFrameElement(currentWin); } } return rectToClientRect({ width: width, height: height, x: x, y: y }); } function getWindowScrollBarX(element, rect) { const leftScroll = getNodeScroll(element).scrollLeft; if (!rect) { return getBoundingClientRect(getDocumentElement(element)).left + leftScroll; } return rect.left + leftScroll; } function getHTMLOffset(documentElement, scroll, ignoreScrollbarX) { if (ignoreScrollbarX === void 0) { ignoreScrollbarX = false; } const htmlRect = documentElement.getBoundingClientRect(); const x = htmlRect.left + scroll.scrollLeft - (ignoreScrollbarX ? 0 : getWindowScrollBarX(documentElement, htmlRect)); const y = htmlRect.top + scroll.scrollTop; return { x: x, y: y }; } function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) { let {elements: elements, rect: rect, offsetParent: offsetParent, strategy: strategy} = _ref; const isFixed = strategy === "fixed"; const documentElement = getDocumentElement(offsetParent); const topLayer = elements ? isTopLayer(elements.floating) : false; if (offsetParent === documentElement || topLayer && isFixed) { return rect; } let scroll = { scrollLeft: 0, scrollTop: 0 }; let scale = createCoords(1); const offsets = createCoords(0); const isOffsetParentAnElement = isHTMLElement(offsetParent); if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) { scroll = getNodeScroll(offsetParent); } if (isHTMLElement(offsetParent)) { const offsetRect = getBoundingClientRect(offsetParent); scale = getScale(offsetParent); offsets.x = offsetRect.x + offsetParent.clientLeft; offsets.y = offsetRect.y + offsetParent.clientTop; } } const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll, true) : createCoords(0); return { width: rect.width * scale.x, height: rect.height * scale.y, x: rect.x * scale.x - scroll.scrollLef