viewdoc 0.2.1 → 0.3.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 (48) hide show
  1. package/README.md +7 -2
  2. package/dist/DocxViewer-F3MW62BA.js +10 -0
  3. package/dist/PdfViewer-6YF7AER3.js +9 -0
  4. package/dist/XlsxViewer-7X25BBRT.js +10 -0
  5. package/dist/{chunk-LE4YTMPN.js → chunk-3EUNNQXJ.js} +36 -9
  6. package/dist/chunk-3EUNNQXJ.js.map +1 -0
  7. package/dist/{chunk-EQCFZMLL.js → chunk-4BFQ7U2R.js} +10 -4
  8. package/dist/chunk-4BFQ7U2R.js.map +1 -0
  9. package/dist/{chunk-US2KTONG.js → chunk-AIDVQYXH.js} +6 -3
  10. package/dist/chunk-AIDVQYXH.js.map +1 -0
  11. package/dist/chunk-DKFD7M4R.js +12 -0
  12. package/dist/chunk-DKFD7M4R.js.map +1 -0
  13. package/dist/{chunk-OA35SYM6.js → chunk-HOF2XEU5.js} +43 -6
  14. package/dist/chunk-HOF2XEU5.js.map +1 -0
  15. package/dist/docx.cjs +53 -7
  16. package/dist/docx.cjs.map +1 -1
  17. package/dist/docx.d.cts +3 -1
  18. package/dist/docx.d.ts +3 -1
  19. package/dist/docx.js +4 -2
  20. package/dist/index.cjs +94 -16
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.d.cts +5 -1
  23. package/dist/index.d.ts +5 -1
  24. package/dist/index.js +7 -5
  25. package/dist/index.js.map +1 -1
  26. package/dist/pdf.cjs +44 -6
  27. package/dist/pdf.cjs.map +1 -1
  28. package/dist/pdf.d.cts +3 -1
  29. package/dist/pdf.d.ts +3 -1
  30. package/dist/pdf.js +3 -2
  31. package/dist/styles.css +10 -0
  32. package/dist/styles.css.map +1 -1
  33. package/dist/xlsx.cjs +77 -12
  34. package/dist/xlsx.cjs.map +1 -1
  35. package/dist/xlsx.d.cts +9 -1
  36. package/dist/xlsx.d.ts +9 -1
  37. package/dist/xlsx.js +4 -2
  38. package/package.json +5 -1
  39. package/dist/DocxViewer-HQFSWXQW.js +0 -8
  40. package/dist/PdfViewer-YJOHTAPL.js +0 -8
  41. package/dist/XlsxViewer-SQMAF5UA.js +0 -8
  42. package/dist/chunk-EQCFZMLL.js.map +0 -1
  43. package/dist/chunk-LE4YTMPN.js.map +0 -1
  44. package/dist/chunk-OA35SYM6.js.map +0 -1
  45. package/dist/chunk-US2KTONG.js.map +0 -1
  46. /package/dist/{DocxViewer-HQFSWXQW.js.map → DocxViewer-F3MW62BA.js.map} +0 -0
  47. /package/dist/{PdfViewer-YJOHTAPL.js.map → PdfViewer-6YF7AER3.js.map} +0 -0
  48. /package/dist/{XlsxViewer-SQMAF5UA.js.map → XlsxViewer-7X25BBRT.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -1,3 +1,4 @@
1
+ 'use client'
1
2
  "use strict";
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -297,9 +298,10 @@ function ViewerShell({
297
298
  document.addEventListener("fullscreenchange", onChange);
298
299
  return () => document.removeEventListener("fullscreenchange", onChange);
299
300
  }, []);
301
+ const fullscreenSupported = typeof document !== "undefined" && typeof document.fullscreenEnabled === "boolean" ? document.fullscreenEnabled : false;
300
302
  const onFullscreen = (0, import_react2.useCallback)(() => {
301
303
  const el = rootRef.current;
302
- if (!el) return;
304
+ if (!el || typeof el.requestFullscreen !== "function") return;
303
305
  if (document.fullscreenElement) {
304
306
  document.exitFullscreen();
305
307
  } else {
@@ -325,7 +327,7 @@ function ViewerShell({
325
327
  onZoomIn: zoomPan.zoomIn,
326
328
  onZoomOut: zoomPan.zoomOut,
327
329
  onReset: zoomPan.resetZoom,
328
- onFullscreen: enableFullscreen ? onFullscreen : void 0,
330
+ onFullscreen: enableFullscreen && fullscreenSupported ? onFullscreen : void 0,
329
331
  onDownload,
330
332
  isFullscreen,
331
333
  showZoomControls: enableZoomControls,
@@ -374,6 +376,9 @@ var init_ViewerShell = __esm({
374
376
  });
375
377
 
376
378
  // src/core/useZoomPan.ts
379
+ function pointerDistance(a, b) {
380
+ return Math.hypot(a.x - b.x, a.y - b.y);
381
+ }
377
382
  function useZoomPan(options = {}) {
378
383
  const {
379
384
  minScale = DEFAULT_MIN,
@@ -381,7 +386,8 @@ function useZoomPan(options = {}) {
381
386
  zoomStep = DEFAULT_STEP,
382
387
  enablePan = true,
383
388
  enableWheelZoom = true,
384
- enableDragScroll = false
389
+ enableDragScroll = false,
390
+ enablePinchZoom = true
385
391
  } = options;
386
392
  const [state, setState] = (0, import_react3.useState)({ scale: 1, translateX: 0, translateY: 0 });
387
393
  const containerRef = (0, import_react3.useRef)(null);
@@ -395,6 +401,12 @@ function useZoomPan(options = {}) {
395
401
  const scrollDragState = (0, import_react3.useRef)(
396
402
  { dragging: false, startX: 0, startY: 0, originLeft: 0, originTop: 0 }
397
403
  );
404
+ const activePointers = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
405
+ const pinchState = (0, import_react3.useRef)({
406
+ pinching: false,
407
+ startDistance: 0,
408
+ startScale: 1
409
+ });
398
410
  const clamp = (0, import_react3.useCallback)(
399
411
  (value) => Math.min(maxScale, Math.max(minScale, value)),
400
412
  [minScale, maxScale]
@@ -418,6 +430,16 @@ function useZoomPan(options = {}) {
418
430
  );
419
431
  const onPointerDown = (0, import_react3.useCallback)(
420
432
  (e) => {
433
+ if (enablePinchZoom) {
434
+ activePointers.current.set(e.pointerId, { x: e.clientX, y: e.clientY });
435
+ if (activePointers.current.size === 2) {
436
+ const [a, b] = Array.from(activePointers.current.values());
437
+ pinchState.current = { pinching: true, startDistance: pointerDistance(a, b), startScale: state.scale };
438
+ dragState.current.dragging = false;
439
+ scrollDragState.current.dragging = false;
440
+ return;
441
+ }
442
+ }
421
443
  if (enablePan) {
422
444
  dragState.current = {
423
445
  dragging: true,
@@ -438,10 +460,20 @@ function useZoomPan(options = {}) {
438
460
  e.target.setPointerCapture(e.pointerId);
439
461
  }
440
462
  },
441
- [enablePan, enableDragScroll, state.translateX, state.translateY]
463
+ [enablePan, enableDragScroll, enablePinchZoom, state.translateX, state.translateY, state.scale]
442
464
  );
443
465
  const onPointerMove = (0, import_react3.useCallback)(
444
466
  (e) => {
467
+ if (enablePinchZoom && activePointers.current.has(e.pointerId)) {
468
+ activePointers.current.set(e.pointerId, { x: e.clientX, y: e.clientY });
469
+ }
470
+ if (pinchState.current.pinching && activePointers.current.size === 2) {
471
+ const [a, b] = Array.from(activePointers.current.values());
472
+ const distance = pointerDistance(a, b);
473
+ const ratio = distance / (pinchState.current.startDistance || distance);
474
+ setScale(pinchState.current.startScale * ratio);
475
+ return;
476
+ }
445
477
  if (enablePan) {
446
478
  if (!dragState.current.dragging) return;
447
479
  const dx = e.clientX - dragState.current.startX;
@@ -459,10 +491,14 @@ function useZoomPan(options = {}) {
459
491
  containerRef.current.scrollTop = scrollDragState.current.originTop - dy;
460
492
  }
461
493
  },
462
- [enablePan, enableDragScroll]
494
+ [enablePan, enableDragScroll, enablePinchZoom, setScale]
463
495
  );
464
496
  const onPointerUp = (0, import_react3.useCallback)(
465
497
  (e) => {
498
+ activePointers.current.delete(e.pointerId);
499
+ if (activePointers.current.size < 2) {
500
+ pinchState.current.pinching = false;
501
+ }
466
502
  if (enablePan) {
467
503
  dragState.current.dragging = false;
468
504
  e.target.releasePointerCapture(e.pointerId);
@@ -628,6 +664,7 @@ function PdfViewer({
628
664
  renderScale,
629
665
  enableZoomControls = true,
630
666
  enableWheelZoom = true,
667
+ enablePinchZoom = true,
631
668
  enableFullscreen = true,
632
669
  enableDownload = true,
633
670
  onDownload,
@@ -642,7 +679,8 @@ function PdfViewer({
642
679
  zoomStep,
643
680
  enablePan: false,
644
681
  enableDragScroll: true,
645
- enableWheelZoom
682
+ enableWheelZoom,
683
+ enablePinchZoom
646
684
  });
647
685
  const { doc, numPages, error, loading } = usePdfDocument(uri);
648
686
  const currentPage = useVisiblePage(zoomPan.containerRef, numPages);
@@ -693,6 +731,18 @@ var init_PdfViewer = __esm({
693
731
  }
694
732
  });
695
733
 
734
+ // src/core/sanitizeHtml.ts
735
+ function sanitizeUntrustedHtml(html) {
736
+ return import_dompurify.default.sanitize(html);
737
+ }
738
+ var import_dompurify;
739
+ var init_sanitizeHtml = __esm({
740
+ "src/core/sanitizeHtml.ts"() {
741
+ "use strict";
742
+ import_dompurify = __toESM(require("dompurify"), 1);
743
+ }
744
+ });
745
+
696
746
  // src/viewers/useDocxHtml.ts
697
747
  function useDocxHtml(uri) {
698
748
  const [html, setHtml] = (0, import_react8.useState)(null);
@@ -712,7 +762,7 @@ function useDocxHtml(uri) {
712
762
  })
713
763
  ).then((result) => {
714
764
  if (cancelled) return;
715
- setHtml(result.value);
765
+ setHtml(sanitizeUntrustedHtml(result.value));
716
766
  setLoading(false);
717
767
  }).catch((err) => {
718
768
  if (!cancelled) {
@@ -732,6 +782,7 @@ var init_useDocxHtml = __esm({
732
782
  "use strict";
733
783
  import_react8 = require("react");
734
784
  import_mammoth = __toESM(require("mammoth"), 1);
785
+ init_sanitizeHtml();
735
786
  }
736
787
  });
737
788
 
@@ -761,6 +812,7 @@ function DocxViewer({
761
812
  zoomStep,
762
813
  enableZoomControls = true,
763
814
  enableWheelZoom = true,
815
+ enablePinchZoom = true,
764
816
  enableFullscreen = true,
765
817
  enableDownload = true,
766
818
  onDownload,
@@ -775,7 +827,8 @@ function DocxViewer({
775
827
  zoomStep,
776
828
  enablePan: false,
777
829
  enableDragScroll: true,
778
- enableWheelZoom
830
+ enableWheelZoom,
831
+ enablePinchZoom
779
832
  });
780
833
  const { html, error, loading } = useDocxHtml(uri);
781
834
  const handleDownload = enableDownload ? onDownload ?? (() => defaultDownload3(uri, fileName)) : void 0;
@@ -882,13 +935,15 @@ function XlsxViewer({
882
935
  zoomStep,
883
936
  enableZoomControls = true,
884
937
  enableWheelZoom = true,
938
+ enablePinchZoom = true,
885
939
  enableFullscreen = true,
886
940
  enableDownload = true,
887
941
  onDownload,
888
942
  theme,
889
943
  floating = true,
890
944
  windowDraggable = true,
891
- defaultPosition
945
+ defaultPosition,
946
+ maxRows = 2e3
892
947
  }) {
893
948
  const zoomPan = useZoomPan({
894
949
  minScale,
@@ -896,18 +951,32 @@ function XlsxViewer({
896
951
  zoomStep,
897
952
  enablePan: false,
898
953
  enableDragScroll: true,
899
- enableWheelZoom
954
+ enableWheelZoom,
955
+ enablePinchZoom
900
956
  });
901
957
  const { workbook, error, loading } = useXlsxWorkbook(uri);
902
958
  const [activeSheet, setActiveSheet] = (0, import_react10.useState)(0);
903
959
  const handleDownload = enableDownload ? onDownload ?? (() => defaultDownload4(uri, fileName)) : void 0;
904
- const tableHtml = (0, import_react10.useMemo)(() => {
905
- if (!workbook) return null;
960
+ const { tableHtml, truncatedRowCount, totalRowCount } = (0, import_react10.useMemo)(() => {
961
+ if (!workbook) return { tableHtml: null, truncatedRowCount: null, totalRowCount: 0 };
906
962
  const sheetName = workbook.SheetNames[activeSheet];
907
963
  const sheet = workbook.Sheets[sheetName];
908
- if (!sheet) return null;
909
- return XLSX2.utils.sheet_to_html(sheet, { editable: false });
910
- }, [workbook, activeSheet]);
964
+ if (!sheet || !sheet["!ref"]) return { tableHtml: null, truncatedRowCount: null, totalRowCount: 0 };
965
+ const range = XLSX2.utils.decode_range(sheet["!ref"]);
966
+ const totalRows = range.e.r - range.s.r + 1;
967
+ let sheetToRender = sheet;
968
+ let truncated = null;
969
+ if (totalRows > maxRows) {
970
+ truncated = maxRows;
971
+ const clampedRange = { s: range.s, e: { r: range.s.r + maxRows - 1, c: range.e.c } };
972
+ sheetToRender = { ...sheet, "!ref": XLSX2.utils.encode_range(clampedRange) };
973
+ }
974
+ return {
975
+ tableHtml: sanitizeUntrustedHtml(XLSX2.utils.sheet_to_html(sheetToRender, { editable: false })),
976
+ truncatedRowCount: truncated,
977
+ totalRowCount: totalRows
978
+ };
979
+ }, [workbook, activeSheet, maxRows]);
911
980
  const wrapperStyle = floating ? { ...style } : { display: "flex", alignItems: "center", justifyContent: "center", width: "100%", height: "100%", ...style };
912
981
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className, style: wrapperStyle, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
913
982
  ViewerShell,
@@ -941,6 +1010,13 @@ function XlsxViewer({
941
1010
  },
942
1011
  name
943
1012
  )) }),
1013
+ truncatedRowCount != null && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "vd-xlsx-truncated-notice", children: [
1014
+ "Showing the first ",
1015
+ truncatedRowCount.toLocaleString(),
1016
+ " of ",
1017
+ totalRowCount.toLocaleString(),
1018
+ " rows. Download the file to see the rest."
1019
+ ] }),
944
1020
  tableHtml && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "vd-xlsx-table", dangerouslySetInnerHTML: { __html: tableHtml } })
945
1021
  ] })
946
1022
  ]
@@ -954,6 +1030,7 @@ var init_XlsxViewer = __esm({
954
1030
  import_react10 = require("react");
955
1031
  XLSX2 = __toESM(require("xlsx"), 1);
956
1032
  init_ViewerShell();
1033
+ init_sanitizeHtml();
957
1034
  init_useZoomPan();
958
1035
  init_useXlsxWorkbook();
959
1036
  import_jsx_runtime8 = require("react/jsx-runtime");
@@ -1003,6 +1080,7 @@ function ImageViewer({
1003
1080
  zoomStep,
1004
1081
  enableZoomControls = true,
1005
1082
  enableWheelZoom = true,
1083
+ enablePinchZoom = true,
1006
1084
  enablePan = true,
1007
1085
  enableFullscreen = true,
1008
1086
  enableDownload = true,
@@ -1012,7 +1090,7 @@ function ImageViewer({
1012
1090
  windowDraggable = true,
1013
1091
  defaultPosition
1014
1092
  }) {
1015
- const zoomPan = useZoomPan({ minScale, maxScale, zoomStep, enablePan, enableWheelZoom });
1093
+ const zoomPan = useZoomPan({ minScale, maxScale, zoomStep, enablePan, enableWheelZoom, enablePinchZoom });
1016
1094
  const [failed, setFailed] = (0, import_react4.useState)(false);
1017
1095
  (0, import_react4.useEffect)(() => setFailed(false), [uri]);
1018
1096
  const handleDownload = enableDownload ? onDownload ?? (() => defaultDownload(uri, fileName)) : void 0;