box-content-preview 3.96.0 → 3.98.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.96.0-blue.svg?style=flat-square)](https://github.com/box/box-content-preview)
5
+ [![version](https://img.shields.io/badge/version-v3.98.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.96.0
25
+ - Version: v3.98.0
26
26
  - Locale: en-US
27
27
 
28
- https://cdn01.boxcdn.net/platform/preview/3.96.0/en-US/preview.js
29
- https://cdn01.boxcdn.net/platform/preview/3.96.0/en-US/preview.css
28
+ https://cdn01.boxcdn.net/platform/preview/3.98.0/en-US/preview.js
29
+ https://cdn01.boxcdn.net/platform/preview/3.98.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.96.0/en-US/preview.js"></script>
55
+ <script src="https://cdn01.boxcdn.net/platform/preview/3.98.0/en-US/preview.js"></script>
56
56
  <link
57
57
  rel="stylesheet"
58
- href="https://cdn01.boxcdn.net/platform/preview/3.96.0/en-US/preview.css"
58
+ href="https://cdn01.boxcdn.net/platform/preview/3.98.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.96.0`
79
+ - Check out a specific version with `git checkout v3.98.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`
@@ -61,11 +61,12 @@
61
61
  .bp-MarkerAvatarStack{position:absolute;bottom:calc(100% + 4px);left:50%;display:flex;align-items:center;transform:translateX(-50%)}.bp-MarkerAvatarStack-item{position:relative;flex-shrink:0;box-sizing:content-box;width:20px;height:20px;padding:0;background:none;border:0;border-radius:50%;outline:none;overflow:visible;cursor:pointer;appearance:none;transition:margin 150ms}.bp-MarkerAvatarStack-item:focus,.bp-MarkerAvatarStack-item:focus-visible{outline:none}.bp-MarkerAvatarStack-item:not(:first-child){margin-left:var(--bp-marker-stack-overlap, -10px)}.bp-MarkerAvatarStack-item .bp-MarkerAvatar{position:absolute;top:50%;bottom:auto;left:50%;display:block;transform:translate(-50%, -50%);transform-origin:center center}.bp-MarkerAvatarStack-item:hover,.bp-MarkerAvatarStack-item:focus-visible{z-index:3}:is(.bp-WaveformCommentMarkers-marker--group,.bp-TimeControlsV2-marker--group,.bp-MarkerCluster):is(:hover,:has(.bp-MarkerAvatarStack-item:focus-visible)) .bp-MarkerAvatarStack-item:not(:first-child){margin-left:2px}.bp-MarkerAvatarStack-overflow{cursor:pointer}.bp-MarkerAvatarStack-overflowBadge{background-color:#383838;color:#fff}.bp-MarkerAvatarStack-overflowBadge .bp-MarkerAvatar-initial{color:#fff}
62
62
  .bp-WaveformCommentMarkers{position:absolute;top:-2px;right:0;left:0;z-index:4;box-sizing:border-box;height:24px;padding:0 60px;overflow:visible;pointer-events:auto}.bp-WaveformCommentMarkers--zoomed,.bp-WaveformCommentMarkers--tape{padding:0;overflow:clip visible}.bp-WaveformCommentMarkers--tape{top:auto;bottom:100%;margin-bottom:12px}.bp-WaveformCommentMarkers-track{position:relative;width:100%;height:100%;overflow:visible}.bp-WaveformCommentMarkers--zoomed .bp-WaveformCommentMarkers-track,.bp-WaveformCommentMarkers--tape .bp-WaveformCommentMarkers-track{overflow:clip visible}.bp-WaveformCommentMarkers-marker{position:absolute;top:50%;z-index:1;display:flex;align-items:center;justify-content:center;width:auto;height:auto;padding:0;background:none;border:0;border-radius:50%;transform:translate(-50%, -50%);cursor:pointer;appearance:none;pointer-events:auto;overflow:visible;outline:none;transition:box-shadow 150ms}.bp-WaveformCommentMarkers-marker:focus,.bp-WaveformCommentMarkers-marker:focus-visible{outline:none}.bp-WaveformCommentMarkers-marker .bp-MarkerAvatar{overflow:visible;isolation:isolate;cursor:pointer}.bp-WaveformCommentMarkers-marker .bp-MarkerAvatar img{cursor:pointer}.bp-WaveformCommentMarkers-marker .bp-MarkerAvatar::after{position:absolute;z-index:1;inset:0;background:#000;border-radius:50%;opacity:.4;pointer-events:none;content:"";transition:opacity 150ms}.bp-WaveformCommentMarkers-marker>.bp-MarkerAvatar{position:relative;bottom:auto;left:auto;transform:none;transform-origin:center center}.bp-WaveformCommentMarkers-marker .bp-MarkerAvatar:not(.bp-MarkerAvatarStack-overflowBadge),.bp-WaveformCommentMarkers-marker .bp-MarkerAvatarStack .bp-MarkerAvatar:not(.bp-MarkerAvatarStack-overflowBadge){background-color:#000}.bp-WaveformCommentMarkers-marker .bp-MarkerAvatarStack{position:relative;bottom:auto;left:auto;transform:none}.bp-WaveformCommentMarkers-marker--group{width:auto}.bp-WaveformView:hover~.bp-WaveformCommentMarkers .bp-MarkerAvatar::after,.bp-WaveformCommentMarkers:hover .bp-MarkerAvatar::after,.bp-WaveformCommentMarkers:has(:focus-visible) .bp-MarkerAvatar::after,.bp-WaveformCommentMarkers-marker:not(.bp-WaveformCommentMarkers-marker--group).bp-WaveformCommentMarkers-marker--selected .bp-MarkerAvatar::after,.bp-WaveformCommentMarkers .bp-MarkerAvatarStack-item--selected .bp-MarkerAvatar::after{opacity:0}.bp-WaveformCommentMarkers-marker--selected{z-index:3}.bp-WaveformCommentMarkers-marker:hover,.bp-WaveformCommentMarkers-marker:focus-within{z-index:4}.bp-WaveformCommentMarkers .bp-MarkerAvatarStack-item{cursor:pointer;transition:margin 150ms}.bp-WaveformCommentMarkers .bp-MarkerAvatarStack-item:hover,.bp-WaveformCommentMarkers .bp-MarkerAvatarStack-item:focus-visible{z-index:3}@media(prefers-reduced-motion: reduce){.bp-WaveformCommentMarkers-marker,.bp-WaveformCommentMarkers .bp-MarkerAvatarStack-item,.bp-WaveformCommentMarkers-marker .bp-MarkerAvatar::after{transition:none}}
63
63
  .bp-WaveformGeneratingIndicator{display:flex;gap:4px;align-items:center;height:48px;padding:8px 16px 8px 12px;pointer-events:none}.bp-WaveformGeneratingIndicator-bars{display:flex;flex:0 0 24px;align-items:center;justify-content:center;width:24px;height:24px}.bp-WaveformGeneratingIndicator-bar{width:2px;height:10px;background:rgba(255,255,255,.3);border-radius:6px;animation:bp-WaveformGeneratingIndicator-pulse .66s ease-in-out infinite}.bp-WaveformGeneratingIndicator-bar:nth-child(2){margin-left:2px;animation-delay:.1s}.bp-WaveformGeneratingIndicator-bar:last-child{margin-left:2px;animation-delay:.2s}.bp-WaveformGeneratingIndicator-label{color:#fff;font-weight:normal;font-size:14px;line-height:22px;white-space:nowrap}@keyframes bp-WaveformGeneratingIndicator-pulse{0%,80%,100%{background:rgba(255,255,255,.3);transform:scaleY(1.2)}40%{background:#fff;transform:scaleY(1.6)}}@media(prefers-reduced-motion: reduce){.bp-WaveformGeneratingIndicator-bar{animation:none;background:#fff;transform:none}}
64
- .bp-WaveformRange{position:absolute;inset:0;z-index:2;pointer-events:none}.bp-WaveformRange-region{position:absolute;top:50%;box-sizing:border-box;height:150px;pointer-events:none;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.4);border-radius:10px;box-shadow:0 0 0 1px #222;transform:translateY(-50%);transition:border-width 100ms ease,border-color 100ms ease}.bp-WaveformRange--highlight .bp-WaveformRange-region,.bp-WaveformRange:has(.bp-WaveformRange-handle:hover) .bp-WaveformRange-region,.bp-WaveformRange:has(.bp-WaveformRange-handle--dragging) .bp-WaveformRange-region{border-width:2px;border-color:#fff}.bp-WaveformRange-handle{position:absolute;top:50%;z-index:1;width:24px;height:150px;pointer-events:auto;cursor:ew-resize;touch-action:none;transform:translate(-50%, -50%)}.bp-WaveformRange-handle--end{z-index:2}.bp-WaveformRange-handleGrip{position:absolute;top:50%;left:50%;width:8px;height:20px;background:#fff;border:1px solid #222;border-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.4);opacity:0;pointer-events:none;transform:translate(-50%, -50%) scale(0.5);transition:opacity 100ms ease-in,transform 100ms ease-in}.bp-WaveformRange-handle:hover .bp-WaveformRange-handleGrip,.bp-WaveformRange-handle:focus-visible .bp-WaveformRange-handleGrip,.bp-WaveformRange-handle--dragging .bp-WaveformRange-handleGrip{opacity:1;transform:translate(-50%, -50%) scale(1);transition:opacity 150ms ease-out,transform 150ms ease-out}.bp-WaveformRange-comment{position:absolute;top:calc(50% - 75px);z-index:5;display:inline-flex;gap:8px;align-items:center;justify-content:center;box-sizing:border-box;height:48px;padding:8px 14px;color:rgba(255,255,255,.8);font-weight:normal;font-size:14px;font-family:Lato,Arial,sans-serif;line-height:22px;letter-spacing:.1px;white-space:nowrap;background:rgba(0,0,0,.8);border:0;backdrop-filter:blur(12px);border-radius:46px;box-shadow:0 2px 4px 0 rgba(0,0,0,.12);transform:translate(-50%, calc(-100% - 36px));cursor:pointer;appearance:none;pointer-events:auto}.bp-WaveformRange-commentIcon{display:block;flex:0 0 auto;width:20px;height:20px}.bp-WaveformView--tape .bp-WaveformRange-comment{top:calc(50% - (100% + 10px) / 2)}.bp-WaveformRange-tooltip{position:absolute;top:100%;z-index:3;margin-top:4px;pointer-events:none;transform:translateX(-50%)}.bp-WaveformRange-tooltipTime{padding:4px 10px;color:#fff;font-weight:normal;font-size:14px;font-family:Lato,Arial,sans-serif;line-height:20px;letter-spacing:.3px;white-space:nowrap;background:rgba(34,34,34,.92);border:1px solid rgba(255,255,255,.18);border-radius:8px}@media(prefers-reduced-motion: reduce){.bp-WaveformRange-region,.bp-WaveformRange-handleGrip{transition:none}}
64
+ .bp-WaveformShuttle{position:absolute;top:48px;left:50%;z-index:6;display:flex;gap:4px;align-items:center;height:48px;padding:8px 16px;color:#fff;background:rgba(255,255,255,.1);border-radius:24px;box-shadow:0 2px 12px rgba(0,0,0,.08);transform:translateX(-50%);backdrop-filter:blur(60px);pointer-events:none;-webkit-user-select:none;user-select:none}.bp-WaveformShuttle-glyph{display:block;flex:0 0 auto;width:19px;height:11px}.bp-WaveformShuttle.bp-is-reverse .bp-WaveformShuttle-glyph{transform:scaleX(-1)}.bp-WaveformShuttle-rate{font-weight:500;font-size:14px;line-height:22px;white-space:nowrap}
65
+ .bp-WaveformRange{position:absolute;inset:0;z-index:2;pointer-events:none}.bp-WaveformRange-region{position:absolute;top:50%;box-sizing:border-box;height:150px;pointer-events:none;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.4);border-radius:10px;box-shadow:0 0 0 1px #222;transform:translateY(-50%);transition:border-width 100ms ease,border-color 100ms ease}.bp-WaveformRange--swiping .bp-WaveformRange-region{visibility:hidden}.bp-WaveformRange--highlight .bp-WaveformRange-region,.bp-WaveformRange:has(.bp-WaveformRange-handle:hover) .bp-WaveformRange-region,.bp-WaveformRange:has(.bp-WaveformRange-handle--dragging) .bp-WaveformRange-region{border-width:2px;border-color:#fff}.bp-WaveformRange-handle{position:absolute;top:50%;z-index:1;width:24px;height:150px;pointer-events:auto;cursor:ew-resize;touch-action:none;transform:translate(-50%, -50%)}.bp-WaveformRange-handle--end{z-index:2}.bp-WaveformRange-handleGrip{position:absolute;top:50%;left:50%;width:8px;height:20px;background:#fff;border:1px solid #222;border-radius:4px;box-shadow:0 1px 4px rgba(0,0,0,.4);opacity:0;pointer-events:none;transform:translate(-50%, -50%) scale(0.5);transition:opacity 100ms ease-in,transform 100ms ease-in}.bp-WaveformRange-handle:hover .bp-WaveformRange-handleGrip,.bp-WaveformRange-handle:focus-visible .bp-WaveformRange-handleGrip,.bp-WaveformRange-handle--dragging .bp-WaveformRange-handleGrip{opacity:1;transform:translate(-50%, -50%) scale(1);transition:opacity 150ms ease-out,transform 150ms ease-out}.bp-WaveformRange-comment{position:absolute;top:calc(50% - 75px);z-index:5;display:inline-flex;gap:8px;align-items:center;justify-content:center;box-sizing:border-box;height:48px;padding:8px 14px;color:rgba(255,255,255,.8);font-weight:normal;font-size:14px;font-family:Lato,Arial,sans-serif;line-height:22px;letter-spacing:.1px;white-space:nowrap;background:rgba(0,0,0,.8);border:0;backdrop-filter:blur(12px);border-radius:46px;box-shadow:0 2px 4px 0 rgba(0,0,0,.12);transform:translate(-50%, calc(-100% - 36px));cursor:pointer;appearance:none;pointer-events:auto}.bp-WaveformRange-commentIcon{display:block;flex:0 0 auto;width:20px;height:20px}.bp-WaveformView--tape .bp-WaveformRange-comment{top:calc(50% - (100% + 10px) / 2)}.bp-WaveformRange-tooltip{position:absolute;top:100%;z-index:3;margin-top:4px;pointer-events:none;transform:translateX(-50%)}.bp-WaveformRange-tooltipTime{padding:4px 10px;color:#fff;font-weight:normal;font-size:14px;font-family:Lato,Arial,sans-serif;line-height:20px;letter-spacing:.3px;white-space:nowrap;background:rgba(34,34,34,.92);border:1px solid rgba(255,255,255,.18);border-radius:8px}@media(prefers-reduced-motion: reduce){.bp-WaveformRange-region,.bp-WaveformRange-handleGrip{transition:none}}
65
66
  .bp-WaveformView{box-sizing:border-box;width:100%;height:206px;min-height:206px;padding:0 60px;overflow:visible;background:none;-webkit-tap-highlight-color:transparent}.bp-WaveformView.bp-WaveformView--zoomed,.bp-WaveformView.bp-WaveformView--tape{padding:0;touch-action:none}.bp-WaveformView.bp-WaveformView--zoomed .bp-WaveformView-canvas,.bp-WaveformView.bp-WaveformView--tape .bp-WaveformView-canvas{overflow:hidden;mask-image:linear-gradient(to right, transparent, #000 92px, #000 calc(100% - 92px), transparent)}.bp-WaveformView.bp-WaveformView--zoomed .bp-WaveformView-canvas>*::part(scroll),.bp-WaveformView.bp-WaveformView--tape .bp-WaveformView-canvas>*::part(scroll){overscroll-behavior-x:none}.bp-WaveformView.bp-WaveformView--tape{flex:1 1 auto;height:100%;min-height:0}.bp-WaveformView.bp-WaveformView--tape .bp-WaveformView-canvas{height:100%}.bp-WaveformView.bp-WaveformView--tape .bp-WaveformView-canvas>*::part(scroll){scrollbar-width:none}.bp-WaveformView.bp-WaveformView--tape .bp-WaveformView-playhead,.bp-WaveformView.bp-WaveformView--tape .bp-WaveformRange-region,.bp-WaveformView.bp-WaveformView--tape .bp-WaveformRange-handle{height:calc(100% + 10px)}.bp-WaveformView-track{position:relative;display:flex;align-items:center;width:100%;height:100%;cursor:pointer}.bp-WaveformView-canvas{z-index:0;width:100%;height:140px}.bp-WaveformView-playhead{position:absolute;top:50%;left:0;z-index:1;width:2px;height:150px;pointer-events:none;background:linear-gradient(#2487ff, #006bed);border-radius:1px;box-shadow:0 0 0 1px #222,0 0 10px 0 rgba(36,135,255,.3);transform:translate(-50%, -50%)}.bp-WaveformView-hover{position:absolute;top:100%;z-index:2;margin-top:4px;pointer-events:none;transform:translateX(-50%)}.bp-WaveformView-hover--tape{top:-24px;left:50%;z-index:5;margin-top:0;transform:translate(-50%, -50%)}.bp-WaveformView-hoverTime{padding:4px 10px;color:#fff;font-weight:normal;font-size:14px;font-family:Lato,Arial,sans-serif;line-height:20px;letter-spacing:.3px;white-space:nowrap;background:rgba(34,34,34,.92);border:1px solid rgba(255,255,255,.18);border-radius:8px}.bp-WaveformView--inert{pointer-events:none}.bp-WaveformView--inert .bp-WaveformView-track{cursor:default}.bp-WaveformView--inert .bp-WaveformRange-handle,.bp-WaveformView--inert .bp-WaveformRange-comment{pointer-events:none;cursor:default}.bp-WaveformView:not(:hover) .bp-WaveformRange:not(.bp-WaveformRange--persist){opacity:.4}
66
67
  .bp-SliderControl{outline:0;position:relative;cursor:pointer}.bp-SliderControl:focus:not(:disabled){box-shadow:inset 0 0 0 1px rgba(211,211,211,.5),0 1px 2px rgba(0,0,0,.1)}.bp-SliderControl:focus-visible:not(:disabled){box-shadow:inset 0 0 0 1px rgba(211,211,211,.5),0 1px 2px rgba(0,0,0,.1)}.bp-SliderControl:focus:not(:focus-visible){box-shadow:none}.bp-SliderControl-thumb{position:absolute;top:calc(50% - 6px);width:12px;height:12px;margin-left:-6px;background:#0061d5;border:0;border-radius:12px;cursor:pointer}.bp-SliderControl-track{position:absolute;inset:0;height:3px;margin:auto 3px;background:transparent linear-gradient(#fff, #fff) no-repeat center border-box}
67
68
  .bp-WaveformZoomControl{display:flex;flex-direction:row;gap:0;align-items:center;justify-content:flex-end;width:48px;height:48px;padding:4px;overflow:hidden;background:rgba(255,255,255,.1);border-radius:32px;box-shadow:0 2px 12px rgba(0,0,0,.08);backdrop-filter:blur(60px);transition:width 150ms ease-out,gap 150ms ease-out}.bp-WaveformZoomControl.bp-has-multiplier{padding:4px 4px 4px 12px}.bp-WaveformZoomControl.bp-has-multiplier:not(.bp-is-open){width:88px}.bp-WaveformZoomControl.bp-is-open{gap:8px;width:207px}.bp-WaveformZoomControl.bp-is-open.bp-has-multiplier{width:264px}.bp-WaveformZoomControl-multiplier{display:flex;flex:0 0 32px;order:-3;align-items:center;justify-content:center;width:32px;height:32px;color:#fff;font-weight:500;font-size:14px;line-height:22px;pointer-events:none;-webkit-user-select:none;user-select:none;white-space:nowrap}.bp-WaveformZoomControl-divider{display:none;flex:0 0 1px;order:-2;width:1px;height:28px;background:rgba(255,255,255,.3)}.bp-WaveformZoomControl.bp-is-open.bp-has-multiplier .bp-WaveformZoomControl-divider{display:block}.bp-WaveformZoomControl-flyout{display:flex;flex:0 0 auto;order:-1;gap:8px;align-items:center;width:0;height:40px;overflow:hidden;transition:width 150ms ease-out}.bp-WaveformZoomControl-flyout.bp-is-open{width:151px}.bp-WaveformZoomControl-slider{width:103px;height:8px}.bp-WaveformZoomControl-slider .bp-SliderControl-track{height:8px;margin:0;background:rgba(255,255,255,.3);background-image:none;border-radius:20px}.bp-WaveformZoomControl-slider .bp-SliderControl-track::after{position:absolute;top:0;left:0;width:calc(8px + 95px * var(--bp-zoom-t, 0));height:8px;background:rgba(255,255,255,.9);border-radius:20px;content:""}.bp-WaveformZoomControl-slider .bp-SliderControl-thumb{display:none}.bp-WaveformZoomControl-button{position:relative;z-index:1;display:flex;flex:0 0 40px;align-items:center;justify-content:center;width:40px;height:40px;padding:0;color:#fff;background:transparent;border:0;border-radius:50%;cursor:pointer}.bp-WaveformZoomControl-button[aria-disabled=true]{cursor:default;opacity:.3}.bp-WaveformZoomControl-button svg{width:20px;height:20px;padding:0}@media(prefers-reduced-motion: reduce){.bp-WaveformZoomControl,.bp-WaveformZoomControl-flyout{transition:none}}
68
- .bp-MP3ControlsRoot:has(.bp-MP3ControlsV2){position:absolute;inset:0;width:100%;height:100%;transform:none;pointer-events:none}.bp-MP3ControlsV2{--bp-waveform-bar-min: 140px;position:relative;width:100%;max-width:none;height:100%;background:transparent;pointer-events:none}.bp-MP3ControlsV2-stage{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;min-height:0;pointer-events:none}.bp-MP3ControlsV2-stage .bp-WaveformView,.bp-MP3ControlsV2-stage .bp-MP3ControlsV2-waveform,.bp-MP3ControlsV2-stage .bp-WaveformCommentMarkers{pointer-events:auto}.bp-MP3ControlsV2-waveform{position:relative;width:100%;overflow:visible}.bp-MP3ControlsV2-stage:has(.bp-WaveformView--tape) .bp-MP3ControlsV2-waveform{display:flex;flex-direction:column;height:max(var(--bp-waveform-bar-min, 140px), 25%);min-height:0}.bp-MP3ControlsV2-waveformZoom{position:absolute;top:48px;right:48px;z-index:6;pointer-events:none}.bp-MP3ControlsV2-waveformZoom .bp-WaveformZoomControl{pointer-events:auto}.bp-MP3ControlsV2-playOverlay{position:absolute;top:50%;left:50%;z-index:2;display:flex;align-items:center;justify-content:center;width:80px;height:80px;padding:0;background:rgba(0,0,0,.5);border:0;border-radius:50%;transform:translate(-50%, -50%);cursor:pointer;pointer-events:auto}.bp-MP3ControlsV2-playOverlay svg{width:48px;height:48px;fill:#fff}.bp-MP3ControlsV2-stage .bp-media-buffering-spinner{z-index:2;pointer-events:none}.bp-MP3ControlsV2-bar{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;align-items:center;justify-content:space-between;min-height:32px;padding:30px 58px 25px;background:linear-gradient(to top, black, rgba(0, 0, 0, 0));pointer-events:auto}.bp-MP3ControlsV2-group{display:flex;gap:12px;align-items:center}.bp-MP3ControlsV2-divider{width:1px;height:24px;background-color:rgba(255,255,255,.1);border-radius:1px}.bp-MP3ControlsV2 .bp-MP3Controls-settings{position:relative}.bp-MP3ControlsV2 .bp-MP3Controls-settings .bp-SettingsFlyout{right:15px}.bp-MP3ControlsV2 .bp-MP3Controls-settings .bp-SettingsToggle-button{width:36px;height:40px}
69
+ .bp-MP3ControlsRoot:has(.bp-MP3ControlsV2){position:absolute;inset:0;width:100%;height:100%;transform:none;pointer-events:none}.bp-MP3ControlsV2{--bp-waveform-bar-min: 140px;position:relative;width:100%;max-width:none;height:100%;background:transparent;pointer-events:none}.bp-MP3ControlsV2-stage{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%;min-height:0;pointer-events:none}.bp-MP3ControlsV2-stage .bp-WaveformView,.bp-MP3ControlsV2-stage .bp-MP3ControlsV2-waveform,.bp-MP3ControlsV2-stage .bp-WaveformCommentMarkers{pointer-events:auto}.bp-MP3ControlsV2-waveform{position:relative;width:100%;overflow:visible}.bp-MP3ControlsV2-stage:has(.bp-WaveformView--tape) .bp-MP3ControlsV2-waveform{display:flex;flex-direction:column;height:max(var(--bp-waveform-bar-min, 140px), 25%);min-height:0}.bp-MP3ControlsV2-waveformZoom{position:absolute;top:48px;right:48px;z-index:4;pointer-events:none}.bp-MP3ControlsV2-waveformZoom .bp-WaveformZoomControl{pointer-events:auto}.bp-MP3ControlsV2-playOverlay{position:absolute;top:50%;left:50%;z-index:2;display:flex;align-items:center;justify-content:center;width:80px;height:80px;padding:0;background:rgba(0,0,0,.5);border:0;border-radius:50%;transform:translate(-50%, -50%);cursor:pointer;pointer-events:auto}.bp-MP3ControlsV2-playOverlay svg{width:48px;height:48px;fill:#fff}.bp-MP3ControlsV2-stage .bp-media-buffering-spinner{z-index:2;pointer-events:none}.bp-MP3ControlsV2-bar{position:absolute;right:0;bottom:0;left:0;z-index:2;display:flex;align-items:center;justify-content:space-between;min-height:32px;padding:30px 58px 25px;background:linear-gradient(to top, black, rgba(0, 0, 0, 0));pointer-events:auto}.bp-MP3ControlsV2-group{display:flex;gap:12px;align-items:center}.bp-MP3ControlsV2-divider{width:1px;height:24px;background-color:rgba(255,255,255,.1);border-radius:1px}.bp-MP3ControlsV2 .bp-MP3Controls-settings{position:relative}.bp-MP3ControlsV2 .bp-MP3Controls-settings .bp-SettingsFlyout{right:15px}.bp-MP3ControlsV2 .bp-MP3Controls-settings .bp-SettingsToggle-button{width:36px;height:40px}
69
70
  .bp-Filmstrip{position:absolute;bottom:100%;overflow:hidden;background:transparent;box-shadow:0 0 1px #464a4f;visibility:hidden}.bp-Filmstrip.bp-is-shown{visibility:visible}.bp-Filmstrip-frame{display:flex;align-items:center;justify-content:center}.bp-Filmstrip-time{height:20px;color:#fff;font-size:13px;line-height:20px;text-align:center;background-color:#222}
70
71
  .bp-TimeControls{position:relative;margin-right:10px;margin-left:10px}.bp-TimeControls-slider{height:18px}.bp-TimeControls-slider .bp-SliderControl-thumb{transform:scale(0);transition:transform 100ms ease;will-change:transform}.bp-TimeControls-slider .bp-SliderControl-track{backface-visibility:hidden;transition:transform 100ms ease;will-change:transform}.bp-TimeControls-slider.bp-is-scrubbing .bp-SliderControl-thumb,.bp-TimeControls-slider:focus .bp-SliderControl-thumb,.bp-TimeControls-slider:hover .bp-SliderControl-thumb{transform:scale(1)}.bp-TimeControls-slider.bp-is-scrubbing .bp-SliderControl-track,.bp-TimeControls-slider:focus .bp-SliderControl-track,.bp-TimeControls-slider:hover .bp-SliderControl-track{transform:scaleY(2)}
71
72
  .bp-MP3Controls{display:flex;flex-direction:column;width:360px;background-color:#000}.bp-MP3Controls-bar{display:flex;justify-content:space-between;padding:0 10px 5px}.bp-MP3Controls-group{display:flex;align-items:center}.bp-MP3Controls-settings{position:relative}.bp-MP3Controls-settings .bp-SettingsFlyout{right:15px}.bp-MP3Controls-settings .bp-SettingsToggle-button{width:36px;height:40px}
package/dist/lib/index.js CHANGED
@@ -1029,7 +1029,7 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
1029
1029
  const CLIENT_NAME = "box-content-preview"; // eslint-disable-line no-undef
1030
1030
  const CLIENT_NAME_KEY = 'box_client_name';
1031
1031
  const CLIENT_VERSION_KEY = 'box_client_version';
1032
- const CLIENT_VERSION = "3.96.0"; // eslint-disable-line no-undef
1032
+ const CLIENT_VERSION = "3.98.0"; // eslint-disable-line no-undef
1033
1033
  const HEADER_CLIENT_NAME = 'X-Box-Client-Name';
1034
1034
  const HEADER_CLIENT_VERSION = 'X-Box-Client-Version';
1035
1035
  const PROMISE_MAP = {};
@@ -4620,7 +4620,7 @@ function getPdfjsWorkerSrc() {
4620
4620
 
4621
4621
  /***/ },
4622
4622
 
4623
- /***/ 8862
4623
+ /***/ 2460
4624
4624
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
4625
4625
 
4626
4626
 
@@ -4746,43 +4746,8 @@ function morphPeaks(from, to, elapsedMs) {
4746
4746
  }
4747
4747
  // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/viewport.ts
4748
4748
  var waveform_viewport = __webpack_require__(772);
4749
- ;// ./src/lib/viewers/media/waveform/useTapeWaveform.ts
4750
-
4751
-
4752
- function isIPadNavigator(tapeNavigator) {
4753
- return /iPad/i.test(tapeNavigator.userAgent || '') || tapeNavigator.platform === 'MacIntel' && (tapeNavigator.maxTouchPoints || 0) > 1;
4754
- }
4755
- function isCoarsePrimaryPointer(tapeWindow) {
4756
- return typeof tapeWindow.matchMedia === 'function' && tapeWindow.matchMedia(constants/* TAPE_POINTER_MEDIA_QUERY */.Le).matches;
4757
- }
4758
-
4759
- /**
4760
- * Tape vs desktop camera: coarse primary pointer (finger) or iPad
4761
- * (including iPadOS reporting itself as Mac). Not width, not hasTouch,
4762
- * not Browser.isMobile().
4763
- */
4764
- function isTapeWaveformInput(tapeWindow = window) {
4765
- return isCoarsePrimaryPointer(tapeWindow) || isIPadNavigator(tapeWindow.navigator);
4766
- }
4767
-
4768
- /** Subscribe to the pointer media query; re-read the iPad heuristic on change. */
4769
- function useTapeWaveform() {
4770
- const [isTape, setIsTape] = (0,external_react_.useState)(() => typeof window !== 'undefined' && isTapeWaveformInput(window));
4771
- (0,external_react_.useEffect)(() => {
4772
- if (typeof window.matchMedia !== 'function') {
4773
- setIsTape(isTapeWaveformInput(window));
4774
- return undefined;
4775
- }
4776
- const mediaQuery = window.matchMedia(constants/* TAPE_POINTER_MEDIA_QUERY */.Le);
4777
- const sync = () => {
4778
- setIsTape(isTapeWaveformInput(window));
4779
- };
4780
- sync();
4781
- mediaQuery.addEventListener('change', sync);
4782
- return () => mediaQuery.removeEventListener('change', sync);
4783
- }, []);
4784
- return isTape;
4785
- }
4749
+ // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/useTapeWaveform.ts
4750
+ var useTapeWaveform = __webpack_require__(7308);
4786
4751
  // EXTERNAL MODULE: ./node_modules/classnames/index.js
4787
4752
  var classnames = __webpack_require__(2485);
4788
4753
  var classnames_default = /*#__PURE__*/__webpack_require__.n(classnames);
@@ -4973,14 +4938,62 @@ function WaveformGeneratingIndicator() {
4973
4938
  className: "bp-WaveformGeneratingIndicator-label"
4974
4939
  }, label));
4975
4940
  }
4941
+ ;// ./src/lib/viewers/controls/icons/IconShuttleForward.tsx
4942
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
4943
+
4944
+ function IconShuttleForward(props) {
4945
+ return /*#__PURE__*/external_react_.createElement("svg", _extends({
4946
+ "data-testid": "IconShuttleForward",
4947
+ focusable: false,
4948
+ height: 11,
4949
+ viewBox: "35.57 37.51 37.79 21.24",
4950
+ width: 19
4951
+ }, props), /*#__PURE__*/external_react_.createElement("path", {
4952
+ d: "M35.5684 56.7422V39.502C35.5684 38.8275 35.7415 38.3262 36.0879 37.998C36.4342 37.6699 36.8398 37.5059 37.3047 37.5059C37.7331 37.5059 38.1523 37.6289 38.5625 37.875L53.0137 46.2832C53.5423 46.5931 53.9206 46.8848 54.1484 47.1582C54.3854 47.4316 54.5039 47.7552 54.5039 48.1289C54.5039 48.5026 54.3854 48.8262 54.1484 49.0996C53.9206 49.373 53.5423 49.6647 53.0137 49.9746L38.5625 58.3828C38.1523 58.6289 37.7331 58.752 37.3047 58.752C36.8398 58.752 36.4342 58.5879 36.0879 58.2598C35.7415 57.9316 35.5684 57.4258 35.5684 56.7422Z",
4953
+ fill: "currentColor"
4954
+ }), /*#__PURE__*/external_react_.createElement("path", {
4955
+ d: "M54.4219 56.7422V39.502C54.4219 38.8275 54.5905 38.3262 54.9277 37.998C55.2741 37.6699 55.6842 37.5059 56.1582 37.5059C56.5866 37.5059 57.0059 37.6289 57.416 37.875L71.8672 46.2832C72.3958 46.5931 72.7741 46.8848 73.002 47.1582C73.2389 47.4316 73.3574 47.7552 73.3574 48.1289C73.3574 48.5026 73.2389 48.8262 73.002 49.0996C72.7741 49.373 72.3958 49.6647 71.8672 49.9746L57.416 58.3828C57.0059 58.6289 56.5866 58.752 56.1582 58.752C55.6842 58.752 55.2741 58.5879 54.9277 58.2598C54.5905 57.9316 54.4219 57.4258 54.4219 56.7422Z",
4956
+ fill: "currentColor"
4957
+ }));
4958
+ }
4959
+ /* harmony default export */ const icons_IconShuttleForward = (IconShuttleForward);
4960
+ // EXTERNAL MODULE: ./src/lib/util.js + 1 modules
4961
+ var util = __webpack_require__(4410);
4962
+ ;// ./src/lib/viewers/media/waveform/WaveformShuttleIndicator.scss
4963
+ // extracted by mini-css-extract-plugin
4964
+
4965
+ ;// ./src/lib/viewers/media/waveform/WaveformShuttleIndicator.tsx
4966
+
4967
+
4968
+
4969
+
4970
+
4971
+ function WaveformShuttleIndicator({
4972
+ direction,
4973
+ rate
4974
+ }) {
4975
+ const isReverse = direction === 'reverse';
4976
+ const label = (0,util/* replacePlaceholders */.Lb)(isReverse ? "Scanning backward at {1}x" : "Scanning forward at {1}x", [String(rate)]);
4977
+ return /*#__PURE__*/external_react_["default"].createElement("div", {
4978
+ "aria-label": label,
4979
+ className: classnames_default()('bp-WaveformShuttle', {
4980
+ 'bp-is-reverse': isReverse
4981
+ }),
4982
+ "data-testid": "bp-waveform-shuttle",
4983
+ role: "status"
4984
+ }, /*#__PURE__*/external_react_["default"].createElement(icons_IconShuttleForward, {
4985
+ "aria-hidden": "true",
4986
+ className: "bp-WaveformShuttle-glyph"
4987
+ }), /*#__PURE__*/external_react_["default"].createElement("span", {
4988
+ className: "bp-WaveformShuttle-rate"
4989
+ }, `${rate}x`));
4990
+ }
4976
4991
  ;// external "react-dom"
4977
4992
 
4978
4993
  ;// ./node_modules/wavesurfer.js/dist/wavesurfer.esm.js
4979
4994
  function t(t,e,i,n){return new(i||(i=Promise))((function(s,r){function o(t){try{l(n.next(t))}catch(t){r(t)}}function a(t){try{l(n.throw(t))}catch(t){r(t)}}function l(t){var e;t.done?s(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(o,a)}l((n=n.apply(t,e||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class e{constructor(){this.listeners={}}on(t,e,i){if(this.listeners[t]||(this.listeners[t]=new Set),null==i?void 0:i.once){const i=(...n)=>{this.un(t,i),e(...n)};return this.listeners[t].add(i),()=>this.un(t,i)}return this.listeners[t].add(e),()=>this.un(t,e)}un(t,e){var i;null===(i=this.listeners[t])||void 0===i||i.delete(e)}once(t,e){return this.on(t,e,{once:!0})}unAll(){this.listeners={}}emit(t,...e){this.listeners[t]&&this.listeners[t].forEach((t=>t(...e)))}}const i={decode:function(e,i){return t(this,void 0,void 0,(function*(){const t=new AudioContext({sampleRate:i});try{return yield t.decodeAudioData(e)}finally{"closed"!==t.state&&(yield t.close().catch((()=>{})))}}))},createBuffer:function(t,e){if(!t||0===t.length)throw new Error("channelData must be a non-empty array");if(e<=0)throw new Error("duration must be greater than 0");if("number"==typeof t[0]&&(t=[t]),!t[0]||0===t[0].length)throw new Error("channelData must contain non-empty channel arrays");!function(t){const e=t[0];if(e.some((t=>t>1||t<-1))){const i=e.length;let n=0;for(let t=0;t<i;t++){const i=Math.abs(e[t]);i>n&&(n=i)}for(const e of t)for(let t=0;t<i;t++)e[t]/=n}}(t);const i=t.map((t=>t instanceof Float32Array?t:Float32Array.from(t)));return{duration:e,length:i[0].length,sampleRate:i[0].length/e,numberOfChannels:i.length,getChannelData:t=>{const e=i[t];if(!e)throw new Error(`Channel ${t} not found`);return e},copyFromChannel:AudioBuffer.prototype.copyFromChannel,copyToChannel:AudioBuffer.prototype.copyToChannel}}};function n(t,e){const i=e.xmlns?document.createElementNS(e.xmlns,t):document.createElement(t);for(const[t,s]of Object.entries(e))if("children"===t&&s)for(const[t,e]of Object.entries(s))e instanceof Node?i.appendChild(e):"string"==typeof e?i.appendChild(document.createTextNode(e)):i.appendChild(n(t,e));else"style"===t?Object.assign(i.style,s):"textContent"===t?i.textContent=s:i.setAttribute(t,s.toString());return i}function s(t,e,i){const s=n(t,e||{});return null==i||i.appendChild(s),s}function r(t){return t instanceof HTMLElement||"object"==typeof t&&null!==t&&t.nodeType===Node.ELEMENT_NODE&&"object"==typeof t.style}var o=Object.freeze({__proto__:null,createElement:s,default:s,isHTMLElement:r});const a={fetchBlob:function(e,i,n){return t(this,void 0,void 0,(function*(){var s;const r=yield fetch(e,n);if(r.status>=400)throw new Error(`Failed to fetch ${e}: ${r.status} (${r.statusText})`);return function(e,i,n){t(this,void 0,void 0,(function*(){var t;if(!e.body||!e.headers)return;const s=e.body.getReader(),r=Number(e.headers.get("Content-Length"))||0;let o=0;const a=()=>{s.cancel()};if(n){if(n.aborted)return void s.cancel();n.addEventListener("abort",a,{once:!0})}try{for(;;){const e=yield s.read();if(e.done)break;if(o+=(null===(t=e.value)||void 0===t?void 0:t.length)||0,r>0){const t=Math.round(o/r*100);i(t)}}}catch(t){if(t instanceof DOMException&&"AbortError"===t.name)return;console.warn("Progress tracking error:",t)}finally{n&&n.removeEventListener("abort",a)}}))}(r.clone(),i,null!==(s=null==n?void 0:n.signal)&&void 0!==s?s:void 0),r.blob()}))}};function l(t){let e=t;const i=new Set;return{get value(){return e},set(t){Object.is(e,t)||(e=t,i.forEach((t=>t(e))))},update(t){this.set(t(e))},subscribe:t=>(i.add(t),()=>i.delete(t))}}function h(t,e){const i=l(t());return e.forEach((e=>e.subscribe((()=>{const e=t();Object.is(i.value,e)||i.set(e)})))),{get value(){return i.value},subscribe:t=>i.subscribe(t)}}function c(t,e){let i;const n=()=>{i&&(i(),i=void 0),i=t()},s=e.map((t=>t.subscribe(n)));return n(),()=>{i&&(i(),i=void 0),s.forEach((t=>t()))}}class u extends e{get isPlayingSignal(){return this._isPlaying}get currentTimeSignal(){return this._currentTime}get durationSignal(){return this._duration}get volumeSignal(){return this._volume}get mutedSignal(){return this._muted}get playbackRateSignal(){return this._playbackRate}get seekingSignal(){return this._seeking}constructor(t){super(),this.isExternalMedia=!1,this._ownBlobUrl=null,this.reactiveMediaEventCleanups=[],t.media?(this.media=t.media,this.isExternalMedia=!0):this.media=document.createElement("audio"),this._isPlaying=l(!1),this._currentTime=l(0),this._duration=l(0),this._volume=l(this.media.volume),this._muted=l(this.media.muted),this._playbackRate=l(this.media.playbackRate||1),this._seeking=l(!1),this.setupReactiveMediaEvents(),t.mediaControls&&(this.media.controls=!0),t.autoplay&&(this.media.autoplay=!0),null!=t.playbackRate&&this.onMediaEvent("canplay",(()=>{null!=t.playbackRate&&(this.media.playbackRate=t.playbackRate)}),{once:!0})}setupReactiveMediaEvents(){this.reactiveMediaEventCleanups.push(this.onMediaEvent("play",(()=>{this._isPlaying.set(!0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("pause",(()=>{this._isPlaying.set(!1)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("ended",(()=>{this._isPlaying.set(!1)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("timeupdate",(()=>{this._currentTime.set(this.media.currentTime)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("durationchange",(()=>{this._duration.set(this.media.duration||0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("loadedmetadata",(()=>{this._duration.set(this.media.duration||0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("seeking",(()=>{this._seeking.set(!0)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("seeked",(()=>{this._seeking.set(!1)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("volumechange",(()=>{this._volume.set(this.media.volume),this._muted.set(this.media.muted)}))),this.reactiveMediaEventCleanups.push(this.onMediaEvent("ratechange",(()=>{this._playbackRate.set(this.media.playbackRate)})))}onMediaEvent(t,e,i){return this.media.addEventListener(t,e,i),()=>this.media.removeEventListener(t,e,i)}getSrc(){return this.media.currentSrc||this.media.src||""}revokeSrc(){this._ownBlobUrl&&(URL.revokeObjectURL(this._ownBlobUrl),this._ownBlobUrl=null)}canPlayType(t){return""!==this.media.canPlayType(t)}setSrc(t,e){const i=this.getSrc();if(t&&i===t)return;this.revokeSrc();const n=e instanceof Blob&&(this.canPlayType(e.type)||!t)?URL.createObjectURL(e):t;if(n!==t&&(this._ownBlobUrl=n),i&&this.media.removeAttribute("src"),n||t)try{this.media.src=n}catch(e){this.media.src=t}}destroy(){this.reactiveMediaEventCleanups.forEach((t=>t())),this.reactiveMediaEventCleanups=[],this.revokeSrc(),this.unAll(),this.isExternalMedia||(this.media.pause(),this.media.removeAttribute("src"),this.media.load(),this.media.remove())}setMediaElement(t){this.reactiveMediaEventCleanups.forEach((t=>t())),this.reactiveMediaEventCleanups=[],this.media=t,this.setupReactiveMediaEvents()}play(){return t(this,void 0,void 0,(function*(){try{return yield this.media.play()}catch(t){if(t instanceof DOMException&&"AbortError"===t.name)return;throw t}}))}pause(){this.media.pause()}isPlaying(){return!this.media.paused&&!this.media.ended}setTime(t){this.media.currentTime=Math.max(0,Math.min(t,this.getDuration()))}getDuration(){return this.media.duration}getCurrentTime(){return this.media.currentTime}getVolume(){return this.media.volume}setVolume(t){this.media.volume=t}getMuted(){return this.media.muted}setMuted(t){this.media.muted=t}getPlaybackRate(){return this.media.playbackRate}isSeeking(){return this.media.seeking}setPlaybackRate(t,e){null!=e&&(this.media.preservesPitch=e),this.media.playbackRate=t}getMediaElement(){return this.media}setSinkId(t){return this.media.setSinkId(t)}}function d({maxTop:t,maxBottom:e,halfHeight:i,vScale:n,barMinHeight:s=0,barAlign:r}){let o=Math.round(t*i*n);let a=o+Math.round(e*i*n)||1;return a<s&&(a=s,r||(o=a/2)),{topHeight:o,totalHeight:a}}function p({barAlign:t,halfHeight:e,topHeight:i,totalHeight:n,canvasHeight:s}){return"top"===t?0:"bottom"===t?s-n:e-i}function m(t,e,i){const n=e-t.left,s=i-t.top;return[n/t.width,s/t.height]}function g(t){return Boolean(t.barWidth||t.barGap||t.barAlign)}function f(t,e){if(!g(e))return t;const i=e.barWidth||.5,n=i+(e.barGap||i/2);return 0===n?t:Math.floor(t/n)*n}function v({scrollLeft:t,totalWidth:e,numCanvases:i}){if(0===e)return[0];const n=t/e,s=Math.floor(n*i);return[s-1,s,s+1]}function b(t){const e=t._cleanup;"function"==typeof e&&e()}function y(t){const e=l({scrollLeft:t.scrollLeft,scrollWidth:t.scrollWidth,clientWidth:t.clientWidth}),i=h((()=>function(t){const{scrollLeft:e,scrollWidth:i,clientWidth:n}=t;if(0===i)return{startX:0,endX:1};const s=e/i,r=(e+n)/i;return{startX:Math.max(0,Math.min(1,s)),endX:Math.max(0,Math.min(1,r))}}(e.value)),[e]),n=h((()=>function(t){return{left:t.scrollLeft,right:t.scrollLeft+t.clientWidth}}(e.value)),[e]),s=()=>{e.set({scrollLeft:t.scrollLeft,scrollWidth:t.scrollWidth,clientWidth:t.clientWidth})};t.addEventListener("scroll",s,{passive:!0});return{scrollData:e,percentages:i,bounds:n,cleanup:()=>{t.removeEventListener("scroll",s),b(e)}}}class C extends e{constructor(t,e){super(),this.timeouts=[],this.isScrollable=!1,this.audioData=null,this.resizeObserver=null,this.lastContainerWidth=0,this.isDragging=!1,this.subscriptions=[],this.unsubscribeOnScroll=[],this.dragStream=null,this.scrollStream=null,this.containerInlinePadding=0,this.onClickWrapper=t=>{const e=this.wrapper.getBoundingClientRect(),[i,n]=m(e,t.clientX,t.clientY);this.emit("click",i,n)},this.onDblClickWrapper=t=>{const e=this.wrapper.getBoundingClientRect(),[i,n]=m(e,t.clientX,t.clientY);this.emit("dblclick",i,n)},this.subscriptions=[],this.options=t;const i=this.parentFromOptionsContainer(t.container);this.parent=i;const[n,s]=this.initHtml();i.appendChild(n),this.container=n,this.scrollContainer=s.querySelector(".scroll"),this.wrapper=s.querySelector(".wrapper"),this.canvasWrapper=s.querySelector(".canvases"),this.progressWrapper=s.querySelector(".progress"),this.cursor=s.querySelector(".cursor"),this.calculateInlinePadding(),e&&s.appendChild(e),this.initEvents()}parentFromOptionsContainer(t){let e;if("string"==typeof t?e=document.querySelector(t):r(t)&&(e=t),!e)throw new Error("Container not found");return e}initEvents(){this.wrapper.addEventListener("click",this.onClickWrapper),this.wrapper.addEventListener("dblclick",this.onDblClickWrapper),!0!==this.options.dragToSeek&&"object"!=typeof this.options.dragToSeek||this.initDrag(),this.scrollStream=y(this.scrollContainer);const t=c((()=>{const{startX:t,endX:e}=this.scrollStream.percentages.value,{left:i,right:n}=this.scrollStream.bounds.value;this.emit("scroll",t,e,i,n)}),[this.scrollStream.percentages,this.scrollStream.bounds]);if(this.subscriptions.push(t),"function"==typeof ResizeObserver){const t=this.createDelay(100);this.resizeObserver=new ResizeObserver((()=>{t().then((()=>this.onContainerResize())).catch((()=>{}))})),this.resizeObserver.observe(this.scrollContainer)}}onContainerResize(){const t=this.parent.clientWidth;this.calculateInlinePadding(),t===this.lastContainerWidth&&"auto"!==this.options.height||(this.lastContainerWidth=t,this.reRender(),this.emit("resize"))}initDrag(){if(this.dragStream)return;this.dragStream=function(t,e={}){const{threshold:i=3,mouseButton:n=0,touchDelay:s=100}=e,r=l(null),o=new Map,a=matchMedia("(pointer: coarse)").matches;let h=()=>{};const c=e=>{if(e.button!==n)return;if(o.has(e.pointerId))return;if(o.set(e.pointerId,e),o.size>1)return;const l=e.pointerId;let c=e.clientX,u=e.clientY,d=!1;const p=Date.now(),m=t.getBoundingClientRect(),{left:g,top:f}=m,v=t=>{if(t.pointerId!==l)return;if(t.defaultPrevented||o.size>1)return;if(a&&Date.now()-p<s)return;const e=t.clientX,n=t.clientY,h=e-c,m=n-u;(d||Math.abs(h)>i||Math.abs(m)>i)&&(t.preventDefault(),t.stopPropagation(),d||(r.set({type:"start",x:c-g,y:u-f}),d=!0),r.set({type:"move",x:e-g,y:n-f,deltaX:h,deltaY:m}),c=e,u=n)},b=t=>{if(o.delete(t.pointerId)){if(t.pointerId===l&&d){const e=t.clientX,i=t.clientY;r.set({type:"end",x:e-g,y:i-f})}0===o.size&&h()}},y=t=>{t.relatedTarget&&t.relatedTarget!==document.documentElement||b(t)},C=t=>{d&&(t.stopPropagation(),t.preventDefault())},S=t=>{t.defaultPrevented||o.size>1||d&&t.preventDefault()};document.addEventListener("pointermove",v),document.addEventListener("pointerup",b),document.addEventListener("pointerout",y),document.addEventListener("pointercancel",y),document.addEventListener("touchmove",S,{passive:!1}),document.addEventListener("click",C,{capture:!0}),h=()=>{document.removeEventListener("pointermove",v),document.removeEventListener("pointerup",b),document.removeEventListener("pointerout",y),document.removeEventListener("pointercancel",y),document.removeEventListener("touchmove",S),setTimeout((()=>{document.removeEventListener("click",C,{capture:!0})}),10)}};return t.addEventListener("pointerdown",c),{signal:r,cleanup:()=>{h(),t.removeEventListener("pointerdown",c),o.clear(),b(r)}}}(this.wrapper);const t=c((()=>{const t=this.dragStream.signal.value;if(!t)return;const e=this.wrapper.getBoundingClientRect().width,i=(n=t.x/e)<0?0:n>1?1:n;var n;"start"===t.type?(this.isDragging=!0,this.emit("dragstart",i)):"move"===t.type?this.emit("drag",i):"end"===t.type&&(this.isDragging=!1,this.emit("dragend",i))}),[this.dragStream.signal]);this.subscriptions.push(t)}calculateInlinePadding(){const{paddingLeft:t,paddingRight:e}=getComputedStyle(this.scrollContainer),i=parseFloat(t)+parseFloat(e);this.containerInlinePadding=Number.isNaN(i)?0:i}initHtml(){const t=document.createElement("div"),e=t.attachShadow({mode:"open"}),i=this.options.cspNonce&&"string"==typeof this.options.cspNonce?this.options.cspNonce.replace(/"/g,""):"";return e.innerHTML=`\n <style${i?` nonce="${i}"`:""}>\n :host {\n user-select: none;\n min-width: 1px;\n }\n :host audio {\n display: block;\n width: 100%;\n }\n :host .scroll {\n overflow-x: auto;\n overflow-y: hidden;\n width: 100%;\n position: relative;\n }\n :host .noScrollbar {\n scrollbar-color: transparent;\n scrollbar-width: none;\n }\n :host .noScrollbar::-webkit-scrollbar {\n display: none;\n -webkit-appearance: none;\n }\n :host .wrapper {\n position: relative;\n overflow: visible;\n z-index: 2;\n }\n :host .canvases {\n min-height: ${this.getHeight(this.options.height,this.options.splitChannels)}px;\n pointer-events: none;\n }\n :host .canvases > div {\n position: relative;\n }\n :host canvas {\n display: block;\n position: absolute;\n top: 0;\n image-rendering: pixelated;\n }\n :host .progress {\n pointer-events: none;\n position: absolute;\n z-index: 2;\n top: 0;\n left: 0;\n width: 0;\n height: 100%;\n overflow: hidden;\n }\n :host .progress > div {\n position: relative;\n }\n :host .cursor {\n pointer-events: none;\n position: absolute;\n z-index: 5;\n top: 0;\n left: 0;\n height: 100%;\n border-radius: 2px;\n }\n </style>\n\n <div class="scroll" part="scroll">\n <div class="wrapper" part="wrapper">\n <div class="canvases" part="canvases"></div>\n <div class="progress" part="progress"></div>\n <div class="cursor" part="cursor"></div>\n </div>\n </div>\n `,[t,e]}setOptions(t){var e;if(this.options.container!==t.container){const e=this.parentFromOptionsContainer(t.container);e.appendChild(this.container),this.parent=e}!0===t.dragToSeek||"object"==typeof this.options.dragToSeek?this.initDrag():(null===(e=this.dragStream)||void 0===e||e.cleanup(),this.dragStream=null),this.options=t,this.reRender()}getWrapper(){return this.wrapper}getWidth(){return this.scrollContainer.clientWidth-this.containerInlinePadding}getScroll(){return this.scrollContainer.scrollLeft}setScroll(t){this.scrollContainer.scrollLeft=t}setScrollPercentage(t){const{scrollWidth:e}=this.scrollContainer,i=e*t;this.setScroll(i)}destroy(){var t;this.wrapper.removeEventListener("click",this.onClickWrapper),this.wrapper.removeEventListener("dblclick",this.onDblClickWrapper),this.timeouts.forEach((t=>t())),this.timeouts=[],this.subscriptions.forEach((t=>t())),this.container.remove(),this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),null===(t=this.unsubscribeOnScroll)||void 0===t||t.forEach((t=>t())),this.unsubscribeOnScroll=[],this.dragStream&&(this.dragStream.cleanup(),this.dragStream=null),this.scrollStream&&(this.scrollStream.cleanup(),this.scrollStream=null)}createDelay(t=10){let e,i;const n=()=>{e&&(clearTimeout(e),e=void 0),i&&(i(),i=void 0)};return this.timeouts.push(n),()=>new Promise(((s,r)=>{n(),i=r,e=setTimeout((()=>{e=void 0,i=void 0,s()}),t)}))}getHeight(t,e){var i;const n=(null===(i=this.audioData)||void 0===i?void 0:i.numberOfChannels)||1;return function({optionsHeight:t,optionsSplitChannels:e,parentHeight:i,numberOfChannels:n,defaultHeight:s=128}){if(null==t)return s;const r=Number(t);if(!isNaN(r))return r;if("auto"===t){const t=i||s;return(null==e?void 0:e.every((t=>!t.overlay)))?t/n:t}return s}({optionsHeight:t,optionsSplitChannels:e,parentHeight:this.parent.clientHeight,numberOfChannels:n,defaultHeight:128})}convertColorValues(t,e){return function(t,e,i){if(!Array.isArray(t))return t||"";if(0===t.length)return"#999";if(t.length<2)return t[0]||"";const n=document.createElement("canvas"),s=n.getContext("2d");if(!s)return t[0]||"";const r=i||n.height*e,o=s.createLinearGradient(0,0,0,r),a=1/(t.length-1);return t.forEach(((t,e)=>{o.addColorStop(e*a,t)})),o}(t,this.getPixelRatio(),null==e?void 0:e.canvas.height)}getPixelRatio(){return t=window.devicePixelRatio,Math.max(1,t||1);// removed by dead control flow
4980
4995
  var t; }renderBarWaveform(t,e,i,n){const{width:s,height:r}=i.canvas,{halfHeight:o,barWidth:a,barRadius:l,barIndexScale:h,barSpacing:c,barMinHeight:u}=function({width:t,height:e,length:i,options:n,pixelRatio:s}){const r=e/2,o=n.barWidth?n.barWidth*s:1,a=n.barGap?n.barGap*s:n.barWidth?o/2:0,l=o+a||1;return{halfHeight:r,barWidth:o,barGap:a,barRadius:n.barRadius||0,barMinHeight:n.barMinHeight?n.barMinHeight*s:0,barIndexScale:i>0?t/l/i:0,barSpacing:l}}({width:s,height:r,length:(t[0]||[]).length,options:e,pixelRatio:this.getPixelRatio()}),m=function({channelData:t,barIndexScale:e,barSpacing:i,barWidth:n,halfHeight:s,vScale:r,canvasHeight:o,barAlign:a,barMinHeight:l}){const h=t[0]||[],c=t[1]||h,u=h.length,m=[];let g=0,f=0,v=0;for(let t=0;t<=u;t++){const u=Math.round(t*e);if(u>g){const{topHeight:t,totalHeight:e}=d({maxTop:f,maxBottom:v,halfHeight:s,vScale:r,barMinHeight:l,barAlign:a}),h=p({barAlign:a,halfHeight:s,topHeight:t,totalHeight:e,canvasHeight:o});m.push({x:g*i,y:h,width:n,height:e}),g=u,f=0,v=0}const b=Math.abs(h[t]||0),y=Math.abs(c[t]||0);b>f&&(f=b),y>v&&(v=y)}return m}({channelData:t,barIndexScale:h,barSpacing:c,barWidth:a,halfHeight:o,vScale:n,canvasHeight:r,barAlign:e.barAlign,barMinHeight:u});i.beginPath();for(const t of m)l&&"roundRect"in i?i.roundRect(t.x,t.y,t.width,t.height,l):i.rect(t.x,t.y,t.width,t.height);i.fill(),i.closePath()}renderLineWaveform(t,e,i,n){const{width:s,height:r}=i.canvas,o=function({channelData:t,width:e,height:i,vScale:n}){const s=i/2,r=t[0]||[];return[r,t[1]||r].map(((t,i)=>{const r=t.length,o=r?e/r:0,a=s,l=0===i?-1:1,h=[{x:0,y:a}];let c=0,u=0;for(let e=0;e<=r;e++){const i=Math.round(e*o);if(i>c){const t=a+(Math.round(u*s*n)||1)*l;h.push({x:c,y:t}),c=i,u=0}const r=Math.abs(t[e]||0);r>u&&(u=r)}return h.push({x:c,y:a}),h}))}({channelData:t,width:s,height:r,vScale:n});i.beginPath();for(const t of o)if(t.length){i.moveTo(t[0].x,t[0].y);for(let e=1;e<t.length;e++){const n=t[e];i.lineTo(n.x,n.y)}}i.fill(),i.closePath()}renderWaveform(t,e,i){if(i.fillStyle=this.convertColorValues(e.waveColor,i),e.renderFunction)return void e.renderFunction(t,i);const n=function({channelData:t,barHeight:e,normalize:i,maxPeak:n}){var s;const r=e||1;if(!i)return r;const o=t[0];if(!o||0===o.length)return r;let a=null!=n?n:0;if(!n)for(let t=0;t<o.length;t++){const e=null!==(s=o[t])&&void 0!==s?s:0,i=Math.abs(e);i>a&&(a=i)}return a?r/a:r}({channelData:t,barHeight:e.barHeight,normalize:e.normalize,maxPeak:e.maxPeak});g(e)?this.renderBarWaveform(t,e,i,n):this.renderLineWaveform(t,e,i,n)}renderSingleCanvas(t,e,i,n,s,r,o){const a=this.getPixelRatio(),l=document.createElement("canvas");l.width=Math.round(i*a),l.height=Math.round(n*a),l.style.width=`${i}px`,l.style.height=`${n}px`,l.style.left=`${Math.round(s)}px`,r.appendChild(l);const h=l.getContext("2d");if(e.renderFunction?(h.fillStyle=this.convertColorValues(e.waveColor,h),e.renderFunction(t,h)):this.renderWaveform(t,e,h),l.width>0&&l.height>0){const t=l.cloneNode(),i=t.getContext("2d");i.drawImage(l,0,0),i.globalCompositeOperation="source-in",i.fillStyle=this.convertColorValues(e.progressColor,i),i.fillRect(0,0,l.width,l.height),o.appendChild(t)}}renderMultiCanvas(t,e,i,n,s,r){const o=this.getPixelRatio(),{clientWidth:a}=this.scrollContainer,l=i/o,h=function({clientWidth:t,totalWidth:e,options:i}){return f(Math.min(8e3,t,e),i)}({clientWidth:a,totalWidth:l,options:e});let c={};if(0===h)return;const u=i=>{if(i<0||i>=d)return;if(c[i])return;c[i]=!0;const o=i*h;let a=Math.min(l-o,h);if(a=f(a,e),a<=0)return;const u=function({channelData:t,offset:e,clampedWidth:i,totalWidth:n}){return t.map((t=>{const s=Math.floor(e/n*t.length),r=Math.floor((e+i)/n*t.length);return t.slice(s,r)}))}({channelData:t,offset:o,clampedWidth:a,totalWidth:l});this.renderSingleCanvas(u,e,a,n,o,s,r)},d=Math.ceil(l/h);if(!this.isScrollable){for(let t=0;t<d;t++)u(t);return}if(v({scrollLeft:this.scrollContainer.scrollLeft,totalWidth:l,numCanvases:d}).forEach((t=>u(t))),d>1){const t=this.on("scroll",(()=>{const{scrollLeft:t}=this.scrollContainer;Object.keys(c).length>10&&(s.innerHTML="",r.innerHTML="",c={}),v({scrollLeft:t,totalWidth:l,numCanvases:d}).forEach((t=>u(t)))}));this.unsubscribeOnScroll.push(t)}}renderChannel(t,e,i,n){var{overlay:s}=e,r=function(t,e){var i={};for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&e.indexOf(n)<0&&(i[n]=t[n]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(n=Object.getOwnPropertySymbols(t);s<n.length;s++)e.indexOf(n[s])<0&&Object.prototype.propertyIsEnumerable.call(t,n[s])&&(i[n[s]]=t[n[s]])}return i}(e,["overlay"]);const o=document.createElement("div"),a=this.getHeight(r.height,r.splitChannels);o.style.height=`${a}px`,s&&n>0&&(o.style.marginTop=`-${a}px`),this.canvasWrapper.style.minHeight=`${a}px`,this.canvasWrapper.appendChild(o);const l=o.cloneNode();this.progressWrapper.appendChild(l),this.renderMultiCanvas(t,r,i,a,o,l)}render(e){return t(this,void 0,void 0,(function*(){var t;this.timeouts.forEach((t=>t())),this.timeouts=[],this.unsubscribeOnScroll.forEach((t=>t())),this.unsubscribeOnScroll=[],this.canvasWrapper.innerHTML="",this.progressWrapper.innerHTML="",null!=this.options.width&&(this.scrollContainer.style.width="number"==typeof this.options.width?`${this.options.width}px`:this.options.width);const i=this.getPixelRatio(),n=this.scrollContainer.clientWidth-this.containerInlinePadding,{scrollWidth:s,isScrollable:r,useParentWidth:o,width:a}=function({duration:t,minPxPerSec:e=0,parentWidth:i,fillParent:n,pixelRatio:s}){const r=Math.ceil(t*e),o=r>i,a=Boolean(n&&!o);return{scrollWidth:r,isScrollable:o,useParentWidth:a,width:(a?i:r)*s}}({duration:e.duration,minPxPerSec:this.options.minPxPerSec||0,parentWidth:n,fillParent:this.options.fillParent,pixelRatio:i});if(this.isScrollable=r,this.wrapper.style.width=o?"100%":`${s}px`,this.scrollContainer.style.overflowX=this.isScrollable?"auto":"hidden",this.scrollContainer.classList.toggle("noScrollbar",!!this.options.hideScrollbar),this.cursor.style.backgroundColor=`${this.options.cursorColor||this.options.progressColor}`,this.cursor.style.width=`${this.options.cursorWidth}px`,this.audioData=e,this.emit("render"),this.options.splitChannels)for(let i=0;i<e.numberOfChannels;i++){const n=Object.assign(Object.assign({},this.options),null===(t=this.options.splitChannels)||void 0===t?void 0:t[i]);this.renderChannel([e.getChannelData(i)],n,a,i)}else{const t=[e.getChannelData(0)];e.numberOfChannels>1&&t.push(e.getChannelData(1)),this.renderChannel(t,this.options,a,0)}Promise.resolve().then((()=>this.emit("rendered")))}))}reRender(){if(this.unsubscribeOnScroll.forEach((t=>t())),this.unsubscribeOnScroll=[],!this.audioData)return;const{scrollWidth:t}=this.scrollContainer,{right:e}=this.progressWrapper.getBoundingClientRect();if(this.render(this.audioData),!this.isScrollable&&this.scrollContainer.scrollLeft)this.scrollContainer.scrollLeft=0;else if(this.isScrollable&&t!==this.scrollContainer.scrollWidth){const{right:t}=this.progressWrapper.getBoundingClientRect(),i=function(t){const e=2*t;return(e<0?Math.floor(e):Math.ceil(e))/2}(t-e);this.scrollContainer.scrollLeft+=i}}zoom(t){this.options.minPxPerSec=t,this.reRender()}scrollIntoView(t,e=!1){var i;const{scrollLeft:n,scrollWidth:s,clientWidth:r}=this.scrollContainer,o=t*s,a=n,l=n+r,h=r/2;if(this.isDragging){const t=30;o+t>l?this.scrollContainer.scrollLeft+=t:o-t<a&&(this.scrollContainer.scrollLeft-=t)}else{(o<a||o>l)&&(this.scrollContainer.scrollLeft=o-(this.options.autoCenter?h:0));const t=o-n-h;if(e&&this.options.autoCenter&&t>0){const e=null===(i=this.audioData)||void 0===i?void 0:i.duration;if(void 0===e||e<=0)return void(this.scrollContainer.scrollLeft+=t);const n=s/e;this.scrollContainer.scrollLeft+=n<=600?Math.min(t,10):t}}}renderProgress(t,e){if(isNaN(t))return;const i=100*t;this.canvasWrapper.style.clipPath=`polygon(${i}% 0%, 100% 0%, 100% 100%, ${i}% 100%)`,this.progressWrapper.style.width=`${i}%`,this.cursor.style.left=`${i}%`,this.cursor.style.transform=this.options.cursorWidth?`translateX(-${t*this.options.cursorWidth}px)`:"",this.isScrollable&&this.options.autoScroll&&this.audioData&&this.audioData.duration>0&&this.scrollIntoView(t,e)}exportImage(e,i,n){return t(this,void 0,void 0,(function*(){const t=this.canvasWrapper.querySelectorAll("canvas");if(!t.length)throw new Error("No waveform data");if("dataURL"===n){const n=Array.from(t).map((t=>t.toDataURL(e,i)));return Promise.resolve(n)}return Promise.all(Array.from(t).map((t=>new Promise(((n,s)=>{t.toBlob((t=>{t?n(t):s(new Error("Could not export image"))}),e,i)})))))}))}}class S extends e{constructor(){super(...arguments),this.animationFrameId=null,this.isRunning=!1}start(){if(this.isRunning)return;this.isRunning=!0;const t=()=>{this.isRunning&&(this.emit("tick"),this.animationFrameId=requestAnimationFrame(t))};t()}stop(){this.isRunning=!1,null!==this.animationFrameId&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}destroy(){this.stop(),this.unAll()}}class E extends e{constructor(t){super(),this.bufferNode=null,this.playStartTime=0,this.playbackPosition=0,this._muted=!1,this._playbackRate=1,this._duration=void 0,this.buffer=null,this.currentSrc="",this.paused=!0,this.crossOrigin=null,this.seeking=!1,this.autoplay=!1,this.addEventListener=this.on,this.removeEventListener=this.un,this._destroyed=!1,function(){const t=globalThis.navigator;if(null==t?void 0:t.audioSession)try{t.audioSession.type="playback"}catch(t){console.warn("Setting navigator.audioSession.type failed:",t)}}(),this.audioContext=t||new AudioContext,this.gainNode=this.audioContext.createGain(),this.gainNode.connect(this.audioContext.destination)}load(){return t(this,void 0,void 0,(function*(){}))}remove(){this.destroy()}destroy(){if(!this._destroyed){if(this._destroyed=!0,this.currentSrc="",this.bufferNode){this.bufferNode.onended=null;try{this.bufferNode.stop()}catch(t){}this.bufferNode.disconnect(),this.bufferNode=null}this.gainNode.disconnect(),"function"==typeof this.audioContext.close&&Promise.resolve(this.audioContext.close.call(this.audioContext)).catch((()=>{})),this.buffer=null,this.unAll()}}get src(){return this.currentSrc}set src(t){if(this.currentSrc=t,this._duration=void 0,!t)return this.buffer=null,void this.emit("emptied");fetch(t).then((e=>{if(e.status>=400)throw new Error(`Failed to fetch ${t}: ${e.status} (${e.statusText})`);return e.arrayBuffer()})).then((e=>this.currentSrc!==t?null:this.audioContext.decodeAudioData(e))).then((e=>{this.currentSrc===t&&(this.buffer=e,this.emit("loadedmetadata"),this.emit("canplay"),this.autoplay&&this.play())})).catch((t=>{console.error("WebAudioPlayer load error:",t)}))}_play(){if(!this.paused)return;this.paused=!1,this.bufferNode&&(this.bufferNode.onended=null,this.bufferNode.disconnect()),this.bufferNode=this.audioContext.createBufferSource(),this.buffer&&(this.bufferNode.buffer=this.buffer),this.bufferNode.playbackRate.value=this._playbackRate,this.bufferNode.connect(this.gainNode);let t=this.playbackPosition;(t>=this.duration||t<0)&&(t=0,this.playbackPosition=0),this.bufferNode.start(this.audioContext.currentTime,t),this.playStartTime=this.audioContext.currentTime,this.bufferNode.onended=()=>{!this.paused&&this.duration-this.currentTime<.01&&(this.pause(),this.emit("ended"))}}_pause(){if(this.paused=!0,this.bufferNode){this.bufferNode.onended=null;try{this.bufferNode.stop()}catch(t){}}this.playbackPosition+=(this.audioContext.currentTime-this.playStartTime)*this._playbackRate}play(){return t(this,void 0,void 0,(function*(){this.paused&&(this._play(),this.emit("play"))}))}pause(){this.paused||(this._pause(),this.emit("pause"))}stopAt(t){const e=(t-this.currentTime)/this._playbackRate,i=this.bufferNode;null==i||i.stop(this.audioContext.currentTime+e),null==i||i.addEventListener("ended",(()=>{i===this.bufferNode&&(this.bufferNode=null,this.pause(),this.playbackPosition=Math.min(t,this.duration),this.emit("timeupdate"))}),{once:!0})}setSinkId(e){return t(this,void 0,void 0,(function*(){return this.audioContext.setSinkId(e)}))}get playbackRate(){return this._playbackRate}set playbackRate(t){const e=!this.paused;e&&this._pause(),this._playbackRate=t,e&&this._play(),this.bufferNode&&(this.bufferNode.playbackRate.value=t)}get currentTime(){return this.paused?this.playbackPosition:this.playbackPosition+(this.audioContext.currentTime-this.playStartTime)*this._playbackRate}set currentTime(t){const e=!this.paused;e&&this._pause(),this.playbackPosition=t,e&&this._play(),this.emit("seeking"),this.emit("timeupdate")}get duration(){var t,e;return null!==(t=this._duration)&&void 0!==t?t:(null===(e=this.buffer)||void 0===e?void 0:e.duration)||0}set duration(t){this._duration=t}get volume(){return this.gainNode.gain.value}set volume(t){this.gainNode.gain.value=t,this.emit("volumechange")}get muted(){return this._muted}set muted(t){this._muted!==t&&(this._muted=t,this._muted?this.gainNode.disconnect():this.gainNode.connect(this.audioContext.destination))}canPlayType(t){return/^(audio|video)\//.test(t)}getGainNode(){return this.gainNode}getChannelData(){const t=[];if(!this.buffer)return t;const e=this.buffer.numberOfChannels;for(let i=0;i<e;i++)t.push(this.buffer.getChannelData(i));return t}removeAttribute(t){switch(t){case"src":this.src="";break;case"playbackRate":this.playbackRate=0;break;case"currentTime":this.currentTime=0;break;case"duration":this.duration=0;break;case"volume":this.volume=0;break;case"muted":this.muted=!1}}}const P={waveColor:"#999",progressColor:"#555",cursorWidth:1,minPxPerSec:0,fillParent:!0,interact:!0,dragToSeek:!1,autoScroll:!0,autoCenter:!0,sampleRate:8e3};class w extends u{static create(t){return new w(t)}getState(){return this.wavesurferState}getRenderer(){return this.renderer}constructor(t){const e=t.media||("WebAudio"===t.backend?new E:void 0);super({media:e,mediaControls:t.mediaControls,autoplay:t.autoplay,playbackRate:t.audioRate}),this.plugins=[],this.decodedData=null,this.stopAtPosition=null,this.subscriptions=[],this.mediaSubscriptions=[],this.abortController=null,this._isDestroyed=!1,this._loadVersion=0,this.reactiveCleanups=[],this.options=Object.assign({},P,t);const{state:i,actions:n}=function(t){var e,i,n,s,r,o;const a=null!==(e=null==t?void 0:t.currentTime)&&void 0!==e?e:l(0),c=null!==(i=null==t?void 0:t.duration)&&void 0!==i?i:l(0),u=null!==(n=null==t?void 0:t.isPlaying)&&void 0!==n?n:l(!1),d=null!==(s=null==t?void 0:t.isSeeking)&&void 0!==s?s:l(!1),p=null!==(r=null==t?void 0:t.volume)&&void 0!==r?r:l(1),m=null!==(o=null==t?void 0:t.playbackRate)&&void 0!==o?o:l(1),g=l(null),f=l(null),v=l(""),b=l(0),y=l(0),C=h((()=>!u.value),[u]),S=h((()=>null!==g.value),[g]),E=h((()=>S.value&&c.value>0),[S,c]),P=h((()=>a.value),[a]),w=h((()=>c.value>0?a.value/c.value:0),[a,c]);return{state:{currentTime:a,duration:c,isPlaying:u,isPaused:C,isSeeking:d,volume:p,playbackRate:m,audioBuffer:g,peaks:f,url:v,zoom:b,scrollPosition:y,canPlay:S,isReady:E,progress:P,progressPercent:w},actions:{setCurrentTime:t=>{const e=Math.max(0,Math.min(c.value||1/0,t));a.set(e)},setDuration:t=>{c.set(Math.max(0,t))},setPlaying:t=>{u.set(t)},setSeeking:t=>{d.set(t)},setVolume:t=>{const e=Math.max(0,Math.min(1,t));p.set(e)},setPlaybackRate:t=>{const e=Math.max(.1,Math.min(16,t));m.set(e)},setAudioBuffer:t=>{g.set(t),t&&c.set(t.duration)},setPeaks:t=>{f.set(t)},setUrl:t=>{v.set(t)},setZoom:t=>{b.set(Math.max(0,t))},setScrollPosition:t=>{y.set(Math.max(0,t))}}}}({isPlaying:this.isPlayingSignal,currentTime:this.currentTimeSignal,duration:this.durationSignal,volume:this.volumeSignal,playbackRate:this.playbackRateSignal,isSeeking:this.seekingSignal});this.wavesurferState=i,this.wavesurferActions=n,this.timer=new S;const s=e?void 0:this.getMediaElement();this.renderer=new C(this.options,s),this.initPlayerEvents(),this.initRendererEvents(),this.initTimerEvents(),this.initReactiveState(),this.initPlugins();const r=this.options.url||this.getSrc()||"";Promise.resolve().then((()=>{this.emit("init");const{peaks:t,duration:e}=this.options;(r||t&&e)&&this.load(r,t,e).catch((()=>{}))}))}updateProgress(t=this.getCurrentTime()){return this.renderer.renderProgress(t/this.getDuration(),this.isPlaying()),t}initTimerEvents(){this.subscriptions.push(this.timer.on("tick",(()=>{if(!this.isSeeking()){const t=this.updateProgress();if(this.emit("timeupdate",t),this.emit("audioprocess",t),null!=this.stopAtPosition&&this.isPlaying()&&t>=this.stopAtPosition){const t=this.stopAtPosition;this.pause(),this.setTime(t)}}})))}initReactiveState(){this.reactiveCleanups.push(function(t,e){const i=[];i.push(c((()=>{const i=t.isPlaying.value;e.emit(i?"play":"pause")}),[t.isPlaying])),i.push(c((()=>{const i=t.currentTime.value;e.emit("timeupdate",i),t.isPlaying.value&&e.emit("audioprocess",i)}),[t.currentTime,t.isPlaying])),i.push(c((()=>{t.isSeeking.value&&e.emit("seeking",t.currentTime.value)}),[t.isSeeking,t.currentTime]));let n=!1;i.push(c((()=>{t.isReady.value&&!n&&(n=!0,e.emit("ready",t.duration.value))}),[t.isReady,t.duration])),i.push(c((()=>{null===t.audioBuffer.value&&(n=!1)}),[t.audioBuffer]));let s=!1;return i.push(c((()=>{const i=t.isPlaying.value,n=t.currentTime.value,r=t.duration.value,o=r>0&&n>=r;s&&!i&&o&&e.emit("finish"),s=i&&o}),[t.isPlaying,t.currentTime,t.duration])),i.push(c((()=>{const i=t.zoom.value;i>0&&e.emit("zoom",i)}),[t.zoom])),()=>{i.forEach((t=>t()))}}(this.wavesurferState,{emit:this.emit.bind(this)}))}initPlayerEvents(){this.isPlaying()&&(this.emit("play"),this.timer.start()),this.mediaSubscriptions.push(this.onMediaEvent("timeupdate",(()=>{const t=this.updateProgress();this.emit("timeupdate",t)})),this.onMediaEvent("play",(()=>{this.emit("play"),this.timer.start()})),this.onMediaEvent("pause",(()=>{this.emit("pause"),this.timer.stop(),this.stopAtPosition=null})),this.onMediaEvent("emptied",(()=>{this.timer.stop(),this.stopAtPosition=null})),this.onMediaEvent("ended",(()=>{this.emit("timeupdate",this.getDuration()),this.emit("finish"),this.stopAtPosition=null})),this.onMediaEvent("seeking",(()=>{this.emit("seeking",this.getCurrentTime())})),this.onMediaEvent("error",(()=>{var t;this.emit("error",null!==(t=this.getMediaElement().error)&&void 0!==t?t:new Error("Media error")),this.stopAtPosition=null})))}initRendererEvents(){this.subscriptions.push(this.renderer.on("click",((t,e)=>{this.options.interact&&(this.seekTo(t),this.emit("interaction",t*this.getDuration()),this.emit("click",t,e))})),this.renderer.on("dblclick",((t,e)=>{this.emit("dblclick",t,e)})),this.renderer.on("scroll",((t,e,i,n)=>{const s=this.getDuration();this.emit("scroll",t*s,e*s,i,n)})),this.renderer.on("render",(()=>{this.emit("redraw")})),this.renderer.on("rendered",(()=>{this.emit("redrawcomplete")})),this.renderer.on("dragstart",(t=>{this.emit("dragstart",t)})),this.renderer.on("dragend",(t=>{this.emit("dragend",t)})),this.renderer.on("resize",(()=>{this.emit("resize")})));{let t;const e=this.renderer.on("drag",(e=>{var i;if(!this.options.interact)return;this.renderer.renderProgress(e),clearTimeout(t);let n=0;const s=this.options.dragToSeek;this.isPlaying()?n=0:!0===s?n=200:s&&"object"==typeof s&&(n=null!==(i=s.debounceTime)&&void 0!==i?i:200),t=setTimeout((()=>{this.seekTo(e)}),n),this.emit("interaction",e*this.getDuration()),this.emit("drag",e)}));this.subscriptions.push((()=>{clearTimeout(t),e()}))}}initPlugins(){var t;(null===(t=this.options.plugins)||void 0===t?void 0:t.length)&&this.options.plugins.forEach((t=>{this.registerPlugin(t)}))}unsubscribePlayerEvents(){this.mediaSubscriptions.forEach((t=>t())),this.mediaSubscriptions=[]}setOptions(t){this.options=Object.assign({},this.options,t),t.duration&&!t.peaks&&(this.decodedData=i.createBuffer(this.exportPeaks(),t.duration)),t.peaks&&t.duration&&(this.decodedData=i.createBuffer(t.peaks,t.duration)),this.renderer.setOptions(this.options),t.audioRate&&this.setPlaybackRate(t.audioRate),null!=t.mediaControls&&(this.getMediaElement().controls=t.mediaControls)}registerPlugin(t){if(this.plugins.includes(t))return t;t._init(this),this.plugins.push(t);const e=t.once("destroy",(()=>{this.plugins=this.plugins.filter((e=>e!==t)),this.subscriptions=this.subscriptions.filter((t=>t!==e))}));return this.subscriptions.push(e),t}unregisterPlugin(t){this.plugins=this.plugins.filter((e=>e!==t)),t.destroy()}getWrapper(){return this.renderer.getWrapper()}getWidth(){return this.renderer.getWidth()}getScroll(){return this.renderer.getScroll()}setScroll(t){return this.renderer.setScroll(t)}setScrollTime(t){const e=t/this.getDuration();this.renderer.setScrollPercentage(e)}getActivePlugins(){return this.plugins}loadAudio(e,n,s,r){return t(this,void 0,void 0,(function*(){var t;const o=++this._loadVersion;if(this._isDestroyed=!1,this.emit("load",e),!this.options.media&&this.isPlaying()&&this.pause(),this.decodedData=null,this.stopAtPosition=null,null===(t=this.abortController)||void 0===t||t.abort(),this.abortController=null,!n&&!s){const t=this.options.fetchParams||{};window.AbortController&&!t.signal&&(this.abortController=new AbortController,t.signal=this.abortController.signal);const i=t=>this.emit("loading",t);if(n=yield a.fetchBlob(e,i,t),this._isDestroyed||o!==this._loadVersion)return;const s=this.options.blobMimeType;s&&(n=new Blob([n],{type:s}))}if(this._isDestroyed||o!==this._loadVersion)return;this.setSrc(e,n);const l=yield new Promise((t=>{const e=r||this.getDuration();e?t(e):this.mediaSubscriptions.push(this.onMediaEvent("loadedmetadata",(()=>t(this.getDuration())),{once:!0}))}));if(!this._isDestroyed&&o===this._loadVersion){if(!e&&!n){const t=this.getMediaElement();t instanceof E&&(t.duration=l)}if(s)this.decodedData=i.createBuffer(s,l||0);else if(n){const t=yield n.arrayBuffer();if(this._isDestroyed||o!==this._loadVersion)return;this.decodedData=yield i.decode(t,this.options.sampleRate)}this._isDestroyed||o!==this._loadVersion||(this.decodedData&&(this.emit("decode",this.getDuration()),this.renderer.render(this.decodedData)),this.emit("ready",this.getDuration()))}}))}load(e,i,n){return t(this,void 0,void 0,(function*(){try{return yield this.loadAudio(e,void 0,i,n)}catch(t){throw this.emit("error",t),t}}))}loadBlob(e,i,n){return t(this,void 0,void 0,(function*(){try{return yield this.loadAudio("",e,i,n)}catch(t){throw this.emit("error",t),t}}))}zoom(t){if(!this.decodedData)throw new Error("No audio loaded");this.renderer.zoom(t),this.emit("zoom",t)}getDecodedData(){return this.decodedData}exportPeaks({channels:t=2,maxLength:e=8e3,precision:i=1e4}={}){if(!this.decodedData)throw new Error("The audio has not been decoded yet");const n=Math.min(t,this.decodedData.numberOfChannels),s=[];for(let t=0;t<n;t++){const n=this.decodedData.getChannelData(t),r=[],o=n.length/e;for(let t=0;t<e;t++){const e=n.slice(Math.floor(t*o),Math.ceil((t+1)*o));let s=0;for(let t=0;t<e.length;t++){const i=e[t];Math.abs(i)>Math.abs(s)&&(s=i)}r.push(Math.round(s*i)/i)}s.push(r)}return s}getDuration(){let t=super.getDuration()||0;return 0!==t&&t!==1/0||!this.decodedData||(t=this.decodedData.duration),t}toggleInteraction(t){this.options.interact=t}setTime(t){this.stopAtPosition=null,super.setTime(t),this.updateProgress(t),this.emit("timeupdate",t)}seekTo(t){const e=this.getDuration()*t;this.setTime(e)}play(e,i){const n=Object.create(null,{play:{get:()=>super.play}});return t(this,void 0,void 0,(function*(){null!=e&&this.setTime(e);const t=yield n.play.call(this);return null!=i&&(this.media instanceof E?this.media.stopAt(i):this.stopAtPosition=i),t}))}playPause(){return t(this,void 0,void 0,(function*(){return this.isPlaying()?this.pause():this.play()}))}stop(){this.pause(),this.setTime(0)}skip(t){this.setTime(this.getCurrentTime()+t)}empty(){this.load("",[[0]],.001)}setMediaElement(t){this.unsubscribePlayerEvents(),super.setMediaElement(t),this.initPlayerEvents()}exportImage(){return t(this,arguments,void 0,(function*(t="image/png",e=1,i="dataURL"){return this.renderer.exportImage(t,e,i)}))}destroy(){var t;this._isDestroyed=!0,this.emit("destroy"),null===(t=this.abortController)||void 0===t||t.abort(),this.plugins.forEach((t=>t.destroy())),this.subscriptions.forEach((t=>t())),this.unsubscribePlayerEvents(),this.reactiveCleanups.forEach((t=>t())),this.reactiveCleanups=[],this.timer.destroy(),this.renderer.destroy(),super.destroy()}}w.BasePlugin=class extends e{constructor(t){super(),this.subscriptions=[],this.isDestroyed=!1,this.options=t}onInit(){}_init(t){this.isDestroyed&&(this.subscriptions=[],this.isDestroyed=!1),this.wavesurfer=t,this.onInit()}destroy(){this.emit("destroy"),this.subscriptions.forEach((t=>t())),this.subscriptions=[],this.isDestroyed=!0,this.wavesurfer=void 0}},w.dom=o;
4981
4996
 
4982
- // EXTERNAL MODULE: ./src/lib/util.js + 1 modules
4983
- var util = __webpack_require__(4410);
4984
4997
  ;// ./src/lib/viewers/media/waveform/colors.ts
4985
4998
  /**
4986
4999
  * Figma Audio Player waveform tokens as opaque fills.
@@ -5617,10 +5630,10 @@ function usePlayheadCamera({
5617
5630
  };
5618
5631
  }
5619
5632
  ;// ./src/lib/viewers/controls/icons/IconComment24.tsx
5620
- function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
5633
+ function IconComment24_extends() { return IconComment24_extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, IconComment24_extends.apply(null, arguments); }
5621
5634
 
5622
5635
  function IconComment24(props) {
5623
- return /*#__PURE__*/external_react_.createElement("svg", _extends({
5636
+ return /*#__PURE__*/external_react_.createElement("svg", IconComment24_extends({
5624
5637
  "data-testid": "IconComment24",
5625
5638
  fill: "none",
5626
5639
  focusable: false,
@@ -5646,6 +5659,7 @@ function IconComment24(props) {
5646
5659
 
5647
5660
 
5648
5661
 
5662
+
5649
5663
  function offsetLeftCss(base, offsetPx) {
5650
5664
  if (!offsetPx) {
5651
5665
  return base;
@@ -5679,14 +5693,17 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5679
5693
  currentTimeSec = 0,
5680
5694
  durationSec,
5681
5695
  getPlayheadSec,
5696
+ isSwiping = false,
5682
5697
  interactive = true,
5683
5698
  isHighlighted = false,
5684
5699
  keepHighlight = true,
5685
5700
  onDragCreate,
5686
5701
  onDragChange,
5702
+ onDragPointerX,
5687
5703
  onPreviewChange,
5688
5704
  onRangeChange,
5689
5705
  range,
5706
+ readOnly = false,
5690
5707
  viewport
5691
5708
  }, ref) {
5692
5709
  const rootRef = (0,external_react_.useRef)(null);
@@ -5696,11 +5713,13 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5696
5713
  const tooltipRef = (0,external_react_.useRef)(null);
5697
5714
  const commentRef = (0,external_react_.useRef)(null);
5698
5715
  const dragRef = (0,external_react_.useRef)(null);
5716
+ const replayDragRef = (0,external_react_.useRef)(() => undefined);
5699
5717
  const rangeRef = (0,external_react_.useRef)(range);
5700
5718
  const displayedRef = (0,external_react_.useRef)((0,waveform_range/* resolveRange */.Ss)(range, (0,waveform_range/* durationMsFromSec */.uH)(durationSec)));
5701
5719
  const viewportRef = (0,external_react_.useRef)(viewport);
5702
5720
  const durationSecRef = (0,external_react_.useRef)(durationSec);
5703
5721
  const onDragChangeRef = (0,external_react_.useRef)(onDragChange);
5722
+ const onDragPointerXRef = (0,external_react_.useRef)(onDragPointerX);
5704
5723
  const onPreviewChangeRef = (0,external_react_.useRef)(onPreviewChange);
5705
5724
  const onRangeChangeRef = (0,external_react_.useRef)(onRangeChange);
5706
5725
  const getPlayheadSecRef = (0,external_react_.useRef)(getPlayheadSec);
@@ -5710,6 +5729,7 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5710
5729
  rangeRef.current = range;
5711
5730
  durationSecRef.current = durationSec;
5712
5731
  onDragChangeRef.current = onDragChange;
5732
+ onDragPointerXRef.current = onDragPointerX;
5713
5733
  onPreviewChangeRef.current = onPreviewChange;
5714
5734
  onRangeChangeRef.current = onRangeChange;
5715
5735
  getPlayheadSecRef.current = getPlayheadSec;
@@ -5717,7 +5737,7 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5717
5737
  const durationMs = (0,waveform_range/* durationMsFromSec */.uH)(durationSec);
5718
5738
  const displayed = dragRange ?? (0,waveform_range/* resolveRange */.Ss)(range, durationMs);
5719
5739
  displayedRef.current = displayed;
5720
- const showCommentButton = Boolean(onDragCreate) && displayed.startMs !== displayed.endMs && activeHandle == null;
5740
+ const showCommentButton = !readOnly && Boolean(onDragCreate) && displayed.startMs !== displayed.endMs && activeHandle == null;
5721
5741
  const syncPositions = (0,external_react_.useCallback)((next, nextViewport, nextDurationSec) => {
5722
5742
  displayedRef.current = next;
5723
5743
  const collapsed = next.startMs === next.endMs;
@@ -5735,18 +5755,27 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5735
5755
  comment.style.left = (0,waveform_viewport/* timeLeftPercent */.Mu)((next.startMs + next.endMs) / 2000, nextDurationSec, nextViewport);
5736
5756
  }
5737
5757
  }, []);
5758
+ const refreshRangePositions = (0,external_react_.useCallback)(() => {
5759
+ const drag = dragRef.current;
5760
+ if (!drag) {
5761
+ syncPositions(displayedRef.current, viewportRef.current, durationSecRef.current);
5762
+ return;
5763
+ }
5764
+ replayDragRef.current(drag.lastClientX);
5765
+ }, [syncPositions]);
5738
5766
  (0,external_react_.useImperativeHandle)(ref, () => ({
5739
5767
  applyViewport: nextViewport => {
5740
5768
  viewportRef.current = nextViewport;
5741
- syncPositions(displayedRef.current, nextViewport, durationSecRef.current);
5769
+ refreshRangePositions();
5742
5770
  }
5743
- }), [syncPositions]);
5771
+ }), [refreshRangePositions]);
5744
5772
  (0,external_react_.useLayoutEffect)(() => {
5745
5773
  syncPositions(displayedRef.current, viewportRef.current, durationSec);
5746
5774
  }, [activeHandle, displayed.endMs, displayed.startMs, durationSec, showCommentButton, syncPositions]);
5747
5775
  (0,external_react_.useLayoutEffect)(() => {
5748
5776
  const next = (0,waveform_viewport/* createWaveformViewport */.eq)({
5749
5777
  durationSec: viewport.durationSec,
5778
+ gutterPx: viewport.gutterPx,
5750
5779
  heightPx: viewport.heightPx,
5751
5780
  maxZoom: viewport.maxZoom,
5752
5781
  scrollLeftPx: viewportRef.current.scrollLeftPx,
@@ -5754,8 +5783,8 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5754
5783
  zoomLevel: viewport.zoomLevel
5755
5784
  });
5756
5785
  viewportRef.current = next;
5757
- syncPositions(displayedRef.current, next, durationSecRef.current);
5758
- }, [syncPositions, viewport.durationSec, viewport.heightPx, viewport.maxZoom, viewport.widthPx, viewport.zoomLevel]);
5786
+ refreshRangePositions();
5787
+ }, [refreshRangePositions, viewport.durationSec, viewport.gutterPx, viewport.heightPx, viewport.maxZoom, viewport.widthPx, viewport.zoomLevel]);
5759
5788
  const endDrag = (0,external_react_.useCallback)(event => {
5760
5789
  const drag = dragRef.current;
5761
5790
  if (!drag || event.pointerId && drag.pointerId !== event.pointerId) {
@@ -5770,6 +5799,7 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5770
5799
  setActiveHandle(null);
5771
5800
  setDragRange(null);
5772
5801
  onDragChangeRef.current?.(false);
5802
+ event.stopPropagation();
5773
5803
  const didChange = drag.range.startMs !== drag.originRange.startMs || drag.range.endMs !== drag.originRange.endMs;
5774
5804
  if (!didChange) {
5775
5805
  return;
@@ -5788,6 +5818,8 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5788
5818
  if (!root) {
5789
5819
  return;
5790
5820
  }
5821
+ drag.lastClientX = event.clientX;
5822
+ onDragPointerXRef.current?.(event.clientX);
5791
5823
  const rect = root.getBoundingClientRect();
5792
5824
  const pointerX = event.clientX - rect.left;
5793
5825
  const vp = viewportRef.current;
@@ -5799,6 +5831,7 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5799
5831
  timeMs: (0,waveform_range/* pointerTimeMs */.v2)(pointerX, vp)
5800
5832
  });
5801
5833
  if (drag.originMs === drag.range.startMs && drag.originMs === drag.range.endMs && pointerMs === drag.originMs) {
5834
+ syncPositions(drag.range, vp, durationSecRef.current);
5802
5835
  return;
5803
5836
  }
5804
5837
  const next = (0,waveform_range/* dragRangeHandle */.Mo)({
@@ -5820,8 +5853,18 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5820
5853
  startMs: next.range.startMs
5821
5854
  });
5822
5855
  }, [currentTimeSec, syncPositions]);
5856
+ replayDragRef.current = clientX => {
5857
+ const drag = dragRef.current;
5858
+ if (!drag || !Number.isFinite(clientX)) {
5859
+ return;
5860
+ }
5861
+ moveDrag({
5862
+ clientX,
5863
+ pointerId: drag.pointerId
5864
+ });
5865
+ };
5823
5866
  const startDrag = (0,external_react_.useCallback)((handle, event) => {
5824
- if (!interactive || event.button > 1 || event.ctrlKey || event.metaKey) {
5867
+ if (readOnly || !interactive || event.button > 1 || event.ctrlKey || event.metaKey) {
5825
5868
  return;
5826
5869
  }
5827
5870
  event.preventDefault();
@@ -5829,6 +5872,7 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5829
5872
  const resolved = (0,waveform_range/* resolveRange */.Ss)(rangeRef.current, (0,waveform_range/* durationMsFromSec */.uH)(durationSecRef.current));
5830
5873
  dragRef.current = {
5831
5874
  handle,
5875
+ lastClientX: event.clientX,
5832
5876
  originMs: handle === 'start' ? resolved.startMs : resolved.endMs,
5833
5877
  originRange: {
5834
5878
  endMs: resolved.endMs,
@@ -5837,6 +5881,7 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5837
5881
  pointerId: event.pointerId,
5838
5882
  range: resolved
5839
5883
  };
5884
+ onDragPointerXRef.current?.(event.clientX);
5840
5885
  event.currentTarget.setPointerCapture(event.pointerId);
5841
5886
  setActiveHandle(handle);
5842
5887
  setDragRange(resolved);
@@ -5845,7 +5890,7 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5845
5890
  endMs: (0,waveform_range/* isRangeCollapsed */.BT)(rangeRef.current) ? null : resolved.endMs,
5846
5891
  startMs: resolved.startMs
5847
5892
  });
5848
- }, [interactive]);
5893
+ }, [interactive, readOnly]);
5849
5894
  const onHandlePointerDown = (0,external_react_.useCallback)(event => {
5850
5895
  const root = rootRef.current;
5851
5896
  if (!root) {
@@ -5927,25 +5972,34 @@ const WaveformRangeSelection = /*#__PURE__*/(0,external_react_.forwardRef)(funct
5927
5972
  }), "Comment") : null;
5928
5973
  return /*#__PURE__*/external_react_["default"].createElement("div", {
5929
5974
  ref: rootRef,
5930
- className: `bp-WaveformRange${keepHighlight ? ' bp-WaveformRange--persist' : ''}${highlight ? ' bp-WaveformRange--highlight' : ''}`,
5975
+ className: classnames_default()('bp-WaveformRange', {
5976
+ 'bp-WaveformRange--highlight': highlight,
5977
+ 'bp-WaveformRange--persist': keepHighlight,
5978
+ 'bp-WaveformRange--swiping': collapsed && isSwiping
5979
+ }),
5931
5980
  "data-collapsed": collapsed ? 'true' : 'false',
5932
5981
  "data-highlighted": highlight ? 'true' : 'false',
5982
+ "data-readonly": readOnly ? 'true' : 'false',
5933
5983
  "data-testid": "bp-waveform-range"
5934
5984
  }, /*#__PURE__*/external_react_["default"].createElement("div", {
5935
5985
  ref: regionRef,
5936
5986
  className: "bp-WaveformRange-region",
5937
5987
  "data-testid": "bp-waveform-range-region"
5938
- }), /*#__PURE__*/external_react_["default"].createElement("div", {
5988
+ }), !readOnly && /*#__PURE__*/external_react_["default"].createElement("div", {
5939
5989
  ref: startHandleRef,
5940
- className: `bp-WaveformRange-handle bp-WaveformRange-handle--start${activeHandle === 'start' ? ' bp-WaveformRange-handle--dragging' : ''}`,
5990
+ className: classnames_default()('bp-WaveformRange-handle', 'bp-WaveformRange-handle--start', {
5991
+ 'bp-WaveformRange-handle--dragging': activeHandle === 'start'
5992
+ }),
5941
5993
  "data-testid": "bp-waveform-range-handle-start",
5942
5994
  onMouseMove: event => event.stopPropagation(),
5943
5995
  onPointerDown: onHandlePointerDown
5944
5996
  }, /*#__PURE__*/external_react_["default"].createElement("div", {
5945
5997
  className: "bp-WaveformRange-handleGrip"
5946
- })), /*#__PURE__*/external_react_["default"].createElement("div", {
5998
+ })), !readOnly && /*#__PURE__*/external_react_["default"].createElement("div", {
5947
5999
  ref: endHandleRef,
5948
- className: `bp-WaveformRange-handle bp-WaveformRange-handle--end${activeHandle === 'end' ? ' bp-WaveformRange-handle--dragging' : ''}`,
6000
+ className: classnames_default()('bp-WaveformRange-handle', 'bp-WaveformRange-handle--end', {
6001
+ 'bp-WaveformRange-handle--dragging': activeHandle === 'end'
6002
+ }),
5949
6003
  "data-testid": "bp-waveform-range-handle-end",
5950
6004
  onMouseMove: event => event.stopPropagation(),
5951
6005
  onPointerDown: onHandlePointerDown
@@ -6140,6 +6194,7 @@ function WaveformView({
6140
6194
  onZoomChange,
6141
6195
  peaks,
6142
6196
  range = null,
6197
+ rangeReadOnly = false,
6143
6198
  zoomLevel: zoomLevelProp
6144
6199
  }) {
6145
6200
  // DOM / WaveSurfer
@@ -6212,8 +6267,9 @@ function WaveformView({
6212
6267
  const isRangeDraggingRef = (0,external_react_.useRef)(false);
6213
6268
  const rangeRef = (0,external_react_.useRef)(range); // latest committed draft; drag-create must not start on top of an open span
6214
6269
  const createDragRef = (0,external_react_.useRef)(null);
6270
+ const rangeDragPointerXRef = (0,external_react_.useRef)(null); // clientX while a handle or create-drag is down
6215
6271
  const removeCreateDragListenersRef = (0,external_react_.useRef)(null);
6216
- const skipNextSeekRef = (0,external_react_.useRef)(false);
6272
+ const skipNextSeekRef = (0,external_react_.useRef)(false); // ignore the click fired when a handle is released
6217
6273
  const lastSetTimeSecRef = (0,external_react_.useRef)(null);
6218
6274
  const [isRangeHovered, setIsRangeHovered] = (0,external_react_.useState)(false);
6219
6275
  const isControlled = typeof zoomLevelProp === 'number';
@@ -6287,11 +6343,19 @@ function WaveformView({
6287
6343
  viewportRef,
6288
6344
  wavesurferRef
6289
6345
  });
6346
+ const suppressTapToPlayPause = (0,external_react_.useCallback)(() => {
6347
+ suppressNextTapPlayPauseRef.current = true;
6348
+ window.clearTimeout(suppressNextTapPlayPauseTimerRef.current);
6349
+ suppressNextTapPlayPauseTimerRef.current = window.setTimeout(() => {
6350
+ suppressNextTapPlayPauseRef.current = false;
6351
+ suppressNextTapPlayPauseTimerRef.current = 0;
6352
+ }, constants/* WAVEFORM_TAPE_CLICK_SUPPRESS_MS */.fI);
6353
+ }, []);
6290
6354
  const toggleTapePlayback = (0,external_react_.useCallback)(() => {
6291
6355
  if (!interactiveRef.current) {
6292
6356
  return;
6293
6357
  }
6294
- if (isUserPanning() || pointerZoomRef.current) {
6358
+ if (isUserPanning() || pointerZoomRef.current || isRangeDraggingRef.current) {
6295
6359
  return;
6296
6360
  }
6297
6361
  if (suppressNextTapPlayPauseRef.current) {
@@ -6301,13 +6365,8 @@ function WaveformView({
6301
6365
  return;
6302
6366
  }
6303
6367
  onPlayPauseRef.current?.(!isPlayingRef.current);
6304
- suppressNextTapPlayPauseRef.current = true;
6305
- window.clearTimeout(suppressNextTapPlayPauseTimerRef.current);
6306
- suppressNextTapPlayPauseTimerRef.current = window.setTimeout(() => {
6307
- suppressNextTapPlayPauseRef.current = false;
6308
- suppressNextTapPlayPauseTimerRef.current = 0;
6309
- }, constants/* WAVEFORM_TAPE_CLICK_SUPPRESS_MS */.fI);
6310
- }, [isUserPanning]);
6368
+ suppressTapToPlayPause();
6369
+ }, [isUserPanning, suppressTapToPlayPause]);
6311
6370
  toggleTapePlaybackRef.current = toggleTapePlayback;
6312
6371
  (0,external_react_.useLayoutEffect)(() => {
6313
6372
  viewportRef.current = (0,waveform_viewport/* createWaveformViewport */.eq)({
@@ -6513,12 +6572,13 @@ function WaveformView({
6513
6572
  onSeekRef.current?.(timeSec);
6514
6573
  });
6515
6574
  const unsubscribeScroll = wavesurfer.on('scroll', () => {
6516
- if (suppressViewportSyncRef.current) {
6575
+ if (suppressViewportSyncRef.current || isRangeDraggingRef.current) {
6576
+ // A handle drag scrolls from its own frame loop. A pan settle would pull it back.
6517
6577
  return;
6518
6578
  }
6519
6579
  // User pan: map scroll to the time under the playhead, then tape seeks it.
6520
6580
  handleCameraScroll(timeSec => {
6521
- if (cameraModeRef.current === 'tape' && !pointerZoomRef.current) {
6581
+ if (cameraModeRef.current === 'tape' && !pointerZoomRef.current && !createDragRef.current) {
6522
6582
  handleTapeSwipe(timeSec);
6523
6583
  }
6524
6584
  syncViewport();
@@ -6638,14 +6698,18 @@ function WaveformView({
6638
6698
  const tick = () => {
6639
6699
  if (!media.paused) {
6640
6700
  updatePlayheadPosition(media.currentTime);
6641
- applyPlayheadCamera(media.currentTime, false);
6701
+ if (!isRangeDraggingRef.current) {
6702
+ applyPlayheadCamera(media.currentTime, false);
6703
+ }
6642
6704
  }
6643
6705
  playheadAnimationRef.current = window.requestAnimationFrame(tick);
6644
6706
  };
6645
6707
  const startLoop = () => {
6646
6708
  window.cancelAnimationFrame(playheadAnimationRef.current);
6647
6709
  releaseUserPanHold();
6648
- applyPlayheadCamera(media.currentTime, true);
6710
+ if (!isRangeDraggingRef.current) {
6711
+ applyPlayheadCamera(media.currentTime, true);
6712
+ }
6649
6713
  playheadAnimationRef.current = window.requestAnimationFrame(tick);
6650
6714
  };
6651
6715
  const stopLoop = () => {
@@ -6660,7 +6724,7 @@ function WaveformView({
6660
6724
  };
6661
6725
  const handleSeeked = () => {
6662
6726
  onPlayheadSeek(media.currentTime);
6663
- if (!isUserPanning()) {
6727
+ if (!isUserPanning() && !isRangeDraggingRef.current) {
6664
6728
  seekTo(media.currentTime);
6665
6729
  }
6666
6730
  updatePlayheadPosition(media.currentTime);
@@ -6845,9 +6909,12 @@ function WaveformView({
6845
6909
  const handleRangeDragChange = (0,external_react_.useCallback)(isDragging => {
6846
6910
  isRangeDraggingRef.current = isDragging;
6847
6911
  setIsRangeDragging(isDragging);
6912
+ suppressTapToPlayPause();
6913
+ cancelJump();
6848
6914
  if (isDragging) {
6849
6915
  setHoverProgress(null);
6850
6916
  } else {
6917
+ rangeDragPointerXRef.current = null;
6851
6918
  skipNextSeekRef.current = true;
6852
6919
  window.setTimeout(() => {
6853
6920
  skipNextSeekRef.current = false;
@@ -6855,7 +6922,60 @@ function WaveformView({
6855
6922
  setPreviewRange(null);
6856
6923
  }
6857
6924
  onRangeDragChange?.(isDragging);
6858
- }, [onRangeDragChange]);
6925
+ }, [cancelJump, onRangeDragChange, suppressTapToPlayPause]);
6926
+ (0,external_react_.useEffect)(() => {
6927
+ if (!isTape || !isRangeDragging) {
6928
+ return undefined;
6929
+ }
6930
+ let frameId = 0;
6931
+ let previousFrameMs = 0;
6932
+ let hasPreviousFrame = false;
6933
+ let pendingScrollPx = 0;
6934
+ const getPointerInTrack = () => {
6935
+ const track = trackRef.current;
6936
+ const pointerClientX = rangeDragPointerXRef.current;
6937
+ if (!track || pointerClientX == null || !Number.isFinite(pointerClientX)) {
6938
+ return null;
6939
+ }
6940
+ const rect = track.getBoundingClientRect();
6941
+ return {
6942
+ width: rect.width,
6943
+ x: pointerClientX - rect.left
6944
+ };
6945
+ };
6946
+ const scrollWhileHandleAtEdge = frameMs => {
6947
+ const rawElapsedSec = hasPreviousFrame ? Math.max(0, (frameMs - previousFrameMs) / 1000) : 0;
6948
+ const elapsedSec = Math.min(rawElapsedSec, constants/* WAVEFORM_RANGE_EDGE_SCROLL_MAX_FRAME_SEC */.bf);
6949
+ hasPreviousFrame = true;
6950
+ previousFrameMs = frameMs;
6951
+ const pointer = getPointerInTrack();
6952
+ const viewport = viewportRef.current;
6953
+ const scrollDeltaPx = pointer ? (0,waveform_viewport/* getRangeEdgeScrollDeltaPx */.CD)({
6954
+ elapsedSec,
6955
+ pixelsPerSecond: viewport.pixelsPerSecond,
6956
+ pointerX: pointer.x,
6957
+ widthPx: pointer.width
6958
+ }) : null;
6959
+ if (scrollDeltaPx == null) {
6960
+ pendingScrollPx = 0;
6961
+ } else {
6962
+ pendingScrollPx += scrollDeltaPx;
6963
+ const nextScroll = Math.min((0,waveform_viewport/* maxScrollLeft */.d0)(viewport), Math.max(0, viewport.scrollLeftPx + pendingScrollPx));
6964
+ const scrolledPx = nextScroll - viewport.scrollLeftPx;
6965
+ pendingScrollPx = scrolledPx === 0 ? 0 : pendingScrollPx - scrolledPx;
6966
+ if (scrolledPx !== 0) {
6967
+ applyScrollLeft(nextScroll, true);
6968
+ const nextViewport = viewportRef.current;
6969
+ onSeekRef.current?.((0,waveform_viewport/* timeFromPositionPx */.lZ)(nextViewport.widthPx / 2, nextViewport));
6970
+ }
6971
+ }
6972
+ frameId = window.requestAnimationFrame(scrollWhileHandleAtEdge);
6973
+ };
6974
+ frameId = window.requestAnimationFrame(scrollWhileHandleAtEdge);
6975
+ return () => {
6976
+ window.cancelAnimationFrame(frameId);
6977
+ };
6978
+ }, [applyScrollLeft, isRangeDragging, isTape]);
6859
6979
  const getPlayheadSec = (0,external_react_.useCallback)(() => {
6860
6980
  return mediaElRef.current ? mediaElRef.current.currentTime : currentTimeRef.current;
6861
6981
  }, []);
@@ -6956,6 +7076,7 @@ function WaveformView({
6956
7076
  }, []);
6957
7077
  const hoverLeft = isRangeDragging || hoverProgress == null ? null : (0,waveform_viewport/* timeLeftPercent */.Mu)(hoverProgress * durationSec, durationSec, viewportRef.current);
6958
7078
  const overlayRange = createRange ?? range;
7079
+ const isOverlayReadOnly = rangeReadOnly && createRange == null;
6959
7080
  const showRangeOverlay = Boolean(overlayRange) && (isRangeDragging || !isPlaying || !(0,waveform_range/* isRangeCollapsed */.BT)(overlayRange));
6960
7081
  const scrubTimeChip = isTape && scrubPreviewTimeSec != null ? /*#__PURE__*/external_react_["default"].createElement("div", {
6961
7082
  className: "bp-WaveformView-hover bp-WaveformView-hover--tape",
@@ -7004,14 +7125,19 @@ function WaveformView({
7004
7125
  currentTimeSec: currentTime,
7005
7126
  durationSec: durationSec,
7006
7127
  getPlayheadSec: getPlayheadSec,
7007
- interactive: interactive,
7128
+ interactive: interactive && !isOverlayReadOnly,
7008
7129
  isHighlighted: isRangeDragging || isRangeHovered,
7130
+ isSwiping: isTape && scrubPreviewTimeSec != null,
7009
7131
  keepHighlight: true,
7010
7132
  onDragChange: handleRangeDragChange,
7011
- onDragCreate: interactive && !isRangeDragging ? onRangeDragCreate : undefined,
7133
+ onDragCreate: interactive && !isRangeDragging && !isOverlayReadOnly ? onRangeDragCreate : undefined,
7134
+ onDragPointerX: clientX => {
7135
+ rangeDragPointerXRef.current = clientX;
7136
+ },
7012
7137
  onPreviewChange: setPreviewRange,
7013
- onRangeChange: interactive ? onRangeChange : undefined,
7138
+ onRangeChange: interactive && !isOverlayReadOnly ? onRangeChange : undefined,
7014
7139
  range: overlayRange,
7140
+ readOnly: isOverlayReadOnly,
7015
7141
  viewport: viewport
7016
7142
  }), hoverLeft != null && hoverProgress != null && !isRangeDragging && /*#__PURE__*/external_react_["default"].createElement("div", {
7017
7143
  className: "bp-WaveformView-hover",
@@ -7260,12 +7386,14 @@ function WaveformZoomControl({
7260
7386
 
7261
7387
 
7262
7388
 
7389
+
7263
7390
  const PLACEHOLDER_PEAKS = placeholderPeaks();
7264
7391
  function MP3ControlsV2({
7265
7392
  autoplay,
7266
7393
  bufferedRange,
7267
7394
  commentMarkers,
7268
7395
  commentRangeDraft = null,
7396
+ commentRangeReadOnly = null,
7269
7397
  currentTime,
7270
7398
  durationTime,
7271
7399
  hasStartedPlayback = false,
@@ -7289,6 +7417,8 @@ function MP3ControlsV2({
7289
7417
  peaks,
7290
7418
  playNext,
7291
7419
  rate,
7420
+ shuttleDirection = null,
7421
+ shuttleRate = 0,
7292
7422
  volume
7293
7423
  }) {
7294
7424
  const durationValue = typeof durationTime === 'number' && isFinite_default()(durationTime) ? durationTime : 0;
@@ -7304,7 +7434,7 @@ function MP3ControlsV2({
7304
7434
  const waveformDurationSec = hasWaveformDuration ? durationValue : PLACEHOLDER_DURATION_SEC;
7305
7435
  const [playRequested, setPlayRequested] = (0,external_react_.useState)(hasStartedPlayback);
7306
7436
  const [viewport, setViewport] = (0,external_react_.useState)(null);
7307
- const isTape = useTapeWaveform();
7437
+ const isTape = (0,useTapeWaveform/* default */.Ay)();
7308
7438
  const hasAppliedTapeDefaultZoomRef = (0,external_react_.useRef)(false); // ~10s window applied; reset to 1× when leaving tape
7309
7439
  const lastKeyboardZoomStepRef = (0,external_react_.useRef)(0); // last +/− step applied; skip re-step when maxZoom retriggers the effect
7310
7440
  const userChangedTapeZoomRef = (0,external_react_.useRef)(false); // pinch/wheel zoom; skip re-applying the 10s default
@@ -7373,6 +7503,8 @@ function MP3ControlsV2({
7373
7503
  // Overlay unmounts on click; without this, focus lands on body and Space is lost.
7374
7504
  mediaEl?.closest('.bp-media-container')?.focus();
7375
7505
  }, [mediaEl, onPlayPause]);
7506
+ const waveformRange = commentRangeDraft ?? commentRangeReadOnly;
7507
+ const isRangeReadOnly = commentRangeDraft == null && commentRangeReadOnly != null;
7376
7508
  const waveformMarkers = (0,external_react_.useMemo)(() => commentMarkers || [], [commentMarkers]);
7377
7509
  const selectedMarkerId = (0,external_react_.useMemo)(() => waveformMarkers.find(marker => marker.isSelected)?.id ?? null, [waveformMarkers]);
7378
7510
  const handleCommentMarkerClick = (0,external_react_.useCallback)(marker => {
@@ -7391,6 +7523,7 @@ function MP3ControlsV2({
7391
7523
  const hasZoomHandlers = hasRealPeaks && !showPlayOverlay;
7392
7524
  const hasZoomControl = hasZoomHandlers && hasMediaMetadata && maxZoom > constants/* WAVEFORM_ZOOM_MIN */.LW;
7393
7525
  const showGeneratingWaveformIndicator = isGeneratingWaveform && !hasRealPeaks;
7526
+ const showShuttle = !isTape && !!shuttleDirection && shuttleRate > 0;
7394
7527
  const waveformZoomLevel = isTape || hasZoomHandlers ? zoomLevel : constants/* WAVEFORM_ZOOM_MIN */.LW;
7395
7528
  return /*#__PURE__*/external_react_["default"].createElement("div", {
7396
7529
  className: "bp-MP3ControlsV2",
@@ -7416,7 +7549,8 @@ function MP3ControlsV2({
7416
7549
  onViewportChange: hasRealPeaks ? handleViewportChange : undefined,
7417
7550
  onZoomChange: hasZoomHandlers ? handleWaveformZoom : undefined,
7418
7551
  peaks: waveformPeaks,
7419
- range: commentRangeDraft,
7552
+ range: waveformRange,
7553
+ rangeReadOnly: isRangeReadOnly,
7420
7554
  zoomLevel: waveformZoomLevel
7421
7555
  }), /*#__PURE__*/external_react_["default"].createElement(WaveformCommentMarkers, {
7422
7556
  commentMarkers: waveformMarkers,
@@ -7425,7 +7559,10 @@ function MP3ControlsV2({
7425
7559
  onCommentMarkerClick: handleCommentMarkerClick,
7426
7560
  selectedId: selectedMarkerId,
7427
7561
  viewport: viewport
7428
- })), (showGeneratingWaveformIndicator || hasZoomControl) && /*#__PURE__*/external_react_["default"].createElement("div", {
7562
+ })), showShuttle && shuttleDirection && /*#__PURE__*/external_react_["default"].createElement(WaveformShuttleIndicator, {
7563
+ direction: shuttleDirection,
7564
+ rate: shuttleRate
7565
+ }), (showGeneratingWaveformIndicator || hasZoomControl) && /*#__PURE__*/external_react_["default"].createElement("div", {
7429
7566
  className: "bp-MP3ControlsV2-waveformZoom"
7430
7567
  }, showGeneratingWaveformIndicator ? /*#__PURE__*/external_react_["default"].createElement(WaveformGeneratingIndicator, null) : /*#__PURE__*/external_react_["default"].createElement(WaveformZoomControl, {
7431
7568
  isRevealed: isZoomRevealed,
@@ -7566,11 +7703,14 @@ function isFpsAvailable(player) {
7566
7703
  /* harmony export */ LW: () => (/* binding */ WAVEFORM_ZOOM_MIN),
7567
7704
  /* harmony export */ Le: () => (/* binding */ TAPE_POINTER_MEDIA_QUERY),
7568
7705
  /* harmony export */ Lu: () => (/* binding */ WAVEFORM_BAR_GAP),
7706
+ /* harmony export */ MR: () => (/* binding */ WAVEFORM_RANGE_EDGE_ZONE_PX),
7569
7707
  /* harmony export */ NM: () => (/* binding */ WAVEFORM_FOLLOW_INSET_PX),
7570
7708
  /* harmony export */ QD: () => (/* binding */ WAVEFORM_ZOOM_BUTTON_STEP),
7709
+ /* harmony export */ VS: () => (/* binding */ WAVEFORM_RANGE_EDGE_SCROLL_AUDIO_SEC_PER_SEC),
7571
7710
  /* harmony export */ XS: () => (/* binding */ WAVEFORM_BAR_MIN_HEIGHT),
7572
7711
  /* harmony export */ Zs: () => (/* binding */ WAVEFORM_FOLLOW_SCROLL_SETTLE_MS),
7573
7712
  /* harmony export */ bX: () => (/* binding */ WAVEFORM_RANGE_MIN_DURATION_MS),
7713
+ /* harmony export */ bf: () => (/* binding */ WAVEFORM_RANGE_EDGE_SCROLL_MAX_FRAME_SEC),
7574
7714
  /* harmony export */ f3: () => (/* binding */ CLIENT_DECODE_PEAK_COUNT),
7575
7715
  /* harmony export */ fI: () => (/* binding */ WAVEFORM_TAPE_CLICK_SUPPRESS_MS),
7576
7716
  /* harmony export */ h1: () => (/* binding */ WAVEFORM_RANGE_HANDLE_LINE_PX),
@@ -7653,6 +7793,12 @@ const WAVEFORM_RANGE_SNAP_PX = 8;
7653
7793
  const WAVEFORM_RANGE_MIN_DURATION_MS = 250;
7654
7794
  /** Pointer travel before a waveform press becomes a new draft range. Shorter presses stay click-to-seek. */
7655
7795
  const WAVEFORM_RANGE_CREATE_DRAG_PX = 4;
7796
+ /** Drag a handle inside this many CSS pixels of either view edge and the tape scrolls. */
7797
+ const WAVEFORM_RANGE_EDGE_ZONE_PX = 100;
7798
+ /** Audio seconds moved per wall-clock second when the pointer is on the view edge. */
7799
+ const WAVEFORM_RANGE_EDGE_SCROLL_AUDIO_SEC_PER_SEC = 4;
7800
+ /** Longest gap one edge-scroll frame may apply. A stalled timestamp must not jump the playhead. */
7801
+ const WAVEFORM_RANGE_EDGE_SCROLL_MAX_FRAME_SEC = 0.05;
7656
7802
  const WAVEFORM_RANGE_GRIP_IN_MS = 150;
7657
7803
  const WAVEFORM_RANGE_GRIP_OUT_MS = 100;
7658
7804
 
@@ -7706,6 +7852,8 @@ function isWaveformErrorCode(value) {
7706
7852
 
7707
7853
  /** Desktop walks then pins near the right inset. Tape keeps the playhead at center. */
7708
7854
 
7855
+ /** J scans backward, L scans forward. Absent when shuttle is off. */
7856
+
7709
7857
  /** One canvas linear-gradient stop. `offset` is 0–1 along the bar. */
7710
7858
 
7711
7859
  /**
@@ -8448,6 +8596,55 @@ function rangeProgress(range, durationMs) {
8448
8596
 
8449
8597
  /***/ },
8450
8598
 
8599
+ /***/ 7308
8600
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
8601
+
8602
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8603
+ /* harmony export */ Ay: () => (/* binding */ useTapeWaveform),
8604
+ /* harmony export */ MQ: () => (/* binding */ isTapeWaveformInput)
8605
+ /* harmony export */ });
8606
+ /* unused harmony exports isIPadNavigator, isCoarsePrimaryPointer */
8607
+ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1649);
8608
+ /* harmony import */ var _constants__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4929);
8609
+
8610
+
8611
+ function isIPadNavigator(tapeNavigator) {
8612
+ return /iPad/i.test(tapeNavigator.userAgent || '') || tapeNavigator.platform === 'MacIntel' && (tapeNavigator.maxTouchPoints || 0) > 1;
8613
+ }
8614
+ function isCoarsePrimaryPointer(tapeWindow) {
8615
+ return typeof tapeWindow.matchMedia === 'function' && tapeWindow.matchMedia(_constants__WEBPACK_IMPORTED_MODULE_1__/* .TAPE_POINTER_MEDIA_QUERY */ .Le).matches;
8616
+ }
8617
+
8618
+ /**
8619
+ * Tape vs desktop camera: coarse primary pointer (finger) or iPad
8620
+ * (including iPadOS reporting itself as Mac). Not width, not hasTouch,
8621
+ * not Browser.isMobile().
8622
+ */
8623
+ function isTapeWaveformInput(tapeWindow = window) {
8624
+ return isCoarsePrimaryPointer(tapeWindow) || isIPadNavigator(tapeWindow.navigator);
8625
+ }
8626
+
8627
+ /** Subscribe to the pointer media query; re-read the iPad heuristic on change. */
8628
+ function useTapeWaveform() {
8629
+ const [isTape, setIsTape] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(() => typeof window !== 'undefined' && isTapeWaveformInput(window));
8630
+ (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
8631
+ if (typeof window.matchMedia !== 'function') {
8632
+ setIsTape(isTapeWaveformInput(window));
8633
+ return undefined;
8634
+ }
8635
+ const mediaQuery = window.matchMedia(_constants__WEBPACK_IMPORTED_MODULE_1__/* .TAPE_POINTER_MEDIA_QUERY */ .Le);
8636
+ const sync = () => {
8637
+ setIsTape(isTapeWaveformInput(window));
8638
+ };
8639
+ sync();
8640
+ mediaQuery.addEventListener('change', sync);
8641
+ return () => mediaQuery.removeEventListener('change', sync);
8642
+ }, []);
8643
+ return isTape;
8644
+ }
8645
+
8646
+ /***/ },
8647
+
8451
8648
  /***/ 1053
8452
8649
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
8453
8650
 
@@ -8639,6 +8836,7 @@ function isRetryableWaveformError(code) {
8639
8836
  (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
8640
8837
 
8641
8838
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
8839
+ /* harmony export */ CD: () => (/* binding */ getRangeEdgeScrollDeltaPx),
8642
8840
  /* harmony export */ Iw: () => (/* binding */ sliderValueFromZoom),
8643
8841
  /* harmony export */ J$: () => (/* binding */ getZoomedPixelsPerSecond),
8644
8842
  /* harmony export */ KH: () => (/* binding */ viewportEquals),
@@ -8929,6 +9127,30 @@ function getTapePinnedPlayheadLeft() {
8929
9127
  return '50%';
8930
9128
  }
8931
9129
 
9130
+ /**
9131
+ * Pixels to scroll this frame while a range handle is held in the edge zone.
9132
+ * Negative moves toward the start of the file. Null means the pointer is outside the zone.
9133
+ */
9134
+ function getRangeEdgeScrollDeltaPx({
9135
+ audioSecPerSec = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_EDGE_SCROLL_AUDIO_SEC_PER_SEC */ .VS,
9136
+ elapsedSec,
9137
+ edgeZonePx = _constants__WEBPACK_IMPORTED_MODULE_0__/* .WAVEFORM_RANGE_EDGE_ZONE_PX */ .MR,
9138
+ pixelsPerSecond,
9139
+ pointerX,
9140
+ widthPx
9141
+ }) {
9142
+ if (!(widthPx > 0) || !(elapsedSec > 0) || !(edgeZonePx > 0) || !(pixelsPerSecond > 0)) {
9143
+ return null;
9144
+ }
9145
+ const distanceFromEdgePx = Math.min(pointerX, widthPx - pointerX);
9146
+ if (distanceFromEdgePx >= edgeZonePx) {
9147
+ return null;
9148
+ }
9149
+ const intensity = 1 - distanceFromEdgePx / edgeZonePx;
9150
+ const direction = pointerX < widthPx / 2 ? -1 : 1;
9151
+ return direction * pixelsPerSecond * audioSecPerSec * elapsedSec * intensity;
9152
+ }
9153
+
8932
9154
  /** CSS left % of the playhead from the left of the visible window. */
8933
9155
  function timeLeftPercent(timeSec, durationSec, viewport) {
8934
9156
  if (viewport.widthPx > 0 && viewport.pixelsPerSecond > 0) {
@@ -24661,7 +24883,7 @@ class Browser {
24661
24883
  ;// ./src/lib/Logger.js
24662
24884
  /* eslint-disable no-undef */
24663
24885
  const CLIENT_NAME = "box-content-preview";
24664
- const CLIENT_VERSION = "3.96.0";
24886
+ const CLIENT_VERSION = "3.98.0";
24665
24887
  /* eslint-enable no-undef */
24666
24888
 
24667
24889
  class Logger {
@@ -33887,6 +34109,27 @@ class TextLoader extends viewers_AssetLoader {
33887
34109
  }
33888
34110
  }
33889
34111
  /* harmony default export */ const text_TextLoader = (new TextLoader());
34112
+ ;// ./src/lib/viewers/controls/media/markers/helpers/commentMarkerRange.ts
34113
+ /**
34114
+ * Turn a host comment marker into the waveform range for a read-only span.
34115
+ * `comment_markers` uses seconds (`time` is the start, `endTime` the end); the
34116
+ * waveform draws `{ startMs, endMs }`. A point comment, or a span whose end is
34117
+ * not after the start, has no range, so the viewer only seeks.
34118
+ */
34119
+ function commentMarkerRange(marker) {
34120
+ if (!marker || !Number.isFinite(marker.time) || marker.endTime == null || !Number.isFinite(marker.endTime)) {
34121
+ return null;
34122
+ }
34123
+ const startMs = Math.round(marker.time * 1000);
34124
+ const endMs = Math.round(marker.endTime * 1000);
34125
+ if (!(endMs > startMs)) {
34126
+ return null;
34127
+ }
34128
+ return {
34129
+ endMs,
34130
+ startMs
34131
+ };
34132
+ }
33890
34133
  ;// ./src/lib/viewers/controls/media/types.ts
33891
34134
  /**
33892
34135
  * Draft range drawn on the waveform. Sidebar sends `comment_range_draft`
@@ -37442,6 +37685,8 @@ var waveform_constants = __webpack_require__(4929);
37442
37685
  var createWaveformLoader = __webpack_require__(4971);
37443
37686
  // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/range.ts
37444
37687
  var range = __webpack_require__(4253);
37688
+ // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/useTapeWaveform.ts
37689
+ var useTapeWaveform = __webpack_require__(7308);
37445
37690
  // EXTERNAL MODULE: ./src/lib/viewers/media/waveform/validateWaveformPayload.ts
37446
37691
  var validateWaveformPayload = __webpack_require__(1053);
37447
37692
  ;// ./src/lib/viewers/media/MP3.scss
@@ -37465,6 +37710,8 @@ function MP3Viewer_toPrimitive(t, r) { if ("object" != typeof t || !t) return t;
37465
37710
 
37466
37711
 
37467
37712
 
37713
+
37714
+
37468
37715
  const CSS_CLASS_MP3 = 'bp-media-mp3';
37469
37716
  const AUDIO_V2_SHUTTLE_RATES = [2, 4, 8, 16];
37470
37717
  const AUDIO_V2_SHUTTLE_TICK_MS = 50;
@@ -37562,6 +37809,7 @@ class MP3Viewer extends media_MediaBaseViewer {
37562
37809
  if (selected) {
37563
37810
  if (selected.id !== this.hostSelectedMarkerId) {
37564
37811
  this.hostSelectedMarkerId = selected.id;
37812
+ this.commentRangeReadOnly = commentMarkerRange(selected);
37565
37813
  if (Number.isFinite(selected.time)) {
37566
37814
  this.pendingHostSelectedSeek = selected;
37567
37815
  this.applyPendingHostSelectedSeek();
@@ -37570,6 +37818,7 @@ class MP3Viewer extends media_MediaBaseViewer {
37570
37818
  } else if (this.hostSelectedMarkerId && !markers.some(marker => marker.id === this.hostSelectedMarkerId)) {
37571
37819
  this.hostSelectedMarkerId = null;
37572
37820
  this.pendingHostSelectedSeek = null;
37821
+ this.commentRangeReadOnly = null;
37573
37822
  }
37574
37823
  this.renderUI();
37575
37824
  });
@@ -37639,21 +37888,19 @@ class MP3Viewer extends media_MediaBaseViewer {
37639
37888
  this.isCommentRangeDragging = !!isDragging;
37640
37889
  });
37641
37890
  MP3Viewer_defineProperty(this, "handleCommentRangeClear", () => {
37642
- if (!this.commentRangeDraft || this.commentRangeDraft.endMs == null) {
37891
+ const clearedDraftRange = this.clearOpenCommentRangeDraft();
37892
+ const clearedReadOnlyRange = this.commentRangeReadOnly != null;
37893
+ this.commentRangeReadOnly = null;
37894
+ if (!clearedDraftRange && !clearedReadOnlyRange) {
37643
37895
  return;
37644
37896
  }
37645
- const notifyHost = this.isCommentRangeTimestampActive;
37646
- this.commentRangeDraft = null;
37647
- this.isCommentRangeTimestampActive = false;
37648
- if (notifyHost) {
37649
- this.emit(EVENT_COMMENT_RANGE_DRAFT_DISMISS);
37650
- }
37651
37897
  this.syncCommentRangeLoop();
37652
37898
  this.renderUI();
37653
37899
  });
37654
37900
  MP3Viewer_defineProperty(this, "handleCommentMarkerClick", marker => {
37655
37901
  this.exitShuttle();
37656
37902
  this.hostSelectedMarkerId = marker.id;
37903
+ this.commentRangeReadOnly = commentMarkerRange(marker);
37657
37904
  this.pendingHostSelectedSeek = marker;
37658
37905
  if (this.mediaEl) {
37659
37906
  this.mediaEl.pause();
@@ -37709,6 +37956,7 @@ class MP3Viewer extends media_MediaBaseViewer {
37709
37956
  this.mediaEl.setAttribute('preload', 'auto');
37710
37957
  this.commentMarkers = [];
37711
37958
  this.commentRangeDraft = null;
37959
+ this.commentRangeReadOnly = null;
37712
37960
  this.hostSelectedMarkerId = null;
37713
37961
  this.isCommentRangeDragging = false;
37714
37962
  this.isCommentRangeTimestampActive = false;
@@ -37851,6 +38099,9 @@ class MP3Viewer extends media_MediaBaseViewer {
37851
38099
  this.handlePlayRequest();
37852
38100
  }
37853
38101
  shuttle(direction) {
38102
+ if ((0,useTapeWaveform/* isTapeWaveformInput */.MQ)()) {
38103
+ return;
38104
+ }
37854
38105
  const sameDirection = this.shuttleDirection === direction;
37855
38106
  const rate = nextShuttleRate(this.shuttleRate, sameDirection);
37856
38107
  if (direction === 'forward') {
@@ -37877,6 +38128,7 @@ class MP3Viewer extends media_MediaBaseViewer {
37877
38128
  }).catch(() => {});
37878
38129
  }
37879
38130
  this.scheduleCommentRangeLoopWrap(true);
38131
+ this.renderUI();
37880
38132
  }
37881
38133
  startReverseShuttle(rate) {
37882
38134
  this.stopReverseShuttle();
@@ -37896,6 +38148,7 @@ class MP3Viewer extends media_MediaBaseViewer {
37896
38148
  this.exitShuttle();
37897
38149
  }
37898
38150
  }, AUDIO_V2_SHUTTLE_TICK_MS);
38151
+ this.renderUI();
37899
38152
  }
37900
38153
  stopReverseShuttle() {
37901
38154
  if (this.reverseShuttleTimer) {
@@ -37999,7 +38252,7 @@ class MP3Viewer extends media_MediaBaseViewer {
37999
38252
  * @return {Promise<{ default: Function }>} MP3ControlsV2 module
38000
38253
  */
38001
38254
  importV2Controls() {
38002
- return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 8862));
38255
+ return Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 2460));
38003
38256
  }
38004
38257
 
38005
38258
  /**
@@ -38026,6 +38279,7 @@ class MP3Viewer extends media_MediaBaseViewer {
38026
38279
  this.removeListener(EVENT_COMMENT_RANGE_DRAFT, this.handleCommentRangeDraft);
38027
38280
  this.removeListener(EVENT_COMMENT_RANGE_DRAFT_CLEAR, this.handleCommentRangeDraftClear);
38028
38281
  this.commentRangeDraft = null;
38282
+ this.commentRangeReadOnly = null;
38029
38283
  this.isCommentRangeDragging = false;
38030
38284
  this.isCommentRangeTimestampActive = false;
38031
38285
  this.stopReverseShuttle();
@@ -38042,6 +38296,7 @@ class MP3Viewer extends media_MediaBaseViewer {
38042
38296
  if (this.isAudioPlayerV2) {
38043
38297
  // A file-version switch is a clear, not a resync of the previous draft.
38044
38298
  this.commentRangeDraft = null;
38299
+ this.commentRangeReadOnly = null;
38045
38300
  this.isCommentRangeDragging = false;
38046
38301
  this.isCommentRangeTimestampActive = false;
38047
38302
  this.syncCommentRangeLoop();
@@ -38466,30 +38721,52 @@ class MP3Viewer extends media_MediaBaseViewer {
38466
38721
  }
38467
38722
  this.pendingHostSelectedSeek = null;
38468
38723
  this.exitShuttle();
38469
- this.handleCommentRangeClear();
38724
+ this.clearOpenCommentRangeDraft();
38725
+ this.commentRangeReadOnly = commentMarkerRange(marker);
38470
38726
  this.mediaEl.pause();
38471
38727
  if (this.mediaEl.currentTime !== marker.time) {
38472
38728
  this.mediaEl.currentTime = marker.time;
38473
38729
  }
38730
+ this.syncCommentRangeLoop();
38474
38731
  }
38475
38732
 
38476
38733
  /**
38477
- * Seconds of the open draft span, or null when collapsed / absent.
38478
- * Collapsed drafts (`endMs: null`) do not confine playback.
38734
+ * Seconds of the span that confines playback, or null when collapsed / absent.
38735
+ * A composer draft wins over a viewed comment range. Collapsed drafts do not confine playback.
38479
38736
  *
38480
38737
  * @return {{endSec: number, startSec: number}|null}
38481
38738
  */
38482
38739
  getOpenCommentRangeSeconds() {
38483
- const draft = this.commentRangeDraft;
38484
- if ((0,range/* isRangeCollapsed */.BT)(draft) || !Number.isFinite(draft.startMs) || !Number.isFinite(draft.endMs)) {
38740
+ // An open composer draft owns playback. A viewed comment range does otherwise.
38741
+ const source = this.commentRangeDraft != null ? this.commentRangeDraft : this.commentRangeReadOnly;
38742
+ if ((0,range/* isRangeCollapsed */.BT)(source) || !Number.isFinite(source.startMs) || !Number.isFinite(source.endMs)) {
38485
38743
  return null;
38486
38744
  }
38487
38745
  return {
38488
- endSec: draft.endMs / 1000,
38489
- startSec: draft.startMs / 1000
38746
+ endSec: source.endMs / 1000,
38747
+ startSec: source.startMs / 1000
38490
38748
  };
38491
38749
  }
38492
38750
 
38751
+ /**
38752
+ * Drop an open composer draft. A collapsed timestamp is left alone.
38753
+ * Does not clear a viewed comment range.
38754
+ *
38755
+ * @return {boolean} whether an open draft was cleared
38756
+ */
38757
+ clearOpenCommentRangeDraft() {
38758
+ if (!this.commentRangeDraft || this.commentRangeDraft.endMs == null) {
38759
+ return false;
38760
+ }
38761
+ const notifyHost = this.isCommentRangeTimestampActive;
38762
+ this.commentRangeDraft = null;
38763
+ this.isCommentRangeTimestampActive = false;
38764
+ if (notifyHost) {
38765
+ this.emit(EVENT_COMMENT_RANGE_DRAFT_DISMISS);
38766
+ }
38767
+ return true;
38768
+ }
38769
+
38493
38770
  /**
38494
38771
  * Keep a seek inside the open draft. Waveform click-outside and host
38495
38772
  * comment seeks dismiss first, then seek; clamp does not apply then.
@@ -38659,6 +38936,7 @@ class MP3Viewer extends media_MediaBaseViewer {
38659
38936
  this.controls.render(/*#__PURE__*/external_react_["default"].createElement(Mp3ControlsV2, MP3Viewer_extends({}, sharedProps, {
38660
38937
  commentMarkers: this.commentMarkers || [],
38661
38938
  commentRangeDraft: this.commentRangeDraft || null,
38939
+ commentRangeReadOnly: this.commentRangeReadOnly || null,
38662
38940
  hasStartedPlayback: !!this.userRequestedPlay,
38663
38941
  isGeneratingWaveform: this.isGeneratingWaveform(),
38664
38942
  keyboardVolumeStep: this.keyboardVolumeStep,
@@ -38671,7 +38949,9 @@ class MP3Viewer extends media_MediaBaseViewer {
38671
38949
  onCommentRangeDragCreate: this.handleCommentRangeDragCreate,
38672
38950
  onPlayNextChange: this.setPlayNext,
38673
38951
  peaks: this.waveformPeaks,
38674
- playNext: this.isPlayNextEnabled()
38952
+ playNext: this.isPlayNextEnabled(),
38953
+ shuttleDirection: this.shuttleDirection,
38954
+ shuttleRate: this.shuttleRate
38675
38955
  })));
38676
38956
  return;
38677
38957
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "box-content-preview",
3
- "version": "3.96.0",
3
+ "version": "3.98.0",
4
4
  "description": "Box Content Preview UI Element",
5
5
  "author": "Box (https://www.box.com/)",
6
6
  "license": "SEE LICENSE IN LICENSE",