useChartHighlight.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import dayjs from 'dayjs'
  2. import { useState } from 'react'
  3. type ChartHighlightMouseEvent = {
  4. activeLabel?: string
  5. coordinates?: string
  6. }
  7. export interface ChartHighlight {
  8. left: string | undefined
  9. right: string | undefined
  10. coordinates: { left?: string; right?: string }
  11. isSelecting: boolean
  12. popoverPosition: { x: number; y: number } | null
  13. handleMouseDown: (e: ChartHighlightMouseEvent) => void
  14. handleMouseMove: (e: ChartHighlightMouseEvent) => void
  15. handleMouseUp: (e: { chartX?: number; chartY?: number }) => void
  16. clearHighlight: () => void
  17. }
  18. export function useChartHighlight(): ChartHighlight {
  19. const [left, setLeft] = useState<string | undefined>(undefined)
  20. const [right, setRight] = useState<string | undefined>(undefined)
  21. const [coordinates, setCoordinates] = useState<{ left?: string; right?: string }>({
  22. left: undefined,
  23. right: undefined,
  24. })
  25. const [isSelecting, setIsSelecting] = useState(false)
  26. const [popoverPosition, setPopoverPosition] = useState<{ x: number; y: number } | null>(null)
  27. const [initialPoint, setInitialPoint] = useState<string | undefined>(undefined)
  28. const handleMouseDown = (e: ChartHighlightMouseEvent) => {
  29. clearHighlight()
  30. if (!e || !e.activeLabel) return
  31. setIsSelecting(true)
  32. setLeft(e.activeLabel)
  33. setRight(e.activeLabel)
  34. setInitialPoint(e.activeLabel)
  35. setCoordinates({ left: e.coordinates, right: e.coordinates })
  36. }
  37. const handleMouseMove = (e: ChartHighlightMouseEvent) => {
  38. if (!isSelecting || !e || !e.activeLabel) return
  39. const currentTimestamp = dayjs(e.activeLabel)
  40. const initialTimestamp = dayjs(initialPoint)
  41. if (currentTimestamp.isBefore(initialTimestamp)) {
  42. // If dragging left, update left and keep right as initial
  43. setLeft(e.activeLabel)
  44. setRight(initialPoint)
  45. setCoordinates({
  46. left: e.coordinates,
  47. right: coordinates.right,
  48. })
  49. } else {
  50. // If dragging right, update right and keep left as initial
  51. setRight(e.activeLabel)
  52. setLeft(initialPoint)
  53. setCoordinates({
  54. left: coordinates.left,
  55. right: e.coordinates,
  56. })
  57. }
  58. }
  59. const handleMouseUp = (e: unknown) => {
  60. if (!isSelecting) return
  61. setIsSelecting(false)
  62. setInitialPoint(undefined)
  63. if (
  64. typeof e === 'object' &&
  65. e !== null &&
  66. 'chartX' in e &&
  67. 'chartY' in e &&
  68. typeof e.chartX === 'number' &&
  69. typeof e.chartY === 'number'
  70. ) {
  71. setPopoverPosition({ x: e.chartX, y: e.chartY })
  72. }
  73. }
  74. const clearHighlight = () => {
  75. setLeft(undefined)
  76. setRight(undefined)
  77. setCoordinates({ left: undefined, right: undefined })
  78. setPopoverPosition(null)
  79. setInitialPoint(undefined)
  80. }
  81. return {
  82. left,
  83. right,
  84. coordinates,
  85. isSelecting,
  86. popoverPosition,
  87. handleMouseDown,
  88. handleMouseMove,
  89. handleMouseUp,
  90. clearHighlight,
  91. }
  92. }