UNPKG

@1771technologies/lytenyte-pro

Version:

242 lines (241 loc) 8.24 kB
import * as React from "react"; import { u as useLatestRef, s as shift, l as limitShift, a as size, b as arrow, h as hide, g as getSide, c as useFloating, d as useEnhancedEffect, e as autoUpdate, f as getAlignment, o as offset, i as flip } from "./proptypes-BjYr2nFr.js"; import { u as useDirection } from "./DirectionContext-DIPP5cAe.js"; function getLogicalSide(sideParam, renderedSide, isRtl) { const isLogicalSideParam = sideParam === "inline-start" || sideParam === "inline-end"; const logicalRight = isRtl ? "inline-start" : "inline-end"; const logicalLeft = isRtl ? "inline-end" : "inline-start"; return { top: "top", right: isLogicalSideParam ? logicalRight : "right", bottom: "bottom", left: isLogicalSideParam ? logicalLeft : "left" }[renderedSide]; } function useAnchorPositioning(params) { const { // Public parameters anchor, positionMethod = "absolute", side: sideParam = "bottom", sideOffset = 0, align = "center", alignOffset = 0, collisionBoundary, collisionPadding = 5, sticky = false, arrowPadding = 5, // Private parameters keepMounted = false, floatingRootContext, mounted, trackAnchor = true, nodeId } = params; const direction = useDirection(); const isRtl = direction === "rtl"; const side = { top: "top", right: "right", bottom: "bottom", left: "left", "inline-end": isRtl ? "left" : "right", "inline-start": isRtl ? "right" : "left" }[sideParam]; const placement = align === "center" ? side : `${side}-${align}`; const commonCollisionProps = { boundary: collisionBoundary === "clipping-ancestors" ? "clippingAncestors" : collisionBoundary, padding: collisionPadding }; const arrowRef = React.useRef(null); const sideOffsetRef = useLatestRef(sideOffset); const alignOffsetRef = useLatestRef(alignOffset); const sideOffsetDep = typeof sideOffset !== "function" ? sideOffset : 0; const alignOffsetDep = typeof alignOffset !== "function" ? alignOffset : 0; const middleware = [offset(({ rects, placement: currentPlacement }) => { const data = { side: getLogicalSide(sideParam, getSide(currentPlacement), isRtl), align: getAlignment(currentPlacement) || "center", anchor: { width: rects.reference.width, height: rects.reference.height }, positioner: { width: rects.floating.width, height: rects.floating.height } }; const sideAxis = typeof sideOffsetRef.current === "function" ? sideOffsetRef.current(data) : sideOffsetRef.current; const alignAxis = typeof alignOffsetRef.current === "function" ? alignOffsetRef.current(data) : alignOffsetRef.current; return { mainAxis: sideAxis, crossAxis: alignAxis, alignmentAxis: alignAxis }; }, [sideOffsetDep, alignOffsetDep, isRtl, sideParam])]; const flipMiddleware = flip(commonCollisionProps); const shiftMiddleware = shift({ ...commonCollisionProps, crossAxis: sticky, limiter: sticky ? void 0 : limitShift(() => { if (!arrowRef.current) { return {}; } const { height } = arrowRef.current.getBoundingClientRect(); return { offset: height / 2 + (typeof collisionPadding === "number" ? collisionPadding : 0) }; }) }); if (align !== "center") { middleware.push(flipMiddleware, shiftMiddleware); } else { middleware.push(shiftMiddleware, flipMiddleware); } middleware.push(size({ ...commonCollisionProps, apply({ elements: { floating }, rects: { reference }, availableWidth, availableHeight }) { Object.entries({ "--available-width": `${availableWidth}px`, "--available-height": `${availableHeight}px`, "--anchor-width": `${reference.width}px`, "--anchor-height": `${reference.height}px` }).forEach(([key, value]) => { floating.style.setProperty(key, value); }); } }), arrow(() => ({ // `transform-origin` calculations rely on an element existing. If the arrow hasn't been set, // we'll create a fake element. element: arrowRef.current || document.createElement("div"), padding: arrowPadding }), [arrowPadding]), hide(), { name: "transformOrigin", fn({ elements: elements2, middlewareData: middlewareData2, placement: renderedPlacement2 }) { const currentRenderedSide = getSide(renderedPlacement2); const arrowEl = arrowRef.current; const arrowX = middlewareData2.arrow?.x ?? 0; const arrowY = middlewareData2.arrow?.y ?? 0; const arrowWidth = arrowEl?.clientWidth ?? 0; const arrowHeight = arrowEl?.clientHeight ?? 0; const transformX = arrowX + arrowWidth / 2; const transformY = arrowY + arrowHeight / 2; const transformOrigin = { top: `${transformX}px calc(100% + ${sideOffset}px)`, bottom: `${transformX}px ${-sideOffset}px`, left: `calc(100% + ${sideOffset}px) ${transformY}px`, right: `${-sideOffset}px ${transformY}px` }[currentRenderedSide]; elements2.floating.style.setProperty("--transform-origin", transformOrigin); return {}; } }); let rootContext = floatingRootContext; if (!mounted && floatingRootContext) { rootContext = { ...floatingRootContext, elements: { reference: null, floating: null, domReference: null } }; } const autoUpdateOptions = React.useMemo(() => ({ elementResize: trackAnchor && typeof ResizeObserver !== "undefined", layoutShift: trackAnchor && typeof IntersectionObserver !== "undefined" }), [trackAnchor]); const { refs, elements, floatingStyles, middlewareData, update, placement: renderedPlacement, context, isPositioned } = useFloating({ rootContext, placement, middleware, strategy: positionMethod, whileElementsMounted: keepMounted ? void 0 : (...args) => autoUpdate(...args, autoUpdateOptions), nodeId }); const registeredPositionReferenceRef = React.useRef(null); useEnhancedEffect(() => { if (!mounted) { return; } const resolvedAnchor = typeof anchor === "function" ? anchor() : anchor; if (resolvedAnchor) { const unwrappedElement = isRef(resolvedAnchor) ? resolvedAnchor.current : resolvedAnchor; refs.setPositionReference(unwrappedElement); registeredPositionReferenceRef.current = unwrappedElement; } }, [mounted, refs, anchor]); React.useEffect(() => { if (!mounted) { return; } if (typeof anchor === "function") { return; } if (isRef(anchor) && anchor.current !== registeredPositionReferenceRef.current) { refs.setPositionReference(anchor.current); registeredPositionReferenceRef.current = anchor.current; } }, [mounted, refs, anchor]); React.useEffect(() => { if (keepMounted && mounted && elements.domReference && elements.floating) { return autoUpdate(elements.domReference, elements.floating, update, autoUpdateOptions); } return void 0; }, [keepMounted, mounted, elements, update, autoUpdateOptions]); const renderedSide = getSide(renderedPlacement); const logicalRenderedSide = getLogicalSide(sideParam, renderedSide, isRtl); const renderedAlign = getAlignment(renderedPlacement) || "center"; const anchorHidden = Boolean(middlewareData.hide?.referenceHidden); const arrowStyles = React.useMemo(() => ({ position: "absolute", top: middlewareData.arrow?.y, left: middlewareData.arrow?.x }), [middlewareData.arrow]); const arrowUncentered = middlewareData.arrow?.centerOffset !== 0; return React.useMemo(() => ({ positionerStyles: floatingStyles, arrowStyles, arrowRef, arrowUncentered, side: logicalRenderedSide, align: renderedAlign, anchorHidden, refs, context, isPositioned }), [floatingStyles, arrowStyles, arrowRef, arrowUncentered, logicalRenderedSide, renderedAlign, anchorHidden, refs, context, isPositioned]); } function isRef(param) { return param != null && "current" in param; } export { useAnchorPositioning as u };