@atlaskit/media-document-viewer 0.1.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 (55) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +11 -0
  3. package/README.md +9 -0
  4. package/dist/cjs/documentViewer.compiled.css +9 -0
  5. package/dist/cjs/documentViewer.js +56 -0
  6. package/dist/cjs/index.js +19 -0
  7. package/dist/cjs/page.compiled.css +11 -0
  8. package/dist/cjs/page.js +162 -0
  9. package/dist/cjs/types.js +1 -0
  10. package/dist/cjs/usePageContent.js +81 -0
  11. package/dist/cjs/utils/getDocumentRoot.js +20 -0
  12. package/dist/cjs/utils/useCachedGetImage.js +57 -0
  13. package/dist/cjs/utils/useIntersectionObserver.js +65 -0
  14. package/dist/cjs/utils/useStaticCallback.js +14 -0
  15. package/dist/es2019/documentViewer.compiled.css +9 -0
  16. package/dist/es2019/documentViewer.js +46 -0
  17. package/dist/es2019/index.js +2 -0
  18. package/dist/es2019/page.compiled.css +11 -0
  19. package/dist/es2019/page.js +146 -0
  20. package/dist/es2019/types.js +0 -0
  21. package/dist/es2019/usePageContent.js +47 -0
  22. package/dist/es2019/utils/getDocumentRoot.js +14 -0
  23. package/dist/es2019/utils/useCachedGetImage.js +20 -0
  24. package/dist/es2019/utils/useIntersectionObserver.js +55 -0
  25. package/dist/es2019/utils/useStaticCallback.js +6 -0
  26. package/dist/esm/documentViewer.compiled.css +9 -0
  27. package/dist/esm/documentViewer.js +47 -0
  28. package/dist/esm/index.js +2 -0
  29. package/dist/esm/page.compiled.css +11 -0
  30. package/dist/esm/page.js +153 -0
  31. package/dist/esm/types.js +0 -0
  32. package/dist/esm/usePageContent.js +74 -0
  33. package/dist/esm/utils/getDocumentRoot.js +14 -0
  34. package/dist/esm/utils/useCachedGetImage.js +50 -0
  35. package/dist/esm/utils/useIntersectionObserver.js +58 -0
  36. package/dist/esm/utils/useStaticCallback.js +8 -0
  37. package/dist/types/documentViewer.d.ts +10 -0
  38. package/dist/types/index.d.ts +2 -0
  39. package/dist/types/page.d.ts +16 -0
  40. package/dist/types/types.d.ts +42 -0
  41. package/dist/types/usePageContent.d.ts +15 -0
  42. package/dist/types/utils/getDocumentRoot.d.ts +2 -0
  43. package/dist/types/utils/useCachedGetImage.d.ts +1 -0
  44. package/dist/types/utils/useIntersectionObserver.d.ts +5 -0
  45. package/dist/types/utils/useStaticCallback.d.ts +1 -0
  46. package/dist/types-ts4.5/documentViewer.d.ts +10 -0
  47. package/dist/types-ts4.5/index.d.ts +2 -0
  48. package/dist/types-ts4.5/page.d.ts +16 -0
  49. package/dist/types-ts4.5/types.d.ts +42 -0
  50. package/dist/types-ts4.5/usePageContent.d.ts +15 -0
  51. package/dist/types-ts4.5/utils/getDocumentRoot.d.ts +2 -0
  52. package/dist/types-ts4.5/utils/useCachedGetImage.d.ts +1 -0
  53. package/dist/types-ts4.5/utils/useIntersectionObserver.d.ts +5 -0
  54. package/dist/types-ts4.5/utils/useStaticCallback.d.ts +1 -0
  55. package/package.json +92 -0
@@ -0,0 +1,146 @@
1
+ /* page.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import "./page.compiled.css";
3
+ import * as React from 'react';
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import { forwardRef, useEffect, useState } from 'react';
6
+ import { getDocumentRoot } from './utils/getDocumentRoot';
7
+ import { useIntersectionObserver } from './utils/useIntersectionObserver';
8
+ import { useStaticCallback } from './utils/useStaticCallback';
9
+ const Span = ({
10
+ span,
11
+ font
12
+ }) => {
13
+ const width = span.l;
14
+ const height = span.h;
15
+ if (width <= 0) {
16
+ return null;
17
+ }
18
+ return /*#__PURE__*/React.createElement("tspan", {
19
+ lengthAdjust: "spacingAndGlyphs",
20
+ x: span.x,
21
+ y: `-${span.y}`,
22
+ height: height,
23
+ textLength: width,
24
+ style: {
25
+ ['fontFamily']: `${font.name}`,
26
+ ['fontSize']: `${font.size === 1 ? height : font.size}px`
27
+ }
28
+ }, span.text);
29
+ };
30
+ const textStyles = null;
31
+ const Line = ({
32
+ spans,
33
+ rotation,
34
+ fonts,
35
+ dataTestId
36
+ } = {
37
+ spans: [],
38
+ rotation: 0,
39
+ fonts: []
40
+ }) => /*#__PURE__*/React.createElement("text", {
41
+ opacity: "0.5",
42
+ // eslint-disable-next-line react/no-unknown-property
43
+ "transform-origin": `${spans[0].x} -${spans[0].y}`,
44
+ style: {
45
+ transform: `rotate(${rotation}rad)`
46
+ },
47
+ "data-testid": dataTestId,
48
+ className: ax(["_o572qvpr"])
49
+ }, spans.map((span, i) => /*#__PURE__*/React.createElement(Span, {
50
+ span: span,
51
+ font: fonts[span.fi],
52
+ key: i
53
+ })));
54
+ const pageSvgStyles = null;
55
+ const pageImageStyles = null;
56
+ const pageWrapperStyles = null;
57
+ const PageView = /*#__PURE__*/forwardRef(({
58
+ dimensions,
59
+ imageSrc,
60
+ content,
61
+ fonts,
62
+ pageIndex,
63
+ zoom,
64
+ onImageLoad
65
+ }, ref) => {
66
+ const style = {
67
+ width: dimensions ? `calc(var(--document-viewer-zoom) * ${dimensions.width}px)` : 'initial',
68
+ height: dimensions ? `calc(var(--document-viewer-zoom) * ${dimensions.height}px)` : 'initial'
69
+ };
70
+ return /*#__PURE__*/React.createElement("div", {
71
+ ref: ref,
72
+ style: style,
73
+ "data-testid": `page-${pageIndex}`,
74
+ className: ax(["_kqswh2mm _bfhku67f"])
75
+ }, imageSrc && /*#__PURE__*/React.createElement("img", {
76
+ style: style,
77
+ "data-testid": `page-${pageIndex}-image`,
78
+ "data-zoom": zoom,
79
+ src: imageSrc,
80
+ alt: "",
81
+ onLoad: onImageLoad,
82
+ className: ax(["_kqswstnw _154iidpf _1ltvidpf _uiztglyw _1kemd8h4"])
83
+ }), content && /*#__PURE__*/React.createElement("svg", {
84
+ "data-testid": `page-${pageIndex}-text-layer`,
85
+ style: style,
86
+ viewBox: `0 -${content.height} ${content.width} ${content.height}`,
87
+ className: ax(["_kqswstnw _154iidpf _1ltvidpf _uizt1kdv _80om1kdv _lswu1j28"])
88
+ }, content.lines.map((line, i) => /*#__PURE__*/React.createElement(Line, {
89
+ dataTestId: `page-${pageIndex}-line-${i}`,
90
+ spans: line.spans,
91
+ rotation: line.r,
92
+ fonts: fonts,
93
+ key: i
94
+ }))));
95
+ });
96
+ export const Page = ({
97
+ getPageSrc,
98
+ content,
99
+ fonts,
100
+ pageIndex,
101
+ zoom,
102
+ defaultDimensions,
103
+ onVisible
104
+ }) => {
105
+ var _ref;
106
+ const [imageSrc, setImageSrc] = useState();
107
+ const {
108
+ observedRef,
109
+ isVisibleRef
110
+ } = useIntersectionObserver({
111
+ root: getDocumentRoot(),
112
+ // this will load the page 3 pages before or after the current page
113
+ // ensuring that the page is loaded before the user scrolls to it
114
+ rootMargin: '300%',
115
+ threshold: 0.1
116
+ }, () => {
117
+ onVisible();
118
+ getPageSrc(pageIndex, zoom).then(setImageSrc);
119
+ });
120
+ const [dimensions, setDimensions] = useState();
121
+ const onImageLoad = useStaticCallback(event => {
122
+ const image = event.currentTarget;
123
+ if (!content) {
124
+ const zoom = image.dataset.zoom ? Number(image.dataset.zoom) : 1;
125
+ setDimensions({
126
+ width: image.width / zoom,
127
+ height: image.height / zoom
128
+ });
129
+ }
130
+ });
131
+ useEffect(() => {
132
+ if (isVisibleRef.current) {
133
+ getPageSrc(pageIndex, zoom).then(setImageSrc);
134
+ }
135
+ }, [isVisibleRef, pageIndex, zoom, getPageSrc]);
136
+ return /*#__PURE__*/React.createElement(PageView, {
137
+ ref: observedRef,
138
+ dimensions: (_ref = content !== null && content !== void 0 ? content : dimensions) !== null && _ref !== void 0 ? _ref : defaultDimensions,
139
+ imageSrc: imageSrc,
140
+ content: content,
141
+ fonts: fonts,
142
+ pageIndex: pageIndex,
143
+ zoom: zoom,
144
+ onImageLoad: onImageLoad
145
+ });
146
+ };
File without changes
@@ -0,0 +1,47 @@
1
+ import { useMemo, useRef, useState } from "react";
2
+ import { useStaticCallback } from "./utils/useStaticCallback";
3
+ export function usePageContent(getContent, paginationSize) {
4
+ const [contentRanges, setContentRanges] = useState([]);
5
+ const contentRangesRequestRef = useRef({});
6
+ const loadPageContent = useStaticCallback(async pageInd => {
7
+ const contentRangeInd = Math.floor(pageInd / paginationSize);
8
+ // Content already loaded for this page range
9
+ if (contentRanges[contentRangeInd]) {
10
+ return;
11
+ }
12
+ const startIndex = contentRangeInd * paginationSize;
13
+ const endIndex = startIndex + paginationSize;
14
+ contentRangesRequestRef.current[contentRangeInd] ??= getContent(startIndex, endIndex);
15
+ const content = await contentRangesRequestRef.current[contentRangeInd];
16
+ setContentRanges(prev => {
17
+ const newRanges = [...prev];
18
+ newRanges[contentRangeInd] = content;
19
+ return newRanges;
20
+ });
21
+ });
22
+ function getPageContent(pageInd) {
23
+ var _contentRanges$conten, _contentRanges$conten2;
24
+ const contentRangeInd = Math.floor(pageInd / paginationSize);
25
+ const page = (_contentRanges$conten = contentRanges[contentRangeInd]) === null || _contentRanges$conten === void 0 ? void 0 : _contentRanges$conten.pages[pageInd % paginationSize];
26
+ const fonts = (_contentRanges$conten2 = contentRanges[contentRangeInd]) === null || _contentRanges$conten2 === void 0 ? void 0 : _contentRanges$conten2.fonts;
27
+ return {
28
+ page,
29
+ fonts
30
+ };
31
+ }
32
+ const documentMetadata = useMemo(() => {
33
+ var _contentRanges$, _contentRanges$0$tota, _contentRanges$2;
34
+ return {
35
+ defaultDimensions: (_contentRanges$ = contentRanges[0]) !== null && _contentRanges$ !== void 0 && _contentRanges$.pages[0] ? {
36
+ height: contentRanges[0].pages[0].height,
37
+ width: contentRanges[0].pages[0].width
38
+ } : undefined,
39
+ pageCount: (_contentRanges$0$tota = (_contentRanges$2 = contentRanges[0]) === null || _contentRanges$2 === void 0 ? void 0 : _contentRanges$2.total_pages) !== null && _contentRanges$0$tota !== void 0 ? _contentRanges$0$tota : 4
40
+ };
41
+ }, [contentRanges]);
42
+ return {
43
+ getPageContent,
44
+ loadPageContent,
45
+ documentMetadata
46
+ };
47
+ }
@@ -0,0 +1,14 @@
1
+ export const DOCUMENT_SCROLL_ROOT_ID = 'document-scroll-root';
2
+ export const getDocumentRoot = () => {
3
+ if (typeof window === 'undefined') {
4
+ return;
5
+ }
6
+ if (typeof window.document === 'undefined') {
7
+ return;
8
+ }
9
+ const root = document.getElementById(DOCUMENT_SCROLL_ROOT_ID);
10
+ if (root) {
11
+ return root;
12
+ }
13
+ return window.document;
14
+ };
@@ -0,0 +1,20 @@
1
+ import { useRef } from "react";
2
+ import { useStaticCallback } from "./useStaticCallback";
3
+ export const useCachedGetImage = getPageImageUrl => {
4
+ const imageUrlRefs = useRef({});
5
+ const getImageUrl = useStaticCallback(async (pageNumber, zoom) => {
6
+ const key = `${pageNumber}-${zoom}`;
7
+ if (imageUrlRefs.current[key]) {
8
+ return imageUrlRefs.current[key];
9
+ }
10
+ let url = await getPageImageUrl(pageNumber, zoom);
11
+ const isBlobUrl = url.startsWith('blob:');
12
+ if (!isBlobUrl) {
13
+ const blob = await fetch(url).then(res => res.blob());
14
+ url = URL.createObjectURL(blob);
15
+ }
16
+ imageUrlRefs.current[key] = url;
17
+ return url;
18
+ });
19
+ return getImageUrl;
20
+ };
@@ -0,0 +1,55 @@
1
+ import { useEffect, useRef } from "react";
2
+ import { useStaticCallback } from "./useStaticCallback";
3
+ export const useIntersectionObserver = (options, onVisible) => {
4
+ const staticOnVisible = useStaticCallback(onVisible);
5
+ const observerRef = useRef(null);
6
+ const timeoutRef = useRef(null);
7
+ const isVisibleRef = useRef(false);
8
+ const currentNodeRef = useRef(null);
9
+ const observedRef = useStaticCallback(node => {
10
+ currentNodeRef.current = node;
11
+ if (observerRef.current) {
12
+ observerRef.current.disconnect();
13
+ }
14
+ if (timeoutRef.current) {
15
+ clearTimeout(timeoutRef.current);
16
+ timeoutRef.current = null;
17
+ }
18
+ if (node) {
19
+ observerRef.current = new IntersectionObserver(([entry]) => {
20
+ if (entry.isIntersecting && !isVisibleRef.current) {
21
+ isVisibleRef.current = true;
22
+ timeoutRef.current = setTimeout(() => {
23
+ if (isVisibleRef.current) {
24
+ staticOnVisible();
25
+ timeoutRef.current = null;
26
+ }
27
+ }, 100);
28
+ }
29
+ if (!entry.isIntersecting && isVisibleRef.current) {
30
+ isVisibleRef.current = false;
31
+ }
32
+ if (!entry.isIntersecting && isVisibleRef.current && timeoutRef.current) {
33
+ isVisibleRef.current = false;
34
+ clearTimeout(timeoutRef.current);
35
+ timeoutRef.current = null;
36
+ }
37
+ }, options);
38
+ observerRef.current.observe(node);
39
+ }
40
+ });
41
+ useEffect(() => {
42
+ return () => {
43
+ if (observerRef.current) {
44
+ observerRef.current.disconnect();
45
+ }
46
+ if (timeoutRef.current) {
47
+ clearTimeout(timeoutRef.current);
48
+ }
49
+ };
50
+ }, []);
51
+ return {
52
+ observedRef,
53
+ isVisibleRef
54
+ };
55
+ };
@@ -0,0 +1,6 @@
1
+ import { useCallback, useRef } from "react";
2
+ export const useStaticCallback = callback => {
3
+ const callbackRef = useRef(callback);
4
+ callbackRef.current = callback;
5
+ return useCallback((...args) => callbackRef.current(...args), []);
6
+ };
@@ -0,0 +1,9 @@
1
+
2
+ ._zulputpp{gap:var(--ds-space-150,9pt)}._18m91wug{overflow-y:auto}
3
+ ._19pkxncg{margin-top:var(--ds-space-800,4pc)}
4
+ ._1bah1h6o{justify-content:center}
5
+ ._1e0c1txw{display:flex}
6
+ ._1reo1wug{overflow-x:auto}
7
+ ._1ul91osq{min-width:100%}
8
+ ._2lx21bp4{flex-direction:column}
9
+ ._4cvr1h6o{align-items:center}
@@ -0,0 +1,47 @@
1
+ /* documentViewer.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ import "./documentViewer.compiled.css";
4
+ import * as React from 'react';
5
+ import { ax, ix } from "@compiled/react/runtime";
6
+ import { Page } from './page';
7
+ import { usePageContent } from './usePageContent';
8
+ import { useCachedGetImage } from './utils/useCachedGetImage';
9
+ var documentViewerStyles = null;
10
+ var DEFAULT_PAGINATION_SIZE = 50;
11
+ export var DocumentViewer = function DocumentViewer(_ref) {
12
+ var _documentMetadata$pag;
13
+ var getContent = _ref.getContent,
14
+ getPageImageUrl = _ref.getPageImageUrl,
15
+ _ref$paginationSize = _ref.paginationSize,
16
+ paginationSize = _ref$paginationSize === void 0 ? DEFAULT_PAGINATION_SIZE : _ref$paginationSize,
17
+ zoom = _ref.zoom;
18
+ var _usePageContent = usePageContent(getContent, paginationSize),
19
+ getPageContent = _usePageContent.getPageContent,
20
+ loadPageContent = _usePageContent.loadPageContent,
21
+ documentMetadata = _usePageContent.documentMetadata;
22
+ var getImageUrl = useCachedGetImage(getPageImageUrl);
23
+ var style = {
24
+ '--document-viewer-zoom': zoom
25
+ };
26
+ return /*#__PURE__*/React.createElement("div", {
27
+ "data-testid": "document-viewer",
28
+ style: style,
29
+ className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _4cvr1h6o _1bah1h6o"])
30
+ }, _toConsumableArray(Array((_documentMetadata$pag = documentMetadata.pageCount) !== null && _documentMetadata$pag !== void 0 ? _documentMetadata$pag : 4)).map(function (_, i) {
31
+ var _getPageContent = getPageContent(i),
32
+ page = _getPageContent.page,
33
+ fonts = _getPageContent.fonts;
34
+ return /*#__PURE__*/React.createElement(Page, {
35
+ key: i,
36
+ getPageSrc: getImageUrl,
37
+ pageIndex: i,
38
+ zoom: zoom,
39
+ defaultDimensions: documentMetadata.defaultDimensions,
40
+ onVisible: function onVisible() {
41
+ return loadPageContent(i);
42
+ },
43
+ fonts: fonts,
44
+ content: page
45
+ });
46
+ }));
47
+ };
@@ -0,0 +1,2 @@
1
+ export { DocumentViewer } from './documentViewer';
2
+ export { DOCUMENT_SCROLL_ROOT_ID } from './utils/getDocumentRoot';
@@ -0,0 +1,11 @@
1
+ ._154iidpf{top:0}
2
+ ._1kemd8h4{image-rendering:pixelated}
3
+ ._1ltvidpf{left:0}
4
+ ._80om1kdv{cursor:text}
5
+ ._bfhku67f{background-color:#fff}
6
+ ._kqswh2mm{position:relative}
7
+ ._kqswstnw{position:absolute}
8
+ ._lswu1j28{fill:transparent}
9
+ ._o572qvpr{white-space:pre}
10
+ ._uizt1kdv{-webkit-user-select:text;-ms-user-select:text;user-select:text}
11
+ ._uiztglyw{-webkit-user-select:none;-ms-user-select:none;user-select:none}
@@ -0,0 +1,153 @@
1
+ /* page.tsx generated by @compiled/babel-plugin v0.36.1 */
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
+ import "./page.compiled.css";
5
+ import * as React from 'react';
6
+ import { ax, ix } from "@compiled/react/runtime";
7
+ import { forwardRef, useEffect, useState } from 'react';
8
+ import { getDocumentRoot } from './utils/getDocumentRoot';
9
+ import { useIntersectionObserver } from './utils/useIntersectionObserver';
10
+ import { useStaticCallback } from './utils/useStaticCallback';
11
+ var Span = function Span(_ref) {
12
+ var span = _ref.span,
13
+ font = _ref.font;
14
+ var width = span.l;
15
+ var height = span.h;
16
+ if (width <= 0) {
17
+ return null;
18
+ }
19
+ return /*#__PURE__*/React.createElement("tspan", {
20
+ lengthAdjust: "spacingAndGlyphs",
21
+ x: span.x,
22
+ y: "-".concat(span.y),
23
+ height: height,
24
+ textLength: width,
25
+ style: _defineProperty(_defineProperty({}, 'fontFamily', "".concat(font.name)), 'fontSize', "".concat(font.size === 1 ? height : font.size, "px"))
26
+ }, span.text);
27
+ };
28
+ var textStyles = null;
29
+ var Line = function Line() {
30
+ var _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
31
+ spans: [],
32
+ rotation: 0,
33
+ fonts: []
34
+ },
35
+ spans = _ref3.spans,
36
+ rotation = _ref3.rotation,
37
+ fonts = _ref3.fonts,
38
+ dataTestId = _ref3.dataTestId;
39
+ return /*#__PURE__*/React.createElement("text", {
40
+ opacity: "0.5",
41
+ // eslint-disable-next-line react/no-unknown-property
42
+ "transform-origin": "".concat(spans[0].x, " -").concat(spans[0].y),
43
+ style: {
44
+ transform: "rotate(".concat(rotation, "rad)")
45
+ },
46
+ "data-testid": dataTestId,
47
+ className: ax(["_o572qvpr"])
48
+ }, spans.map(function (span, i) {
49
+ return /*#__PURE__*/React.createElement(Span, {
50
+ span: span,
51
+ font: fonts[span.fi],
52
+ key: i
53
+ });
54
+ }));
55
+ };
56
+ var pageSvgStyles = null;
57
+ var pageImageStyles = null;
58
+ var pageWrapperStyles = null;
59
+ var PageView = /*#__PURE__*/forwardRef(function (_ref4, ref) {
60
+ var dimensions = _ref4.dimensions,
61
+ imageSrc = _ref4.imageSrc,
62
+ content = _ref4.content,
63
+ fonts = _ref4.fonts,
64
+ pageIndex = _ref4.pageIndex,
65
+ zoom = _ref4.zoom,
66
+ onImageLoad = _ref4.onImageLoad;
67
+ var style = {
68
+ width: dimensions ? "calc(var(--document-viewer-zoom) * ".concat(dimensions.width, "px)") : 'initial',
69
+ height: dimensions ? "calc(var(--document-viewer-zoom) * ".concat(dimensions.height, "px)") : 'initial'
70
+ };
71
+ return /*#__PURE__*/React.createElement("div", {
72
+ ref: ref,
73
+ style: style,
74
+ "data-testid": "page-".concat(pageIndex),
75
+ className: ax(["_kqswh2mm _bfhku67f"])
76
+ }, imageSrc && /*#__PURE__*/React.createElement("img", {
77
+ style: style,
78
+ "data-testid": "page-".concat(pageIndex, "-image"),
79
+ "data-zoom": zoom,
80
+ src: imageSrc,
81
+ alt: "",
82
+ onLoad: onImageLoad,
83
+ className: ax(["_kqswstnw _154iidpf _1ltvidpf _uiztglyw _1kemd8h4"])
84
+ }), content && /*#__PURE__*/React.createElement("svg", {
85
+ "data-testid": "page-".concat(pageIndex, "-text-layer"),
86
+ style: style,
87
+ viewBox: "0 -".concat(content.height, " ").concat(content.width, " ").concat(content.height),
88
+ className: ax(["_kqswstnw _154iidpf _1ltvidpf _uizt1kdv _80om1kdv _lswu1j28"])
89
+ }, content.lines.map(function (line, i) {
90
+ return /*#__PURE__*/React.createElement(Line, {
91
+ dataTestId: "page-".concat(pageIndex, "-line-").concat(i),
92
+ spans: line.spans,
93
+ rotation: line.r,
94
+ fonts: fonts,
95
+ key: i
96
+ });
97
+ })));
98
+ });
99
+ export var Page = function Page(_ref5) {
100
+ var _ref6;
101
+ var getPageSrc = _ref5.getPageSrc,
102
+ content = _ref5.content,
103
+ fonts = _ref5.fonts,
104
+ pageIndex = _ref5.pageIndex,
105
+ zoom = _ref5.zoom,
106
+ defaultDimensions = _ref5.defaultDimensions,
107
+ onVisible = _ref5.onVisible;
108
+ var _useState = useState(),
109
+ _useState2 = _slicedToArray(_useState, 2),
110
+ imageSrc = _useState2[0],
111
+ setImageSrc = _useState2[1];
112
+ var _useIntersectionObser = useIntersectionObserver({
113
+ root: getDocumentRoot(),
114
+ // this will load the page 3 pages before or after the current page
115
+ // ensuring that the page is loaded before the user scrolls to it
116
+ rootMargin: '300%',
117
+ threshold: 0.1
118
+ }, function () {
119
+ onVisible();
120
+ getPageSrc(pageIndex, zoom).then(setImageSrc);
121
+ }),
122
+ observedRef = _useIntersectionObser.observedRef,
123
+ isVisibleRef = _useIntersectionObser.isVisibleRef;
124
+ var _useState3 = useState(),
125
+ _useState4 = _slicedToArray(_useState3, 2),
126
+ dimensions = _useState4[0],
127
+ setDimensions = _useState4[1];
128
+ var onImageLoad = useStaticCallback(function (event) {
129
+ var image = event.currentTarget;
130
+ if (!content) {
131
+ var _zoom = image.dataset.zoom ? Number(image.dataset.zoom) : 1;
132
+ setDimensions({
133
+ width: image.width / _zoom,
134
+ height: image.height / _zoom
135
+ });
136
+ }
137
+ });
138
+ useEffect(function () {
139
+ if (isVisibleRef.current) {
140
+ getPageSrc(pageIndex, zoom).then(setImageSrc);
141
+ }
142
+ }, [isVisibleRef, pageIndex, zoom, getPageSrc]);
143
+ return /*#__PURE__*/React.createElement(PageView, {
144
+ ref: observedRef,
145
+ dimensions: (_ref6 = content !== null && content !== void 0 ? content : dimensions) !== null && _ref6 !== void 0 ? _ref6 : defaultDimensions,
146
+ imageSrc: imageSrc,
147
+ content: content,
148
+ fonts: fonts,
149
+ pageIndex: pageIndex,
150
+ zoom: zoom,
151
+ onImageLoad: onImageLoad
152
+ });
153
+ };
File without changes
@@ -0,0 +1,74 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
5
+ import { useMemo, useRef, useState } from "react";
6
+ import { useStaticCallback } from "./utils/useStaticCallback";
7
+ export function usePageContent(getContent, paginationSize) {
8
+ var _useState = useState([]),
9
+ _useState2 = _slicedToArray(_useState, 2),
10
+ contentRanges = _useState2[0],
11
+ setContentRanges = _useState2[1];
12
+ var contentRangesRequestRef = useRef({});
13
+ var loadPageContent = useStaticCallback( /*#__PURE__*/function () {
14
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(pageInd) {
15
+ var _contentRangesRequest, _contentRangesRequest2;
16
+ var contentRangeInd, startIndex, endIndex, content;
17
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
18
+ while (1) switch (_context.prev = _context.next) {
19
+ case 0:
20
+ contentRangeInd = Math.floor(pageInd / paginationSize); // Content already loaded for this page range
21
+ if (!contentRanges[contentRangeInd]) {
22
+ _context.next = 3;
23
+ break;
24
+ }
25
+ return _context.abrupt("return");
26
+ case 3:
27
+ startIndex = contentRangeInd * paginationSize;
28
+ endIndex = startIndex + paginationSize;
29
+ (_contentRangesRequest2 = (_contentRangesRequest = contentRangesRequestRef.current)[contentRangeInd]) !== null && _contentRangesRequest2 !== void 0 ? _contentRangesRequest2 : _contentRangesRequest[contentRangeInd] = getContent(startIndex, endIndex);
30
+ _context.next = 8;
31
+ return contentRangesRequestRef.current[contentRangeInd];
32
+ case 8:
33
+ content = _context.sent;
34
+ setContentRanges(function (prev) {
35
+ var newRanges = _toConsumableArray(prev);
36
+ newRanges[contentRangeInd] = content;
37
+ return newRanges;
38
+ });
39
+ case 10:
40
+ case "end":
41
+ return _context.stop();
42
+ }
43
+ }, _callee);
44
+ }));
45
+ return function (_x) {
46
+ return _ref.apply(this, arguments);
47
+ };
48
+ }());
49
+ function getPageContent(pageInd) {
50
+ var _contentRanges$conten, _contentRanges$conten2;
51
+ var contentRangeInd = Math.floor(pageInd / paginationSize);
52
+ var page = (_contentRanges$conten = contentRanges[contentRangeInd]) === null || _contentRanges$conten === void 0 ? void 0 : _contentRanges$conten.pages[pageInd % paginationSize];
53
+ var fonts = (_contentRanges$conten2 = contentRanges[contentRangeInd]) === null || _contentRanges$conten2 === void 0 ? void 0 : _contentRanges$conten2.fonts;
54
+ return {
55
+ page: page,
56
+ fonts: fonts
57
+ };
58
+ }
59
+ var documentMetadata = useMemo(function () {
60
+ var _contentRanges$, _contentRanges$0$tota, _contentRanges$2;
61
+ return {
62
+ defaultDimensions: (_contentRanges$ = contentRanges[0]) !== null && _contentRanges$ !== void 0 && _contentRanges$.pages[0] ? {
63
+ height: contentRanges[0].pages[0].height,
64
+ width: contentRanges[0].pages[0].width
65
+ } : undefined,
66
+ pageCount: (_contentRanges$0$tota = (_contentRanges$2 = contentRanges[0]) === null || _contentRanges$2 === void 0 ? void 0 : _contentRanges$2.total_pages) !== null && _contentRanges$0$tota !== void 0 ? _contentRanges$0$tota : 4
67
+ };
68
+ }, [contentRanges]);
69
+ return {
70
+ getPageContent: getPageContent,
71
+ loadPageContent: loadPageContent,
72
+ documentMetadata: documentMetadata
73
+ };
74
+ }
@@ -0,0 +1,14 @@
1
+ export var DOCUMENT_SCROLL_ROOT_ID = 'document-scroll-root';
2
+ export var getDocumentRoot = function getDocumentRoot() {
3
+ if (typeof window === 'undefined') {
4
+ return;
5
+ }
6
+ if (typeof window.document === 'undefined') {
7
+ return;
8
+ }
9
+ var root = document.getElementById(DOCUMENT_SCROLL_ROOT_ID);
10
+ if (root) {
11
+ return root;
12
+ }
13
+ return window.document;
14
+ };
@@ -0,0 +1,50 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
3
+ import { useRef } from "react";
4
+ import { useStaticCallback } from "./useStaticCallback";
5
+ export var useCachedGetImage = function useCachedGetImage(getPageImageUrl) {
6
+ var imageUrlRefs = useRef({});
7
+ var getImageUrl = useStaticCallback( /*#__PURE__*/function () {
8
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(pageNumber, zoom) {
9
+ var key, url, isBlobUrl, blob;
10
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
11
+ while (1) switch (_context.prev = _context.next) {
12
+ case 0:
13
+ key = "".concat(pageNumber, "-").concat(zoom);
14
+ if (!imageUrlRefs.current[key]) {
15
+ _context.next = 3;
16
+ break;
17
+ }
18
+ return _context.abrupt("return", imageUrlRefs.current[key]);
19
+ case 3:
20
+ _context.next = 5;
21
+ return getPageImageUrl(pageNumber, zoom);
22
+ case 5:
23
+ url = _context.sent;
24
+ isBlobUrl = url.startsWith('blob:');
25
+ if (isBlobUrl) {
26
+ _context.next = 12;
27
+ break;
28
+ }
29
+ _context.next = 10;
30
+ return fetch(url).then(function (res) {
31
+ return res.blob();
32
+ });
33
+ case 10:
34
+ blob = _context.sent;
35
+ url = URL.createObjectURL(blob);
36
+ case 12:
37
+ imageUrlRefs.current[key] = url;
38
+ return _context.abrupt("return", url);
39
+ case 14:
40
+ case "end":
41
+ return _context.stop();
42
+ }
43
+ }, _callee);
44
+ }));
45
+ return function (_x, _x2) {
46
+ return _ref.apply(this, arguments);
47
+ };
48
+ }());
49
+ return getImageUrl;
50
+ };