@waveform-playlist/ui-components 8.1.0 → 9.0.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/dist/index.js CHANGED
@@ -949,8 +949,7 @@ var PlaylistErrorBoundary = class extends import_react5.default.Component {
949
949
 
950
950
  // src/components/Clip.tsx
951
951
  var import_styled_components13 = __toESM(require("styled-components"));
952
- var import_core2 = require("@dnd-kit/core");
953
- var import_utilities = require("@dnd-kit/utilities");
952
+ var import_react7 = require("@dnd-kit/react");
954
953
 
955
954
  // src/components/ClipHeader.tsx
956
955
  var import_styled_components10 = __toESM(require("styled-components"));
@@ -964,7 +963,7 @@ var HeaderContainer = import_styled_components10.default.div`
964
963
  display: flex;
965
964
  align-items: center;
966
965
  padding: 0 8px;
967
- cursor: ${(props) => props.$interactive ? props.$isDragging ? "grabbing" : "grab" : "default"};
966
+ cursor: ${(props) => props.$interactive ? "grab" : "default"};
968
967
  user-select: none;
969
968
  z-index: 110;
970
969
  flex-shrink: 0;
@@ -994,7 +993,7 @@ var ClipHeaderPresentational = ({
994
993
  trackName,
995
994
  isSelected = false
996
995
  }) => {
997
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderContainer, { $isDragging: false, $interactive: false, $isSelected: isSelected, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TrackName, { children: trackName }) });
996
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HeaderContainer, { $interactive: false, $isSelected: isSelected, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TrackName, { children: trackName }) });
998
997
  };
999
998
  var ClipHeader = ({
1000
999
  clipId,
@@ -1008,16 +1007,14 @@ var ClipHeader = ({
1008
1007
  if (disableDrag || !dragHandleProps) {
1009
1008
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ClipHeaderPresentational, { trackName, isSelected });
1010
1009
  }
1011
- const { attributes, listeners, setActivatorNodeRef } = dragHandleProps;
1010
+ const { handleRef } = dragHandleProps;
1012
1011
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1013
1012
  HeaderContainer,
1014
1013
  {
1015
- ref: setActivatorNodeRef,
1014
+ ref: handleRef,
1016
1015
  "data-clip-id": clipId,
1017
1016
  $interactive: true,
1018
1017
  $isSelected: isSelected,
1019
- ...listeners,
1020
- ...attributes,
1021
1018
  children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TrackName, { children: trackName })
1022
1019
  }
1023
1020
  );
@@ -1070,11 +1067,11 @@ var ClipBoundary = ({
1070
1067
  if (!dragHandleProps) {
1071
1068
  return null;
1072
1069
  }
1073
- const { attributes, listeners, setActivatorNodeRef, isDragging } = dragHandleProps;
1070
+ const { ref: boundaryRef, isDragging } = dragHandleProps;
1074
1071
  return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1075
1072
  BoundaryContainer,
1076
1073
  {
1077
- ref: setActivatorNodeRef,
1074
+ ref: boundaryRef,
1078
1075
  "data-clip-id": clipId,
1079
1076
  "data-boundary-edge": edge,
1080
1077
  $edge: edge,
@@ -1082,9 +1079,7 @@ var ClipBoundary = ({
1082
1079
  $isHovered: isHovered,
1083
1080
  $touchOptimized: touchOptimized,
1084
1081
  onMouseEnter: () => setIsHovered(true),
1085
- onMouseLeave: () => setIsHovered(false),
1086
- ...listeners,
1087
- ...attributes
1082
+ onMouseLeave: () => setIsHovered(false)
1088
1083
  }
1089
1084
  );
1090
1085
  };
@@ -1205,42 +1200,34 @@ var Clip = ({
1205
1200
  const width = endPixel - left;
1206
1201
  const enableDrag = showHeader && !disableHeaderDrag && !isOverlay;
1207
1202
  const draggableId = `clip-${trackIndex}-${clipIndex}`;
1208
- const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging } = (0, import_core2.useDraggable)({
1203
+ const {
1204
+ ref: clipRef,
1205
+ handleRef,
1206
+ isDragSource
1207
+ } = (0, import_react7.useDraggable)({
1209
1208
  id: draggableId,
1210
1209
  data: { clipId, trackIndex, clipIndex },
1211
1210
  disabled: !enableDrag
1212
1211
  });
1213
1212
  const leftBoundaryId = `clip-boundary-left-${trackIndex}-${clipIndex}`;
1214
- const {
1215
- attributes: leftBoundaryAttributes,
1216
- listeners: leftBoundaryListeners,
1217
- setActivatorNodeRef: setLeftBoundaryActivatorRef,
1218
- isDragging: isLeftBoundaryDragging
1219
- } = (0, import_core2.useDraggable)({
1213
+ const { ref: leftBoundaryRef, isDragSource: isLeftBoundaryDragging } = (0, import_react7.useDraggable)({
1220
1214
  id: leftBoundaryId,
1221
1215
  data: { clipId, trackIndex, clipIndex, boundary: "left" },
1222
- disabled: !enableDrag
1216
+ disabled: !enableDrag,
1217
+ feedback: "none"
1223
1218
  });
1224
1219
  const rightBoundaryId = `clip-boundary-right-${trackIndex}-${clipIndex}`;
1225
- const {
1226
- attributes: rightBoundaryAttributes,
1227
- listeners: rightBoundaryListeners,
1228
- setActivatorNodeRef: setRightBoundaryActivatorRef,
1229
- isDragging: isRightBoundaryDragging
1230
- } = (0, import_core2.useDraggable)({
1220
+ const { ref: rightBoundaryRef, isDragSource: isRightBoundaryDragging } = (0, import_react7.useDraggable)({
1231
1221
  id: rightBoundaryId,
1232
1222
  data: { clipId, trackIndex, clipIndex, boundary: "right" },
1233
- disabled: !enableDrag
1223
+ disabled: !enableDrag,
1224
+ feedback: "none"
1234
1225
  });
1235
- const style = transform ? {
1236
- transform: import_utilities.CSS.Translate.toString(transform),
1237
- zIndex: isDragging ? 100 : void 0
1238
- // Below controls (z-index: 999) but above other clips
1239
- } : void 0;
1226
+ const style = isDragSource ? { zIndex: 100 } : void 0;
1240
1227
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1241
1228
  ClipContainer,
1242
1229
  {
1243
- ref: setNodeRef,
1230
+ ref: clipRef,
1244
1231
  style,
1245
1232
  className,
1246
1233
  $left: left,
@@ -1259,7 +1246,7 @@ var Clip = ({
1259
1246
  trackName,
1260
1247
  isSelected,
1261
1248
  disableDrag: disableHeaderDrag,
1262
- dragHandleProps: enableDrag ? { attributes, listeners, setActivatorNodeRef } : void 0
1249
+ dragHandleProps: enableDrag ? { handleRef } : void 0
1263
1250
  }
1264
1251
  ),
1265
1252
  /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ClipViewportOriginProvider, { originX: left, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ChannelsWrapper, { $isOverlay: isOverlay, children: [
@@ -1293,9 +1280,7 @@ var Clip = ({
1293
1280
  edge: "left",
1294
1281
  touchOptimized,
1295
1282
  dragHandleProps: {
1296
- attributes: leftBoundaryAttributes,
1297
- listeners: leftBoundaryListeners,
1298
- setActivatorNodeRef: setLeftBoundaryActivatorRef,
1283
+ ref: leftBoundaryRef,
1299
1284
  isDragging: isLeftBoundaryDragging
1300
1285
  }
1301
1286
  }
@@ -1309,9 +1294,7 @@ var Clip = ({
1309
1294
  edge: "right",
1310
1295
  touchOptimized,
1311
1296
  dragHandleProps: {
1312
- attributes: rightBoundaryAttributes,
1313
- listeners: rightBoundaryListeners,
1314
- setActivatorNodeRef: setRightBoundaryActivatorRef,
1297
+ ref: rightBoundaryRef,
1315
1298
  isDragging: isRightBoundaryDragging
1316
1299
  }
1317
1300
  }
@@ -1363,7 +1346,7 @@ var MasterVolumeControl = ({
1363
1346
  };
1364
1347
 
1365
1348
  // src/components/Playhead.tsx
1366
- var import_react7 = require("react");
1349
+ var import_react8 = require("react");
1367
1350
  var import_styled_components15 = __toESM(require("styled-components"));
1368
1351
  var import_jsx_runtime12 = require("react/jsx-runtime");
1369
1352
  var PlayheadLine = import_styled_components15.default.div.attrs((props) => ({
@@ -1423,9 +1406,9 @@ var PlayheadWithMarker = ({
1423
1406
  getAudioContextTime,
1424
1407
  getPlaybackTime
1425
1408
  }) => {
1426
- const containerRef = (0, import_react7.useRef)(null);
1427
- const animationFrameRef = (0, import_react7.useRef)(null);
1428
- (0, import_react7.useEffect)(() => {
1409
+ const containerRef = (0, import_react8.useRef)(null);
1410
+ const animationFrameRef = (0, import_react8.useRef)(null);
1411
+ (0, import_react8.useEffect)(() => {
1429
1412
  const updatePosition = () => {
1430
1413
  if (containerRef.current) {
1431
1414
  let time;
@@ -1470,7 +1453,7 @@ var PlayheadWithMarker = ({
1470
1453
  getAudioContextTime,
1471
1454
  getPlaybackTime
1472
1455
  ]);
1473
- (0, import_react7.useEffect)(() => {
1456
+ (0, import_react8.useEffect)(() => {
1474
1457
  if (!isPlaying && containerRef.current) {
1475
1458
  const time = currentTimeRef.current ?? 0;
1476
1459
  const pos = time * sampleRate / samplesPerPixel + controlsOffset;
@@ -1485,7 +1468,7 @@ var PlayheadWithMarker = ({
1485
1468
 
1486
1469
  // src/components/Playlist.tsx
1487
1470
  var import_styled_components16 = __toESM(require("styled-components"));
1488
- var import_react8 = require("react");
1471
+ var import_react9 = require("react");
1489
1472
  var import_jsx_runtime13 = require("react/jsx-runtime");
1490
1473
  var Wrapper2 = import_styled_components16.default.div`
1491
1474
  overflow-y: hidden;
@@ -1540,8 +1523,8 @@ var Playlist = ({
1540
1523
  isSelecting,
1541
1524
  "data-playlist-state": playlistState
1542
1525
  }) => {
1543
- const wrapperRef = (0, import_react8.useRef)(null);
1544
- const handleRef = (0, import_react8.useCallback)(
1526
+ const wrapperRef = (0, import_react9.useRef)(null);
1527
+ const handleRef = (0, import_react9.useCallback)(
1545
1528
  (el) => {
1546
1529
  wrapperRef.current = el;
1547
1530
  scrollContainerRef?.(el);
@@ -1598,7 +1581,7 @@ var Selection = ({
1598
1581
  };
1599
1582
 
1600
1583
  // src/components/LoopRegion.tsx
1601
- var import_react9 = require("react");
1584
+ var import_react10 = require("react");
1602
1585
  var import_styled_components18 = __toESM(require("styled-components"));
1603
1586
  var import_jsx_runtime15 = require("react/jsx-runtime");
1604
1587
  var LoopRegionOverlayDiv = import_styled_components18.default.div.attrs((props) => ({
@@ -1749,12 +1732,12 @@ var LoopRegionMarkers = ({
1749
1732
  minPosition = 0,
1750
1733
  maxPosition = Infinity
1751
1734
  }) => {
1752
- const [draggingMarker, setDraggingMarker] = (0, import_react9.useState)(null);
1753
- const dragStartX = (0, import_react9.useRef)(0);
1754
- const dragStartPosition = (0, import_react9.useRef)(0);
1755
- const dragStartEnd = (0, import_react9.useRef)(0);
1735
+ const [draggingMarker, setDraggingMarker] = (0, import_react10.useState)(null);
1736
+ const dragStartX = (0, import_react10.useRef)(0);
1737
+ const dragStartPosition = (0, import_react10.useRef)(0);
1738
+ const dragStartEnd = (0, import_react10.useRef)(0);
1756
1739
  const width = Math.max(0, endPosition - startPosition);
1757
- const handleMarkerMouseDown = (0, import_react9.useCallback)(
1740
+ const handleMarkerMouseDown = (0, import_react10.useCallback)(
1758
1741
  (e, marker) => {
1759
1742
  e.preventDefault();
1760
1743
  e.stopPropagation();
@@ -1782,7 +1765,7 @@ var LoopRegionMarkers = ({
1782
1765
  },
1783
1766
  [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]
1784
1767
  );
1785
- const handleRegionMouseDown = (0, import_react9.useCallback)(
1768
+ const handleRegionMouseDown = (0, import_react10.useCallback)(
1786
1769
  (e) => {
1787
1770
  e.preventDefault();
1788
1771
  e.stopPropagation();
@@ -1876,11 +1859,11 @@ var TimescaleLoopRegion = ({
1876
1859
  maxPosition = Infinity,
1877
1860
  controlsOffset = 0
1878
1861
  }) => {
1879
- const [, setIsCreating] = (0, import_react9.useState)(false);
1880
- const createStartX = (0, import_react9.useRef)(0);
1881
- const containerRef = (0, import_react9.useRef)(null);
1862
+ const [, setIsCreating] = (0, import_react10.useState)(false);
1863
+ const createStartX = (0, import_react10.useRef)(0);
1864
+ const containerRef = (0, import_react10.useRef)(null);
1882
1865
  const hasLoopRegion = endPosition > startPosition;
1883
- const handleBackgroundMouseDown = (0, import_react9.useCallback)(
1866
+ const handleBackgroundMouseDown = (0, import_react10.useCallback)(
1884
1867
  (e) => {
1885
1868
  const target = e.target;
1886
1869
  if (target.closest("[data-loop-marker-handle]") || target.closest("[data-loop-region-timescale]")) {
@@ -1937,10 +1920,10 @@ var TimescaleLoopRegion = ({
1937
1920
  };
1938
1921
 
1939
1922
  // src/components/SelectionTimeInputs.tsx
1940
- var import_react11 = require("react");
1923
+ var import_react12 = require("react");
1941
1924
 
1942
1925
  // src/components/TimeInput.tsx
1943
- var import_react10 = require("react");
1926
+ var import_react11 = require("react");
1944
1927
 
1945
1928
  // src/utils/timeFormat.ts
1946
1929
  function clockFormat(seconds, decimals) {
@@ -2000,8 +1983,8 @@ var TimeInput = ({
2000
1983
  onChange,
2001
1984
  readOnly = false
2002
1985
  }) => {
2003
- const [displayValue, setDisplayValue] = (0, import_react10.useState)("");
2004
- (0, import_react10.useEffect)(() => {
1986
+ const [displayValue, setDisplayValue] = (0, import_react11.useState)("");
1987
+ (0, import_react11.useEffect)(() => {
2005
1988
  const formatted = formatTime(value, format);
2006
1989
  setDisplayValue(formatted);
2007
1990
  }, [value, format, id]);
@@ -2047,8 +2030,8 @@ var SelectionTimeInputs = ({
2047
2030
  onSelectionChange,
2048
2031
  className
2049
2032
  }) => {
2050
- const [timeFormat, setTimeFormat] = (0, import_react11.useState)("hh:mm:ss.uuu");
2051
- (0, import_react11.useEffect)(() => {
2033
+ const [timeFormat, setTimeFormat] = (0, import_react12.useState)("hh:mm:ss.uuu");
2034
+ (0, import_react12.useEffect)(() => {
2052
2035
  const timeFormatSelect = document.querySelector(".time-format");
2053
2036
  const handleFormatChange = () => {
2054
2037
  if (timeFormatSelect) {
@@ -2100,14 +2083,14 @@ var SelectionTimeInputs = ({
2100
2083
  };
2101
2084
 
2102
2085
  // src/contexts/DevicePixelRatio.tsx
2103
- var import_react12 = require("react");
2086
+ var import_react13 = require("react");
2104
2087
  var import_jsx_runtime18 = require("react/jsx-runtime");
2105
2088
  function getScale() {
2106
2089
  return window.devicePixelRatio;
2107
2090
  }
2108
- var DevicePixelRatioContext = (0, import_react12.createContext)(getScale());
2091
+ var DevicePixelRatioContext = (0, import_react13.createContext)(getScale());
2109
2092
  var DevicePixelRatioProvider = ({ children }) => {
2110
- const [scale, setScale] = (0, import_react12.useState)(getScale());
2093
+ const [scale, setScale] = (0, import_react13.useState)(getScale());
2111
2094
  matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
2112
2095
  "change",
2113
2096
  () => {
@@ -2117,11 +2100,11 @@ var DevicePixelRatioProvider = ({ children }) => {
2117
2100
  );
2118
2101
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
2119
2102
  };
2120
- var useDevicePixelRatio = () => (0, import_react12.useContext)(DevicePixelRatioContext);
2103
+ var useDevicePixelRatio = () => (0, import_react13.useContext)(DevicePixelRatioContext);
2121
2104
 
2122
2105
  // src/contexts/PlaylistInfo.tsx
2123
- var import_react13 = require("react");
2124
- var PlaylistInfoContext = (0, import_react13.createContext)({
2106
+ var import_react14 = require("react");
2107
+ var PlaylistInfoContext = (0, import_react14.createContext)({
2125
2108
  sampleRate: 48e3,
2126
2109
  samplesPerPixel: 1e3,
2127
2110
  zoomLevels: [1e3, 1500, 2e3, 2500],
@@ -2135,21 +2118,21 @@ var PlaylistInfoContext = (0, import_react13.createContext)({
2135
2118
  barWidth: 1,
2136
2119
  barGap: 0
2137
2120
  });
2138
- var usePlaylistInfo = () => (0, import_react13.useContext)(PlaylistInfoContext);
2121
+ var usePlaylistInfo = () => (0, import_react14.useContext)(PlaylistInfoContext);
2139
2122
 
2140
2123
  // src/contexts/Theme.tsx
2141
- var import_react14 = require("react");
2124
+ var import_react15 = require("react");
2142
2125
  var import_styled_components19 = require("styled-components");
2143
- var useTheme2 = () => (0, import_react14.useContext)(import_styled_components19.ThemeContext);
2126
+ var useTheme2 = () => (0, import_react15.useContext)(import_styled_components19.ThemeContext);
2144
2127
 
2145
2128
  // src/contexts/TrackControls.tsx
2146
- var import_react15 = require("react");
2129
+ var import_react16 = require("react");
2147
2130
  var import_jsx_runtime19 = require("react/jsx-runtime");
2148
- var TrackControlsContext = (0, import_react15.createContext)(/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react15.Fragment, {}));
2149
- var useTrackControls = () => (0, import_react15.useContext)(TrackControlsContext);
2131
+ var TrackControlsContext = (0, import_react16.createContext)(/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react16.Fragment, {}));
2132
+ var useTrackControls = () => (0, import_react16.useContext)(TrackControlsContext);
2150
2133
 
2151
2134
  // src/contexts/Playout.tsx
2152
- var import_react16 = require("react");
2135
+ var import_react17 = require("react");
2153
2136
  var import_jsx_runtime20 = require("react/jsx-runtime");
2154
2137
  var defaultProgress = 0;
2155
2138
  var defaultIsPlaying = false;
@@ -2161,8 +2144,8 @@ var defaultPlayout = {
2161
2144
  selectionStart: defaultSelectionStart,
2162
2145
  selectionEnd: defaultSelectionEnd
2163
2146
  };
2164
- var PlayoutStatusContext = (0, import_react16.createContext)(defaultPlayout);
2165
- var PlayoutStatusUpdateContext = (0, import_react16.createContext)({
2147
+ var PlayoutStatusContext = (0, import_react17.createContext)(defaultPlayout);
2148
+ var PlayoutStatusUpdateContext = (0, import_react17.createContext)({
2166
2149
  setIsPlaying: () => {
2167
2150
  },
2168
2151
  setProgress: () => {
@@ -2171,23 +2154,23 @@ var PlayoutStatusUpdateContext = (0, import_react16.createContext)({
2171
2154
  }
2172
2155
  });
2173
2156
  var PlayoutProvider = ({ children }) => {
2174
- const [isPlaying, setIsPlaying] = (0, import_react16.useState)(defaultIsPlaying);
2175
- const [progress, setProgress] = (0, import_react16.useState)(defaultProgress);
2176
- const [selectionStart, setSelectionStart] = (0, import_react16.useState)(defaultSelectionStart);
2177
- const [selectionEnd, setSelectionEnd] = (0, import_react16.useState)(defaultSelectionEnd);
2157
+ const [isPlaying, setIsPlaying] = (0, import_react17.useState)(defaultIsPlaying);
2158
+ const [progress, setProgress] = (0, import_react17.useState)(defaultProgress);
2159
+ const [selectionStart, setSelectionStart] = (0, import_react17.useState)(defaultSelectionStart);
2160
+ const [selectionEnd, setSelectionEnd] = (0, import_react17.useState)(defaultSelectionEnd);
2178
2161
  const setSelection = (start, end) => {
2179
2162
  setSelectionStart(start);
2180
2163
  setSelectionEnd(end);
2181
2164
  };
2182
2165
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
2183
2166
  };
2184
- var usePlayoutStatus = () => (0, import_react16.useContext)(PlayoutStatusContext);
2185
- var usePlayoutStatusUpdate = () => (0, import_react16.useContext)(PlayoutStatusUpdateContext);
2167
+ var usePlayoutStatus = () => (0, import_react17.useContext)(PlayoutStatusContext);
2168
+ var usePlayoutStatusUpdate = () => (0, import_react17.useContext)(PlayoutStatusUpdateContext);
2186
2169
 
2187
2170
  // src/components/SpectrogramChannel.tsx
2188
- var import_react17 = require("react");
2171
+ var import_react18 = require("react");
2189
2172
  var import_styled_components20 = __toESM(require("styled-components"));
2190
- var import_core3 = require("@waveform-playlist/core");
2173
+ var import_core2 = require("@waveform-playlist/core");
2191
2174
  var import_jsx_runtime21 = require("react/jsx-runtime");
2192
2175
  var LINEAR_FREQUENCY_SCALE = (f, minF, maxF) => (f - minF) / (maxF - minF);
2193
2176
  var Wrapper3 = import_styled_components20.default.div.attrs((props) => ({
@@ -2242,24 +2225,24 @@ var SpectrogramChannel = ({
2242
2225
  }) => {
2243
2226
  const channelIndex = channelIndexProp ?? index;
2244
2227
  const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
2245
- const registeredIdsRef = (0, import_react17.useRef)([]);
2246
- const transferredCanvasesRef = (0, import_react17.useRef)(/* @__PURE__ */ new WeakSet());
2247
- const workerApiRef = (0, import_react17.useRef)(workerApi);
2248
- const onCanvasesReadyRef = (0, import_react17.useRef)(onCanvasesReady);
2228
+ const registeredIdsRef = (0, import_react18.useRef)([]);
2229
+ const transferredCanvasesRef = (0, import_react18.useRef)(/* @__PURE__ */ new WeakSet());
2230
+ const workerApiRef = (0, import_react18.useRef)(workerApi);
2231
+ const onCanvasesReadyRef = (0, import_react18.useRef)(onCanvasesReady);
2249
2232
  const isWorkerMode = !!(workerApi && clipId);
2250
2233
  const clipOriginX = useClipViewportOrigin();
2251
- const visibleChunkIndices = useVisibleChunkIndices(length, import_core3.MAX_CANVAS_WIDTH, clipOriginX);
2234
+ const visibleChunkIndices = useVisibleChunkIndices(length, import_core2.MAX_CANVAS_WIDTH, clipOriginX);
2252
2235
  const lut = colorLUT ?? DEFAULT_COLOR_LUT;
2253
2236
  const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
2254
2237
  const scaleFn = frequencyScaleFn ?? LINEAR_FREQUENCY_SCALE;
2255
2238
  const hasCustomFrequencyScale = Boolean(frequencyScaleFn);
2256
- (0, import_react17.useEffect)(() => {
2239
+ (0, import_react18.useEffect)(() => {
2257
2240
  workerApiRef.current = workerApi;
2258
2241
  }, [workerApi]);
2259
- (0, import_react17.useEffect)(() => {
2242
+ (0, import_react18.useEffect)(() => {
2260
2243
  onCanvasesReadyRef.current = onCanvasesReady;
2261
2244
  }, [onCanvasesReady]);
2262
- (0, import_react17.useEffect)(() => {
2245
+ (0, import_react18.useEffect)(() => {
2263
2246
  if (!isWorkerMode) return;
2264
2247
  const currentWorkerApi = workerApiRef.current;
2265
2248
  if (!currentWorkerApi || !clipId) return;
@@ -2314,15 +2297,15 @@ var SpectrogramChannel = ({
2314
2297
  const match = id.match(/chunk(\d+)$/);
2315
2298
  if (!match) {
2316
2299
  console.warn(`[spectrogram] Unexpected canvas ID format: ${id}`);
2317
- return import_core3.MAX_CANVAS_WIDTH;
2300
+ return import_core2.MAX_CANVAS_WIDTH;
2318
2301
  }
2319
2302
  const chunkIdx = parseInt(match[1], 10);
2320
- return Math.min(length - chunkIdx * import_core3.MAX_CANVAS_WIDTH, import_core3.MAX_CANVAS_WIDTH);
2303
+ return Math.min(length - chunkIdx * import_core2.MAX_CANVAS_WIDTH, import_core2.MAX_CANVAS_WIDTH);
2321
2304
  });
2322
2305
  onCanvasesReadyRef.current?.(allIds, allWidths);
2323
2306
  }
2324
2307
  }, [canvasMapRef, isWorkerMode, clipId, channelIndex, length, visibleChunkIndices]);
2325
- (0, import_react17.useEffect)(() => {
2308
+ (0, import_react18.useEffect)(() => {
2326
2309
  return () => {
2327
2310
  const api = workerApiRef.current;
2328
2311
  if (!api) return;
@@ -2336,7 +2319,7 @@ var SpectrogramChannel = ({
2336
2319
  registeredIdsRef.current = [];
2337
2320
  };
2338
2321
  }, []);
2339
- (0, import_react17.useLayoutEffect)(() => {
2322
+ (0, import_react18.useLayoutEffect)(() => {
2340
2323
  if (isWorkerMode || !data) return;
2341
2324
  const {
2342
2325
  frequencyBinCount,
@@ -2349,7 +2332,7 @@ var SpectrogramChannel = ({
2349
2332
  const rangeDb = rawRangeDb === 0 ? 1 : rawRangeDb;
2350
2333
  const binToFreq = (bin) => bin / frequencyBinCount * (sampleRate / 2);
2351
2334
  for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
2352
- const globalPixelOffset = canvasIdx * import_core3.MAX_CANVAS_WIDTH;
2335
+ const globalPixelOffset = canvasIdx * import_core2.MAX_CANVAS_WIDTH;
2353
2336
  const ctx = canvas.getContext("2d");
2354
2337
  if (!ctx) continue;
2355
2338
  const canvasWidth = canvas.width / devicePixelRatio;
@@ -2425,8 +2408,8 @@ var SpectrogramChannel = ({
2425
2408
  visibleChunkIndices
2426
2409
  ]);
2427
2410
  const canvases = visibleChunkIndices.map((i) => {
2428
- const chunkLeft = i * import_core3.MAX_CANVAS_WIDTH;
2429
- const currentWidth = Math.min(length - chunkLeft, import_core3.MAX_CANVAS_WIDTH);
2411
+ const chunkLeft = i * import_core2.MAX_CANVAS_WIDTH;
2412
+ const currentWidth = Math.min(length - chunkLeft, import_core2.MAX_CANVAS_WIDTH);
2430
2413
  return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2431
2414
  SpectrogramCanvas,
2432
2415
  {
@@ -2556,7 +2539,7 @@ var SmartChannel = ({
2556
2539
  };
2557
2540
 
2558
2541
  // src/components/SpectrogramLabels.tsx
2559
- var import_react18 = require("react");
2542
+ var import_react19 = require("react");
2560
2543
  var import_styled_components21 = __toESM(require("styled-components"));
2561
2544
  var import_jsx_runtime23 = require("react/jsx-runtime");
2562
2545
  var LABELS_WIDTH = 72;
@@ -2608,12 +2591,12 @@ var SpectrogramLabels = ({
2608
2591
  renderMode = "spectrogram",
2609
2592
  hasClipHeaders = false
2610
2593
  }) => {
2611
- const canvasRef = (0, import_react18.useRef)(null);
2594
+ const canvasRef = (0, import_react19.useRef)(null);
2612
2595
  const devicePixelRatio = useDevicePixelRatio();
2613
2596
  const spectrogramHeight = renderMode === "both" ? Math.floor(waveHeight / 2) : waveHeight;
2614
2597
  const totalHeight = numChannels * waveHeight;
2615
2598
  const clipHeaderOffset = hasClipHeaders ? 22 : 0;
2616
- (0, import_react18.useLayoutEffect)(() => {
2599
+ (0, import_react19.useLayoutEffect)(() => {
2617
2600
  const canvas = canvasRef.current;
2618
2601
  if (!canvas) return;
2619
2602
  const ctx = canvas.getContext("2d");
@@ -2667,10 +2650,10 @@ var SpectrogramLabels = ({
2667
2650
  };
2668
2651
 
2669
2652
  // src/components/SmartScale.tsx
2670
- var import_react20 = require("react");
2653
+ var import_react21 = require("react");
2671
2654
 
2672
2655
  // src/components/TimeScale.tsx
2673
- var import_react19 = __toESM(require("react"));
2656
+ var import_react20 = __toESM(require("react"));
2674
2657
  var import_styled_components22 = __toESM(require("styled-components"));
2675
2658
 
2676
2659
  // src/utils/conversions.ts
@@ -2694,7 +2677,7 @@ function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
2694
2677
  }
2695
2678
 
2696
2679
  // src/components/TimeScale.tsx
2697
- var import_core4 = require("@waveform-playlist/core");
2680
+ var import_core3 = require("@waveform-playlist/core");
2698
2681
  var import_jsx_runtime24 = require("react/jsx-runtime");
2699
2682
  function formatTime2(milliseconds) {
2700
2683
  const seconds = Math.floor(milliseconds / 1e3);
@@ -2752,9 +2735,9 @@ var TimeScale = (props) => {
2752
2735
  samplesPerPixel,
2753
2736
  timeScaleHeight,
2754
2737
  controls: { show: showControls, width: controlWidth }
2755
- } = (0, import_react19.useContext)(PlaylistInfoContext);
2738
+ } = (0, import_react20.useContext)(PlaylistInfoContext);
2756
2739
  const devicePixelRatio = useDevicePixelRatio();
2757
- const { widthX, canvasInfo, timeMarkersWithPositions } = (0, import_react19.useMemo)(() => {
2740
+ const { widthX, canvasInfo, timeMarkersWithPositions } = (0, import_react20.useMemo)(() => {
2758
2741
  const nextCanvasInfo = /* @__PURE__ */ new Map();
2759
2742
  const nextMarkers = [];
2760
2743
  const nextWidthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);
@@ -2765,7 +2748,7 @@ var TimeScale = (props) => {
2765
2748
  if (counter % marker === 0) {
2766
2749
  const timeMs = counter;
2767
2750
  const timestamp = formatTime2(timeMs);
2768
- const element = renderTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react19.default.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
2751
+ const element = renderTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react20.default.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
2769
2752
  nextMarkers.push({ pix, element });
2770
2753
  nextCanvasInfo.set(pix, timeScaleHeight);
2771
2754
  } else if (counter % bigStep === 0) {
@@ -2790,10 +2773,10 @@ var TimeScale = (props) => {
2790
2773
  renderTimestamp,
2791
2774
  timeScaleHeight
2792
2775
  ]);
2793
- const visibleChunkIndices = useVisibleChunkIndices(widthX, import_core4.MAX_CANVAS_WIDTH);
2776
+ const visibleChunkIndices = useVisibleChunkIndices(widthX, import_core3.MAX_CANVAS_WIDTH);
2794
2777
  const visibleChunks = visibleChunkIndices.map((i) => {
2795
- const chunkLeft = i * import_core4.MAX_CANVAS_WIDTH;
2796
- const chunkWidth = Math.min(widthX - chunkLeft, import_core4.MAX_CANVAS_WIDTH);
2778
+ const chunkLeft = i * import_core3.MAX_CANVAS_WIDTH;
2779
+ const chunkWidth = Math.min(widthX - chunkLeft, import_core3.MAX_CANVAS_WIDTH);
2797
2780
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2798
2781
  TimeTickChunk,
2799
2782
  {
@@ -2808,14 +2791,14 @@ var TimeScale = (props) => {
2808
2791
  `timescale-${i}`
2809
2792
  );
2810
2793
  });
2811
- const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] * import_core4.MAX_CANVAS_WIDTH : 0;
2812
- const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) * import_core4.MAX_CANVAS_WIDTH : Infinity;
2794
+ const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] * import_core3.MAX_CANVAS_WIDTH : 0;
2795
+ const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) * import_core3.MAX_CANVAS_WIDTH : Infinity;
2813
2796
  const visibleMarkers = visibleChunkIndices.length > 0 ? timeMarkersWithPositions.filter(({ pix }) => pix >= firstChunkLeft && pix < lastChunkRight).map(({ element }) => element) : timeMarkersWithPositions.map(({ element }) => element);
2814
- (0, import_react19.useLayoutEffect)(() => {
2797
+ (0, import_react20.useLayoutEffect)(() => {
2815
2798
  for (const [chunkIdx, canvas] of canvasMapRef.current.entries()) {
2816
2799
  const ctx = canvas.getContext("2d");
2817
2800
  if (!ctx) continue;
2818
- const chunkLeft = chunkIdx * import_core4.MAX_CANVAS_WIDTH;
2801
+ const chunkLeft = chunkIdx * import_core3.MAX_CANVAS_WIDTH;
2819
2802
  const chunkWidth = canvas.width / devicePixelRatio;
2820
2803
  ctx.resetTransform();
2821
2804
  ctx.clearRect(0, 0, canvas.width, canvas.height);
@@ -2928,7 +2911,7 @@ function getScaleInfo(samplesPerPixel) {
2928
2911
  return config;
2929
2912
  }
2930
2913
  var SmartScale = ({ renderTimestamp }) => {
2931
- const { samplesPerPixel, duration } = (0, import_react20.useContext)(PlaylistInfoContext);
2914
+ const { samplesPerPixel, duration } = (0, import_react21.useContext)(PlaylistInfoContext);
2932
2915
  let config = getScaleInfo(samplesPerPixel);
2933
2916
  return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2934
2917
  StyledTimeScale,
@@ -3159,7 +3142,7 @@ var ButtonGroup = import_styled_components26.default.div`
3159
3142
 
3160
3143
  // src/components/TrackControls/CloseButton.tsx
3161
3144
  var import_styled_components27 = __toESM(require("styled-components"));
3162
- var import_react21 = require("@phosphor-icons/react");
3145
+ var import_react22 = require("@phosphor-icons/react");
3163
3146
  var import_jsx_runtime28 = require("react/jsx-runtime");
3164
3147
  var StyledCloseButton = import_styled_components27.default.button`
3165
3148
  position: absolute;
@@ -3184,7 +3167,7 @@ var StyledCloseButton = import_styled_components27.default.button`
3184
3167
  color: #dc3545;
3185
3168
  }
3186
3169
  `;
3187
- var CloseButton = ({ onClick, title = "Remove track" }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(StyledCloseButton, { onClick, title, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react21.X, { size: 12, weight: "bold" }) });
3170
+ var CloseButton = ({ onClick, title = "Remove track" }) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(StyledCloseButton, { onClick, title, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react22.X, { size: 12, weight: "bold" }) });
3188
3171
 
3189
3172
  // src/components/TrackControls/Controls.tsx
3190
3173
  var import_styled_components28 = __toESM(require("styled-components"));
@@ -3219,24 +3202,24 @@ var Header = import_styled_components29.default.header`
3219
3202
  `;
3220
3203
 
3221
3204
  // src/components/TrackControls/VolumeDownIcon.tsx
3222
- var import_react22 = require("@phosphor-icons/react");
3205
+ var import_react23 = require("@phosphor-icons/react");
3223
3206
  var import_jsx_runtime29 = require("react/jsx-runtime");
3224
- var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react22.SpeakerLowIcon, { weight: "light", ...props });
3207
+ var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react23.SpeakerLowIcon, { weight: "light", ...props });
3225
3208
 
3226
3209
  // src/components/TrackControls/VolumeUpIcon.tsx
3227
- var import_react23 = require("@phosphor-icons/react");
3210
+ var import_react24 = require("@phosphor-icons/react");
3228
3211
  var import_jsx_runtime30 = require("react/jsx-runtime");
3229
- var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react23.SpeakerHighIcon, { weight: "light", ...props });
3212
+ var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react24.SpeakerHighIcon, { weight: "light", ...props });
3230
3213
 
3231
3214
  // src/components/TrackControls/TrashIcon.tsx
3232
- var import_react24 = require("@phosphor-icons/react");
3215
+ var import_react25 = require("@phosphor-icons/react");
3233
3216
  var import_jsx_runtime31 = require("react/jsx-runtime");
3234
- var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react24.TrashIcon, { weight: "light", ...props });
3217
+ var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react25.TrashIcon, { weight: "light", ...props });
3235
3218
 
3236
3219
  // src/components/TrackControls/DotsIcon.tsx
3237
- var import_react25 = require("@phosphor-icons/react");
3220
+ var import_react26 = require("@phosphor-icons/react");
3238
3221
  var import_jsx_runtime32 = require("react/jsx-runtime");
3239
- var DotsIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react25.DotsThreeIcon, { weight: "bold", ...props });
3222
+ var DotsIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react26.DotsThreeIcon, { weight: "bold", ...props });
3240
3223
 
3241
3224
  // src/components/TrackControls/Slider.tsx
3242
3225
  var import_styled_components30 = __toESM(require("styled-components"));
@@ -3304,7 +3287,7 @@ var SliderWrapper = import_styled_components31.default.label`
3304
3287
  `;
3305
3288
 
3306
3289
  // src/components/TrackMenu.tsx
3307
- var import_react26 = __toESM(require("react"));
3290
+ var import_react27 = __toESM(require("react"));
3308
3291
  var import_react_dom = require("react-dom");
3309
3292
  var import_styled_components32 = __toESM(require("styled-components"));
3310
3293
  var import_jsx_runtime33 = require("react/jsx-runtime");
@@ -3346,13 +3329,13 @@ var Divider = import_styled_components32.default.hr`
3346
3329
  margin: 0.35rem 0;
3347
3330
  `;
3348
3331
  var TrackMenu = ({ items: itemsProp }) => {
3349
- const [open, setOpen] = (0, import_react26.useState)(false);
3332
+ const [open, setOpen] = (0, import_react27.useState)(false);
3350
3333
  const close = () => setOpen(false);
3351
3334
  const items = typeof itemsProp === "function" ? itemsProp(close) : itemsProp;
3352
- const [dropdownPos, setDropdownPos] = (0, import_react26.useState)({ top: 0, left: 0 });
3353
- const buttonRef = (0, import_react26.useRef)(null);
3354
- const dropdownRef = (0, import_react26.useRef)(null);
3355
- (0, import_react26.useEffect)(() => {
3335
+ const [dropdownPos, setDropdownPos] = (0, import_react27.useState)({ top: 0, left: 0 });
3336
+ const buttonRef = (0, import_react27.useRef)(null);
3337
+ const dropdownRef = (0, import_react27.useRef)(null);
3338
+ (0, import_react27.useEffect)(() => {
3356
3339
  if (open && buttonRef.current) {
3357
3340
  const rect = buttonRef.current.getBoundingClientRect();
3358
3341
  setDropdownPos({
@@ -3361,7 +3344,7 @@ var TrackMenu = ({ items: itemsProp }) => {
3361
3344
  });
3362
3345
  }
3363
3346
  }, [open]);
3364
- (0, import_react26.useEffect)(() => {
3347
+ (0, import_react27.useEffect)(() => {
3365
3348
  if (!open) return;
3366
3349
  const handleClick = (e) => {
3367
3350
  const target = e.target;
@@ -3395,7 +3378,7 @@ var TrackMenu = ({ items: itemsProp }) => {
3395
3378
  $top: dropdownPos.top,
3396
3379
  $left: dropdownPos.left,
3397
3380
  onMouseDown: (e) => e.stopPropagation(),
3398
- children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react26.default.Fragment, { children: [
3381
+ children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react27.default.Fragment, { children: [
3399
3382
  index > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Divider, {}),
3400
3383
  item.content
3401
3384
  ] }, item.id))