{"version":3,"sources":["../src/hooks/usePositioning/usePositioning.ts"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { useId, useIsomorphicLayoutEffect } from '@fluentui/react-utilities';\nimport { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';\nimport type {\n  PositioningImperativeRef,\n  PositioningShorthandValue,\n  PositioningVirtualElement,\n} from '@fluentui/react-positioning';\nimport type { PositioningProps, PositioningReturn } from './types';\nimport { POSITIONS, ALIGNMENTS, POSITION_AREA_MAP } from './constants';\nimport { getPlacementString, normalizeAlign } from './utils/placement';\nimport { applyOffset, getCoverSelfAlignment, resolveElementRef, resolveOffset, shorthandToPositionArea } from './utils';\nimport { usePlacementObserver } from './usePlacementObserver';\n\nexport type TargetElement = HTMLElement | PositioningVirtualElement;\n\nconst DEFAULT_FLIP = ['flip-block', 'flip-inline', 'flip-block flip-inline'];\n\nconst EMPTY_FALLBACK_POSITIONS: PositioningShorthandValue[] = [];\n\n/**\n * Reads the current anchor-name property from an element and parses it into an array of names.\n * Handles comma-separated values and trimming.\n */\nconst readAnchorNames = (element: HTMLElement): string[] => {\n  return element.style\n    .getPropertyValue('anchor-name')\n    .split(',')\n    .map(name => name.trim())\n    .filter(Boolean);\n};\n\nexport function usePositioning(options: PositioningProps): PositioningReturn {\n  const {\n    pinned,\n    target: customTarget = null,\n    align: alignInput = ALIGNMENTS.center,\n    position = POSITIONS.above,\n    fallbackPositions = EMPTY_FALLBACK_POSITIONS,\n    offset,\n    coverTarget = false,\n    strategy = 'fixed',\n    matchTargetSize,\n    positioningRef,\n  } = options;\n\n  const align = normalizeAlign(alignInput);\n\n  const { mainAxis, crossAxis } = resolveOffset(offset);\n  const coverAlignment = React.useMemo(\n    () => (coverTarget ? getCoverSelfAlignment(position, align) : null),\n    [coverTarget, position, align],\n  );\n\n  const [triggerEl, setTriggerEl] = React.useState<HTMLElement | null>(null);\n  const [containerEl, setContainerEl] = React.useState<HTMLElement | null>(null);\n  const [imperativeTarget, setImperativeTarget] = React.useState<HTMLElement | null>(null);\n  const effectiveTarget = imperativeTarget ?? resolveElementRef(customTarget) ?? triggerEl;\n\n  const anchorName = `--${useId('popover-anchor-')}`;\n  const positionArea = POSITION_AREA_MAP[position][align];\n  const placement = getPlacementString(position, align);\n\n  const { targetDocument } = useFluent();\n\n  const fallbackAreas = React.useMemo(() => fallbackPositions.map(shorthandToPositionArea), [fallbackPositions]);\n\n  const requestPlacementUpdate = usePlacementObserver(containerEl, effectiveTarget, targetDocument, coverTarget);\n\n  React.useImperativeHandle<PositioningImperativeRef, PositioningImperativeRef>(\n    positioningRef,\n    () => ({\n      setTarget: (el: TargetElement | null) => {\n        setImperativeTarget(resolveElementRef(el));\n      },\n      updatePosition: requestPlacementUpdate,\n    }),\n    [requestPlacementUpdate],\n  );\n\n  useIsomorphicLayoutEffect(() => {\n    if (!effectiveTarget) {\n      return;\n    }\n\n    // `anchor-name` is a comma-separated list. Append this instance's name\n    // instead of overwriting so that multiple positioned popovers can share a\n    // single trigger (e.g. a Tooltip on hover and a Menu on click attached to\n    // the same button) without clobbering each other's anchor. On cleanup we\n    // remove only our own name, preserving any others still in use.\n    if (anchorName) {\n      const names = readAnchorNames(effectiveTarget);\n      if (!names.includes(anchorName)) {\n        effectiveTarget.style.setProperty('anchor-name', [...names, anchorName].join(', '));\n      }\n    }\n\n    return () => {\n      if (anchorName) {\n        const remaining = readAnchorNames(effectiveTarget).filter(name => name !== anchorName);\n        if (remaining.length > 0) {\n          effectiveTarget.style.setProperty('anchor-name', remaining.join(', '));\n        } else {\n          effectiveTarget.style.removeProperty('anchor-name');\n        }\n      }\n    };\n  }, [effectiveTarget, anchorName]);\n\n  const targetRef: React.RefCallback<HTMLElement> = React.useCallback(node => {\n    setTriggerEl(node);\n  }, []);\n\n  const containerRef: React.RefCallback<HTMLElement> = React.useCallback(\n    node => {\n      setContainerEl(node);\n\n      if (!node) {\n        return;\n      }\n\n      node.style.setProperty('position', strategy);\n      node.style.setProperty('inset', 'auto');\n      node.style.setProperty('margin', '0');\n\n      applyOffset(node, position, mainAxis, crossAxis);\n\n      if (matchTargetSize === 'width') {\n        node.style.setProperty('width', 'anchor-size(width)');\n      } else {\n        node.style.removeProperty('width');\n      }\n\n      node.style.setProperty('position-anchor', anchorName);\n      node.setAttribute('data-placement', placement);\n\n      if (coverAlignment) {\n        node.style.setProperty('position-area', 'center');\n        node.style.setProperty('align-self', coverAlignment.alignSelf);\n        node.style.setProperty('justify-self', coverAlignment.justifySelf);\n        node.style.removeProperty('position-try-fallbacks');\n        return;\n      }\n\n      node.style.setProperty('position-area', positionArea);\n\n      /*\n       * Workaround for https://crbug.com/438334710: Chromium (<=130-ish) doesn't\n         apply the implicit `anchor-center` self-alignment that the spec defines\n         for single-keyword `position-area` values (`block-start`, `block-end`,\n    `    inline-start`, `inline-end`) or `span-all`.\n      */\n      if (align === ALIGNMENTS.center) {\n        node.style.setProperty('place-self', 'anchor-center');\n      } else {\n        node.style.removeProperty('place-self');\n        node.style.removeProperty('align-self');\n        node.style.removeProperty('justify-self');\n      }\n\n      if (pinned) {\n        node.style.removeProperty('position-try-fallbacks');\n        return;\n      }\n\n      if (fallbackAreas.length > 0) {\n        node.style.setProperty('position-try-fallbacks', fallbackAreas.join(', '));\n      } else {\n        node.style.setProperty('position-try-fallbacks', DEFAULT_FLIP.join(', '));\n      }\n    },\n    [\n      anchorName,\n      positionArea,\n      placement,\n      fallbackAreas,\n      pinned,\n      position,\n      align,\n      mainAxis,\n      crossAxis,\n      coverAlignment,\n      strategy,\n      matchTargetSize,\n    ],\n  );\n\n  return { targetRef, containerRef };\n}\n"],"names":["usePositioning","DEFAULT_FLIP","EMPTY_FALLBACK_POSITIONS","readAnchorNames","element","style","getPropertyValue","split","map","name","trim","filter","Boolean","options","pinned","target","customTarget","align","alignInput","ALIGNMENTS","center","position","POSITIONS","above","fallbackPositions","offset","coverTarget","strategy","matchTargetSize","positioningRef","normalizeAlign","mainAxis","crossAxis","resolveOffset","coverAlignment","React","useMemo","getCoverSelfAlignment","triggerEl","setTriggerEl","useState","containerEl","setContainerEl","imperativeTarget","setImperativeTarget","effectiveTarget","resolveElementRef","anchorName","useId","positionArea","POSITION_AREA_MAP","placement","getPlacementString","targetDocument","useFluent","fallbackAreas","shorthandToPositionArea","requestPlacementUpdate","usePlacementObserver","useImperativeHandle","setTarget","el","updatePosition","useIsomorphicLayoutEffect","names","includes","setProperty","join","remaining","length","removeProperty","targetRef","useCallback","node","containerRef","applyOffset","setAttribute","alignSelf","justifySelf"],"mappings":"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"}