@waveform-playlist/ui-components 7.1.1 → 7.1.3
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.d.mts +33 -9
- package/dist/index.d.ts +33 -9
- package/dist/index.js +536 -522
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +469 -456
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -5
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ __export(index_exports, {
|
|
|
51
51
|
ClipBoundary: () => ClipBoundary,
|
|
52
52
|
ClipHeader: () => ClipHeader,
|
|
53
53
|
ClipHeaderPresentational: () => ClipHeaderPresentational,
|
|
54
|
+
ClipViewportOriginProvider: () => ClipViewportOriginProvider,
|
|
54
55
|
CloseButton: () => CloseButton,
|
|
55
56
|
Controls: () => Controls,
|
|
56
57
|
DevicePixelRatioProvider: () => DevicePixelRatioProvider,
|
|
@@ -60,7 +61,6 @@ __export(index_exports, {
|
|
|
60
61
|
InlineLabel: () => InlineLabel,
|
|
61
62
|
LoopRegion: () => LoopRegion,
|
|
62
63
|
LoopRegionMarkers: () => LoopRegionMarkers,
|
|
63
|
-
MAX_CANVAS_WIDTH: () => MAX_CANVAS_WIDTH,
|
|
64
64
|
MasterVolumeControl: () => MasterVolumeControl,
|
|
65
65
|
Playhead: () => Playhead,
|
|
66
66
|
PlayheadWithMarker: () => PlayheadWithMarker,
|
|
@@ -101,6 +101,7 @@ __export(index_exports, {
|
|
|
101
101
|
samplesToSeconds: () => samplesToSeconds,
|
|
102
102
|
secondsToPixels: () => secondsToPixels,
|
|
103
103
|
secondsToSamples: () => secondsToSamples,
|
|
104
|
+
useClipViewportOrigin: () => useClipViewportOrigin,
|
|
104
105
|
useDevicePixelRatio: () => useDevicePixelRatio,
|
|
105
106
|
usePlaylistInfo: () => usePlaylistInfo,
|
|
106
107
|
usePlayoutStatus: () => usePlayoutStatus,
|
|
@@ -109,6 +110,7 @@ __export(index_exports, {
|
|
|
109
110
|
useScrollViewportSelector: () => useScrollViewportSelector,
|
|
110
111
|
useTheme: () => useTheme2,
|
|
111
112
|
useTrackControls: () => useTrackControls,
|
|
113
|
+
useVisibleChunkIndices: () => useVisibleChunkIndices,
|
|
112
114
|
waveformColorToCss: () => waveformColorToCss
|
|
113
115
|
});
|
|
114
116
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -123,10 +125,7 @@ var PositionDisplay = import_styled_components.default.span`
|
|
|
123
125
|
color: ${(props) => props.theme?.textColor || "#333"};
|
|
124
126
|
user-select: none;
|
|
125
127
|
`;
|
|
126
|
-
var AudioPosition = ({
|
|
127
|
-
formattedTime,
|
|
128
|
-
className
|
|
129
|
-
}) => {
|
|
128
|
+
var AudioPosition = ({ formattedTime, className }) => {
|
|
130
129
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PositionDisplay, { className, "aria-label": "Audio position", children: formattedTime });
|
|
131
130
|
};
|
|
132
131
|
|
|
@@ -146,7 +145,9 @@ var BaseButton = import_styled_components2.default.button`
|
|
|
146
145
|
border-radius: ${(props) => props.theme.borderRadius};
|
|
147
146
|
cursor: pointer;
|
|
148
147
|
outline: none;
|
|
149
|
-
transition:
|
|
148
|
+
transition:
|
|
149
|
+
background-color 0.15s ease-in-out,
|
|
150
|
+
border-color 0.15s ease-in-out,
|
|
150
151
|
box-shadow 0.15s ease-in-out;
|
|
151
152
|
|
|
152
153
|
&:hover:not(:disabled) {
|
|
@@ -243,7 +244,9 @@ var BaseInput = import_styled_components5.default.input`
|
|
|
243
244
|
border: 1px solid ${(props) => props.theme.inputBorder};
|
|
244
245
|
border-radius: ${(props) => props.theme.borderRadius};
|
|
245
246
|
outline: none;
|
|
246
|
-
transition:
|
|
247
|
+
transition:
|
|
248
|
+
border-color 0.15s ease-in-out,
|
|
249
|
+
box-shadow 0.15s ease-in-out;
|
|
247
250
|
|
|
248
251
|
&::placeholder {
|
|
249
252
|
color: ${(props) => props.theme.inputPlaceholder};
|
|
@@ -311,7 +314,9 @@ var BaseSelect = import_styled_components7.default.select`
|
|
|
311
314
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
|
|
312
315
|
background-repeat: no-repeat;
|
|
313
316
|
background-position: right 0.75rem center;
|
|
314
|
-
transition:
|
|
317
|
+
transition:
|
|
318
|
+
border-color 0.15s ease-in-out,
|
|
319
|
+
box-shadow 0.15s ease-in-out;
|
|
315
320
|
|
|
316
321
|
&:focus {
|
|
317
322
|
border-color: ${(props) => props.theme.inputFocusBorder};
|
|
@@ -357,7 +362,9 @@ var BaseSlider = import_styled_components8.default.input.attrs({ type: "range" }
|
|
|
357
362
|
border-radius: 50%;
|
|
358
363
|
cursor: pointer;
|
|
359
364
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
360
|
-
transition:
|
|
365
|
+
transition:
|
|
366
|
+
transform 0.15s ease,
|
|
367
|
+
box-shadow 0.15s ease;
|
|
361
368
|
}
|
|
362
369
|
|
|
363
370
|
&::-webkit-slider-thumb:hover {
|
|
@@ -374,7 +381,9 @@ var BaseSlider = import_styled_components8.default.input.attrs({ type: "range" }
|
|
|
374
381
|
border-radius: 50%;
|
|
375
382
|
cursor: pointer;
|
|
376
383
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
377
|
-
transition:
|
|
384
|
+
transition:
|
|
385
|
+
transform 0.15s ease,
|
|
386
|
+
box-shadow 0.15s ease;
|
|
378
387
|
}
|
|
379
388
|
|
|
380
389
|
&::-moz-range-thumb:hover {
|
|
@@ -442,7 +451,7 @@ var AutomaticScrollCheckbox = ({
|
|
|
442
451
|
};
|
|
443
452
|
|
|
444
453
|
// src/components/Channel.tsx
|
|
445
|
-
var
|
|
454
|
+
var import_react4 = require("react");
|
|
446
455
|
var import_styled_components9 = __toESM(require("styled-components"));
|
|
447
456
|
|
|
448
457
|
// src/wfpl-theme.ts
|
|
@@ -637,10 +646,7 @@ var ViewportStoreContext = (0, import_react.createContext)(null);
|
|
|
637
646
|
var EMPTY_SUBSCRIBE = () => () => {
|
|
638
647
|
};
|
|
639
648
|
var NULL_SNAPSHOT = () => null;
|
|
640
|
-
var ScrollViewportProvider = ({
|
|
641
|
-
containerRef,
|
|
642
|
-
children
|
|
643
|
-
}) => {
|
|
649
|
+
var ScrollViewportProvider = ({ containerRef, children }) => {
|
|
644
650
|
const storeRef = (0, import_react.useRef)(null);
|
|
645
651
|
if (storeRef.current === null) {
|
|
646
652
|
storeRef.current = new ViewportStore();
|
|
@@ -695,12 +701,64 @@ function useScrollViewportSelector(selector) {
|
|
|
695
701
|
() => selector(null)
|
|
696
702
|
);
|
|
697
703
|
}
|
|
704
|
+
function useVisibleChunkIndices(totalWidth, chunkWidth, originX = 0) {
|
|
705
|
+
const visibleChunkKey = useScrollViewportSelector((viewport) => {
|
|
706
|
+
const totalChunks = Math.ceil(totalWidth / chunkWidth);
|
|
707
|
+
const indices = [];
|
|
708
|
+
for (let i = 0; i < totalChunks; i++) {
|
|
709
|
+
const chunkLeft = i * chunkWidth;
|
|
710
|
+
const thisChunkWidth = Math.min(totalWidth - chunkLeft, chunkWidth);
|
|
711
|
+
if (viewport) {
|
|
712
|
+
const chunkLeftGlobal = originX + chunkLeft;
|
|
713
|
+
const chunkEndGlobal = chunkLeftGlobal + thisChunkWidth;
|
|
714
|
+
if (chunkEndGlobal <= viewport.visibleStart || chunkLeftGlobal >= viewport.visibleEnd) {
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
indices.push(i);
|
|
719
|
+
}
|
|
720
|
+
return indices.join(",");
|
|
721
|
+
});
|
|
722
|
+
return (0, import_react.useMemo)(
|
|
723
|
+
() => visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [],
|
|
724
|
+
[visibleChunkKey]
|
|
725
|
+
);
|
|
726
|
+
}
|
|
698
727
|
|
|
699
|
-
// src/
|
|
700
|
-
var
|
|
728
|
+
// src/contexts/ClipViewportOrigin.tsx
|
|
729
|
+
var import_react2 = require("react");
|
|
730
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
731
|
+
var ClipViewportOriginContext = (0, import_react2.createContext)(0);
|
|
732
|
+
var ClipViewportOriginProvider = ({
|
|
733
|
+
originX,
|
|
734
|
+
children
|
|
735
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ClipViewportOriginContext.Provider, { value: originX, children });
|
|
736
|
+
var useClipViewportOrigin = () => (0, import_react2.useContext)(ClipViewportOriginContext);
|
|
737
|
+
|
|
738
|
+
// src/hooks/useChunkedCanvasRefs.ts
|
|
739
|
+
var import_react3 = require("react");
|
|
740
|
+
function useChunkedCanvasRefs() {
|
|
741
|
+
const canvasMapRef = (0, import_react3.useRef)(/* @__PURE__ */ new Map());
|
|
742
|
+
const canvasRef = (0, import_react3.useCallback)((canvas) => {
|
|
743
|
+
if (canvas !== null) {
|
|
744
|
+
const idx = parseInt(canvas.dataset.index, 10);
|
|
745
|
+
canvasMapRef.current.set(idx, canvas);
|
|
746
|
+
}
|
|
747
|
+
}, []);
|
|
748
|
+
(0, import_react3.useEffect)(() => {
|
|
749
|
+
const map = canvasMapRef.current;
|
|
750
|
+
for (const [idx, canvas] of map.entries()) {
|
|
751
|
+
if (!canvas.isConnected) {
|
|
752
|
+
map.delete(idx);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
});
|
|
756
|
+
return { canvasRef, canvasMapRef };
|
|
757
|
+
}
|
|
701
758
|
|
|
702
759
|
// src/components/Channel.tsx
|
|
703
|
-
var
|
|
760
|
+
var import_core = require("@waveform-playlist/core");
|
|
761
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
704
762
|
function createCanvasFillStyle(ctx, color, width, height) {
|
|
705
763
|
if (!isWaveformGradient(color)) {
|
|
706
764
|
return color;
|
|
@@ -760,49 +818,13 @@ var Channel = (props) => {
|
|
|
760
818
|
transparentBackground = false,
|
|
761
819
|
drawMode = "inverted"
|
|
762
820
|
} = props;
|
|
763
|
-
const
|
|
764
|
-
const
|
|
765
|
-
|
|
766
|
-
|
|
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;
|
|
821
|
+
const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
|
|
822
|
+
const clipOriginX = useClipViewportOrigin();
|
|
823
|
+
const visibleChunkIndices = useVisibleChunkIndices(length, import_core.MAX_CANVAS_WIDTH, clipOriginX);
|
|
824
|
+
(0, import_react4.useLayoutEffect)(() => {
|
|
800
825
|
const step = barWidth + barGap;
|
|
801
|
-
for (
|
|
802
|
-
const
|
|
803
|
-
if (!canvas) continue;
|
|
804
|
-
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
805
|
-
const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
|
|
826
|
+
for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
|
|
827
|
+
const globalPixelOffset = canvasIdx * import_core.MAX_CANVAS_WIDTH;
|
|
806
828
|
const ctx = canvas.getContext("2d");
|
|
807
829
|
const h2 = Math.floor(waveHeight / 2);
|
|
808
830
|
const maxValue = 2 ** (bits - 1);
|
|
@@ -818,12 +840,7 @@ var Channel = (props) => {
|
|
|
818
840
|
} else {
|
|
819
841
|
fillColor = waveOutlineColor;
|
|
820
842
|
}
|
|
821
|
-
ctx.fillStyle = createCanvasFillStyle(
|
|
822
|
-
ctx,
|
|
823
|
-
fillColor,
|
|
824
|
-
canvasWidth,
|
|
825
|
-
waveHeight
|
|
826
|
-
);
|
|
843
|
+
ctx.fillStyle = createCanvasFillStyle(ctx, fillColor, canvasWidth, waveHeight);
|
|
827
844
|
const canvasStartGlobal = globalPixelOffset;
|
|
828
845
|
const canvasEndGlobal = globalPixelOffset + canvasWidth;
|
|
829
846
|
const firstBarGlobal = Math.floor((canvasStartGlobal - barWidth + step) / step) * step;
|
|
@@ -847,6 +864,7 @@ var Channel = (props) => {
|
|
|
847
864
|
}
|
|
848
865
|
}
|
|
849
866
|
}, [
|
|
867
|
+
canvasMapRef,
|
|
850
868
|
data,
|
|
851
869
|
bits,
|
|
852
870
|
waveHeight,
|
|
@@ -857,12 +875,12 @@ var Channel = (props) => {
|
|
|
857
875
|
barWidth,
|
|
858
876
|
barGap,
|
|
859
877
|
drawMode,
|
|
860
|
-
|
|
878
|
+
visibleChunkIndices
|
|
861
879
|
]);
|
|
862
880
|
const waveforms = visibleChunkIndices.map((i) => {
|
|
863
|
-
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
864
|
-
const currentWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
|
|
865
|
-
return /* @__PURE__ */ (0,
|
|
881
|
+
const chunkLeft = i * import_core.MAX_CANVAS_WIDTH;
|
|
882
|
+
const currentWidth = Math.min(length - chunkLeft, import_core.MAX_CANVAS_WIDTH);
|
|
883
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
866
884
|
Waveform,
|
|
867
885
|
{
|
|
868
886
|
$cssWidth: currentWidth,
|
|
@@ -878,7 +896,7 @@ var Channel = (props) => {
|
|
|
878
896
|
});
|
|
879
897
|
const bgColor = waveFillColor;
|
|
880
898
|
const backgroundCss = transparentBackground ? "transparent" : waveformColorToCss(bgColor);
|
|
881
|
-
return /* @__PURE__ */ (0,
|
|
899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
882
900
|
Wrapper,
|
|
883
901
|
{
|
|
884
902
|
$index: index,
|
|
@@ -892,8 +910,8 @@ var Channel = (props) => {
|
|
|
892
910
|
};
|
|
893
911
|
|
|
894
912
|
// src/components/ErrorBoundary.tsx
|
|
895
|
-
var
|
|
896
|
-
var
|
|
913
|
+
var import_react5 = __toESM(require("react"));
|
|
914
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
897
915
|
var errorContainerStyle = {
|
|
898
916
|
padding: "16px",
|
|
899
917
|
background: "#1a1a2e",
|
|
@@ -907,7 +925,7 @@ var errorContainerStyle = {
|
|
|
907
925
|
alignItems: "center",
|
|
908
926
|
justifyContent: "center"
|
|
909
927
|
};
|
|
910
|
-
var PlaylistErrorBoundary = class extends
|
|
928
|
+
var PlaylistErrorBoundary = class extends import_react5.default.Component {
|
|
911
929
|
constructor(props) {
|
|
912
930
|
super(props);
|
|
913
931
|
this.state = { hasError: false, error: null };
|
|
@@ -923,7 +941,7 @@ var PlaylistErrorBoundary = class extends import_react3.default.Component {
|
|
|
923
941
|
if (this.props.fallback) {
|
|
924
942
|
return this.props.fallback;
|
|
925
943
|
}
|
|
926
|
-
return /* @__PURE__ */ (0,
|
|
944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: errorContainerStyle, children: "Waveform playlist encountered an error. Check console for details." });
|
|
927
945
|
}
|
|
928
946
|
return this.props.children;
|
|
929
947
|
}
|
|
@@ -931,12 +949,12 @@ var PlaylistErrorBoundary = class extends import_react3.default.Component {
|
|
|
931
949
|
|
|
932
950
|
// src/components/Clip.tsx
|
|
933
951
|
var import_styled_components13 = __toESM(require("styled-components"));
|
|
934
|
-
var
|
|
952
|
+
var import_core2 = require("@dnd-kit/core");
|
|
935
953
|
var import_utilities = require("@dnd-kit/utilities");
|
|
936
954
|
|
|
937
955
|
// src/components/ClipHeader.tsx
|
|
938
956
|
var import_styled_components10 = __toESM(require("styled-components"));
|
|
939
|
-
var
|
|
957
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
940
958
|
var CLIP_HEADER_HEIGHT = 22;
|
|
941
959
|
var HeaderContainer = import_styled_components10.default.div`
|
|
942
960
|
position: relative;
|
|
@@ -976,15 +994,7 @@ var ClipHeaderPresentational = ({
|
|
|
976
994
|
trackName,
|
|
977
995
|
isSelected = false
|
|
978
996
|
}) => {
|
|
979
|
-
return /* @__PURE__ */ (0,
|
|
980
|
-
HeaderContainer,
|
|
981
|
-
{
|
|
982
|
-
$isDragging: false,
|
|
983
|
-
$interactive: false,
|
|
984
|
-
$isSelected: isSelected,
|
|
985
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TrackName, { children: trackName })
|
|
986
|
-
}
|
|
987
|
-
);
|
|
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 }) });
|
|
988
998
|
};
|
|
989
999
|
var ClipHeader = ({
|
|
990
1000
|
clipId,
|
|
@@ -996,16 +1006,10 @@ var ClipHeader = ({
|
|
|
996
1006
|
dragHandleProps
|
|
997
1007
|
}) => {
|
|
998
1008
|
if (disableDrag || !dragHandleProps) {
|
|
999
|
-
return /* @__PURE__ */ (0,
|
|
1000
|
-
ClipHeaderPresentational,
|
|
1001
|
-
{
|
|
1002
|
-
trackName,
|
|
1003
|
-
isSelected
|
|
1004
|
-
}
|
|
1005
|
-
);
|
|
1009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ClipHeaderPresentational, { trackName, isSelected });
|
|
1006
1010
|
}
|
|
1007
1011
|
const { attributes, listeners, setActivatorNodeRef } = dragHandleProps;
|
|
1008
|
-
return /* @__PURE__ */ (0,
|
|
1012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1009
1013
|
HeaderContainer,
|
|
1010
1014
|
{
|
|
1011
1015
|
ref: setActivatorNodeRef,
|
|
@@ -1014,15 +1018,15 @@ var ClipHeader = ({
|
|
|
1014
1018
|
$isSelected: isSelected,
|
|
1015
1019
|
...listeners,
|
|
1016
1020
|
...attributes,
|
|
1017
|
-
children: /* @__PURE__ */ (0,
|
|
1021
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TrackName, { children: trackName })
|
|
1018
1022
|
}
|
|
1019
1023
|
);
|
|
1020
1024
|
};
|
|
1021
1025
|
|
|
1022
1026
|
// src/components/ClipBoundary.tsx
|
|
1023
|
-
var
|
|
1027
|
+
var import_react6 = __toESM(require("react"));
|
|
1024
1028
|
var import_styled_components11 = __toESM(require("styled-components"));
|
|
1025
|
-
var
|
|
1029
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1026
1030
|
var CLIP_BOUNDARY_WIDTH = 8;
|
|
1027
1031
|
var CLIP_BOUNDARY_WIDTH_TOUCH = 24;
|
|
1028
1032
|
var BoundaryContainer = import_styled_components11.default.div`
|
|
@@ -1062,12 +1066,12 @@ var ClipBoundary = ({
|
|
|
1062
1066
|
dragHandleProps,
|
|
1063
1067
|
touchOptimized = false
|
|
1064
1068
|
}) => {
|
|
1065
|
-
const [isHovered, setIsHovered] =
|
|
1069
|
+
const [isHovered, setIsHovered] = import_react6.default.useState(false);
|
|
1066
1070
|
if (!dragHandleProps) {
|
|
1067
1071
|
return null;
|
|
1068
1072
|
}
|
|
1069
1073
|
const { attributes, listeners, setActivatorNodeRef, isDragging } = dragHandleProps;
|
|
1070
|
-
return /* @__PURE__ */ (0,
|
|
1074
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1071
1075
|
BoundaryContainer,
|
|
1072
1076
|
{
|
|
1073
1077
|
ref: setActivatorNodeRef,
|
|
@@ -1087,7 +1091,7 @@ var ClipBoundary = ({
|
|
|
1087
1091
|
|
|
1088
1092
|
// src/components/FadeOverlay.tsx
|
|
1089
1093
|
var import_styled_components12 = __toESM(require("styled-components"));
|
|
1090
|
-
var
|
|
1094
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1091
1095
|
var FadeContainer = import_styled_components12.default.div.attrs((props) => ({
|
|
1092
1096
|
style: {
|
|
1093
1097
|
left: `${props.$left}px`,
|
|
@@ -1144,17 +1148,11 @@ var FadeOverlay = ({
|
|
|
1144
1148
|
const theme = (0, import_styled_components12.useTheme)();
|
|
1145
1149
|
if (width < 1) return null;
|
|
1146
1150
|
const fillColor = color || theme?.fadeOverlayColor || "rgba(0, 0, 0, 0.4)";
|
|
1147
|
-
return /* @__PURE__ */ (0,
|
|
1148
|
-
"path",
|
|
1149
|
-
{
|
|
1150
|
-
d: generateFadePath(width, 100, curveType),
|
|
1151
|
-
fill: fillColor
|
|
1152
|
-
}
|
|
1153
|
-
) }) });
|
|
1151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FadeContainer, { $left: left, $width: width, $type: type, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(FadeSvg, { $type: type, viewBox: `0 0 ${width} 100`, preserveAspectRatio: "none", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: generateFadePath(width, 100, curveType), fill: fillColor }) }) });
|
|
1154
1152
|
};
|
|
1155
1153
|
|
|
1156
1154
|
// src/components/Clip.tsx
|
|
1157
|
-
var
|
|
1155
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1158
1156
|
var ClipContainer = import_styled_components13.default.div.attrs((props) => ({
|
|
1159
1157
|
style: props.$isOverlay ? {} : {
|
|
1160
1158
|
left: `${props.$left}px`,
|
|
@@ -1207,7 +1205,7 @@ var Clip = ({
|
|
|
1207
1205
|
const width = endPixel - left;
|
|
1208
1206
|
const enableDrag = showHeader && !disableHeaderDrag && !isOverlay;
|
|
1209
1207
|
const draggableId = `clip-${trackIndex}-${clipIndex}`;
|
|
1210
|
-
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging } = (0,
|
|
1208
|
+
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging } = (0, import_core2.useDraggable)({
|
|
1211
1209
|
id: draggableId,
|
|
1212
1210
|
data: { clipId, trackIndex, clipIndex },
|
|
1213
1211
|
disabled: !enableDrag
|
|
@@ -1218,7 +1216,7 @@ var Clip = ({
|
|
|
1218
1216
|
listeners: leftBoundaryListeners,
|
|
1219
1217
|
setActivatorNodeRef: setLeftBoundaryActivatorRef,
|
|
1220
1218
|
isDragging: isLeftBoundaryDragging
|
|
1221
|
-
} = (0,
|
|
1219
|
+
} = (0, import_core2.useDraggable)({
|
|
1222
1220
|
id: leftBoundaryId,
|
|
1223
1221
|
data: { clipId, trackIndex, clipIndex, boundary: "left" },
|
|
1224
1222
|
disabled: !enableDrag
|
|
@@ -1229,7 +1227,7 @@ var Clip = ({
|
|
|
1229
1227
|
listeners: rightBoundaryListeners,
|
|
1230
1228
|
setActivatorNodeRef: setRightBoundaryActivatorRef,
|
|
1231
1229
|
isDragging: isRightBoundaryDragging
|
|
1232
|
-
} = (0,
|
|
1230
|
+
} = (0, import_core2.useDraggable)({
|
|
1233
1231
|
id: rightBoundaryId,
|
|
1234
1232
|
data: { clipId, trackIndex, clipIndex, boundary: "right" },
|
|
1235
1233
|
disabled: !enableDrag
|
|
@@ -1239,7 +1237,7 @@ var Clip = ({
|
|
|
1239
1237
|
zIndex: isDragging ? 100 : void 0
|
|
1240
1238
|
// Below controls (z-index: 999) but above other clips
|
|
1241
1239
|
} : void 0;
|
|
1242
|
-
return /* @__PURE__ */ (0,
|
|
1240
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
1243
1241
|
ClipContainer,
|
|
1244
1242
|
{
|
|
1245
1243
|
ref: setNodeRef,
|
|
@@ -1252,7 +1250,7 @@ var Clip = ({
|
|
|
1252
1250
|
"data-track-id": trackId,
|
|
1253
1251
|
onMouseDown,
|
|
1254
1252
|
children: [
|
|
1255
|
-
showHeader && /* @__PURE__ */ (0,
|
|
1253
|
+
showHeader && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1256
1254
|
ClipHeader,
|
|
1257
1255
|
{
|
|
1258
1256
|
clipId,
|
|
@@ -1264,9 +1262,9 @@ var Clip = ({
|
|
|
1264
1262
|
dragHandleProps: enableDrag ? { attributes, listeners, setActivatorNodeRef } : void 0
|
|
1265
1263
|
}
|
|
1266
1264
|
),
|
|
1267
|
-
/* @__PURE__ */ (0,
|
|
1265
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ClipViewportOriginProvider, { originX: left, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ChannelsWrapper, { $isOverlay: isOverlay, children: [
|
|
1268
1266
|
children,
|
|
1269
|
-
showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */ (0,
|
|
1267
|
+
showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1270
1268
|
FadeOverlay,
|
|
1271
1269
|
{
|
|
1272
1270
|
left: 0,
|
|
@@ -1275,7 +1273,7 @@ var Clip = ({
|
|
|
1275
1273
|
curveType: fadeIn.type
|
|
1276
1274
|
}
|
|
1277
1275
|
),
|
|
1278
|
-
showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */ (0,
|
|
1276
|
+
showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1279
1277
|
FadeOverlay,
|
|
1280
1278
|
{
|
|
1281
1279
|
left: width - Math.floor(fadeOut.duration * sampleRate / samplesPerPixel),
|
|
@@ -1284,9 +1282,9 @@ var Clip = ({
|
|
|
1284
1282
|
curveType: fadeOut.type
|
|
1285
1283
|
}
|
|
1286
1284
|
)
|
|
1287
|
-
] }),
|
|
1288
|
-
showHeader && !disableHeaderDrag && !isOverlay && /* @__PURE__ */ (0,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1285
|
+
] }) }),
|
|
1286
|
+
showHeader && !disableHeaderDrag && !isOverlay && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
1287
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1290
1288
|
ClipBoundary,
|
|
1291
1289
|
{
|
|
1292
1290
|
clipId,
|
|
@@ -1302,7 +1300,7 @@ var Clip = ({
|
|
|
1302
1300
|
}
|
|
1303
1301
|
}
|
|
1304
1302
|
),
|
|
1305
|
-
/* @__PURE__ */ (0,
|
|
1303
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1306
1304
|
ClipBoundary,
|
|
1307
1305
|
{
|
|
1308
1306
|
clipId,
|
|
@@ -1326,7 +1324,7 @@ var Clip = ({
|
|
|
1326
1324
|
|
|
1327
1325
|
// src/components/MasterVolumeControl.tsx
|
|
1328
1326
|
var import_styled_components14 = __toESM(require("styled-components"));
|
|
1329
|
-
var
|
|
1327
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1330
1328
|
var VolumeContainer = import_styled_components14.default.div`
|
|
1331
1329
|
display: inline-flex;
|
|
1332
1330
|
align-items: center;
|
|
@@ -1348,9 +1346,9 @@ var MasterVolumeControl = ({
|
|
|
1348
1346
|
const handleChange = (e) => {
|
|
1349
1347
|
onChange(parseFloat(e.target.value) / 100);
|
|
1350
1348
|
};
|
|
1351
|
-
return /* @__PURE__ */ (0,
|
|
1352
|
-
/* @__PURE__ */ (0,
|
|
1353
|
-
/* @__PURE__ */ (0,
|
|
1349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(VolumeContainer, { className, children: [
|
|
1350
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(VolumeLabel, { htmlFor: "master-gain", children: "Master Volume" }),
|
|
1351
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1354
1352
|
VolumeSlider,
|
|
1355
1353
|
{
|
|
1356
1354
|
min: "0",
|
|
@@ -1365,9 +1363,9 @@ var MasterVolumeControl = ({
|
|
|
1365
1363
|
};
|
|
1366
1364
|
|
|
1367
1365
|
// src/components/Playhead.tsx
|
|
1368
|
-
var
|
|
1366
|
+
var import_react7 = require("react");
|
|
1369
1367
|
var import_styled_components15 = __toESM(require("styled-components"));
|
|
1370
|
-
var
|
|
1368
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1371
1369
|
var PlayheadLine = import_styled_components15.default.div.attrs((props) => ({
|
|
1372
1370
|
style: {
|
|
1373
1371
|
transform: `translate3d(${props.$position}px, 0, 0)`
|
|
@@ -1384,7 +1382,7 @@ var PlayheadLine = import_styled_components15.default.div.attrs((props) => ({
|
|
|
1384
1382
|
will-change: transform;
|
|
1385
1383
|
`;
|
|
1386
1384
|
var Playhead = ({ position, color = "#ff0000" }) => {
|
|
1387
|
-
return /* @__PURE__ */ (0,
|
|
1385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PlayheadLine, { $position: position, $color: color });
|
|
1388
1386
|
};
|
|
1389
1387
|
var PlayheadWithMarkerContainer = import_styled_components15.default.div`
|
|
1390
1388
|
position: absolute;
|
|
@@ -1424,9 +1422,9 @@ var PlayheadWithMarker = ({
|
|
|
1424
1422
|
controlsOffset,
|
|
1425
1423
|
getAudioContextTime
|
|
1426
1424
|
}) => {
|
|
1427
|
-
const containerRef = (0,
|
|
1428
|
-
const animationFrameRef = (0,
|
|
1429
|
-
(0,
|
|
1425
|
+
const containerRef = (0, import_react7.useRef)(null);
|
|
1426
|
+
const animationFrameRef = (0, import_react7.useRef)(null);
|
|
1427
|
+
(0, import_react7.useEffect)(() => {
|
|
1430
1428
|
const updatePosition = () => {
|
|
1431
1429
|
if (containerRef.current) {
|
|
1432
1430
|
let time;
|
|
@@ -1454,24 +1452,33 @@ var PlayheadWithMarker = ({
|
|
|
1454
1452
|
animationFrameRef.current = null;
|
|
1455
1453
|
}
|
|
1456
1454
|
};
|
|
1457
|
-
}, [
|
|
1458
|
-
|
|
1455
|
+
}, [
|
|
1456
|
+
isPlaying,
|
|
1457
|
+
sampleRate,
|
|
1458
|
+
samplesPerPixel,
|
|
1459
|
+
controlsOffset,
|
|
1460
|
+
currentTimeRef,
|
|
1461
|
+
playbackStartTimeRef,
|
|
1462
|
+
audioStartPositionRef,
|
|
1463
|
+
getAudioContextTime
|
|
1464
|
+
]);
|
|
1465
|
+
(0, import_react7.useEffect)(() => {
|
|
1459
1466
|
if (!isPlaying && containerRef.current) {
|
|
1460
1467
|
const time = currentTimeRef.current ?? 0;
|
|
1461
1468
|
const pos = time * sampleRate / samplesPerPixel + controlsOffset;
|
|
1462
1469
|
containerRef.current.style.transform = `translate3d(${pos}px, 0, 0)`;
|
|
1463
1470
|
}
|
|
1464
1471
|
});
|
|
1465
|
-
return /* @__PURE__ */ (0,
|
|
1466
|
-
/* @__PURE__ */ (0,
|
|
1467
|
-
/* @__PURE__ */ (0,
|
|
1472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(PlayheadWithMarkerContainer, { ref: containerRef, $color: color, children: [
|
|
1473
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkerTriangle, { $color: color }),
|
|
1474
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(MarkerLine, { $color: color })
|
|
1468
1475
|
] });
|
|
1469
1476
|
};
|
|
1470
1477
|
|
|
1471
1478
|
// src/components/Playlist.tsx
|
|
1472
1479
|
var import_styled_components16 = __toESM(require("styled-components"));
|
|
1473
|
-
var
|
|
1474
|
-
var
|
|
1480
|
+
var import_react8 = require("react");
|
|
1481
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1475
1482
|
var Wrapper2 = import_styled_components16.default.div`
|
|
1476
1483
|
overflow-y: hidden;
|
|
1477
1484
|
overflow-x: auto;
|
|
@@ -1525,41 +1532,37 @@ var Playlist = ({
|
|
|
1525
1532
|
isSelecting,
|
|
1526
1533
|
"data-playlist-state": playlistState
|
|
1527
1534
|
}) => {
|
|
1528
|
-
const wrapperRef = (0,
|
|
1529
|
-
const handleRef = (0,
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
] })
|
|
1554
|
-
]
|
|
1555
|
-
}
|
|
1556
|
-
) }) });
|
|
1535
|
+
const wrapperRef = (0, import_react8.useRef)(null);
|
|
1536
|
+
const handleRef = (0, import_react8.useCallback)(
|
|
1537
|
+
(el) => {
|
|
1538
|
+
wrapperRef.current = el;
|
|
1539
|
+
scrollContainerRef?.(el);
|
|
1540
|
+
},
|
|
1541
|
+
[scrollContainerRef]
|
|
1542
|
+
);
|
|
1543
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Wrapper2, { "data-scroll-container": "true", "data-playlist-state": playlistState, ref: handleRef, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScrollViewportProvider, { containerRef: wrapperRef, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(ScrollContainer, { $backgroundColor: backgroundColor, $width: scrollContainerWidth, children: [
|
|
1544
|
+
timescale && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(TimescaleWrapper, { $width: timescaleWidth, $backgroundColor: timescaleBackgroundColor, children: timescale }),
|
|
1545
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(TracksContainer, { $width: tracksWidth, $backgroundColor: backgroundColor, children: [
|
|
1546
|
+
children,
|
|
1547
|
+
(onTracksClick || onTracksMouseDown) && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1548
|
+
ClickOverlay,
|
|
1549
|
+
{
|
|
1550
|
+
$controlsWidth: controlsWidth,
|
|
1551
|
+
$isSelecting: isSelecting,
|
|
1552
|
+
onClick: onTracksClick,
|
|
1553
|
+
onMouseDown: onTracksMouseDown,
|
|
1554
|
+
onMouseMove: onTracksMouseMove,
|
|
1555
|
+
onMouseUp: onTracksMouseUp
|
|
1556
|
+
}
|
|
1557
|
+
)
|
|
1558
|
+
] })
|
|
1559
|
+
] }) }) });
|
|
1557
1560
|
};
|
|
1558
1561
|
var StyledPlaylist = (0, import_styled_components16.withTheme)(Playlist);
|
|
1559
1562
|
|
|
1560
1563
|
// src/components/Selection.tsx
|
|
1561
1564
|
var import_styled_components17 = __toESM(require("styled-components"));
|
|
1562
|
-
var
|
|
1565
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1563
1566
|
var SelectionOverlay = import_styled_components17.default.div.attrs((props) => ({
|
|
1564
1567
|
style: {
|
|
1565
1568
|
left: `${props.$left}px`,
|
|
@@ -1583,13 +1586,13 @@ var Selection = ({
|
|
|
1583
1586
|
if (width <= 0) {
|
|
1584
1587
|
return null;
|
|
1585
1588
|
}
|
|
1586
|
-
return /* @__PURE__ */ (0,
|
|
1589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SelectionOverlay, { $left: startPosition, $width: width, $color: color, "data-selection": true });
|
|
1587
1590
|
};
|
|
1588
1591
|
|
|
1589
1592
|
// src/components/LoopRegion.tsx
|
|
1590
|
-
var
|
|
1593
|
+
var import_react9 = require("react");
|
|
1591
1594
|
var import_styled_components18 = __toESM(require("styled-components"));
|
|
1592
|
-
var
|
|
1595
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1593
1596
|
var LoopRegionOverlayDiv = import_styled_components18.default.div.attrs((props) => ({
|
|
1594
1597
|
style: {
|
|
1595
1598
|
left: `${props.$left}px`,
|
|
@@ -1638,8 +1641,8 @@ var LoopRegion = ({
|
|
|
1638
1641
|
if (width <= 0) {
|
|
1639
1642
|
return null;
|
|
1640
1643
|
}
|
|
1641
|
-
return /* @__PURE__ */ (0,
|
|
1642
|
-
/* @__PURE__ */ (0,
|
|
1644
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
1645
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1643
1646
|
LoopRegionOverlayDiv,
|
|
1644
1647
|
{
|
|
1645
1648
|
$left: startPosition,
|
|
@@ -1648,7 +1651,7 @@ var LoopRegion = ({
|
|
|
1648
1651
|
"data-loop-region": true
|
|
1649
1652
|
}
|
|
1650
1653
|
),
|
|
1651
|
-
/* @__PURE__ */ (0,
|
|
1654
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1652
1655
|
LoopMarker,
|
|
1653
1656
|
{
|
|
1654
1657
|
$left: startPosition,
|
|
@@ -1657,7 +1660,7 @@ var LoopRegion = ({
|
|
|
1657
1660
|
"data-loop-marker": "start"
|
|
1658
1661
|
}
|
|
1659
1662
|
),
|
|
1660
|
-
/* @__PURE__ */ (0,
|
|
1663
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1661
1664
|
LoopMarker,
|
|
1662
1665
|
{
|
|
1663
1666
|
$left: endPosition - 2,
|
|
@@ -1738,71 +1741,77 @@ var LoopRegionMarkers = ({
|
|
|
1738
1741
|
minPosition = 0,
|
|
1739
1742
|
maxPosition = Infinity
|
|
1740
1743
|
}) => {
|
|
1741
|
-
const [draggingMarker, setDraggingMarker] = (0,
|
|
1742
|
-
const dragStartX = (0,
|
|
1743
|
-
const dragStartPosition = (0,
|
|
1744
|
-
const dragStartEnd = (0,
|
|
1744
|
+
const [draggingMarker, setDraggingMarker] = (0, import_react9.useState)(null);
|
|
1745
|
+
const dragStartX = (0, import_react9.useRef)(0);
|
|
1746
|
+
const dragStartPosition = (0, import_react9.useRef)(0);
|
|
1747
|
+
const dragStartEnd = (0, import_react9.useRef)(0);
|
|
1745
1748
|
const width = Math.max(0, endPosition - startPosition);
|
|
1746
|
-
const handleMarkerMouseDown = (0,
|
|
1747
|
-
e
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
const
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1749
|
+
const handleMarkerMouseDown = (0, import_react9.useCallback)(
|
|
1750
|
+
(e, marker) => {
|
|
1751
|
+
e.preventDefault();
|
|
1752
|
+
e.stopPropagation();
|
|
1753
|
+
setDraggingMarker(marker);
|
|
1754
|
+
dragStartX.current = e.clientX;
|
|
1755
|
+
dragStartPosition.current = marker === "start" ? startPosition : endPosition;
|
|
1756
|
+
const handleMouseMove = (moveEvent) => {
|
|
1757
|
+
const delta = moveEvent.clientX - dragStartX.current;
|
|
1758
|
+
const newPosition = dragStartPosition.current + delta;
|
|
1759
|
+
if (marker === "start") {
|
|
1760
|
+
const clampedPosition = Math.max(minPosition, Math.min(endPosition - 10, newPosition));
|
|
1761
|
+
onLoopStartChange?.(clampedPosition);
|
|
1762
|
+
} else {
|
|
1763
|
+
const clampedPosition = Math.max(startPosition + 10, Math.min(maxPosition, newPosition));
|
|
1764
|
+
onLoopEndChange?.(clampedPosition);
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
const handleMouseUp = () => {
|
|
1768
|
+
setDraggingMarker(null);
|
|
1769
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1770
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
1771
|
+
};
|
|
1772
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1773
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
1774
|
+
},
|
|
1775
|
+
[startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]
|
|
1776
|
+
);
|
|
1777
|
+
const handleRegionMouseDown = (0, import_react9.useCallback)(
|
|
1778
|
+
(e) => {
|
|
1779
|
+
e.preventDefault();
|
|
1780
|
+
e.stopPropagation();
|
|
1781
|
+
setDraggingMarker("region");
|
|
1782
|
+
dragStartX.current = e.clientX;
|
|
1783
|
+
dragStartPosition.current = startPosition;
|
|
1784
|
+
dragStartEnd.current = endPosition;
|
|
1785
|
+
const regionWidth = endPosition - startPosition;
|
|
1786
|
+
const handleMouseMove = (moveEvent) => {
|
|
1787
|
+
const delta = moveEvent.clientX - dragStartX.current;
|
|
1788
|
+
let newStart = dragStartPosition.current + delta;
|
|
1789
|
+
let newEnd = dragStartEnd.current + delta;
|
|
1790
|
+
if (newStart < minPosition) {
|
|
1791
|
+
newStart = minPosition;
|
|
1792
|
+
newEnd = minPosition + regionWidth;
|
|
1793
|
+
}
|
|
1794
|
+
if (newEnd > maxPosition) {
|
|
1795
|
+
newEnd = maxPosition;
|
|
1796
|
+
newStart = maxPosition - regionWidth;
|
|
1797
|
+
}
|
|
1798
|
+
onLoopRegionMove?.(newStart, newEnd);
|
|
1799
|
+
};
|
|
1800
|
+
const handleMouseUp = () => {
|
|
1801
|
+
setDraggingMarker(null);
|
|
1802
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1803
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
1804
|
+
};
|
|
1805
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1806
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
1807
|
+
},
|
|
1808
|
+
[startPosition, endPosition, minPosition, maxPosition, onLoopRegionMove]
|
|
1809
|
+
);
|
|
1801
1810
|
if (width <= 0) {
|
|
1802
1811
|
return null;
|
|
1803
1812
|
}
|
|
1804
|
-
return /* @__PURE__ */ (0,
|
|
1805
|
-
/* @__PURE__ */ (0,
|
|
1813
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1806
1815
|
TimescaleLoopShade,
|
|
1807
1816
|
{
|
|
1808
1817
|
$left: startPosition,
|
|
@@ -1813,7 +1822,7 @@ var LoopRegionMarkers = ({
|
|
|
1813
1822
|
"data-loop-region-timescale": true
|
|
1814
1823
|
}
|
|
1815
1824
|
),
|
|
1816
|
-
/* @__PURE__ */ (0,
|
|
1825
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1817
1826
|
DraggableMarkerHandle,
|
|
1818
1827
|
{
|
|
1819
1828
|
$left: startPosition,
|
|
@@ -1824,7 +1833,7 @@ var LoopRegionMarkers = ({
|
|
|
1824
1833
|
"data-loop-marker-handle": "start"
|
|
1825
1834
|
}
|
|
1826
1835
|
),
|
|
1827
|
-
/* @__PURE__ */ (0,
|
|
1836
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1828
1837
|
DraggableMarkerHandle,
|
|
1829
1838
|
{
|
|
1830
1839
|
$left: endPosition,
|
|
@@ -1859,46 +1868,49 @@ var TimescaleLoopRegion = ({
|
|
|
1859
1868
|
maxPosition = Infinity,
|
|
1860
1869
|
controlsOffset = 0
|
|
1861
1870
|
}) => {
|
|
1862
|
-
const [, setIsCreating] = (0,
|
|
1863
|
-
const createStartX = (0,
|
|
1864
|
-
const containerRef = (0,
|
|
1871
|
+
const [, setIsCreating] = (0, import_react9.useState)(false);
|
|
1872
|
+
const createStartX = (0, import_react9.useRef)(0);
|
|
1873
|
+
const containerRef = (0, import_react9.useRef)(null);
|
|
1865
1874
|
const hasLoopRegion = endPosition > startPosition;
|
|
1866
|
-
const handleBackgroundMouseDown = (0,
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
const
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1875
|
+
const handleBackgroundMouseDown = (0, import_react9.useCallback)(
|
|
1876
|
+
(e) => {
|
|
1877
|
+
const target = e.target;
|
|
1878
|
+
if (target.closest("[data-loop-marker-handle]") || target.closest("[data-loop-region-timescale]")) {
|
|
1879
|
+
return;
|
|
1880
|
+
}
|
|
1881
|
+
e.preventDefault();
|
|
1882
|
+
setIsCreating(true);
|
|
1883
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
1884
|
+
if (!rect) return;
|
|
1885
|
+
const clickX = e.clientX - rect.left;
|
|
1886
|
+
const clampedX = Math.max(minPosition, Math.min(maxPosition, clickX));
|
|
1887
|
+
createStartX.current = clampedX;
|
|
1888
|
+
onLoopRegionChange?.(clampedX, clampedX);
|
|
1889
|
+
const handleMouseMove = (moveEvent) => {
|
|
1890
|
+
const currentX = moveEvent.clientX - rect.left;
|
|
1891
|
+
const clampedCurrentX = Math.max(minPosition, Math.min(maxPosition, currentX));
|
|
1892
|
+
const newStart = Math.min(createStartX.current, clampedCurrentX);
|
|
1893
|
+
const newEnd = Math.max(createStartX.current, clampedCurrentX);
|
|
1894
|
+
onLoopRegionChange?.(newStart, newEnd);
|
|
1895
|
+
};
|
|
1896
|
+
const handleMouseUp = () => {
|
|
1897
|
+
setIsCreating(false);
|
|
1898
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1899
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
1900
|
+
};
|
|
1901
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1902
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
1903
|
+
},
|
|
1904
|
+
[minPosition, maxPosition, onLoopRegionChange]
|
|
1905
|
+
);
|
|
1906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1895
1907
|
TimescaleLoopCreator,
|
|
1896
1908
|
{
|
|
1897
1909
|
ref: containerRef,
|
|
1898
1910
|
$leftOffset: controlsOffset,
|
|
1899
1911
|
onMouseDown: handleBackgroundMouseDown,
|
|
1900
1912
|
"data-timescale-loop-creator": true,
|
|
1901
|
-
children: hasLoopRegion && /* @__PURE__ */ (0,
|
|
1913
|
+
children: hasLoopRegion && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1902
1914
|
LoopRegionMarkers,
|
|
1903
1915
|
{
|
|
1904
1916
|
startPosition,
|
|
@@ -1917,10 +1929,10 @@ var TimescaleLoopRegion = ({
|
|
|
1917
1929
|
};
|
|
1918
1930
|
|
|
1919
1931
|
// src/components/SelectionTimeInputs.tsx
|
|
1920
|
-
var
|
|
1932
|
+
var import_react11 = require("react");
|
|
1921
1933
|
|
|
1922
1934
|
// src/components/TimeInput.tsx
|
|
1923
|
-
var
|
|
1935
|
+
var import_react10 = require("react");
|
|
1924
1936
|
|
|
1925
1937
|
// src/utils/timeFormat.ts
|
|
1926
1938
|
function clockFormat(seconds, decimals) {
|
|
@@ -1970,7 +1982,7 @@ function parseTime(timeStr, format) {
|
|
|
1970
1982
|
}
|
|
1971
1983
|
|
|
1972
1984
|
// src/components/TimeInput.tsx
|
|
1973
|
-
var
|
|
1985
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1974
1986
|
var TimeInput = ({
|
|
1975
1987
|
id,
|
|
1976
1988
|
label,
|
|
@@ -1980,8 +1992,8 @@ var TimeInput = ({
|
|
|
1980
1992
|
onChange,
|
|
1981
1993
|
readOnly = false
|
|
1982
1994
|
}) => {
|
|
1983
|
-
const [displayValue, setDisplayValue] = (0,
|
|
1984
|
-
(0,
|
|
1995
|
+
const [displayValue, setDisplayValue] = (0, import_react10.useState)("");
|
|
1996
|
+
(0, import_react10.useEffect)(() => {
|
|
1985
1997
|
const formatted = formatTime(value, format);
|
|
1986
1998
|
setDisplayValue(formatted);
|
|
1987
1999
|
}, [value, format, id]);
|
|
@@ -2001,9 +2013,9 @@ var TimeInput = ({
|
|
|
2001
2013
|
e.currentTarget.blur();
|
|
2002
2014
|
}
|
|
2003
2015
|
};
|
|
2004
|
-
return /* @__PURE__ */ (0,
|
|
2005
|
-
/* @__PURE__ */ (0,
|
|
2006
|
-
/* @__PURE__ */ (0,
|
|
2016
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
2017
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ScreenReaderOnly, { as: "label", htmlFor: id, children: label }),
|
|
2018
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2007
2019
|
BaseInput,
|
|
2008
2020
|
{
|
|
2009
2021
|
type: "text",
|
|
@@ -2020,15 +2032,15 @@ var TimeInput = ({
|
|
|
2020
2032
|
};
|
|
2021
2033
|
|
|
2022
2034
|
// src/components/SelectionTimeInputs.tsx
|
|
2023
|
-
var
|
|
2035
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2024
2036
|
var SelectionTimeInputs = ({
|
|
2025
2037
|
selectionStart,
|
|
2026
2038
|
selectionEnd,
|
|
2027
2039
|
onSelectionChange,
|
|
2028
2040
|
className
|
|
2029
2041
|
}) => {
|
|
2030
|
-
const [timeFormat, setTimeFormat] = (0,
|
|
2031
|
-
(0,
|
|
2042
|
+
const [timeFormat, setTimeFormat] = (0, import_react11.useState)("hh:mm:ss.uuu");
|
|
2043
|
+
(0, import_react11.useEffect)(() => {
|
|
2032
2044
|
const timeFormatSelect = document.querySelector(".time-format");
|
|
2033
2045
|
const handleFormatChange = () => {
|
|
2034
2046
|
if (timeFormatSelect) {
|
|
@@ -2053,8 +2065,8 @@ var SelectionTimeInputs = ({
|
|
|
2053
2065
|
onSelectionChange(selectionStart, value);
|
|
2054
2066
|
}
|
|
2055
2067
|
};
|
|
2056
|
-
return /* @__PURE__ */ (0,
|
|
2057
|
-
/* @__PURE__ */ (0,
|
|
2068
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className, children: [
|
|
2069
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2058
2070
|
TimeInput,
|
|
2059
2071
|
{
|
|
2060
2072
|
id: "audio_start",
|
|
@@ -2065,7 +2077,7 @@ var SelectionTimeInputs = ({
|
|
|
2065
2077
|
onChange: handleStartChange
|
|
2066
2078
|
}
|
|
2067
2079
|
),
|
|
2068
|
-
/* @__PURE__ */ (0,
|
|
2080
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2069
2081
|
TimeInput,
|
|
2070
2082
|
{
|
|
2071
2083
|
id: "audio_end",
|
|
@@ -2080,14 +2092,14 @@ var SelectionTimeInputs = ({
|
|
|
2080
2092
|
};
|
|
2081
2093
|
|
|
2082
2094
|
// src/contexts/DevicePixelRatio.tsx
|
|
2083
|
-
var
|
|
2084
|
-
var
|
|
2095
|
+
var import_react12 = require("react");
|
|
2096
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
2085
2097
|
function getScale() {
|
|
2086
2098
|
return window.devicePixelRatio;
|
|
2087
2099
|
}
|
|
2088
|
-
var DevicePixelRatioContext = (0,
|
|
2100
|
+
var DevicePixelRatioContext = (0, import_react12.createContext)(getScale());
|
|
2089
2101
|
var DevicePixelRatioProvider = ({ children }) => {
|
|
2090
|
-
const [scale, setScale] = (0,
|
|
2102
|
+
const [scale, setScale] = (0, import_react12.useState)(getScale());
|
|
2091
2103
|
matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
|
|
2092
2104
|
"change",
|
|
2093
2105
|
() => {
|
|
@@ -2095,13 +2107,13 @@ var DevicePixelRatioProvider = ({ children }) => {
|
|
|
2095
2107
|
},
|
|
2096
2108
|
{ once: true }
|
|
2097
2109
|
);
|
|
2098
|
-
return /* @__PURE__ */ (0,
|
|
2110
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
|
|
2099
2111
|
};
|
|
2100
|
-
var useDevicePixelRatio = () => (0,
|
|
2112
|
+
var useDevicePixelRatio = () => (0, import_react12.useContext)(DevicePixelRatioContext);
|
|
2101
2113
|
|
|
2102
2114
|
// src/contexts/PlaylistInfo.tsx
|
|
2103
|
-
var
|
|
2104
|
-
var PlaylistInfoContext = (0,
|
|
2115
|
+
var import_react13 = require("react");
|
|
2116
|
+
var PlaylistInfoContext = (0, import_react13.createContext)({
|
|
2105
2117
|
sampleRate: 48e3,
|
|
2106
2118
|
samplesPerPixel: 1e3,
|
|
2107
2119
|
zoomLevels: [1e3, 1500, 2e3, 2500],
|
|
@@ -2115,22 +2127,22 @@ var PlaylistInfoContext = (0, import_react11.createContext)({
|
|
|
2115
2127
|
barWidth: 1,
|
|
2116
2128
|
barGap: 0
|
|
2117
2129
|
});
|
|
2118
|
-
var usePlaylistInfo = () => (0,
|
|
2130
|
+
var usePlaylistInfo = () => (0, import_react13.useContext)(PlaylistInfoContext);
|
|
2119
2131
|
|
|
2120
2132
|
// src/contexts/Theme.tsx
|
|
2121
|
-
var
|
|
2133
|
+
var import_react14 = require("react");
|
|
2122
2134
|
var import_styled_components19 = require("styled-components");
|
|
2123
|
-
var useTheme2 = () => (0,
|
|
2135
|
+
var useTheme2 = () => (0, import_react14.useContext)(import_styled_components19.ThemeContext);
|
|
2124
2136
|
|
|
2125
2137
|
// src/contexts/TrackControls.tsx
|
|
2126
|
-
var
|
|
2127
|
-
var
|
|
2128
|
-
var TrackControlsContext = (0,
|
|
2129
|
-
var useTrackControls = () => (0,
|
|
2138
|
+
var import_react15 = require("react");
|
|
2139
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2140
|
+
var TrackControlsContext = (0, import_react15.createContext)(/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react15.Fragment, {}));
|
|
2141
|
+
var useTrackControls = () => (0, import_react15.useContext)(TrackControlsContext);
|
|
2130
2142
|
|
|
2131
2143
|
// src/contexts/Playout.tsx
|
|
2132
|
-
var
|
|
2133
|
-
var
|
|
2144
|
+
var import_react16 = require("react");
|
|
2145
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2134
2146
|
var defaultProgress = 0;
|
|
2135
2147
|
var defaultIsPlaying = false;
|
|
2136
2148
|
var defaultSelectionStart = 0;
|
|
@@ -2141,8 +2153,8 @@ var defaultPlayout = {
|
|
|
2141
2153
|
selectionStart: defaultSelectionStart,
|
|
2142
2154
|
selectionEnd: defaultSelectionEnd
|
|
2143
2155
|
};
|
|
2144
|
-
var PlayoutStatusContext = (0,
|
|
2145
|
-
var PlayoutStatusUpdateContext = (0,
|
|
2156
|
+
var PlayoutStatusContext = (0, import_react16.createContext)(defaultPlayout);
|
|
2157
|
+
var PlayoutStatusUpdateContext = (0, import_react16.createContext)({
|
|
2146
2158
|
setIsPlaying: () => {
|
|
2147
2159
|
},
|
|
2148
2160
|
setProgress: () => {
|
|
@@ -2151,23 +2163,24 @@ var PlayoutStatusUpdateContext = (0, import_react14.createContext)({
|
|
|
2151
2163
|
}
|
|
2152
2164
|
});
|
|
2153
2165
|
var PlayoutProvider = ({ children }) => {
|
|
2154
|
-
const [isPlaying, setIsPlaying] = (0,
|
|
2155
|
-
const [progress, setProgress] = (0,
|
|
2156
|
-
const [selectionStart, setSelectionStart] = (0,
|
|
2157
|
-
const [selectionEnd, setSelectionEnd] = (0,
|
|
2166
|
+
const [isPlaying, setIsPlaying] = (0, import_react16.useState)(defaultIsPlaying);
|
|
2167
|
+
const [progress, setProgress] = (0, import_react16.useState)(defaultProgress);
|
|
2168
|
+
const [selectionStart, setSelectionStart] = (0, import_react16.useState)(defaultSelectionStart);
|
|
2169
|
+
const [selectionEnd, setSelectionEnd] = (0, import_react16.useState)(defaultSelectionEnd);
|
|
2158
2170
|
const setSelection = (start, end) => {
|
|
2159
2171
|
setSelectionStart(start);
|
|
2160
2172
|
setSelectionEnd(end);
|
|
2161
2173
|
};
|
|
2162
|
-
return /* @__PURE__ */ (0,
|
|
2174
|
+
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 }) });
|
|
2163
2175
|
};
|
|
2164
|
-
var usePlayoutStatus = () => (0,
|
|
2165
|
-
var usePlayoutStatusUpdate = () => (0,
|
|
2176
|
+
var usePlayoutStatus = () => (0, import_react16.useContext)(PlayoutStatusContext);
|
|
2177
|
+
var usePlayoutStatusUpdate = () => (0, import_react16.useContext)(PlayoutStatusUpdateContext);
|
|
2166
2178
|
|
|
2167
2179
|
// src/components/SpectrogramChannel.tsx
|
|
2168
|
-
var
|
|
2180
|
+
var import_react17 = require("react");
|
|
2169
2181
|
var import_styled_components20 = __toESM(require("styled-components"));
|
|
2170
|
-
var
|
|
2182
|
+
var import_core3 = require("@waveform-playlist/core");
|
|
2183
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2171
2184
|
var LINEAR_FREQUENCY_SCALE = (f, minF, maxF) => (f - minF) / (maxF - minF);
|
|
2172
2185
|
var Wrapper3 = import_styled_components20.default.div.attrs((props) => ({
|
|
2173
2186
|
style: {
|
|
@@ -2220,60 +2233,52 @@ var SpectrogramChannel = ({
|
|
|
2220
2233
|
onCanvasesReady
|
|
2221
2234
|
}) => {
|
|
2222
2235
|
const channelIndex = channelIndexProp ?? index;
|
|
2223
|
-
const
|
|
2224
|
-
const registeredIdsRef = (0,
|
|
2225
|
-
const transferredCanvasesRef = (0,
|
|
2226
|
-
const workerApiRef = (0,
|
|
2227
|
-
const onCanvasesReadyRef = (0,
|
|
2236
|
+
const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
|
|
2237
|
+
const registeredIdsRef = (0, import_react17.useRef)([]);
|
|
2238
|
+
const transferredCanvasesRef = (0, import_react17.useRef)(/* @__PURE__ */ new WeakSet());
|
|
2239
|
+
const workerApiRef = (0, import_react17.useRef)(workerApi);
|
|
2240
|
+
const onCanvasesReadyRef = (0, import_react17.useRef)(onCanvasesReady);
|
|
2228
2241
|
const isWorkerMode = !!(workerApi && clipId);
|
|
2229
|
-
const
|
|
2230
|
-
|
|
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
|
-
);
|
|
2242
|
+
const clipOriginX = useClipViewportOrigin();
|
|
2243
|
+
const visibleChunkIndices = useVisibleChunkIndices(length, import_core3.MAX_CANVAS_WIDTH, clipOriginX);
|
|
2255
2244
|
const lut = colorLUT ?? DEFAULT_COLOR_LUT;
|
|
2256
2245
|
const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
|
|
2257
2246
|
const scaleFn = frequencyScaleFn ?? LINEAR_FREQUENCY_SCALE;
|
|
2258
2247
|
const hasCustomFrequencyScale = Boolean(frequencyScaleFn);
|
|
2259
|
-
(0,
|
|
2248
|
+
(0, import_react17.useEffect)(() => {
|
|
2260
2249
|
workerApiRef.current = workerApi;
|
|
2261
2250
|
}, [workerApi]);
|
|
2262
|
-
(0,
|
|
2251
|
+
(0, import_react17.useEffect)(() => {
|
|
2263
2252
|
onCanvasesReadyRef.current = onCanvasesReady;
|
|
2264
2253
|
}, [onCanvasesReady]);
|
|
2265
|
-
(0,
|
|
2254
|
+
(0, import_react17.useEffect)(() => {
|
|
2266
2255
|
if (!isWorkerMode) return;
|
|
2267
2256
|
const currentWorkerApi = workerApiRef.current;
|
|
2268
2257
|
if (!currentWorkerApi || !clipId) return;
|
|
2269
|
-
const
|
|
2258
|
+
const previousCount = registeredIdsRef.current.length;
|
|
2259
|
+
const remaining = [];
|
|
2260
|
+
for (const id of registeredIdsRef.current) {
|
|
2261
|
+
const match = id.match(/chunk(\d+)$/);
|
|
2262
|
+
if (!match) {
|
|
2263
|
+
remaining.push(id);
|
|
2264
|
+
continue;
|
|
2265
|
+
}
|
|
2266
|
+
const chunkIdx = parseInt(match[1], 10);
|
|
2267
|
+
const canvas = canvasMapRef.current.get(chunkIdx);
|
|
2268
|
+
if (canvas && canvas.isConnected) {
|
|
2269
|
+
remaining.push(id);
|
|
2270
|
+
} else {
|
|
2271
|
+
try {
|
|
2272
|
+
currentWorkerApi.unregisterCanvas(id);
|
|
2273
|
+
} catch (err) {
|
|
2274
|
+
console.warn(`[spectrogram] unregisterCanvas failed for ${id}:`, err);
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
registeredIdsRef.current = remaining;
|
|
2270
2279
|
const newIds = [];
|
|
2271
|
-
const
|
|
2272
|
-
for (let i = 0; i < canvases2.length; i++) {
|
|
2273
|
-
const canvas = canvases2[i];
|
|
2274
|
-
if (!canvas) continue;
|
|
2280
|
+
for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
|
|
2275
2281
|
if (transferredCanvasesRef.current.has(canvas)) continue;
|
|
2276
|
-
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
2277
2282
|
const canvasId = `${clipId}-ch${channelIndex}-chunk${canvasIdx}`;
|
|
2278
2283
|
let offscreen;
|
|
2279
2284
|
try {
|
|
@@ -2286,7 +2291,6 @@ var SpectrogramChannel = ({
|
|
|
2286
2291
|
try {
|
|
2287
2292
|
currentWorkerApi.registerCanvas(canvasId, offscreen);
|
|
2288
2293
|
newIds.push(canvasId);
|
|
2289
|
-
newWidths.push(Math.min(length - canvasIdx * MAX_CANVAS_WIDTH, MAX_CANVAS_WIDTH));
|
|
2290
2294
|
} catch (err) {
|
|
2291
2295
|
console.warn(`[spectrogram] registerCanvas failed for ${canvasId}:`, err);
|
|
2292
2296
|
continue;
|
|
@@ -2294,35 +2298,23 @@ var SpectrogramChannel = ({
|
|
|
2294
2298
|
}
|
|
2295
2299
|
if (newIds.length > 0) {
|
|
2296
2300
|
registeredIdsRef.current = [...registeredIdsRef.current, ...newIds];
|
|
2297
|
-
onCanvasesReadyRef.current?.(newIds, newWidths);
|
|
2298
2301
|
}
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
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);
|
|
2302
|
+
const canvasSetChanged = newIds.length > 0 || remaining.length < previousCount;
|
|
2303
|
+
if (canvasSetChanged) {
|
|
2304
|
+
const allIds = registeredIdsRef.current;
|
|
2305
|
+
const allWidths = allIds.map((id) => {
|
|
2306
|
+
const match = id.match(/chunk(\d+)$/);
|
|
2307
|
+
if (!match) {
|
|
2308
|
+
console.warn(`[spectrogram] Unexpected canvas ID format: ${id}`);
|
|
2309
|
+
return import_core3.MAX_CANVAS_WIDTH;
|
|
2320
2310
|
}
|
|
2321
|
-
|
|
2311
|
+
const chunkIdx = parseInt(match[1], 10);
|
|
2312
|
+
return Math.min(length - chunkIdx * import_core3.MAX_CANVAS_WIDTH, import_core3.MAX_CANVAS_WIDTH);
|
|
2313
|
+
});
|
|
2314
|
+
onCanvasesReadyRef.current?.(allIds, allWidths);
|
|
2322
2315
|
}
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
(0, import_react15.useEffect)(() => {
|
|
2316
|
+
}, [canvasMapRef, isWorkerMode, clipId, channelIndex, length, visibleChunkIndices]);
|
|
2317
|
+
(0, import_react17.useEffect)(() => {
|
|
2326
2318
|
return () => {
|
|
2327
2319
|
const api = workerApiRef.current;
|
|
2328
2320
|
if (!api) return;
|
|
@@ -2336,17 +2328,20 @@ var SpectrogramChannel = ({
|
|
|
2336
2328
|
registeredIdsRef.current = [];
|
|
2337
2329
|
};
|
|
2338
2330
|
}, []);
|
|
2339
|
-
(0,
|
|
2331
|
+
(0, import_react17.useLayoutEffect)(() => {
|
|
2340
2332
|
if (isWorkerMode || !data) return;
|
|
2341
|
-
const
|
|
2342
|
-
|
|
2333
|
+
const {
|
|
2334
|
+
frequencyBinCount,
|
|
2335
|
+
frameCount,
|
|
2336
|
+
hopSize,
|
|
2337
|
+
sampleRate,
|
|
2338
|
+
gainDb,
|
|
2339
|
+
rangeDb: rawRangeDb
|
|
2340
|
+
} = data;
|
|
2343
2341
|
const rangeDb = rawRangeDb === 0 ? 1 : rawRangeDb;
|
|
2344
2342
|
const binToFreq = (bin) => bin / frequencyBinCount * (sampleRate / 2);
|
|
2345
|
-
for (
|
|
2346
|
-
const
|
|
2347
|
-
if (!canvas) continue;
|
|
2348
|
-
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
2349
|
-
const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
|
|
2343
|
+
for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
|
|
2344
|
+
const globalPixelOffset = canvasIdx * import_core3.MAX_CANVAS_WIDTH;
|
|
2350
2345
|
const ctx = canvas.getContext("2d");
|
|
2351
2346
|
if (!ctx) continue;
|
|
2352
2347
|
const canvasWidth = canvas.width / devicePixelRatio;
|
|
@@ -2406,11 +2401,25 @@ var SpectrogramChannel = ({
|
|
|
2406
2401
|
ctx.drawImage(tmpCanvas, 0, 0, canvas.width, canvas.height);
|
|
2407
2402
|
}
|
|
2408
2403
|
}
|
|
2409
|
-
}, [
|
|
2404
|
+
}, [
|
|
2405
|
+
canvasMapRef,
|
|
2406
|
+
isWorkerMode,
|
|
2407
|
+
data,
|
|
2408
|
+
length,
|
|
2409
|
+
waveHeight,
|
|
2410
|
+
devicePixelRatio,
|
|
2411
|
+
samplesPerPixel,
|
|
2412
|
+
lut,
|
|
2413
|
+
minFrequency,
|
|
2414
|
+
maxF,
|
|
2415
|
+
scaleFn,
|
|
2416
|
+
hasCustomFrequencyScale,
|
|
2417
|
+
visibleChunkIndices
|
|
2418
|
+
]);
|
|
2410
2419
|
const canvases = visibleChunkIndices.map((i) => {
|
|
2411
|
-
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
2412
|
-
const currentWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
|
|
2413
|
-
return /* @__PURE__ */ (0,
|
|
2420
|
+
const chunkLeft = i * import_core3.MAX_CANVAS_WIDTH;
|
|
2421
|
+
const currentWidth = Math.min(length - chunkLeft, import_core3.MAX_CANVAS_WIDTH);
|
|
2422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2414
2423
|
SpectrogramCanvas,
|
|
2415
2424
|
{
|
|
2416
2425
|
$cssWidth: currentWidth,
|
|
@@ -2424,11 +2433,11 @@ var SpectrogramChannel = ({
|
|
|
2424
2433
|
`${length}-${i}`
|
|
2425
2434
|
);
|
|
2426
2435
|
});
|
|
2427
|
-
return /* @__PURE__ */ (0,
|
|
2436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Wrapper3, { $index: index, $cssWidth: length, $waveHeight: waveHeight, children: canvases });
|
|
2428
2437
|
};
|
|
2429
2438
|
|
|
2430
2439
|
// src/components/SmartChannel.tsx
|
|
2431
|
-
var
|
|
2440
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2432
2441
|
var SmartChannel = ({
|
|
2433
2442
|
isSelected,
|
|
2434
2443
|
transparentBackground,
|
|
@@ -2453,7 +2462,7 @@ var SmartChannel = ({
|
|
|
2453
2462
|
const drawMode = theme?.waveformDrawMode || "inverted";
|
|
2454
2463
|
const hasSpectrogram = spectrogramData || spectrogramWorkerApi;
|
|
2455
2464
|
if (renderMode === "spectrogram" && hasSpectrogram) {
|
|
2456
|
-
return /* @__PURE__ */ (0,
|
|
2465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2457
2466
|
SpectrogramChannel,
|
|
2458
2467
|
{
|
|
2459
2468
|
index: props.index,
|
|
@@ -2474,8 +2483,8 @@ var SmartChannel = ({
|
|
|
2474
2483
|
}
|
|
2475
2484
|
if (renderMode === "both" && hasSpectrogram) {
|
|
2476
2485
|
const halfHeight = Math.floor(waveHeight / 2);
|
|
2477
|
-
return /* @__PURE__ */ (0,
|
|
2478
|
-
/* @__PURE__ */ (0,
|
|
2486
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
2487
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2479
2488
|
SpectrogramChannel,
|
|
2480
2489
|
{
|
|
2481
2490
|
index: props.index * 2,
|
|
@@ -2494,24 +2503,35 @@ var SmartChannel = ({
|
|
|
2494
2503
|
onCanvasesReady: spectrogramOnCanvasesReady
|
|
2495
2504
|
}
|
|
2496
2505
|
),
|
|
2497
|
-
/* @__PURE__ */ (0,
|
|
2498
|
-
|
|
2506
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2507
|
+
"div",
|
|
2499
2508
|
{
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2509
|
+
style: {
|
|
2510
|
+
position: "absolute",
|
|
2511
|
+
top: (props.index * 2 + 1) * halfHeight,
|
|
2512
|
+
width: props.length,
|
|
2513
|
+
height: halfHeight
|
|
2514
|
+
},
|
|
2515
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2516
|
+
Channel,
|
|
2517
|
+
{
|
|
2518
|
+
...props,
|
|
2519
|
+
index: 0,
|
|
2520
|
+
waveOutlineColor,
|
|
2521
|
+
waveFillColor,
|
|
2522
|
+
waveHeight: halfHeight,
|
|
2523
|
+
devicePixelRatio,
|
|
2524
|
+
barWidth,
|
|
2525
|
+
barGap,
|
|
2526
|
+
transparentBackground,
|
|
2527
|
+
drawMode
|
|
2528
|
+
}
|
|
2529
|
+
)
|
|
2510
2530
|
}
|
|
2511
|
-
)
|
|
2531
|
+
)
|
|
2512
2532
|
] });
|
|
2513
2533
|
}
|
|
2514
|
-
return /* @__PURE__ */ (0,
|
|
2534
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2515
2535
|
Channel,
|
|
2516
2536
|
{
|
|
2517
2537
|
...props,
|
|
@@ -2528,9 +2548,9 @@ var SmartChannel = ({
|
|
|
2528
2548
|
};
|
|
2529
2549
|
|
|
2530
2550
|
// src/components/SpectrogramLabels.tsx
|
|
2531
|
-
var
|
|
2551
|
+
var import_react18 = require("react");
|
|
2532
2552
|
var import_styled_components21 = __toESM(require("styled-components"));
|
|
2533
|
-
var
|
|
2553
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2534
2554
|
var LABELS_WIDTH = 72;
|
|
2535
2555
|
var LabelsStickyWrapper = import_styled_components21.default.div`
|
|
2536
2556
|
position: sticky;
|
|
@@ -2580,12 +2600,12 @@ var SpectrogramLabels = ({
|
|
|
2580
2600
|
renderMode = "spectrogram",
|
|
2581
2601
|
hasClipHeaders = false
|
|
2582
2602
|
}) => {
|
|
2583
|
-
const canvasRef = (0,
|
|
2603
|
+
const canvasRef = (0, import_react18.useRef)(null);
|
|
2584
2604
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2585
2605
|
const spectrogramHeight = renderMode === "both" ? Math.floor(waveHeight / 2) : waveHeight;
|
|
2586
2606
|
const totalHeight = numChannels * waveHeight;
|
|
2587
2607
|
const clipHeaderOffset = hasClipHeaders ? 22 : 0;
|
|
2588
|
-
(0,
|
|
2608
|
+
(0, import_react18.useLayoutEffect)(() => {
|
|
2589
2609
|
const canvas = canvasRef.current;
|
|
2590
2610
|
if (!canvas) return;
|
|
2591
2611
|
const ctx = canvas.getContext("2d");
|
|
@@ -2611,8 +2631,19 @@ var SpectrogramLabels = ({
|
|
|
2611
2631
|
ctx.fillText(text, padding, y);
|
|
2612
2632
|
}
|
|
2613
2633
|
}
|
|
2614
|
-
}, [
|
|
2615
|
-
|
|
2634
|
+
}, [
|
|
2635
|
+
waveHeight,
|
|
2636
|
+
numChannels,
|
|
2637
|
+
frequencyScaleFn,
|
|
2638
|
+
minFrequency,
|
|
2639
|
+
maxFrequency,
|
|
2640
|
+
labelsColor,
|
|
2641
|
+
labelsBackground,
|
|
2642
|
+
devicePixelRatio,
|
|
2643
|
+
spectrogramHeight,
|
|
2644
|
+
clipHeaderOffset
|
|
2645
|
+
]);
|
|
2646
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(LabelsStickyWrapper, { $height: totalHeight + clipHeaderOffset, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2616
2647
|
"canvas",
|
|
2617
2648
|
{
|
|
2618
2649
|
ref: canvasRef,
|
|
@@ -2628,10 +2659,10 @@ var SpectrogramLabels = ({
|
|
|
2628
2659
|
};
|
|
2629
2660
|
|
|
2630
2661
|
// src/components/SmartScale.tsx
|
|
2631
|
-
var
|
|
2662
|
+
var import_react20 = require("react");
|
|
2632
2663
|
|
|
2633
2664
|
// src/components/TimeScale.tsx
|
|
2634
|
-
var
|
|
2665
|
+
var import_react19 = __toESM(require("react"));
|
|
2635
2666
|
var import_styled_components22 = __toESM(require("styled-components"));
|
|
2636
2667
|
|
|
2637
2668
|
// src/utils/conversions.ts
|
|
@@ -2655,7 +2686,8 @@ function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
|
|
|
2655
2686
|
}
|
|
2656
2687
|
|
|
2657
2688
|
// src/components/TimeScale.tsx
|
|
2658
|
-
var
|
|
2689
|
+
var import_core4 = require("@waveform-playlist/core");
|
|
2690
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2659
2691
|
function formatTime2(milliseconds) {
|
|
2660
2692
|
const seconds = Math.floor(milliseconds / 1e3);
|
|
2661
2693
|
const s = seconds % 60;
|
|
@@ -2706,21 +2738,15 @@ var TimeScale = (props) => {
|
|
|
2706
2738
|
secondStep,
|
|
2707
2739
|
renderTimestamp
|
|
2708
2740
|
} = props;
|
|
2709
|
-
const
|
|
2741
|
+
const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
|
|
2710
2742
|
const {
|
|
2711
2743
|
sampleRate,
|
|
2712
2744
|
samplesPerPixel,
|
|
2713
2745
|
timeScaleHeight,
|
|
2714
2746
|
controls: { show: showControls, width: controlWidth }
|
|
2715
|
-
} = (0,
|
|
2747
|
+
} = (0, import_react19.useContext)(PlaylistInfoContext);
|
|
2716
2748
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2717
|
-
const
|
|
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)(() => {
|
|
2749
|
+
const { widthX, canvasInfo, timeMarkersWithPositions } = (0, import_react19.useMemo)(() => {
|
|
2724
2750
|
const nextCanvasInfo = /* @__PURE__ */ new Map();
|
|
2725
2751
|
const nextMarkers = [];
|
|
2726
2752
|
const nextWidthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);
|
|
@@ -2731,7 +2757,7 @@ var TimeScale = (props) => {
|
|
|
2731
2757
|
if (counter % marker === 0) {
|
|
2732
2758
|
const timeMs = counter;
|
|
2733
2759
|
const timestamp = formatTime2(timeMs);
|
|
2734
|
-
const element = renderTimestamp ? /* @__PURE__ */ (0,
|
|
2760
|
+
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);
|
|
2735
2761
|
nextMarkers.push({ pix, element });
|
|
2736
2762
|
nextCanvasInfo.set(pix, timeScaleHeight);
|
|
2737
2763
|
} else if (counter % bigStep === 0) {
|
|
@@ -2746,28 +2772,21 @@ var TimeScale = (props) => {
|
|
|
2746
2772
|
canvasInfo: nextCanvasInfo,
|
|
2747
2773
|
timeMarkersWithPositions: nextMarkers
|
|
2748
2774
|
};
|
|
2749
|
-
}, [
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
}
|
|
2761
|
-
}
|
|
2762
|
-
indices.push(i);
|
|
2763
|
-
}
|
|
2764
|
-
return indices.join(",");
|
|
2765
|
-
});
|
|
2766
|
-
const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
|
|
2775
|
+
}, [
|
|
2776
|
+
duration,
|
|
2777
|
+
samplesPerPixel,
|
|
2778
|
+
sampleRate,
|
|
2779
|
+
marker,
|
|
2780
|
+
bigStep,
|
|
2781
|
+
secondStep,
|
|
2782
|
+
renderTimestamp,
|
|
2783
|
+
timeScaleHeight
|
|
2784
|
+
]);
|
|
2785
|
+
const visibleChunkIndices = useVisibleChunkIndices(widthX, import_core4.MAX_CANVAS_WIDTH);
|
|
2767
2786
|
const visibleChunks = visibleChunkIndices.map((i) => {
|
|
2768
|
-
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
2769
|
-
const chunkWidth = Math.min(widthX - chunkLeft, MAX_CANVAS_WIDTH);
|
|
2770
|
-
return /* @__PURE__ */ (0,
|
|
2787
|
+
const chunkLeft = i * import_core4.MAX_CANVAS_WIDTH;
|
|
2788
|
+
const chunkWidth = Math.min(widthX - chunkLeft, import_core4.MAX_CANVAS_WIDTH);
|
|
2789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2771
2790
|
TimeTickChunk,
|
|
2772
2791
|
{
|
|
2773
2792
|
$cssWidth: chunkWidth,
|
|
@@ -2776,27 +2795,19 @@ var TimeScale = (props) => {
|
|
|
2776
2795
|
width: chunkWidth * devicePixelRatio,
|
|
2777
2796
|
height: timeScaleHeight * devicePixelRatio,
|
|
2778
2797
|
"data-index": i,
|
|
2779
|
-
ref:
|
|
2798
|
+
ref: canvasRef
|
|
2780
2799
|
},
|
|
2781
2800
|
`timescale-${i}`
|
|
2782
2801
|
);
|
|
2783
2802
|
});
|
|
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;
|
|
2803
|
+
const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] * import_core4.MAX_CANVAS_WIDTH : 0;
|
|
2804
|
+
const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) * import_core4.MAX_CANVAS_WIDTH : Infinity;
|
|
2786
2805
|
const visibleMarkers = visibleChunkIndices.length > 0 ? timeMarkersWithPositions.filter(({ pix }) => pix >= firstChunkLeft && pix < lastChunkRight).map(({ element }) => element) : timeMarkersWithPositions.map(({ element }) => element);
|
|
2787
|
-
(0,
|
|
2788
|
-
const
|
|
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()) {
|
|
2806
|
+
(0, import_react19.useLayoutEffect)(() => {
|
|
2807
|
+
for (const [chunkIdx, canvas] of canvasMapRef.current.entries()) {
|
|
2797
2808
|
const ctx = canvas.getContext("2d");
|
|
2798
2809
|
if (!ctx) continue;
|
|
2799
|
-
const chunkLeft = chunkIdx * MAX_CANVAS_WIDTH;
|
|
2810
|
+
const chunkLeft = chunkIdx * import_core4.MAX_CANVAS_WIDTH;
|
|
2800
2811
|
const chunkWidth = canvas.width / devicePixelRatio;
|
|
2801
2812
|
ctx.resetTransform();
|
|
2802
2813
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
@@ -2810,8 +2821,16 @@ var TimeScale = (props) => {
|
|
|
2810
2821
|
ctx.fillRect(localX, scaleY, 1, scaleHeight);
|
|
2811
2822
|
}
|
|
2812
2823
|
}
|
|
2813
|
-
}, [
|
|
2814
|
-
|
|
2824
|
+
}, [
|
|
2825
|
+
canvasMapRef,
|
|
2826
|
+
duration,
|
|
2827
|
+
devicePixelRatio,
|
|
2828
|
+
timeColor,
|
|
2829
|
+
timeScaleHeight,
|
|
2830
|
+
canvasInfo,
|
|
2831
|
+
visibleChunkIndices
|
|
2832
|
+
]);
|
|
2833
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2815
2834
|
PlaylistTimeScaleScroll,
|
|
2816
2835
|
{
|
|
2817
2836
|
$cssWidth: widthX,
|
|
@@ -2827,7 +2846,7 @@ var TimeScale = (props) => {
|
|
|
2827
2846
|
var StyledTimeScale = (0, import_styled_components22.withTheme)(TimeScale);
|
|
2828
2847
|
|
|
2829
2848
|
// src/components/SmartScale.tsx
|
|
2830
|
-
var
|
|
2849
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2831
2850
|
var timeinfo = /* @__PURE__ */ new Map([
|
|
2832
2851
|
[
|
|
2833
2852
|
700,
|
|
@@ -2901,9 +2920,9 @@ function getScaleInfo(samplesPerPixel) {
|
|
|
2901
2920
|
return config;
|
|
2902
2921
|
}
|
|
2903
2922
|
var SmartScale = ({ renderTimestamp }) => {
|
|
2904
|
-
const { samplesPerPixel, duration } = (0,
|
|
2923
|
+
const { samplesPerPixel, duration } = (0, import_react20.useContext)(PlaylistInfoContext);
|
|
2905
2924
|
let config = getScaleInfo(samplesPerPixel);
|
|
2906
|
-
return /* @__PURE__ */ (0,
|
|
2925
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2907
2926
|
StyledTimeScale,
|
|
2908
2927
|
{
|
|
2909
2928
|
marker: config.marker,
|
|
@@ -2917,7 +2936,7 @@ var SmartScale = ({ renderTimestamp }) => {
|
|
|
2917
2936
|
|
|
2918
2937
|
// src/components/TimeFormatSelect.tsx
|
|
2919
2938
|
var import_styled_components23 = __toESM(require("styled-components"));
|
|
2920
|
-
var
|
|
2939
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2921
2940
|
var SelectWrapper = import_styled_components23.default.div`
|
|
2922
2941
|
display: inline-flex;
|
|
2923
2942
|
align-items: center;
|
|
@@ -2940,7 +2959,7 @@ var TimeFormatSelect = ({
|
|
|
2940
2959
|
const handleChange = (e) => {
|
|
2941
2960
|
onChange(e.target.value);
|
|
2942
2961
|
};
|
|
2943
|
-
return /* @__PURE__ */ (0,
|
|
2962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SelectWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2944
2963
|
BaseSelect,
|
|
2945
2964
|
{
|
|
2946
2965
|
className: "time-format",
|
|
@@ -2948,14 +2967,14 @@ var TimeFormatSelect = ({
|
|
|
2948
2967
|
onChange: handleChange,
|
|
2949
2968
|
disabled,
|
|
2950
2969
|
"aria-label": "Time format selection",
|
|
2951
|
-
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0,
|
|
2970
|
+
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("option", { value: option.value, children: option.label }, option.value))
|
|
2952
2971
|
}
|
|
2953
2972
|
) });
|
|
2954
2973
|
};
|
|
2955
2974
|
|
|
2956
2975
|
// src/components/Track.tsx
|
|
2957
2976
|
var import_styled_components24 = __toESM(require("styled-components"));
|
|
2958
|
-
var
|
|
2977
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2959
2978
|
var Container = import_styled_components24.default.div.attrs((props) => ({
|
|
2960
2979
|
style: {
|
|
2961
2980
|
height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`
|
|
@@ -3010,7 +3029,7 @@ var Track = ({
|
|
|
3010
3029
|
controls: { show, width: controlWidth }
|
|
3011
3030
|
} = usePlaylistInfo();
|
|
3012
3031
|
const controls = useTrackControls();
|
|
3013
|
-
return /* @__PURE__ */ (0,
|
|
3032
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
3014
3033
|
Container,
|
|
3015
3034
|
{
|
|
3016
3035
|
$numChannels: numChannels,
|
|
@@ -3021,15 +3040,8 @@ var Track = ({
|
|
|
3021
3040
|
$hasClipHeaders: hasClipHeaders,
|
|
3022
3041
|
$isSelected: isSelected,
|
|
3023
3042
|
children: [
|
|
3024
|
-
/* @__PURE__ */ (0,
|
|
3025
|
-
|
|
3026
|
-
{
|
|
3027
|
-
$controlWidth: show ? controlWidth : 0,
|
|
3028
|
-
$isSelected: isSelected,
|
|
3029
|
-
children: controls
|
|
3030
|
-
}
|
|
3031
|
-
),
|
|
3032
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3043
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ControlsWrapper, { $controlWidth: show ? controlWidth : 0, $isSelected: isSelected, children: controls }),
|
|
3044
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3033
3045
|
ChannelContainer,
|
|
3034
3046
|
{
|
|
3035
3047
|
$controlWidth: show ? controlWidth : 0,
|
|
@@ -3060,8 +3072,11 @@ var Button = import_styled_components25.default.button.attrs({
|
|
|
3060
3072
|
font-size: ${(props) => props.theme.fontSizeSmall};
|
|
3061
3073
|
line-height: 1;
|
|
3062
3074
|
border-radius: ${(props) => props.theme.borderRadius};
|
|
3063
|
-
transition:
|
|
3064
|
-
|
|
3075
|
+
transition:
|
|
3076
|
+
color 0.15s ease-in-out,
|
|
3077
|
+
background-color 0.15s ease-in-out,
|
|
3078
|
+
border-color 0.15s ease-in-out,
|
|
3079
|
+
box-shadow 0.15s ease-in-out;
|
|
3065
3080
|
cursor: pointer;
|
|
3066
3081
|
|
|
3067
3082
|
${(props) => {
|
|
@@ -3136,8 +3151,8 @@ var ButtonGroup = import_styled_components26.default.div`
|
|
|
3136
3151
|
|
|
3137
3152
|
// src/components/TrackControls/CloseButton.tsx
|
|
3138
3153
|
var import_styled_components27 = __toESM(require("styled-components"));
|
|
3139
|
-
var
|
|
3140
|
-
var
|
|
3154
|
+
var import_react21 = require("@phosphor-icons/react");
|
|
3155
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3141
3156
|
var StyledCloseButton = import_styled_components27.default.button`
|
|
3142
3157
|
position: absolute;
|
|
3143
3158
|
left: 0;
|
|
@@ -3152,17 +3167,16 @@ var StyledCloseButton = import_styled_components27.default.button`
|
|
|
3152
3167
|
align-items: center;
|
|
3153
3168
|
justify-content: center;
|
|
3154
3169
|
opacity: 0.7;
|
|
3155
|
-
transition:
|
|
3170
|
+
transition:
|
|
3171
|
+
opacity 0.15s,
|
|
3172
|
+
color 0.15s;
|
|
3156
3173
|
|
|
3157
3174
|
&:hover {
|
|
3158
3175
|
opacity: 1;
|
|
3159
3176
|
color: #dc3545;
|
|
3160
3177
|
}
|
|
3161
3178
|
`;
|
|
3162
|
-
var CloseButton = ({
|
|
3163
|
-
onClick,
|
|
3164
|
-
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" }) });
|
|
3179
|
+
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" }) });
|
|
3166
3180
|
|
|
3167
3181
|
// src/components/TrackControls/Controls.tsx
|
|
3168
3182
|
var import_styled_components28 = __toESM(require("styled-components"));
|
|
@@ -3197,24 +3211,24 @@ var Header = import_styled_components29.default.header`
|
|
|
3197
3211
|
`;
|
|
3198
3212
|
|
|
3199
3213
|
// src/components/TrackControls/VolumeDownIcon.tsx
|
|
3200
|
-
var
|
|
3201
|
-
var
|
|
3202
|
-
var VolumeDownIcon = (props) => /* @__PURE__ */ (0,
|
|
3214
|
+
var import_react22 = require("@phosphor-icons/react");
|
|
3215
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
3216
|
+
var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react22.SpeakerLowIcon, { weight: "light", ...props });
|
|
3203
3217
|
|
|
3204
3218
|
// src/components/TrackControls/VolumeUpIcon.tsx
|
|
3205
|
-
var
|
|
3206
|
-
var
|
|
3207
|
-
var VolumeUpIcon = (props) => /* @__PURE__ */ (0,
|
|
3219
|
+
var import_react23 = require("@phosphor-icons/react");
|
|
3220
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
3221
|
+
var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react23.SpeakerHighIcon, { weight: "light", ...props });
|
|
3208
3222
|
|
|
3209
3223
|
// src/components/TrackControls/TrashIcon.tsx
|
|
3210
|
-
var
|
|
3211
|
-
var
|
|
3212
|
-
var TrashIcon = (props) => /* @__PURE__ */ (0,
|
|
3224
|
+
var import_react24 = require("@phosphor-icons/react");
|
|
3225
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
3226
|
+
var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react24.TrashIcon, { weight: "light", ...props });
|
|
3213
3227
|
|
|
3214
3228
|
// src/components/TrackControls/DotsIcon.tsx
|
|
3215
|
-
var
|
|
3216
|
-
var
|
|
3217
|
-
var DotsIcon = (props) => /* @__PURE__ */ (0,
|
|
3229
|
+
var import_react25 = require("@phosphor-icons/react");
|
|
3230
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
3231
|
+
var DotsIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react25.DotsThreeIcon, { weight: "bold", ...props });
|
|
3218
3232
|
|
|
3219
3233
|
// src/components/TrackControls/Slider.tsx
|
|
3220
3234
|
var import_styled_components30 = __toESM(require("styled-components"));
|
|
@@ -3282,10 +3296,10 @@ var SliderWrapper = import_styled_components31.default.label`
|
|
|
3282
3296
|
`;
|
|
3283
3297
|
|
|
3284
3298
|
// src/components/TrackMenu.tsx
|
|
3285
|
-
var
|
|
3299
|
+
var import_react26 = __toESM(require("react"));
|
|
3286
3300
|
var import_react_dom = require("react-dom");
|
|
3287
3301
|
var import_styled_components32 = __toESM(require("styled-components"));
|
|
3288
|
-
var
|
|
3302
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
3289
3303
|
var MenuContainer = import_styled_components32.default.div`
|
|
3290
3304
|
position: relative;
|
|
3291
3305
|
display: inline-block;
|
|
@@ -3323,16 +3337,14 @@ var Divider = import_styled_components32.default.hr`
|
|
|
3323
3337
|
border-top: 1px solid rgba(128, 128, 128, 0.3);
|
|
3324
3338
|
margin: 0.35rem 0;
|
|
3325
3339
|
`;
|
|
3326
|
-
var TrackMenu = ({
|
|
3327
|
-
|
|
3328
|
-
}) => {
|
|
3329
|
-
const [open, setOpen] = (0, import_react24.useState)(false);
|
|
3340
|
+
var TrackMenu = ({ items: itemsProp }) => {
|
|
3341
|
+
const [open, setOpen] = (0, import_react26.useState)(false);
|
|
3330
3342
|
const close = () => setOpen(false);
|
|
3331
3343
|
const items = typeof itemsProp === "function" ? itemsProp(close) : itemsProp;
|
|
3332
|
-
const [dropdownPos, setDropdownPos] = (0,
|
|
3333
|
-
const buttonRef = (0,
|
|
3334
|
-
const dropdownRef = (0,
|
|
3335
|
-
(0,
|
|
3344
|
+
const [dropdownPos, setDropdownPos] = (0, import_react26.useState)({ top: 0, left: 0 });
|
|
3345
|
+
const buttonRef = (0, import_react26.useRef)(null);
|
|
3346
|
+
const dropdownRef = (0, import_react26.useRef)(null);
|
|
3347
|
+
(0, import_react26.useEffect)(() => {
|
|
3336
3348
|
if (open && buttonRef.current) {
|
|
3337
3349
|
const rect = buttonRef.current.getBoundingClientRect();
|
|
3338
3350
|
setDropdownPos({
|
|
@@ -3341,7 +3353,7 @@ var TrackMenu = ({
|
|
|
3341
3353
|
});
|
|
3342
3354
|
}
|
|
3343
3355
|
}, [open]);
|
|
3344
|
-
(0,
|
|
3356
|
+
(0, import_react26.useEffect)(() => {
|
|
3345
3357
|
if (!open) return;
|
|
3346
3358
|
const handleClick = (e) => {
|
|
3347
3359
|
const target = e.target;
|
|
@@ -3352,8 +3364,8 @@ var TrackMenu = ({
|
|
|
3352
3364
|
document.addEventListener("mousedown", handleClick);
|
|
3353
3365
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
3354
3366
|
}, [open]);
|
|
3355
|
-
return /* @__PURE__ */ (0,
|
|
3356
|
-
/* @__PURE__ */ (0,
|
|
3367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(MenuContainer, { children: [
|
|
3368
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
3357
3369
|
MenuButton,
|
|
3358
3370
|
{
|
|
3359
3371
|
ref: buttonRef,
|
|
@@ -3364,19 +3376,19 @@ var TrackMenu = ({
|
|
|
3364
3376
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3365
3377
|
title: "Track menu",
|
|
3366
3378
|
"aria-label": "Track menu",
|
|
3367
|
-
children: /* @__PURE__ */ (0,
|
|
3379
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(DotsIcon, { size: 16 })
|
|
3368
3380
|
}
|
|
3369
3381
|
),
|
|
3370
3382
|
open && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
|
|
3371
|
-
/* @__PURE__ */ (0,
|
|
3383
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
3372
3384
|
Dropdown,
|
|
3373
3385
|
{
|
|
3374
3386
|
ref: dropdownRef,
|
|
3375
3387
|
$top: dropdownPos.top,
|
|
3376
3388
|
$left: dropdownPos.left,
|
|
3377
3389
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3378
|
-
children: items.map((item, index) => /* @__PURE__ */ (0,
|
|
3379
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
3390
|
+
children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_react26.default.Fragment, { children: [
|
|
3391
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Divider, {}),
|
|
3380
3392
|
item.content
|
|
3381
3393
|
] }, item.id))
|
|
3382
3394
|
}
|
|
@@ -3408,6 +3420,7 @@ var TrackMenu = ({
|
|
|
3408
3420
|
ClipBoundary,
|
|
3409
3421
|
ClipHeader,
|
|
3410
3422
|
ClipHeaderPresentational,
|
|
3423
|
+
ClipViewportOriginProvider,
|
|
3411
3424
|
CloseButton,
|
|
3412
3425
|
Controls,
|
|
3413
3426
|
DevicePixelRatioProvider,
|
|
@@ -3417,7 +3430,6 @@ var TrackMenu = ({
|
|
|
3417
3430
|
InlineLabel,
|
|
3418
3431
|
LoopRegion,
|
|
3419
3432
|
LoopRegionMarkers,
|
|
3420
|
-
MAX_CANVAS_WIDTH,
|
|
3421
3433
|
MasterVolumeControl,
|
|
3422
3434
|
Playhead,
|
|
3423
3435
|
PlayheadWithMarker,
|
|
@@ -3458,6 +3470,7 @@ var TrackMenu = ({
|
|
|
3458
3470
|
samplesToSeconds,
|
|
3459
3471
|
secondsToPixels,
|
|
3460
3472
|
secondsToSamples,
|
|
3473
|
+
useClipViewportOrigin,
|
|
3461
3474
|
useDevicePixelRatio,
|
|
3462
3475
|
usePlaylistInfo,
|
|
3463
3476
|
usePlayoutStatus,
|
|
@@ -3466,6 +3479,7 @@ var TrackMenu = ({
|
|
|
3466
3479
|
useScrollViewportSelector,
|
|
3467
3480
|
useTheme,
|
|
3468
3481
|
useTrackControls,
|
|
3482
|
+
useVisibleChunkIndices,
|
|
3469
3483
|
waveformColorToCss
|
|
3470
3484
|
});
|
|
3471
3485
|
//# sourceMappingURL=index.js.map
|