{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "hover-navigation-viewer", "dependencies": [ "react-pdf", "@wojtekmaj/react-hooks", "lucide-react" ], "registryDependencies": [ "button" ], "files": [ { "path": "registry/reusables/pdf-viewers/hover-navigation-viewer.tsx", "content": "\"use client\"\n\nimport { useCallback, useState } from \"react\"\nimport { useResizeObserver } from \"@wojtekmaj/react-hooks\"\nimport { ChevronLeft, ChevronRight } from \"lucide-react\"\nimport { Document, Page, pdfjs } from \"react-pdf\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\n\nimport { LoadingSpinner } from \"./loading-spinner\"\n\npdfjs.GlobalWorkerOptions.workerSrc = new URL(\n \"pdfjs-dist/build/pdf.worker.min.mjs\",\n import.meta.url\n).toString()\n\nconst resizeObserverOptions = {}\nconst maxWidth = 800\n\ninterface HoverNavigationViewerProps {\n url: string\n}\n\nexport const HoverNavigationViewer = ({ url }: HoverNavigationViewerProps) => {\n const [numPages, setNumPages] = useState(null)\n const [pageNumber, setPageNumber] = useState(1)\n const [isHovering, setIsHovering] = useState(false)\n const [containerRef, setContainerRef] = useState(null)\n const [containerWidth, setContainerWidth] = useState()\n const [pageHeight, setPageHeight] = useState(0)\n\n const onResize = useCallback((entries) => {\n const [entry] = entries\n if (entry) {\n setContainerWidth(entry.contentRect.width)\n }\n }, [])\n\n useResizeObserver(containerRef, resizeObserverOptions, onResize)\n\n const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {\n setNumPages(numPages)\n }\n\n const changePage = (offset: number) => {\n setPageNumber((prevPageNumber) => {\n const newPageNumber = prevPageNumber + offset\n return numPages ?\n Math.min(Math.max(1, newPageNumber), numPages)\n : prevPageNumber\n })\n }\n\n const pageWidth =\n containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth\n\n return (\n setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n ref={setContainerRef}\n >\n
\n }\n className=\"flex justify-center\"\n >\n \n }\n onLoadSuccess={(page) => {\n setPageHeight(page.height * (pageWidth / page.width))\n }}\n />\n \n
\n\n {numPages && numPages > 1 && isHovering && (\n <>\n changePage(-1)}\n disabled={pageNumber <= 1}\n className={cn(\n \"absolute top-1/2 left-2 z-50 -translate-y-1/2 rounded-full\",\n \"bg-white/90 shadow-lg transition-all duration-200 hover:bg-white dark:bg-white dark:text-black dark:hover:bg-white\"\n )}\n >\n \n \n\n changePage(1)}\n disabled={pageNumber >= (numPages || 1)}\n className={cn(\n \"absolute top-1/2 right-2 z-50 -translate-y-1/2 rounded-full\",\n \"bg-white/90 shadow-lg transition-all duration-200 hover:bg-white dark:bg-white dark:text-black dark:hover:bg-white\"\n )}\n >\n \n \n\n
\n Page {pageNumber} of {numPages}\n
\n \n )}\n \n )\n}\n", "type": "registry:component", "target": "components/pdf-viewers/hover-navigation-viewer.tsx" }, { "path": "registry/reusables/pdf-viewers/loading-spinner.tsx", "content": "import { Loader2 } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\ninterface LoadingSpinnerProps {\n minHeight?: string\n minWidth?: string\n className?: string\n spinnerClassName?: string\n}\n\nexport const LoadingSpinner = ({\n minHeight = \"600px\",\n minWidth = \"800px\",\n className,\n spinnerClassName,\n}: LoadingSpinnerProps) => {\n return (\n \n \n \n )\n}\n", "type": "registry:component", "target": "components/pdf-viewers/loading-spinner.tsx" } ], "type": "registry:component" }