box-content-preview 3.68.0 → 3.70.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
  [![Mergify Status](https://img.shields.io/endpoint.svg?url=https://gh.mergify.io/badges/box/box-content-preview&style=flat)](https://mergify.io)
3
3
  [![Styled With Prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
4
4
  [![build status](https://img.shields.io/travis/box/box-content-preview/master.svg?style=flat-square)](https://travis-ci.org/box/box-content-preview)
5
- [![version](https://img.shields.io/badge/version-v3.68.0-blue.svg?style=flat-square)](https://github.com/box/box-content-preview)
5
+ [![version](https://img.shields.io/badge/version-v3.70.0-blue.svg?style=flat-square)](https://github.com/box/box-content-preview)
6
6
  [![npm version](https://img.shields.io/npm/v/box-ui-elements.svg?style=flat-square)](https://www.npmjs.com/package/box-ui-elements)
7
7
 
8
8
  # [Box Content Preview](https://developer.box.com/docs/box-content-preview)
@@ -22,11 +22,11 @@ We encourage all users to update their applications to utilize modern browsers f
22
22
 
23
23
  ## Current Version
24
24
 
25
- - Version: v3.68.0
25
+ - Version: v3.70.0
26
26
  - Locale: en-US
27
27
 
28
- https://cdn01.boxcdn.net/platform/preview/3.68.0/en-US/preview.js
29
- https://cdn01.boxcdn.net/platform/preview/3.68.0/en-US/preview.css
28
+ https://cdn01.boxcdn.net/platform/preview/3.70.0/en-US/preview.js
29
+ https://cdn01.boxcdn.net/platform/preview/3.70.0/en-US/preview.css
30
30
 
31
31
  ## Supported Locales
32
32
 
@@ -52,10 +52,10 @@ You can self-host the Box Content Preview library or reference the versions avai
52
52
  <title>Box Content Preview Demo</title>
53
53
 
54
54
  <!-- Latest version of Preview SDK for your locale -->
55
- <script src="https://cdn01.boxcdn.net/platform/preview/3.68.0/en-US/preview.js"></script>
55
+ <script src="https://cdn01.boxcdn.net/platform/preview/3.70.0/en-US/preview.js"></script>
56
56
  <link
57
57
  rel="stylesheet"
58
- href="https://cdn01.boxcdn.net/platform/preview/3.68.0/en-US/preview.css"
58
+ href="https://cdn01.boxcdn.net/platform/preview/3.70.0/en-US/preview.css"
59
59
  />
60
60
  </head>
61
61
  <body>
@@ -76,7 +76,7 @@ To self-host the Box Content Preview library, follow these steps:
76
76
 
77
77
  1. Either fork the repo and check out the version you want to host or download the specific version as a zip:
78
78
 
79
- - Check out a specific version with `git checkout v3.68.0`
79
+ - Check out a specific version with `git checkout v3.70.0`
80
80
  - Download a specific version as a zip from https://github.com/box/box-content-preview/releases
81
81
 
82
82
  2. Install dependencies and build the library with `yarn install && yarn build:i18n && yarn build:prod`
package/dist/lib/index.js CHANGED
@@ -17387,6 +17387,15 @@ const USER_DOCUMENT_THUMBNAIL_EVENTS = {
17387
17387
  NAVIGATE: 'user_document_thumbnails_navigate',
17388
17388
  OPEN: 'user_document_thumbnails_open'
17389
17389
  };
17390
+
17391
+ // Events fired when using gallery view
17392
+ const USER_DOCUMENT_GALLERY_EVENTS = {
17393
+ DISMISS: 'user_document_gallery_dismiss',
17394
+ // The gallery closes without the user settling on a page
17395
+ NAVIGATE: 'user_document_gallery_navigate',
17396
+ // The user picks a page, or closes on one they browsed to
17397
+ OPEN: 'user_document_gallery_open' // The user opens the gallery
17398
+ };
17390
17399
  const MISSING_EXTERNAL_REFS = 'missing_x_refs';
17391
17400
  const MEDIA_METRIC = {
17392
17401
  bufferFill: 'bufferFill',
@@ -17416,7 +17425,7 @@ function util_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var
17416
17425
  const CLIENT_NAME = "box-content-preview"; // eslint-disable-line no-undef
17417
17426
  const CLIENT_NAME_KEY = 'box_client_name';
17418
17427
  const CLIENT_VERSION_KEY = 'box_client_version';
17419
- const CLIENT_VERSION = "3.68.0"; // eslint-disable-line no-undef
17428
+ const CLIENT_VERSION = "3.70.0"; // eslint-disable-line no-undef
17420
17429
  const HEADER_CLIENT_NAME = 'X-Box-Client-Name';
17421
17430
  const HEADER_CLIENT_VERSION = 'X-Box-Client-Version';
17422
17431
  const PROMISE_MAP = {};
@@ -19141,7 +19150,7 @@ class Browser {
19141
19150
  ;// ./src/lib/Logger.js
19142
19151
  /* eslint-disable no-undef */
19143
19152
  const Logger_CLIENT_NAME = "box-content-preview";
19144
- const Logger_CLIENT_VERSION = "3.68.0";
19153
+ const Logger_CLIENT_VERSION = "3.70.0";
19145
19154
  /* eslint-enable no-undef */
19146
19155
 
19147
19156
  class Logger {
@@ -24627,13 +24636,13 @@ const ImageLoader_VIEWERS = [{
24627
24636
  NAME: 'Image',
24628
24637
  CONSTRUCTOR: image_ImageViewer,
24629
24638
  REP: 'jpg',
24630
- EXT: ['jpeg', 'jpg', 'cr2', 'crw', 'dng', 'nef', 'raf', 'raw'],
24639
+ EXT: ['jpeg', 'jpg', 'cr2', 'cr3', 'crw', 'dng', 'nef', 'raf', 'raw'],
24631
24640
  ASSET: '1.jpg'
24632
24641
  }, {
24633
24642
  NAME: 'Image',
24634
24643
  CONSTRUCTOR: image_ImageViewer,
24635
24644
  REP: 'png',
24636
- EXT: ['ai', 'bmp', 'dcm', 'eps', 'gif', 'heic', 'png', 'ps', 'psd', 'tga', 'tif', 'tiff', 'webp'],
24645
+ EXT: ['ai', 'avif', 'bmp', 'dcm', 'eps', 'gif', 'heic', 'png', 'ps', 'psd', 'tga', 'tif', 'tiff', 'webp'],
24637
24646
  ASSET: '1.png'
24638
24647
  }];
24639
24648
  class ImageLoader extends viewers_AssetLoader {
@@ -39525,6 +39534,9 @@ class Thumbnail {
39525
39534
  return Promise.resolve(null);
39526
39535
  }
39527
39536
  return pdfDocument.getPage(1).then(page => {
39537
+ if (!this.thumbnailImageCache) {
39538
+ return null;
39539
+ }
39528
39540
  const rotation = ((this.pdfViewer.pagesRotation || 0) + page.rotate) % 360;
39529
39541
  const viewport = page.getViewport({
39530
39542
  scale: 1,
@@ -39586,6 +39598,9 @@ class Thumbnail {
39586
39598
  * @return {Promise} - promise reolves with the image HTMLElement or null if generation is in progress
39587
39599
  */
39588
39600
  createThumbnailImage(itemIndex, thumbOptions) {
39601
+ if (!this.thumbnailImageCache) {
39602
+ return Promise.resolve(null);
39603
+ }
39589
39604
  const cacheEntry = this.getImageFromCache(itemIndex);
39590
39605
  // If this thumbnail has already been cached, use it
39591
39606
  if (cacheEntry && cacheEntry.image) {
@@ -39602,8 +39617,10 @@ class Thumbnail {
39602
39617
  inProgress: true
39603
39618
  }));
39604
39619
  return this.getThumbnailDataURL(itemIndex + 1, thumbOptions).then(dataUrl => {
39605
- return this.createImageEl(dataUrl, thumbOptions);
39606
- }).then(imageEl => {
39620
+ if (!this.thumbnailImageCache) {
39621
+ return null;
39622
+ }
39623
+ const imageEl = this.createImageEl(dataUrl, thumbOptions);
39607
39624
  // Cache this image element for future use
39608
39625
  this.thumbnailImageCache.set(itemIndex, {
39609
39626
  inProgress: false,
@@ -39611,6 +39628,9 @@ class Thumbnail {
39611
39628
  });
39612
39629
  return imageEl;
39613
39630
  }).catch(() => {
39631
+ if (!this.thumbnailImageCache) {
39632
+ return null;
39633
+ }
39614
39634
  this.thumbnailImageCache.set(itemIndex, Thumbnail_objectSpread(Thumbnail_objectSpread({}, this.getImageFromCache(itemIndex)), {}, {
39615
39635
  inProgress: false
39616
39636
  }));
@@ -39625,7 +39645,7 @@ class Thumbnail {
39625
39645
  * @return {Promise} - promise reolves with the image HTMLElement or null if generation is in progress
39626
39646
  */
39627
39647
  getImageFromCache(itemIndex) {
39628
- return this.thumbnailImageCache.get(itemIndex);
39648
+ return this.thumbnailImageCache?.get(itemIndex) || null;
39629
39649
  }
39630
39650
 
39631
39651
  /**
@@ -39644,6 +39664,9 @@ class Thumbnail {
39644
39664
  const canvas = document.createElement('canvas');
39645
39665
  const thumbnailImageWidth = thumbOptions && thumbOptions.thumbMaxWidth ? thumbOptions.thumbMaxWidth : THUMBNAIL_IMAGE_WIDTH;
39646
39666
  return pdfDocument.getPage(pageNum).then(page => {
39667
+ if (!this.thumbnailImageCache) {
39668
+ return null;
39669
+ }
39647
39670
  const rotation = ((this.pdfViewer.pagesRotation || 0) + page.rotate) % 360;
39648
39671
  const viewport = page.getViewport({
39649
39672
  scale: 1,
@@ -39728,6 +39751,7 @@ const GalleryTile = /*#__PURE__*/__WEBPACK_EXTERNAL_MODULE_react_default__.memo(
39728
39751
  "aria-selected": isFocused,
39729
39752
  className: `bp-gallery-tile${isFocused ? ' bp-gallery-tile--selected' : ''}`,
39730
39753
  "data-page": pageNum,
39754
+ "data-resin-target": "galleryTile",
39731
39755
  onClick: () => onClick(pageNum),
39732
39756
  onFocus: () => onFocus(pageNum),
39733
39757
  role: "option",
@@ -40078,6 +40102,7 @@ class GalleryController {
40078
40102
  GalleryController_defineProperty(this, "focusToggle", void 0);
40079
40103
  GalleryController_defineProperty(this, "onBeforeOpen", void 0);
40080
40104
  GalleryController_defineProperty(this, "onAfterClose", void 0);
40105
+ GalleryController_defineProperty(this, "onClose", void 0);
40081
40106
  GalleryController_defineProperty(this, "galleryRoot", null);
40082
40107
  GalleryController_defineProperty(this, "galleryEl", null);
40083
40108
  GalleryController_defineProperty(this, "galleryThumbnail", null);
@@ -40086,6 +40111,7 @@ class GalleryController {
40086
40111
  GalleryController_defineProperty(this, "gallerySidebarTimeoutId", null);
40087
40112
  GalleryController_defineProperty(this, "sidebarWasOpen", false);
40088
40113
  GalleryController_defineProperty(this, "isGalleryOpen", false);
40114
+ GalleryController_defineProperty(this, "pickedPage", null);
40089
40115
  GalleryController_defineProperty(this, "toggle", () => {
40090
40116
  this.isGalleryOpen = !this.isGalleryOpen;
40091
40117
  if (this.isGalleryOpen) {
@@ -40136,6 +40162,11 @@ class GalleryController {
40136
40162
  }, THUMBNAILS_SIDEBAR_TRANSITION_TIME);
40137
40163
  }
40138
40164
  }
40165
+ const {
40166
+ pickedPage
40167
+ } = this;
40168
+ this.pickedPage = null;
40169
+ this.onClose(pickedPage ?? navigateToPage);
40139
40170
  }
40140
40171
  this.requestUiUpdate();
40141
40172
  if (!this.isGalleryOpen) {
@@ -40145,6 +40176,7 @@ class GalleryController {
40145
40176
  });
40146
40177
  GalleryController_defineProperty(this, "handleGalleryNavigate", pageNum => {
40147
40178
  this.galleryFocusedPage = pageNum;
40179
+ this.pickedPage = pageNum;
40148
40180
  this.toggle();
40149
40181
  });
40150
40182
  GalleryController_defineProperty(this, "handleFocusChange", pageNum => {
@@ -40175,6 +40207,7 @@ class GalleryController {
40175
40207
  this.focusToggle = opts.focusToggle;
40176
40208
  this.onBeforeOpen = opts.onBeforeOpen;
40177
40209
  this.onAfterClose = opts.onAfterClose;
40210
+ this.onClose = opts.onClose;
40178
40211
  }
40179
40212
  get isOpen() {
40180
40213
  return this.isGalleryOpen;
@@ -40215,6 +40248,12 @@ class GalleryController {
40215
40248
  }
40216
40249
  }
40217
40250
  destroy() {
40251
+ // Teardown with the gallery still open (file switch, preview closed) resolves the open
40252
+ // instead of leaving it looking abandoned. Depends on the viewer destroying this controller
40253
+ // before BaseViewer.destroy drops the metric listeners.
40254
+ if (this.isGalleryOpen) {
40255
+ this.onClose(null);
40256
+ }
40218
40257
  if (this.galleryMountTimeoutId !== null) {
40219
40258
  clearTimeout(this.galleryMountTimeoutId);
40220
40259
  this.galleryMountTimeoutId = null;
@@ -40261,6 +40300,7 @@ class GalleryController {
40261
40300
  }
40262
40301
  const thumbnail = this.galleryThumbnail;
40263
40302
  this.galleryEl = document.createElement('div');
40303
+ this.galleryEl.setAttribute('data-resin-component', 'gallery');
40264
40304
  this.containerEl.insertBefore(this.galleryEl, this.containerEl.querySelector('.bp-ControlsRoot'));
40265
40305
  this.galleryRoot = __WEBPACK_EXTERNAL_MODULE_react_dom_client_4cb20cd7_createRoot__(this.galleryEl);
40266
40306
  this.galleryFocusedPage = pdfViewer.currentPageNumber;
@@ -41302,11 +41342,16 @@ class ThumbnailsSidebar {
41302
41342
  this.virtualScroller.destroy();
41303
41343
  this.virtualScroller = null;
41304
41344
  }
41345
+ if (this.thumbnail) {
41346
+ this.thumbnail.destroy();
41347
+ this.thumbnail = null;
41348
+ }
41305
41349
  this.pdfViewer = null;
41306
41350
  this.currentThumbnails = [];
41307
41351
  this.currentPage = null;
41308
41352
  this.preloader = null;
41309
41353
  this.anchorEl.removeEventListener('click', this.thumbnailClickHandler);
41354
+ this.anchorEl.removeEventListener('keydown', this.onKeydown);
41310
41355
  }
41311
41356
 
41312
41357
  /**
@@ -41377,6 +41422,9 @@ class ThumbnailsSidebar {
41377
41422
  * @return {void}
41378
41423
  */
41379
41424
  renderNextThumbnailImage() {
41425
+ if (!this.thumbnail || !this.virtualScroller) {
41426
+ return;
41427
+ }
41380
41428
  const scrollerNotInited = this.virtualScroller && this.virtualScroller instanceof lib_VirtualScroller && typeof this.virtualScroller.totalItems === 'undefined';
41381
41429
  if (scrollerNotInited) {
41382
41430
  this.thumbnail.init().then(this.initVirtualScrollerIfReady);
@@ -41450,6 +41498,9 @@ class ThumbnailsSidebar {
41450
41498
  * @return {void}
41451
41499
  */
41452
41500
  requestThumbnailImage(itemIndex, thumbnailEl) {
41501
+ if (!this.thumbnail) {
41502
+ return;
41503
+ }
41453
41504
  const requestId = requestAnimationFrame(() => {
41454
41505
  this.animationFrameRequestIds = this.animationFrameRequestIds.filter(id => id !== requestId);
41455
41506
  this.thumbnail.createThumbnailImage(itemIndex).then(imageEl => {
@@ -41556,7 +41607,7 @@ class ThumbnailsSidebar {
41556
41607
  }
41557
41608
  refresh() {
41558
41609
  if (!this.virtualScroller) {
41559
- return;
41610
+ return Promise.resolve();
41560
41611
  }
41561
41612
  this.virtualScroller.destroy();
41562
41613
  this.virtualScroller = new lib_VirtualScroller(this.anchorEl);
@@ -41567,7 +41618,10 @@ class ThumbnailsSidebar {
41567
41618
  // Skip preloader path since preloader dimensions are unrotated
41568
41619
  const savedPreloader = this.thumbnail.preloader;
41569
41620
  this.thumbnail.preloader = null;
41570
- this.thumbnail.init().then(thumbnailHeight => {
41621
+ return this.thumbnail.init().then(thumbnailHeight => {
41622
+ if (!this.thumbnail || !this.virtualScroller) {
41623
+ return;
41624
+ }
41571
41625
  this.thumbnail.preloader = savedPreloader;
41572
41626
  if (thumbnailHeight) {
41573
41627
  const count = this.pdfViewer?.pagesCount || this.preloader?.numPages;
@@ -41816,7 +41870,8 @@ class DocBaseViewer extends viewers_BaseViewer {
41816
41870
  }
41817
41871
  },
41818
41872
  onBeforeOpen: () => this.handleGalleryEnter(),
41819
- onAfterClose: () => this.handleGalleryExit()
41873
+ onAfterClose: () => this.handleGalleryExit(),
41874
+ onClose: landedPage => this.handleGalleryClose(landedPage)
41820
41875
  });
41821
41876
  }
41822
41877
 
@@ -41847,6 +41902,13 @@ class DocBaseViewer extends viewers_BaseViewer {
41847
41902
  if (this.galleryController) {
41848
41903
  this.galleryController.destroy();
41849
41904
  }
41905
+ if (this.thumbnailsSidebar) {
41906
+ this.thumbnailsSidebar.destroy();
41907
+ }
41908
+ if (this.advancedInsightsThumbs) {
41909
+ this.advancedInsightsThumbs.destroy();
41910
+ this.advancedInsightsThumbs = null;
41911
+ }
41850
41912
 
41851
41913
  // Clean up PDF network requests
41852
41914
  if (this.pdfLoadingTask) {
@@ -41857,16 +41919,19 @@ class DocBaseViewer extends viewers_BaseViewer {
41857
41919
  }
41858
41920
  }
41859
41921
 
41860
- // Clean up viewer
41922
+ // Clean up and detach the PDF.js document so retained viewer instances
41923
+ // do not keep page views and document resources alive.
41861
41924
  if (this.pdfViewer) {
41862
41925
  this.pdfViewer.cleanup();
41926
+ this.pdfViewer.setDocument(null);
41863
41927
  }
41928
+ if (this.pdfLinkService) {
41929
+ this.pdfLinkService.setDocument(null);
41930
+ }
41931
+ this.doc = null;
41864
41932
  if (this.printPopup) {
41865
41933
  this.printPopup.destroy();
41866
41934
  }
41867
- if (this.thumbnailsSidebar) {
41868
- this.thumbnailsSidebar.destroy();
41869
- }
41870
41935
  if (this.thumbnailsSidebarEl) {
41871
41936
  // Since we are cleaning up make sure the thumbnails open class is
41872
41937
  // removed so that the content div shifts back left
@@ -42614,6 +42679,10 @@ class DocBaseViewer extends viewers_BaseViewer {
42614
42679
  this.pageTracker.addListener('page_tracker_report', this.handleAdvancedInsightsReport);
42615
42680
  }
42616
42681
  return this.pdfLoadingTask.promise.then(doc => {
42682
+ if (this.isDestroyed()) {
42683
+ return null;
42684
+ }
42685
+
42617
42686
  // Only check operations for .numbers and .xlsx files
42618
42687
  if (file.extension === 'numbers' || file.extension === 'xlsx') {
42619
42688
  return countPdfOperations(doc, MAX_OPERATION_PAGES).then(opCount => {
@@ -42625,6 +42694,9 @@ class DocBaseViewer extends viewers_BaseViewer {
42625
42694
  }
42626
42695
  return doc;
42627
42696
  }).then(doc => {
42697
+ if (this.isDestroyed()) {
42698
+ return;
42699
+ }
42628
42700
  this.pdfLinkService.setDocument(doc, pdfUrl);
42629
42701
  this.pdfViewer.setDocument(doc);
42630
42702
  if (this.shouldThumbnailsBeToggled()) {
@@ -42635,6 +42707,9 @@ class DocBaseViewer extends viewers_BaseViewer {
42635
42707
  // store a reference to the doc for docfirstpages
42636
42708
  this.doc = doc;
42637
42709
  }).catch(err => {
42710
+ if (this.isDestroyed()) {
42711
+ return;
42712
+ }
42638
42713
  console.error(err); // eslint-disable-line
42639
42714
 
42640
42715
  // pdf.js gives us the status code in their error message
@@ -43527,9 +43602,35 @@ class DocBaseViewer extends viewers_BaseViewer {
43527
43602
  if (this.annotator) {
43528
43603
  this.annotator.toggleAnnotationMode(AnnotationMode.NONE);
43529
43604
  }
43605
+ this.emitMetric({
43606
+ name: USER_DOCUMENT_GALLERY_EVENTS.OPEN,
43607
+ data: this.pdfViewer?.pagesCount ?? 0
43608
+ });
43530
43609
  this.emit(VIEWER_EVENT.galleryOpen);
43531
43610
  }
43532
43611
 
43612
+ /**
43613
+ * Called as the gallery closes, with the page the user landed on or null if they left without
43614
+ * settling on one. Reported as two distinct metrics so the pick-through rate is measurable.
43615
+ *
43616
+ * @protected
43617
+ * @param {number|null} landedPage - Page the gallery left the document on, or null if unchanged
43618
+ * @return {void}
43619
+ */
43620
+ handleGalleryClose(landedPage) {
43621
+ if (landedPage !== null) {
43622
+ this.emitMetric({
43623
+ name: USER_DOCUMENT_GALLERY_EVENTS.NAVIGATE,
43624
+ data: landedPage
43625
+ });
43626
+ } else {
43627
+ this.emitMetric({
43628
+ name: USER_DOCUMENT_GALLERY_EVENTS.DISMISS,
43629
+ data: this.pdfViewer?.pagesCount ?? 0
43630
+ });
43631
+ }
43632
+ }
43633
+
43533
43634
  /**
43534
43635
  * Called after the gallery closes. Restores REGION mode so the region-comment cursor is active.
43535
43636
  *
@@ -43789,9 +43890,12 @@ class DocBaseViewer extends viewers_BaseViewer {
43789
43890
  * Get a thumbnail image element
43790
43891
  *
43791
43892
  * @param {number} pageNumber - the page number
43792
- * @return {Promise} - promise resolves with the image HTMLElement or null if generation is in progress
43893
+ * @return {Promise} - promise resolves with the image HTMLElement or null if unavailable or in progress
43793
43894
  */
43794
43895
  getThumbnail(pageNumber) {
43896
+ if (this.isDestroyed()) {
43897
+ return Promise.resolve(null);
43898
+ }
43795
43899
  if (!this.advancedInsightsThumbs) {
43796
43900
  this.advancedInsightsThumbs = new lib_Thumbnail(this.pdfViewer);
43797
43901
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "box-content-preview",
3
- "version": "3.68.0",
3
+ "version": "3.70.0",
4
4
  "description": "Box Content Preview UI Element",
5
5
  "author": "Box (https://www.box.com/)",
6
6
  "license": "SEE LICENSE IN LICENSE",