@monime/pdfio 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["__iconNode","__iconNode","__iconNode","__iconNode","__iconNode","__iconNode","__iconNode","__iconNode","__iconNode","__iconNode"],"sources":["../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/shared/src/utils/mergeClasses.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/shared/src/utils/toKebabCase.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/shared/src/utils/toCamelCase.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/shared/src/utils/toPascalCase.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/defaultAttributes.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/shared/src/utils/hasA11yProp.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/context.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/Icon.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/createLucideIcon.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/arrow-left-right.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/arrow-up-down.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/chevron-left.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/chevron-right.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/file-text.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/loader-circle.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/maximize.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/minimize.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/triangle-alert.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/zoom-in.mjs","../node_modules/.pnpm/lucide-react@1.14.0_react@19.2.6/node_modules/lucide-react/dist/esm/icons/zoom-out.mjs","../src/lib/PdfViewer.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\n\nexport { mergeClasses };\n//# sourceMappingURL=mergeClasses.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\n\nexport { toKebabCase };\n//# sourceMappingURL=toKebabCase.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\n\nexport { toCamelCase };\n//# sourceMappingURL=toCamelCase.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { toCamelCase } from './toCamelCase.mjs';\n\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\n\nexport { toPascalCase };\n//# sourceMappingURL=toPascalCase.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n return false;\n};\n\nexport { hasA11yProp };\n//# sourceMappingURL=hasA11yProp.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { createContext, useContext, useMemo, createElement } from 'react';\n\nconst LucideContext = createContext({});\nfunction LucideProvider({\n children,\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n className\n}) {\n const value = useMemo(\n () => ({\n size,\n color,\n strokeWidth,\n absoluteStrokeWidth,\n className\n }),\n [size, color, strokeWidth, absoluteStrokeWidth, className]\n );\n return createElement(LucideContext.Provider, { value }, children);\n}\nconst useLucideContext = () => useContext(LucideContext);\n\nexport { LucideProvider, useLucideContext };\n//# sourceMappingURL=context.mjs.map\n","\"use strict\";\n\"use client\";\n/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.mjs';\nimport { hasA11yProp } from './shared/src/utils/hasA11yProp.mjs';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.mjs';\nimport { useLucideContext } from './context.mjs';\n\nconst Icon = forwardRef(\n ({ color, size, strokeWidth, absoluteStrokeWidth, className = \"\", children, iconNode, ...rest }, ref) => {\n const {\n size: contextSize = 24,\n strokeWidth: contextStrokeWidth = 2,\n absoluteStrokeWidth: contextAbsoluteStrokeWidth = false,\n color: contextColor = \"currentColor\",\n className: contextClass = \"\"\n } = useLucideContext() ?? {};\n const calculatedStrokeWidth = absoluteStrokeWidth ?? contextAbsoluteStrokeWidth ? Number(strokeWidth ?? contextStrokeWidth) * 24 / Number(size ?? contextSize) : strokeWidth ?? contextStrokeWidth;\n return createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size ?? contextSize ?? defaultAttributes.width,\n height: size ?? contextSize ?? defaultAttributes.height,\n stroke: color ?? contextColor,\n strokeWidth: calculatedStrokeWidth,\n className: mergeClasses(\"lucide\", contextClass, className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n );\n }\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses } from './shared/src/utils/mergeClasses.mjs';\nimport { toKebabCase } from './shared/src/utils/toKebabCase.mjs';\nimport { toPascalCase } from './shared/src/utils/toPascalCase.mjs';\nimport Icon from './Icon.mjs';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M8 3 4 7l4 4\", key: \"9rb6wj\" }],\n [\"path\", { d: \"M4 7h16\", key: \"6tx8e3\" }],\n [\"path\", { d: \"m16 21 4-4-4-4\", key: \"siv7j2\" }],\n [\"path\", { d: \"M20 17H4\", key: \"h6l3hr\" }]\n];\nconst ArrowLeftRight = createLucideIcon(\"arrow-left-right\", __iconNode);\n\nexport { __iconNode, ArrowLeftRight as default };\n//# sourceMappingURL=arrow-left-right.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"m21 16-4 4-4-4\", key: \"f6ql7i\" }],\n [\"path\", { d: \"M17 20V4\", key: \"1ejh1v\" }],\n [\"path\", { d: \"m3 8 4-4 4 4\", key: \"11wl7u\" }],\n [\"path\", { d: \"M7 4v16\", key: \"1glfcx\" }]\n];\nconst ArrowUpDown = createLucideIcon(\"arrow-up-down\", __iconNode);\n\nexport { __iconNode, ArrowUpDown as default };\n//# sourceMappingURL=arrow-up-down.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [[\"path\", { d: \"m15 18-6-6 6-6\", key: \"1wnfg3\" }]];\nconst ChevronLeft = createLucideIcon(\"chevron-left\", __iconNode);\n\nexport { __iconNode, ChevronLeft as default };\n//# sourceMappingURL=chevron-left.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [[\"path\", { d: \"m9 18 6-6-6-6\", key: \"mthhwq\" }]];\nconst ChevronRight = createLucideIcon(\"chevron-right\", __iconNode);\n\nexport { __iconNode, ChevronRight as default };\n//# sourceMappingURL=chevron-right.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"path\", { d: \"M10 9H8\", key: \"b1mrlr\" }],\n [\"path\", { d: \"M16 13H8\", key: \"t4e002\" }],\n [\"path\", { d: \"M16 17H8\", key: \"z1uh3a\" }]\n];\nconst FileText = createLucideIcon(\"file-text\", __iconNode);\n\nexport { __iconNode, FileText as default };\n//# sourceMappingURL=file-text.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [[\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]];\nconst LoaderCircle = createLucideIcon(\"loader-circle\", __iconNode);\n\nexport { __iconNode, LoaderCircle as default };\n//# sourceMappingURL=loader-circle.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M8 3H5a2 2 0 0 0-2 2v3\", key: \"1dcmit\" }],\n [\"path\", { d: \"M21 8V5a2 2 0 0 0-2-2h-3\", key: \"1e4gt3\" }],\n [\"path\", { d: \"M3 16v3a2 2 0 0 0 2 2h3\", key: \"wsl5sc\" }],\n [\"path\", { d: \"M16 21h3a2 2 0 0 0 2-2v-3\", key: \"18trek\" }]\n];\nconst Maximize = createLucideIcon(\"maximize\", __iconNode);\n\nexport { __iconNode, Maximize as default };\n//# sourceMappingURL=maximize.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M8 3v3a2 2 0 0 1-2 2H3\", key: \"hohbtr\" }],\n [\"path\", { d: \"M21 8h-3a2 2 0 0 1-2-2V3\", key: \"5jw1f3\" }],\n [\"path\", { d: \"M3 16h3a2 2 0 0 1 2 2v3\", key: \"198tvr\" }],\n [\"path\", { d: \"M16 21v-3a2 2 0 0 1 2-2h3\", key: \"ph8mxp\" }]\n];\nconst Minimize = createLucideIcon(\"minimize\", __iconNode);\n\nexport { __iconNode, Minimize as default };\n//# sourceMappingURL=minimize.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\",\n key: \"wmoenq\"\n }\n ],\n [\"path\", { d: \"M12 9v4\", key: \"juzpu7\" }],\n [\"path\", { d: \"M12 17h.01\", key: \"p32p05\" }]\n];\nconst TriangleAlert = createLucideIcon(\"triangle-alert\", __iconNode);\n\nexport { __iconNode, TriangleAlert as default };\n//# sourceMappingURL=triangle-alert.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"line\", { x1: \"21\", x2: \"16.65\", y1: \"21\", y2: \"16.65\", key: \"13gj7c\" }],\n [\"line\", { x1: \"11\", x2: \"11\", y1: \"8\", y2: \"14\", key: \"1vmskp\" }],\n [\"line\", { x1: \"8\", x2: \"14\", y1: \"11\", y2: \"11\", key: \"durymu\" }]\n];\nconst ZoomIn = createLucideIcon(\"zoom-in\", __iconNode);\n\nexport { __iconNode, ZoomIn as default };\n//# sourceMappingURL=zoom-in.mjs.map\n","/**\n * @license lucide-react v1.14.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"circle\", { cx: \"11\", cy: \"11\", r: \"8\", key: \"4ej97u\" }],\n [\"line\", { x1: \"21\", x2: \"16.65\", y1: \"21\", y2: \"16.65\", key: \"13gj7c\" }],\n [\"line\", { x1: \"8\", x2: \"14\", y1: \"11\", y2: \"11\", key: \"durymu\" }]\n];\nconst ZoomOut = createLucideIcon(\"zoom-out\", __iconNode);\n\nexport { __iconNode, ZoomOut as default };\n//# sourceMappingURL=zoom-out.mjs.map\n","\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type KeyboardEvent,\n} from \"react\";\nimport type { PDFDocumentProxy, RenderTask } from \"pdfjs-dist\";\nimport {\n ChevronLeft,\n ChevronRight,\n ZoomIn,\n ZoomOut,\n Maximize,\n Minimize,\n ArrowLeftRight,\n ArrowUpDown,\n Loader2,\n AlertTriangle,\n FileText,\n} from \"lucide-react\";\n\nconst MIN_SCALE = 0.25;\nconst MAX_SCALE = 4;\nconst ZOOM_STEP = 0.25;\nconst PAGE_GAP = 16; // px between pages\nconst PRESETS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4];\n\nfunction clamp(v: number, min: number, max: number) {\n return Math.min(max, Math.max(min, v));\n}\n\nexport interface PDFViewerProps {\n src?: string;\n}\n\ntype PageSize = { width: number; height: number };\n\nexport function PDFViewer({\n src = \"https://snippet.embedpdf.com/ebook.pdf\",\n}: PDFViewerProps) {\n // ── Refs ────────────────────────────────────────────────────────────────────\n const containerRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const pageInputRef = useRef<HTMLInputElement>(null);\n const pdfRef = useRef<PDFDocumentProxy | null>(null);\n const pageWrapperRefs = useRef(new Map<number, HTMLDivElement>());\n const canvasRefs = useRef(new Map<number, HTMLCanvasElement>());\n const renderTasksRef = useRef(new Map<number, RenderTask>());\n\n // ── State ───────────────────────────────────────────────────────────────────\n const [numPages, setNumPages] = useState(0);\n const [pageSizes, setPageSizes] = useState<PageSize[]>([]);\n const [currentPage, setCurrentPage] = useState(1);\n const [scale, setScale] = useState(1.0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [isEditingPage, setIsEditingPage] = useState(false);\n const [pageInput, setPageInput] = useState(\"\");\n\n // ── Load document + collect page sizes ─────────────────────────────────────\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n setLoading(true);\n setError(null);\n setNumPages(0);\n setPageSizes([]);\n setCurrentPage(1);\n\n try {\n const { GlobalWorkerOptions, getDocument } = await import(\"pdfjs-dist\");\n GlobalWorkerOptions.workerSrc = new URL(\n \"pdfjs-dist/build/pdf.worker.min.mjs\",\n import.meta.url,\n ).toString();\n\n const loadTask = getDocument(src);\n const pdf = await loadTask.promise;\n if (cancelled) { void pdf.destroy(); return; }\n\n void pdfRef.current?.destroy();\n pdfRef.current = pdf;\n\n // Collect natural sizes at scale=1 for all pages\n const sizes: PageSize[] = [];\n for (let i = 1; i <= pdf.numPages; i++) {\n if (cancelled) return;\n const p = await pdf.getPage(i);\n const vp = p.getViewport({ scale: 1 });\n sizes.push({ width: vp.width, height: vp.height });\n }\n if (cancelled) return;\n\n setNumPages(pdf.numPages);\n setPageSizes(sizes);\n } catch (e) {\n if (!cancelled)\n setError(e instanceof Error ? e.message : \"Failed to load PDF.\");\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n void load();\n return () => { cancelled = true; };\n }, [src]);\n\n // ── Render all pages whenever pageSizes or scale changes ───────────────────\n\n useEffect(() => {\n const pdf = pdfRef.current;\n if (!pdf || pageSizes.length === 0) return;\n\n let cancelled = false;\n\n async function renderAll() {\n for (let pageNum = 1; pageNum <= pageSizes.length; pageNum++) {\n if (cancelled) return;\n\n const canvas = canvasRefs.current.get(pageNum);\n if (!canvas) continue;\n\n renderTasksRef.current.get(pageNum)?.cancel();\n\n try {\n const pdfPage = await pdf!.getPage(pageNum);\n if (cancelled) return;\n\n const viewport = pdfPage.getViewport({ scale });\n const dpr = window.devicePixelRatio || 1;\n\n canvas.width = Math.floor(viewport.width * dpr);\n canvas.height = Math.floor(viewport.height * dpr);\n canvas.style.width = `${viewport.width}px`;\n canvas.style.height = `${viewport.height}px`;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) continue;\n\n const task = pdfPage.render({\n canvas,\n canvasContext: ctx,\n viewport,\n transform: dpr !== 1 ? [dpr, 0, 0, dpr, 0, 0] : undefined,\n });\n renderTasksRef.current.set(pageNum, task);\n await task.promise;\n } catch {\n // cancelled render — ignore\n }\n }\n }\n\n void renderAll();\n\n return () => {\n cancelled = true;\n renderTasksRef.current.forEach((t) => t.cancel());\n renderTasksRef.current.clear();\n };\n }, [pageSizes, scale]);\n\n // ── Scroll listener — track current page ──────────────────────────────────\n\n useEffect(() => {\n const container = scrollRef.current;\n if (!container || pageSizes.length === 0) return;\n\n function update() {\n const mid = container!.scrollTop + container!.clientHeight / 2;\n let found = 1;\n for (let i = 1; i <= pageSizes.length; i++) {\n const el = pageWrapperRefs.current.get(i);\n if (!el) continue;\n if (el.offsetTop <= mid) found = i;\n else break;\n }\n setCurrentPage(found);\n }\n\n update(); // set on mount\n container.addEventListener(\"scroll\", update, { passive: true });\n return () => container.removeEventListener(\"scroll\", update);\n }, [pageSizes.length]);\n\n // ── Fullscreen ──────────────────────────────────────────────────────────────\n\n useEffect(() => {\n function onChange() { setIsFullscreen(!!document.fullscreenElement); }\n document.addEventListener(\"fullscreenchange\", onChange);\n return () => document.removeEventListener(\"fullscreenchange\", onChange);\n }, []);\n\n // ── Ref callbacks ───────────────────────────────────────────────────────────\n\n const setPageWrapper = useCallback(\n (pageNum: number) => (el: HTMLDivElement | null) => {\n if (el) pageWrapperRefs.current.set(pageNum, el);\n else pageWrapperRefs.current.delete(pageNum);\n },\n [],\n );\n\n const setCanvas = useCallback(\n (pageNum: number) => (el: HTMLCanvasElement | null) => {\n if (el) canvasRefs.current.set(pageNum, el);\n else canvasRefs.current.delete(pageNum);\n },\n [],\n );\n\n // ── Actions ─────────────────────────────────────────────────────────────────\n\n const scrollToPage = useCallback((n: number) => {\n const p = clamp(n, 1, numPages);\n const target = pageWrapperRefs.current.get(p);\n const container = scrollRef.current;\n if (!target || !container) return;\n container.scrollTop = target.offsetTop - PAGE_GAP;\n }, [numPages]);\n\n const zoomTo = useCallback(\n (s: number) => setScale(clamp(s, MIN_SCALE, MAX_SCALE)),\n [],\n );\n\n function fitToWidth() {\n const container = scrollRef.current;\n if (!container || pageSizes.length === 0) return;\n const available = container.clientWidth - PAGE_GAP * 2;\n zoomTo(available / pageSizes[0].width);\n }\n\n function fitToHeight() {\n const container = scrollRef.current;\n if (!container || pageSizes.length === 0) return;\n const available = container.clientHeight - PAGE_GAP * 2;\n zoomTo(available / pageSizes[0].height);\n }\n\n function toggleFullscreen() {\n if (isFullscreen) document.exitFullscreen();\n else containerRef.current?.requestFullscreen();\n }\n\n function startEditingPage() {\n setPageInput(String(currentPage));\n setIsEditingPage(true);\n setTimeout(() => pageInputRef.current?.select(), 0);\n }\n\n function commitPageEdit() {\n const n = parseInt(pageInput, 10);\n if (!isNaN(n)) scrollToPage(n);\n setIsEditingPage(false);\n }\n\n function handlePageKey(e: KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Enter\") commitPageEdit();\n else if (e.key === \"Escape\") setIsEditingPage(false);\n }\n\n const canPrev = currentPage > 1;\n const canNext = currentPage < numPages;\n\n // ── Render ──────────────────────────────────────────────────────────────────\n\n return (\n <div\n ref={containerRef}\n className=\"flex h-screen flex-col bg-white text-neutral-800\"\n >\n {/* ── Toolbar ──────────────────────────────────────────────────────── */}\n <div className=\"flex flex-shrink-0 items-center gap-1 border-b border-neutral-200 bg-white px-3 py-2 shadow-sm\">\n\n {/* Prev page */}\n <button\n type=\"button\"\n onClick={() => scrollToPage(currentPage - 1)}\n disabled={!canPrev}\n title=\"Previous page\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <ChevronLeft size={18} />\n </button>\n\n {/* Page indicator / jump input */}\n {isEditingPage ? (\n <input\n ref={pageInputRef}\n type=\"number\"\n min={1}\n max={numPages}\n value={pageInput}\n onChange={(e) => setPageInput(e.target.value)}\n onBlur={commitPageEdit}\n onKeyDown={handlePageKey}\n className=\"w-14 rounded-md border border-neutral-300 bg-white px-2 py-0.5 text-center text-sm outline-none focus:border-blue-500\"\n />\n ) : (\n <button\n type=\"button\"\n onClick={numPages > 0 ? startEditingPage : undefined}\n disabled={numPages === 0}\n title=\"Click to jump to page\"\n className=\"flex items-center gap-1 rounded-md px-2 py-0.5 text-sm transition hover:bg-neutral-100 disabled:opacity-40\"\n >\n <span className=\"font-medium tabular-nums\">\n {numPages > 0 ? currentPage : \"—\"}\n </span>\n <span className=\"text-neutral-400\">/</span>\n <span className=\"tabular-nums text-neutral-500\">\n {numPages > 0 ? numPages : \"—\"}\n </span>\n </button>\n )}\n\n {/* Next page */}\n <button\n type=\"button\"\n onClick={() => scrollToPage(currentPage + 1)}\n disabled={!canNext}\n title=\"Next page\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <ChevronRight size={18} />\n </button>\n\n <div className=\"mx-2 h-5 w-px bg-neutral-200\" />\n\n {/* Zoom out */}\n <button\n type=\"button\"\n onClick={() => zoomTo(scale - ZOOM_STEP)}\n disabled={scale <= MIN_SCALE}\n title=\"Zoom out\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <ZoomOut size={16} />\n </button>\n\n {/* Zoom preset dropdown — always shows current value */}\n <select\n value={scale}\n onChange={(e) => zoomTo(parseFloat(e.target.value))}\n title=\"Zoom level\"\n className=\"w-[5.5rem] rounded-md border border-neutral-300 bg-white px-1.5 py-0.5 text-xs text-neutral-700 outline-none focus:border-blue-500\"\n >\n {!PRESETS.some((p) => Math.abs(p - scale) < 0.001) && (\n <option value={scale}>{Math.round(scale * 100)}%</option>\n )}\n {PRESETS.map((v) => (\n <option key={v} value={v}>\n {Math.round(v * 100)}%\n </option>\n ))}\n </select>\n\n {/* Zoom in */}\n <button\n type=\"button\"\n onClick={() => zoomTo(scale + ZOOM_STEP)}\n disabled={scale >= MAX_SCALE}\n title=\"Zoom in\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <ZoomIn size={16} />\n </button>\n\n <div className=\"mx-1 h-5 w-px bg-neutral-200\" />\n\n {/* Fit to width */}\n <button\n type=\"button\"\n onClick={fitToWidth}\n disabled={pageSizes.length === 0}\n title=\"Fit to width\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <ArrowLeftRight size={15} />\n </button>\n\n {/* Fit to height */}\n <button\n type=\"button\"\n onClick={fitToHeight}\n disabled={pageSizes.length === 0}\n title=\"Fit to height\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <ArrowUpDown size={15} />\n </button>\n\n <div className=\"flex-1\" />\n\n {/* Fullscreen */}\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n title={isFullscreen ? \"Exit fullscreen\" : \"Enter fullscreen\"}\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100\"\n >\n {isFullscreen ? <Minimize size={16} /> : <Maximize size={16} />}\n </button>\n </div>\n\n {/* ── Scroll area ──────────────────────────────────────────────────── */}\n <div\n ref={scrollRef}\n className=\"flex-1 overflow-y-auto overflow-x-auto bg-white\"\n >\n {/* Loading */}\n {loading && (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"flex flex-col items-center gap-3 text-neutral-400\">\n <Loader2 size={32} className=\"animate-spin\" />\n <span className=\"text-sm\">Loading document…</span>\n </div>\n </div>\n )}\n\n {/* Error */}\n {!loading && error && (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"flex flex-col items-center gap-3 rounded-xl border border-red-200 bg-red-50 px-8 py-10 text-red-600\">\n <AlertTriangle size={32} />\n <p className=\"max-w-xs text-center text-sm\">{error}</p>\n </div>\n </div>\n )}\n\n {/* Empty */}\n {!loading && !error && numPages === 0 && (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"flex flex-col items-center gap-3 text-neutral-300\">\n <FileText size={48} />\n <span className=\"text-sm\">No document loaded</span>\n </div>\n </div>\n )}\n\n {/* Pages */}\n {!loading && !error && pageSizes.length > 0 && (\n <div\n className=\"flex flex-col items-center py-4\"\n style={{ gap: PAGE_GAP }}\n >\n {pageSizes.map((size, idx) => {\n const pageNum = idx + 1;\n return (\n <div\n key={pageNum}\n ref={setPageWrapper(pageNum)}\n data-page={pageNum}\n className=\"flex-shrink-0\"\n style={{\n width: Math.floor(size.width * scale),\n height: Math.floor(size.height * scale),\n }}\n >\n <canvas\n ref={setCanvas(pageNum)}\n className=\"block shadow-md ring-1 ring-black/10\"\n />\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/lib/Icons.tsx","../src/lib/PdfViewer.tsx"],"sourcesContent":["type IconProps = {\n size?: number;\n className?: string;\n};\n\nconst Icon = ({\n size = 24,\n className,\n children,\n}: IconProps & { children: React.ReactNode }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n {children}\n </svg>\n);\n\nexport const Icons = {\n ChevronLeft: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"m15 18-6-6 6-6\" />\n </Icon>\n ),\n ChevronRight: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"m9 18 6-6-6-6\" />\n </Icon>\n ),\n ZoomIn: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" x2=\"16.65\" y1=\"21\" y2=\"16.65\" />\n <line x1=\"11\" x2=\"11\" y1=\"8\" y2=\"14\" />\n <line x1=\"8\" x2=\"14\" y1=\"11\" y2=\"11\" />\n </Icon>\n ),\n ZoomOut: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <line x1=\"21\" x2=\"16.65\" y1=\"21\" y2=\"16.65\" />\n <line x1=\"8\" x2=\"14\" y1=\"11\" y2=\"11\" />\n </Icon>\n ),\n Maximize: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\n </Icon>\n ),\n Minimize: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\n <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\n </Icon>\n ),\n ArrowLeftRight: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"M8 3 4 7l4 4\" />\n <path d=\"M4 7h16\" />\n <path d=\"m16 21 4-4-4-4\" />\n <path d=\"M20 17H4\" />\n </Icon>\n ),\n ArrowUpDown: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"m21 16-4 4-4-4\" />\n <path d=\"M17 20V4\" />\n <path d=\"m3 8 4-4 4 4\" />\n <path d=\"M7 4v16\" />\n </Icon>\n ),\n Loader2: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </Icon>\n ),\n AlertTriangle: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z\" />\n <line x1=\"12\" x2=\"12\" y1=\"9\" y2=\"13\" />\n <line x1=\"12\" x2=\"12.01\" y1=\"17\" y2=\"17\" />\n </Icon>\n ),\n FileText: ({ size = 24, className }: IconProps) => (\n <Icon size={size} className={className}>\n <path d=\"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\" />\n <path d=\"M14 2v4a2 2 0 0 0 2 2h4\" />\n <path d=\"M10 9H8\" />\n <path d=\"M16 13H8\" />\n <path d=\"M16 17H8\" />\n </Icon>\n ),\n};\n","\"use client\";\n\nimport {\n useCallback,\n useEffect,\n useRef,\n useState,\n type KeyboardEvent,\n} from \"react\";\nimport type { PDFDocumentProxy, RenderTask } from \"pdfjs-dist\";\nimport { Icons } from \"./Icons\";\n\nconst MIN_SCALE = 0.25;\nconst MAX_SCALE = 4;\nconst ZOOM_STEP = 0.25;\nconst PAGE_GAP = 16; // px between pages\nconst PRESETS = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 3, 4];\n\nfunction clamp(v: number, min: number, max: number) {\n return Math.min(max, Math.max(min, v));\n}\n\nexport interface WatermarkConfig {\n text: string;\n /** CSS color string — default: \"rgba(0,0,0,0.12)\" */\n color?: string;\n /** Font size in px at scale=1 — default: 28 */\n fontSize?: number;\n /** Rotation angle in degrees — default: -35 */\n angle?: number;\n /** Horizontal gap between repeated labels in px — default: 80 */\n gap?: number;\n /** Font family — default: \"sans-serif\" */\n fontFamily?: string;\n /** Font weight — default: \"600\" */\n fontWeight?: string;\n}\n\nexport interface PDFViewerProps {\n src?: string | ArrayBuffer | URL;\n /** Pass a string for a quick watermark, or a WatermarkConfig for full control. */\n watermark?: string | WatermarkConfig;\n}\n\ntype PageSize = { width: number; height: number };\n\nfunction WatermarkOverlay({\n config,\n width,\n height,\n}: {\n config: WatermarkConfig;\n width: number;\n height: number;\n}) {\n const {\n text,\n color = \"rgba(0,0,0,0.12)\",\n fontSize = 28,\n angle = -35,\n gap = 80,\n fontFamily = \"sans-serif\",\n fontWeight = \"600\",\n } = config;\n\n // Estimate text width so tiles don't overlap horizontally.\n const estimatedTextWidth = text.length * fontSize * 0.55;\n const tileW = estimatedTextWidth + gap;\n const tileH = fontSize * 3;\n // Unique id per text so multiple viewers on the same page don't clash.\n const patternId = `wm-${text.replace(/\\W/g, \"\").slice(0, 12)}-${Math.round(fontSize)}`;\n\n return (\n <svg\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n inset: 0,\n width,\n height,\n pointerEvents: \"none\",\n userSelect: \"none\",\n }}\n width={width}\n height={height}\n >\n <defs>\n <pattern\n id={patternId}\n x=\"0\"\n y=\"0\"\n width={tileW}\n height={tileH}\n patternUnits=\"userSpaceOnUse\"\n patternTransform={`rotate(${angle}, ${width / 2}, ${height / 2})`}\n >\n <text\n x={tileW / 2}\n y={tileH / 2}\n textAnchor=\"middle\"\n dominantBaseline=\"middle\"\n fill={color}\n fontSize={fontSize}\n fontFamily={fontFamily}\n fontWeight={fontWeight}\n letterSpacing=\"0.05em\"\n >\n {text}\n </text>\n </pattern>\n </defs>\n <rect width={width} height={height} fill={`url(#${patternId})`} />\n </svg>\n );\n}\n\nexport function PDFViewer({ src, watermark }: PDFViewerProps) {\n // ── Refs ────────────────────────────────────────────────────────────────────\n const containerRef = useRef<HTMLDivElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n const pageInputRef = useRef<HTMLInputElement>(null);\n const pdfRef = useRef<PDFDocumentProxy | null>(null);\n const pageWrapperRefs = useRef(new Map<number, HTMLDivElement>());\n const canvasRefs = useRef(new Map<number, HTMLCanvasElement>());\n const renderTasksRef = useRef(new Map<number, RenderTask>());\n\n // ── State ───────────────────────────────────────────────────────────────────\n const [numPages, setNumPages] = useState(0);\n const [pageSizes, setPageSizes] = useState<PageSize[]>([]);\n const [currentPage, setCurrentPage] = useState(1);\n const [scale, setScale] = useState(1.0);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const [isEditingPage, setIsEditingPage] = useState(false);\n const [pageInput, setPageInput] = useState(\"\");\n\n // ── Load document + collect page sizes ─────────────────────────────────────\n\n useEffect(() => {\n let cancelled = false;\n\n async function load() {\n if (src === undefined) {\n setLoading(false);\n setError(null);\n setNumPages(0);\n setPageSizes([]);\n setCurrentPage(1);\n return;\n }\n\n setLoading(true);\n setError(null);\n setNumPages(0);\n setPageSizes([]);\n setCurrentPage(1);\n\n try {\n const { GlobalWorkerOptions, getDocument } = await import(\"pdfjs-dist\");\n GlobalWorkerOptions.workerSrc = new URL(\n \"pdfjs-dist/build/pdf.worker.min.mjs\",\n import.meta.url,\n ).toString();\n\n const loadTask = getDocument(src);\n const pdf = await loadTask.promise;\n if (cancelled) {\n void pdf.destroy();\n return;\n }\n\n void pdfRef.current?.destroy();\n pdfRef.current = pdf;\n\n // Collect natural sizes at scale=1 for all pages\n const sizes: PageSize[] = [];\n for (let i = 1; i <= pdf.numPages; i++) {\n if (cancelled) return;\n const p = await pdf.getPage(i);\n const vp = p.getViewport({ scale: 1 });\n sizes.push({ width: vp.width, height: vp.height });\n }\n if (cancelled) return;\n\n setNumPages(pdf.numPages);\n setPageSizes(sizes);\n } catch (e) {\n if (!cancelled)\n setError(e instanceof Error ? e.message : \"Failed to load PDF.\");\n } finally {\n if (!cancelled) setLoading(false);\n }\n }\n\n void load();\n return () => {\n cancelled = true;\n };\n }, [src]);\n\n // ── Render all pages whenever pageSizes or scale changes ───────────────────\n\n useEffect(() => {\n const pdf = pdfRef.current;\n if (!pdf || pageSizes.length === 0) return;\n\n let cancelled = false;\n\n async function renderAll() {\n for (let pageNum = 1; pageNum <= pageSizes.length; pageNum++) {\n if (cancelled) return;\n\n const canvas = canvasRefs.current.get(pageNum);\n if (!canvas) continue;\n\n renderTasksRef.current.get(pageNum)?.cancel();\n\n try {\n const pdfPage = await pdf!.getPage(pageNum);\n if (cancelled) return;\n\n const viewport = pdfPage.getViewport({ scale });\n const dpr = window.devicePixelRatio || 1;\n\n canvas.width = Math.floor(viewport.width * dpr);\n canvas.height = Math.floor(viewport.height * dpr);\n canvas.style.width = `${viewport.width}px`;\n canvas.style.height = `${viewport.height}px`;\n\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) continue;\n\n const task = pdfPage.render({\n canvas,\n canvasContext: ctx,\n viewport,\n transform: dpr !== 1 ? [dpr, 0, 0, dpr, 0, 0] : undefined,\n });\n renderTasksRef.current.set(pageNum, task);\n await task.promise;\n } catch {\n // cancelled render — ignore\n }\n }\n }\n\n void renderAll();\n\n return () => {\n cancelled = true;\n renderTasksRef.current.forEach((t) => t.cancel());\n renderTasksRef.current.clear();\n };\n }, [pageSizes, scale]);\n\n // ── Scroll listener — track current page ──────────────────────────────────\n\n useEffect(() => {\n const container = scrollRef.current;\n if (!container || pageSizes.length === 0) return;\n\n function update() {\n const mid = container!.scrollTop + container!.clientHeight / 2;\n let found = 1;\n for (let i = 1; i <= pageSizes.length; i++) {\n const el = pageWrapperRefs.current.get(i);\n if (!el) continue;\n if (el.offsetTop <= mid) found = i;\n else break;\n }\n setCurrentPage(found);\n }\n\n update(); // set on mount\n container.addEventListener(\"scroll\", update, { passive: true });\n return () => container.removeEventListener(\"scroll\", update);\n }, [pageSizes.length]);\n\n // ── Fullscreen ──────────────────────────────────────────────────────────────\n\n useEffect(() => {\n function onChange() {\n setIsFullscreen(!!document.fullscreenElement);\n }\n document.addEventListener(\"fullscreenchange\", onChange);\n return () => document.removeEventListener(\"fullscreenchange\", onChange);\n }, []);\n\n // ── Ref callbacks ───────────────────────────────────────────────────────────\n\n const setPageWrapper = useCallback(\n (pageNum: number) => (el: HTMLDivElement | null) => {\n if (el) pageWrapperRefs.current.set(pageNum, el);\n else pageWrapperRefs.current.delete(pageNum);\n },\n [],\n );\n\n const setCanvas = useCallback(\n (pageNum: number) => (el: HTMLCanvasElement | null) => {\n if (el) canvasRefs.current.set(pageNum, el);\n else canvasRefs.current.delete(pageNum);\n },\n [],\n );\n\n // ── Actions ─────────────────────────────────────────────────────────────────\n\n const scrollToPage = useCallback(\n (n: number) => {\n const p = clamp(n, 1, numPages);\n const target = pageWrapperRefs.current.get(p);\n const container = scrollRef.current;\n if (!target || !container) return;\n container.scrollTop = target.offsetTop - PAGE_GAP;\n },\n [numPages],\n );\n\n const zoomTo = useCallback(\n (s: number) => setScale(clamp(s, MIN_SCALE, MAX_SCALE)),\n [],\n );\n\n function fitToWidth() {\n const container = scrollRef.current;\n if (!container || pageSizes.length === 0) return;\n const available = container.clientWidth - PAGE_GAP * 2;\n zoomTo(available / pageSizes[0].width);\n }\n\n function fitToHeight() {\n const container = scrollRef.current;\n if (!container || pageSizes.length === 0) return;\n const available = container.clientHeight - PAGE_GAP * 2;\n zoomTo(available / pageSizes[0].height);\n }\n\n function toggleFullscreen() {\n if (isFullscreen) document.exitFullscreen();\n else containerRef.current?.requestFullscreen();\n }\n\n function startEditingPage() {\n setPageInput(String(currentPage));\n setIsEditingPage(true);\n setTimeout(() => pageInputRef.current?.select(), 0);\n }\n\n function commitPageEdit() {\n const n = parseInt(pageInput, 10);\n if (!isNaN(n)) scrollToPage(n);\n setIsEditingPage(false);\n }\n\n function handlePageKey(e: KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Enter\") commitPageEdit();\n else if (e.key === \"Escape\") setIsEditingPage(false);\n }\n\n const canPrev = currentPage > 1;\n const canNext = currentPage < numPages;\n\n // Normalise the watermark prop into a config object (or undefined).\n const watermarkConfig: WatermarkConfig | undefined =\n watermark === undefined\n ? undefined\n : typeof watermark === \"string\"\n ? { text: watermark }\n : watermark;\n\n // ── Render ──────────────────────────────────────────────────────────────────\n\n return (\n <div\n ref={containerRef}\n className=\"flex h-full flex-col bg-white text-neutral-800 border border-gray-200\"\n >\n {/* ── Toolbar ──────────────────────────────────────────────────────── */}\n <div className=\"flex shrink-0 items-center gap-1 border-b border-neutral-200 bg-white px-3 py-2 shadow-sm\">\n {/* Prev page */}\n <button\n type=\"button\"\n onClick={() => scrollToPage(currentPage - 1)}\n disabled={!canPrev}\n title=\"Previous page\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <Icons.ChevronLeft size={18} />\n </button>\n\n {/* Page indicator / jump input */}\n {isEditingPage ? (\n <input\n ref={pageInputRef}\n type=\"number\"\n min={1}\n max={numPages}\n value={pageInput}\n onChange={(e) => setPageInput(e.target.value)}\n onBlur={commitPageEdit}\n onKeyDown={handlePageKey}\n className=\"w-14 rounded-md border border-neutral-300 bg-white px-2 py-0.5 text-center text-sm outline-none focus:border-blue-500\"\n />\n ) : (\n <button\n type=\"button\"\n onClick={numPages > 0 ? startEditingPage : undefined}\n disabled={numPages === 0}\n title=\"Click to jump to page\"\n className=\"flex items-center gap-1 rounded-md px-2 py-0.5 text-sm transition hover:bg-neutral-100 disabled:opacity-40\"\n >\n <span className=\"font-medium tabular-nums\">\n {numPages > 0 ? currentPage : \"—\"}\n </span>\n <span className=\"text-neutral-400\">/</span>\n <span className=\"tabular-nums text-neutral-500\">\n {numPages > 0 ? numPages : \"—\"}\n </span>\n </button>\n )}\n\n {/* Next page */}\n <button\n type=\"button\"\n onClick={() => scrollToPage(currentPage + 1)}\n disabled={!canNext}\n title=\"Next page\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <Icons.ChevronRight size={18} />\n </button>\n\n <div className=\"mx-2 h-5 w-px bg-neutral-200\" />\n\n {/* Zoom out */}\n <button\n type=\"button\"\n onClick={() => zoomTo(scale - ZOOM_STEP)}\n disabled={scale <= MIN_SCALE}\n title=\"Zoom out\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <Icons.ZoomOut size={16} />\n </button>\n\n {/* Zoom preset dropdown — always shows current value */}\n <select\n value={scale}\n onChange={(e) => zoomTo(parseFloat(e.target.value))}\n title=\"Zoom level\"\n className=\"w-[5.5rem] rounded-md border border-neutral-300 bg-white px-1.5 py-0.5 text-xs text-neutral-700 outline-none focus:border-blue-500\"\n >\n {!PRESETS.some((p) => Math.abs(p - scale) < 0.001) && (\n <option value={scale}>{Math.round(scale * 100)}%</option>\n )}\n {PRESETS.map((v) => (\n <option key={v} value={v}>\n {Math.round(v * 100)}%\n </option>\n ))}\n </select>\n\n {/* Zoom in */}\n <button\n type=\"button\"\n onClick={() => zoomTo(scale + ZOOM_STEP)}\n disabled={scale >= MAX_SCALE}\n title=\"Zoom in\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <Icons.ZoomIn size={16} />\n </button>\n\n <div className=\"mx-1 h-5 w-px bg-neutral-200\" />\n\n {/* Fit to width */}\n <button\n type=\"button\"\n onClick={fitToWidth}\n disabled={pageSizes.length === 0}\n title=\"Fit to width\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <Icons.ArrowLeftRight size={15} />\n </button>\n\n {/* Fit to height */}\n <button\n type=\"button\"\n onClick={fitToHeight}\n disabled={pageSizes.length === 0}\n title=\"Fit to height\"\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100 disabled:cursor-not-allowed disabled:opacity-30\"\n >\n <Icons.ArrowUpDown size={15} />\n </button>\n\n <div className=\"flex-1\" />\n\n {/* Fullscreen */}\n <button\n type=\"button\"\n onClick={toggleFullscreen}\n title={isFullscreen ? \"Exit fullscreen\" : \"Enter fullscreen\"}\n className=\"flex h-8 w-8 items-center justify-center rounded-md transition hover:bg-neutral-100\"\n >\n {isFullscreen ? (\n <Icons.Minimize size={16} />\n ) : (\n <Icons.Maximize size={16} />\n )}\n </button>\n </div>\n\n {/* ── Scroll area ──────────────────────────────────────────────────── */}\n <div\n ref={scrollRef}\n className=\"flex-1 overflow-y-auto overflow-x-auto bg-white\"\n >\n {/* Loading */}\n {loading && (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"flex flex-col items-center gap-3 text-neutral-400\">\n <Icons.Loader2 size={32} className=\"animate-spin\" />\n <span className=\"text-sm\">Loading document…</span>\n </div>\n </div>\n )}\n\n {/* Error */}\n {!loading && error && (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"flex flex-col items-center gap-3 rounded-xl border border-red-200 bg-red-50 px-8 py-10 text-red-600\">\n <Icons.AlertTriangle size={32} />\n <p className=\"max-w-xs text-center text-sm\">{error}</p>\n </div>\n </div>\n )}\n\n {/* Empty */}\n {!loading && !error && numPages === 0 && (\n <div className=\"flex h-full items-center justify-center\">\n <div className=\"flex flex-col items-center gap-3 text-neutral-300\">\n <Icons.FileText size={48} />\n <span className=\"text-sm\">No document loaded</span>\n </div>\n </div>\n )}\n\n {/* Pages */}\n {!loading && !error && pageSizes.length > 0 && (\n <div\n className=\"flex flex-col items-center py-4\"\n style={{ gap: PAGE_GAP }}\n >\n {pageSizes.map((size, idx) => {\n const pageNum = idx + 1;\n return (\n <div\n key={pageNum}\n ref={setPageWrapper(pageNum)}\n data-page={pageNum}\n className=\"relative flex-shrink-0\"\n style={{\n width: Math.floor(size.width * scale),\n height: Math.floor(size.height * scale),\n }}\n >\n <canvas\n ref={setCanvas(pageNum)}\n className=\"block shadow-md ring-1 ring-black/10\"\n />\n {watermarkConfig && (\n <WatermarkOverlay\n config={{\n ...watermarkConfig,\n fontSize: (watermarkConfig.fontSize ?? 28) * scale,\n gap: (watermarkConfig.gap ?? 80) * scale,\n }}\n width={Math.floor(size.width * scale)}\n height={Math.floor(size.height * scale)}\n />\n )}\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
package/dist/style.css ADDED
@@ -0,0 +1,3 @@
1
+ /*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-200:oklch(88.5% .062 18.334);--color-red-600:oklch(57.7% .245 27.325);--color-blue-500:oklch(62.3% .214 259.815);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-neutral-100:oklch(97% 0 0);--color-neutral-200:oklch(92.2% 0 0);--color-neutral-300:oklch(87% 0 0);--color-neutral-400:oklch(70.8% 0 0);--color-neutral-500:oklch(55.6% 0 0);--color-neutral-700:oklch(37.1% 0 0);--color-neutral-800:oklch(26.9% 0 0);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-xs:20rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--radius-md:.375rem;--radius-xl:.75rem;--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.table-cell{display:table-cell}.h-5{height:calc(var(--spacing) * 5)}.h-8{height:calc(var(--spacing) * 8)}.h-\[80vh\]{height:80vh}.h-full{height:100%}.h-screen{height:100vh}.max-h-screen{max-height:100vh}.w-1\/2{width:50%}.w-8{width:calc(var(--spacing) * 8)}.w-14{width:calc(var(--spacing) * 14)}.w-\[5\.5rem\]{width:5.5rem}.w-\[80vw\]{width:80vw}.w-full{width:100%}.w-px{width:1px}.max-w-xs{max-width:var(--container-xs)}.flex-1{flex:1}.flex-shrink-0,.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-spin{animation:var(--animate-spin)}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1{gap:calc(var(--spacing) * 1)}.gap-3{gap:calc(var(--spacing) * 3)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-neutral-200{border-color:var(--color-neutral-200)}.border-neutral-300{border-color:var(--color-neutral-300)}.border-red-200{border-color:var(--color-red-200)}.bg-black{background-color:var(--color-black)}.bg-neutral-200{background-color:var(--color-neutral-200)}.bg-red-50{background-color:var(--color-red-50)}.bg-white{background-color:var(--color-white)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-8{padding-inline:calc(var(--spacing) * 8)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-10{padding-block:calc(var(--spacing) * 10)}.text-center{text-align:center}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.text-neutral-300{color:var(--color-neutral-300)}.text-neutral-400{color:var(--color-neutral-400)}.text-neutral-500{color:var(--color-neutral-500)}.text-neutral-700{color:var(--color-neutral-700)}.text-neutral-800{color:var(--color-neutral-800)}.text-red-600{color:var(--color-red-600)}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.line-through{text-decoration-line:line-through}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-black\/10{--tw-ring-color:#0000001a}@supports (color:color-mix(in lab, red, red)){.ring-black\/10{--tw-ring-color:color-mix(in oklab, var(--color-black) 10%, transparent)}}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.hover\:bg-neutral-100:hover{background-color:var(--color-neutral-100)}}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}
3
+ /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monime/pdfio",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "A simple custom PDF viewer component for React.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -34,7 +34,6 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@tailwindcss/vite": "^4.3.0",
37
- "lucide-react": "^1.14.0",
38
37
  "tailwindcss": "^4.3.0"
39
38
  },
40
39
  "devDependencies": {