@atlaskit/media-document-viewer 0.2.3 → 0.3.1

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # @atlaskit/media-document-viewer
2
2
 
3
+ ## 0.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#180383](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/180383)
8
+ [`ff93dcfae3aa1`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/ff93dcfae3aa1) -
9
+ Fixed zoom centering correctly, zooming on mixed page size pdfs no longer cutting off PDFs and
10
+ pressing arrow keys on PDF inputs no longer causing media viewer to scroll
11
+
12
+ ## 0.3.0
13
+
14
+ ### Minor Changes
15
+
16
+ - [#179532](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/179532)
17
+ [`3102656e971a4`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3102656e971a4) -
18
+ Fixed form view by removing unnecessary div and replacing with fragment and added a new
19
+ `onSuccess` callback to enable success analytics
20
+
3
21
  ## 0.2.3
4
22
 
5
23
  ### Patch Changes
@@ -2,18 +2,16 @@
2
2
  "use strict";
3
3
 
4
4
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
- var _typeof = require("@babel/runtime/helpers/typeof");
6
5
  Object.defineProperty(exports, "__esModule", {
7
6
  value: true
8
7
  });
9
8
  exports.TextInputFormField = exports.ComboBoxFormField = exports.Annotations = void 0;
10
9
  require("./annotations.compiled.css");
11
- var React = _interopRequireWildcard(require("react"));
12
10
  var _runtime = require("@compiled/react/runtime");
13
11
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
14
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+ var _react = _interopRequireDefault(require("react"));
15
14
  var _chevronDown = _interopRequireDefault(require("@atlaskit/icon/core/chevron-down"));
16
- 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); }
17
15
  /* eslint-disable @atlaskit/ui-styling-standard/enforce-style-prop */
18
16
  var formInputBaseStyles = null;
19
17
  var textInputStyles = null;
@@ -23,17 +21,23 @@ var foreignObjectProps = {
23
21
  var TextInputFormField = exports.TextInputFormField = function TextInputFormField(_ref) {
24
22
  var field = _ref.field,
25
23
  dataTestId = _ref.dataTestId;
26
- return /*#__PURE__*/React.createElement("foreignObject", {
24
+ return /*#__PURE__*/_react.default.createElement("foreignObject", {
27
25
  x: field.x,
28
26
  y: -field.y,
29
27
  width: field.w,
30
28
  height: field.h,
31
29
  "data-testid": dataTestId
32
- }, /*#__PURE__*/React.createElement("input", (0, _extends2.default)({}, foreignObjectProps, {
30
+ }, /*#__PURE__*/_react.default.createElement("input", (0, _extends2.default)({}, foreignObjectProps, {
33
31
  style: (0, _defineProperty2.default)({}, 'fontSize', "".concat(field.f, "px")),
34
32
  type: "text",
35
33
  value: field.text,
36
34
  readOnly: true,
35
+ onKeyUp: function onKeyUp(e) {
36
+ // stop propagation of the arrow key events because they can be used to navigate viewports
37
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
38
+ e.stopPropagation();
39
+ }
40
+ },
37
41
  className: (0, _runtime.ax)(["_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _r06hglyw", "_kqswstnw _4t3i1osq _1bsb1osq"])
38
42
  })));
39
43
  };
@@ -42,35 +46,42 @@ var comboBoxInputStyles = null;
42
46
  var ComboBoxFormField = exports.ComboBoxFormField = function ComboBoxFormField(_ref3) {
43
47
  var field = _ref3.field,
44
48
  dataTestId = _ref3.dataTestId;
45
- return /*#__PURE__*/React.createElement("foreignObject", {
49
+ return /*#__PURE__*/_react.default.createElement("foreignObject", {
46
50
  x: field.x,
47
51
  y: -field.y,
48
52
  width: field.w,
49
53
  height: field.h,
50
54
  "data-testid": dataTestId
51
- }, /*#__PURE__*/React.createElement("div", (0, _extends2.default)({}, foreignObjectProps, {
55
+ }, /*#__PURE__*/_react.default.createElement("div", (0, _extends2.default)({}, foreignObjectProps, {
52
56
  className: (0, _runtime.ax)(["_1e0c11p5 _yv0e1ghl _4cvr1h6o _1bah1yb4 _kqswstnw _4t3i1osq _1bsb1osq"])
53
- }), /*#__PURE__*/React.createElement("input", {
57
+ }), /*#__PURE__*/_react.default.createElement("input", {
54
58
  style: (0, _defineProperty2.default)({}, 'fontSize', "".concat(field.f, "px")),
55
59
  type: "text",
56
- value: field.text,
60
+ value: field.text
61
+ // stop propagation of the arrow key events because they can be used to navigate viewports
62
+ ,
63
+ onKeyUp: function onKeyUp(e) {
64
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
65
+ e.stopPropagation();
66
+ }
67
+ },
57
68
  readOnly: true,
58
69
  className: (0, _runtime.ax)(["_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _r06hglyw", "_1bsb1osq"])
59
- }), /*#__PURE__*/React.createElement(_chevronDown.default, {
70
+ }), /*#__PURE__*/_react.default.createElement(_chevronDown.default, {
60
71
  label: "",
61
72
  size: "small"
62
73
  })));
63
74
  };
64
75
  var Annotations = exports.Annotations = function Annotations(_ref5) {
65
76
  var annotations = _ref5.annotations;
66
- return /*#__PURE__*/React.createElement("div", null, annotations.text_form_fields.map(function (field, i) {
67
- return /*#__PURE__*/React.createElement(TextInputFormField, {
77
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, annotations.text_form_fields.map(function (field, i) {
78
+ return /*#__PURE__*/_react.default.createElement(TextInputFormField, {
68
79
  field: field,
69
80
  dataTestId: "text-form-field-".concat(i),
70
81
  key: i
71
82
  });
72
83
  }), annotations.combobox_form_fields.map(function (field, i) {
73
- return /*#__PURE__*/React.createElement(ComboBoxFormField, {
84
+ return /*#__PURE__*/_react.default.createElement(ComboBoxFormField, {
74
85
  field: field,
75
86
  dataTestId: "combobox-form-field-".concat(i),
76
87
  key: i
@@ -1,9 +1,7 @@
1
1
 
2
2
  ._zulputpp{gap:var(--ds-space-150,9pt)}._18m91wug{overflow-y:auto}
3
3
  ._19pkxncg{margin-top:var(--ds-space-800,4pc)}
4
- ._1bah1h6o{justify-content:center}
5
4
  ._1e0c1txw{display:flex}
6
5
  ._1reo1wug{overflow-x:auto}
7
6
  ._1ul91osq{min-width:100%}
8
- ._2lx21bp4{flex-direction:column}
9
- ._4cvr1h6o{align-items:center}
7
+ ._2lx21bp4{flex-direction:column}
@@ -8,18 +8,21 @@ Object.defineProperty(exports, "__esModule", {
8
8
  });
9
9
  exports.DocumentViewer = void 0;
10
10
  require("./documentViewer.compiled.css");
11
- var React = _interopRequireWildcard(require("react"));
11
+ var _react = _interopRequireWildcard(require("react"));
12
+ var React = _react;
12
13
  var _runtime = require("@compiled/react/runtime");
13
14
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
14
15
  var _page = require("./page");
15
16
  var _usePageContent2 = require("./usePageContent");
17
+ var _getDocumentRoot = require("./utils/getDocumentRoot");
16
18
  var _useCachedGetImage = require("./utils/useCachedGetImage");
17
19
  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); }
18
20
  var documentViewerStyles = null;
19
21
  var DEFAULT_PAGINATION_SIZE = 50;
20
22
  var DocumentViewer = exports.DocumentViewer = function DocumentViewer(_ref) {
21
23
  var _documentMetadata$pag;
22
- var getContent = _ref.getContent,
24
+ var onSuccess = _ref.onSuccess,
25
+ getContent = _ref.getContent,
23
26
  getPageImageUrl = _ref.getPageImageUrl,
24
27
  _ref$paginationSize = _ref.paginationSize,
25
28
  paginationSize = _ref$paginationSize === void 0 ? DEFAULT_PAGINATION_SIZE : _ref$paginationSize,
@@ -32,10 +35,39 @@ var DocumentViewer = exports.DocumentViewer = function DocumentViewer(_ref) {
32
35
  var style = {
33
36
  '--document-viewer-zoom': zoom
34
37
  };
38
+ var previousZoomRef = (0, _react.useRef)(zoom);
39
+
40
+ // Apply zoom with center-based adjustment
41
+ (0, _react.useLayoutEffect)(function () {
42
+ var previousZoom = previousZoomRef.current;
43
+
44
+ // Only adjust scroll if zoom actually changed
45
+ if (previousZoom !== zoom) {
46
+ // If we are not using a custom scroll element, we don't need to adjust the scroll position
47
+ var container = (0, _getDocumentRoot.getScrollElement)();
48
+ if (!container) {
49
+ return;
50
+ }
51
+
52
+ // Calculate the center point of the viewport before zoom
53
+ var viewportCenterX = container.scrollLeft + container.clientWidth / 2;
54
+ var viewportCenterY = container.scrollTop + container.clientHeight / 2;
55
+
56
+ // Calculate scale difference
57
+ var scaleDiff = zoom / previousZoom - 1;
58
+
59
+ // Adjust scroll to keep center point fixed
60
+ container.scrollLeft += viewportCenterX * scaleDiff;
61
+ container.scrollTop += viewportCenterY * scaleDiff;
62
+
63
+ // Update previous zoom
64
+ previousZoomRef.current = zoom;
65
+ }
66
+ }, [zoom]);
35
67
  return /*#__PURE__*/React.createElement("div", {
36
68
  "data-testid": "document-viewer",
37
69
  style: style,
38
- className: (0, _runtime.ax)(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _4cvr1h6o _1bah1h6o"])
70
+ className: (0, _runtime.ax)(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4"])
39
71
  }, (0, _toConsumableArray2.default)(Array((_documentMetadata$pag = documentMetadata.pageCount) !== null && _documentMetadata$pag !== void 0 ? _documentMetadata$pag : 4)).map(function (_, i) {
40
72
  var _getPageContent = getPageContent(i),
41
73
  page = _getPageContent.page,
@@ -49,6 +81,7 @@ var DocumentViewer = exports.DocumentViewer = function DocumentViewer(_ref) {
49
81
  onVisible: function onVisible() {
50
82
  return loadPageContent(i);
51
83
  },
84
+ onLoad: i === 0 ? onSuccess : undefined,
52
85
  fonts: fonts,
53
86
  content: page
54
87
  });
@@ -1,6 +1,8 @@
1
1
  ._154iidpf{top:0}
2
+ ._18u01wug{margin-left:auto}
2
3
  ._1kemd8h4{image-rendering:pixelated}
3
4
  ._1ltvidpf{left:0}
5
+ ._2hwx1wug{margin-right:auto}
4
6
  ._80om1kdv{cursor:text}
5
7
  ._bfhku67f{background-color:#fff}
6
8
  ._kqswh2mm{position:relative}
package/dist/cjs/page.js CHANGED
@@ -84,7 +84,7 @@ var PageView = /*#__PURE__*/(0, _react.forwardRef)(function (_ref4, ref) {
84
84
  style: style,
85
85
  "data-testid": "page-".concat(pageIndex),
86
86
  id: "page-".concat(pageIndex + 1),
87
- className: (0, _runtime.ax)(["_kqswh2mm _bfhku67f"])
87
+ className: (0, _runtime.ax)(["_kqswh2mm _bfhku67f _18u01wug _2hwx1wug"])
88
88
  }, imageSrc && /*#__PURE__*/React.createElement("img", {
89
89
  style: style,
90
90
  "data-testid": "page-".concat(pageIndex, "-image"),
@@ -120,7 +120,8 @@ var Page = exports.Page = function Page(_ref5) {
120
120
  pageIndex = _ref5.pageIndex,
121
121
  zoom = _ref5.zoom,
122
122
  defaultDimensions = _ref5.defaultDimensions,
123
- onVisible = _ref5.onVisible;
123
+ onVisible = _ref5.onVisible,
124
+ onLoad = _ref5.onLoad;
124
125
  var _useState = (0, _react.useState)(),
125
126
  _useState2 = (0, _slicedToArray2.default)(_useState, 2),
126
127
  imageSrc = _useState2[0],
@@ -143,6 +144,7 @@ var Page = exports.Page = function Page(_ref5) {
143
144
  setDimensions = _useState4[1];
144
145
  var onImageLoad = (0, _mediaCommon.useStaticCallback)(function (event) {
145
146
  var image = event.currentTarget;
147
+ onLoad === null || onLoad === void 0 || onLoad();
146
148
  if (!content) {
147
149
  var _zoom = image.dataset.zoom ? Number(image.dataset.zoom) : 1;
148
150
  setDimensions({
@@ -3,18 +3,21 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getDocumentRoot = exports.DOCUMENT_SCROLL_ROOT_ID = void 0;
6
+ exports.getScrollElement = exports.getDocumentRoot = exports.DOCUMENT_SCROLL_ROOT_ID = void 0;
7
+ var _browserApis = require("@atlaskit/browser-apis");
7
8
  var DOCUMENT_SCROLL_ROOT_ID = exports.DOCUMENT_SCROLL_ROOT_ID = 'document-scroll-root';
8
9
  var getDocumentRoot = exports.getDocumentRoot = function getDocumentRoot() {
9
- if (typeof window === 'undefined') {
10
+ var doc = (0, _browserApis.getDocument)();
11
+ if (!doc) {
10
12
  return;
11
13
  }
12
- if (typeof window.document === 'undefined') {
13
- return;
14
- }
15
- var root = document.getElementById(DOCUMENT_SCROLL_ROOT_ID);
14
+ var root = doc.getElementById(DOCUMENT_SCROLL_ROOT_ID);
16
15
  if (root) {
17
16
  return root;
18
17
  }
19
- return window.document;
18
+ return doc;
19
+ };
20
+ var getScrollElement = exports.getScrollElement = function getScrollElement() {
21
+ var element = (0, _browserApis.getDocument)();
22
+ return element && element.getElementById(DOCUMENT_SCROLL_ROOT_ID);
20
23
  };
@@ -1,10 +1,10 @@
1
1
  /* annotations.tsx generated by @compiled/babel-plugin v0.36.1 */
2
2
  import _extends from "@babel/runtime/helpers/extends";
3
3
  import "./annotations.compiled.css";
4
- import * as React from 'react';
5
4
  import { ax, ix } from "@compiled/react/runtime";
6
5
  /* eslint-disable @atlaskit/ui-styling-standard/enforce-style-prop */
7
6
 
7
+ import React from 'react';
8
8
  import ChevronDownIcon from '@atlaskit/icon/core/chevron-down';
9
9
  const formInputBaseStyles = null;
10
10
  const textInputStyles = null;
@@ -28,6 +28,12 @@ export const TextInputFormField = ({
28
28
  type: "text",
29
29
  value: field.text,
30
30
  readOnly: true,
31
+ onKeyUp: e => {
32
+ // stop propagation of the arrow key events because they can be used to navigate viewports
33
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
34
+ e.stopPropagation();
35
+ }
36
+ },
31
37
  className: ax(["_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _r06hglyw", "_kqswstnw _4t3i1osq _1bsb1osq"])
32
38
  })));
33
39
  };
@@ -50,7 +56,14 @@ export const ComboBoxFormField = ({
50
56
  ['fontSize']: `${field.f}px`
51
57
  },
52
58
  type: "text",
53
- value: field.text,
59
+ value: field.text
60
+ // stop propagation of the arrow key events because they can be used to navigate viewports
61
+ ,
62
+ onKeyUp: e => {
63
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
64
+ e.stopPropagation();
65
+ }
66
+ },
54
67
  readOnly: true,
55
68
  className: ax(["_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _r06hglyw", "_1bsb1osq"])
56
69
  }), /*#__PURE__*/React.createElement(ChevronDownIcon, {
@@ -61,7 +74,7 @@ export const ComboBoxFormField = ({
61
74
  export const Annotations = ({
62
75
  annotations
63
76
  }) => {
64
- return /*#__PURE__*/React.createElement("div", null, annotations.text_form_fields.map((field, i) => {
77
+ return /*#__PURE__*/React.createElement(React.Fragment, null, annotations.text_form_fields.map((field, i) => {
65
78
  return /*#__PURE__*/React.createElement(TextInputFormField, {
66
79
  field: field,
67
80
  dataTestId: `text-form-field-${i}`,
@@ -1,9 +1,7 @@
1
1
 
2
2
  ._zulputpp{gap:var(--ds-space-150,9pt)}._18m91wug{overflow-y:auto}
3
3
  ._19pkxncg{margin-top:var(--ds-space-800,4pc)}
4
- ._1bah1h6o{justify-content:center}
5
4
  ._1e0c1txw{display:flex}
6
5
  ._1reo1wug{overflow-x:auto}
7
6
  ._1ul91osq{min-width:100%}
8
- ._2lx21bp4{flex-direction:column}
9
- ._4cvr1h6o{align-items:center}
7
+ ._2lx21bp4{flex-direction:column}
@@ -2,12 +2,15 @@
2
2
  import "./documentViewer.compiled.css";
3
3
  import * as React from 'react';
4
4
  import { ax, ix } from "@compiled/react/runtime";
5
+ import { useLayoutEffect, useRef } from 'react';
5
6
  import { Page } from './page';
6
7
  import { usePageContent } from './usePageContent';
8
+ import { getScrollElement } from './utils/getDocumentRoot';
7
9
  import { useCachedGetImage } from './utils/useCachedGetImage';
8
10
  const documentViewerStyles = null;
9
11
  const DEFAULT_PAGINATION_SIZE = 50;
10
12
  export const DocumentViewer = ({
13
+ onSuccess,
11
14
  getContent,
12
15
  getPageImageUrl,
13
16
  paginationSize = DEFAULT_PAGINATION_SIZE,
@@ -23,10 +26,39 @@ export const DocumentViewer = ({
23
26
  const style = {
24
27
  '--document-viewer-zoom': zoom
25
28
  };
29
+ const previousZoomRef = useRef(zoom);
30
+
31
+ // Apply zoom with center-based adjustment
32
+ useLayoutEffect(() => {
33
+ const previousZoom = previousZoomRef.current;
34
+
35
+ // Only adjust scroll if zoom actually changed
36
+ if (previousZoom !== zoom) {
37
+ // If we are not using a custom scroll element, we don't need to adjust the scroll position
38
+ const container = getScrollElement();
39
+ if (!container) {
40
+ return;
41
+ }
42
+
43
+ // Calculate the center point of the viewport before zoom
44
+ const viewportCenterX = container.scrollLeft + container.clientWidth / 2;
45
+ const viewportCenterY = container.scrollTop + container.clientHeight / 2;
46
+
47
+ // Calculate scale difference
48
+ const scaleDiff = zoom / previousZoom - 1;
49
+
50
+ // Adjust scroll to keep center point fixed
51
+ container.scrollLeft += viewportCenterX * scaleDiff;
52
+ container.scrollTop += viewportCenterY * scaleDiff;
53
+
54
+ // Update previous zoom
55
+ previousZoomRef.current = zoom;
56
+ }
57
+ }, [zoom]);
26
58
  return /*#__PURE__*/React.createElement("div", {
27
59
  "data-testid": "document-viewer",
28
60
  style: style,
29
- className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _4cvr1h6o _1bah1h6o"])
61
+ className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4"])
30
62
  }, [...Array((_documentMetadata$pag = documentMetadata.pageCount) !== null && _documentMetadata$pag !== void 0 ? _documentMetadata$pag : 4)].map((_, i) => {
31
63
  const {
32
64
  page,
@@ -39,6 +71,7 @@ export const DocumentViewer = ({
39
71
  zoom: zoom,
40
72
  defaultDimensions: documentMetadata.defaultDimensions,
41
73
  onVisible: () => loadPageContent(i),
74
+ onLoad: i === 0 ? onSuccess : undefined,
42
75
  fonts: fonts,
43
76
  content: page
44
77
  });
@@ -1,6 +1,8 @@
1
1
  ._154iidpf{top:0}
2
+ ._18u01wug{margin-left:auto}
2
3
  ._1kemd8h4{image-rendering:pixelated}
3
4
  ._1ltvidpf{left:0}
5
+ ._2hwx1wug{margin-right:auto}
4
6
  ._80om1kdv{cursor:text}
5
7
  ._bfhku67f{background-color:#fff}
6
8
  ._kqswh2mm{position:relative}
@@ -74,7 +74,7 @@ const PageView = /*#__PURE__*/forwardRef(({
74
74
  style: style,
75
75
  "data-testid": `page-${pageIndex}`,
76
76
  id: `page-${pageIndex + 1}`,
77
- className: ax(["_kqswh2mm _bfhku67f"])
77
+ className: ax(["_kqswh2mm _bfhku67f _18u01wug _2hwx1wug"])
78
78
  }, imageSrc && /*#__PURE__*/React.createElement("img", {
79
79
  style: style,
80
80
  "data-testid": `page-${pageIndex}-image`,
@@ -107,7 +107,8 @@ export const Page = ({
107
107
  pageIndex,
108
108
  zoom,
109
109
  defaultDimensions,
110
- onVisible
110
+ onVisible,
111
+ onLoad
111
112
  }) => {
112
113
  var _ref;
113
114
  const [imageSrc, setImageSrc] = useState();
@@ -127,6 +128,7 @@ export const Page = ({
127
128
  const [dimensions, setDimensions] = useState();
128
129
  const onImageLoad = useStaticCallback(event => {
129
130
  const image = event.currentTarget;
131
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad();
130
132
  if (!content) {
131
133
  const zoom = image.dataset.zoom ? Number(image.dataset.zoom) : 1;
132
134
  setDimensions({
@@ -1,14 +1,17 @@
1
+ import { getDocument } from "@atlaskit/browser-apis";
1
2
  export const DOCUMENT_SCROLL_ROOT_ID = 'document-scroll-root';
2
3
  export const getDocumentRoot = () => {
3
- if (typeof window === 'undefined') {
4
+ const doc = getDocument();
5
+ if (!doc) {
4
6
  return;
5
7
  }
6
- if (typeof window.document === 'undefined') {
7
- return;
8
- }
9
- const root = document.getElementById(DOCUMENT_SCROLL_ROOT_ID);
8
+ const root = doc.getElementById(DOCUMENT_SCROLL_ROOT_ID);
10
9
  if (root) {
11
10
  return root;
12
11
  }
13
- return window.document;
12
+ return doc;
13
+ };
14
+ export const getScrollElement = () => {
15
+ const element = getDocument();
16
+ return element && element.getElementById(DOCUMENT_SCROLL_ROOT_ID);
14
17
  };
@@ -2,10 +2,10 @@
2
2
  import _extends from "@babel/runtime/helpers/extends";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
4
  import "./annotations.compiled.css";
5
- import * as React from 'react';
6
5
  import { ax, ix } from "@compiled/react/runtime";
7
6
  /* eslint-disable @atlaskit/ui-styling-standard/enforce-style-prop */
8
7
 
8
+ import React from 'react';
9
9
  import ChevronDownIcon from '@atlaskit/icon/core/chevron-down';
10
10
  var formInputBaseStyles = null;
11
11
  var textInputStyles = null;
@@ -26,6 +26,12 @@ export var TextInputFormField = function TextInputFormField(_ref) {
26
26
  type: "text",
27
27
  value: field.text,
28
28
  readOnly: true,
29
+ onKeyUp: function onKeyUp(e) {
30
+ // stop propagation of the arrow key events because they can be used to navigate viewports
31
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
32
+ e.stopPropagation();
33
+ }
34
+ },
29
35
  className: ax(["_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _r06hglyw", "_kqswstnw _4t3i1osq _1bsb1osq"])
30
36
  })));
31
37
  };
@@ -45,7 +51,14 @@ export var ComboBoxFormField = function ComboBoxFormField(_ref3) {
45
51
  }), /*#__PURE__*/React.createElement("input", {
46
52
  style: _defineProperty({}, 'fontSize', "".concat(field.f, "px")),
47
53
  type: "text",
48
- value: field.text,
54
+ value: field.text
55
+ // stop propagation of the arrow key events because they can be used to navigate viewports
56
+ ,
57
+ onKeyUp: function onKeyUp(e) {
58
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
59
+ e.stopPropagation();
60
+ }
61
+ },
49
62
  readOnly: true,
50
63
  className: ax(["_19itglyw _ca0qidpf _u5f3idpf _n3tdidpf _19bvidpf _r06hglyw", "_1bsb1osq"])
51
64
  }), /*#__PURE__*/React.createElement(ChevronDownIcon, {
@@ -55,7 +68,7 @@ export var ComboBoxFormField = function ComboBoxFormField(_ref3) {
55
68
  };
56
69
  export var Annotations = function Annotations(_ref5) {
57
70
  var annotations = _ref5.annotations;
58
- return /*#__PURE__*/React.createElement("div", null, annotations.text_form_fields.map(function (field, i) {
71
+ return /*#__PURE__*/React.createElement(React.Fragment, null, annotations.text_form_fields.map(function (field, i) {
59
72
  return /*#__PURE__*/React.createElement(TextInputFormField, {
60
73
  field: field,
61
74
  dataTestId: "text-form-field-".concat(i),
@@ -1,9 +1,7 @@
1
1
 
2
2
  ._zulputpp{gap:var(--ds-space-150,9pt)}._18m91wug{overflow-y:auto}
3
3
  ._19pkxncg{margin-top:var(--ds-space-800,4pc)}
4
- ._1bah1h6o{justify-content:center}
5
4
  ._1e0c1txw{display:flex}
6
5
  ._1reo1wug{overflow-x:auto}
7
6
  ._1ul91osq{min-width:100%}
8
- ._2lx21bp4{flex-direction:column}
9
- ._4cvr1h6o{align-items:center}
7
+ ._2lx21bp4{flex-direction:column}
@@ -3,14 +3,17 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  import "./documentViewer.compiled.css";
4
4
  import * as React from 'react';
5
5
  import { ax, ix } from "@compiled/react/runtime";
6
+ import { useLayoutEffect, useRef } from 'react';
6
7
  import { Page } from './page';
7
8
  import { usePageContent } from './usePageContent';
9
+ import { getScrollElement } from './utils/getDocumentRoot';
8
10
  import { useCachedGetImage } from './utils/useCachedGetImage';
9
11
  var documentViewerStyles = null;
10
12
  var DEFAULT_PAGINATION_SIZE = 50;
11
13
  export var DocumentViewer = function DocumentViewer(_ref) {
12
14
  var _documentMetadata$pag;
13
- var getContent = _ref.getContent,
15
+ var onSuccess = _ref.onSuccess,
16
+ getContent = _ref.getContent,
14
17
  getPageImageUrl = _ref.getPageImageUrl,
15
18
  _ref$paginationSize = _ref.paginationSize,
16
19
  paginationSize = _ref$paginationSize === void 0 ? DEFAULT_PAGINATION_SIZE : _ref$paginationSize,
@@ -23,10 +26,39 @@ export var DocumentViewer = function DocumentViewer(_ref) {
23
26
  var style = {
24
27
  '--document-viewer-zoom': zoom
25
28
  };
29
+ var previousZoomRef = useRef(zoom);
30
+
31
+ // Apply zoom with center-based adjustment
32
+ useLayoutEffect(function () {
33
+ var previousZoom = previousZoomRef.current;
34
+
35
+ // Only adjust scroll if zoom actually changed
36
+ if (previousZoom !== zoom) {
37
+ // If we are not using a custom scroll element, we don't need to adjust the scroll position
38
+ var container = getScrollElement();
39
+ if (!container) {
40
+ return;
41
+ }
42
+
43
+ // Calculate the center point of the viewport before zoom
44
+ var viewportCenterX = container.scrollLeft + container.clientWidth / 2;
45
+ var viewportCenterY = container.scrollTop + container.clientHeight / 2;
46
+
47
+ // Calculate scale difference
48
+ var scaleDiff = zoom / previousZoom - 1;
49
+
50
+ // Adjust scroll to keep center point fixed
51
+ container.scrollLeft += viewportCenterX * scaleDiff;
52
+ container.scrollTop += viewportCenterY * scaleDiff;
53
+
54
+ // Update previous zoom
55
+ previousZoomRef.current = zoom;
56
+ }
57
+ }, [zoom]);
26
58
  return /*#__PURE__*/React.createElement("div", {
27
59
  "data-testid": "document-viewer",
28
60
  style: style,
29
- className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4 _4cvr1h6o _1bah1h6o"])
61
+ className: ax(["_zulputpp _1reo1wug _18m91wug _19pkxncg _1ul91osq _1e0c1txw _2lx21bp4"])
30
62
  }, _toConsumableArray(Array((_documentMetadata$pag = documentMetadata.pageCount) !== null && _documentMetadata$pag !== void 0 ? _documentMetadata$pag : 4)).map(function (_, i) {
31
63
  var _getPageContent = getPageContent(i),
32
64
  page = _getPageContent.page,
@@ -40,6 +72,7 @@ export var DocumentViewer = function DocumentViewer(_ref) {
40
72
  onVisible: function onVisible() {
41
73
  return loadPageContent(i);
42
74
  },
75
+ onLoad: i === 0 ? onSuccess : undefined,
43
76
  fonts: fonts,
44
77
  content: page
45
78
  });
@@ -1,6 +1,8 @@
1
1
  ._154iidpf{top:0}
2
+ ._18u01wug{margin-left:auto}
2
3
  ._1kemd8h4{image-rendering:pixelated}
3
4
  ._1ltvidpf{left:0}
5
+ ._2hwx1wug{margin-right:auto}
4
6
  ._80om1kdv{cursor:text}
5
7
  ._bfhku67f{background-color:#fff}
6
8
  ._kqswh2mm{position:relative}
package/dist/esm/page.js CHANGED
@@ -75,7 +75,7 @@ var PageView = /*#__PURE__*/forwardRef(function (_ref4, ref) {
75
75
  style: style,
76
76
  "data-testid": "page-".concat(pageIndex),
77
77
  id: "page-".concat(pageIndex + 1),
78
- className: ax(["_kqswh2mm _bfhku67f"])
78
+ className: ax(["_kqswh2mm _bfhku67f _18u01wug _2hwx1wug"])
79
79
  }, imageSrc && /*#__PURE__*/React.createElement("img", {
80
80
  style: style,
81
81
  "data-testid": "page-".concat(pageIndex, "-image"),
@@ -111,7 +111,8 @@ export var Page = function Page(_ref5) {
111
111
  pageIndex = _ref5.pageIndex,
112
112
  zoom = _ref5.zoom,
113
113
  defaultDimensions = _ref5.defaultDimensions,
114
- onVisible = _ref5.onVisible;
114
+ onVisible = _ref5.onVisible,
115
+ onLoad = _ref5.onLoad;
115
116
  var _useState = useState(),
116
117
  _useState2 = _slicedToArray(_useState, 2),
117
118
  imageSrc = _useState2[0],
@@ -134,6 +135,7 @@ export var Page = function Page(_ref5) {
134
135
  setDimensions = _useState4[1];
135
136
  var onImageLoad = useStaticCallback(function (event) {
136
137
  var image = event.currentTarget;
138
+ onLoad === null || onLoad === void 0 || onLoad();
137
139
  if (!content) {
138
140
  var _zoom = image.dataset.zoom ? Number(image.dataset.zoom) : 1;
139
141
  setDimensions({
@@ -1,14 +1,17 @@
1
+ import { getDocument } from "@atlaskit/browser-apis";
1
2
  export var DOCUMENT_SCROLL_ROOT_ID = 'document-scroll-root';
2
3
  export var getDocumentRoot = function getDocumentRoot() {
3
- if (typeof window === 'undefined') {
4
+ var doc = getDocument();
5
+ if (!doc) {
4
6
  return;
5
7
  }
6
- if (typeof window.document === 'undefined') {
7
- return;
8
- }
9
- var root = document.getElementById(DOCUMENT_SCROLL_ROOT_ID);
8
+ var root = doc.getElementById(DOCUMENT_SCROLL_ROOT_ID);
10
9
  if (root) {
11
10
  return root;
12
11
  }
13
- return window.document;
12
+ return doc;
13
+ };
14
+ export var getScrollElement = function getScrollElement() {
15
+ var element = getDocument();
16
+ return element && element.getElementById(DOCUMENT_SCROLL_ROOT_ID);
14
17
  };
@@ -5,6 +5,7 @@ type DocumentViewerProps = {
5
5
  getPageImageUrl: (pageNumber: number, zoom: number) => Promise<string>;
6
6
  paginationSize?: number;
7
7
  zoom: number;
8
+ onSuccess?: () => void;
8
9
  };
9
- export declare const DocumentViewer: ({ getContent, getPageImageUrl, paginationSize, zoom, }: DocumentViewerProps) => JSX.Element;
10
+ export declare const DocumentViewer: ({ onSuccess, getContent, getPageImageUrl, paginationSize, zoom, }: DocumentViewerProps) => JSX.Element;
10
11
  export {};
@@ -11,6 +11,7 @@ type PageProps = {
11
11
  height: number;
12
12
  };
13
13
  onVisible: () => void;
14
+ onLoad?: () => void;
14
15
  };
15
- export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, }: PageProps) => JSX.Element;
16
+ export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, onLoad, }: PageProps) => JSX.Element;
16
17
  export {};
@@ -1,2 +1,3 @@
1
1
  export declare const DOCUMENT_SCROLL_ROOT_ID = "document-scroll-root";
2
2
  export declare const getDocumentRoot: () => HTMLElement | Document | undefined;
3
+ export declare const getScrollElement: () => HTMLElement | null;
@@ -5,6 +5,7 @@ type DocumentViewerProps = {
5
5
  getPageImageUrl: (pageNumber: number, zoom: number) => Promise<string>;
6
6
  paginationSize?: number;
7
7
  zoom: number;
8
+ onSuccess?: () => void;
8
9
  };
9
- export declare const DocumentViewer: ({ getContent, getPageImageUrl, paginationSize, zoom, }: DocumentViewerProps) => JSX.Element;
10
+ export declare const DocumentViewer: ({ onSuccess, getContent, getPageImageUrl, paginationSize, zoom, }: DocumentViewerProps) => JSX.Element;
10
11
  export {};
@@ -11,6 +11,7 @@ type PageProps = {
11
11
  height: number;
12
12
  };
13
13
  onVisible: () => void;
14
+ onLoad?: () => void;
14
15
  };
15
- export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, }: PageProps) => JSX.Element;
16
+ export declare const Page: ({ getPageSrc, content, fonts, pageIndex, zoom, defaultDimensions, onVisible, onLoad, }: PageProps) => JSX.Element;
16
17
  export {};
@@ -1,2 +1,3 @@
1
1
  export declare const DOCUMENT_SCROLL_ROOT_ID = "document-scroll-root";
2
2
  export declare const getDocumentRoot: () => HTMLElement | Document | undefined;
3
+ export declare const getScrollElement: () => HTMLElement | null;
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "atlassian": {
3
3
  "team": "Media Exif",
4
- "runReact18": true,
5
4
  "website": {
6
5
  "name": "MediaDocumentViewer",
7
6
  "category": "Layout and structure"
@@ -28,6 +27,7 @@
28
27
  ".": "./src/index.ts"
29
28
  },
30
29
  "dependencies": {
30
+ "@atlaskit/browser-apis": "^0.0.1",
31
31
  "@atlaskit/css": "^0.12.0",
32
32
  "@atlaskit/icon": "^27.2.0",
33
33
  "@atlaskit/media-common": "^12.3.0",
@@ -45,6 +45,7 @@
45
45
  "@atlaskit/ssr": "workspace:^",
46
46
  "@atlaskit/visual-regression": "workspace:^",
47
47
  "@testing-library/react": "^13.4.0",
48
+ "@testing-library/user-event": "^14.4.3",
48
49
  "react-dom": "^18.2.0",
49
50
  "typescript": "~5.4.2"
50
51
  },
@@ -84,7 +85,7 @@
84
85
  }
85
86
  },
86
87
  "name": "@atlaskit/media-document-viewer",
87
- "version": "0.2.3",
88
+ "version": "0.3.1",
88
89
  "description": "Modern and fast document viewer",
89
90
  "author": "Atlassian Pty Ltd",
90
91
  "license": "Apache-2.0",