{
  "name": "use-mouse",
  "author": "Brendan Dash (https://shadcn-hooks.com)",
  "description": "A hook to track mouse position with optional touch support",
  "registryDependencies": [
    "@shadcnhooks/use-event-listener"
  ],
  "files": [
    {
      "path": "registry/hooks/use-mouse.ts",
      "content": "import { useState } from 'react'\nimport { useEventListener } from '@/registry/hooks/use-event-listener'\n\nexport type UseMouseCoordType = 'page' | 'client' | 'screen' | 'movement'\nexport type UseMouseSourceType = 'mouse' | 'touch' | null\n\nexport interface UseMouseInitialValue {\n  x: number\n  y: number\n}\n\nexport interface UseMouseState extends UseMouseInitialValue {\n  sourceType: UseMouseSourceType\n}\n\nexport interface UseMouseOptions {\n  type?: UseMouseCoordType\n  touch?: boolean\n  resetOnTouchEnds?: boolean\n  initialValue?: UseMouseInitialValue\n  window?: Window\n}\n\ntype MouseCoordKey =\n  | 'pageX'\n  | 'pageY'\n  | 'clientX'\n  | 'clientY'\n  | 'screenX'\n  | 'screenY'\n  | 'movementX'\n  | 'movementY'\ntype TouchCoordKey =\n  | 'pageX'\n  | 'pageY'\n  | 'clientX'\n  | 'clientY'\n  | 'screenX'\n  | 'screenY'\ntype TouchCoordType = Exclude<UseMouseCoordType, 'movement'>\n\nconst DEFAULT_INITIAL_VALUE: UseMouseInitialValue = {\n  x: 0,\n  y: 0,\n}\n\nconst MOUSE_X_COORD_KEY_BY_TYPE: Record<UseMouseCoordType, MouseCoordKey> = {\n  page: 'pageX',\n  client: 'clientX',\n  screen: 'screenX',\n  movement: 'movementX',\n}\n\nconst MOUSE_Y_COORD_KEY_BY_TYPE: Record<UseMouseCoordType, MouseCoordKey> = {\n  page: 'pageY',\n  client: 'clientY',\n  screen: 'screenY',\n  movement: 'movementY',\n}\n\nconst TOUCH_X_COORD_KEY_BY_TYPE: Record<TouchCoordType, TouchCoordKey> = {\n  page: 'pageX',\n  client: 'clientX',\n  screen: 'screenX',\n}\n\nconst TOUCH_Y_COORD_KEY_BY_TYPE: Record<TouchCoordType, TouchCoordKey> = {\n  page: 'pageY',\n  client: 'clientY',\n  screen: 'screenY',\n}\n\nfunction readMousePosition(\n  event: MouseEvent,\n  type: UseMouseCoordType,\n): UseMouseInitialValue {\n  const xKey = MOUSE_X_COORD_KEY_BY_TYPE[type]\n  const yKey = MOUSE_Y_COORD_KEY_BY_TYPE[type]\n\n  return {\n    x: event[xKey],\n    y: event[yKey],\n  }\n}\n\nfunction readTouchPosition(\n  touchPoint: Touch,\n  type: UseMouseCoordType,\n): UseMouseInitialValue {\n  if (type === 'movement') {\n    return {\n      x: touchPoint.clientX,\n      y: touchPoint.clientY,\n    }\n  }\n\n  const xKey = TOUCH_X_COORD_KEY_BY_TYPE[type]\n  const yKey = TOUCH_Y_COORD_KEY_BY_TYPE[type]\n\n  return {\n    x: touchPoint[xKey],\n    y: touchPoint[yKey],\n  }\n}\n\n/**\n * Reactive mouse position with optional touch support.\n *\n * @see https://shadcn-hooks.com/docs/hooks/use-mouse\n */\nexport function useMouse(options: UseMouseOptions = {}): UseMouseState {\n  const {\n    type = 'page',\n    touch = true,\n    resetOnTouchEnds = false,\n    initialValue = DEFAULT_INITIAL_VALUE,\n    window: customWindow,\n  } = options\n\n  const [state, setState] = useState<UseMouseState>(() => ({\n    x: initialValue.x,\n    y: initialValue.y,\n    sourceType: null,\n  }))\n\n  const targetWindow =\n    customWindow ?? (typeof window === 'undefined' ? undefined : window)\n  const enable = Boolean(targetWindow)\n\n  const updateFromMouseEvent = (event: MouseEvent) => {\n    const nextPosition = readMousePosition(event, type)\n    setState((prev) => ({\n      ...prev,\n      ...nextPosition,\n      sourceType: 'mouse',\n    }))\n  }\n\n  const updateFromTouchEvent = (event: TouchEvent) => {\n    const touchPoint = event.touches[0] ?? event.changedTouches[0]\n    if (!touchPoint) {\n      return\n    }\n\n    const nextPosition = readTouchPosition(touchPoint, type)\n    setState((prev) => ({\n      ...prev,\n      ...nextPosition,\n      sourceType: 'touch',\n    }))\n  }\n\n  const resetPosition = () => {\n    setState((prev) => ({\n      ...prev,\n      x: initialValue.x,\n      y: initialValue.y,\n    }))\n  }\n\n  const handleTouchEnd = (event: TouchEvent) => {\n    if (resetOnTouchEnds) {\n      resetPosition()\n      return\n    }\n\n    updateFromTouchEvent(event)\n  }\n\n  useEventListener('mousemove', updateFromMouseEvent, {\n    target: targetWindow,\n    passive: true,\n    enable,\n  })\n\n  useEventListener('dragover', updateFromMouseEvent, {\n    target: targetWindow,\n    passive: true,\n    enable,\n  })\n\n  useEventListener('touchstart', updateFromTouchEvent, {\n    target: targetWindow,\n    passive: true,\n    enable: enable && touch,\n  })\n\n  useEventListener('touchmove', updateFromTouchEvent, {\n    target: targetWindow,\n    passive: true,\n    enable: enable && touch,\n  })\n\n  useEventListener('touchend', handleTouchEnd, {\n    target: targetWindow,\n    passive: true,\n    enable: enable && touch,\n  })\n\n  return state\n}\n",
      "type": "registry:hook"
    }
  ],
  "type": "registry:hook"
}
