{"version":3,"file":"use-floating-window.cjs","names":[],"sources":["../../src/use-floating-window/use-floating-window.ts"],"sourcesContent":["// Required to disable for webkit-user-select, although deprecated, it is still required for Safari support\n/* oxlint-disable typescript/no-deprecated */\nimport { RefCallback, RefObject, useCallback, useEffect, useRef, useState } from 'react';\n\nfunction useRefValue<T>(value: T) {\n  const ref = useRef(value);\n  ref.current = value;\n  return ref;\n}\n\ninterface FloatingWindowPositionConfig {\n  top?: number;\n  left?: number;\n  right?: number;\n  bottom?: number;\n}\n\ninterface FloatingWindowPosition {\n  /** Element offset from the left side of the viewport */\n  x: number;\n\n  /** Element offset from the top side of the viewport */\n  y: number;\n}\n\nexport interface UseFloatingWindowOptions {\n  /** If `false`, the element can not be dragged. */\n  enabled?: boolean;\n\n  /** If `true`, the element can only move within the current viewport boundaries. */\n  constrainToViewport?: boolean;\n\n  /** The offset from the viewport edges when constraining the element. Requires `constrainToViewport: true`. */\n  constrainOffset?: number;\n\n  /** Selector of an element that should be used to drag floating window. If not specified, the entire root element is used as a drag target. */\n  dragHandleSelector?: string;\n\n  /** Selector of an element within `dragHandleSelector` that should be excluded from the drag event. */\n  excludeDragHandleSelector?: string;\n\n  /** If set, restricts movement to the specified axis */\n  axis?: 'x' | 'y';\n\n  /** Initial position. If not set, calculated from element styles. */\n  initialPosition?: FloatingWindowPositionConfig;\n\n  /** Called when the element position changes */\n  onPositionChange?: (pos: FloatingWindowPosition) => void;\n\n  /** Called when the drag starts */\n  onDragStart?: () => void;\n\n  /** Called when the drag stops */\n  onDragEnd?: () => void;\n}\n\nexport type SetFloatingWindowPosition = (position: FloatingWindowPositionConfig) => void;\n\nexport interface UseFloatingWindowReturnValue<T extends HTMLElement> {\n  /** Ref to the element that should be draggable */\n  ref: RefCallback<T | null>;\n\n  /** Function to set the position of the element */\n  setPosition: SetFloatingWindowPosition;\n\n  /** `true` if the element is currently being dragged */\n  isDragging: boolean;\n}\n\nexport function useFloatingWindow<T extends HTMLElement>(\n  options: UseFloatingWindowOptions = {}\n): UseFloatingWindowReturnValue<T> {\n  const [element, setElement] = useState<T | null>(null);\n  const ref = useRef<T>(null);\n  const pos = useRef({ x: 0, y: 0 });\n  const offset = useRef({ x: 0, y: 0 });\n  const [isDragging, setIsDragging] = useState(false);\n  const isDraggingRef = useRef(false);\n  const initialized = useRef(false);\n  const enabledRef = useRefValue(options.enabled);\n\n  const setDragging = useCallback((value: boolean) => {\n    setIsDragging(value);\n    isDraggingRef.current = value;\n  }, []);\n\n  const assignRef = useCallback((node: T | null) => {\n    if (node) {\n      ref.current = node;\n      setElement(node);\n    } else {\n      ref.current = null;\n      setElement(null);\n    }\n  }, []);\n\n  useEffect(() => {\n    const el = ref.current;\n    if (!initialized.current && el) {\n      initialized.current = true;\n      pos.current = calculateInitialPosition(el, options);\n      el.style.left = `${pos.current.x}px`;\n      el.style.top = `${pos.current.y}px`;\n      el.style.right = 'unset';\n      el.style.bottom = 'unset';\n    }\n\n    return () => {\n      initialized.current = false;\n    };\n  }, [\n    element,\n    options.constrainOffset,\n    options.initialPosition?.top,\n    options.initialPosition?.left,\n    options.initialPosition?.right,\n    options.initialPosition?.bottom,\n    options.constrainToViewport,\n  ]);\n\n  useEffect(() => {\n    const el = ref.current;\n    if (!el) {\n      return;\n    }\n\n    const controller = new AbortController();\n    const signal = controller.signal;\n\n    const onStart = (e: MouseEvent | TouchEvent) => {\n      if (enabledRef.current === false) {\n        return;\n      }\n\n      const point = 'touches' in e ? e.touches[0] : e;\n\n      if ('button' in e && e.button !== 0) {\n        return;\n      }\n\n      if (!getHandle(el, e.target, options)) {\n        return;\n      }\n\n      setDragging(true);\n      document.body.style.userSelect = 'none';\n      document.body.style.webkitUserSelect = 'none';\n\n      const rect = el.getBoundingClientRect();\n\n      offset.current = {\n        x: point.clientX - rect.left,\n        y: point.clientY - rect.top,\n      };\n\n      options.onDragStart?.();\n\n      document.addEventListener('mousemove', onMove, { signal });\n      document.addEventListener('mouseup', onEnd, { signal });\n      document.addEventListener('touchmove', onMove, { signal, passive: false });\n      document.addEventListener('touchend', onEnd, { signal });\n    };\n\n    const onMove = (e: MouseEvent | TouchEvent) => {\n      if (!isDraggingRef.current) {\n        return;\n      }\n\n      const point = 'touches' in e ? e.touches[0] : e;\n      e.preventDefault();\n\n      let x = point.clientX - offset.current.x;\n      let y = point.clientY - offset.current.y;\n\n      const constrained = getConstrainedPosition(el, { x, y }, options);\n      if (options.axis === 'x') {\n        x = constrained.x;\n        y = pos.current.y;\n      } else if (options.axis === 'y') {\n        x = pos.current.x;\n        y = constrained.y;\n      } else {\n        x = constrained.x;\n        y = constrained.y;\n      }\n\n      pos.current = { x, y };\n\n      if (ref.current) {\n        ref.current.style.left = `${x}px`;\n        ref.current.style.top = `${y}px`;\n      }\n\n      options.onPositionChange?.({ x, y });\n    };\n\n    const onEnd = () => {\n      if (isDraggingRef.current) {\n        setDragging(false);\n        document.body.style.userSelect = '';\n        document.body.style.webkitUserSelect = '';\n        options.onDragEnd?.();\n      }\n    };\n\n    el.addEventListener('mousedown', onStart, { signal });\n    el.addEventListener('touchstart', onStart, { signal, passive: false });\n\n    return () => {\n      controller.abort();\n    };\n  }, [\n    options.constrainToViewport,\n    options.constrainOffset,\n    options.dragHandleSelector,\n    options.axis,\n    options.onPositionChange,\n    options.onDragStart,\n    options.onDragEnd,\n    options.initialPosition?.top,\n    options.initialPosition?.left,\n    options.initialPosition?.right,\n    options.initialPosition?.bottom,\n    element,\n  ]);\n\n  useEffect(() => {\n    const el = ref.current;\n    if (!el) {\n      return;\n    }\n\n    const observer = new ResizeObserver(() => {\n      // Re-clamp current position if element size changes\n      const constrained = getConstrainedPosition(el, pos.current, options);\n      pos.current = constrained;\n      el.style.left = `${constrained.x}px`;\n      el.style.top = `${constrained.y}px`;\n    });\n\n    observer.observe(el);\n\n    return () => {\n      observer.disconnect();\n    };\n  }, [options.constrainToViewport, options.constrainOffset]);\n\n  return {\n    ref: assignRef,\n    setPosition: createSetPosition(ref, pos, options),\n    isDragging,\n  };\n}\n\n// -------------------------------------------------------\n// Helper functions\n// -------------------------------------------------------\n\nfunction px(v: string) {\n  return v.endsWith('px') ? parseFloat(v) : 0;\n}\n\nfunction calculateInitialPosition(\n  el: HTMLElement,\n  options: UseFloatingWindowOptions\n): { x: number; y: number } {\n  const rect = el.getBoundingClientRect();\n  const offset = options.constrainOffset ?? 0;\n  const winW = window.innerWidth;\n  const winH = window.innerHeight;\n  const style = window.getComputedStyle(el);\n  const top = options.initialPosition?.top;\n  const left = options.initialPosition?.left;\n  const right = options.initialPosition?.right;\n  const bottom = options.initialPosition?.bottom;\n\n  let x = offset;\n  let y = offset;\n\n  if (left != null) {\n    x = left;\n  } else if (right != null) {\n    x = winW - rect.width - right;\n  } else {\n    x = px(style.left) || winW - rect.width - px(style.right) || offset;\n  }\n\n  if (top != null) {\n    y = top;\n  } else if (bottom != null) {\n    y = winH - rect.height - bottom;\n  } else {\n    y = px(style.top) || winH - rect.height - px(style.bottom) || offset;\n  }\n\n  return options.constrainToViewport\n    ? clampToViewport(x, y, el, options.constrainOffset)\n    : { x, y };\n}\n\nfunction getConstrainedPosition(\n  el: HTMLElement,\n  pos: FloatingWindowPosition,\n  options: UseFloatingWindowOptions\n) {\n  if (!options.constrainToViewport || !el) {\n    return pos;\n  }\n\n  const rect = el.getBoundingClientRect();\n  const offset = options.constrainOffset ?? 0;\n  const maxX = window.innerWidth - rect.width - offset;\n  const maxY = window.innerHeight - rect.height - offset;\n\n  return {\n    x: Math.min(Math.max(offset, pos.x), maxX),\n    y: Math.min(Math.max(offset, pos.y), maxY),\n  };\n}\n\nfunction matchesExcludeSelector(target: Node, excludeSelector?: string): boolean {\n  if (!excludeSelector) {\n    return false;\n  }\n  if (!(target instanceof Element)) {\n    return false;\n  }\n\n  return Boolean(target.closest(excludeSelector));\n}\n\nfunction getHandle(\n  el: HTMLElement,\n  target: EventTarget | null,\n  options: UseFloatingWindowOptions\n): boolean {\n  if (!(target instanceof Node)) {\n    return false;\n  }\n\n  // If no drag handle selector, allow dragging from entire element\n  if (!options.dragHandleSelector) {\n    return !matchesExcludeSelector(target, options.excludeDragHandleSelector);\n  }\n\n  const handles = Array.from(el.querySelectorAll(options.dragHandleSelector));\n  return handles.some(\n    (handle) =>\n      handle.contains(target) && !matchesExcludeSelector(target, options.excludeDragHandleSelector)\n  );\n}\n\nfunction clampToViewport(\n  x: number,\n  y: number,\n  el: HTMLElement,\n  offset: number = 0\n): { x: number; y: number } {\n  const rect = el.getBoundingClientRect();\n  const maxX = window.innerWidth - rect.width - offset;\n  const maxY = window.innerHeight - rect.height - offset;\n\n  return {\n    x: Math.min(Math.max(offset, x), maxX),\n    y: Math.min(Math.max(offset, y), maxY),\n  };\n}\n\nfunction createSetPosition(\n  elRef: RefObject<HTMLElement | null>,\n  posRef: React.RefObject<{ x: number; y: number }>,\n  options: UseFloatingWindowOptions\n) {\n  return useCallback(\n    (position: FloatingWindowPositionConfig) => {\n      const el = elRef.current;\n      if (!el) {\n        return;\n      }\n\n      const offset = options.constrainOffset ?? 0;\n      const rect = el.getBoundingClientRect();\n\n      let x: number | undefined;\n      let y: number | undefined;\n\n      if (position.left != null) {\n        x = position.left;\n      } else if (position.right != null) {\n        x = window.innerWidth - rect.width - position.right;\n      }\n\n      if (position.top != null) {\n        y = position.top;\n      } else if (position.bottom != null) {\n        y = window.innerHeight - rect.height - position.bottom;\n      }\n\n      x = x ?? posRef.current.x;\n      y = y ?? posRef.current.y;\n\n      if (options.constrainToViewport) {\n        const clamped = clampToViewport(x, y, el, offset);\n        x = clamped.x;\n        y = clamped.y;\n      }\n\n      posRef.current = { x, y };\n      el.style.left = `${x}px`;\n      el.style.top = `${y}px`;\n      options.onPositionChange?.({ x, y });\n    },\n    [options.constrainToViewport, options.constrainOffset, options.onPositionChange]\n  );\n}\n\nexport namespace useFloatingWindow {\n  export type Options = UseFloatingWindowOptions;\n  export type Position = FloatingWindowPosition;\n  export type SetPosition = SetFloatingWindowPosition;\n  export type ReturnValue<T extends HTMLElement> = UseFloatingWindowReturnValue<T>;\n}\n"],"mappings":"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"}