box-content-preview 3.89.0 → 3.90.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.89.0-blue.svg?style=flat-square)](https://github.com/box/box-content-preview)
5
+ [![version](https://img.shields.io/badge/version-v3.90.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.89.0
25
+ - Version: v3.90.0
26
26
  - Locale: en-US
27
27
 
28
- https://cdn01.boxcdn.net/platform/preview/3.89.0/en-US/preview.js
29
- https://cdn01.boxcdn.net/platform/preview/3.89.0/en-US/preview.css
28
+ https://cdn01.boxcdn.net/platform/preview/3.90.0/en-US/preview.js
29
+ https://cdn01.boxcdn.net/platform/preview/3.90.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.89.0/en-US/preview.js"></script>
55
+ <script src="https://cdn01.boxcdn.net/platform/preview/3.90.0/en-US/preview.js"></script>
56
56
  <link
57
57
  rel="stylesheet"
58
- href="https://cdn01.boxcdn.net/platform/preview/3.89.0/en-US/preview.css"
58
+ href="https://cdn01.boxcdn.net/platform/preview/3.90.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.89.0`
79
+ - Check out a specific version with `git checkout v3.90.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
@@ -327,6 +327,7 @@ class PreviewError extends Error {
327
327
  /* harmony export */ Jm: () => (/* binding */ SELECTOR_BOX_PREVIEW_LOGO_CUSTOM),
328
328
  /* harmony export */ Kb: () => (/* binding */ CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER),
329
329
  /* harmony export */ Kh: () => (/* binding */ SELECTOR_NAVIGATION_RIGHT),
330
+ /* harmony export */ Ku: () => (/* binding */ AUDIO_PLAYER_V2),
330
331
  /* harmony export */ Lq: () => (/* binding */ PREVIEW_SCRIPT_NAME),
331
332
  /* harmony export */ Lz: () => (/* binding */ CLASS_BOX_PREVIEW_THUMBNAILS_CLOSE),
332
333
  /* harmony export */ M$: () => (/* binding */ CLASS_BOX_PREVIEW_PRELOAD_WRAPPER_DOCUMENT),
@@ -379,6 +380,7 @@ class PreviewError extends Error {
379
380
  /* harmony export */ jF: () => (/* binding */ CLASS_IS_VISIBLE),
380
381
  /* harmony export */ jP: () => (/* binding */ CLASS_PREVIEW_LOADED),
381
382
  /* harmony export */ jf: () => (/* binding */ CLASS_FULLSCREEN_UNSUPPORTED),
383
+ /* harmony export */ jr: () => (/* binding */ X_REP_HINT_WAVEFORM),
382
384
  /* harmony export */ lM: () => (/* binding */ CLASS_BOX_PREVIEW_MOBILE),
383
385
  /* harmony export */ lR: () => (/* binding */ SELECTOR_BOX_PREVIEW_HEADER_CONTAINER),
384
386
  /* harmony export */ lX: () => (/* binding */ CLASS_BOX_PREVIEW_PRELOAD_OVERLAY),
@@ -396,6 +398,8 @@ class PreviewError extends Error {
396
398
  /* harmony export */ rR: () => (/* binding */ CLASS_BOX_PREVIEW_THEME_DARK),
397
399
  /* harmony export */ rZ: () => (/* binding */ CLASS_BOX_PREVIEW_OVERLAY),
398
400
  /* harmony export */ rr: () => (/* binding */ CLASS_IS_BUFFERING),
401
+ /* harmony export */ u4: () => (/* binding */ WAVEFORM_REP_NAME),
402
+ /* harmony export */ uD: () => (/* binding */ STATUS_ERROR),
399
403
  /* harmony export */ uN: () => (/* binding */ MEDIA_PLAYBACK_SKIP_DURATION),
400
404
  /* harmony export */ vV: () => (/* binding */ CLASS_BOX_PREVIEW_PRELOAD_WRAPPER_PRESENTATION),
401
405
  /* harmony export */ v_: () => (/* binding */ SELECTOR_BOX_PREVIEW_BTN_DOWNLOAD),
@@ -415,7 +419,7 @@ class PreviewError extends Error {
415
419
  /* harmony export */ zb: () => (/* binding */ CLASS_DOC_FIRST_IMAGE),
416
420
  /* harmony export */ ze: () => (/* binding */ STATUS_PENDING)
417
421
  /* harmony export */ });
418
- /* unused harmony exports CLASS_ACTIVE, CLASS_BOX_PREVIEW, CLASS_BOX_PREVIEW_CONTAINER, CLASS_BOX_PREVIEW_HEADER_CONTAINER, CLASS_BOX_PREVIEW_ICON, CLASS_BOX_PREVIEW_LOGO_CUSTOM, CLASS_BOX_PREVIEW_LOGO_DEFAULT, CLASS_PREFETCHED_IMAGE, SELECTOR_BOX_PREVIEW_HEADER, SELECTOR_BOX_PREVIEW_NOTIFICATION, STATUS_ERROR */
422
+ /* unused harmony exports CLASS_ACTIVE, CLASS_BOX_PREVIEW, CLASS_BOX_PREVIEW_CONTAINER, CLASS_BOX_PREVIEW_HEADER_CONTAINER, CLASS_BOX_PREVIEW_ICON, CLASS_BOX_PREVIEW_LOGO_CUSTOM, CLASS_BOX_PREVIEW_LOGO_DEFAULT, CLASS_PREFETCHED_IMAGE, SELECTOR_BOX_PREVIEW_HEADER, SELECTOR_BOX_PREVIEW_NOTIFICATION */
419
423
  const CLASS_ACTIVE = 'bp-is-active';
420
424
  const CLASS_ANNOTATIONS_CREATE_DRAWING = 'bp-annotations-create--drawing';
421
425
  const CLASS_ANNOTATIONS_CREATE_HIGHLIGHT = 'bp-annotations-create--highlight';
@@ -502,6 +506,7 @@ const APP_HOST = 'https://app.box.com';
502
506
  const ORIGINAL_REP_NAME = 'ORIGINAL';
503
507
  const PRELOAD_REP_NAME = 'jpg';
504
508
  const PRELOAD_PAGED_REP_NAME = 'webp';
509
+ const WAVEFORM_REP_NAME = 'waveform';
505
510
  const VIDEO_VIEWER_NAMES = ['Dash', 'MP4'];
506
511
  const STATUS_ERROR = 'error';
507
512
  const STATUS_NONE = 'none';
@@ -516,7 +521,9 @@ const X_REP_HINT_IMAGE = '[jpg?dimensions=2048x2048,png?dimensions=2048x2048]';
516
521
  const X_REP_HINT_VIDEO_DASH = '[dash,mp4][filmstrip]';
517
522
  const X_REP_HINT_VIDEO_DASH_EXTRACTED_TEXT = '[extracted_text]';
518
523
  const X_REP_HINT_VIDEO_MP4 = '[mp4]';
524
+ const X_REP_HINT_WAVEFORM = '[waveform]';
519
525
  const AI_TRANSCRIPTION_FOR_VIDEO_SUBTITLES = 'aiTranscriptionForVideoSubtitles';
526
+ const AUDIO_PLAYER_V2 = 'audioPlayerV2.enabled';
520
527
  const PDFJS_CSS_UNITS = 96.0 / 72.0; // Should match CSS_UNITS in pdf_viewer.js
521
528
  const PDFJS_MAX_AUTO_SCALE = 1.25; // Should match MAX_AUTO_SCALE in pdf_viewer.js
522
529
  const PDFJS_WIDTH_PADDING_PX = 40; // Should match SCROLLBAR_PADDING in pdf_viewer.js
@@ -1010,7 +1017,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
1010
1017
  const CLIENT_NAME = "box-content-preview"; // eslint-disable-line no-undef
1011
1018
  const CLIENT_NAME_KEY = 'box_client_name';
1012
1019
  const CLIENT_VERSION_KEY = 'box_client_version';
1013
- const CLIENT_VERSION = "3.89.0"; // eslint-disable-line no-undef
1020
+ const CLIENT_VERSION = "3.90.0"; // eslint-disable-line no-undef
1014
1021
  const HEADER_CLIENT_NAME = 'X-Box-Client-Name';
1015
1022
  const HEADER_CLIENT_VERSION = 'X-Box-Client-Version';
1016
1023
  const PROMISE_MAP = {};
@@ -6375,14 +6382,16 @@ function MP3ControlsV2({
6375
6382
  volume
6376
6383
  }) {
6377
6384
  const durationValue = typeof durationTime === 'number' && isFinite_default()(durationTime) ? durationTime : 0;
6385
+ const mediaDuration = mediaEl ? mediaEl.duration : NaN;
6386
+ const hasMediaMetadata = typeof mediaDuration === 'number' && Number.isFinite(mediaDuration) && mediaDuration > 0;
6387
+ const hasWaveformDuration = durationValue > 0;
6378
6388
  const [zoomLevel, setZoomLevel] = (0,external_react_.useState)(constants/* WAVEFORM_ZOOM_MIN */.LW);
6379
6389
  const [maxZoom, setMaxZoom] = (0,external_react_.useState)(constants/* WAVEFORM_ZOOM_MIN */.LW);
6380
6390
  const [isZoomRevealed, setIsZoomRevealed] = (0,external_react_.useState)(false);
6381
6391
  const zoomRevealTimerRef = (0,external_react_.useRef)(0);
6382
6392
  const hasRealPeaks = !!(peaks && peaks.length);
6383
6393
  const waveformPeaks = hasRealPeaks ? peaks : PLACEHOLDER_PEAKS;
6384
- const hasMetadata = durationValue > 0;
6385
- const waveformDurationSec = hasMetadata ? durationValue : PLACEHOLDER_DURATION_SEC;
6394
+ const waveformDurationSec = hasWaveformDuration ? durationValue : PLACEHOLDER_DURATION_SEC;
6386
6395
  const [playRequested, setPlayRequested] = (0,external_react_.useState)(false);
6387
6396
  const [viewport, setViewport] = (0,external_react_.useState)(null);
6388
6397
  const handleViewportChange = (0,external_react_.useCallback)(next => {
@@ -6427,11 +6436,11 @@ function MP3ControlsV2({
6427
6436
  }
6428
6437
  onTimeChange(marker.time);
6429
6438
  }, [onCommentMarkerClick, onPlayPause, onTimeChange]);
6430
- const isWaveformInteractive = playRequested && hasMetadata;
6431
- const isWaitingToPlay = playRequested && !hasMetadata;
6439
+ const isWaveformInteractive = playRequested && hasMediaMetadata;
6440
+ const isWaitingToPlay = playRequested && !hasMediaMetadata;
6432
6441
  const showPlayOverlay = !playRequested && !isPlaying;
6433
6442
  const hasZoomHandlers = hasRealPeaks && !showPlayOverlay;
6434
- const hasZoomControl = hasZoomHandlers && hasMetadata && maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW;
6443
+ const hasZoomControl = hasZoomHandlers && hasMediaMetadata && maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW;
6435
6444
  return /*#__PURE__*/external_react_["default"].createElement("div", {
6436
6445
  className: "bp-MP3ControlsV2",
6437
6446
  "data-testid": "media-controls-wrapper-v2"
@@ -6452,7 +6461,7 @@ function MP3ControlsV2({
6452
6461
  zoomLevel: hasZoomHandlers ? zoomLevel : constants/* WAVEFORM_ZOOM_MIN */.LW
6453
6462
  }), /*#__PURE__*/external_react_["default"].createElement(WaveformCommentMarkers, {
6454
6463
  commentMarkers: waveformMarkers,
6455
- durationSec: hasMetadata ? durationValue : 0,
6464
+ durationSec: hasWaveformDuration ? durationValue : 0,
6456
6465
  onCommentMarkerClick: handleCommentMarkerClick,
6457
6466
  selectedId: selectedMarkerId,
6458
6467
  viewport: viewport
@@ -6479,7 +6488,7 @@ function MP3ControlsV2({
6479
6488
  }), isWaitingToPlay && /*#__PURE__*/external_react_["default"].createElement("div", {
6480
6489
  className: "bp-media-buffering-spinner",
6481
6490
  "data-testid": "bp-MP3ControlsV2-loading"
6482
- })), hasMetadata && /*#__PURE__*/external_react_["default"].createElement("div", {
6491
+ })), hasMediaMetadata && /*#__PURE__*/external_react_["default"].createElement("div", {
6483
6492
  className: "bp-MP3ControlsV2-bar",
6484
6493
  "data-testid": "bp-MP3ControlsV2-bar"
6485
6494
  }, /*#__PURE__*/external_react_["default"].createElement("div", {
@@ -6650,25 +6659,19 @@ const WAVEFORM_HEIGHT = 140;
6650
6659
 
6651
6660
  /***/ },
6652
6661
 
6653
- /***/ 546
6662
+ /***/ 4971
6654
6663
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
6655
6664
 
6656
6665
 
6657
6666
  // EXPORTS
6658
6667
  __webpack_require__.d(__webpack_exports__, {
6659
- decodeToPeaks: () => (/* binding */ decodeToPeaks),
6660
- extractPeaks: () => (/* binding */ extractPeaks),
6661
- getDecodeDecision: () => (/* binding */ getDecodeDecision),
6662
- loadPeaks: () => (/* binding */ loadPeaks),
6663
- runClientDecode: () => (/* binding */ runClientDecode)
6668
+ oz: () => (/* binding */ WaveformLoadError),
6669
+ iY: () => (/* binding */ createCappedWaveformState),
6670
+ nR: () => (/* binding */ createWaveformLoader),
6671
+ Vq: () => (/* binding */ errorFromUnknown),
6672
+ zf: () => (/* binding */ isAbortError)
6664
6673
  });
6665
- // ESM COMPAT FLAG
6666
- __webpack_require__.r(__webpack_exports__);
6667
6674
 
6668
- // EXTERNAL MODULE: ./src/lib/util.js + 1 modules
6669
- var util = __webpack_require__(4410);
6670
- // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/constants.ts
6671
- var constants = __webpack_require__(4929);
6672
6675
  ;// ./src/lib/viewers/media/waveform/types.ts
6673
6676
  /**
6674
6677
  * Box V1 is the in-viewer form: unsigned mono peaks in [0, 1] (peak envelope, mono_max).
@@ -6704,9 +6707,9 @@ function isWaveformErrorCode(value) {
6704
6707
  * Wavesurfer's two paints: left of the playhead (`progressColor`) and right of it (`waveColor`).
6705
6708
  * A string is a solid fill; a stop list is a left-to-right step gradient.
6706
6709
  */
6710
+ // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
6711
+ var validateWaveformPayload = __webpack_require__(1053);
6707
6712
  ;// ./src/lib/viewers/media/waveform/createWaveformLoader.ts
6708
- /* unused harmony import specifier */ var isRetryableWaveformError;
6709
- /* unused harmony import specifier */ var validateWaveformPayload;
6710
6713
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
6711
6714
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
6712
6715
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
@@ -6753,7 +6756,7 @@ function failedLoadState(error) {
6753
6756
  return {
6754
6757
  status: 'failed',
6755
6758
  error,
6756
- retryable: isRetryableWaveformError(error.code)
6759
+ retryable: (0,validateWaveformPayload/* isRetryableWaveformError */.Oe)(error.code)
6757
6760
  };
6758
6761
  }
6759
6762
  function readyLoadState(payload) {
@@ -6835,7 +6838,7 @@ function createWaveformLoader(fetchPayload, options = {}) {
6835
6838
  if (staleAfterFetch) {
6836
6839
  return staleAfterFetch;
6837
6840
  }
6838
- const validation = validateWaveformPayload(raw, options);
6841
+ const validation = (0,validateWaveformPayload/* validateWaveformPayload */.a9)(raw, options);
6839
6842
  const staleAfterValidate = cancelledIfStale(request);
6840
6843
  if (staleAfterValidate) {
6841
6844
  return staleAfterValidate;
@@ -6877,185 +6880,29 @@ function createCappedWaveformState(message) {
6877
6880
  }
6878
6881
  };
6879
6882
  }
6880
- ;// ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
6881
6883
 
6882
- const DEFAULT_PEAK_SCALE = 'unit';
6883
- const DEFAULT_CHANNEL_POLICY = 'mono_max';
6884
- const DEFAULT_ENVELOPE = 'peak';
6885
- function fail(code, message, retryable = false) {
6886
- return {
6887
- ok: false,
6888
- error: {
6889
- code,
6890
- message
6891
- },
6892
- retryable
6893
- };
6894
- }
6895
- function isPlainObject(value) {
6896
- return typeof value === 'object' && value !== null && !Array.isArray(value);
6897
- }
6898
- function payloadByteLength(raw) {
6899
- try {
6900
- const serialized = JSON.stringify(raw);
6901
- if (typeof Buffer !== 'undefined') {
6902
- return Buffer.byteLength(serialized, 'utf8');
6903
- }
6904
- if (typeof TextEncoder !== 'undefined') {
6905
- return new TextEncoder().encode(serialized).length;
6906
- }
6907
- return serialized.length;
6908
- } catch {
6909
- return Number.MAX_SAFE_INTEGER;
6910
- }
6911
- }
6912
- function readOptionalPolicy(raw, key, allowed) {
6913
- if (!(key in raw) || raw[key] === undefined) {
6914
- return undefined;
6915
- }
6916
- return raw[key] === allowed ? allowed : null;
6917
- }
6918
- function asWaveformPayloadV1(raw) {
6919
- const {
6920
- version,
6921
- durationSec,
6922
- peaks
6923
- } = raw;
6924
- if (version !== constants/* WAVEFORM_PAYLOAD_VERSION */.sh || typeof durationSec !== 'number' || !Array.isArray(peaks)) {
6925
- return null;
6926
- }
6927
- const peakScale = readOptionalPolicy(raw, 'peakScale', DEFAULT_PEAK_SCALE);
6928
- const channelPolicy = readOptionalPolicy(raw, 'channelPolicy', DEFAULT_CHANNEL_POLICY);
6929
- const envelope = readOptionalPolicy(raw, 'envelope', DEFAULT_ENVELOPE);
6930
- if (peakScale === null || channelPolicy === null || envelope === null) {
6931
- return null;
6932
- }
6933
- if ('channels' in raw && raw.channels !== undefined && raw.channels !== 1) {
6934
- return null;
6935
- }
6936
- return {
6937
- version: constants/* WAVEFORM_PAYLOAD_VERSION */.sh,
6938
- durationSec,
6939
- peaks: peaks,
6940
- peakScale: peakScale ?? DEFAULT_PEAK_SCALE,
6941
- channelPolicy: channelPolicy ?? DEFAULT_CHANNEL_POLICY,
6942
- envelope: envelope ?? DEFAULT_ENVELOPE,
6943
- channels: 1
6944
- };
6945
- }
6946
- function readPayloadObject(raw, maxPayloadBytes, isPayloadByteCheckSkipped = false) {
6947
- if (raw === null || raw === undefined) {
6948
- return fail('INVALID_PAYLOAD', 'Payload is null or undefined');
6949
- }
6950
- if (!isPayloadByteCheckSkipped) {
6951
- const byteLength = payloadByteLength(raw);
6952
- if (byteLength > maxPayloadBytes) {
6953
- return fail('PAYLOAD_TOO_LARGE', `Payload size ${byteLength} exceeds limit ${maxPayloadBytes}`);
6954
- }
6955
- }
6956
- if (!isPlainObject(raw)) {
6957
- return fail('INVALID_PAYLOAD', 'Payload must be an object');
6958
- }
6959
- return {
6960
- ok: true,
6961
- value: raw
6962
- };
6963
- }
6964
- function checkVersion(raw) {
6965
- if (raw.version === constants/* WAVEFORM_PAYLOAD_VERSION */.sh) {
6966
- return null;
6967
- }
6968
- const {
6969
- version
6970
- } = raw;
6971
- if (typeof version === 'number' && version > constants/* WAVEFORM_PAYLOAD_VERSION */.sh) {
6972
- return fail('UNSUPPORTED_VERSION', `Unsupported waveform version ${version}; max supported is ${constants/* WAVEFORM_PAYLOAD_VERSION */.sh}`);
6973
- }
6974
- return fail('INVALID_PAYLOAD', 'Missing or invalid version field');
6975
- }
6976
- function checkDuration(payload, expectedDurationSec) {
6977
- if (!Number.isFinite(payload.durationSec) || payload.durationSec <= 0) {
6978
- return fail('INVALID_DURATION', 'durationSec must be a positive finite number');
6979
- }
6980
- if (expectedDurationSec !== undefined && Number.isFinite(expectedDurationSec) && Math.abs(payload.durationSec - expectedDurationSec) > constants/* DURATION_MISMATCH_TOLERANCE_SEC */.GQ) {
6981
- return fail('DURATION_MISMATCH', `Payload duration ${payload.durationSec}s differs from media duration ${expectedDurationSec}s`, true);
6982
- }
6983
- return null;
6984
- }
6985
- function normalizePeaks(peaks, maxPeakCount) {
6986
- if (peaks.length === 0) {
6987
- return fail('EMPTY_PEAKS', 'peaks array must not be empty');
6988
- }
6989
- if (peaks.length > maxPeakCount) {
6990
- return fail('PEAK_COUNT_EXCEEDED', `peaks length ${peaks.length} exceeds max ${maxPeakCount}`);
6991
- }
6992
- const normalized = new Float32Array(peaks.length);
6993
- for (let i = 0; i < peaks.length; i += 1) {
6994
- const value = peaks[i];
6995
- if (!Number.isFinite(value)) {
6996
- return fail('NON_FINITE_PEAK', `Peak at index ${i} is not finite`);
6997
- }
6998
- if (value < constants/* PEAK_UNIT_MIN */.mJ || value > constants/* PEAK_UNIT_MAX */.i8) {
6999
- return fail('PEAK_OUT_OF_RANGE', `Peak at index ${i} is outside [${constants/* PEAK_UNIT_MIN */.mJ}, ${constants/* PEAK_UNIT_MAX */.i8}]`);
7000
- }
7001
- normalized[i] = value;
7002
- }
7003
- return {
7004
- ok: true,
7005
- peaks: normalized
7006
- };
7007
- }
6884
+ /***/ },
7008
6885
 
7009
- /**
7010
- * Validates a version-1 waveform payload and returns normalized peaks for rendering.
7011
- * Wire JSON requires version, durationSec, and peaks. sampleCount and source are ignored.
7012
- */
7013
- function validateWaveformPayload_validateWaveformPayload(raw, options = {}) {
7014
- const maxPeakCount = options.maxPeakCount ?? constants/* MAX_PEAK_COUNT */.FY;
7015
- const maxPayloadBytes = options.maxPayloadBytes ?? constants/* MAX_PAYLOAD_BYTES */.qY;
7016
- const objectResult = readPayloadObject(raw, maxPayloadBytes, options.isPayloadByteCheckSkipped === true);
7017
- if (!objectResult.ok) {
7018
- return objectResult;
7019
- }
7020
- const versionFailure = checkVersion(objectResult.value);
7021
- if (versionFailure) {
7022
- return versionFailure;
7023
- }
7024
- const payload = asWaveformPayloadV1(objectResult.value);
7025
- if (!payload) {
7026
- return fail('INVALID_PAYLOAD', 'Payload failed structural validation');
7027
- }
7028
- const durationFailure = checkDuration(payload, options.expectedDurationSec);
7029
- if (durationFailure) {
7030
- return durationFailure;
7031
- }
7032
- const peaksResult = normalizePeaks(payload.peaks, maxPeakCount);
7033
- if (!peaksResult.ok) {
7034
- return peaksResult;
7035
- }
7036
- return {
7037
- ok: true,
7038
- payload: {
7039
- version: constants/* WAVEFORM_PAYLOAD_VERSION */.sh,
7040
- durationSec: payload.durationSec,
7041
- peaks: peaksResult.peaks,
7042
- peakScale: payload.peakScale ?? DEFAULT_PEAK_SCALE,
7043
- channelPolicy: payload.channelPolicy ?? DEFAULT_CHANNEL_POLICY,
7044
- envelope: payload.envelope ?? DEFAULT_ENVELOPE
7045
- }
7046
- };
7047
- }
6886
+ /***/ 8296
6887
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
7048
6888
 
7049
- /** Maps validation / load failures to retry policy for loaders. */
7050
- function validateWaveformPayload_isRetryableWaveformError(code) {
7051
- return code === 'DURATION_MISMATCH' || code === 'DECODE_FAILED' || code === 'LOAD_FAILED';
7052
- }
7053
- ;// ./src/lib/viewers/media/waveform/decode.ts
6889
+ __webpack_require__.r(__webpack_exports__);
6890
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
6891
+ /* harmony export */ decodeToPeaks: () => (/* binding */ decodeToPeaks),
6892
+ /* harmony export */ extractPeaks: () => (/* binding */ extractPeaks),
6893
+ /* harmony export */ getDecodeDecision: () => (/* binding */ getDecodeDecision),
6894
+ /* harmony export */ loadPeaks: () => (/* binding */ loadPeaks),
6895
+ /* harmony export */ runClientDecode: () => (/* binding */ runClientDecode)
6896
+ /* harmony export */ });
6897
+ /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4410);
6898
+ /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4929);
6899
+ /* harmony import */ var _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4971);
6900
+ /* harmony import */ var _validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1053);
7054
6901
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7055
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { decode_defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7056
- function decode_defineProperty(e, r, t) { return (r = decode_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
7057
- function decode_toPropertyKey(t) { var i = decode_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
7058
- function decode_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6902
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6903
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
6904
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
6905
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
7059
6906
 
7060
6907
 
7061
6908
 
@@ -7067,9 +6914,6 @@ const EMPTY_TIMINGS = {
7067
6914
  function createAbortError() {
7068
6915
  return new DOMException('Aborted', 'AbortError');
7069
6916
  }
7070
- function isPositiveFinite(value) {
7071
- return typeof value === 'number' && Number.isFinite(value) && value > 0;
7072
- }
7073
6917
  function getAudioContextConstructor() {
7074
6918
  if (typeof window === 'undefined') {
7075
6919
  return undefined;
@@ -7102,7 +6946,7 @@ function createSkippedDecodeResult(reason) {
7102
6946
  reason
7103
6947
  };
7104
6948
  }
7105
- return _objectSpread(_objectSpread({}, createCappedWaveformState(getDecodeSkipMessage(reason))), {}, {
6949
+ return _objectSpread(_objectSpread({}, (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .createCappedWaveformState */ .iY)(getDecodeSkipMessage(reason))), {}, {
7106
6950
  isDecodeSkipped: true,
7107
6951
  timings: EMPTY_TIMINGS,
7108
6952
  reason
@@ -7126,11 +6970,11 @@ function decodeWithContext(context, buffer, signal) {
7126
6970
  }
7127
6971
  isSettled = true;
7128
6972
  signal?.removeEventListener('abort', onAbort);
7129
- if (isAbortError(error)) {
6973
+ if ((0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .isAbortError */ .zf)(error)) {
7130
6974
  reject(error instanceof DOMException ? error : createAbortError());
7131
6975
  return;
7132
6976
  }
7133
- reject(error instanceof WaveformLoadError ? error : new WaveformLoadError('DECODE_FAILED', 'decodeAudioData failed'));
6977
+ reject(error instanceof _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .WaveformLoadError */ .oz ? error : new _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .WaveformLoadError */ .oz('DECODE_FAILED', 'decodeAudioData failed'));
7134
6978
  };
7135
6979
  onAbort = () => onFailure(createAbortError());
7136
6980
  if (signal?.aborted) {
@@ -7156,13 +7000,13 @@ function decodeWithContext(context, buffer, signal) {
7156
7000
  * skips decode so playback is never blocked by expanding the full audio buffer.
7157
7001
  */
7158
7002
  function getDecodeDecision(media, caps = {}) {
7159
- const maxCompressedBytes = caps.maxCompressedBytes ?? constants/* CLIENT_DECODE_MAX_COMPRESSED_BYTES */.EB;
7160
- const maxDurationSec = caps.maxDurationSec ?? constants/* CLIENT_DECODE_MAX_DURATION_SEC */.nG;
7003
+ const maxCompressedBytes = caps.maxCompressedBytes ?? _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_MAX_COMPRESSED_BYTES */ .EB;
7004
+ const maxDurationSec = caps.maxDurationSec ?? _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_MAX_DURATION_SEC */ .nG;
7161
7005
  const {
7162
7006
  compressedBytes,
7163
7007
  durationSec
7164
7008
  } = media;
7165
- if (!isPositiveFinite(compressedBytes) || !isPositiveFinite(durationSec)) {
7009
+ if (!(0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isPositiveFinite */ .Ze)(compressedBytes) || !(0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isPositiveFinite */ .Ze)(durationSec)) {
7166
7010
  return {
7167
7011
  isAllowed: false,
7168
7012
  reason: 'missing_metadata'
@@ -7189,7 +7033,7 @@ function getDecodeDecision(media, caps = {}) {
7189
7033
  * Collapse audio channels to one unsigned peak per time bucket (max abs, then clamp to unit).
7190
7034
  * Accepts an AudioBuffer so callers can extract before closing the AudioContext.
7191
7035
  */
7192
- function extractPeaks(audio, peakCount = constants/* CLIENT_DECODE_PEAK_COUNT */.f3) {
7036
+ function extractPeaks(audio, peakCount = _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_PEAK_COUNT */ .f3) {
7193
7037
  const channels = Array.isArray(audio) ? audio : Array.from({
7194
7038
  length: audio.numberOfChannels
7195
7039
  }, (_, channelIndex) => audio.getChannelData(channelIndex));
@@ -7214,7 +7058,7 @@ function extractPeaks(audio, peakCount = constants/* CLIENT_DECODE_PEAK_COUNT */
7214
7058
  }
7215
7059
  }
7216
7060
  }
7217
- peaks[i] = Math.min(constants/* PEAK_UNIT_MAX */.i8, Math.max(constants/* PEAK_UNIT_MIN */.mJ, maxAbs));
7061
+ peaks[i] = Math.min(_constants__WEBPACK_IMPORTED_MODULE_1__/* .PEAK_UNIT_MAX */ .i8, Math.max(_constants__WEBPACK_IMPORTED_MODULE_1__/* .PEAK_UNIT_MIN */ .mJ, maxAbs));
7218
7062
  }
7219
7063
  return peaks;
7220
7064
  }
@@ -7223,13 +7067,13 @@ function extractPeaks(audio, peakCount = constants/* CLIENT_DECODE_PEAK_COUNT */
7223
7067
  * Decode compressed audio and extract unit peaks while the AudioBuffer is live.
7224
7068
  * Does not attach a media element or fetch a URL. Does not copy channel data.
7225
7069
  */
7226
- async function decodeToPeaks(arrayBuffer, signal, peakCount = constants/* CLIENT_DECODE_PEAK_COUNT */.f3) {
7070
+ async function decodeToPeaks(arrayBuffer, signal, peakCount = _constants__WEBPACK_IMPORTED_MODULE_1__/* .CLIENT_DECODE_PEAK_COUNT */ .f3) {
7227
7071
  if (signal?.aborted) {
7228
7072
  throw createAbortError();
7229
7073
  }
7230
7074
  const AudioContextConstructor = getAudioContextConstructor();
7231
7075
  if (!AudioContextConstructor) {
7232
- throw new WaveformLoadError('DECODE_FAILED', 'AudioContext is not available');
7076
+ throw new _createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .WaveformLoadError */ .oz('DECODE_FAILED', 'AudioContext is not available');
7233
7077
  }
7234
7078
  const context = new AudioContextConstructor();
7235
7079
  try {
@@ -7237,15 +7081,15 @@ async function decodeToPeaks(arrayBuffer, signal, peakCount = constants/* CLIENT
7237
7081
  if (signal?.aborted) {
7238
7082
  throw createAbortError();
7239
7083
  }
7240
- const extractStarted = (0,util/* getCurrentTimeMs */.RU)();
7084
+ const extractStarted = (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)();
7241
7085
  const peaks = extractPeaks(audioBuffer, peakCount);
7242
7086
  return {
7243
7087
  durationSec: audioBuffer.duration,
7244
7088
  peaks,
7245
- extractMs: (0,util/* getCurrentTimeMs */.RU)() - extractStarted
7089
+ extractMs: (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)() - extractStarted
7246
7090
  };
7247
7091
  } catch (error) {
7248
- if (signal?.aborted || isAbortError(error)) {
7092
+ if (signal?.aborted || (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .isAbortError */ .zf)(error)) {
7249
7093
  throw createAbortError();
7250
7094
  }
7251
7095
  throw error;
@@ -7278,31 +7122,31 @@ async function runClientDecode(options) {
7278
7122
  };
7279
7123
  }
7280
7124
  const signal = options.signal ?? new AbortController().signal;
7281
- const decodeStarted = (0,util/* getCurrentTimeMs */.RU)();
7125
+ const decodeStarted = (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)();
7282
7126
  let decodeOutput;
7283
7127
  try {
7284
7128
  decodeOutput = await options.decode(signal);
7285
7129
  } catch (error) {
7286
- if (signal.aborted || isAbortError(error)) {
7130
+ if (signal.aborted || (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .isAbortError */ .zf)(error)) {
7287
7131
  return {
7288
7132
  status: 'cancelled',
7289
7133
  isDecodeSkipped: false,
7290
7134
  timings: EMPTY_TIMINGS
7291
7135
  };
7292
7136
  }
7293
- const waveformError = errorFromUnknown(error, 'DECODE_FAILED');
7137
+ const waveformError = (0,_createWaveformLoader__WEBPACK_IMPORTED_MODULE_2__/* .errorFromUnknown */ .Vq)(error, 'DECODE_FAILED');
7294
7138
  return {
7295
7139
  status: 'failed',
7296
7140
  error: waveformError,
7297
- retryable: validateWaveformPayload_isRetryableWaveformError(waveformError.code),
7141
+ retryable: (0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isRetryableWaveformError */ .Oe)(waveformError.code),
7298
7142
  isDecodeSkipped: false,
7299
7143
  timings: {
7300
- attemptMs: (0,util/* getCurrentTimeMs */.RU)() - decodeStarted,
7144
+ attemptMs: (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)() - decodeStarted,
7301
7145
  extractMs: null
7302
7146
  }
7303
7147
  };
7304
7148
  }
7305
- const attemptMs = (0,util/* getCurrentTimeMs */.RU)() - decodeStarted;
7149
+ const attemptMs = (0,_util__WEBPACK_IMPORTED_MODULE_0__/* .getCurrentTimeMs */ .RU)() - decodeStarted;
7306
7150
  if (signal.aborted) {
7307
7151
  return {
7308
7152
  status: 'cancelled',
@@ -7313,8 +7157,8 @@ async function runClientDecode(options) {
7313
7157
  }
7314
7158
  };
7315
7159
  }
7316
- const validation = validateWaveformPayload_validateWaveformPayload({
7317
- version: constants/* WAVEFORM_PAYLOAD_VERSION */.sh,
7160
+ const validation = (0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .validateWaveformPayload */ .a9)({
7161
+ version: _constants__WEBPACK_IMPORTED_MODULE_1__/* .WAVEFORM_PAYLOAD_VERSION */ .sh,
7318
7162
  durationSec: options.durationSec ?? decodeOutput.durationSec,
7319
7163
  peaks: decodeOutput.peaks
7320
7164
  }, {
@@ -7324,7 +7168,7 @@ async function runClientDecode(options) {
7324
7168
  return {
7325
7169
  status: 'failed',
7326
7170
  error: validation.error,
7327
- retryable: validateWaveformPayload_isRetryableWaveformError(validation.error.code),
7171
+ retryable: (0,_validateWaveformPayload__WEBPACK_IMPORTED_MODULE_3__/* .isRetryableWaveformError */ .Oe)(validation.error.code),
7328
7172
  isDecodeSkipped: false,
7329
7173
  timings: {
7330
7174
  attemptMs,
@@ -7361,6 +7205,193 @@ function loadPeaks(request) {
7361
7205
 
7362
7206
  /***/ },
7363
7207
 
7208
+ /***/ 1053
7209
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
7210
+
7211
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
7212
+ /* harmony export */ Oe: () => (/* binding */ isRetryableWaveformError),
7213
+ /* harmony export */ Ze: () => (/* binding */ isPositiveFinite),
7214
+ /* harmony export */ a9: () => (/* binding */ validateWaveformPayload)
7215
+ /* harmony export */ });
7216
+ /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4929);
7217
+
7218
+ const DEFAULT_PEAK_SCALE = 'unit';
7219
+ const DEFAULT_CHANNEL_POLICY = 'mono_max';
7220
+ const DEFAULT_ENVELOPE = 'peak';
7221
+ function fail(code, message, retryable = false) {
7222
+ return {
7223
+ ok: false,
7224
+ error: {
7225
+ code,
7226
+ message
7227
+ },
7228
+ retryable
7229
+ };
7230
+ }
7231
+ function isPositiveFinite(value) {
7232
+ return typeof value === 'number' && Number.isFinite(value) && value > 0;
7233
+ }
7234
+ function isPlainObject(value) {
7235
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
7236
+ }
7237
+ function payloadByteLength(raw) {
7238
+ try {
7239
+ const serialized = JSON.stringify(raw);
7240
+ if (typeof Buffer !== 'undefined') {
7241
+ return Buffer.byteLength(serialized, 'utf8');
7242
+ }
7243
+ if (typeof TextEncoder !== 'undefined') {
7244
+ return new TextEncoder().encode(serialized).length;
7245
+ }
7246
+ return serialized.length;
7247
+ } catch {
7248
+ return Number.MAX_SAFE_INTEGER;
7249
+ }
7250
+ }
7251
+ function readOptionalPolicy(raw, key, allowed) {
7252
+ if (!(key in raw) || raw[key] === undefined) {
7253
+ return undefined;
7254
+ }
7255
+ return raw[key] === allowed ? allowed : null;
7256
+ }
7257
+ function asWaveformPayloadV1(raw) {
7258
+ const {
7259
+ version,
7260
+ durationSec,
7261
+ peaks
7262
+ } = raw;
7263
+ if (version !== _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh || typeof durationSec !== 'number' || !Array.isArray(peaks)) {
7264
+ return null;
7265
+ }
7266
+ const peakScale = readOptionalPolicy(raw, 'peakScale', DEFAULT_PEAK_SCALE);
7267
+ const channelPolicy = readOptionalPolicy(raw, 'channelPolicy', DEFAULT_CHANNEL_POLICY);
7268
+ const envelope = readOptionalPolicy(raw, 'envelope', DEFAULT_ENVELOPE);
7269
+ if (peakScale === null || channelPolicy === null || envelope === null) {
7270
+ return null;
7271
+ }
7272
+ if ('channels' in raw && raw.channels !== undefined && raw.channels !== 1) {
7273
+ return null;
7274
+ }
7275
+ return {
7276
+ version: _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh,
7277
+ durationSec,
7278
+ peaks: peaks,
7279
+ peakScale: peakScale ?? DEFAULT_PEAK_SCALE,
7280
+ channelPolicy: channelPolicy ?? DEFAULT_CHANNEL_POLICY,
7281
+ envelope: envelope ?? DEFAULT_ENVELOPE,
7282
+ channels: 1
7283
+ };
7284
+ }
7285
+ function readPayloadObject(raw, maxPayloadBytes, isPayloadByteCheckSkipped = false) {
7286
+ if (raw === null || raw === undefined) {
7287
+ return fail('INVALID_PAYLOAD', 'Payload is null or undefined');
7288
+ }
7289
+ if (!isPayloadByteCheckSkipped) {
7290
+ const byteLength = payloadByteLength(raw);
7291
+ if (byteLength > maxPayloadBytes) {
7292
+ return fail('PAYLOAD_TOO_LARGE', `Payload size ${byteLength} exceeds limit ${maxPayloadBytes}`);
7293
+ }
7294
+ }
7295
+ if (!isPlainObject(raw)) {
7296
+ return fail('INVALID_PAYLOAD', 'Payload must be an object');
7297
+ }
7298
+ return {
7299
+ ok: true,
7300
+ value: raw
7301
+ };
7302
+ }
7303
+ function checkVersion(raw) {
7304
+ if (raw.version === _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh) {
7305
+ return null;
7306
+ }
7307
+ const {
7308
+ version
7309
+ } = raw;
7310
+ if (typeof version === 'number' && version > _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh) {
7311
+ return fail('UNSUPPORTED_VERSION', `Unsupported waveform version ${version}; max supported is ${_constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh}`);
7312
+ }
7313
+ return fail('INVALID_PAYLOAD', 'Missing or invalid version field');
7314
+ }
7315
+ function checkDuration(payload, expectedDurationSec) {
7316
+ if (!isPositiveFinite(payload.durationSec)) {
7317
+ return fail('INVALID_DURATION', 'durationSec must be a positive finite number');
7318
+ }
7319
+ if (expectedDurationSec !== undefined && Number.isFinite(expectedDurationSec) && Math.abs(payload.durationSec - expectedDurationSec) > _constants__WEBPACK_IMPORTED_MODULE_0__/* .DURATION_MISMATCH_TOLERANCE_SEC */ .GQ) {
7320
+ return fail('DURATION_MISMATCH', `Payload duration ${payload.durationSec}s differs from media duration ${expectedDurationSec}s`, true);
7321
+ }
7322
+ return null;
7323
+ }
7324
+ function normalizePeaks(peaks, maxPeakCount) {
7325
+ if (peaks.length === 0) {
7326
+ return fail('EMPTY_PEAKS', 'peaks array must not be empty');
7327
+ }
7328
+ if (peaks.length > maxPeakCount) {
7329
+ return fail('PEAK_COUNT_EXCEEDED', `peaks length ${peaks.length} exceeds max ${maxPeakCount}`);
7330
+ }
7331
+ const normalized = new Float32Array(peaks.length);
7332
+ for (let i = 0; i < peaks.length; i += 1) {
7333
+ const value = peaks[i];
7334
+ if (!Number.isFinite(value)) {
7335
+ return fail('NON_FINITE_PEAK', `Peak at index ${i} is not finite`);
7336
+ }
7337
+ if (value < _constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MIN */ .mJ || value > _constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MAX */ .i8) {
7338
+ return fail('PEAK_OUT_OF_RANGE', `Peak at index ${i} is outside [${_constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MIN */ .mJ}, ${_constants__WEBPACK_IMPORTED_MODULE_0__/* .PEAK_UNIT_MAX */ .i8}]`);
7339
+ }
7340
+ normalized[i] = value;
7341
+ }
7342
+ return {
7343
+ ok: true,
7344
+ peaks: normalized
7345
+ };
7346
+ }
7347
+
7348
+ /**
7349
+ * Validates a version-1 waveform payload and returns normalized peaks for rendering.
7350
+ * Wire JSON requires version, durationSec, and peaks. sampleCount and source are ignored.
7351
+ */
7352
+ function validateWaveformPayload(raw, options = {}) {
7353
+ const maxPeakCount = options.maxPeakCount ?? _constants__WEBPACK_IMPORTED_MODULE_0__/* .MAX_PEAK_COUNT */ .FY;
7354
+ const maxPayloadBytes = options.maxPayloadBytes ?? _constants__WEBPACK_IMPORTED_MODULE_0__/* .MAX_PAYLOAD_BYTES */ .qY;
7355
+ const objectResult = readPayloadObject(raw, maxPayloadBytes, options.isPayloadByteCheckSkipped === true);
7356
+ if (!objectResult.ok) {
7357
+ return objectResult;
7358
+ }
7359
+ const versionFailure = checkVersion(objectResult.value);
7360
+ if (versionFailure) {
7361
+ return versionFailure;
7362
+ }
7363
+ const payload = asWaveformPayloadV1(objectResult.value);
7364
+ if (!payload) {
7365
+ return fail('INVALID_PAYLOAD', 'Payload failed structural validation');
7366
+ }
7367
+ const durationFailure = checkDuration(payload, options.expectedDurationSec);
7368
+ if (durationFailure) {
7369
+ return durationFailure;
7370
+ }
7371
+ const peaksResult = normalizePeaks(payload.peaks, maxPeakCount);
7372
+ if (!peaksResult.ok) {
7373
+ return peaksResult;
7374
+ }
7375
+ return {
7376
+ ok: true,
7377
+ payload: {
7378
+ version: _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_PAYLOAD_VERSION */ .sh,
7379
+ durationSec: payload.durationSec,
7380
+ peaks: peaksResult.peaks,
7381
+ peakScale: payload.peakScale ?? DEFAULT_PEAK_SCALE,
7382
+ channelPolicy: payload.channelPolicy ?? DEFAULT_CHANNEL_POLICY,
7383
+ envelope: payload.envelope ?? DEFAULT_ENVELOPE
7384
+ }
7385
+ };
7386
+ }
7387
+
7388
+ /** Maps validation / load failures to retry policy for loaders. */
7389
+ function isRetryableWaveformError(code) {
7390
+ return code === 'DURATION_MISMATCH' || code === 'DECODE_FAILED' || code === 'LOAD_FAILED';
7391
+ }
7392
+
7393
+ /***/ },
7394
+
7364
7395
  /***/ 2485
7365
7396
  (module, exports) {
7366
7397
 
@@ -23024,7 +23055,7 @@ class Browser {
23024
23055
  ;// ./src/lib/Logger.js
23025
23056
  /* eslint-disable no-undef */
23026
23057
  const CLIENT_NAME = "box-content-preview";
23027
- const CLIENT_VERSION = "3.89.0";
23058
+ const CLIENT_VERSION = "3.90.0";
23028
23059
  /* eslint-enable no-undef */
23029
23060
 
23030
23061
  class Logger {
@@ -35709,6 +35740,12 @@ class MP3ControlsRoot {
35709
35740
  this.root.render(controls);
35710
35741
  }
35711
35742
  }
35743
+ // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/constants.ts
35744
+ var waveform_constants = __webpack_require__(4929);
35745
+ // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/createWaveformLoader.ts + 1 modules
35746
+ var createWaveformLoader = __webpack_require__(4971);
35747
+ // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
35748
+ var validateWaveformPayload = __webpack_require__(1053);
35712
35749
  ;// ./src/lib/viewers/media/MP3.scss
35713
35750
  // extracted by mini-css-extract-plugin
35714
35751
 
@@ -35723,6 +35760,11 @@ function MP3Viewer_toPrimitive(t, r) { if ("object" != typeof t || !t) return t;
35723
35760
 
35724
35761
 
35725
35762
 
35763
+
35764
+
35765
+
35766
+
35767
+
35726
35768
  const CSS_CLASS_MP3 = 'bp-media-mp3';
35727
35769
  function createLoadFailedError(message) {
35728
35770
  const error = new Error(message);
@@ -35738,7 +35780,7 @@ class MP3Viewer extends media_MediaBaseViewer {
35738
35780
  MP3Viewer_defineProperty(this, "handlePlayRequest", () => {
35739
35781
  this.userRequestedPlay = true;
35740
35782
  this.togglePlay();
35741
- if (this.isWaveformDecodeRetryPending && !this.hasUsedWaveformDecodePlayRetry) {
35783
+ if (this.shouldRaceClientWaveformDecode() && this.isWaveformDecodeRetryPending && !this.hasUsedWaveformDecodePlayRetry) {
35742
35784
  this.hasUsedWaveformDecodePlayRetry = true;
35743
35785
  this.isWaveformDecodeRetryPending = false;
35744
35786
  this.startClientWaveformDecode();
@@ -35775,11 +35817,11 @@ class MP3Viewer extends media_MediaBaseViewer {
35775
35817
  });
35776
35818
  MP3Viewer_defineProperty(this, "handleCommentMarkerClick", marker => {
35777
35819
  this.hostSelectedMarkerId = marker.id;
35778
- this.pendingHostSelectedSeek = null;
35820
+ this.pendingHostSelectedSeek = marker;
35779
35821
  if (this.mediaEl) {
35780
35822
  this.mediaEl.pause();
35781
- this.mediaEl.currentTime = marker.time;
35782
35823
  }
35824
+ this.applyPendingHostSelectedSeek();
35783
35825
  // Overlay paints the ring from click optimism until the host re-emits selected.
35784
35826
  this.emit('comment_marker_select', {
35785
35827
  id: marker.id,
@@ -35811,11 +35853,16 @@ class MP3Viewer extends media_MediaBaseViewer {
35811
35853
  this.wrapperEl.classList.add(CSS_CLASS_MP3);
35812
35854
  this.isAudioPlayerV2 = this.getIsAudioPlayerV2();
35813
35855
  this.waveformPeaks = [];
35856
+ this.waveformPeaksSource = null;
35857
+ this.waveformDurationSec = 0;
35814
35858
  if (this.isAudioPlayerV2) {
35815
35859
  this.wrapperEl.classList.add('bp-media--v2');
35816
35860
  this.mediaContainerEl.classList.add('bp-media-container--v2');
35817
35861
  this.ensureV2Controls();
35818
35862
  this.importWaveformDecode();
35863
+ // Listen on the loading shell. The waveform is on
35864
+ // screen before the audio blob is playable; getViewer() is still null.
35865
+ this.bindCommentMarkersListener();
35819
35866
  }
35820
35867
 
35821
35868
  // Audio element
@@ -35823,6 +35870,13 @@ class MP3Viewer extends media_MediaBaseViewer {
35823
35870
  this.mediaEl.setAttribute('preload', 'auto');
35824
35871
  this.commentMarkers = [];
35825
35872
  }
35873
+ bindCommentMarkersListener() {
35874
+ if (!this.isAudioPlayerV2) {
35875
+ return;
35876
+ }
35877
+ this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
35878
+ this.addListener('comment_markers', this.handleCommentMarkersUpdated);
35879
+ }
35826
35880
 
35827
35881
  /**
35828
35882
  * Audio player v2 (waveform). Off unless the host enables `audioPlayerV2`
@@ -35831,7 +35885,7 @@ class MP3Viewer extends media_MediaBaseViewer {
35831
35885
  * @return {boolean} whether v2 treatment is on
35832
35886
  */
35833
35887
  getIsAudioPlayerV2() {
35834
- return this.featureEnabled('audioPlayerV2.enabled') && this.useReactControls();
35888
+ return this.featureEnabled(constants/* AUDIO_PLAYER_V2 */.Ku) && this.useReactControls();
35835
35889
  }
35836
35890
 
35837
35891
  /**
@@ -35863,6 +35917,7 @@ class MP3Viewer extends media_MediaBaseViewer {
35863
35917
  */
35864
35918
  fallbackToV1Controls() {
35865
35919
  this.isAudioPlayerV2 = false;
35920
+ this.abortWaveformLoads();
35866
35921
  if (this.wrapperEl) {
35867
35922
  this.wrapperEl.classList.remove('bp-media--v2');
35868
35923
  }
@@ -35883,7 +35938,7 @@ class MP3Viewer extends media_MediaBaseViewer {
35883
35938
  */
35884
35939
  async importWaveformDecode() {
35885
35940
  if (!this.waveformDecodeImport) {
35886
- this.waveformDecodeImport = Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 546));
35941
+ this.waveformDecodeImport = Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 8296));
35887
35942
  }
35888
35943
  try {
35889
35944
  return await this.waveformDecodeImport;
@@ -35898,7 +35953,7 @@ class MP3Viewer extends media_MediaBaseViewer {
35898
35953
  */
35899
35954
  destroy() {
35900
35955
  this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
35901
- this.abortClientWaveformDecode();
35956
+ this.abortWaveformLoads();
35902
35957
  super.destroy();
35903
35958
  }
35904
35959
 
@@ -35908,6 +35963,7 @@ class MP3Viewer extends media_MediaBaseViewer {
35908
35963
  load() {
35909
35964
  if (this.isAudioPlayerV2) {
35910
35965
  this.showAudioLoadingShell();
35966
+ this.startConversionWaveformLoad();
35911
35967
  }
35912
35968
  return super.load();
35913
35969
  }
@@ -35945,6 +36001,9 @@ class MP3Viewer extends media_MediaBaseViewer {
35945
36001
  * @inheritdoc
35946
36002
  */
35947
36003
  loadeddataHandler() {
36004
+ if (this.isAudioPlayerV2) {
36005
+ this.dropConversionPeaksOnDurationMismatch();
36006
+ }
35948
36007
  super.loadeddataHandler();
35949
36008
  if (!this.isAudioPlayerV2) {
35950
36009
  return;
@@ -35955,7 +36014,173 @@ class MP3Viewer extends media_MediaBaseViewer {
35955
36014
  if (this.userRequestedPlay) {
35956
36015
  this.play();
35957
36016
  }
35958
- this.startClientWaveformDecode();
36017
+ if (this.shouldRaceClientWaveformDecode()) {
36018
+ this.startClientWaveformDecode();
36019
+ }
36020
+ }
36021
+
36022
+ /**
36023
+ * Client decode races conversion until some source applies peaks. Size and
36024
+ * duration caps still apply. First source to apply peaks wins; later
36025
+ * results are ignored.
36026
+ *
36027
+ * @return {boolean}
36028
+ */
36029
+ shouldRaceClientWaveformDecode() {
36030
+ if (!this.isAudioPlayerV2 || this.destroyed || this.waveformPeaksSource) {
36031
+ return false;
36032
+ }
36033
+ const compressedBytes = this.options.file?.size;
36034
+ const durationSec = this.mediaEl?.duration;
36035
+ return (0,validateWaveformPayload/* isPositiveFinite */.Ze)(compressedBytes) && compressedBytes <= waveform_constants/* CLIENT_DECODE_MAX_COMPRESSED_BYTES */.EB && (0,validateWaveformPayload/* isPositiveFinite */.Ze)(durationSec) && durationSec <= waveform_constants/* CLIENT_DECODE_MAX_DURATION_SEC */.nG;
36036
+ }
36037
+
36038
+ /**
36039
+ * @param {number} durationSec
36040
+ * @return {boolean}
36041
+ */
36042
+ isConversionDurationMismatch(durationSec) {
36043
+ const mediaDuration = this.mediaEl?.duration;
36044
+ return (0,validateWaveformPayload/* isPositiveFinite */.Ze)(mediaDuration) && (0,validateWaveformPayload/* isPositiveFinite */.Ze)(durationSec) && Math.abs(durationSec - mediaDuration) > waveform_constants/* DURATION_MISMATCH_TOLERANCE_SEC */.GQ;
36045
+ }
36046
+
36047
+ /**
36048
+ * Conversion JSON fetched before metadata skipped duration matching. Drop
36049
+ * those peaks once media duration is known if they disagree.
36050
+ *
36051
+ * @return {void}
36052
+ */
36053
+ dropConversionPeaksOnDurationMismatch() {
36054
+ if (this.waveformPeaksSource !== 'conversion' || !this.isConversionDurationMismatch(this.waveformDurationSec)) {
36055
+ return;
36056
+ }
36057
+ this.waveformPeaks = [];
36058
+ this.waveformPeaksSource = null;
36059
+ this.waveformDurationSec = 0;
36060
+ this.renderUI();
36061
+ }
36062
+
36063
+ /**
36064
+ * Poll the conversion waveform representation and fetch its JSON.
36065
+ * Missing, failed, or unloadable conversion falls back to client decode
36066
+ * when the file is under size and duration caps.
36067
+ *
36068
+ * @return {Promise<void>}
36069
+ */
36070
+ async startConversionWaveformLoad() {
36071
+ if (!this.isAudioPlayerV2 || this.destroyed) {
36072
+ return;
36073
+ }
36074
+ const {
36075
+ file
36076
+ } = this.options;
36077
+ const waveform = file?.representations?.entries ? getRepresentation(file, constants/* WAVEFORM_REP_NAME */.u4) : null;
36078
+ const template = waveform?.content?.url_template;
36079
+ const conversionStatus = waveform?.status;
36080
+ const statusState = conversionStatus && typeof conversionStatus === 'object' ? conversionStatus.state : null;
36081
+ if (!waveform || !template || !statusState || statusState === constants/* STATUS_ERROR */.uD) {
36082
+ this.startClientWaveformDecode();
36083
+ return;
36084
+ }
36085
+ this.abortConversionWaveformLoad();
36086
+ this.waveformStatus = this.getRepStatus(waveform);
36087
+ this.waveformStatus.removeListener('conversionpending', this.resetLoadTimeout);
36088
+ const status = this.waveformStatus;
36089
+ try {
36090
+ await status.getPromise();
36091
+ if (this.destroyed || this.waveformStatus !== status || this.waveformPeaksSource) {
36092
+ return;
36093
+ }
36094
+ const result = await this.loadConversionWaveformPayload(template);
36095
+ this.handleConversionWaveformResult(result, status);
36096
+ } catch {
36097
+ this.startClientWaveformDecode();
36098
+ }
36099
+ }
36100
+
36101
+ /**
36102
+ * Fetch and validate conversion waveform JSON after the rep is ready.
36103
+ * `{+asset_path}` is empty. Auth is a header, not a query token.
36104
+ *
36105
+ * @param {string} template - content URL template
36106
+ * @return {Promise<import('./waveform/types').WaveformLoadState>}
36107
+ */
36108
+ loadConversionWaveformPayload(template) {
36109
+ const url = this.createContentUrlV2(template);
36110
+ const durationSec = this.mediaEl?.duration;
36111
+ const source = (0,createWaveformLoader/* createWaveformLoader */.nR)(signal => this.api.get(url, {
36112
+ headers: this.appendAuthHeader(),
36113
+ signal
36114
+ }), Number.isFinite(durationSec) ? {
36115
+ expectedDurationSec: durationSec
36116
+ } : {});
36117
+ this.waveformSource = source;
36118
+ return source.load();
36119
+ }
36120
+ abortWaveformLoads() {
36121
+ this.abortConversionWaveformLoad();
36122
+ this.abortClientWaveformDecode();
36123
+ }
36124
+ abortConversionWaveformLoad() {
36125
+ if (this.waveformSource) {
36126
+ this.waveformSource.abort();
36127
+ this.waveformSource = null;
36128
+ }
36129
+ if (this.waveformStatus) {
36130
+ this.waveformStatus.destroy();
36131
+ this.waveformStatus = null;
36132
+ }
36133
+ }
36134
+
36135
+ /**
36136
+ * First source to apply peaks wins. Later results are ignored.
36137
+ *
36138
+ * @param {'conversion'|'client'} source
36139
+ * @param {{ peaks: ArrayLike<number>, durationSec?: number }} payload
36140
+ * @return {boolean} true when this source claimed peaks
36141
+ */
36142
+ applyWaveformPeaks(source, payload) {
36143
+ if (this.waveformPeaksSource) {
36144
+ return false;
36145
+ }
36146
+ this.waveformPeaks = payload.peaks;
36147
+ this.waveformPeaksSource = source;
36148
+ this.isWaveformDecodeRetryPending = false;
36149
+ if (source === 'conversion') {
36150
+ this.waveformDurationSec = payload.durationSec;
36151
+ this.abortClientWaveformDecode();
36152
+ } else if (this.waveformSource) {
36153
+ // RepStatus.destroy() does not reject getPromise().
36154
+ this.waveformSource.abort();
36155
+ this.waveformSource = null;
36156
+ }
36157
+ this.renderUI();
36158
+ return true;
36159
+ }
36160
+
36161
+ /**
36162
+ * Apply conversion peaks when the load is still current. Ignored if client
36163
+ * decode already applied peaks.
36164
+ *
36165
+ * @param {import('./waveform/types').WaveformLoadState} result
36166
+ * @param {Object} status - RepStatus instance that started this load
36167
+ * @return {void}
36168
+ */
36169
+ handleConversionWaveformResult(result, status) {
36170
+ if (!result || this.destroyed || !this.isAudioPlayerV2 || this.waveformStatus !== status) {
36171
+ return;
36172
+ }
36173
+ if (result.status !== 'ready') {
36174
+ if (result.status !== 'cancelled') {
36175
+ this.startClientWaveformDecode();
36176
+ }
36177
+ return;
36178
+ }
36179
+ if (this.isConversionDurationMismatch(result.payload.durationSec)) {
36180
+ this.startClientWaveformDecode();
36181
+ return;
36182
+ }
36183
+ this.applyWaveformPeaks('conversion', result.payload);
35959
36184
  }
35960
36185
  /**
35961
36186
  * Fetch compressed audio bytes for client decode. Prefers an already-fetched blob URL.
@@ -35996,16 +36221,19 @@ class MP3Viewer extends media_MediaBaseViewer {
35996
36221
  }
35997
36222
 
35998
36223
  /**
35999
- * Decode peaks in the background when the file is under size and duration caps.
36000
- * Does not block playback. Capped or failed decode keeps the placeholder waveform.
36224
+ * Decode peaks in the background until conversion or client decode applies
36225
+ * them, when the file is under size and duration caps. Does not block
36226
+ * playback. First source to apply peaks wins.
36001
36227
  *
36002
36228
  * @return {Promise<void>}
36003
36229
  */
36004
36230
  async startClientWaveformDecode() {
36005
- if (!this.isAudioPlayerV2 || this.destroyed) {
36231
+ if (!this.shouldRaceClientWaveformDecode()) {
36232
+ return;
36233
+ }
36234
+ if (this.waveformDecodeController && !this.waveformDecodeController.signal.aborted) {
36006
36235
  return;
36007
36236
  }
36008
- this.abortClientWaveformDecode();
36009
36237
  const controller = new AbortController();
36010
36238
  this.waveformDecodeController = controller;
36011
36239
  const {
@@ -36054,9 +36282,7 @@ class MP3Viewer extends media_MediaBaseViewer {
36054
36282
  return;
36055
36283
  }
36056
36284
  if (result.status === 'ready') {
36057
- this.waveformPeaks = result.payload.peaks;
36058
- this.isWaveformDecodeRetryPending = false;
36059
- this.renderUI();
36285
+ this.applyWaveformPeaks('client', result.payload);
36060
36286
  return;
36061
36287
  }
36062
36288
  if (result.status === 'cancelled') {
@@ -36086,10 +36312,7 @@ class MP3Viewer extends media_MediaBaseViewer {
36086
36312
  containerEl: this.mediaContainerEl
36087
36313
  });
36088
36314
  }
36089
- if (this.isAudioPlayerV2) {
36090
- this.removeListener('comment_markers', this.handleCommentMarkersUpdated);
36091
- this.addListener('comment_markers', this.handleCommentMarkersUpdated);
36092
- }
36315
+ this.bindCommentMarkersListener();
36093
36316
  this.renderUI();
36094
36317
  }
36095
36318
  /**
@@ -36117,11 +36340,13 @@ class MP3Viewer extends media_MediaBaseViewer {
36117
36340
  if (!this.controls) {
36118
36341
  return;
36119
36342
  }
36343
+ const mediaDuration = this.mediaEl.duration;
36344
+ const durationTime = typeof mediaDuration === 'number' && mediaDuration > 0 ? mediaDuration : this.waveformDurationSec;
36120
36345
  const sharedProps = {
36121
36346
  autoplay: this.isAutoplayEnabled(),
36122
36347
  bufferedRange: this.mediaEl.buffered,
36123
36348
  currentTime: this.mediaEl.currentTime,
36124
- durationTime: this.mediaEl.duration,
36349
+ durationTime,
36125
36350
  isPlaying: !this.mediaEl.paused,
36126
36351
  movePlayback: this.movePlayback,
36127
36352
  onAutoplayChange: this.setAutoplay,
@@ -54353,8 +54578,12 @@ class Preview extends (events_default()) {
54353
54578
  if (isDash && isFeatureEnabled(this.options.features, constants/* AI_TRANSCRIPTION_FOR_VIDEO_SUBTITLES */.Iu)) {
54354
54579
  videoHint += constants/* X_REP_HINT_VIDEO_DASH_EXTRACTED_TEXT */.xU;
54355
54580
  }
54581
+ let hints = `${constants/* X_REP_HINT_BASE */.pl}${constants/* X_REP_HINT_DOC_THUMBNAIL */.nC}${constants/* X_REP_HINT_IMAGE */.h3}${videoHint}`;
54582
+ if (isFeatureEnabled(this.options.features, constants/* AUDIO_PLAYER_V2 */.Ku)) {
54583
+ hints += constants/* X_REP_HINT_WAVEFORM */.jr;
54584
+ }
54356
54585
  const headers = {
54357
- 'X-Rep-Hints': `${constants/* X_REP_HINT_BASE */.pl}${constants/* X_REP_HINT_DOC_THUMBNAIL */.nC}${constants/* X_REP_HINT_IMAGE */.h3}${videoHint}`
54586
+ 'X-Rep-Hints': hints
54358
54587
  };
54359
54588
  return (0,util/* getHeaders */.dJ)(headers, token || this.options.token, this.options.sharedLink, this.options.sharedLinkPassword);
54360
54589
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "box-content-preview",
3
- "version": "3.89.0",
3
+ "version": "3.90.0",
4
4
  "description": "Box Content Preview UI Element",
5
5
  "author": "Box (https://www.box.com/)",
6
6
  "license": "SEE LICENSE IN LICENSE",