{"version":3,"file":"XAxisInteractionAreaPlugin.cjs","sources":["../../../../../src/components/uPlot/plugins/XAxisInteractionAreaPlugin.tsx"],"sourcesContent":["import { useLayoutEffect } from 'react';\nimport uPlot from 'uplot';\n\nimport { getFeatureToggle } from '../../../utils/featureToggle';\nimport { UPlotConfigBuilder } from '../config/UPlotConfigBuilder';\n\nconst MIN_PAN_DIST = 5;\n\n/**\n * Calculates the new time range after a pan operation.\n *\n * @returns Object containing the new from and to time values\n * @internal - exported for testing only\n */\nexport const calculatePanRange = (\n  timeFrom: number,\n  timeTo: number,\n  dragPixels: number,\n  plotWidth: number\n): { from: number; to: number } => {\n  const unitsPerPx = (timeTo - timeFrom) / (plotWidth / uPlot.pxRatio);\n  const timeShift = dragPixels * unitsPerPx;\n\n  return {\n    from: timeFrom - timeShift,\n    to: timeTo - timeShift,\n  };\n};\n\n/**\n * Enables panning the time range by click and dragging x-axis labels with the mouse.\n * Provides visual feedback (grab/grabbing cursor) and real-time grid updates during drag.\n *\n * @returns Cleanup function to remove event listeners\n * @internal - exported for testing only\n */\nexport const setupXAxisPan = (\n  u: uPlot,\n  config: UPlotConfigBuilder,\n  queryZoom: (range: { from: number; to: number }) => void\n): (() => void) => {\n  let xAxes = u.root.querySelectorAll('.u-axis');\n  let xAxis = xAxes[0];\n\n  if (!xAxis || !(xAxis instanceof HTMLElement)) {\n    return () => {};\n  }\n\n  const xAxisEl = xAxis;\n\n  let activeMoveListener: ((e: MouseEvent) => void) | null = null;\n  let activeUpListener: ((e: MouseEvent) => void) | null = null;\n\n  const handleMouseEnter = () => {\n    xAxisEl.style.cursor = 'grab';\n  };\n\n  const handleMouseLeave = () => {\n    xAxisEl.style.cursor = '';\n  };\n\n  const handleMouseDown = (e: Event) => {\n    if (!(e instanceof MouseEvent)) {\n      return;\n    }\n    e.preventDefault();\n\n    xAxisEl.style.cursor = 'grabbing';\n\n    let xScale = u.scales.x;\n\n    let rect = u.over.getBoundingClientRect();\n    let startX = e.clientX - rect.left;\n    let startMin = xScale.min!;\n    let startMax = xScale.max!;\n\n    const onMove = (e: MouseEvent) => {\n      e.preventDefault();\n\n      let currentX = e.clientX - rect.left;\n      let dragPixels = currentX - startX;\n\n      const { from, to } = calculatePanRange(startMin, startMax, dragPixels, u.bbox.width);\n\n      config.setState({ isPanning: true, min: from, max: to });\n\n      u.setScale('x', {\n        min: from,\n        max: to,\n      });\n    };\n\n    const onUp = (e: MouseEvent) => {\n      let endX = e.clientX - rect.left;\n      let dragPixels = endX - startX;\n\n      xAxisEl.style.cursor = 'grab';\n\n      const isSignificantDrag = Math.abs(dragPixels) >= MIN_PAN_DIST;\n\n      if (isSignificantDrag) {\n        const newRange = calculatePanRange(startMin, startMax, dragPixels, u.bbox.width);\n        config.setState({ isPanning: true, min: newRange.from, max: newRange.to, isTimeRangePending: true });\n        queryZoom(newRange);\n      } else {\n        config.setState({ isPanning: false });\n      }\n\n      document.removeEventListener('mousemove', onMove);\n      document.removeEventListener('mouseup', onUp);\n      activeMoveListener = null;\n      activeUpListener = null;\n    };\n\n    activeMoveListener = onMove;\n    activeUpListener = onUp;\n\n    document.addEventListener('mousemove', onMove);\n    document.addEventListener('mouseup', onUp);\n  };\n\n  xAxisEl.addEventListener('mouseenter', handleMouseEnter);\n  xAxisEl.addEventListener('mouseleave', handleMouseLeave);\n  xAxisEl.addEventListener('mousedown', handleMouseDown);\n\n  return () => {\n    xAxisEl.removeEventListener('mouseenter', handleMouseEnter);\n    xAxisEl.removeEventListener('mouseleave', handleMouseLeave);\n    xAxisEl.removeEventListener('mousedown', handleMouseDown);\n\n    if (activeMoveListener) {\n      document.removeEventListener('mousemove', activeMoveListener);\n    }\n    if (activeUpListener) {\n      document.removeEventListener('mouseup', activeUpListener);\n    }\n  };\n};\n\nexport interface XAxisInteractionAreaPluginProps {\n  config: UPlotConfigBuilder;\n  queryZoom?: (range: { from: number; to: number }) => void;\n}\n\n/**\n * Plugin for handling x-axis area interactions, such as time range panning.\n * Properly manages event listener lifecycle to prevent memory leaks.\n */\nexport const XAxisInteractionAreaPlugin = ({ config, queryZoom }: XAxisInteractionAreaPluginProps) => {\n  useLayoutEffect(() => {\n    let cleanup: (() => void) | undefined;\n\n    config.addHook('init', (u) => {\n      if (queryZoom != null && getFeatureToggle('timeRangePan')) {\n        cleanup = setupXAxisPan(u, config, queryZoom);\n      }\n    });\n\n    return () => {\n      if (cleanup) {\n        cleanup();\n      }\n    };\n  }, [config, queryZoom]);\n\n  return null;\n};\n"],"names":["uPlot","e","useLayoutEffect","getFeatureToggle"],"mappings":"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"}