@atlaskit/media-document-viewer 0.6.11 → 0.7.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.
- package/CHANGELOG.md +14 -0
- package/dist/cjs/documentLinks.js +9 -3
- package/dist/cjs/documentViewer.js +178 -29
- package/dist/cjs/page.js +9 -5
- package/dist/es2019/documentLinks.js +7 -3
- package/dist/es2019/documentViewer.js +168 -27
- package/dist/es2019/page.js +9 -5
- package/dist/esm/documentLinks.js +9 -3
- package/dist/esm/documentViewer.js +179 -30
- package/dist/esm/page.js +9 -5
- package/dist/types/documentLinks.d.ts +2 -1
- package/dist/types/documentViewer.d.ts +7 -1
- package/dist/types/page.d.ts +9 -2
- package/dist/types-ts4.5/documentLinks.d.ts +2 -1
- package/dist/types-ts4.5/documentViewer.d.ts +7 -1
- package/dist/types-ts4.5/page.d.ts +9 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @atlaskit/media-document-viewer
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`34c40eb233aa4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/34c40eb233aa4) -
|
|
8
|
+
isUxChange: true
|
|
9
|
+
|
|
10
|
+
Lazy-append document pages for MS Excel previews behind platform_media_excel_lazy_load gate to fix
|
|
11
|
+
initial-render freeze on very large documents
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
|
|
3
17
|
## 0.6.11
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -20,7 +20,8 @@ var anchorStyles = {
|
|
|
20
20
|
};
|
|
21
21
|
var DocumentLink = function DocumentLink(_ref) {
|
|
22
22
|
var link = _ref.link,
|
|
23
|
-
dataTestId = _ref.dataTestId
|
|
23
|
+
dataTestId = _ref.dataTestId,
|
|
24
|
+
appendUpTo = _ref.appendUpTo;
|
|
24
25
|
return /*#__PURE__*/_react.default.createElement("foreignObject", {
|
|
25
26
|
x: link.x,
|
|
26
27
|
y: -link.y,
|
|
@@ -34,15 +35,20 @@ var DocumentLink = function DocumentLink(_ref) {
|
|
|
34
35
|
style: anchorStyles
|
|
35
36
|
})) : /*#__PURE__*/_react.default.createElement(_anchor.default, (0, _extends2.default)({}, foreignObjectProps, {
|
|
36
37
|
href: "#page-".concat(link.p_num + 1),
|
|
37
|
-
style: anchorStyles
|
|
38
|
+
style: anchorStyles,
|
|
39
|
+
onClick: appendUpTo ? function () {
|
|
40
|
+
return appendUpTo(link.p_num + 1);
|
|
41
|
+
} : undefined
|
|
38
42
|
})));
|
|
39
43
|
};
|
|
40
44
|
var DocumentLinks = exports.DocumentLinks = function DocumentLinks(_ref2) {
|
|
41
|
-
var links = _ref2.links
|
|
45
|
+
var links = _ref2.links,
|
|
46
|
+
appendUpTo = _ref2.appendUpTo;
|
|
42
47
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, links.map(function (link, i) {
|
|
43
48
|
return /*#__PURE__*/_react.default.createElement(DocumentLink, {
|
|
44
49
|
link: link,
|
|
45
50
|
dataTestId: "document-link-".concat(i),
|
|
51
|
+
appendUpTo: appendUpTo,
|
|
46
52
|
key: i
|
|
47
53
|
});
|
|
48
54
|
}));
|
|
@@ -11,7 +11,9 @@ require("./documentViewer.compiled.css");
|
|
|
11
11
|
var _react = _interopRequireWildcard(require("react"));
|
|
12
12
|
var React = _react;
|
|
13
13
|
var _runtime = require("@compiled/react/runtime");
|
|
14
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
14
15
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
16
|
+
var _browserApis = require("@atlaskit/browser-apis");
|
|
15
17
|
var _mediaCommon = require("@atlaskit/media-common");
|
|
16
18
|
var _page = require("./page");
|
|
17
19
|
var _usePageContent2 = require("./usePageContent");
|
|
@@ -20,14 +22,173 @@ var _useCachedGetImage = require("./utils/useCachedGetImage");
|
|
|
20
22
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
21
23
|
var documentViewerStyles = null;
|
|
22
24
|
var DEFAULT_PAGINATION_SIZE = 50;
|
|
23
|
-
var
|
|
25
|
+
var INITIAL_PAGE_COUNT = 50;
|
|
26
|
+
var APPEND_STEP = 50;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* TAIL-APPEND PATTERN FOR LAZY LOADING:
|
|
30
|
+
*
|
|
31
|
+
* The <Page> component has an `onVisible: () => void` prop that is called when the page
|
|
32
|
+
* enters the viewport (via useIntersectionObserver with a 300% rootMargin). This callback
|
|
33
|
+
* is currently used to load page content via `loadPageContent(i)`.
|
|
34
|
+
*
|
|
35
|
+
* For the LazyAppendPages feature (T2.3), the parent component can leverage this same
|
|
36
|
+
* mechanism by:
|
|
37
|
+
* 1. Rendering only a subset of pages (lazyPageCount instead of all documentMetadata.pageCount)
|
|
38
|
+
* 2. Passing onVisible={handleAppend} ONLY to the last rendered page (i === lazyPageCount - 1)
|
|
39
|
+
* 3. For all other pages, passing onVisible={() => loadPageContent(i)} as usual
|
|
40
|
+
*
|
|
41
|
+
* When the last page enters the viewport, handleAppend will be triggered, which can:
|
|
42
|
+
* - Fetch the next batch of pages
|
|
43
|
+
* - Append them to the rendered page list
|
|
44
|
+
* - This effectively creates a tail-append/infinite-scroll behavior without any changes to <Page>
|
|
45
|
+
*
|
|
46
|
+
* No changes to the <Page> signature are required. The onVisible callback is already
|
|
47
|
+
* properly wired and can be overridden by parent components for different behaviors.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
var LegacyPages = function LegacyPages(_ref) {
|
|
24
51
|
var _documentMetadata$pag;
|
|
25
|
-
var
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
52
|
+
var documentMetadata = _ref.documentMetadata,
|
|
53
|
+
getPageContent = _ref.getPageContent,
|
|
54
|
+
loadPageContent = _ref.loadPageContent,
|
|
55
|
+
getImageUrl = _ref.getImageUrl,
|
|
56
|
+
zoom = _ref.zoom,
|
|
57
|
+
onSuccess = _ref.onSuccess,
|
|
58
|
+
style = _ref.style,
|
|
59
|
+
onTouchStart = _ref.onTouchStart,
|
|
60
|
+
onTouchMove = _ref.onTouchMove,
|
|
61
|
+
onTouchEnd = _ref.onTouchEnd;
|
|
62
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
63
|
+
"data-testid": "document-viewer",
|
|
64
|
+
style: style,
|
|
65
|
+
onTouchStart: onTouchStart,
|
|
66
|
+
onTouchMove: onTouchMove,
|
|
67
|
+
onTouchEnd: onTouchEnd,
|
|
68
|
+
className: (0, _runtime.ax)(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _1bsb1ris"])
|
|
69
|
+
}, (0, _toConsumableArray2.default)(Array((_documentMetadata$pag = documentMetadata.pageCount) !== null && _documentMetadata$pag !== void 0 ? _documentMetadata$pag : 4)).map(function (_, i) {
|
|
70
|
+
var _getPageContent = getPageContent(i),
|
|
71
|
+
page = _getPageContent.page,
|
|
72
|
+
fonts = _getPageContent.fonts;
|
|
73
|
+
return /*#__PURE__*/React.createElement(_page.Page, {
|
|
74
|
+
key: i,
|
|
75
|
+
getPageSrc: getImageUrl,
|
|
76
|
+
pageIndex: i,
|
|
77
|
+
zoom: zoom,
|
|
78
|
+
defaultDimensions: documentMetadata.defaultDimensions,
|
|
79
|
+
onVisible: loadPageContent,
|
|
80
|
+
onLoad: i === 0 ? onSuccess : undefined,
|
|
81
|
+
fonts: fonts,
|
|
82
|
+
content: page
|
|
83
|
+
});
|
|
84
|
+
}));
|
|
85
|
+
};
|
|
86
|
+
var LazyAppendPages = function LazyAppendPages(_ref2) {
|
|
87
|
+
var _documentMetadata$pag2;
|
|
88
|
+
var documentMetadata = _ref2.documentMetadata,
|
|
89
|
+
getPageContent = _ref2.getPageContent,
|
|
90
|
+
loadPageContent = _ref2.loadPageContent,
|
|
91
|
+
getImageUrl = _ref2.getImageUrl,
|
|
92
|
+
zoom = _ref2.zoom,
|
|
93
|
+
onSuccess = _ref2.onSuccess,
|
|
94
|
+
style = _ref2.style,
|
|
95
|
+
onTouchStart = _ref2.onTouchStart,
|
|
96
|
+
onTouchMove = _ref2.onTouchMove,
|
|
97
|
+
onTouchEnd = _ref2.onTouchEnd;
|
|
98
|
+
var totalPages = (_documentMetadata$pag2 = documentMetadata.pageCount) !== null && _documentMetadata$pag2 !== void 0 ? _documentMetadata$pag2 : 4;
|
|
99
|
+
var _useState = (0, _react.useState)(function () {
|
|
100
|
+
return Math.min(INITIAL_PAGE_COUNT, totalPages);
|
|
101
|
+
}),
|
|
102
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
103
|
+
lazyPageCount = _useState2[0],
|
|
104
|
+
setLazyPageCount = _useState2[1];
|
|
105
|
+
|
|
106
|
+
// lastAppendTriggerIndex deduplicates: only append when a strictly-larger
|
|
107
|
+
// tail page fires onVisible. This prevents double-append on scroll-up-then-down.
|
|
108
|
+
var lastAppendTriggerIndex = (0, _react.useRef)(-1);
|
|
109
|
+
|
|
110
|
+
// Handle #page-N URL hash on first load: fast-forward lazyPageCount to include the target page.
|
|
111
|
+
// Capture totalPages in a ref so the one-shot effect can read it without being re-run when
|
|
112
|
+
// totalPages changes (the effect must only fire once, on mount).
|
|
113
|
+
var totalPagesRef = (0, _react.useRef)(totalPages);
|
|
114
|
+
(0, _react.useEffect)(function () {
|
|
115
|
+
var total = totalPagesRef.current;
|
|
116
|
+
var hash = window.location.hash;
|
|
117
|
+
var match = hash.match(/^#page-(\d+)$/);
|
|
118
|
+
if (match) {
|
|
119
|
+
var targetPage = parseInt(match[1], 10);
|
|
120
|
+
if (targetPage >= 1 && targetPage <= total) {
|
|
121
|
+
// Update dedup ref BEFORE setLazyPageCount so handleAppend does not
|
|
122
|
+
// cascade when the new tail page enters the viewport via IntersectionObserver.
|
|
123
|
+
lastAppendTriggerIndex.current = targetPage - 1;
|
|
124
|
+
// Fast-forward lazyPageCount to include the target page
|
|
125
|
+
setLazyPageCount(function (prev) {
|
|
126
|
+
return Math.max(prev, targetPage);
|
|
127
|
+
});
|
|
128
|
+
// After the pages are mounted (next animation frame), scroll to the target
|
|
129
|
+
requestAnimationFrame(function () {
|
|
130
|
+
var _getDocument;
|
|
131
|
+
var el = (_getDocument = (0, _browserApis.getDocument)()) === null || _getDocument === void 0 ? void 0 : _getDocument.getElementById("page-".concat(targetPage));
|
|
132
|
+
if (el) {
|
|
133
|
+
el.scrollIntoView();
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps -- intentionally one-shot; totalPages read via ref
|
|
139
|
+
|
|
140
|
+
var handleAppendAndLoadPageContent = (0, _react.useCallback)(function (pageIndex) {
|
|
141
|
+
if (pageIndex > lastAppendTriggerIndex.current) {
|
|
142
|
+
lastAppendTriggerIndex.current = pageIndex;
|
|
143
|
+
setLazyPageCount(function (c) {
|
|
144
|
+
return Math.min(c + APPEND_STEP, totalPages);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
loadPageContent(pageIndex);
|
|
148
|
+
}, [totalPages, loadPageContent]);
|
|
149
|
+
var appendUpTo = (0, _react.useCallback)(function (targetPage) {
|
|
150
|
+
var clamped = Math.min(Math.max(targetPage, 0), totalPages);
|
|
151
|
+
if (clamped > lastAppendTriggerIndex.current) {
|
|
152
|
+
lastAppendTriggerIndex.current = clamped - 1;
|
|
153
|
+
setLazyPageCount(function (prev) {
|
|
154
|
+
return Math.max(prev, clamped);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}, [totalPages]);
|
|
158
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
159
|
+
"data-testid": "document-viewer",
|
|
160
|
+
style: style,
|
|
161
|
+
onTouchStart: onTouchStart,
|
|
162
|
+
onTouchMove: onTouchMove,
|
|
163
|
+
onTouchEnd: onTouchEnd,
|
|
164
|
+
className: (0, _runtime.ax)(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _1bsb1ris"])
|
|
165
|
+
}, (0, _toConsumableArray2.default)(Array(lazyPageCount)).map(function (_, i) {
|
|
166
|
+
var _getPageContent2 = getPageContent(i),
|
|
167
|
+
page = _getPageContent2.page,
|
|
168
|
+
fonts = _getPageContent2.fonts;
|
|
169
|
+
return /*#__PURE__*/React.createElement(_page.Page, {
|
|
170
|
+
key: i,
|
|
171
|
+
getPageSrc: getImageUrl,
|
|
172
|
+
pageIndex: i,
|
|
173
|
+
zoom: zoom,
|
|
174
|
+
defaultDimensions: documentMetadata.defaultDimensions,
|
|
175
|
+
onVisible: i === lazyPageCount - 1 ? handleAppendAndLoadPageContent : loadPageContent,
|
|
176
|
+
onLoad: i === 0 ? onSuccess : undefined,
|
|
177
|
+
fonts: fonts,
|
|
178
|
+
content: page,
|
|
179
|
+
appendUpTo: appendUpTo
|
|
180
|
+
});
|
|
181
|
+
}));
|
|
182
|
+
};
|
|
183
|
+
var DocumentViewer = exports.DocumentViewer = function DocumentViewer(_ref3) {
|
|
184
|
+
var onSuccess = _ref3.onSuccess,
|
|
185
|
+
getContent = _ref3.getContent,
|
|
186
|
+
getPageImageUrl = _ref3.getPageImageUrl,
|
|
187
|
+
_ref3$paginationSize = _ref3.paginationSize,
|
|
188
|
+
paginationSize = _ref3$paginationSize === void 0 ? DEFAULT_PAGINATION_SIZE : _ref3$paginationSize,
|
|
189
|
+
zoom = _ref3.zoom,
|
|
190
|
+
_ref3$enableLazyPageR = _ref3.enableLazyPageRendering,
|
|
191
|
+
enableLazyPageRendering = _ref3$enableLazyPageR === void 0 ? false : _ref3$enableLazyPageR;
|
|
31
192
|
var _usePageContent = (0, _usePageContent2.usePageContent)(getContent, paginationSize),
|
|
32
193
|
getPageContent = _usePageContent.getPageContent,
|
|
33
194
|
loadPageContent = _usePageContent.loadPageContent,
|
|
@@ -102,29 +263,17 @@ var DocumentViewer = exports.DocumentViewer = function DocumentViewer(_ref) {
|
|
|
102
263
|
var onTouchEnd = (0, _react.useCallback)(function () {
|
|
103
264
|
touchStartRef.current = null;
|
|
104
265
|
}, []);
|
|
105
|
-
|
|
106
|
-
|
|
266
|
+
var sharedProps = {
|
|
267
|
+
documentMetadata: documentMetadata,
|
|
268
|
+
getPageContent: getPageContent,
|
|
269
|
+
loadPageContent: loadPageContent,
|
|
270
|
+
getImageUrl: getImageUrl,
|
|
271
|
+
zoom: zoom,
|
|
272
|
+
onSuccess: onSuccess,
|
|
107
273
|
style: style,
|
|
108
274
|
onTouchStart: onTouchStart,
|
|
109
275
|
onTouchMove: onTouchMove,
|
|
110
|
-
onTouchEnd: onTouchEnd
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
var _getPageContent = getPageContent(i),
|
|
114
|
-
page = _getPageContent.page,
|
|
115
|
-
fonts = _getPageContent.fonts;
|
|
116
|
-
return /*#__PURE__*/React.createElement(_page.Page, {
|
|
117
|
-
key: i,
|
|
118
|
-
getPageSrc: getImageUrl,
|
|
119
|
-
pageIndex: i,
|
|
120
|
-
zoom: zoom,
|
|
121
|
-
defaultDimensions: documentMetadata.defaultDimensions,
|
|
122
|
-
onVisible: function onVisible() {
|
|
123
|
-
return loadPageContent(i);
|
|
124
|
-
},
|
|
125
|
-
onLoad: i === 0 ? onSuccess : undefined,
|
|
126
|
-
fonts: fonts,
|
|
127
|
-
content: page
|
|
128
|
-
});
|
|
129
|
-
}));
|
|
276
|
+
onTouchEnd: onTouchEnd
|
|
277
|
+
};
|
|
278
|
+
return enableLazyPageRendering ? /*#__PURE__*/React.createElement(LazyAppendPages, sharedProps) : /*#__PURE__*/React.createElement(LegacyPages, sharedProps);
|
|
130
279
|
};
|
package/dist/cjs/page.js
CHANGED
|
@@ -81,7 +81,8 @@ var PageView = /*#__PURE__*/(0, _react.forwardRef)(function (_ref4, ref) {
|
|
|
81
81
|
fonts = _ref4.fonts,
|
|
82
82
|
pageIndex = _ref4.pageIndex,
|
|
83
83
|
zoom = _ref4.zoom,
|
|
84
|
-
onImageLoad = _ref4.onImageLoad
|
|
84
|
+
onImageLoad = _ref4.onImageLoad,
|
|
85
|
+
appendUpTo = _ref4.appendUpTo;
|
|
85
86
|
var style = {};
|
|
86
87
|
if (dimensions) {
|
|
87
88
|
// contents endpoint has loaded so dimensions are available
|
|
@@ -130,7 +131,8 @@ var PageView = /*#__PURE__*/(0, _react.forwardRef)(function (_ref4, ref) {
|
|
|
130
131
|
}), content.annotations && /*#__PURE__*/React.createElement(_annotations.Annotations, {
|
|
131
132
|
annotations: content.annotations
|
|
132
133
|
}), content.links && /*#__PURE__*/React.createElement(_documentLinks.DocumentLinks, {
|
|
133
|
-
links: content.links
|
|
134
|
+
links: content.links,
|
|
135
|
+
appendUpTo: appendUpTo
|
|
134
136
|
})));
|
|
135
137
|
});
|
|
136
138
|
var Page = exports.Page = function Page(_ref5) {
|
|
@@ -142,7 +144,8 @@ var Page = exports.Page = function Page(_ref5) {
|
|
|
142
144
|
zoom = _ref5.zoom,
|
|
143
145
|
defaultDimensions = _ref5.defaultDimensions,
|
|
144
146
|
onVisible = _ref5.onVisible,
|
|
145
|
-
onLoad = _ref5.onLoad
|
|
147
|
+
onLoad = _ref5.onLoad,
|
|
148
|
+
appendUpTo = _ref5.appendUpTo;
|
|
146
149
|
var _useState = (0, _react.useState)(),
|
|
147
150
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
148
151
|
imageSrc = _useState2[0],
|
|
@@ -154,7 +157,7 @@ var Page = exports.Page = function Page(_ref5) {
|
|
|
154
157
|
rootMargin: '300%',
|
|
155
158
|
threshold: 0.1
|
|
156
159
|
}, function () {
|
|
157
|
-
onVisible();
|
|
160
|
+
onVisible(pageIndex);
|
|
158
161
|
getPageSrc(pageIndex, zoom).then(setImageSrc);
|
|
159
162
|
}),
|
|
160
163
|
observedRef = _useIntersectionObser.observedRef,
|
|
@@ -190,6 +193,7 @@ var Page = exports.Page = function Page(_ref5) {
|
|
|
190
193
|
fonts: fonts,
|
|
191
194
|
pageIndex: pageIndex,
|
|
192
195
|
zoom: zoom,
|
|
193
|
-
onImageLoad: onImageLoad
|
|
196
|
+
onImageLoad: onImageLoad,
|
|
197
|
+
appendUpTo: appendUpTo
|
|
194
198
|
});
|
|
195
199
|
};
|
|
@@ -12,7 +12,8 @@ const anchorStyles = {
|
|
|
12
12
|
};
|
|
13
13
|
const DocumentLink = ({
|
|
14
14
|
link,
|
|
15
|
-
dataTestId
|
|
15
|
+
dataTestId,
|
|
16
|
+
appendUpTo
|
|
16
17
|
}) => {
|
|
17
18
|
return /*#__PURE__*/React.createElement("foreignObject", {
|
|
18
19
|
x: link.x,
|
|
@@ -27,15 +28,18 @@ const DocumentLink = ({
|
|
|
27
28
|
style: anchorStyles
|
|
28
29
|
})) : /*#__PURE__*/React.createElement(Anchor, _extends({}, foreignObjectProps, {
|
|
29
30
|
href: `#page-${link.p_num + 1}`,
|
|
30
|
-
style: anchorStyles
|
|
31
|
+
style: anchorStyles,
|
|
32
|
+
onClick: appendUpTo ? () => appendUpTo(link.p_num + 1) : undefined
|
|
31
33
|
})));
|
|
32
34
|
};
|
|
33
35
|
export const DocumentLinks = ({
|
|
34
|
-
links
|
|
36
|
+
links,
|
|
37
|
+
appendUpTo
|
|
35
38
|
}) => {
|
|
36
39
|
return /*#__PURE__*/React.createElement(React.Fragment, null, links.map((link, i) => /*#__PURE__*/React.createElement(DocumentLink, {
|
|
37
40
|
link: link,
|
|
38
41
|
dataTestId: `document-link-${i}`,
|
|
42
|
+
appendUpTo: appendUpTo,
|
|
39
43
|
key: i
|
|
40
44
|
})));
|
|
41
45
|
};
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import "./documentViewer.compiled.css";
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import { ax, ix } from "@compiled/react/runtime";
|
|
5
|
-
import { useCallback, useLayoutEffect, useRef } from 'react';
|
|
5
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
6
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
6
7
|
import { useStaticCallback } from '@atlaskit/media-common';
|
|
7
8
|
import { Page } from './page';
|
|
8
9
|
import { usePageContent } from './usePageContent';
|
|
@@ -10,14 +11,165 @@ import { getScrollElement } from './utils/getDocumentRoot';
|
|
|
10
11
|
import { useCachedGetImage } from './utils/useCachedGetImage';
|
|
11
12
|
const documentViewerStyles = null;
|
|
12
13
|
const DEFAULT_PAGINATION_SIZE = 50;
|
|
14
|
+
const INITIAL_PAGE_COUNT = 50;
|
|
15
|
+
const APPEND_STEP = 50;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* TAIL-APPEND PATTERN FOR LAZY LOADING:
|
|
19
|
+
*
|
|
20
|
+
* The <Page> component has an `onVisible: () => void` prop that is called when the page
|
|
21
|
+
* enters the viewport (via useIntersectionObserver with a 300% rootMargin). This callback
|
|
22
|
+
* is currently used to load page content via `loadPageContent(i)`.
|
|
23
|
+
*
|
|
24
|
+
* For the LazyAppendPages feature (T2.3), the parent component can leverage this same
|
|
25
|
+
* mechanism by:
|
|
26
|
+
* 1. Rendering only a subset of pages (lazyPageCount instead of all documentMetadata.pageCount)
|
|
27
|
+
* 2. Passing onVisible={handleAppend} ONLY to the last rendered page (i === lazyPageCount - 1)
|
|
28
|
+
* 3. For all other pages, passing onVisible={() => loadPageContent(i)} as usual
|
|
29
|
+
*
|
|
30
|
+
* When the last page enters the viewport, handleAppend will be triggered, which can:
|
|
31
|
+
* - Fetch the next batch of pages
|
|
32
|
+
* - Append them to the rendered page list
|
|
33
|
+
* - This effectively creates a tail-append/infinite-scroll behavior without any changes to <Page>
|
|
34
|
+
*
|
|
35
|
+
* No changes to the <Page> signature are required. The onVisible callback is already
|
|
36
|
+
* properly wired and can be overridden by parent components for different behaviors.
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
const LegacyPages = ({
|
|
40
|
+
documentMetadata,
|
|
41
|
+
getPageContent,
|
|
42
|
+
loadPageContent,
|
|
43
|
+
getImageUrl,
|
|
44
|
+
zoom,
|
|
45
|
+
onSuccess,
|
|
46
|
+
style,
|
|
47
|
+
onTouchStart,
|
|
48
|
+
onTouchMove,
|
|
49
|
+
onTouchEnd
|
|
50
|
+
}) => {
|
|
51
|
+
var _documentMetadata$pag;
|
|
52
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
53
|
+
"data-testid": "document-viewer",
|
|
54
|
+
style: style,
|
|
55
|
+
onTouchStart: onTouchStart,
|
|
56
|
+
onTouchMove: onTouchMove,
|
|
57
|
+
onTouchEnd: onTouchEnd,
|
|
58
|
+
className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _1bsb1ris"])
|
|
59
|
+
}, [...Array((_documentMetadata$pag = documentMetadata.pageCount) !== null && _documentMetadata$pag !== void 0 ? _documentMetadata$pag : 4)].map((_, i) => {
|
|
60
|
+
const {
|
|
61
|
+
page,
|
|
62
|
+
fonts
|
|
63
|
+
} = getPageContent(i);
|
|
64
|
+
return /*#__PURE__*/React.createElement(Page, {
|
|
65
|
+
key: i,
|
|
66
|
+
getPageSrc: getImageUrl,
|
|
67
|
+
pageIndex: i,
|
|
68
|
+
zoom: zoom,
|
|
69
|
+
defaultDimensions: documentMetadata.defaultDimensions,
|
|
70
|
+
onVisible: loadPageContent,
|
|
71
|
+
onLoad: i === 0 ? onSuccess : undefined,
|
|
72
|
+
fonts: fonts,
|
|
73
|
+
content: page
|
|
74
|
+
});
|
|
75
|
+
}));
|
|
76
|
+
};
|
|
77
|
+
const LazyAppendPages = ({
|
|
78
|
+
documentMetadata,
|
|
79
|
+
getPageContent,
|
|
80
|
+
loadPageContent,
|
|
81
|
+
getImageUrl,
|
|
82
|
+
zoom,
|
|
83
|
+
onSuccess,
|
|
84
|
+
style,
|
|
85
|
+
onTouchStart,
|
|
86
|
+
onTouchMove,
|
|
87
|
+
onTouchEnd
|
|
88
|
+
}) => {
|
|
89
|
+
var _documentMetadata$pag2;
|
|
90
|
+
const totalPages = (_documentMetadata$pag2 = documentMetadata.pageCount) !== null && _documentMetadata$pag2 !== void 0 ? _documentMetadata$pag2 : 4;
|
|
91
|
+
const [lazyPageCount, setLazyPageCount] = useState(() => Math.min(INITIAL_PAGE_COUNT, totalPages));
|
|
92
|
+
|
|
93
|
+
// lastAppendTriggerIndex deduplicates: only append when a strictly-larger
|
|
94
|
+
// tail page fires onVisible. This prevents double-append on scroll-up-then-down.
|
|
95
|
+
const lastAppendTriggerIndex = useRef(-1);
|
|
96
|
+
|
|
97
|
+
// Handle #page-N URL hash on first load: fast-forward lazyPageCount to include the target page.
|
|
98
|
+
// Capture totalPages in a ref so the one-shot effect can read it without being re-run when
|
|
99
|
+
// totalPages changes (the effect must only fire once, on mount).
|
|
100
|
+
const totalPagesRef = useRef(totalPages);
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
const total = totalPagesRef.current;
|
|
103
|
+
const hash = window.location.hash;
|
|
104
|
+
const match = hash.match(/^#page-(\d+)$/);
|
|
105
|
+
if (match) {
|
|
106
|
+
const targetPage = parseInt(match[1], 10);
|
|
107
|
+
if (targetPage >= 1 && targetPage <= total) {
|
|
108
|
+
// Update dedup ref BEFORE setLazyPageCount so handleAppend does not
|
|
109
|
+
// cascade when the new tail page enters the viewport via IntersectionObserver.
|
|
110
|
+
lastAppendTriggerIndex.current = targetPage - 1;
|
|
111
|
+
// Fast-forward lazyPageCount to include the target page
|
|
112
|
+
setLazyPageCount(prev => Math.max(prev, targetPage));
|
|
113
|
+
// After the pages are mounted (next animation frame), scroll to the target
|
|
114
|
+
requestAnimationFrame(() => {
|
|
115
|
+
var _getDocument;
|
|
116
|
+
const el = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.getElementById(`page-${targetPage}`);
|
|
117
|
+
if (el) {
|
|
118
|
+
el.scrollIntoView();
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps -- intentionally one-shot; totalPages read via ref
|
|
124
|
+
|
|
125
|
+
const handleAppendAndLoadPageContent = useCallback(pageIndex => {
|
|
126
|
+
if (pageIndex > lastAppendTriggerIndex.current) {
|
|
127
|
+
lastAppendTriggerIndex.current = pageIndex;
|
|
128
|
+
setLazyPageCount(c => Math.min(c + APPEND_STEP, totalPages));
|
|
129
|
+
}
|
|
130
|
+
loadPageContent(pageIndex);
|
|
131
|
+
}, [totalPages, loadPageContent]);
|
|
132
|
+
const appendUpTo = useCallback(targetPage => {
|
|
133
|
+
const clamped = Math.min(Math.max(targetPage, 0), totalPages);
|
|
134
|
+
if (clamped > lastAppendTriggerIndex.current) {
|
|
135
|
+
lastAppendTriggerIndex.current = clamped - 1;
|
|
136
|
+
setLazyPageCount(prev => Math.max(prev, clamped));
|
|
137
|
+
}
|
|
138
|
+
}, [totalPages]);
|
|
139
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
140
|
+
"data-testid": "document-viewer",
|
|
141
|
+
style: style,
|
|
142
|
+
onTouchStart: onTouchStart,
|
|
143
|
+
onTouchMove: onTouchMove,
|
|
144
|
+
onTouchEnd: onTouchEnd,
|
|
145
|
+
className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _1bsb1ris"])
|
|
146
|
+
}, [...Array(lazyPageCount)].map((_, i) => {
|
|
147
|
+
const {
|
|
148
|
+
page,
|
|
149
|
+
fonts
|
|
150
|
+
} = getPageContent(i);
|
|
151
|
+
return /*#__PURE__*/React.createElement(Page, {
|
|
152
|
+
key: i,
|
|
153
|
+
getPageSrc: getImageUrl,
|
|
154
|
+
pageIndex: i,
|
|
155
|
+
zoom: zoom,
|
|
156
|
+
defaultDimensions: documentMetadata.defaultDimensions,
|
|
157
|
+
onVisible: i === lazyPageCount - 1 ? handleAppendAndLoadPageContent : loadPageContent,
|
|
158
|
+
onLoad: i === 0 ? onSuccess : undefined,
|
|
159
|
+
fonts: fonts,
|
|
160
|
+
content: page,
|
|
161
|
+
appendUpTo: appendUpTo
|
|
162
|
+
});
|
|
163
|
+
}));
|
|
164
|
+
};
|
|
13
165
|
export const DocumentViewer = ({
|
|
14
166
|
onSuccess,
|
|
15
167
|
getContent,
|
|
16
168
|
getPageImageUrl,
|
|
17
169
|
paginationSize = DEFAULT_PAGINATION_SIZE,
|
|
18
|
-
zoom
|
|
170
|
+
zoom,
|
|
171
|
+
enableLazyPageRendering = false
|
|
19
172
|
}) => {
|
|
20
|
-
var _documentMetadata$pag;
|
|
21
173
|
const {
|
|
22
174
|
getPageContent,
|
|
23
175
|
loadPageContent,
|
|
@@ -93,28 +245,17 @@ export const DocumentViewer = ({
|
|
|
93
245
|
const onTouchEnd = useCallback(() => {
|
|
94
246
|
touchStartRef.current = null;
|
|
95
247
|
}, []);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
key: i,
|
|
110
|
-
getPageSrc: getImageUrl,
|
|
111
|
-
pageIndex: i,
|
|
112
|
-
zoom: zoom,
|
|
113
|
-
defaultDimensions: documentMetadata.defaultDimensions,
|
|
114
|
-
onVisible: () => loadPageContent(i),
|
|
115
|
-
onLoad: i === 0 ? onSuccess : undefined,
|
|
116
|
-
fonts: fonts,
|
|
117
|
-
content: page
|
|
118
|
-
});
|
|
119
|
-
}));
|
|
248
|
+
const sharedProps = {
|
|
249
|
+
documentMetadata,
|
|
250
|
+
getPageContent,
|
|
251
|
+
loadPageContent,
|
|
252
|
+
getImageUrl,
|
|
253
|
+
zoom,
|
|
254
|
+
onSuccess,
|
|
255
|
+
style,
|
|
256
|
+
onTouchStart,
|
|
257
|
+
onTouchMove,
|
|
258
|
+
onTouchEnd
|
|
259
|
+
};
|
|
260
|
+
return enableLazyPageRendering ? /*#__PURE__*/React.createElement(LazyAppendPages, sharedProps) : /*#__PURE__*/React.createElement(LegacyPages, sharedProps);
|
|
120
261
|
};
|
package/dist/es2019/page.js
CHANGED
|
@@ -70,7 +70,8 @@ const PageView = /*#__PURE__*/forwardRef(({
|
|
|
70
70
|
fonts,
|
|
71
71
|
pageIndex,
|
|
72
72
|
zoom,
|
|
73
|
-
onImageLoad
|
|
73
|
+
onImageLoad,
|
|
74
|
+
appendUpTo
|
|
74
75
|
}, ref) => {
|
|
75
76
|
const style = {};
|
|
76
77
|
if (dimensions) {
|
|
@@ -118,7 +119,8 @@ const PageView = /*#__PURE__*/forwardRef(({
|
|
|
118
119
|
})), content.annotations && /*#__PURE__*/React.createElement(Annotations, {
|
|
119
120
|
annotations: content.annotations
|
|
120
121
|
}), content.links && /*#__PURE__*/React.createElement(DocumentLinks, {
|
|
121
|
-
links: content.links
|
|
122
|
+
links: content.links,
|
|
123
|
+
appendUpTo: appendUpTo
|
|
122
124
|
})));
|
|
123
125
|
});
|
|
124
126
|
export const Page = ({
|
|
@@ -129,7 +131,8 @@ export const Page = ({
|
|
|
129
131
|
zoom,
|
|
130
132
|
defaultDimensions,
|
|
131
133
|
onVisible,
|
|
132
|
-
onLoad
|
|
134
|
+
onLoad,
|
|
135
|
+
appendUpTo
|
|
133
136
|
}) => {
|
|
134
137
|
var _ref;
|
|
135
138
|
const [imageSrc, setImageSrc] = useState();
|
|
@@ -143,7 +146,7 @@ export const Page = ({
|
|
|
143
146
|
rootMargin: '300%',
|
|
144
147
|
threshold: 0.1
|
|
145
148
|
}, () => {
|
|
146
|
-
onVisible();
|
|
149
|
+
onVisible(pageIndex);
|
|
147
150
|
getPageSrc(pageIndex, zoom).then(setImageSrc);
|
|
148
151
|
});
|
|
149
152
|
const [dimensions, setDimensions] = useState();
|
|
@@ -174,6 +177,7 @@ export const Page = ({
|
|
|
174
177
|
fonts: fonts,
|
|
175
178
|
pageIndex: pageIndex,
|
|
176
179
|
zoom: zoom,
|
|
177
|
-
onImageLoad: onImageLoad
|
|
180
|
+
onImageLoad: onImageLoad,
|
|
181
|
+
appendUpTo: appendUpTo
|
|
178
182
|
});
|
|
179
183
|
};
|
|
@@ -12,7 +12,8 @@ var anchorStyles = {
|
|
|
12
12
|
};
|
|
13
13
|
var DocumentLink = function DocumentLink(_ref) {
|
|
14
14
|
var link = _ref.link,
|
|
15
|
-
dataTestId = _ref.dataTestId
|
|
15
|
+
dataTestId = _ref.dataTestId,
|
|
16
|
+
appendUpTo = _ref.appendUpTo;
|
|
16
17
|
return /*#__PURE__*/React.createElement("foreignObject", {
|
|
17
18
|
x: link.x,
|
|
18
19
|
y: -link.y,
|
|
@@ -26,15 +27,20 @@ var DocumentLink = function DocumentLink(_ref) {
|
|
|
26
27
|
style: anchorStyles
|
|
27
28
|
})) : /*#__PURE__*/React.createElement(Anchor, _extends({}, foreignObjectProps, {
|
|
28
29
|
href: "#page-".concat(link.p_num + 1),
|
|
29
|
-
style: anchorStyles
|
|
30
|
+
style: anchorStyles,
|
|
31
|
+
onClick: appendUpTo ? function () {
|
|
32
|
+
return appendUpTo(link.p_num + 1);
|
|
33
|
+
} : undefined
|
|
30
34
|
})));
|
|
31
35
|
};
|
|
32
36
|
export var DocumentLinks = function DocumentLinks(_ref2) {
|
|
33
|
-
var links = _ref2.links
|
|
37
|
+
var links = _ref2.links,
|
|
38
|
+
appendUpTo = _ref2.appendUpTo;
|
|
34
39
|
return /*#__PURE__*/React.createElement(React.Fragment, null, links.map(function (link, i) {
|
|
35
40
|
return /*#__PURE__*/React.createElement(DocumentLink, {
|
|
36
41
|
link: link,
|
|
37
42
|
dataTestId: "document-link-".concat(i),
|
|
43
|
+
appendUpTo: appendUpTo,
|
|
38
44
|
key: i
|
|
39
45
|
});
|
|
40
46
|
}));
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/* documentViewer.tsx generated by @compiled/babel-plugin v0.39.1 */
|
|
2
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
3
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
4
|
import "./documentViewer.compiled.css";
|
|
4
5
|
import * as React from 'react';
|
|
5
6
|
import { ax, ix } from "@compiled/react/runtime";
|
|
6
|
-
import { useCallback, useLayoutEffect, useRef } from 'react';
|
|
7
|
+
import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
|
8
|
+
import { getDocument } from '@atlaskit/browser-apis';
|
|
7
9
|
import { useStaticCallback } from '@atlaskit/media-common';
|
|
8
10
|
import { Page } from './page';
|
|
9
11
|
import { usePageContent } from './usePageContent';
|
|
@@ -11,14 +13,173 @@ import { getScrollElement } from './utils/getDocumentRoot';
|
|
|
11
13
|
import { useCachedGetImage } from './utils/useCachedGetImage';
|
|
12
14
|
var documentViewerStyles = null;
|
|
13
15
|
var DEFAULT_PAGINATION_SIZE = 50;
|
|
14
|
-
|
|
16
|
+
var INITIAL_PAGE_COUNT = 50;
|
|
17
|
+
var APPEND_STEP = 50;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* TAIL-APPEND PATTERN FOR LAZY LOADING:
|
|
21
|
+
*
|
|
22
|
+
* The <Page> component has an `onVisible: () => void` prop that is called when the page
|
|
23
|
+
* enters the viewport (via useIntersectionObserver with a 300% rootMargin). This callback
|
|
24
|
+
* is currently used to load page content via `loadPageContent(i)`.
|
|
25
|
+
*
|
|
26
|
+
* For the LazyAppendPages feature (T2.3), the parent component can leverage this same
|
|
27
|
+
* mechanism by:
|
|
28
|
+
* 1. Rendering only a subset of pages (lazyPageCount instead of all documentMetadata.pageCount)
|
|
29
|
+
* 2. Passing onVisible={handleAppend} ONLY to the last rendered page (i === lazyPageCount - 1)
|
|
30
|
+
* 3. For all other pages, passing onVisible={() => loadPageContent(i)} as usual
|
|
31
|
+
*
|
|
32
|
+
* When the last page enters the viewport, handleAppend will be triggered, which can:
|
|
33
|
+
* - Fetch the next batch of pages
|
|
34
|
+
* - Append them to the rendered page list
|
|
35
|
+
* - This effectively creates a tail-append/infinite-scroll behavior without any changes to <Page>
|
|
36
|
+
*
|
|
37
|
+
* No changes to the <Page> signature are required. The onVisible callback is already
|
|
38
|
+
* properly wired and can be overridden by parent components for different behaviors.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
var LegacyPages = function LegacyPages(_ref) {
|
|
15
42
|
var _documentMetadata$pag;
|
|
16
|
-
var
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
43
|
+
var documentMetadata = _ref.documentMetadata,
|
|
44
|
+
getPageContent = _ref.getPageContent,
|
|
45
|
+
loadPageContent = _ref.loadPageContent,
|
|
46
|
+
getImageUrl = _ref.getImageUrl,
|
|
47
|
+
zoom = _ref.zoom,
|
|
48
|
+
onSuccess = _ref.onSuccess,
|
|
49
|
+
style = _ref.style,
|
|
50
|
+
onTouchStart = _ref.onTouchStart,
|
|
51
|
+
onTouchMove = _ref.onTouchMove,
|
|
52
|
+
onTouchEnd = _ref.onTouchEnd;
|
|
53
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
54
|
+
"data-testid": "document-viewer",
|
|
55
|
+
style: style,
|
|
56
|
+
onTouchStart: onTouchStart,
|
|
57
|
+
onTouchMove: onTouchMove,
|
|
58
|
+
onTouchEnd: onTouchEnd,
|
|
59
|
+
className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _1bsb1ris"])
|
|
60
|
+
}, _toConsumableArray(Array((_documentMetadata$pag = documentMetadata.pageCount) !== null && _documentMetadata$pag !== void 0 ? _documentMetadata$pag : 4)).map(function (_, i) {
|
|
61
|
+
var _getPageContent = getPageContent(i),
|
|
62
|
+
page = _getPageContent.page,
|
|
63
|
+
fonts = _getPageContent.fonts;
|
|
64
|
+
return /*#__PURE__*/React.createElement(Page, {
|
|
65
|
+
key: i,
|
|
66
|
+
getPageSrc: getImageUrl,
|
|
67
|
+
pageIndex: i,
|
|
68
|
+
zoom: zoom,
|
|
69
|
+
defaultDimensions: documentMetadata.defaultDimensions,
|
|
70
|
+
onVisible: loadPageContent,
|
|
71
|
+
onLoad: i === 0 ? onSuccess : undefined,
|
|
72
|
+
fonts: fonts,
|
|
73
|
+
content: page
|
|
74
|
+
});
|
|
75
|
+
}));
|
|
76
|
+
};
|
|
77
|
+
var LazyAppendPages = function LazyAppendPages(_ref2) {
|
|
78
|
+
var _documentMetadata$pag2;
|
|
79
|
+
var documentMetadata = _ref2.documentMetadata,
|
|
80
|
+
getPageContent = _ref2.getPageContent,
|
|
81
|
+
loadPageContent = _ref2.loadPageContent,
|
|
82
|
+
getImageUrl = _ref2.getImageUrl,
|
|
83
|
+
zoom = _ref2.zoom,
|
|
84
|
+
onSuccess = _ref2.onSuccess,
|
|
85
|
+
style = _ref2.style,
|
|
86
|
+
onTouchStart = _ref2.onTouchStart,
|
|
87
|
+
onTouchMove = _ref2.onTouchMove,
|
|
88
|
+
onTouchEnd = _ref2.onTouchEnd;
|
|
89
|
+
var totalPages = (_documentMetadata$pag2 = documentMetadata.pageCount) !== null && _documentMetadata$pag2 !== void 0 ? _documentMetadata$pag2 : 4;
|
|
90
|
+
var _useState = useState(function () {
|
|
91
|
+
return Math.min(INITIAL_PAGE_COUNT, totalPages);
|
|
92
|
+
}),
|
|
93
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
94
|
+
lazyPageCount = _useState2[0],
|
|
95
|
+
setLazyPageCount = _useState2[1];
|
|
96
|
+
|
|
97
|
+
// lastAppendTriggerIndex deduplicates: only append when a strictly-larger
|
|
98
|
+
// tail page fires onVisible. This prevents double-append on scroll-up-then-down.
|
|
99
|
+
var lastAppendTriggerIndex = useRef(-1);
|
|
100
|
+
|
|
101
|
+
// Handle #page-N URL hash on first load: fast-forward lazyPageCount to include the target page.
|
|
102
|
+
// Capture totalPages in a ref so the one-shot effect can read it without being re-run when
|
|
103
|
+
// totalPages changes (the effect must only fire once, on mount).
|
|
104
|
+
var totalPagesRef = useRef(totalPages);
|
|
105
|
+
useEffect(function () {
|
|
106
|
+
var total = totalPagesRef.current;
|
|
107
|
+
var hash = window.location.hash;
|
|
108
|
+
var match = hash.match(/^#page-(\d+)$/);
|
|
109
|
+
if (match) {
|
|
110
|
+
var targetPage = parseInt(match[1], 10);
|
|
111
|
+
if (targetPage >= 1 && targetPage <= total) {
|
|
112
|
+
// Update dedup ref BEFORE setLazyPageCount so handleAppend does not
|
|
113
|
+
// cascade when the new tail page enters the viewport via IntersectionObserver.
|
|
114
|
+
lastAppendTriggerIndex.current = targetPage - 1;
|
|
115
|
+
// Fast-forward lazyPageCount to include the target page
|
|
116
|
+
setLazyPageCount(function (prev) {
|
|
117
|
+
return Math.max(prev, targetPage);
|
|
118
|
+
});
|
|
119
|
+
// After the pages are mounted (next animation frame), scroll to the target
|
|
120
|
+
requestAnimationFrame(function () {
|
|
121
|
+
var _getDocument;
|
|
122
|
+
var el = (_getDocument = getDocument()) === null || _getDocument === void 0 ? void 0 : _getDocument.getElementById("page-".concat(targetPage));
|
|
123
|
+
if (el) {
|
|
124
|
+
el.scrollIntoView();
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps -- intentionally one-shot; totalPages read via ref
|
|
130
|
+
|
|
131
|
+
var handleAppendAndLoadPageContent = useCallback(function (pageIndex) {
|
|
132
|
+
if (pageIndex > lastAppendTriggerIndex.current) {
|
|
133
|
+
lastAppendTriggerIndex.current = pageIndex;
|
|
134
|
+
setLazyPageCount(function (c) {
|
|
135
|
+
return Math.min(c + APPEND_STEP, totalPages);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
loadPageContent(pageIndex);
|
|
139
|
+
}, [totalPages, loadPageContent]);
|
|
140
|
+
var appendUpTo = useCallback(function (targetPage) {
|
|
141
|
+
var clamped = Math.min(Math.max(targetPage, 0), totalPages);
|
|
142
|
+
if (clamped > lastAppendTriggerIndex.current) {
|
|
143
|
+
lastAppendTriggerIndex.current = clamped - 1;
|
|
144
|
+
setLazyPageCount(function (prev) {
|
|
145
|
+
return Math.max(prev, clamped);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}, [totalPages]);
|
|
149
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
150
|
+
"data-testid": "document-viewer",
|
|
151
|
+
style: style,
|
|
152
|
+
onTouchStart: onTouchStart,
|
|
153
|
+
onTouchMove: onTouchMove,
|
|
154
|
+
onTouchEnd: onTouchEnd,
|
|
155
|
+
className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _1bsb1ris"])
|
|
156
|
+
}, _toConsumableArray(Array(lazyPageCount)).map(function (_, i) {
|
|
157
|
+
var _getPageContent2 = getPageContent(i),
|
|
158
|
+
page = _getPageContent2.page,
|
|
159
|
+
fonts = _getPageContent2.fonts;
|
|
160
|
+
return /*#__PURE__*/React.createElement(Page, {
|
|
161
|
+
key: i,
|
|
162
|
+
getPageSrc: getImageUrl,
|
|
163
|
+
pageIndex: i,
|
|
164
|
+
zoom: zoom,
|
|
165
|
+
defaultDimensions: documentMetadata.defaultDimensions,
|
|
166
|
+
onVisible: i === lazyPageCount - 1 ? handleAppendAndLoadPageContent : loadPageContent,
|
|
167
|
+
onLoad: i === 0 ? onSuccess : undefined,
|
|
168
|
+
fonts: fonts,
|
|
169
|
+
content: page,
|
|
170
|
+
appendUpTo: appendUpTo
|
|
171
|
+
});
|
|
172
|
+
}));
|
|
173
|
+
};
|
|
174
|
+
export var DocumentViewer = function DocumentViewer(_ref3) {
|
|
175
|
+
var onSuccess = _ref3.onSuccess,
|
|
176
|
+
getContent = _ref3.getContent,
|
|
177
|
+
getPageImageUrl = _ref3.getPageImageUrl,
|
|
178
|
+
_ref3$paginationSize = _ref3.paginationSize,
|
|
179
|
+
paginationSize = _ref3$paginationSize === void 0 ? DEFAULT_PAGINATION_SIZE : _ref3$paginationSize,
|
|
180
|
+
zoom = _ref3.zoom,
|
|
181
|
+
_ref3$enableLazyPageR = _ref3.enableLazyPageRendering,
|
|
182
|
+
enableLazyPageRendering = _ref3$enableLazyPageR === void 0 ? false : _ref3$enableLazyPageR;
|
|
22
183
|
var _usePageContent = usePageContent(getContent, paginationSize),
|
|
23
184
|
getPageContent = _usePageContent.getPageContent,
|
|
24
185
|
loadPageContent = _usePageContent.loadPageContent,
|
|
@@ -93,29 +254,17 @@ export var DocumentViewer = function DocumentViewer(_ref) {
|
|
|
93
254
|
var onTouchEnd = useCallback(function () {
|
|
94
255
|
touchStartRef.current = null;
|
|
95
256
|
}, []);
|
|
96
|
-
|
|
97
|
-
|
|
257
|
+
var sharedProps = {
|
|
258
|
+
documentMetadata: documentMetadata,
|
|
259
|
+
getPageContent: getPageContent,
|
|
260
|
+
loadPageContent: loadPageContent,
|
|
261
|
+
getImageUrl: getImageUrl,
|
|
262
|
+
zoom: zoom,
|
|
263
|
+
onSuccess: onSuccess,
|
|
98
264
|
style: style,
|
|
99
265
|
onTouchStart: onTouchStart,
|
|
100
266
|
onTouchMove: onTouchMove,
|
|
101
|
-
onTouchEnd: onTouchEnd
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
var _getPageContent = getPageContent(i),
|
|
105
|
-
page = _getPageContent.page,
|
|
106
|
-
fonts = _getPageContent.fonts;
|
|
107
|
-
return /*#__PURE__*/React.createElement(Page, {
|
|
108
|
-
key: i,
|
|
109
|
-
getPageSrc: getImageUrl,
|
|
110
|
-
pageIndex: i,
|
|
111
|
-
zoom: zoom,
|
|
112
|
-
defaultDimensions: documentMetadata.defaultDimensions,
|
|
113
|
-
onVisible: function onVisible() {
|
|
114
|
-
return loadPageContent(i);
|
|
115
|
-
},
|
|
116
|
-
onLoad: i === 0 ? onSuccess : undefined,
|
|
117
|
-
fonts: fonts,
|
|
118
|
-
content: page
|
|
119
|
-
});
|
|
120
|
-
}));
|
|
267
|
+
onTouchEnd: onTouchEnd
|
|
268
|
+
};
|
|
269
|
+
return enableLazyPageRendering ? /*#__PURE__*/React.createElement(LazyAppendPages, sharedProps) : /*#__PURE__*/React.createElement(LegacyPages, sharedProps);
|
|
121
270
|
};
|
package/dist/esm/page.js
CHANGED
|
@@ -72,7 +72,8 @@ var PageView = /*#__PURE__*/forwardRef(function (_ref4, ref) {
|
|
|
72
72
|
fonts = _ref4.fonts,
|
|
73
73
|
pageIndex = _ref4.pageIndex,
|
|
74
74
|
zoom = _ref4.zoom,
|
|
75
|
-
onImageLoad = _ref4.onImageLoad
|
|
75
|
+
onImageLoad = _ref4.onImageLoad,
|
|
76
|
+
appendUpTo = _ref4.appendUpTo;
|
|
76
77
|
var style = {};
|
|
77
78
|
if (dimensions) {
|
|
78
79
|
// contents endpoint has loaded so dimensions are available
|
|
@@ -121,7 +122,8 @@ var PageView = /*#__PURE__*/forwardRef(function (_ref4, ref) {
|
|
|
121
122
|
}), content.annotations && /*#__PURE__*/React.createElement(Annotations, {
|
|
122
123
|
annotations: content.annotations
|
|
123
124
|
}), content.links && /*#__PURE__*/React.createElement(DocumentLinks, {
|
|
124
|
-
links: content.links
|
|
125
|
+
links: content.links,
|
|
126
|
+
appendUpTo: appendUpTo
|
|
125
127
|
})));
|
|
126
128
|
});
|
|
127
129
|
export var Page = function Page(_ref5) {
|
|
@@ -133,7 +135,8 @@ export var Page = function Page(_ref5) {
|
|
|
133
135
|
zoom = _ref5.zoom,
|
|
134
136
|
defaultDimensions = _ref5.defaultDimensions,
|
|
135
137
|
onVisible = _ref5.onVisible,
|
|
136
|
-
onLoad = _ref5.onLoad
|
|
138
|
+
onLoad = _ref5.onLoad,
|
|
139
|
+
appendUpTo = _ref5.appendUpTo;
|
|
137
140
|
var _useState = useState(),
|
|
138
141
|
_useState2 = _slicedToArray(_useState, 2),
|
|
139
142
|
imageSrc = _useState2[0],
|
|
@@ -145,7 +148,7 @@ export var Page = function Page(_ref5) {
|
|
|
145
148
|
rootMargin: '300%',
|
|
146
149
|
threshold: 0.1
|
|
147
150
|
}, function () {
|
|
148
|
-
onVisible();
|
|
151
|
+
onVisible(pageIndex);
|
|
149
152
|
getPageSrc(pageIndex, zoom).then(setImageSrc);
|
|
150
153
|
}),
|
|
151
154
|
observedRef = _useIntersectionObser.observedRef,
|
|
@@ -181,6 +184,7 @@ export var Page = function Page(_ref5) {
|
|
|
181
184
|
fonts: fonts,
|
|
182
185
|
pageIndex: pageIndex,
|
|
183
186
|
zoom: zoom,
|
|
184
|
-
onImageLoad: onImageLoad
|
|
187
|
+
onImageLoad: onImageLoad,
|
|
188
|
+
appendUpTo: appendUpTo
|
|
185
189
|
});
|
|
186
190
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type Link } from './types';
|
|
3
|
-
export declare const DocumentLinks: ({ links }: {
|
|
3
|
+
export declare const DocumentLinks: ({ links, appendUpTo, }: {
|
|
4
4
|
links: readonly Link[];
|
|
5
|
+
appendUpTo?: (n: number) => void;
|
|
5
6
|
}) => React.JSX.Element;
|
|
@@ -13,5 +13,11 @@ export type DocumentViewerProps = {
|
|
|
13
13
|
maxPageImageZoom?: number;
|
|
14
14
|
zoom: number;
|
|
15
15
|
onSuccess?: () => void;
|
|
16
|
+
/**
|
|
17
|
+
* When true, renders an initial batch of pages and appends more as the user scrolls.
|
|
18
|
+
* Intended for large documents (e.g. large Excel previews).
|
|
19
|
+
* Default: false.
|
|
20
|
+
*/
|
|
21
|
+
enableLazyPageRendering?: boolean;
|
|
16
22
|
};
|
|
17
|
-
export declare const DocumentViewer: ({ onSuccess, getContent, getPageImageUrl, paginationSize, zoom, }: DocumentViewerProps) => JSX.Element;
|
|
23
|
+
export declare const DocumentViewer: ({ onSuccess, getContent, getPageImageUrl, paginationSize, zoom, enableLazyPageRendering, }: DocumentViewerProps) => JSX.Element;
|
package/dist/types/page.d.ts
CHANGED
|
@@ -9,8 +9,15 @@ type PageProps = {
|
|
|
9
9
|
width: number;
|
|
10
10
|
height: number;
|
|
11
11
|
};
|
|
12
|
-
onVisible: () => void;
|
|
12
|
+
onVisible: (pageIndex: number) => void;
|
|
13
13
|
onLoad?: () => void;
|
|
14
|
+
/**
|
|
15
|
+
* Called when a local `#page-N` anchor inside this page is clicked.
|
|
16
|
+
* Fast-forwards the lazy page count so the target page exists in the DOM
|
|
17
|
+
* before the browser performs the native anchor scroll.
|
|
18
|
+
* Only provided when `enableLazyPageRendering` is true.
|
|
19
|
+
*/
|
|
20
|
+
appendUpTo?: (n: number) => void;
|
|
14
21
|
};
|
|
15
|
-
export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, onLoad, }: PageProps) => JSX.Element;
|
|
22
|
+
export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, onLoad, appendUpTo, }: PageProps) => JSX.Element;
|
|
16
23
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { type Link } from './types';
|
|
3
|
-
export declare const DocumentLinks: ({ links }: {
|
|
3
|
+
export declare const DocumentLinks: ({ links, appendUpTo, }: {
|
|
4
4
|
links: readonly Link[];
|
|
5
|
+
appendUpTo?: (n: number) => void;
|
|
5
6
|
}) => React.JSX.Element;
|
|
@@ -13,5 +13,11 @@ export type DocumentViewerProps = {
|
|
|
13
13
|
maxPageImageZoom?: number;
|
|
14
14
|
zoom: number;
|
|
15
15
|
onSuccess?: () => void;
|
|
16
|
+
/**
|
|
17
|
+
* When true, renders an initial batch of pages and appends more as the user scrolls.
|
|
18
|
+
* Intended for large documents (e.g. large Excel previews).
|
|
19
|
+
* Default: false.
|
|
20
|
+
*/
|
|
21
|
+
enableLazyPageRendering?: boolean;
|
|
16
22
|
};
|
|
17
|
-
export declare const DocumentViewer: ({ onSuccess, getContent, getPageImageUrl, paginationSize, zoom, }: DocumentViewerProps) => JSX.Element;
|
|
23
|
+
export declare const DocumentViewer: ({ onSuccess, getContent, getPageImageUrl, paginationSize, zoom, enableLazyPageRendering, }: DocumentViewerProps) => JSX.Element;
|
|
@@ -9,8 +9,15 @@ type PageProps = {
|
|
|
9
9
|
width: number;
|
|
10
10
|
height: number;
|
|
11
11
|
};
|
|
12
|
-
onVisible: () => void;
|
|
12
|
+
onVisible: (pageIndex: number) => void;
|
|
13
13
|
onLoad?: () => void;
|
|
14
|
+
/**
|
|
15
|
+
* Called when a local `#page-N` anchor inside this page is clicked.
|
|
16
|
+
* Fast-forwards the lazy page count so the target page exists in the DOM
|
|
17
|
+
* before the browser performs the native anchor scroll.
|
|
18
|
+
* Only provided when `enableLazyPageRendering` is true.
|
|
19
|
+
*/
|
|
20
|
+
appendUpTo?: (n: number) => void;
|
|
14
21
|
};
|
|
15
|
-
export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, onLoad, }: PageProps) => JSX.Element;
|
|
22
|
+
export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, onLoad, appendUpTo, }: PageProps) => JSX.Element;
|
|
16
23
|
export {};
|
package/package.json
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@atlaskit/browser-apis": "^0.0.1",
|
|
28
28
|
"@atlaskit/css": "^0.19.0",
|
|
29
|
-
"@atlaskit/media-common": "^13.
|
|
29
|
+
"@atlaskit/media-common": "^13.3.0",
|
|
30
30
|
"@atlaskit/primitives": "^19.0.0",
|
|
31
31
|
"@atlaskit/spinner": "^19.1.0",
|
|
32
32
|
"@atlaskit/tokens": "^13.0.0",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
84
|
"name": "@atlaskit/media-document-viewer",
|
|
85
|
-
"version": "0.
|
|
85
|
+
"version": "0.7.0",
|
|
86
86
|
"description": "Modern and fast document viewer",
|
|
87
87
|
"author": "Atlassian Pty Ltd",
|
|
88
88
|
"license": "Apache-2.0",
|