{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "use-controls-visibility",
  "registryDependencies": [
    "https://limeplay.winoffrg.dev/r/use-media.json",
    "https://limeplay.winoffrg.dev/r/use-playback.json",
    "https://limeplay.winoffrg.dev/r/media-provider.json"
  ],
  "files": [
    {
      "path": "registry/default/hooks/use-controls-visibility.ts",
      "content": "\"use client\"\n\nimport React from \"react\"\n\nimport { useMediaStore } from \"@/registry/default/hooks/use-media\"\nimport { usePlaybackStore } from \"@/registry/default/hooks/use-playback\"\n\nexport interface UseControlsVisibilityOptions {\n  controlsHideDelay?: number\n  hideCursorOnIdle?: boolean\n}\n\ntype RootInteractionProps = Pick<\n  React.ComponentPropsWithoutRef<\"div\">,\n  | \"onBlur\"\n  | \"onFocus\"\n  | \"onPointerEnter\"\n  | \"onPointerLeave\"\n  | \"onPointerMove\"\n  | \"onPointerOver\"\n  | \"onPointerUp\"\n>\n\nexport const CONTROLS_FORCE_VISIBLE_ATTRIBUTE = \"data-controls-force-visible\"\n\nconst CONTROLS_KEEP_VISIBLE_SELECTOR = `[${CONTROLS_FORCE_VISIBLE_ATTRIBUTE}]`\n\nexport function useControlsVisibility({\n  controlsHideDelay = 2000,\n  hideCursorOnIdle = true,\n}: UseControlsVisibilityOptions = {}) {\n  const debug = useMediaStore((state) => state.debug)\n  const forceIdle = useMediaStore((state) => state.forceIdle)\n  const idle = useMediaStore((state) => state.idle)\n  const setIdle = useMediaStore((state) => state.setIdle)\n  const status = usePlaybackStore((state) => state.status)\n  const hideTimerRef = React.useRef<null | number>(null)\n  const autoHide = controlsHideDelay > 0\n  const controlsHidden =\n    !debug &&\n    !forceIdle &&\n    idle &&\n    status !== \"buffering\" &&\n    status !== \"error\" &&\n    status !== \"paused\"\n\n  const clearHideTimer = React.useCallback(() => {\n    if (hideTimerRef.current === null) return\n\n    window.clearTimeout(hideTimerRef.current)\n    hideTimerRef.current = null\n  }, [])\n\n  const hideControls = React.useCallback(() => {\n    if (forceIdle) return\n\n    clearHideTimer()\n\n    if (autoHide) {\n      hideTimerRef.current = window.setTimeout(() => {\n        setIdle(true)\n        hideTimerRef.current = null\n      }, controlsHideDelay)\n      return\n    }\n\n    setIdle(true)\n  }, [autoHide, clearHideTimer, controlsHideDelay, forceIdle, setIdle])\n\n  const showControls = React.useCallback(\n    (options?: { autoHide?: boolean }) => {\n      if (forceIdle) return\n\n      clearHideTimer()\n      setIdle(false)\n\n      if (options?.autoHide) {\n        hideControls()\n      }\n    },\n    [clearHideTimer, forceIdle, hideControls, setIdle]\n  )\n\n  React.useEffect(() => clearHideTimer, [clearHideTimer])\n\n  React.useEffect(() => {\n    if (forceIdle) {\n      clearHideTimer()\n    }\n  }, [clearHideTimer, forceIdle])\n\n  const rootProps = React.useMemo<RootInteractionProps>(\n    () => ({\n      onBlur: (event) => {\n        const relatedTarget = event.relatedTarget\n        if (\n          relatedTarget instanceof Node &&\n          event.currentTarget.contains(relatedTarget)\n        ) {\n          return\n        }\n\n        hideControls()\n      },\n      onFocus: () => {\n        showControls()\n      },\n      onPointerEnter: () => {\n        showControls({ autoHide })\n      },\n      onPointerLeave: () => {\n        hideControls()\n      },\n      onPointerMove: (event) => {\n        showControls({\n          autoHide: autoHide && !isKeepVisibleTarget(event.target),\n        })\n      },\n      onPointerOver: (event) => {\n        if (isKeepVisibleTarget(event.target)) {\n          showControls()\n        }\n      },\n      onPointerUp: (event) => {\n        showControls({\n          autoHide: autoHide && !isKeepVisibleTarget(event.target),\n        })\n      },\n    }),\n    [autoHide, hideControls, showControls]\n  )\n\n  return {\n    className: hideCursorOnIdle && controlsHidden ? \"cursor-none\" : undefined,\n    rootProps,\n  }\n}\n\nfunction isKeepVisibleTarget(target: EventTarget | null) {\n  return (\n    target instanceof Element &&\n    target.closest(CONTROLS_KEEP_VISIBLE_SELECTOR) !== null\n  )\n}\n",
      "type": "registry:hook",
      "target": "hooks/limeplay/use-controls-visibility.ts"
    }
  ],
  "type": "registry:hook"
}