@waveform-playlist/ui-components 7.1.1 → 7.1.2

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
@@ -60,7 +60,6 @@ __export(index_exports, {
60
60
  InlineLabel: () => InlineLabel,
61
61
  LoopRegion: () => LoopRegion,
62
62
  LoopRegionMarkers: () => LoopRegionMarkers,
63
- MAX_CANVAS_WIDTH: () => MAX_CANVAS_WIDTH,
64
63
  MasterVolumeControl: () => MasterVolumeControl,
65
64
  Playhead: () => Playhead,
66
65
  PlayheadWithMarker: () => PlayheadWithMarker,
@@ -109,6 +108,7 @@ __export(index_exports, {
109
108
  useScrollViewportSelector: () => useScrollViewportSelector,
110
109
  useTheme: () => useTheme2,
111
110
  useTrackControls: () => useTrackControls,
111
+ useVisibleChunkIndices: () => useVisibleChunkIndices,
112
112
  waveformColorToCss: () => waveformColorToCss
113
113
  });
114
114
  module.exports = __toCommonJS(index_exports);
@@ -442,7 +442,7 @@ var AutomaticScrollCheckbox = ({
442
442
  };
443
443
 
444
444
  // src/components/Channel.tsx
445
- var import_react2 = require("react");
445
+ var import_react3 = require("react");
446
446
  var import_styled_components9 = __toESM(require("styled-components"));
447
447
 
448
448
  // src/wfpl-theme.ts
@@ -695,11 +695,52 @@ function useScrollViewportSelector(selector) {
695
695
  () => selector(null)
696
696
  );
697
697
  }
698
+ function useVisibleChunkIndices(totalWidth, chunkWidth) {
699
+ const visibleChunkKey = useScrollViewportSelector((viewport) => {
700
+ const totalChunks = Math.ceil(totalWidth / chunkWidth);
701
+ const indices = [];
702
+ for (let i = 0; i < totalChunks; i++) {
703
+ const chunkLeft = i * chunkWidth;
704
+ const thisChunkWidth = Math.min(totalWidth - chunkLeft, chunkWidth);
705
+ if (viewport) {
706
+ const chunkEnd = chunkLeft + thisChunkWidth;
707
+ if (chunkEnd <= viewport.visibleStart || chunkLeft >= viewport.visibleEnd) {
708
+ continue;
709
+ }
710
+ }
711
+ indices.push(i);
712
+ }
713
+ return indices.join(",");
714
+ });
715
+ return (0, import_react.useMemo)(
716
+ () => visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [],
717
+ [visibleChunkKey]
718
+ );
719
+ }
698
720
 
699
- // src/constants.ts
700
- var MAX_CANVAS_WIDTH = 1e3;
721
+ // src/hooks/useChunkedCanvasRefs.ts
722
+ var import_react2 = require("react");
723
+ function useChunkedCanvasRefs() {
724
+ const canvasMapRef = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
725
+ const canvasRef = (0, import_react2.useCallback)((canvas) => {
726
+ if (canvas !== null) {
727
+ const idx = parseInt(canvas.dataset.index, 10);
728
+ canvasMapRef.current.set(idx, canvas);
729
+ }
730
+ }, []);
731
+ (0, import_react2.useEffect)(() => {
732
+ const map = canvasMapRef.current;
733
+ for (const [idx, canvas] of map.entries()) {
734
+ if (!canvas.isConnected) {
735
+ map.delete(idx);
736
+ }
737
+ }
738
+ });
739
+ return { canvasRef, canvasMapRef };
740
+ }
701
741
 
702
742
  // src/components/Channel.tsx
743
+ var import_core = require("@waveform-playlist/core");
703
744
  var import_jsx_runtime4 = require("react/jsx-runtime");
704
745
  function createCanvasFillStyle(ctx, color, width, height) {
705
746
  if (!isWaveformGradient(color)) {
@@ -760,49 +801,12 @@ var Channel = (props) => {
760
801
  transparentBackground = false,
761
802
  drawMode = "inverted"
762
803
  } = props;
763
- const canvasesRef = (0, import_react2.useRef)([]);
764
- const visibleChunkKey = useScrollViewportSelector((viewport) => {
765
- const totalChunks = Math.ceil(length / MAX_CANVAS_WIDTH);
766
- const indices = [];
767
- for (let i = 0; i < totalChunks; i++) {
768
- const chunkLeft = i * MAX_CANVAS_WIDTH;
769
- const chunkWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
770
- if (viewport) {
771
- const chunkEnd = chunkLeft + chunkWidth;
772
- if (chunkEnd <= viewport.visibleStart || chunkLeft >= viewport.visibleEnd) {
773
- continue;
774
- }
775
- }
776
- indices.push(i);
777
- }
778
- return indices.join(",");
779
- });
780
- const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
781
- const canvasRef = (0, import_react2.useCallback)(
782
- (canvas) => {
783
- if (canvas !== null) {
784
- const index2 = parseInt(canvas.dataset.index, 10);
785
- canvasesRef.current[index2] = canvas;
786
- }
787
- },
788
- []
789
- );
790
- (0, import_react2.useEffect)(() => {
791
- const canvases = canvasesRef.current;
792
- for (let i = canvases.length - 1; i >= 0; i--) {
793
- if (canvases[i] && !canvases[i].isConnected) {
794
- delete canvases[i];
795
- }
796
- }
797
- });
798
- (0, import_react2.useLayoutEffect)(() => {
799
- const canvases = canvasesRef.current;
804
+ const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
805
+ const visibleChunkIndices = useVisibleChunkIndices(length, import_core.MAX_CANVAS_WIDTH);
806
+ (0, import_react3.useLayoutEffect)(() => {
800
807
  const step = barWidth + barGap;
801
- for (let i = 0; i < canvases.length; i++) {
802
- const canvas = canvases[i];
803
- if (!canvas) continue;
804
- const canvasIdx = parseInt(canvas.dataset.index, 10);
805
- const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
808
+ for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
809
+ const globalPixelOffset = canvasIdx * import_core.MAX_CANVAS_WIDTH;
806
810
  const ctx = canvas.getContext("2d");
807
811
  const h2 = Math.floor(waveHeight / 2);
808
812
  const maxValue = 2 ** (bits - 1);
@@ -847,6 +851,7 @@ var Channel = (props) => {
847
851
  }
848
852
  }
849
853
  }, [
854
+ canvasMapRef,
850
855
  data,
851
856
  bits,
852
857
  waveHeight,
@@ -857,11 +862,11 @@ var Channel = (props) => {
857
862
  barWidth,
858
863
  barGap,
859
864
  drawMode,
860
- visibleChunkKey
865
+ visibleChunkIndices
861
866
  ]);
862
867
  const waveforms = visibleChunkIndices.map((i) => {
863
- const chunkLeft = i * MAX_CANVAS_WIDTH;
864
- const currentWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
868
+ const chunkLeft = i * import_core.MAX_CANVAS_WIDTH;
869
+ const currentWidth = Math.min(length - chunkLeft, import_core.MAX_CANVAS_WIDTH);
865
870
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
866
871
  Waveform,
867
872
  {
@@ -892,7 +897,7 @@ var Channel = (props) => {
892
897
  };
893
898
 
894
899
  // src/components/ErrorBoundary.tsx
895
- var import_react3 = __toESM(require("react"));
900
+ var import_react4 = __toESM(require("react"));
896
901
  var import_jsx_runtime5 = require("react/jsx-runtime");
897
902
  var errorContainerStyle = {
898
903
  padding: "16px",
@@ -907,7 +912,7 @@ var errorContainerStyle = {
907
912
  alignItems: "center",
908
913
  justifyContent: "center"
909
914
  };
910
- var PlaylistErrorBoundary = class extends import_react3.default.Component {
915
+ var PlaylistErrorBoundary = class extends import_react4.default.Component {
911
916
  constructor(props) {
912
917
  super(props);
913
918
  this.state = { hasError: false, error: null };
@@ -931,7 +936,7 @@ var PlaylistErrorBoundary = class extends import_react3.default.Component {
931
936
 
932
937
  // src/components/Clip.tsx
933
938
  var import_styled_components13 = __toESM(require("styled-components"));
934
- var import_core = require("@dnd-kit/core");
939
+ var import_core2 = require("@dnd-kit/core");
935
940
  var import_utilities = require("@dnd-kit/utilities");
936
941
 
937
942
  // src/components/ClipHeader.tsx
@@ -1020,7 +1025,7 @@ var ClipHeader = ({
1020
1025
  };
1021
1026
 
1022
1027
  // src/components/ClipBoundary.tsx
1023
- var import_react4 = __toESM(require("react"));
1028
+ var import_react5 = __toESM(require("react"));
1024
1029
  var import_styled_components11 = __toESM(require("styled-components"));
1025
1030
  var import_jsx_runtime7 = require("react/jsx-runtime");
1026
1031
  var CLIP_BOUNDARY_WIDTH = 8;
@@ -1062,7 +1067,7 @@ var ClipBoundary = ({
1062
1067
  dragHandleProps,
1063
1068
  touchOptimized = false
1064
1069
  }) => {
1065
- const [isHovered, setIsHovered] = import_react4.default.useState(false);
1070
+ const [isHovered, setIsHovered] = import_react5.default.useState(false);
1066
1071
  if (!dragHandleProps) {
1067
1072
  return null;
1068
1073
  }
@@ -1207,7 +1212,7 @@ var Clip = ({
1207
1212
  const width = endPixel - left;
1208
1213
  const enableDrag = showHeader && !disableHeaderDrag && !isOverlay;
1209
1214
  const draggableId = `clip-${trackIndex}-${clipIndex}`;
1210
- const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging } = (0, import_core.useDraggable)({
1215
+ const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging } = (0, import_core2.useDraggable)({
1211
1216
  id: draggableId,
1212
1217
  data: { clipId, trackIndex, clipIndex },
1213
1218
  disabled: !enableDrag
@@ -1218,7 +1223,7 @@ var Clip = ({
1218
1223
  listeners: leftBoundaryListeners,
1219
1224
  setActivatorNodeRef: setLeftBoundaryActivatorRef,
1220
1225
  isDragging: isLeftBoundaryDragging
1221
- } = (0, import_core.useDraggable)({
1226
+ } = (0, import_core2.useDraggable)({
1222
1227
  id: leftBoundaryId,
1223
1228
  data: { clipId, trackIndex, clipIndex, boundary: "left" },
1224
1229
  disabled: !enableDrag
@@ -1229,7 +1234,7 @@ var Clip = ({
1229
1234
  listeners: rightBoundaryListeners,
1230
1235
  setActivatorNodeRef: setRightBoundaryActivatorRef,
1231
1236
  isDragging: isRightBoundaryDragging
1232
- } = (0, import_core.useDraggable)({
1237
+ } = (0, import_core2.useDraggable)({
1233
1238
  id: rightBoundaryId,
1234
1239
  data: { clipId, trackIndex, clipIndex, boundary: "right" },
1235
1240
  disabled: !enableDrag
@@ -1365,7 +1370,7 @@ var MasterVolumeControl = ({
1365
1370
  };
1366
1371
 
1367
1372
  // src/components/Playhead.tsx
1368
- var import_react5 = require("react");
1373
+ var import_react6 = require("react");
1369
1374
  var import_styled_components15 = __toESM(require("styled-components"));
1370
1375
  var import_jsx_runtime11 = require("react/jsx-runtime");
1371
1376
  var PlayheadLine = import_styled_components15.default.div.attrs((props) => ({
@@ -1424,9 +1429,9 @@ var PlayheadWithMarker = ({
1424
1429
  controlsOffset,
1425
1430
  getAudioContextTime
1426
1431
  }) => {
1427
- const containerRef = (0, import_react5.useRef)(null);
1428
- const animationFrameRef = (0, import_react5.useRef)(null);
1429
- (0, import_react5.useEffect)(() => {
1432
+ const containerRef = (0, import_react6.useRef)(null);
1433
+ const animationFrameRef = (0, import_react6.useRef)(null);
1434
+ (0, import_react6.useEffect)(() => {
1430
1435
  const updatePosition = () => {
1431
1436
  if (containerRef.current) {
1432
1437
  let time;
@@ -1455,7 +1460,7 @@ var PlayheadWithMarker = ({
1455
1460
  }
1456
1461
  };
1457
1462
  }, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef, playbackStartTimeRef, audioStartPositionRef, getAudioContextTime]);
1458
- (0, import_react5.useEffect)(() => {
1463
+ (0, import_react6.useEffect)(() => {
1459
1464
  if (!isPlaying && containerRef.current) {
1460
1465
  const time = currentTimeRef.current ?? 0;
1461
1466
  const pos = time * sampleRate / samplesPerPixel + controlsOffset;
@@ -1470,7 +1475,7 @@ var PlayheadWithMarker = ({
1470
1475
 
1471
1476
  // src/components/Playlist.tsx
1472
1477
  var import_styled_components16 = __toESM(require("styled-components"));
1473
- var import_react6 = require("react");
1478
+ var import_react7 = require("react");
1474
1479
  var import_jsx_runtime12 = require("react/jsx-runtime");
1475
1480
  var Wrapper2 = import_styled_components16.default.div`
1476
1481
  overflow-y: hidden;
@@ -1525,8 +1530,8 @@ var Playlist = ({
1525
1530
  isSelecting,
1526
1531
  "data-playlist-state": playlistState
1527
1532
  }) => {
1528
- const wrapperRef = (0, import_react6.useRef)(null);
1529
- const handleRef = (0, import_react6.useCallback)((el) => {
1533
+ const wrapperRef = (0, import_react7.useRef)(null);
1534
+ const handleRef = (0, import_react7.useCallback)((el) => {
1530
1535
  wrapperRef.current = el;
1531
1536
  scrollContainerRef?.(el);
1532
1537
  }, [scrollContainerRef]);
@@ -1587,7 +1592,7 @@ var Selection = ({
1587
1592
  };
1588
1593
 
1589
1594
  // src/components/LoopRegion.tsx
1590
- var import_react7 = require("react");
1595
+ var import_react8 = require("react");
1591
1596
  var import_styled_components18 = __toESM(require("styled-components"));
1592
1597
  var import_jsx_runtime14 = require("react/jsx-runtime");
1593
1598
  var LoopRegionOverlayDiv = import_styled_components18.default.div.attrs((props) => ({
@@ -1738,12 +1743,12 @@ var LoopRegionMarkers = ({
1738
1743
  minPosition = 0,
1739
1744
  maxPosition = Infinity
1740
1745
  }) => {
1741
- const [draggingMarker, setDraggingMarker] = (0, import_react7.useState)(null);
1742
- const dragStartX = (0, import_react7.useRef)(0);
1743
- const dragStartPosition = (0, import_react7.useRef)(0);
1744
- const dragStartEnd = (0, import_react7.useRef)(0);
1746
+ const [draggingMarker, setDraggingMarker] = (0, import_react8.useState)(null);
1747
+ const dragStartX = (0, import_react8.useRef)(0);
1748
+ const dragStartPosition = (0, import_react8.useRef)(0);
1749
+ const dragStartEnd = (0, import_react8.useRef)(0);
1745
1750
  const width = Math.max(0, endPosition - startPosition);
1746
- const handleMarkerMouseDown = (0, import_react7.useCallback)((e, marker) => {
1751
+ const handleMarkerMouseDown = (0, import_react8.useCallback)((e, marker) => {
1747
1752
  e.preventDefault();
1748
1753
  e.stopPropagation();
1749
1754
  setDraggingMarker(marker);
@@ -1768,7 +1773,7 @@ var LoopRegionMarkers = ({
1768
1773
  document.addEventListener("mousemove", handleMouseMove);
1769
1774
  document.addEventListener("mouseup", handleMouseUp);
1770
1775
  }, [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]);
1771
- const handleRegionMouseDown = (0, import_react7.useCallback)((e) => {
1776
+ const handleRegionMouseDown = (0, import_react8.useCallback)((e) => {
1772
1777
  e.preventDefault();
1773
1778
  e.stopPropagation();
1774
1779
  setDraggingMarker("region");
@@ -1859,11 +1864,11 @@ var TimescaleLoopRegion = ({
1859
1864
  maxPosition = Infinity,
1860
1865
  controlsOffset = 0
1861
1866
  }) => {
1862
- const [, setIsCreating] = (0, import_react7.useState)(false);
1863
- const createStartX = (0, import_react7.useRef)(0);
1864
- const containerRef = (0, import_react7.useRef)(null);
1867
+ const [, setIsCreating] = (0, import_react8.useState)(false);
1868
+ const createStartX = (0, import_react8.useRef)(0);
1869
+ const containerRef = (0, import_react8.useRef)(null);
1865
1870
  const hasLoopRegion = endPosition > startPosition;
1866
- const handleBackgroundMouseDown = (0, import_react7.useCallback)((e) => {
1871
+ const handleBackgroundMouseDown = (0, import_react8.useCallback)((e) => {
1867
1872
  const target = e.target;
1868
1873
  if (target.closest("[data-loop-marker-handle]") || target.closest("[data-loop-region-timescale]")) {
1869
1874
  return;
@@ -1917,10 +1922,10 @@ var TimescaleLoopRegion = ({
1917
1922
  };
1918
1923
 
1919
1924
  // src/components/SelectionTimeInputs.tsx
1920
- var import_react9 = require("react");
1925
+ var import_react10 = require("react");
1921
1926
 
1922
1927
  // src/components/TimeInput.tsx
1923
- var import_react8 = require("react");
1928
+ var import_react9 = require("react");
1924
1929
 
1925
1930
  // src/utils/timeFormat.ts
1926
1931
  function clockFormat(seconds, decimals) {
@@ -1980,8 +1985,8 @@ var TimeInput = ({
1980
1985
  onChange,
1981
1986
  readOnly = false
1982
1987
  }) => {
1983
- const [displayValue, setDisplayValue] = (0, import_react8.useState)("");
1984
- (0, import_react8.useEffect)(() => {
1988
+ const [displayValue, setDisplayValue] = (0, import_react9.useState)("");
1989
+ (0, import_react9.useEffect)(() => {
1985
1990
  const formatted = formatTime(value, format);
1986
1991
  setDisplayValue(formatted);
1987
1992
  }, [value, format, id]);
@@ -2027,8 +2032,8 @@ var SelectionTimeInputs = ({
2027
2032
  onSelectionChange,
2028
2033
  className
2029
2034
  }) => {
2030
- const [timeFormat, setTimeFormat] = (0, import_react9.useState)("hh:mm:ss.uuu");
2031
- (0, import_react9.useEffect)(() => {
2035
+ const [timeFormat, setTimeFormat] = (0, import_react10.useState)("hh:mm:ss.uuu");
2036
+ (0, import_react10.useEffect)(() => {
2032
2037
  const timeFormatSelect = document.querySelector(".time-format");
2033
2038
  const handleFormatChange = () => {
2034
2039
  if (timeFormatSelect) {
@@ -2080,14 +2085,14 @@ var SelectionTimeInputs = ({
2080
2085
  };
2081
2086
 
2082
2087
  // src/contexts/DevicePixelRatio.tsx
2083
- var import_react10 = require("react");
2088
+ var import_react11 = require("react");
2084
2089
  var import_jsx_runtime17 = require("react/jsx-runtime");
2085
2090
  function getScale() {
2086
2091
  return window.devicePixelRatio;
2087
2092
  }
2088
- var DevicePixelRatioContext = (0, import_react10.createContext)(getScale());
2093
+ var DevicePixelRatioContext = (0, import_react11.createContext)(getScale());
2089
2094
  var DevicePixelRatioProvider = ({ children }) => {
2090
- const [scale, setScale] = (0, import_react10.useState)(getScale());
2095
+ const [scale, setScale] = (0, import_react11.useState)(getScale());
2091
2096
  matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
2092
2097
  "change",
2093
2098
  () => {
@@ -2097,11 +2102,11 @@ var DevicePixelRatioProvider = ({ children }) => {
2097
2102
  );
2098
2103
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
2099
2104
  };
2100
- var useDevicePixelRatio = () => (0, import_react10.useContext)(DevicePixelRatioContext);
2105
+ var useDevicePixelRatio = () => (0, import_react11.useContext)(DevicePixelRatioContext);
2101
2106
 
2102
2107
  // src/contexts/PlaylistInfo.tsx
2103
- var import_react11 = require("react");
2104
- var PlaylistInfoContext = (0, import_react11.createContext)({
2108
+ var import_react12 = require("react");
2109
+ var PlaylistInfoContext = (0, import_react12.createContext)({
2105
2110
  sampleRate: 48e3,
2106
2111
  samplesPerPixel: 1e3,
2107
2112
  zoomLevels: [1e3, 1500, 2e3, 2500],
@@ -2115,21 +2120,21 @@ var PlaylistInfoContext = (0, import_react11.createContext)({
2115
2120
  barWidth: 1,
2116
2121
  barGap: 0
2117
2122
  });
2118
- var usePlaylistInfo = () => (0, import_react11.useContext)(PlaylistInfoContext);
2123
+ var usePlaylistInfo = () => (0, import_react12.useContext)(PlaylistInfoContext);
2119
2124
 
2120
2125
  // src/contexts/Theme.tsx
2121
- var import_react12 = require("react");
2126
+ var import_react13 = require("react");
2122
2127
  var import_styled_components19 = require("styled-components");
2123
- var useTheme2 = () => (0, import_react12.useContext)(import_styled_components19.ThemeContext);
2128
+ var useTheme2 = () => (0, import_react13.useContext)(import_styled_components19.ThemeContext);
2124
2129
 
2125
2130
  // src/contexts/TrackControls.tsx
2126
- var import_react13 = require("react");
2131
+ var import_react14 = require("react");
2127
2132
  var import_jsx_runtime18 = require("react/jsx-runtime");
2128
- var TrackControlsContext = (0, import_react13.createContext)(/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react13.Fragment, {}));
2129
- var useTrackControls = () => (0, import_react13.useContext)(TrackControlsContext);
2133
+ var TrackControlsContext = (0, import_react14.createContext)(/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react14.Fragment, {}));
2134
+ var useTrackControls = () => (0, import_react14.useContext)(TrackControlsContext);
2130
2135
 
2131
2136
  // src/contexts/Playout.tsx
2132
- var import_react14 = require("react");
2137
+ var import_react15 = require("react");
2133
2138
  var import_jsx_runtime19 = require("react/jsx-runtime");
2134
2139
  var defaultProgress = 0;
2135
2140
  var defaultIsPlaying = false;
@@ -2141,8 +2146,8 @@ var defaultPlayout = {
2141
2146
  selectionStart: defaultSelectionStart,
2142
2147
  selectionEnd: defaultSelectionEnd
2143
2148
  };
2144
- var PlayoutStatusContext = (0, import_react14.createContext)(defaultPlayout);
2145
- var PlayoutStatusUpdateContext = (0, import_react14.createContext)({
2149
+ var PlayoutStatusContext = (0, import_react15.createContext)(defaultPlayout);
2150
+ var PlayoutStatusUpdateContext = (0, import_react15.createContext)({
2146
2151
  setIsPlaying: () => {
2147
2152
  },
2148
2153
  setProgress: () => {
@@ -2151,22 +2156,23 @@ var PlayoutStatusUpdateContext = (0, import_react14.createContext)({
2151
2156
  }
2152
2157
  });
2153
2158
  var PlayoutProvider = ({ children }) => {
2154
- const [isPlaying, setIsPlaying] = (0, import_react14.useState)(defaultIsPlaying);
2155
- const [progress, setProgress] = (0, import_react14.useState)(defaultProgress);
2156
- const [selectionStart, setSelectionStart] = (0, import_react14.useState)(defaultSelectionStart);
2157
- const [selectionEnd, setSelectionEnd] = (0, import_react14.useState)(defaultSelectionEnd);
2159
+ const [isPlaying, setIsPlaying] = (0, import_react15.useState)(defaultIsPlaying);
2160
+ const [progress, setProgress] = (0, import_react15.useState)(defaultProgress);
2161
+ const [selectionStart, setSelectionStart] = (0, import_react15.useState)(defaultSelectionStart);
2162
+ const [selectionEnd, setSelectionEnd] = (0, import_react15.useState)(defaultSelectionEnd);
2158
2163
  const setSelection = (start, end) => {
2159
2164
  setSelectionStart(start);
2160
2165
  setSelectionEnd(end);
2161
2166
  };
2162
2167
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
2163
2168
  };
2164
- var usePlayoutStatus = () => (0, import_react14.useContext)(PlayoutStatusContext);
2165
- var usePlayoutStatusUpdate = () => (0, import_react14.useContext)(PlayoutStatusUpdateContext);
2169
+ var usePlayoutStatus = () => (0, import_react15.useContext)(PlayoutStatusContext);
2170
+ var usePlayoutStatusUpdate = () => (0, import_react15.useContext)(PlayoutStatusUpdateContext);
2166
2171
 
2167
2172
  // src/components/SpectrogramChannel.tsx
2168
- var import_react15 = require("react");
2173
+ var import_react16 = require("react");
2169
2174
  var import_styled_components20 = __toESM(require("styled-components"));
2175
+ var import_core3 = require("@waveform-playlist/core");
2170
2176
  var import_jsx_runtime20 = require("react/jsx-runtime");
2171
2177
  var LINEAR_FREQUENCY_SCALE = (f, minF, maxF) => (f - minF) / (maxF - minF);
2172
2178
  var Wrapper3 = import_styled_components20.default.div.attrs((props) => ({
@@ -2220,60 +2226,51 @@ var SpectrogramChannel = ({
2220
2226
  onCanvasesReady
2221
2227
  }) => {
2222
2228
  const channelIndex = channelIndexProp ?? index;
2223
- const canvasesRef = (0, import_react15.useRef)([]);
2224
- const registeredIdsRef = (0, import_react15.useRef)([]);
2225
- const transferredCanvasesRef = (0, import_react15.useRef)(/* @__PURE__ */ new WeakSet());
2226
- const workerApiRef = (0, import_react15.useRef)(workerApi);
2227
- const onCanvasesReadyRef = (0, import_react15.useRef)(onCanvasesReady);
2229
+ const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
2230
+ const registeredIdsRef = (0, import_react16.useRef)([]);
2231
+ const transferredCanvasesRef = (0, import_react16.useRef)(/* @__PURE__ */ new WeakSet());
2232
+ const workerApiRef = (0, import_react16.useRef)(workerApi);
2233
+ const onCanvasesReadyRef = (0, import_react16.useRef)(onCanvasesReady);
2228
2234
  const isWorkerMode = !!(workerApi && clipId);
2229
- const visibleChunkKey = useScrollViewportSelector((viewport) => {
2230
- const totalChunks = Math.ceil(length / MAX_CANVAS_WIDTH);
2231
- const indices = [];
2232
- for (let i = 0; i < totalChunks; i++) {
2233
- const chunkLeft = i * MAX_CANVAS_WIDTH;
2234
- const chunkWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
2235
- if (viewport) {
2236
- const chunkEnd = chunkLeft + chunkWidth;
2237
- if (chunkEnd <= viewport.visibleStart || chunkLeft >= viewport.visibleEnd) {
2238
- continue;
2239
- }
2240
- }
2241
- indices.push(i);
2242
- }
2243
- return indices.join(",");
2244
- });
2245
- const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
2246
- const canvasRef = (0, import_react15.useCallback)(
2247
- (canvas) => {
2248
- if (canvas !== null) {
2249
- const idx = parseInt(canvas.dataset.index, 10);
2250
- canvasesRef.current[idx] = canvas;
2251
- }
2252
- },
2253
- []
2254
- );
2235
+ const visibleChunkIndices = useVisibleChunkIndices(length, import_core3.MAX_CANVAS_WIDTH);
2255
2236
  const lut = colorLUT ?? DEFAULT_COLOR_LUT;
2256
2237
  const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
2257
2238
  const scaleFn = frequencyScaleFn ?? LINEAR_FREQUENCY_SCALE;
2258
2239
  const hasCustomFrequencyScale = Boolean(frequencyScaleFn);
2259
- (0, import_react15.useEffect)(() => {
2240
+ (0, import_react16.useEffect)(() => {
2260
2241
  workerApiRef.current = workerApi;
2261
2242
  }, [workerApi]);
2262
- (0, import_react15.useEffect)(() => {
2243
+ (0, import_react16.useEffect)(() => {
2263
2244
  onCanvasesReadyRef.current = onCanvasesReady;
2264
2245
  }, [onCanvasesReady]);
2265
- (0, import_react15.useEffect)(() => {
2246
+ (0, import_react16.useEffect)(() => {
2266
2247
  if (!isWorkerMode) return;
2267
2248
  const currentWorkerApi = workerApiRef.current;
2268
2249
  if (!currentWorkerApi || !clipId) return;
2269
- const canvases2 = canvasesRef.current;
2250
+ const previousCount = registeredIdsRef.current.length;
2251
+ const remaining = [];
2252
+ for (const id of registeredIdsRef.current) {
2253
+ const match = id.match(/chunk(\d+)$/);
2254
+ if (!match) {
2255
+ remaining.push(id);
2256
+ continue;
2257
+ }
2258
+ const chunkIdx = parseInt(match[1], 10);
2259
+ const canvas = canvasMapRef.current.get(chunkIdx);
2260
+ if (canvas && canvas.isConnected) {
2261
+ remaining.push(id);
2262
+ } else {
2263
+ try {
2264
+ currentWorkerApi.unregisterCanvas(id);
2265
+ } catch (err) {
2266
+ console.warn(`[spectrogram] unregisterCanvas failed for ${id}:`, err);
2267
+ }
2268
+ }
2269
+ }
2270
+ registeredIdsRef.current = remaining;
2270
2271
  const newIds = [];
2271
- const newWidths = [];
2272
- for (let i = 0; i < canvases2.length; i++) {
2273
- const canvas = canvases2[i];
2274
- if (!canvas) continue;
2272
+ for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
2275
2273
  if (transferredCanvasesRef.current.has(canvas)) continue;
2276
- const canvasIdx = parseInt(canvas.dataset.index, 10);
2277
2274
  const canvasId = `${clipId}-ch${channelIndex}-chunk${canvasIdx}`;
2278
2275
  let offscreen;
2279
2276
  try {
@@ -2286,7 +2283,6 @@ var SpectrogramChannel = ({
2286
2283
  try {
2287
2284
  currentWorkerApi.registerCanvas(canvasId, offscreen);
2288
2285
  newIds.push(canvasId);
2289
- newWidths.push(Math.min(length - canvasIdx * MAX_CANVAS_WIDTH, MAX_CANVAS_WIDTH));
2290
2286
  } catch (err) {
2291
2287
  console.warn(`[spectrogram] registerCanvas failed for ${canvasId}:`, err);
2292
2288
  continue;
@@ -2294,35 +2290,23 @@ var SpectrogramChannel = ({
2294
2290
  }
2295
2291
  if (newIds.length > 0) {
2296
2292
  registeredIdsRef.current = [...registeredIdsRef.current, ...newIds];
2297
- onCanvasesReadyRef.current?.(newIds, newWidths);
2298
2293
  }
2299
- }, [isWorkerMode, clipId, channelIndex, length, visibleChunkKey]);
2300
- (0, import_react15.useEffect)(() => {
2301
- if (!isWorkerMode) return;
2302
- const currentWorkerApi = workerApiRef.current;
2303
- if (!currentWorkerApi) return;
2304
- const remaining = [];
2305
- for (const id of registeredIdsRef.current) {
2306
- const match = id.match(/chunk(\d+)$/);
2307
- if (!match) {
2308
- remaining.push(id);
2309
- continue;
2310
- }
2311
- const chunkIdx = parseInt(match[1], 10);
2312
- const canvas = canvasesRef.current[chunkIdx];
2313
- if (canvas && canvas.isConnected) {
2314
- remaining.push(id);
2315
- } else {
2316
- try {
2317
- currentWorkerApi.unregisterCanvas(id);
2318
- } catch (err) {
2319
- console.warn(`[spectrogram] unregisterCanvas failed for ${id}:`, err);
2294
+ const canvasSetChanged = newIds.length > 0 || remaining.length < previousCount;
2295
+ if (canvasSetChanged) {
2296
+ const allIds = registeredIdsRef.current;
2297
+ const allWidths = allIds.map((id) => {
2298
+ const match = id.match(/chunk(\d+)$/);
2299
+ if (!match) {
2300
+ console.warn(`[spectrogram] Unexpected canvas ID format: ${id}`);
2301
+ return import_core3.MAX_CANVAS_WIDTH;
2320
2302
  }
2321
- }
2303
+ const chunkIdx = parseInt(match[1], 10);
2304
+ return Math.min(length - chunkIdx * import_core3.MAX_CANVAS_WIDTH, import_core3.MAX_CANVAS_WIDTH);
2305
+ });
2306
+ onCanvasesReadyRef.current?.(allIds, allWidths);
2322
2307
  }
2323
- registeredIdsRef.current = remaining;
2324
- });
2325
- (0, import_react15.useEffect)(() => {
2308
+ }, [canvasMapRef, isWorkerMode, clipId, channelIndex, length, visibleChunkIndices]);
2309
+ (0, import_react16.useEffect)(() => {
2326
2310
  return () => {
2327
2311
  const api = workerApiRef.current;
2328
2312
  if (!api) return;
@@ -2336,17 +2320,13 @@ var SpectrogramChannel = ({
2336
2320
  registeredIdsRef.current = [];
2337
2321
  };
2338
2322
  }, []);
2339
- (0, import_react15.useLayoutEffect)(() => {
2323
+ (0, import_react16.useLayoutEffect)(() => {
2340
2324
  if (isWorkerMode || !data) return;
2341
- const canvases2 = canvasesRef.current;
2342
2325
  const { frequencyBinCount, frameCount, hopSize, sampleRate, gainDb, rangeDb: rawRangeDb } = data;
2343
2326
  const rangeDb = rawRangeDb === 0 ? 1 : rawRangeDb;
2344
2327
  const binToFreq = (bin) => bin / frequencyBinCount * (sampleRate / 2);
2345
- for (let i = 0; i < canvases2.length; i++) {
2346
- const canvas = canvases2[i];
2347
- if (!canvas) continue;
2348
- const canvasIdx = parseInt(canvas.dataset.index, 10);
2349
- const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
2328
+ for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
2329
+ const globalPixelOffset = canvasIdx * import_core3.MAX_CANVAS_WIDTH;
2350
2330
  const ctx = canvas.getContext("2d");
2351
2331
  if (!ctx) continue;
2352
2332
  const canvasWidth = canvas.width / devicePixelRatio;
@@ -2406,10 +2386,10 @@ var SpectrogramChannel = ({
2406
2386
  ctx.drawImage(tmpCanvas, 0, 0, canvas.width, canvas.height);
2407
2387
  }
2408
2388
  }
2409
- }, [isWorkerMode, data, length, waveHeight, devicePixelRatio, samplesPerPixel, lut, minFrequency, maxF, scaleFn, hasCustomFrequencyScale, visibleChunkKey]);
2389
+ }, [canvasMapRef, isWorkerMode, data, length, waveHeight, devicePixelRatio, samplesPerPixel, lut, minFrequency, maxF, scaleFn, hasCustomFrequencyScale, visibleChunkIndices]);
2410
2390
  const canvases = visibleChunkIndices.map((i) => {
2411
- const chunkLeft = i * MAX_CANVAS_WIDTH;
2412
- const currentWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
2391
+ const chunkLeft = i * import_core3.MAX_CANVAS_WIDTH;
2392
+ const currentWidth = Math.min(length - chunkLeft, import_core3.MAX_CANVAS_WIDTH);
2413
2393
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2414
2394
  SpectrogramCanvas,
2415
2395
  {
@@ -2528,7 +2508,7 @@ var SmartChannel = ({
2528
2508
  };
2529
2509
 
2530
2510
  // src/components/SpectrogramLabels.tsx
2531
- var import_react16 = require("react");
2511
+ var import_react17 = require("react");
2532
2512
  var import_styled_components21 = __toESM(require("styled-components"));
2533
2513
  var import_jsx_runtime22 = require("react/jsx-runtime");
2534
2514
  var LABELS_WIDTH = 72;
@@ -2580,12 +2560,12 @@ var SpectrogramLabels = ({
2580
2560
  renderMode = "spectrogram",
2581
2561
  hasClipHeaders = false
2582
2562
  }) => {
2583
- const canvasRef = (0, import_react16.useRef)(null);
2563
+ const canvasRef = (0, import_react17.useRef)(null);
2584
2564
  const devicePixelRatio = useDevicePixelRatio();
2585
2565
  const spectrogramHeight = renderMode === "both" ? Math.floor(waveHeight / 2) : waveHeight;
2586
2566
  const totalHeight = numChannels * waveHeight;
2587
2567
  const clipHeaderOffset = hasClipHeaders ? 22 : 0;
2588
- (0, import_react16.useLayoutEffect)(() => {
2568
+ (0, import_react17.useLayoutEffect)(() => {
2589
2569
  const canvas = canvasRef.current;
2590
2570
  if (!canvas) return;
2591
2571
  const ctx = canvas.getContext("2d");
@@ -2628,10 +2608,10 @@ var SpectrogramLabels = ({
2628
2608
  };
2629
2609
 
2630
2610
  // src/components/SmartScale.tsx
2631
- var import_react18 = require("react");
2611
+ var import_react19 = require("react");
2632
2612
 
2633
2613
  // src/components/TimeScale.tsx
2634
- var import_react17 = __toESM(require("react"));
2614
+ var import_react18 = __toESM(require("react"));
2635
2615
  var import_styled_components22 = __toESM(require("styled-components"));
2636
2616
 
2637
2617
  // src/utils/conversions.ts
@@ -2655,6 +2635,7 @@ function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
2655
2635
  }
2656
2636
 
2657
2637
  // src/components/TimeScale.tsx
2638
+ var import_core4 = require("@waveform-playlist/core");
2658
2639
  var import_jsx_runtime23 = require("react/jsx-runtime");
2659
2640
  function formatTime2(milliseconds) {
2660
2641
  const seconds = Math.floor(milliseconds / 1e3);
@@ -2706,21 +2687,15 @@ var TimeScale = (props) => {
2706
2687
  secondStep,
2707
2688
  renderTimestamp
2708
2689
  } = props;
2709
- const canvasRefsMap = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
2690
+ const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
2710
2691
  const {
2711
2692
  sampleRate,
2712
2693
  samplesPerPixel,
2713
2694
  timeScaleHeight,
2714
2695
  controls: { show: showControls, width: controlWidth }
2715
- } = (0, import_react17.useContext)(PlaylistInfoContext);
2696
+ } = (0, import_react18.useContext)(PlaylistInfoContext);
2716
2697
  const devicePixelRatio = useDevicePixelRatio();
2717
- const canvasRefCallback = (0, import_react17.useCallback)((canvas) => {
2718
- if (canvas !== null) {
2719
- const idx = parseInt(canvas.dataset.index, 10);
2720
- canvasRefsMap.current.set(idx, canvas);
2721
- }
2722
- }, []);
2723
- const { widthX, canvasInfo, timeMarkersWithPositions } = (0, import_react17.useMemo)(() => {
2698
+ const { widthX, canvasInfo, timeMarkersWithPositions } = (0, import_react18.useMemo)(() => {
2724
2699
  const nextCanvasInfo = /* @__PURE__ */ new Map();
2725
2700
  const nextMarkers = [];
2726
2701
  const nextWidthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);
@@ -2731,7 +2706,7 @@ var TimeScale = (props) => {
2731
2706
  if (counter % marker === 0) {
2732
2707
  const timeMs = counter;
2733
2708
  const timestamp = formatTime2(timeMs);
2734
- const element = renderTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react17.default.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
2709
+ const element = renderTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react18.default.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
2735
2710
  nextMarkers.push({ pix, element });
2736
2711
  nextCanvasInfo.set(pix, timeScaleHeight);
2737
2712
  } else if (counter % bigStep === 0) {
@@ -2747,26 +2722,10 @@ var TimeScale = (props) => {
2747
2722
  timeMarkersWithPositions: nextMarkers
2748
2723
  };
2749
2724
  }, [duration, samplesPerPixel, sampleRate, marker, bigStep, secondStep, renderTimestamp, timeScaleHeight]);
2750
- const visibleChunkKey = useScrollViewportSelector((viewport) => {
2751
- const totalChunks = Math.ceil(widthX / MAX_CANVAS_WIDTH);
2752
- const indices = [];
2753
- for (let i = 0; i < totalChunks; i++) {
2754
- const chunkLeft = i * MAX_CANVAS_WIDTH;
2755
- const chunkWidth = Math.min(widthX - chunkLeft, MAX_CANVAS_WIDTH);
2756
- if (viewport) {
2757
- const chunkEnd = chunkLeft + chunkWidth;
2758
- if (chunkEnd <= viewport.visibleStart || chunkLeft >= viewport.visibleEnd) {
2759
- continue;
2760
- }
2761
- }
2762
- indices.push(i);
2763
- }
2764
- return indices.join(",");
2765
- });
2766
- const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
2725
+ const visibleChunkIndices = useVisibleChunkIndices(widthX, import_core4.MAX_CANVAS_WIDTH);
2767
2726
  const visibleChunks = visibleChunkIndices.map((i) => {
2768
- const chunkLeft = i * MAX_CANVAS_WIDTH;
2769
- const chunkWidth = Math.min(widthX - chunkLeft, MAX_CANVAS_WIDTH);
2727
+ const chunkLeft = i * import_core4.MAX_CANVAS_WIDTH;
2728
+ const chunkWidth = Math.min(widthX - chunkLeft, import_core4.MAX_CANVAS_WIDTH);
2770
2729
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2771
2730
  TimeTickChunk,
2772
2731
  {
@@ -2776,27 +2735,19 @@ var TimeScale = (props) => {
2776
2735
  width: chunkWidth * devicePixelRatio,
2777
2736
  height: timeScaleHeight * devicePixelRatio,
2778
2737
  "data-index": i,
2779
- ref: canvasRefCallback
2738
+ ref: canvasRef
2780
2739
  },
2781
2740
  `timescale-${i}`
2782
2741
  );
2783
2742
  });
2784
- const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] * MAX_CANVAS_WIDTH : 0;
2785
- const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) * MAX_CANVAS_WIDTH : Infinity;
2743
+ const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] * import_core4.MAX_CANVAS_WIDTH : 0;
2744
+ const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) * import_core4.MAX_CANVAS_WIDTH : Infinity;
2786
2745
  const visibleMarkers = visibleChunkIndices.length > 0 ? timeMarkersWithPositions.filter(({ pix }) => pix >= firstChunkLeft && pix < lastChunkRight).map(({ element }) => element) : timeMarkersWithPositions.map(({ element }) => element);
2787
- (0, import_react17.useEffect)(() => {
2788
- const currentMap = canvasRefsMap.current;
2789
- for (const [idx, canvas] of currentMap.entries()) {
2790
- if (!canvas.isConnected) {
2791
- currentMap.delete(idx);
2792
- }
2793
- }
2794
- });
2795
- (0, import_react17.useLayoutEffect)(() => {
2796
- for (const [chunkIdx, canvas] of canvasRefsMap.current.entries()) {
2746
+ (0, import_react18.useLayoutEffect)(() => {
2747
+ for (const [chunkIdx, canvas] of canvasMapRef.current.entries()) {
2797
2748
  const ctx = canvas.getContext("2d");
2798
2749
  if (!ctx) continue;
2799
- const chunkLeft = chunkIdx * MAX_CANVAS_WIDTH;
2750
+ const chunkLeft = chunkIdx * import_core4.MAX_CANVAS_WIDTH;
2800
2751
  const chunkWidth = canvas.width / devicePixelRatio;
2801
2752
  ctx.resetTransform();
2802
2753
  ctx.clearRect(0, 0, canvas.width, canvas.height);
@@ -2810,7 +2761,7 @@ var TimeScale = (props) => {
2810
2761
  ctx.fillRect(localX, scaleY, 1, scaleHeight);
2811
2762
  }
2812
2763
  }
2813
- }, [duration, devicePixelRatio, timeColor, timeScaleHeight, canvasInfo, visibleChunkKey]);
2764
+ }, [canvasMapRef, duration, devicePixelRatio, timeColor, timeScaleHeight, canvasInfo, visibleChunkIndices]);
2814
2765
  return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
2815
2766
  PlaylistTimeScaleScroll,
2816
2767
  {
@@ -2901,7 +2852,7 @@ function getScaleInfo(samplesPerPixel) {
2901
2852
  return config;
2902
2853
  }
2903
2854
  var SmartScale = ({ renderTimestamp }) => {
2904
- const { samplesPerPixel, duration } = (0, import_react18.useContext)(PlaylistInfoContext);
2855
+ const { samplesPerPixel, duration } = (0, import_react19.useContext)(PlaylistInfoContext);
2905
2856
  let config = getScaleInfo(samplesPerPixel);
2906
2857
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2907
2858
  StyledTimeScale,
@@ -3136,7 +3087,7 @@ var ButtonGroup = import_styled_components26.default.div`
3136
3087
 
3137
3088
  // src/components/TrackControls/CloseButton.tsx
3138
3089
  var import_styled_components27 = __toESM(require("styled-components"));
3139
- var import_react19 = require("@phosphor-icons/react");
3090
+ var import_react20 = require("@phosphor-icons/react");
3140
3091
  var import_jsx_runtime27 = require("react/jsx-runtime");
3141
3092
  var StyledCloseButton = import_styled_components27.default.button`
3142
3093
  position: absolute;
@@ -3162,7 +3113,7 @@ var StyledCloseButton = import_styled_components27.default.button`
3162
3113
  var CloseButton = ({
3163
3114
  onClick,
3164
3115
  title = "Remove track"
3165
- }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StyledCloseButton, { onClick, title, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react19.X, { size: 12, weight: "bold" }) });
3116
+ }) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StyledCloseButton, { onClick, title, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react20.X, { size: 12, weight: "bold" }) });
3166
3117
 
3167
3118
  // src/components/TrackControls/Controls.tsx
3168
3119
  var import_styled_components28 = __toESM(require("styled-components"));
@@ -3197,24 +3148,24 @@ var Header = import_styled_components29.default.header`
3197
3148
  `;
3198
3149
 
3199
3150
  // src/components/TrackControls/VolumeDownIcon.tsx
3200
- var import_react20 = require("@phosphor-icons/react");
3151
+ var import_react21 = require("@phosphor-icons/react");
3201
3152
  var import_jsx_runtime28 = require("react/jsx-runtime");
3202
- var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react20.SpeakerLowIcon, { weight: "light", ...props });
3153
+ var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react21.SpeakerLowIcon, { weight: "light", ...props });
3203
3154
 
3204
3155
  // src/components/TrackControls/VolumeUpIcon.tsx
3205
- var import_react21 = require("@phosphor-icons/react");
3156
+ var import_react22 = require("@phosphor-icons/react");
3206
3157
  var import_jsx_runtime29 = require("react/jsx-runtime");
3207
- var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react21.SpeakerHighIcon, { weight: "light", ...props });
3158
+ var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react22.SpeakerHighIcon, { weight: "light", ...props });
3208
3159
 
3209
3160
  // src/components/TrackControls/TrashIcon.tsx
3210
- var import_react22 = require("@phosphor-icons/react");
3161
+ var import_react23 = require("@phosphor-icons/react");
3211
3162
  var import_jsx_runtime30 = require("react/jsx-runtime");
3212
- var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react22.TrashIcon, { weight: "light", ...props });
3163
+ var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react23.TrashIcon, { weight: "light", ...props });
3213
3164
 
3214
3165
  // src/components/TrackControls/DotsIcon.tsx
3215
- var import_react23 = require("@phosphor-icons/react");
3166
+ var import_react24 = require("@phosphor-icons/react");
3216
3167
  var import_jsx_runtime31 = require("react/jsx-runtime");
3217
- var DotsIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react23.DotsThreeIcon, { weight: "bold", ...props });
3168
+ var DotsIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react24.DotsThreeIcon, { weight: "bold", ...props });
3218
3169
 
3219
3170
  // src/components/TrackControls/Slider.tsx
3220
3171
  var import_styled_components30 = __toESM(require("styled-components"));
@@ -3282,7 +3233,7 @@ var SliderWrapper = import_styled_components31.default.label`
3282
3233
  `;
3283
3234
 
3284
3235
  // src/components/TrackMenu.tsx
3285
- var import_react24 = __toESM(require("react"));
3236
+ var import_react25 = __toESM(require("react"));
3286
3237
  var import_react_dom = require("react-dom");
3287
3238
  var import_styled_components32 = __toESM(require("styled-components"));
3288
3239
  var import_jsx_runtime32 = require("react/jsx-runtime");
@@ -3326,13 +3277,13 @@ var Divider = import_styled_components32.default.hr`
3326
3277
  var TrackMenu = ({
3327
3278
  items: itemsProp
3328
3279
  }) => {
3329
- const [open, setOpen] = (0, import_react24.useState)(false);
3280
+ const [open, setOpen] = (0, import_react25.useState)(false);
3330
3281
  const close = () => setOpen(false);
3331
3282
  const items = typeof itemsProp === "function" ? itemsProp(close) : itemsProp;
3332
- const [dropdownPos, setDropdownPos] = (0, import_react24.useState)({ top: 0, left: 0 });
3333
- const buttonRef = (0, import_react24.useRef)(null);
3334
- const dropdownRef = (0, import_react24.useRef)(null);
3335
- (0, import_react24.useEffect)(() => {
3283
+ const [dropdownPos, setDropdownPos] = (0, import_react25.useState)({ top: 0, left: 0 });
3284
+ const buttonRef = (0, import_react25.useRef)(null);
3285
+ const dropdownRef = (0, import_react25.useRef)(null);
3286
+ (0, import_react25.useEffect)(() => {
3336
3287
  if (open && buttonRef.current) {
3337
3288
  const rect = buttonRef.current.getBoundingClientRect();
3338
3289
  setDropdownPos({
@@ -3341,7 +3292,7 @@ var TrackMenu = ({
3341
3292
  });
3342
3293
  }
3343
3294
  }, [open]);
3344
- (0, import_react24.useEffect)(() => {
3295
+ (0, import_react25.useEffect)(() => {
3345
3296
  if (!open) return;
3346
3297
  const handleClick = (e) => {
3347
3298
  const target = e.target;
@@ -3375,7 +3326,7 @@ var TrackMenu = ({
3375
3326
  $top: dropdownPos.top,
3376
3327
  $left: dropdownPos.left,
3377
3328
  onMouseDown: (e) => e.stopPropagation(),
3378
- children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react24.default.Fragment, { children: [
3329
+ children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react25.default.Fragment, { children: [
3379
3330
  index > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Divider, {}),
3380
3331
  item.content
3381
3332
  ] }, item.id))
@@ -3417,7 +3368,6 @@ var TrackMenu = ({
3417
3368
  InlineLabel,
3418
3369
  LoopRegion,
3419
3370
  LoopRegionMarkers,
3420
- MAX_CANVAS_WIDTH,
3421
3371
  MasterVolumeControl,
3422
3372
  Playhead,
3423
3373
  PlayheadWithMarker,
@@ -3466,6 +3416,7 @@ var TrackMenu = ({
3466
3416
  useScrollViewportSelector,
3467
3417
  useTheme,
3468
3418
  useTrackControls,
3419
+ useVisibleChunkIndices,
3469
3420
  waveformColorToCss
3470
3421
  });
3471
3422
  //# sourceMappingURL=index.js.map