@cannyminds/dms-file-viewers 0.11.0 → 0.13.0

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.
Files changed (73) hide show
  1. package/dist/{chunk-XBIKN46C.js → chunk-7QRYWFCO.js} +96 -57
  2. package/dist/chunk-7QRYWFCO.js.map +1 -0
  3. package/dist/{chunk-KBST5Z5H.mjs → chunk-7R2KG3PE.mjs} +2 -2
  4. package/dist/{chunk-7AUCINV2.mjs → chunk-CFYOPDCG.mjs} +2 -2
  5. package/dist/{chunk-57BAESSV.mjs → chunk-D74R4IKW.mjs} +2 -2
  6. package/dist/{chunk-VJFXCN5Z.mjs → chunk-DFBVN4MO.mjs} +5 -2
  7. package/dist/chunk-DFBVN4MO.mjs.map +1 -0
  8. package/dist/{chunk-ETHSDRF5.js → chunk-EXZCEYLI.js} +4 -4
  9. package/dist/{chunk-ETHSDRF5.js.map → chunk-EXZCEYLI.js.map} +1 -1
  10. package/dist/{chunk-FA5L62Y5.js → chunk-J3JKVSAM.js} +5 -2
  11. package/dist/chunk-J3JKVSAM.js.map +1 -0
  12. package/dist/{chunk-WNZHGFNC.mjs → chunk-NXVIRFGL.mjs} +2 -2
  13. package/dist/{chunk-THFHTTQX.mjs → chunk-P2VNW6OE.mjs} +2 -2
  14. package/dist/{chunk-QNDIZUU5.mjs → chunk-P5FH7LK7.mjs} +94 -55
  15. package/dist/chunk-P5FH7LK7.mjs.map +1 -0
  16. package/dist/{chunk-ORL5FTAW.mjs → chunk-PZJSY6OF.mjs} +51 -3
  17. package/dist/chunk-PZJSY6OF.mjs.map +1 -0
  18. package/dist/{chunk-LQVHD4FS.js → chunk-RVHIXSUP.js} +4 -4
  19. package/dist/{chunk-LQVHD4FS.js.map → chunk-RVHIXSUP.js.map} +1 -1
  20. package/dist/{chunk-QGM5J3SP.js → chunk-TGVFAAIP.js} +4 -4
  21. package/dist/{chunk-QGM5J3SP.js.map → chunk-TGVFAAIP.js.map} +1 -1
  22. package/dist/{chunk-RSCUIGVW.js → chunk-VOLQW3NF.js} +99 -51
  23. package/dist/chunk-VOLQW3NF.js.map +1 -0
  24. package/dist/{chunk-UUM656JE.js → chunk-VSGX22FQ.js} +4 -4
  25. package/dist/{chunk-UUM656JE.js.map → chunk-VSGX22FQ.js.map} +1 -1
  26. package/dist/{chunk-56PP5GHZ.js → chunk-WCAXWJE7.js} +4 -4
  27. package/dist/{chunk-56PP5GHZ.js.map → chunk-WCAXWJE7.js.map} +1 -1
  28. package/dist/components/viewers/AudioViewer.d.mts +1 -1
  29. package/dist/components/viewers/AudioViewer.d.ts +1 -1
  30. package/dist/components/viewers/AudioViewer.js +3 -3
  31. package/dist/components/viewers/AudioViewer.mjs +2 -2
  32. package/dist/components/viewers/DefaultViewer.d.mts +1 -1
  33. package/dist/components/viewers/DefaultViewer.d.ts +1 -1
  34. package/dist/components/viewers/DefaultViewer.js +3 -3
  35. package/dist/components/viewers/DefaultViewer.mjs +2 -2
  36. package/dist/components/viewers/ImageViewer.d.mts +1 -1
  37. package/dist/components/viewers/ImageViewer.d.ts +1 -1
  38. package/dist/components/viewers/ImageViewer.js +3 -3
  39. package/dist/components/viewers/ImageViewer.mjs +2 -2
  40. package/dist/components/viewers/PDFViewer.d.mts +4 -1
  41. package/dist/components/viewers/PDFViewer.d.ts +4 -1
  42. package/dist/components/viewers/PDFViewer.js +3 -3
  43. package/dist/components/viewers/PDFViewer.mjs +2 -2
  44. package/dist/components/viewers/TIFFViewer.d.mts +1 -1
  45. package/dist/components/viewers/TIFFViewer.d.ts +1 -1
  46. package/dist/components/viewers/TIFFViewer.js +3 -3
  47. package/dist/components/viewers/TIFFViewer.mjs +2 -2
  48. package/dist/components/viewers/TextViewer.d.mts +1 -1
  49. package/dist/components/viewers/TextViewer.d.ts +1 -1
  50. package/dist/components/viewers/TextViewer.js +3 -3
  51. package/dist/components/viewers/TextViewer.mjs +2 -2
  52. package/dist/components/viewers/VideoViewer.d.mts +1 -1
  53. package/dist/components/viewers/VideoViewer.d.ts +1 -1
  54. package/dist/components/viewers/VideoViewer.js +3 -3
  55. package/dist/components/viewers/VideoViewer.mjs +2 -2
  56. package/dist/index.d.mts +2 -2
  57. package/dist/index.d.ts +2 -2
  58. package/dist/index.js +9 -9
  59. package/dist/index.mjs +8 -8
  60. package/dist/{types-CQIoF7E1.d.mts → types-DNrkDJdK.d.mts} +1 -0
  61. package/dist/{types-CQIoF7E1.d.ts → types-DNrkDJdK.d.ts} +1 -0
  62. package/package.json +2 -2
  63. package/dist/chunk-FA5L62Y5.js.map +0 -1
  64. package/dist/chunk-ORL5FTAW.mjs.map +0 -1
  65. package/dist/chunk-QNDIZUU5.mjs.map +0 -1
  66. package/dist/chunk-RSCUIGVW.js.map +0 -1
  67. package/dist/chunk-VJFXCN5Z.mjs.map +0 -1
  68. package/dist/chunk-XBIKN46C.js.map +0 -1
  69. /package/dist/{chunk-KBST5Z5H.mjs.map → chunk-7R2KG3PE.mjs.map} +0 -0
  70. /package/dist/{chunk-7AUCINV2.mjs.map → chunk-CFYOPDCG.mjs.map} +0 -0
  71. /package/dist/{chunk-57BAESSV.mjs.map → chunk-D74R4IKW.mjs.map} +0 -0
  72. /package/dist/{chunk-WNZHGFNC.mjs.map → chunk-NXVIRFGL.mjs.map} +0 -0
  73. /package/dist/{chunk-THFHTTQX.mjs.map → chunk-P2VNW6OE.mjs.map} +0 -0
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  FileIcon_default,
7
7
  mergeToolbarConfig
8
- } from "./chunk-VJFXCN5Z.mjs";
8
+ } from "./chunk-DFBVN4MO.mjs";
9
9
 
10
10
  // src/components/viewers/TIFFViewer.tsx
11
11
  import {
@@ -101,8 +101,10 @@ var TIFFViewerContent = ({
101
101
  const [imageUrl, setImageUrl] = useState(null);
102
102
  const [pageImages, setPageImages] = useState(/* @__PURE__ */ new Map());
103
103
  const [internalLoading, setInternalLoading] = useState(false);
104
+ const [imageSize, setImageSize] = useState(null);
104
105
  const viewportRef = useRef(null);
105
106
  const containerRef = useRef(null);
107
+ const imgRef = useRef(null);
106
108
  const pageLoaderRef = useRef(pageLoader);
107
109
  useEffect(() => {
108
110
  pageLoaderRef.current = pageLoader;
@@ -241,12 +243,33 @@ var TIFFViewerContent = ({
241
243
  }, []);
242
244
  const hasImage = !!imageUrl;
243
245
  const hasMultiplePages = totalPages > 1;
246
+ const MARGIN = 40;
247
+ const MIN_ZOOM = 25;
248
+ const MAX_ZOOM = 400;
249
+ const ZOOM_LEVELS = [25, 50, 75, 100, 125, 150, 200, 300, 400];
250
+ const calculateFitZoom = useCallback((mode) => {
251
+ if (!imageSize || viewportWidth <= 0) return null;
252
+ const availableWidth = viewportWidth - MARGIN;
253
+ if (mode === "fit-width") {
254
+ const calculatedZoom = Math.round(availableWidth / imageSize.width * 100);
255
+ return Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, calculatedZoom));
256
+ }
257
+ if (mode === "fit-page" && viewportHeight > 0) {
258
+ const availableHeight = viewportHeight - MARGIN;
259
+ const scaleW = availableWidth / imageSize.width;
260
+ const scaleH = availableHeight / imageSize.height;
261
+ const calculatedZoom = Math.round(Math.min(scaleW, scaleH) * 100);
262
+ return Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, calculatedZoom));
263
+ }
264
+ return null;
265
+ }, [imageSize, viewportWidth, viewportHeight]);
244
266
  useEffect(() => {
245
- if (hasImage) {
246
- setZoom(100);
247
- setFitMode("fit-page");
267
+ if (!hasImage || !imageSize) return;
268
+ const newZoom = calculateFitZoom(fitMode);
269
+ if (newZoom !== null) {
270
+ setZoom(newZoom);
248
271
  }
249
- }, [currentPage, hasImage]);
272
+ }, [currentPage, hasImage, imageSize, fitMode, calculateFitZoom]);
250
273
  useEffect(() => {
251
274
  if (typeof window === "undefined" || typeof ResizeObserver === "undefined") {
252
275
  return void 0;
@@ -271,27 +294,31 @@ var TIFFViewerContent = ({
271
294
  const handleZoomIn = useCallback(() => {
272
295
  setFitMode("zoom");
273
296
  setZoom((value) => {
274
- if (value < 100) return Math.min(value + 25, 100);
275
- if (value < 200) return Math.min(value + 50, 200);
276
- return Math.min(value + 100, 500);
297
+ const nextLevel = ZOOM_LEVELS.find((level) => level > value);
298
+ return nextLevel || MAX_ZOOM;
277
299
  });
278
300
  }, []);
279
301
  const handleZoomOut = useCallback(() => {
280
302
  setFitMode("zoom");
281
303
  setZoom((value) => {
282
- if (value <= 100) return Math.max(value - 25, 25);
283
- if (value <= 200) return Math.max(value - 50, 100);
284
- return Math.max(value - 100, 200);
304
+ const prevLevel = [...ZOOM_LEVELS].reverse().find((level) => level < value);
305
+ return prevLevel || MIN_ZOOM;
285
306
  });
286
307
  }, []);
287
308
  const handleFitWidth = useCallback(() => {
288
309
  setFitMode("fit-width");
289
- setZoom(100);
290
- }, []);
310
+ const newZoom = calculateFitZoom("fit-width");
311
+ if (newZoom !== null) {
312
+ setZoom(newZoom);
313
+ }
314
+ }, [calculateFitZoom]);
291
315
  const handleFitPage = useCallback(() => {
292
316
  setFitMode("fit-page");
293
- setZoom(100);
294
- }, []);
317
+ const newZoom = calculateFitZoom("fit-page");
318
+ if (newZoom !== null) {
319
+ setZoom(newZoom);
320
+ }
321
+ }, [calculateFitZoom]);
295
322
  const handleFirstPage = useCallback(() => {
296
323
  handlePageChange(1);
297
324
  }, [handlePageChange]);
@@ -321,47 +348,51 @@ var TIFFViewerContent = ({
321
348
  }, [isFullScreen]);
322
349
  const toolbar = mergeToolbarConfig({ showDownload, showPrint, showMetadata, showProperties, onDownloadClick, onPrintClick, onMetadataClick, onPropertiesClick, toolbarActions });
323
350
  const displayScale = zoom;
351
+ const handleImageLoad = useCallback((e) => {
352
+ const img = e.currentTarget;
353
+ setImageSize({ width: img.naturalWidth, height: img.naturalHeight });
354
+ if (!hasImage) {
355
+ onLoad?.();
356
+ }
357
+ }, [hasImage, onLoad]);
324
358
  const renderImage = () => {
325
359
  if (!imageUrl) {
326
360
  return /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: "No image available." });
327
361
  }
362
+ let imgStyle = {
363
+ display: "block",
364
+ borderRadius: "4px"
365
+ };
366
+ if (imageSize) {
367
+ const zoomFactor = zoom / 100;
368
+ const scaledWidth = imageSize.width * zoomFactor;
369
+ const scaledHeight = imageSize.height * zoomFactor;
370
+ imgStyle = {
371
+ ...imgStyle,
372
+ width: `${scaledWidth}px`,
373
+ height: `${scaledHeight}px`,
374
+ maxWidth: "none",
375
+ maxHeight: "none"
376
+ };
377
+ }
328
378
  return /* @__PURE__ */ jsx(
329
379
  Box,
330
380
  {
381
+ component: "img",
382
+ ref: imgRef,
383
+ src: imageUrl,
384
+ alt: `${resolvedFileName} page ${currentPage}`,
385
+ onLoad: handleImageLoad,
386
+ onError: () => {
387
+ setError("Failed to load image");
388
+ onError?.(new Error("Failed to load image"));
389
+ },
331
390
  sx: {
332
- position: "relative",
333
- borderRadius: 1,
391
+ ...imgStyle,
334
392
  boxShadow: 1,
335
393
  backgroundColor: "#fff",
336
- display: "flex",
337
- justifyContent: "center",
338
- alignItems: "center"
339
- },
340
- children: /* @__PURE__ */ jsx(
341
- Box,
342
- {
343
- component: "img",
344
- src: imageUrl,
345
- alt: `${resolvedFileName} page ${currentPage}`,
346
- sx: {
347
- maxWidth: fitMode === "fit-width" ? "100%" : "none",
348
- maxHeight: fitMode === "fit-page" ? "100%" : "none",
349
- width: fitMode === "zoom" ? `${zoom}%` : "auto",
350
- height: "auto",
351
- display: "block",
352
- borderRadius: 1
353
- },
354
- onLoad: () => {
355
- if (!hasImage) {
356
- onLoad?.();
357
- }
358
- },
359
- onError: () => {
360
- setError("Failed to load image");
361
- onError?.(new Error("Failed to load image"));
362
- }
363
- }
364
- )
394
+ margin: "20px"
395
+ }
365
396
  }
366
397
  );
367
398
  };
@@ -447,7 +478,7 @@ var TIFFViewerContent = ({
447
478
  {
448
479
  size: "small",
449
480
  onClick: handleZoomOut,
450
- disabled: !hasImage || zoom <= 0.25,
481
+ disabled: !hasImage || zoom <= 25,
451
482
  title: "Zoom Out",
452
483
  "aria-label": "Zoom out",
453
484
  children: /* @__PURE__ */ jsx(ZoomOutIcon, { fontSize: "small" })
@@ -459,7 +490,7 @@ var TIFFViewerContent = ({
459
490
  {
460
491
  size: "small",
461
492
  onClick: handleZoomIn,
462
- disabled: !hasImage || zoom >= 5,
493
+ disabled: !hasImage || zoom >= 400,
463
494
  title: "Zoom In",
464
495
  "aria-label": "Zoom in",
465
496
  children: /* @__PURE__ */ jsx(ZoomInIcon, { fontSize: "small" })
@@ -557,7 +588,7 @@ var TIFFViewerContent = ({
557
588
  flexShrink: 1,
558
589
  minHeight: 0,
559
590
  p: 0,
560
- overflow: "auto",
591
+ overflow: "hidden",
561
592
  backgroundColor: "#f6f8fa",
562
593
  position: "relative"
563
594
  },
@@ -571,13 +602,21 @@ var TIFFViewerContent = ({
571
602
  left: 0,
572
603
  right: 0,
573
604
  bottom: 0,
574
- display: "flex",
575
- alignItems: "center",
576
- justifyContent: "center",
577
- p: 3,
578
605
  overflow: "auto"
579
606
  },
580
- children: renderImage()
607
+ children: /* @__PURE__ */ jsx(
608
+ Box,
609
+ {
610
+ sx: {
611
+ minWidth: "100%",
612
+ minHeight: "100%",
613
+ display: "flex",
614
+ alignItems: "center",
615
+ justifyContent: "center"
616
+ },
617
+ children: renderImage()
618
+ }
619
+ )
581
620
  }
582
621
  )
583
622
  }
@@ -597,4 +636,4 @@ var TIFFViewer = (props) => {
597
636
  export {
598
637
  TIFFViewer
599
638
  };
600
- //# sourceMappingURL=chunk-QNDIZUU5.mjs.map
639
+ //# sourceMappingURL=chunk-P5FH7LK7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/viewers/TIFFViewer.tsx"],"sourcesContent":["import React, {\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState\r\n} from 'react';\r\nimport {\r\n Box,\r\n Button,\r\n ButtonGroup,\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n Divider,\r\n LinearProgress,\r\n Stack,\r\n Typography,\r\n IconButton,\r\n Tooltip\r\n} from '@mui/material';\r\nimport DownloadIcon from '@mui/icons-material/Download';\r\nimport PrintIcon from '@mui/icons-material/Print';\r\nimport FullscreenIcon from '@mui/icons-material/Fullscreen';\r\nimport FirstPageIcon from '@mui/icons-material/FirstPage';\r\nimport LastPageIcon from '@mui/icons-material/LastPage';\r\nimport ChevronLeftIcon from '@mui/icons-material/ChevronLeft';\r\nimport ChevronRightIcon from '@mui/icons-material/ChevronRight';\r\nimport ZoomInIcon from '@mui/icons-material/ZoomIn';\r\nimport ZoomOutIcon from '@mui/icons-material/ZoomOut';\r\nimport FitScreenIcon from '@mui/icons-material/FitScreen';\r\nimport AspectRatioIcon from '@mui/icons-material/AspectRatio';\r\nimport InfoIcon from '@mui/icons-material/Info';\r\nimport DescriptionIcon from '@mui/icons-material/Description';\r\nimport { FileViewerProps } from '../../types';\r\nimport { getFileExtension } from '../../utils/fileUtils';\r\nimport { mergeToolbarConfig } from '../../utils/toolbarUtils';\r\nimport FileIcon from '../FileIcon';\r\n\r\nconst resolveDocumentName = (file?: File, fileName?: string, url?: string) => {\r\n if (file?.name) {\r\n return file.name;\r\n }\r\n if (fileName) {\r\n return fileName;\r\n }\r\n if (url) {\r\n const parts = url.split('?')[0]?.split('#')[0]?.split('/') ?? [];\r\n return parts[parts.length - 1] || 'document.tiff';\r\n }\r\n return 'document.tiff';\r\n};\r\n\r\ninterface TIFFViewerContentProps extends FileViewerProps {\r\n sourceDescription: string;\r\n}\r\n\r\nconst TIFFViewerContent: React.FC<TIFFViewerContentProps> = ({\r\n sourceDescription,\r\n file,\r\n url,\r\n fileName,\r\n totalPages = 1,\r\n className = '',\r\n style = {},\r\n width = '100%',\r\n height = '100%',\r\n onLoad,\r\n onError,\r\n onDownloadClick,\r\n onPrintClick,\r\n onMetadataClick,\r\n onPropertiesClick,\r\n pageLoader,\r\n showDownload = true,\r\n showPrint = true,\r\n showMetadata = false,\r\n showProperties = false,\r\n // Extract props that shouldn't be passed to DOM elements\r\n mimeType,\r\n fileSize,\r\n showPageCount,\r\n showPageNavigation,\r\n showZoomControls,\r\n showSearch,\r\n customRegistry,\r\n initialSearchText,\r\n initialSearchPages,\r\n autoOpenSearch,\r\n autoExecuteSearch,\r\n onSearchComplete,\r\n toolbarActions,\r\n ...props\r\n}) => {\r\n const [currentPage, setCurrentPage] = useState(1);\r\n const [isLoading, setIsLoading] = useState(false);\r\n const [error, setError] = useState<string | null>(null);\r\n const [fitMode, setFitMode] = useState<'fit-width' | 'fit-page' | 'zoom'>('fit-page');\r\n const [zoom, setZoom] = useState(100);\r\n const [viewportWidth, setViewportWidth] = useState<number>(0);\r\n const [viewportHeight, setViewportHeight] = useState<number>(0);\r\n const [isFullScreen, setIsFullScreen] = useState(false);\r\n const [imageUrl, setImageUrl] = useState<string | null>(null);\r\n const [pageImages, setPageImages] = useState<Map<number, string>>(new Map());\r\n const [internalLoading, setInternalLoading] = useState(false);\r\n const [imageSize, setImageSize] = useState<{ width: number; height: number } | null>(null);\r\n\r\n const viewportRef = useRef<HTMLDivElement | null>(null);\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const imgRef = useRef<HTMLImageElement | null>(null);\r\n \r\n // Store pageLoader in ref to prevent re-renders\r\n const pageLoaderRef = useRef(pageLoader);\r\n useEffect(() => {\r\n pageLoaderRef.current = pageLoader;\r\n }, [pageLoader]);\r\n\r\n // Update page image from ArrayBuffer data\r\n const updatePageImage = useCallback((pageData: ArrayBuffer, pageNumber: number) => {\r\n const blob = new Blob([pageData]);\r\n const imageUrl = URL.createObjectURL(blob);\r\n \r\n setPageImages(prev => {\r\n // Only clean up old URL if we're replacing with a different one\r\n const oldUrl = prev.get(pageNumber);\r\n if (oldUrl && oldUrl !== imageUrl) {\r\n URL.revokeObjectURL(oldUrl);\r\n }\r\n return new Map(prev).set(pageNumber, imageUrl);\r\n });\r\n setCurrentPage(pageNumber);\r\n setImageUrl(imageUrl);\r\n }, []);\r\n\r\n // Load initial page when pageLoader is available\r\n useEffect(() => {\r\n const loadInitialPage = async () => {\r\n if (pageLoaderRef.current && !pageImages.has(1) && currentPage === 1) {\r\n setInternalLoading(true);\r\n setError(null);\r\n \r\n try {\r\n const pageData = await pageLoaderRef.current(1);\r\n if (pageData) {\r\n updatePageImage(pageData, 1);\r\n } else {\r\n setError('Failed to load page 1');\r\n }\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : 'Unable to load page 1';\r\n setError(message);\r\n onError?.(new Error(message));\r\n } finally {\r\n setInternalLoading(false);\r\n }\r\n }\r\n };\r\n\r\n loadInitialPage();\r\n }, [pageImages, currentPage, updatePageImage, onError]);\r\n\r\n // Handle internal page navigation\r\n const handlePageChange = useCallback(async (newPageNumber: number) => {\r\n if (!pageLoaderRef.current) {\r\n console.warn('pageLoader not provided - page navigation disabled');\r\n return;\r\n }\r\n\r\n // Check if page is already cached\r\n const cachedUrl = pageImages.get(newPageNumber);\r\n if (cachedUrl) {\r\n setCurrentPage(newPageNumber);\r\n setImageUrl(cachedUrl);\r\n return;\r\n }\r\n\r\n setInternalLoading(true);\r\n setError(null);\r\n \r\n try {\r\n const pageData = await pageLoaderRef.current(newPageNumber);\r\n if (pageData) {\r\n updatePageImage(pageData, newPageNumber);\r\n } else {\r\n setError(`Failed to load page ${newPageNumber}`);\r\n }\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : `Unable to load page ${newPageNumber}`;\r\n setError(message);\r\n onError?.(new Error(message));\r\n } finally {\r\n setInternalLoading(false);\r\n }\r\n }, [pageImages, onError, updatePageImage]);\r\n\r\n const resolvedFileName = useMemo(\r\n () => fileName || sourceDescription,\r\n [fileName, sourceDescription]\r\n );\r\n\r\n const fileExtension = useMemo(\r\n () => getFileExtension(resolvedFileName || ''),\r\n [resolvedFileName]\r\n );\r\n\r\n const loadImage = useCallback(async (resetPage = false) => {\r\n if (!file && !url) {\r\n setImageUrl(null);\r\n if (resetPage) setCurrentPage(1);\r\n setError(null);\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n setError(null);\r\n\r\n try {\r\n let imageDataUrl: string;\r\n if (file) {\r\n imageDataUrl = URL.createObjectURL(file);\r\n } else if (url) {\r\n imageDataUrl = url;\r\n } else {\r\n throw new Error('No file or URL provided');\r\n }\r\n\r\n setImageUrl(imageDataUrl);\r\n if (resetPage) {\r\n setCurrentPage(1);\r\n setFitMode('fit-page');\r\n setZoom(100);\r\n }\r\n onLoad?.();\r\n } catch (err) {\r\n const message = err instanceof Error ? err.message : 'Unable to load image file';\r\n setError(message);\r\n setImageUrl(null);\r\n if (resetPage) {\r\n setCurrentPage(1);\r\n setFitMode('fit-width');\r\n setZoom(100);\r\n }\r\n onError?.(new Error(message));\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [file, url, onLoad, onError]);\r\n\r\n const [previousFileSource, setPreviousFileSource] = useState<{ file?: File; url?: string }>({});\r\n\r\n useEffect(() => {\r\n const currentFileSource = { file, url };\r\n const isNewFile = previousFileSource.file !== file || previousFileSource.url !== url;\r\n \r\n if (isNewFile) {\r\n setPreviousFileSource(currentFileSource);\r\n void loadImage(true); // Reset page on new file\r\n } else {\r\n void loadImage(false); // Don't reset page for same file\r\n }\r\n }, [file, url, loadImage, previousFileSource.file, previousFileSource.url]);\r\n\r\n useEffect(() => {\r\n return () => {\r\n // Clean up all cached page URLs only on unmount\r\n pageImages.forEach((url) => {\r\n URL.revokeObjectURL(url);\r\n });\r\n // Clean up current image URL if it's from a file (not from pageLoader)\r\n if (imageUrl && file && !pageImages.has(currentPage)) {\r\n URL.revokeObjectURL(imageUrl);\r\n }\r\n };\r\n }, []); // Empty dependency array - only cleanup on unmount\r\n\r\n const hasImage = !!imageUrl;\r\n const hasMultiplePages = totalPages > 1;\r\n\r\n // Constants for zoom calculation\r\n const MARGIN = 40;\r\n const MIN_ZOOM = 25;\r\n const MAX_ZOOM = 400;\r\n const ZOOM_LEVELS = [25, 50, 75, 100, 125, 150, 200, 300, 400];\r\n\r\n // Helper function to calculate zoom based on fit mode\r\n const calculateFitZoom = useCallback((mode: 'fit-width' | 'fit-page'): number | null => {\r\n if (!imageSize || viewportWidth <= 0) return null;\r\n\r\n const availableWidth = viewportWidth - MARGIN;\r\n\r\n if (mode === 'fit-width') {\r\n const calculatedZoom = Math.round((availableWidth / imageSize.width) * 100);\r\n return Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, calculatedZoom));\r\n }\r\n\r\n if (mode === 'fit-page' && viewportHeight > 0) {\r\n const availableHeight = viewportHeight - MARGIN;\r\n const scaleW = availableWidth / imageSize.width;\r\n const scaleH = availableHeight / imageSize.height;\r\n const calculatedZoom = Math.round(Math.min(scaleW, scaleH) * 100);\r\n return Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, calculatedZoom));\r\n }\r\n\r\n return null;\r\n }, [imageSize, viewportWidth, viewportHeight]);\r\n\r\n // Recalculate zoom when changing pages in fit modes\r\n useEffect(() => {\r\n if (!hasImage || !imageSize) return;\r\n\r\n const newZoom = calculateFitZoom(fitMode as 'fit-width' | 'fit-page');\r\n if (newZoom !== null) {\r\n setZoom(newZoom);\r\n }\r\n }, [currentPage, hasImage, imageSize, fitMode, calculateFitZoom]);\r\n\r\n useEffect(() => {\r\n if (typeof window === 'undefined' || typeof ResizeObserver === 'undefined') {\r\n return undefined;\r\n }\r\n\r\n if (!viewportRef.current) {\r\n return undefined;\r\n }\r\n\r\n const updateSize = () => {\r\n const bounds = viewportRef.current?.getBoundingClientRect();\r\n if (bounds) {\r\n setViewportWidth(bounds.width);\r\n setViewportHeight(bounds.height);\r\n }\r\n };\r\n\r\n updateSize();\r\n const observer = new ResizeObserver(updateSize);\r\n observer.observe(viewportRef.current);\r\n\r\n return () => {\r\n observer.disconnect();\r\n };\r\n }, []);\r\n\r\n const handleZoomIn = useCallback(() => {\r\n setFitMode('zoom');\r\n setZoom((value) => {\r\n const nextLevel = ZOOM_LEVELS.find(level => level > value);\r\n return nextLevel || MAX_ZOOM;\r\n });\r\n }, []);\r\n\r\n const handleZoomOut = useCallback(() => {\r\n setFitMode('zoom');\r\n setZoom((value) => {\r\n const prevLevel = [...ZOOM_LEVELS].reverse().find(level => level < value);\r\n return prevLevel || MIN_ZOOM;\r\n });\r\n }, []);\r\n\r\n const handleFitWidth = useCallback(() => {\r\n setFitMode('fit-width');\r\n const newZoom = calculateFitZoom('fit-width');\r\n if (newZoom !== null) {\r\n setZoom(newZoom);\r\n }\r\n }, [calculateFitZoom]);\r\n\r\n const handleFitPage = useCallback(() => {\r\n setFitMode('fit-page');\r\n const newZoom = calculateFitZoom('fit-page');\r\n if (newZoom !== null) {\r\n setZoom(newZoom);\r\n }\r\n }, [calculateFitZoom]);\r\n\r\n const handleFirstPage = useCallback(() => {\r\n handlePageChange(1);\r\n }, [handlePageChange]);\r\n\r\n const handleLastPage = useCallback(() => {\r\n handlePageChange(totalPages);\r\n }, [handlePageChange, totalPages]);\r\n\r\n const handlePreviousPage = useCallback(() => {\r\n const newPage = Math.max(currentPage - 1, 1);\r\n if (newPage !== currentPage) {\r\n handlePageChange(newPage);\r\n }\r\n }, [currentPage, handlePageChange]);\r\n\r\n const handleNextPage = useCallback(() => {\r\n const newPage = Math.min(currentPage + 1, totalPages);\r\n if (newPage !== currentPage) {\r\n handlePageChange(newPage);\r\n }\r\n }, [currentPage, totalPages, handlePageChange]);\r\n\r\n const handleToggleFullScreen = useCallback(() => {\r\n if (!isFullScreen && containerRef.current?.requestFullscreen) {\r\n containerRef.current.requestFullscreen();\r\n setIsFullScreen(true);\r\n } else if (isFullScreen && document.exitFullscreen) {\r\n document.exitFullscreen();\r\n setIsFullScreen(false);\r\n }\r\n }, [isFullScreen]);\r\n\r\n const toolbar = mergeToolbarConfig({ showDownload, showPrint, showMetadata, showProperties, onDownloadClick, onPrintClick, onMetadataClick, onPropertiesClick, toolbarActions });\r\n\r\n const displayScale = zoom;\r\n\r\n const handleImageLoad = useCallback((e: React.SyntheticEvent<HTMLImageElement>) => {\r\n const img = e.currentTarget;\r\n setImageSize({ width: img.naturalWidth, height: img.naturalHeight });\r\n if (!hasImage) {\r\n onLoad?.();\r\n }\r\n }, [hasImage, onLoad]);\r\n\r\n const renderImage = () => {\r\n if (!imageUrl) {\r\n return (\r\n <Typography variant=\"body2\" color=\"text.secondary\">\r\n No image available.\r\n </Typography>\r\n );\r\n }\r\n\r\n // Calculate scaled dimensions based on zoom\r\n let imgStyle: React.CSSProperties = {\r\n display: 'block',\r\n borderRadius: '4px',\r\n };\r\n\r\n if (imageSize) {\r\n // Always use zoom-based calculation for consistent behavior\r\n const zoomFactor = zoom / 100;\r\n const scaledWidth = imageSize.width * zoomFactor;\r\n const scaledHeight = imageSize.height * zoomFactor;\r\n imgStyle = {\r\n ...imgStyle,\r\n width: `${scaledWidth}px`,\r\n height: `${scaledHeight}px`,\r\n maxWidth: 'none',\r\n maxHeight: 'none',\r\n };\r\n }\r\n\r\n return (\r\n <Box\r\n component=\"img\"\r\n ref={imgRef}\r\n src={imageUrl}\r\n alt={`${resolvedFileName} page ${currentPage}`}\r\n onLoad={handleImageLoad}\r\n onError={() => {\r\n setError('Failed to load image');\r\n onError?.(new Error('Failed to load image'));\r\n }}\r\n sx={{\r\n ...imgStyle,\r\n boxShadow: 1,\r\n backgroundColor: '#fff',\r\n margin: '20px',\r\n }}\r\n />\r\n );\r\n };\r\n\r\n return (\r\n <Box\r\n ref={containerRef}\r\n className={`tiff-viewer ${className}`}\r\n sx={{\r\n width,\r\n height,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n overflow: 'hidden',\r\n ...style\r\n }}\r\n {...props}\r\n >\r\n <Card sx={{ height: '100%', width: '100%', display: 'flex', flexDirection: 'column', overflow: 'hidden' }} elevation={1}>\r\n <CardHeader\r\n avatar={<FileIcon ext={fileExtension} size={32} />}\r\n title={\r\n <Typography variant=\"subtitle1\" fontWeight={500}>\r\n {resolvedFileName}\r\n </Typography>\r\n }\r\n sx={{ pb: 1 }}\r\n />\r\n\r\n {/* Toolbar - All Controls at Top (Centered) */}\r\n <Box sx={{ px: 2, pb: 1, display: 'flex', justifyContent: 'center' }}>\r\n <Stack direction=\"row\" spacing={1} alignItems=\"center\" flexWrap=\"wrap\" gap={1}>\r\n {/* Page Navigation */}\r\n {hasMultiplePages && (\r\n <>\r\n <IconButton\r\n size=\"small\"\r\n onClick={handleFirstPage}\r\n disabled={currentPage === 1}\r\n title=\"First Page\"\r\n aria-label=\"Go to first page\"\r\n >\r\n <FirstPageIcon fontSize=\"small\" />\r\n </IconButton>\r\n <IconButton\r\n size=\"small\"\r\n onClick={handlePreviousPage}\r\n disabled={currentPage === 1}\r\n title=\"Previous Page\"\r\n aria-label=\"Go to previous page\"\r\n >\r\n <ChevronLeftIcon fontSize=\"small\" />\r\n </IconButton>\r\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ minWidth: 100, textAlign: 'center' }}>\r\n Page {currentPage} of {totalPages}\r\n </Typography>\r\n <IconButton\r\n size=\"small\"\r\n onClick={handleNextPage}\r\n disabled={currentPage === totalPages}\r\n title=\"Next Page\"\r\n aria-label=\"Go to next page\"\r\n >\r\n <ChevronRightIcon fontSize=\"small\" />\r\n </IconButton>\r\n <IconButton\r\n size=\"small\"\r\n onClick={handleLastPage}\r\n disabled={currentPage === totalPages}\r\n title=\"Last Page\"\r\n aria-label=\"Go to last page\"\r\n >\r\n <LastPageIcon fontSize=\"small\" />\r\n </IconButton>\r\n <Divider orientation=\"vertical\" flexItem sx={{ mx: 1 }} />\r\n </>\r\n )}\r\n\r\n {/* Zoom Controls */}\r\n <IconButton\r\n size=\"small\"\r\n onClick={handleZoomOut}\r\n disabled={!hasImage || zoom <= 25}\r\n title=\"Zoom Out\"\r\n aria-label=\"Zoom out\"\r\n >\r\n <ZoomOutIcon fontSize=\"small\" />\r\n </IconButton>\r\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ minWidth: 64, textAlign: 'center' }}>\r\n {hasImage ? `${displayScale}%` : '—'}\r\n </Typography>\r\n <IconButton\r\n size=\"small\"\r\n onClick={handleZoomIn}\r\n disabled={!hasImage || zoom >= 400}\r\n title=\"Zoom In\"\r\n aria-label=\"Zoom in\"\r\n >\r\n <ZoomInIcon fontSize=\"small\" />\r\n </IconButton>\r\n\r\n <IconButton\r\n size=\"small\"\r\n onClick={handleFitWidth}\r\n disabled={!hasImage}\r\n title=\"Fit to Width\"\r\n aria-label=\"Fit to width\"\r\n color={fitMode === 'fit-width' ? 'primary' : 'default'}\r\n >\r\n <AspectRatioIcon fontSize=\"small\" />\r\n </IconButton>\r\n\r\n <IconButton\r\n size=\"small\"\r\n onClick={handleFitPage}\r\n disabled={!hasImage}\r\n title=\"Fit to Page\"\r\n aria-label=\"Fit to page\"\r\n color={fitMode === 'fit-page' ? 'primary' : 'default'}\r\n >\r\n <FitScreenIcon fontSize=\"small\" />\r\n </IconButton>\r\n\r\n <Divider orientation=\"vertical\" flexItem sx={{ mx: 1 }} />\r\n\r\n {/* Actions */}\r\n {!toolbar.isHidden('download') && (\r\n <IconButton\r\n size=\"small\"\r\n onClick={toolbar.getHandler('download', onDownloadClick)}\r\n disabled={toolbar.isDisabled('download')}\r\n title={toolbar.getLabel('download') || \"Download\"}\r\n aria-label=\"Download TIFF\"\r\n >\r\n {toolbar.getIcon('download') || <DownloadIcon fontSize=\"small\" />}\r\n </IconButton>\r\n )}\r\n\r\n {!toolbar.isHidden('print') && (\r\n <IconButton\r\n size=\"small\"\r\n onClick={toolbar.getHandler('print', onPrintClick)}\r\n disabled={toolbar.isDisabled('print')}\r\n title={toolbar.getLabel('print') || \"Print\"}\r\n aria-label=\"Print TIFF\"\r\n >\r\n {toolbar.getIcon('print') || <PrintIcon fontSize=\"small\" />}\r\n </IconButton>\r\n )}\r\n\r\n {!toolbar.isHidden('fullscreen') && (\r\n <IconButton\r\n size=\"small\"\r\n onClick={toolbar.getHandler('fullscreen', handleToggleFullScreen)}\r\n disabled={toolbar.isDisabled('fullscreen')}\r\n title={toolbar.getLabel('fullscreen') || \"Fullscreen\"}\r\n aria-label=\"Toggle fullscreen\"\r\n >\r\n {toolbar.getIcon('fullscreen') || <FullscreenIcon fontSize=\"small\" />}\r\n </IconButton>\r\n )}\r\n\r\n {!toolbar.isHidden('metadata') && (\r\n <IconButton\r\n size=\"small\"\r\n onClick={toolbar.getHandler('metadata', onMetadataClick)}\r\n disabled={toolbar.isDisabled('metadata')}\r\n title={toolbar.getLabel('metadata') || \"Document Metadata\"}\r\n aria-label=\"View document metadata\"\r\n >\r\n {toolbar.getIcon('metadata') || <DescriptionIcon fontSize=\"small\" />}\r\n </IconButton>\r\n )}\r\n\r\n {!toolbar.isHidden('properties') && (\r\n <IconButton\r\n size=\"small\"\r\n onClick={toolbar.getHandler('properties', onPropertiesClick)}\r\n disabled={toolbar.isDisabled('properties')}\r\n title={toolbar.getLabel('properties') || \"Document Properties\"}\r\n aria-label=\"View document properties\"\r\n >\r\n {toolbar.getIcon('properties') || <InfoIcon fontSize=\"small\" />}\r\n </IconButton>\r\n )}\r\n </Stack>\r\n </Box>\r\n\r\n {(isLoading || internalLoading) && <LinearProgress sx={{ mx: 3, mb: 1 }} />}\r\n {error && (\r\n <Typography color=\"error\" variant=\"body2\" sx={{ px: 3, pb: 1 }}>\r\n {error}\r\n </Typography>\r\n )}\r\n <Divider />\r\n <CardContent\r\n sx={{\r\n flexGrow: 1,\r\n flexShrink: 1,\r\n minHeight: 0,\r\n p: 0,\r\n overflow: 'hidden',\r\n backgroundColor: '#f6f8fa',\r\n position: 'relative'\r\n }}\r\n >\r\n <Box\r\n ref={viewportRef}\r\n sx={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n overflow: 'auto',\r\n }}\r\n >\r\n <Box\r\n sx={{\r\n minWidth: '100%',\r\n minHeight: '100%',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n }}\r\n >\r\n {renderImage()}\r\n </Box>\r\n </Box>\r\n </CardContent>\r\n </Card>\r\n </Box>\r\n );\r\n};\r\n\r\nexport const TIFFViewer: React.FC<FileViewerProps> = (props) => {\r\n const sourceDescription = useMemo(\r\n () => resolveDocumentName(props.file, props.fileName, props.url),\r\n [props.file, props.fileName, props.url]\r\n );\r\n\r\n return <TIFFViewerContent {...props} sourceDescription={sourceDescription} />;\r\n};\r\n"],"mappings":"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","names":["imageUrl","url"]}
@@ -8,7 +8,7 @@ import {
8
8
  import {
9
9
  FileIcon_default,
10
10
  mergeToolbarConfig
11
- } from "./chunk-VJFXCN5Z.mjs";
11
+ } from "./chunk-DFBVN4MO.mjs";
12
12
 
13
13
  // src/components/viewers/PDFViewer.tsx
14
14
  import { useCallback, useEffect as useEffect3, useMemo, useRef as useRef2, useState as useState3, forwardRef, useImperativeHandle } from "react";
@@ -50,6 +50,8 @@ import DownloadIcon from "@mui/icons-material/Download";
50
50
  import PrintIcon from "@mui/icons-material/Print";
51
51
  import InfoIcon from "@mui/icons-material/Info";
52
52
  import DescriptionIcon from "@mui/icons-material/Description";
53
+ import RotateLeftIcon from "@mui/icons-material/RotateLeft";
54
+ import RotateRightIcon from "@mui/icons-material/RotateRight";
53
55
  import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
54
56
  var PDFToolbar = React2.memo(({
55
57
  currentPage,
@@ -64,6 +66,9 @@ var PDFToolbar = React2.memo(({
64
66
  showProperties,
65
67
  showDownload,
66
68
  showPrint,
69
+ showRotation,
70
+ disabledRotateLeft,
71
+ disabledRotateRight,
67
72
  disabledMetadata,
68
73
  disabledProperties,
69
74
  disabledDownload,
@@ -80,6 +85,8 @@ var PDFToolbar = React2.memo(({
80
85
  onFitToPage,
81
86
  onToggleSidebar,
82
87
  onToggleFullScreen,
88
+ onRotateLeft,
89
+ onRotateRight,
83
90
  onDownloadClick,
84
91
  onPrintClick,
85
92
  onMetadataClick,
@@ -192,6 +199,31 @@ var PDFToolbar = React2.memo(({
192
199
  )
193
200
  ] })
194
201
  ] }),
202
+ showRotation && /* @__PURE__ */ jsxs(Fragment, { children: [
203
+ /* @__PURE__ */ jsx2("div", { className: "toolbar-separator" }),
204
+ /* @__PURE__ */ jsxs("div", { className: "toolbar-section", children: [
205
+ /* @__PURE__ */ jsx2(
206
+ "button",
207
+ {
208
+ className: "toolbar-button",
209
+ onClick: onRotateLeft,
210
+ disabled: disabledRotateLeft,
211
+ title: "Rotate Counterclockwise",
212
+ children: /* @__PURE__ */ jsx2(RotateLeftIcon, { fontSize: "small" })
213
+ }
214
+ ),
215
+ /* @__PURE__ */ jsx2(
216
+ "button",
217
+ {
218
+ className: "toolbar-button",
219
+ onClick: onRotateRight,
220
+ disabled: disabledRotateRight,
221
+ title: "Rotate Clockwise",
222
+ children: /* @__PURE__ */ jsx2(RotateRightIcon, { fontSize: "small" })
223
+ }
224
+ )
225
+ ] })
226
+ ] }),
195
227
  showSearch && /* @__PURE__ */ jsxs(Fragment, { children: [
196
228
  /* @__PURE__ */ jsx2("div", { className: "toolbar-separator" }),
197
229
  /* @__PURE__ */ jsx2("div", { className: "toolbar-section", children: /* @__PURE__ */ jsx2(
@@ -951,6 +983,7 @@ var PDFViewerContent = forwardRef((props, ref) => {
951
983
  showPageCount = true,
952
984
  showPageNavigation = true,
953
985
  showZoomControls = true,
986
+ showRotation = true,
954
987
  showDownload = true,
955
988
  showPrint = true,
956
989
  showSearch = true,
@@ -1019,6 +1052,7 @@ var PDFViewerContent = forwardRef((props, ref) => {
1019
1052
  showPrint,
1020
1053
  showMetadata,
1021
1054
  showProperties,
1055
+ showRotation,
1022
1056
  onDownloadClick,
1023
1057
  onPrintClick,
1024
1058
  onMetadataClick,
@@ -1118,6 +1152,12 @@ var PDFViewerContent = forwardRef((props, ref) => {
1118
1152
  }
1119
1153
  }
1120
1154
  },
1155
+ handleRotateLeft: () => {
1156
+ pdfViewerRef.current?.rotate?.rotateBackward();
1157
+ },
1158
+ handleRotateRight: () => {
1159
+ pdfViewerRef.current?.rotate?.rotateForward();
1160
+ },
1121
1161
  handleToggleFullScreen
1122
1162
  }), [isSidebarOpen, totalPages, handleToggleFullScreen]);
1123
1163
  useEffect3(() => {
@@ -1329,7 +1369,10 @@ var PDFViewerContent = forwardRef((props, ref) => {
1329
1369
  },
1330
1370
  getSearchState: () => pdfViewerRef.current?.search.getSearchState() || null,
1331
1371
  getSelectedText: () => pdfViewerRef.current?.selection.getSelectedText() || "",
1332
- clearSelection: () => pdfViewerRef.current?.selection.clearSelection()
1372
+ clearSelection: () => pdfViewerRef.current?.selection.clearSelection(),
1373
+ rotateForward: () => pdfViewerRef.current?.rotate?.rotateForward(),
1374
+ rotateBackward: () => pdfViewerRef.current?.rotate?.rotateBackward(),
1375
+ getRotation: () => pdfViewerRef.current?.rotate?.getRotation() || 0
1333
1376
  }), []);
1334
1377
  const updatePageDisplay = () => {
1335
1378
  requestAnimationFrame(() => {
@@ -1612,10 +1655,13 @@ var PDFViewerContent = forwardRef((props, ref) => {
1612
1655
  showPageCount,
1613
1656
  showZoomControls,
1614
1657
  showSearch,
1658
+ showRotation: !toolbar.isHidden("rotation"),
1615
1659
  showMetadata: !toolbar.isHidden("metadata"),
1616
1660
  showProperties: !toolbar.isHidden("properties"),
1617
1661
  showDownload: !toolbar.isHidden("download"),
1618
1662
  showPrint: !toolbar.isHidden("print"),
1663
+ disabledRotateLeft: toolbar.isDisabled("rotateLeft"),
1664
+ disabledRotateRight: toolbar.isDisabled("rotateRight"),
1619
1665
  disabledMetadata: toolbar.isDisabled("metadata"),
1620
1666
  disabledProperties: toolbar.isDisabled("properties"),
1621
1667
  disabledDownload: toolbar.isDisabled("download"),
@@ -1632,6 +1678,8 @@ var PDFViewerContent = forwardRef((props, ref) => {
1632
1678
  onFitToPage: toolbarHandlers.handleFitToPage,
1633
1679
  onToggleSidebar: toolbarHandlers.toggleSidebar,
1634
1680
  onToggleFullScreen: toolbarHandlers.handleToggleFullScreen,
1681
+ onRotateLeft: toolbarHandlers.handleRotateLeft,
1682
+ onRotateRight: toolbarHandlers.handleRotateRight,
1635
1683
  onDownloadClick: toolbar.getHandler("download", onDownloadClick),
1636
1684
  onPrintClick: toolbar.getHandler("print", onPrintClick),
1637
1685
  onMetadataClick: toolbar.getHandler("metadata", onMetadataClick),
@@ -1685,4 +1733,4 @@ PDFViewer.displayName = "PDFViewer";
1685
1733
  export {
1686
1734
  PDFViewer
1687
1735
  };
1688
- //# sourceMappingURL=chunk-ORL5FTAW.mjs.map
1736
+ //# sourceMappingURL=chunk-PZJSY6OF.mjs.map