@cannyminds/dms-file-viewers 0.8.0 → 0.10.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 (31) hide show
  1. package/dist/{chunk-PFJKVNUA.mjs → chunk-QNDIZUU5.mjs} +183 -128
  2. package/dist/chunk-QNDIZUU5.mjs.map +1 -0
  3. package/dist/{chunk-CQ3HSM5S.js → chunk-XBIKN46C.js} +187 -132
  4. package/dist/chunk-XBIKN46C.js.map +1 -0
  5. package/dist/components/viewers/AudioViewer.d.mts +1 -1
  6. package/dist/components/viewers/AudioViewer.d.ts +1 -1
  7. package/dist/components/viewers/DefaultViewer.d.mts +1 -1
  8. package/dist/components/viewers/DefaultViewer.d.ts +1 -1
  9. package/dist/components/viewers/ImageViewer.d.mts +1 -1
  10. package/dist/components/viewers/ImageViewer.d.ts +1 -1
  11. package/dist/components/viewers/PDFViewer.d.mts +1 -1
  12. package/dist/components/viewers/PDFViewer.d.ts +1 -1
  13. package/dist/components/viewers/TIFFViewer.d.mts +1 -1
  14. package/dist/components/viewers/TIFFViewer.d.ts +1 -1
  15. package/dist/components/viewers/TIFFViewer.js +2 -2
  16. package/dist/components/viewers/TIFFViewer.mjs +1 -1
  17. package/dist/components/viewers/TextViewer.d.mts +1 -1
  18. package/dist/components/viewers/TextViewer.d.ts +1 -1
  19. package/dist/components/viewers/VideoViewer.d.mts +1 -1
  20. package/dist/components/viewers/VideoViewer.d.ts +1 -1
  21. package/dist/index.d.mts +2 -2
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.js +10 -8
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.mjs +9 -7
  26. package/dist/index.mjs.map +1 -1
  27. package/dist/{types-BmZB9kkJ.d.mts → types-CQIoF7E1.d.mts} +3 -0
  28. package/dist/{types-BmZB9kkJ.d.ts → types-CQIoF7E1.d.ts} +3 -0
  29. package/package.json +2 -3
  30. package/dist/chunk-CQ3HSM5S.js.map +0 -1
  31. package/dist/chunk-PFJKVNUA.mjs.map +0 -1
@@ -39,40 +39,7 @@ import FitScreenIcon from "@mui/icons-material/FitScreen";
39
39
  import AspectRatioIcon from "@mui/icons-material/AspectRatio";
40
40
  import InfoIcon from "@mui/icons-material/Info";
41
41
  import DescriptionIcon from "@mui/icons-material/Description";
42
- import * as UTIF from "utif";
43
42
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
44
- var decodeTiff = (buffer) => {
45
- if (typeof window === "undefined") {
46
- return [];
47
- }
48
- const frames = [];
49
- const images = UTIF.decode(buffer);
50
- images.forEach((image) => {
51
- try {
52
- UTIF.decodeImage(buffer, image);
53
- const rgba = UTIF.toRGBA8(image);
54
- const width = image.width || 0;
55
- const height = image.height || 0;
56
- if (!width || !height) {
57
- return;
58
- }
59
- const canvas = document.createElement("canvas");
60
- canvas.width = width;
61
- canvas.height = height;
62
- const context = canvas.getContext("2d");
63
- if (!context) {
64
- return;
65
- }
66
- const clamped = new Uint8ClampedArray(rgba.length);
67
- clamped.set(rgba);
68
- const imageData = new ImageData(clamped, width, height);
69
- context.putImageData(imageData, 0, 0);
70
- frames.push({ dataUrl: canvas.toDataURL("image/png"), width, height });
71
- } catch (error) {
72
- }
73
- });
74
- return frames;
75
- };
76
43
  var resolveDocumentName = (file, fileName, url) => {
77
44
  if (file?.name) {
78
45
  return file.name;
@@ -91,6 +58,7 @@ var TIFFViewerContent = ({
91
58
  file,
92
59
  url,
93
60
  fileName,
61
+ totalPages = 1,
94
62
  className = "",
95
63
  style = {},
96
64
  width = "100%",
@@ -101,6 +69,7 @@ var TIFFViewerContent = ({
101
69
  onPrintClick,
102
70
  onMetadataClick,
103
71
  onPropertiesClick,
72
+ pageLoader,
104
73
  showDownload = true,
105
74
  showPrint = true,
106
75
  showMetadata = false,
@@ -121,17 +90,87 @@ var TIFFViewerContent = ({
121
90
  toolbarActions,
122
91
  ...props
123
92
  }) => {
124
- const [frames, setFrames] = useState([]);
125
- const [currentIndex, setCurrentIndex] = useState(0);
93
+ const [currentPage, setCurrentPage] = useState(1);
126
94
  const [isLoading, setIsLoading] = useState(false);
127
95
  const [error, setError] = useState(null);
128
96
  const [fitMode, setFitMode] = useState("fit-page");
129
- const [zoom, setZoom] = useState(1);
97
+ const [zoom, setZoom] = useState(100);
130
98
  const [viewportWidth, setViewportWidth] = useState(0);
131
99
  const [viewportHeight, setViewportHeight] = useState(0);
132
100
  const [isFullScreen, setIsFullScreen] = useState(false);
101
+ const [imageUrl, setImageUrl] = useState(null);
102
+ const [pageImages, setPageImages] = useState(/* @__PURE__ */ new Map());
103
+ const [internalLoading, setInternalLoading] = useState(false);
133
104
  const viewportRef = useRef(null);
134
105
  const containerRef = useRef(null);
106
+ const pageLoaderRef = useRef(pageLoader);
107
+ useEffect(() => {
108
+ pageLoaderRef.current = pageLoader;
109
+ }, [pageLoader]);
110
+ const updatePageImage = useCallback((pageData, pageNumber) => {
111
+ const blob = new Blob([pageData]);
112
+ const imageUrl2 = URL.createObjectURL(blob);
113
+ setPageImages((prev) => {
114
+ const oldUrl = prev.get(pageNumber);
115
+ if (oldUrl && oldUrl !== imageUrl2) {
116
+ URL.revokeObjectURL(oldUrl);
117
+ }
118
+ return new Map(prev).set(pageNumber, imageUrl2);
119
+ });
120
+ setCurrentPage(pageNumber);
121
+ setImageUrl(imageUrl2);
122
+ }, []);
123
+ useEffect(() => {
124
+ const loadInitialPage = async () => {
125
+ if (pageLoaderRef.current && !pageImages.has(1) && currentPage === 1) {
126
+ setInternalLoading(true);
127
+ setError(null);
128
+ try {
129
+ const pageData = await pageLoaderRef.current(1);
130
+ if (pageData) {
131
+ updatePageImage(pageData, 1);
132
+ } else {
133
+ setError("Failed to load page 1");
134
+ }
135
+ } catch (err) {
136
+ const message = err instanceof Error ? err.message : "Unable to load page 1";
137
+ setError(message);
138
+ onError?.(new Error(message));
139
+ } finally {
140
+ setInternalLoading(false);
141
+ }
142
+ }
143
+ };
144
+ loadInitialPage();
145
+ }, [pageImages, currentPage, updatePageImage, onError]);
146
+ const handlePageChange = useCallback(async (newPageNumber) => {
147
+ if (!pageLoaderRef.current) {
148
+ console.warn("pageLoader not provided - page navigation disabled");
149
+ return;
150
+ }
151
+ const cachedUrl = pageImages.get(newPageNumber);
152
+ if (cachedUrl) {
153
+ setCurrentPage(newPageNumber);
154
+ setImageUrl(cachedUrl);
155
+ return;
156
+ }
157
+ setInternalLoading(true);
158
+ setError(null);
159
+ try {
160
+ const pageData = await pageLoaderRef.current(newPageNumber);
161
+ if (pageData) {
162
+ updatePageImage(pageData, newPageNumber);
163
+ } else {
164
+ setError(`Failed to load page ${newPageNumber}`);
165
+ }
166
+ } catch (err) {
167
+ const message = err instanceof Error ? err.message : `Unable to load page ${newPageNumber}`;
168
+ setError(message);
169
+ onError?.(new Error(message));
170
+ } finally {
171
+ setInternalLoading(false);
172
+ }
173
+ }, [pageImages, onError, updatePageImage]);
135
174
  const resolvedFileName = useMemo(
136
175
  () => fileName || sourceDescription,
137
176
  [fileName, sourceDescription]
@@ -140,63 +179,74 @@ var TIFFViewerContent = ({
140
179
  () => getFileExtension(resolvedFileName || ""),
141
180
  [resolvedFileName]
142
181
  );
143
- const loadTiff = useCallback(async () => {
182
+ const loadImage = useCallback(async (resetPage = false) => {
144
183
  if (!file && !url) {
145
- setFrames([]);
146
- setCurrentIndex(0);
184
+ setImageUrl(null);
185
+ if (resetPage) setCurrentPage(1);
147
186
  setError(null);
148
187
  return;
149
188
  }
150
- if (typeof window === "undefined") {
151
- return;
152
- }
153
189
  setIsLoading(true);
154
190
  setError(null);
155
191
  try {
156
- let buffer;
192
+ let imageDataUrl;
157
193
  if (file) {
158
- buffer = await file.arrayBuffer();
194
+ imageDataUrl = URL.createObjectURL(file);
195
+ } else if (url) {
196
+ imageDataUrl = url;
159
197
  } else {
160
- const response = await fetch(url);
161
- if (!response.ok) {
162
- throw new Error(`Failed to fetch TIFF (${response.status})`);
163
- }
164
- buffer = await response.arrayBuffer();
198
+ throw new Error("No file or URL provided");
165
199
  }
166
- const decodedFrames = decodeTiff(buffer);
167
- setFrames(decodedFrames);
168
- setCurrentIndex(0);
169
- setFitMode("fit-page");
170
- setZoom(1);
171
- if (decodedFrames.length > 0) {
172
- onLoad?.();
173
- } else {
174
- setError("No displayable frames detected in TIFF file.");
200
+ setImageUrl(imageDataUrl);
201
+ if (resetPage) {
202
+ setCurrentPage(1);
203
+ setFitMode("fit-page");
204
+ setZoom(100);
175
205
  }
206
+ onLoad?.();
176
207
  } catch (err) {
177
- const message = err instanceof Error ? err.message : "Unable to load TIFF file";
208
+ const message = err instanceof Error ? err.message : "Unable to load image file";
178
209
  setError(message);
179
- setFrames([]);
180
- setCurrentIndex(0);
181
- setFitMode("fit-page");
182
- setZoom(1);
210
+ setImageUrl(null);
211
+ if (resetPage) {
212
+ setCurrentPage(1);
213
+ setFitMode("fit-width");
214
+ setZoom(100);
215
+ }
183
216
  onError?.(new Error(message));
184
217
  } finally {
185
218
  setIsLoading(false);
186
219
  }
187
220
  }, [file, url, onLoad, onError]);
221
+ const [previousFileSource, setPreviousFileSource] = useState({});
188
222
  useEffect(() => {
189
- void loadTiff();
190
- }, [loadTiff]);
191
- const currentFrame = frames[currentIndex];
192
- const hasFrames = frames.length > 0;
193
- const hasMultipleFrames = frames.length > 1;
223
+ const currentFileSource = { file, url };
224
+ const isNewFile = previousFileSource.file !== file || previousFileSource.url !== url;
225
+ if (isNewFile) {
226
+ setPreviousFileSource(currentFileSource);
227
+ void loadImage(true);
228
+ } else {
229
+ void loadImage(false);
230
+ }
231
+ }, [file, url, loadImage, previousFileSource.file, previousFileSource.url]);
194
232
  useEffect(() => {
195
- if (hasFrames) {
196
- setZoom(1);
233
+ return () => {
234
+ pageImages.forEach((url2) => {
235
+ URL.revokeObjectURL(url2);
236
+ });
237
+ if (imageUrl && file && !pageImages.has(currentPage)) {
238
+ URL.revokeObjectURL(imageUrl);
239
+ }
240
+ };
241
+ }, []);
242
+ const hasImage = !!imageUrl;
243
+ const hasMultiplePages = totalPages > 1;
244
+ useEffect(() => {
245
+ if (hasImage) {
246
+ setZoom(100);
197
247
  setFitMode("fit-page");
198
248
  }
199
- }, [currentIndex, hasFrames]);
249
+ }, [currentPage, hasImage]);
200
250
  useEffect(() => {
201
251
  if (typeof window === "undefined" || typeof ResizeObserver === "undefined") {
202
252
  return void 0;
@@ -220,32 +270,46 @@ var TIFFViewerContent = ({
220
270
  }, []);
221
271
  const handleZoomIn = useCallback(() => {
222
272
  setFitMode("zoom");
223
- setZoom((value) => Math.min(Math.round((value + 0.25) * 100) / 100, 5));
273
+ 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);
277
+ });
224
278
  }, []);
225
279
  const handleZoomOut = useCallback(() => {
226
280
  setFitMode("zoom");
227
- setZoom((value) => Math.max(Math.round((value - 0.25) * 100) / 100, 0.25));
281
+ 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);
285
+ });
228
286
  }, []);
229
287
  const handleFitWidth = useCallback(() => {
230
288
  setFitMode("fit-width");
231
- setZoom(1);
289
+ setZoom(100);
232
290
  }, []);
233
291
  const handleFitPage = useCallback(() => {
234
292
  setFitMode("fit-page");
235
- setZoom(1);
293
+ setZoom(100);
236
294
  }, []);
237
295
  const handleFirstPage = useCallback(() => {
238
- setCurrentIndex(0);
239
- }, []);
296
+ handlePageChange(1);
297
+ }, [handlePageChange]);
240
298
  const handleLastPage = useCallback(() => {
241
- setCurrentIndex(frames.length - 1);
242
- }, [frames.length]);
299
+ handlePageChange(totalPages);
300
+ }, [handlePageChange, totalPages]);
243
301
  const handlePreviousPage = useCallback(() => {
244
- setCurrentIndex((index) => Math.max(index - 1, 0));
245
- }, []);
302
+ const newPage = Math.max(currentPage - 1, 1);
303
+ if (newPage !== currentPage) {
304
+ handlePageChange(newPage);
305
+ }
306
+ }, [currentPage, handlePageChange]);
246
307
  const handleNextPage = useCallback(() => {
247
- setCurrentIndex((index) => Math.min(index + 1, frames.length - 1));
248
- }, [frames.length]);
308
+ const newPage = Math.min(currentPage + 1, totalPages);
309
+ if (newPage !== currentPage) {
310
+ handlePageChange(newPage);
311
+ }
312
+ }, [currentPage, totalPages, handlePageChange]);
249
313
  const handleToggleFullScreen = useCallback(() => {
250
314
  if (!isFullScreen && containerRef.current?.requestFullscreen) {
251
315
  containerRef.current.requestFullscreen();
@@ -256,54 +320,45 @@ var TIFFViewerContent = ({
256
320
  }
257
321
  }, [isFullScreen]);
258
322
  const toolbar = mergeToolbarConfig({ showDownload, showPrint, showMetadata, showProperties, onDownloadClick, onPrintClick, onMetadataClick, onPropertiesClick, toolbarActions });
259
- const effectiveScale = useMemo(() => {
260
- if (!currentFrame) {
261
- return 1;
262
- }
263
- if (fitMode === "zoom") {
264
- return zoom;
265
- }
266
- const frameWidth = currentFrame.width;
267
- const frameHeight = currentFrame.height;
268
- if (!viewportWidth || !viewportHeight || !frameWidth || !frameHeight) {
269
- return 1;
270
- }
271
- if (fitMode === "fit-page") {
272
- const ratio = Math.min(viewportWidth / frameWidth, viewportHeight / frameHeight);
273
- return ratio || 1;
274
- }
275
- const widthRatio = viewportWidth / frameWidth;
276
- return widthRatio || 1;
277
- }, [currentFrame, fitMode, viewportWidth, viewportHeight, zoom]);
278
- const displayScale = useMemo(() => Math.round(effectiveScale * 100), [effectiveScale]);
323
+ const displayScale = zoom;
279
324
  const renderImage = () => {
280
- if (!currentFrame) {
281
- return /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: "No TIFF frame available." });
325
+ if (!imageUrl) {
326
+ return /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: "No image available." });
282
327
  }
283
- const widthPx = currentFrame.width * effectiveScale;
284
- const heightPx = currentFrame.height * effectiveScale;
285
328
  return /* @__PURE__ */ jsx(
286
329
  Box,
287
330
  {
288
331
  sx: {
289
332
  position: "relative",
290
- width: widthPx,
291
- height: heightPx,
292
333
  borderRadius: 1,
293
334
  boxShadow: 1,
294
- backgroundColor: "#fff"
335
+ backgroundColor: "#fff",
336
+ display: "flex",
337
+ justifyContent: "center",
338
+ alignItems: "center"
295
339
  },
296
340
  children: /* @__PURE__ */ jsx(
297
341
  Box,
298
342
  {
299
343
  component: "img",
300
- src: currentFrame.dataUrl,
301
- alt: `${resolvedFileName} page ${currentIndex + 1}`,
344
+ src: imageUrl,
345
+ alt: `${resolvedFileName} page ${currentPage}`,
302
346
  sx: {
303
- width: widthPx,
304
- height: heightPx,
347
+ maxWidth: fitMode === "fit-width" ? "100%" : "none",
348
+ maxHeight: fitMode === "fit-page" ? "100%" : "none",
349
+ width: fitMode === "zoom" ? `${zoom}%` : "auto",
350
+ height: "auto",
305
351
  display: "block",
306
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"));
307
362
  }
308
363
  }
309
364
  )
@@ -334,13 +389,13 @@ var TIFFViewerContent = ({
334
389
  }
335
390
  ),
336
391
  /* @__PURE__ */ jsx(Box, { sx: { px: 2, pb: 1, display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", flexWrap: "wrap", gap: 1, children: [
337
- hasMultipleFrames && /* @__PURE__ */ jsxs(Fragment, { children: [
392
+ hasMultiplePages && /* @__PURE__ */ jsxs(Fragment, { children: [
338
393
  /* @__PURE__ */ jsx(
339
394
  IconButton,
340
395
  {
341
396
  size: "small",
342
397
  onClick: handleFirstPage,
343
- disabled: currentIndex === 0,
398
+ disabled: currentPage === 1,
344
399
  title: "First Page",
345
400
  "aria-label": "Go to first page",
346
401
  children: /* @__PURE__ */ jsx(FirstPageIcon, { fontSize: "small" })
@@ -351,7 +406,7 @@ var TIFFViewerContent = ({
351
406
  {
352
407
  size: "small",
353
408
  onClick: handlePreviousPage,
354
- disabled: currentIndex === 0,
409
+ disabled: currentPage === 1,
355
410
  title: "Previous Page",
356
411
  "aria-label": "Go to previous page",
357
412
  children: /* @__PURE__ */ jsx(ChevronLeftIcon, { fontSize: "small" })
@@ -359,16 +414,16 @@ var TIFFViewerContent = ({
359
414
  ),
360
415
  /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "text.secondary", sx: { minWidth: 100, textAlign: "center" }, children: [
361
416
  "Page ",
362
- currentIndex + 1,
417
+ currentPage,
363
418
  " of ",
364
- frames.length
419
+ totalPages
365
420
  ] }),
366
421
  /* @__PURE__ */ jsx(
367
422
  IconButton,
368
423
  {
369
424
  size: "small",
370
425
  onClick: handleNextPage,
371
- disabled: currentIndex === frames.length - 1,
426
+ disabled: currentPage === totalPages,
372
427
  title: "Next Page",
373
428
  "aria-label": "Go to next page",
374
429
  children: /* @__PURE__ */ jsx(ChevronRightIcon, { fontSize: "small" })
@@ -379,7 +434,7 @@ var TIFFViewerContent = ({
379
434
  {
380
435
  size: "small",
381
436
  onClick: handleLastPage,
382
- disabled: currentIndex === frames.length - 1,
437
+ disabled: currentPage === totalPages,
383
438
  title: "Last Page",
384
439
  "aria-label": "Go to last page",
385
440
  children: /* @__PURE__ */ jsx(LastPageIcon, { fontSize: "small" })
@@ -392,19 +447,19 @@ var TIFFViewerContent = ({
392
447
  {
393
448
  size: "small",
394
449
  onClick: handleZoomOut,
395
- disabled: !hasFrames || zoom <= 0.25,
450
+ disabled: !hasImage || zoom <= 0.25,
396
451
  title: "Zoom Out",
397
452
  "aria-label": "Zoom out",
398
453
  children: /* @__PURE__ */ jsx(ZoomOutIcon, { fontSize: "small" })
399
454
  }
400
455
  ),
401
- /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", sx: { minWidth: 64, textAlign: "center" }, children: hasFrames ? `${displayScale}%` : "\u2014" }),
456
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", sx: { minWidth: 64, textAlign: "center" }, children: hasImage ? `${displayScale}%` : "\u2014" }),
402
457
  /* @__PURE__ */ jsx(
403
458
  IconButton,
404
459
  {
405
460
  size: "small",
406
461
  onClick: handleZoomIn,
407
- disabled: !hasFrames || zoom >= 5,
462
+ disabled: !hasImage || zoom >= 5,
408
463
  title: "Zoom In",
409
464
  "aria-label": "Zoom in",
410
465
  children: /* @__PURE__ */ jsx(ZoomInIcon, { fontSize: "small" })
@@ -415,7 +470,7 @@ var TIFFViewerContent = ({
415
470
  {
416
471
  size: "small",
417
472
  onClick: handleFitWidth,
418
- disabled: !hasFrames,
473
+ disabled: !hasImage,
419
474
  title: "Fit to Width",
420
475
  "aria-label": "Fit to width",
421
476
  color: fitMode === "fit-width" ? "primary" : "default",
@@ -427,7 +482,7 @@ var TIFFViewerContent = ({
427
482
  {
428
483
  size: "small",
429
484
  onClick: handleFitPage,
430
- disabled: !hasFrames,
485
+ disabled: !hasImage,
431
486
  title: "Fit to Page",
432
487
  "aria-label": "Fit to page",
433
488
  color: fitMode === "fit-page" ? "primary" : "default",
@@ -491,7 +546,7 @@ var TIFFViewerContent = ({
491
546
  }
492
547
  )
493
548
  ] }) }),
494
- isLoading && /* @__PURE__ */ jsx(LinearProgress, { sx: { mx: 3, mb: 1 } }),
549
+ (isLoading || internalLoading) && /* @__PURE__ */ jsx(LinearProgress, { sx: { mx: 3, mb: 1 } }),
495
550
  error && /* @__PURE__ */ jsx(Typography, { color: "error", variant: "body2", sx: { px: 3, pb: 1 }, children: error }),
496
551
  /* @__PURE__ */ jsx(Divider, {}),
497
552
  /* @__PURE__ */ jsx(
@@ -542,4 +597,4 @@ var TIFFViewer = (props) => {
542
597
  export {
543
598
  TIFFViewer
544
599
  };
545
- //# sourceMappingURL=chunk-PFJKVNUA.mjs.map
600
+ //# sourceMappingURL=chunk-QNDIZUU5.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 \r\n const viewportRef = useRef<HTMLDivElement | null>(null);\r\n const containerRef = useRef<HTMLDivElement>(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 useEffect(() => {\r\n if (hasImage) {\r\n setZoom(100);\r\n setFitMode('fit-page');\r\n }\r\n }, [currentPage, hasImage]);\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 if (value < 100) return Math.min(value + 25, 100);\r\n if (value < 200) return Math.min(value + 50, 200);\r\n return Math.min(value + 100, 500);\r\n });\r\n }, []);\r\n\r\n const handleZoomOut = useCallback(() => {\r\n setFitMode('zoom');\r\n setZoom((value) => {\r\n if (value <= 100) return Math.max(value - 25, 25);\r\n if (value <= 200) return Math.max(value - 50, 100);\r\n return Math.max(value - 100, 200);\r\n });\r\n }, []);\r\n\r\n const handleFitWidth = useCallback(() => {\r\n setFitMode('fit-width');\r\n setZoom(100);\r\n }, []);\r\n\r\n const handleFitPage = useCallback(() => {\r\n setFitMode('fit-page');\r\n setZoom(100);\r\n }, []);\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 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 return (\r\n <Box\r\n sx={{\r\n position: 'relative',\r\n borderRadius: 1,\r\n boxShadow: 1,\r\n backgroundColor: '#fff',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center'\r\n }}\r\n >\r\n <Box\r\n component=\"img\"\r\n src={imageUrl}\r\n alt={`${resolvedFileName} page ${currentPage}`}\r\n sx={{\r\n maxWidth: fitMode === 'fit-width' ? '100%' : 'none',\r\n maxHeight: fitMode === 'fit-page' ? '100%' : 'none',\r\n width: fitMode === 'zoom' ? `${zoom}%` : 'auto',\r\n height: 'auto',\r\n display: 'block',\r\n borderRadius: 1\r\n }}\r\n onLoad={() => {\r\n if (!hasImage) {\r\n onLoad?.();\r\n }\r\n }}\r\n onError={() => {\r\n setError('Failed to load image');\r\n onError?.(new Error('Failed to load image'));\r\n }}\r\n />\r\n </Box>\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 <= 0.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 >= 5}\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: 'auto',\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 display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n p: 3,\r\n overflow: 'auto'\r\n }}\r\n >\r\n {renderImage()}\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"]}