@waveform-playlist/ui-components 7.0.0 → 7.1.1
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 +37 -3
- package/dist/index.d.ts +37 -3
- package/dist/index.js +549 -308
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +523 -279
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -5
package/dist/index.js
CHANGED
|
@@ -60,6 +60,7 @@ __export(index_exports, {
|
|
|
60
60
|
InlineLabel: () => InlineLabel,
|
|
61
61
|
LoopRegion: () => LoopRegion,
|
|
62
62
|
LoopRegionMarkers: () => LoopRegionMarkers,
|
|
63
|
+
MAX_CANVAS_WIDTH: () => MAX_CANVAS_WIDTH,
|
|
63
64
|
MasterVolumeControl: () => MasterVolumeControl,
|
|
64
65
|
Playhead: () => Playhead,
|
|
65
66
|
PlayheadWithMarker: () => PlayheadWithMarker,
|
|
@@ -68,6 +69,7 @@ __export(index_exports, {
|
|
|
68
69
|
PlaylistInfoContext: () => PlaylistInfoContext,
|
|
69
70
|
PlayoutProvider: () => PlayoutProvider,
|
|
70
71
|
ScreenReaderOnly: () => ScreenReaderOnly,
|
|
72
|
+
ScrollViewportProvider: () => ScrollViewportProvider,
|
|
71
73
|
Selection: () => Selection,
|
|
72
74
|
SelectionTimeInputs: () => SelectionTimeInputs,
|
|
73
75
|
Slider: () => Slider,
|
|
@@ -103,6 +105,8 @@ __export(index_exports, {
|
|
|
103
105
|
usePlaylistInfo: () => usePlaylistInfo,
|
|
104
106
|
usePlayoutStatus: () => usePlayoutStatus,
|
|
105
107
|
usePlayoutStatusUpdate: () => usePlayoutStatusUpdate,
|
|
108
|
+
useScrollViewport: () => useScrollViewport,
|
|
109
|
+
useScrollViewportSelector: () => useScrollViewportSelector,
|
|
106
110
|
useTheme: () => useTheme2,
|
|
107
111
|
useTrackControls: () => useTrackControls,
|
|
108
112
|
waveformColorToCss: () => waveformColorToCss
|
|
@@ -438,7 +442,7 @@ var AutomaticScrollCheckbox = ({
|
|
|
438
442
|
};
|
|
439
443
|
|
|
440
444
|
// src/components/Channel.tsx
|
|
441
|
-
var
|
|
445
|
+
var import_react2 = require("react");
|
|
442
446
|
var import_styled_components9 = __toESM(require("styled-components"));
|
|
443
447
|
|
|
444
448
|
// src/wfpl-theme.ts
|
|
@@ -598,9 +602,105 @@ var darkTheme = {
|
|
|
598
602
|
fontSizeSmall: "12px"
|
|
599
603
|
};
|
|
600
604
|
|
|
601
|
-
// src/
|
|
605
|
+
// src/contexts/ScrollViewport.tsx
|
|
606
|
+
var import_react = require("react");
|
|
602
607
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
608
|
+
var ViewportStore = class {
|
|
609
|
+
constructor() {
|
|
610
|
+
this._state = null;
|
|
611
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
612
|
+
this.subscribe = (callback) => {
|
|
613
|
+
this._listeners.add(callback);
|
|
614
|
+
return () => this._listeners.delete(callback);
|
|
615
|
+
};
|
|
616
|
+
this.getSnapshot = () => this._state;
|
|
617
|
+
}
|
|
618
|
+
/**
|
|
619
|
+
* Update viewport state. Applies a 100px scroll threshold to skip updates
|
|
620
|
+
* that don't affect chunk visibility (1000px chunks with 1.5× overscan buffer).
|
|
621
|
+
* Only notifies listeners when the state actually changes.
|
|
622
|
+
*/
|
|
623
|
+
update(scrollLeft, containerWidth) {
|
|
624
|
+
const buffer = containerWidth * 1.5;
|
|
625
|
+
const visibleStart = Math.max(0, scrollLeft - buffer);
|
|
626
|
+
const visibleEnd = scrollLeft + containerWidth + buffer;
|
|
627
|
+
if (this._state && this._state.containerWidth === containerWidth && Math.abs(this._state.scrollLeft - scrollLeft) < 100) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
this._state = { scrollLeft, containerWidth, visibleStart, visibleEnd };
|
|
631
|
+
for (const listener of this._listeners) {
|
|
632
|
+
listener();
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
var ViewportStoreContext = (0, import_react.createContext)(null);
|
|
637
|
+
var EMPTY_SUBSCRIBE = () => () => {
|
|
638
|
+
};
|
|
639
|
+
var NULL_SNAPSHOT = () => null;
|
|
640
|
+
var ScrollViewportProvider = ({
|
|
641
|
+
containerRef,
|
|
642
|
+
children
|
|
643
|
+
}) => {
|
|
644
|
+
const storeRef = (0, import_react.useRef)(null);
|
|
645
|
+
if (storeRef.current === null) {
|
|
646
|
+
storeRef.current = new ViewportStore();
|
|
647
|
+
}
|
|
648
|
+
const store = storeRef.current;
|
|
649
|
+
const rafIdRef = (0, import_react.useRef)(null);
|
|
650
|
+
const measure = (0, import_react.useCallback)(() => {
|
|
651
|
+
const el = containerRef.current;
|
|
652
|
+
if (!el) return;
|
|
653
|
+
store.update(el.scrollLeft, el.clientWidth);
|
|
654
|
+
}, [containerRef, store]);
|
|
655
|
+
const scheduleUpdate = (0, import_react.useCallback)(() => {
|
|
656
|
+
if (rafIdRef.current !== null) return;
|
|
657
|
+
rafIdRef.current = requestAnimationFrame(() => {
|
|
658
|
+
rafIdRef.current = null;
|
|
659
|
+
measure();
|
|
660
|
+
});
|
|
661
|
+
}, [measure]);
|
|
662
|
+
(0, import_react.useEffect)(() => {
|
|
663
|
+
const el = containerRef.current;
|
|
664
|
+
if (!el) return;
|
|
665
|
+
measure();
|
|
666
|
+
el.addEventListener("scroll", scheduleUpdate, { passive: true });
|
|
667
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
668
|
+
scheduleUpdate();
|
|
669
|
+
});
|
|
670
|
+
resizeObserver.observe(el);
|
|
671
|
+
return () => {
|
|
672
|
+
el.removeEventListener("scroll", scheduleUpdate);
|
|
673
|
+
resizeObserver.disconnect();
|
|
674
|
+
if (rafIdRef.current !== null) {
|
|
675
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
676
|
+
rafIdRef.current = null;
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
}, [containerRef, measure, scheduleUpdate]);
|
|
680
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ViewportStoreContext.Provider, { value: store, children });
|
|
681
|
+
};
|
|
682
|
+
var useScrollViewport = () => {
|
|
683
|
+
const store = (0, import_react.useContext)(ViewportStoreContext);
|
|
684
|
+
return (0, import_react.useSyncExternalStore)(
|
|
685
|
+
store ? store.subscribe : EMPTY_SUBSCRIBE,
|
|
686
|
+
store ? store.getSnapshot : NULL_SNAPSHOT,
|
|
687
|
+
NULL_SNAPSHOT
|
|
688
|
+
);
|
|
689
|
+
};
|
|
690
|
+
function useScrollViewportSelector(selector) {
|
|
691
|
+
const store = (0, import_react.useContext)(ViewportStoreContext);
|
|
692
|
+
return (0, import_react.useSyncExternalStore)(
|
|
693
|
+
store ? store.subscribe : EMPTY_SUBSCRIBE,
|
|
694
|
+
() => selector(store ? store.getSnapshot() : null),
|
|
695
|
+
() => selector(null)
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/constants.ts
|
|
603
700
|
var MAX_CANVAS_WIDTH = 1e3;
|
|
701
|
+
|
|
702
|
+
// src/components/Channel.tsx
|
|
703
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
604
704
|
function createCanvasFillStyle(ctx, color, width, height) {
|
|
605
705
|
if (!isWaveformGradient(color)) {
|
|
606
706
|
return color;
|
|
@@ -619,11 +719,12 @@ function createCanvasFillStyle(ctx, color, width, height) {
|
|
|
619
719
|
var Waveform = import_styled_components9.default.canvas.attrs((props) => ({
|
|
620
720
|
style: {
|
|
621
721
|
width: `${props.$cssWidth}px`,
|
|
622
|
-
height: `${props.$waveHeight}px
|
|
722
|
+
height: `${props.$waveHeight}px`,
|
|
723
|
+
left: `${props.$left}px`
|
|
623
724
|
}
|
|
624
725
|
}))`
|
|
625
|
-
|
|
626
|
-
|
|
726
|
+
position: absolute;
|
|
727
|
+
top: 0;
|
|
627
728
|
/* Promote to own compositing layer for smoother scrolling */
|
|
628
729
|
will-change: transform;
|
|
629
730
|
/* Disable image rendering interpolation */
|
|
@@ -659,8 +760,25 @@ var Channel = (props) => {
|
|
|
659
760
|
transparentBackground = false,
|
|
660
761
|
drawMode = "inverted"
|
|
661
762
|
} = props;
|
|
662
|
-
const canvasesRef = (0,
|
|
663
|
-
const
|
|
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)(
|
|
664
782
|
(canvas) => {
|
|
665
783
|
if (canvas !== null) {
|
|
666
784
|
const index2 = parseInt(canvas.dataset.index, 10);
|
|
@@ -669,12 +787,22 @@ var Channel = (props) => {
|
|
|
669
787
|
},
|
|
670
788
|
[]
|
|
671
789
|
);
|
|
672
|
-
(0,
|
|
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)(() => {
|
|
673
799
|
const canvases = canvasesRef.current;
|
|
674
800
|
const step = barWidth + barGap;
|
|
675
|
-
let globalPixelOffset = 0;
|
|
676
801
|
for (let i = 0; i < canvases.length; i++) {
|
|
677
802
|
const canvas = canvases[i];
|
|
803
|
+
if (!canvas) continue;
|
|
804
|
+
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
805
|
+
const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
|
|
678
806
|
const ctx = canvas.getContext("2d");
|
|
679
807
|
const h2 = Math.floor(waveHeight / 2);
|
|
680
808
|
const maxValue = 2 ** (bits - 1);
|
|
@@ -717,7 +845,6 @@ var Channel = (props) => {
|
|
|
717
845
|
}
|
|
718
846
|
}
|
|
719
847
|
}
|
|
720
|
-
globalPixelOffset += canvas.width / devicePixelRatio;
|
|
721
848
|
}
|
|
722
849
|
}, [
|
|
723
850
|
data,
|
|
@@ -729,32 +856,29 @@ var Channel = (props) => {
|
|
|
729
856
|
length,
|
|
730
857
|
barWidth,
|
|
731
858
|
barGap,
|
|
732
|
-
drawMode
|
|
859
|
+
drawMode,
|
|
860
|
+
visibleChunkKey
|
|
733
861
|
]);
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
const currentWidth = Math.min(totalWidth, MAX_CANVAS_WIDTH);
|
|
739
|
-
const waveform = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
862
|
+
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, import_jsx_runtime4.jsx)(
|
|
740
866
|
Waveform,
|
|
741
867
|
{
|
|
742
868
|
$cssWidth: currentWidth,
|
|
869
|
+
$left: chunkLeft,
|
|
743
870
|
width: currentWidth * devicePixelRatio,
|
|
744
871
|
height: waveHeight * devicePixelRatio,
|
|
745
872
|
$waveHeight: waveHeight,
|
|
746
|
-
"data-index":
|
|
873
|
+
"data-index": i,
|
|
747
874
|
ref: canvasRef
|
|
748
875
|
},
|
|
749
|
-
`${length}-${
|
|
876
|
+
`${length}-${i}`
|
|
750
877
|
);
|
|
751
|
-
|
|
752
|
-
totalWidth -= currentWidth;
|
|
753
|
-
waveformCount += 1;
|
|
754
|
-
}
|
|
878
|
+
});
|
|
755
879
|
const bgColor = waveFillColor;
|
|
756
880
|
const backgroundCss = transparentBackground ? "transparent" : waveformColorToCss(bgColor);
|
|
757
|
-
return /* @__PURE__ */ (0,
|
|
881
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
758
882
|
Wrapper,
|
|
759
883
|
{
|
|
760
884
|
$index: index,
|
|
@@ -768,8 +892,8 @@ var Channel = (props) => {
|
|
|
768
892
|
};
|
|
769
893
|
|
|
770
894
|
// src/components/ErrorBoundary.tsx
|
|
771
|
-
var
|
|
772
|
-
var
|
|
895
|
+
var import_react3 = __toESM(require("react"));
|
|
896
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
773
897
|
var errorContainerStyle = {
|
|
774
898
|
padding: "16px",
|
|
775
899
|
background: "#1a1a2e",
|
|
@@ -783,7 +907,7 @@ var errorContainerStyle = {
|
|
|
783
907
|
alignItems: "center",
|
|
784
908
|
justifyContent: "center"
|
|
785
909
|
};
|
|
786
|
-
var PlaylistErrorBoundary = class extends
|
|
910
|
+
var PlaylistErrorBoundary = class extends import_react3.default.Component {
|
|
787
911
|
constructor(props) {
|
|
788
912
|
super(props);
|
|
789
913
|
this.state = { hasError: false, error: null };
|
|
@@ -799,7 +923,7 @@ var PlaylistErrorBoundary = class extends import_react2.default.Component {
|
|
|
799
923
|
if (this.props.fallback) {
|
|
800
924
|
return this.props.fallback;
|
|
801
925
|
}
|
|
802
|
-
return /* @__PURE__ */ (0,
|
|
926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: errorContainerStyle, children: "Waveform playlist encountered an error. Check console for details." });
|
|
803
927
|
}
|
|
804
928
|
return this.props.children;
|
|
805
929
|
}
|
|
@@ -812,7 +936,7 @@ var import_utilities = require("@dnd-kit/utilities");
|
|
|
812
936
|
|
|
813
937
|
// src/components/ClipHeader.tsx
|
|
814
938
|
var import_styled_components10 = __toESM(require("styled-components"));
|
|
815
|
-
var
|
|
939
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
816
940
|
var CLIP_HEADER_HEIGHT = 22;
|
|
817
941
|
var HeaderContainer = import_styled_components10.default.div`
|
|
818
942
|
position: relative;
|
|
@@ -852,27 +976,27 @@ var ClipHeaderPresentational = ({
|
|
|
852
976
|
trackName,
|
|
853
977
|
isSelected = false
|
|
854
978
|
}) => {
|
|
855
|
-
return /* @__PURE__ */ (0,
|
|
979
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
856
980
|
HeaderContainer,
|
|
857
981
|
{
|
|
858
982
|
$isDragging: false,
|
|
859
983
|
$interactive: false,
|
|
860
984
|
$isSelected: isSelected,
|
|
861
|
-
children: /* @__PURE__ */ (0,
|
|
985
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TrackName, { children: trackName })
|
|
862
986
|
}
|
|
863
987
|
);
|
|
864
988
|
};
|
|
865
989
|
var ClipHeader = ({
|
|
866
990
|
clipId,
|
|
867
|
-
trackIndex,
|
|
868
|
-
clipIndex,
|
|
991
|
+
trackIndex: _trackIndex,
|
|
992
|
+
clipIndex: _clipIndex,
|
|
869
993
|
trackName,
|
|
870
994
|
isSelected = false,
|
|
871
995
|
disableDrag = false,
|
|
872
996
|
dragHandleProps
|
|
873
997
|
}) => {
|
|
874
998
|
if (disableDrag || !dragHandleProps) {
|
|
875
|
-
return /* @__PURE__ */ (0,
|
|
999
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
876
1000
|
ClipHeaderPresentational,
|
|
877
1001
|
{
|
|
878
1002
|
trackName,
|
|
@@ -881,7 +1005,7 @@ var ClipHeader = ({
|
|
|
881
1005
|
);
|
|
882
1006
|
}
|
|
883
1007
|
const { attributes, listeners, setActivatorNodeRef } = dragHandleProps;
|
|
884
|
-
return /* @__PURE__ */ (0,
|
|
1008
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
885
1009
|
HeaderContainer,
|
|
886
1010
|
{
|
|
887
1011
|
ref: setActivatorNodeRef,
|
|
@@ -890,15 +1014,15 @@ var ClipHeader = ({
|
|
|
890
1014
|
$isSelected: isSelected,
|
|
891
1015
|
...listeners,
|
|
892
1016
|
...attributes,
|
|
893
|
-
children: /* @__PURE__ */ (0,
|
|
1017
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TrackName, { children: trackName })
|
|
894
1018
|
}
|
|
895
1019
|
);
|
|
896
1020
|
};
|
|
897
1021
|
|
|
898
1022
|
// src/components/ClipBoundary.tsx
|
|
899
|
-
var
|
|
1023
|
+
var import_react4 = __toESM(require("react"));
|
|
900
1024
|
var import_styled_components11 = __toESM(require("styled-components"));
|
|
901
|
-
var
|
|
1025
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
902
1026
|
var CLIP_BOUNDARY_WIDTH = 8;
|
|
903
1027
|
var CLIP_BOUNDARY_WIDTH_TOUCH = 24;
|
|
904
1028
|
var BoundaryContainer = import_styled_components11.default.div`
|
|
@@ -932,18 +1056,18 @@ var BoundaryContainer = import_styled_components11.default.div`
|
|
|
932
1056
|
`;
|
|
933
1057
|
var ClipBoundary = ({
|
|
934
1058
|
clipId,
|
|
935
|
-
trackIndex,
|
|
936
|
-
clipIndex,
|
|
1059
|
+
trackIndex: _trackIndex,
|
|
1060
|
+
clipIndex: _clipIndex,
|
|
937
1061
|
edge,
|
|
938
1062
|
dragHandleProps,
|
|
939
1063
|
touchOptimized = false
|
|
940
1064
|
}) => {
|
|
941
|
-
const [isHovered, setIsHovered] =
|
|
1065
|
+
const [isHovered, setIsHovered] = import_react4.default.useState(false);
|
|
942
1066
|
if (!dragHandleProps) {
|
|
943
1067
|
return null;
|
|
944
1068
|
}
|
|
945
1069
|
const { attributes, listeners, setActivatorNodeRef, isDragging } = dragHandleProps;
|
|
946
|
-
return /* @__PURE__ */ (0,
|
|
1070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
947
1071
|
BoundaryContainer,
|
|
948
1072
|
{
|
|
949
1073
|
ref: setActivatorNodeRef,
|
|
@@ -963,7 +1087,7 @@ var ClipBoundary = ({
|
|
|
963
1087
|
|
|
964
1088
|
// src/components/FadeOverlay.tsx
|
|
965
1089
|
var import_styled_components12 = __toESM(require("styled-components"));
|
|
966
|
-
var
|
|
1090
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
967
1091
|
var FadeContainer = import_styled_components12.default.div.attrs((props) => ({
|
|
968
1092
|
style: {
|
|
969
1093
|
left: `${props.$left}px`,
|
|
@@ -1020,7 +1144,7 @@ var FadeOverlay = ({
|
|
|
1020
1144
|
const theme = (0, import_styled_components12.useTheme)();
|
|
1021
1145
|
if (width < 1) return null;
|
|
1022
1146
|
const fillColor = color || theme?.fadeOverlayColor || "rgba(0, 0, 0, 0.4)";
|
|
1023
|
-
return /* @__PURE__ */ (0,
|
|
1147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FadeContainer, { $left: left, $width: width, $type: type, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(FadeSvg, { $type: type, viewBox: `0 0 ${width} 100`, preserveAspectRatio: "none", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1024
1148
|
"path",
|
|
1025
1149
|
{
|
|
1026
1150
|
d: generateFadePath(width, 100, curveType),
|
|
@@ -1030,7 +1154,7 @@ var FadeOverlay = ({
|
|
|
1030
1154
|
};
|
|
1031
1155
|
|
|
1032
1156
|
// src/components/Clip.tsx
|
|
1033
|
-
var
|
|
1157
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1034
1158
|
var ClipContainer = import_styled_components13.default.div.attrs((props) => ({
|
|
1035
1159
|
style: props.$isOverlay ? {} : {
|
|
1036
1160
|
left: `${props.$left}px`,
|
|
@@ -1115,7 +1239,7 @@ var Clip = ({
|
|
|
1115
1239
|
zIndex: isDragging ? 100 : void 0
|
|
1116
1240
|
// Below controls (z-index: 999) but above other clips
|
|
1117
1241
|
} : void 0;
|
|
1118
|
-
return /* @__PURE__ */ (0,
|
|
1242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
1119
1243
|
ClipContainer,
|
|
1120
1244
|
{
|
|
1121
1245
|
ref: setNodeRef,
|
|
@@ -1128,7 +1252,7 @@ var Clip = ({
|
|
|
1128
1252
|
"data-track-id": trackId,
|
|
1129
1253
|
onMouseDown,
|
|
1130
1254
|
children: [
|
|
1131
|
-
showHeader && /* @__PURE__ */ (0,
|
|
1255
|
+
showHeader && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1132
1256
|
ClipHeader,
|
|
1133
1257
|
{
|
|
1134
1258
|
clipId,
|
|
@@ -1140,9 +1264,9 @@ var Clip = ({
|
|
|
1140
1264
|
dragHandleProps: enableDrag ? { attributes, listeners, setActivatorNodeRef } : void 0
|
|
1141
1265
|
}
|
|
1142
1266
|
),
|
|
1143
|
-
/* @__PURE__ */ (0,
|
|
1267
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(ChannelsWrapper, { $isOverlay: isOverlay, children: [
|
|
1144
1268
|
children,
|
|
1145
|
-
showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */ (0,
|
|
1269
|
+
showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1146
1270
|
FadeOverlay,
|
|
1147
1271
|
{
|
|
1148
1272
|
left: 0,
|
|
@@ -1151,7 +1275,7 @@ var Clip = ({
|
|
|
1151
1275
|
curveType: fadeIn.type
|
|
1152
1276
|
}
|
|
1153
1277
|
),
|
|
1154
|
-
showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */ (0,
|
|
1278
|
+
showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1155
1279
|
FadeOverlay,
|
|
1156
1280
|
{
|
|
1157
1281
|
left: width - Math.floor(fadeOut.duration * sampleRate / samplesPerPixel),
|
|
@@ -1161,8 +1285,8 @@ var Clip = ({
|
|
|
1161
1285
|
}
|
|
1162
1286
|
)
|
|
1163
1287
|
] }),
|
|
1164
|
-
showHeader && !disableHeaderDrag && !isOverlay && /* @__PURE__ */ (0,
|
|
1165
|
-
/* @__PURE__ */ (0,
|
|
1288
|
+
showHeader && !disableHeaderDrag && !isOverlay && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1289
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1166
1290
|
ClipBoundary,
|
|
1167
1291
|
{
|
|
1168
1292
|
clipId,
|
|
@@ -1178,7 +1302,7 @@ var Clip = ({
|
|
|
1178
1302
|
}
|
|
1179
1303
|
}
|
|
1180
1304
|
),
|
|
1181
|
-
/* @__PURE__ */ (0,
|
|
1305
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1182
1306
|
ClipBoundary,
|
|
1183
1307
|
{
|
|
1184
1308
|
clipId,
|
|
@@ -1202,7 +1326,7 @@ var Clip = ({
|
|
|
1202
1326
|
|
|
1203
1327
|
// src/components/MasterVolumeControl.tsx
|
|
1204
1328
|
var import_styled_components14 = __toESM(require("styled-components"));
|
|
1205
|
-
var
|
|
1329
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1206
1330
|
var VolumeContainer = import_styled_components14.default.div`
|
|
1207
1331
|
display: inline-flex;
|
|
1208
1332
|
align-items: center;
|
|
@@ -1224,9 +1348,9 @@ var MasterVolumeControl = ({
|
|
|
1224
1348
|
const handleChange = (e) => {
|
|
1225
1349
|
onChange(parseFloat(e.target.value) / 100);
|
|
1226
1350
|
};
|
|
1227
|
-
return /* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1229
|
-
/* @__PURE__ */ (0,
|
|
1351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(VolumeContainer, { className, children: [
|
|
1352
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(VolumeLabel, { htmlFor: "master-gain", children: "Master Volume" }),
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
1230
1354
|
VolumeSlider,
|
|
1231
1355
|
{
|
|
1232
1356
|
min: "0",
|
|
@@ -1241,9 +1365,9 @@ var MasterVolumeControl = ({
|
|
|
1241
1365
|
};
|
|
1242
1366
|
|
|
1243
1367
|
// src/components/Playhead.tsx
|
|
1244
|
-
var
|
|
1368
|
+
var import_react5 = require("react");
|
|
1245
1369
|
var import_styled_components15 = __toESM(require("styled-components"));
|
|
1246
|
-
var
|
|
1370
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1247
1371
|
var PlayheadLine = import_styled_components15.default.div.attrs((props) => ({
|
|
1248
1372
|
style: {
|
|
1249
1373
|
transform: `translate3d(${props.$position}px, 0, 0)`
|
|
@@ -1260,7 +1384,7 @@ var PlayheadLine = import_styled_components15.default.div.attrs((props) => ({
|
|
|
1260
1384
|
will-change: transform;
|
|
1261
1385
|
`;
|
|
1262
1386
|
var Playhead = ({ position, color = "#ff0000" }) => {
|
|
1263
|
-
return /* @__PURE__ */ (0,
|
|
1387
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PlayheadLine, { $position: position, $color: color });
|
|
1264
1388
|
};
|
|
1265
1389
|
var PlayheadWithMarkerContainer = import_styled_components15.default.div`
|
|
1266
1390
|
position: absolute;
|
|
@@ -1300,9 +1424,9 @@ var PlayheadWithMarker = ({
|
|
|
1300
1424
|
controlsOffset,
|
|
1301
1425
|
getAudioContextTime
|
|
1302
1426
|
}) => {
|
|
1303
|
-
const containerRef = (0,
|
|
1304
|
-
const animationFrameRef = (0,
|
|
1305
|
-
(0,
|
|
1427
|
+
const containerRef = (0, import_react5.useRef)(null);
|
|
1428
|
+
const animationFrameRef = (0, import_react5.useRef)(null);
|
|
1429
|
+
(0, import_react5.useEffect)(() => {
|
|
1306
1430
|
const updatePosition = () => {
|
|
1307
1431
|
if (containerRef.current) {
|
|
1308
1432
|
let time;
|
|
@@ -1331,22 +1455,23 @@ var PlayheadWithMarker = ({
|
|
|
1331
1455
|
}
|
|
1332
1456
|
};
|
|
1333
1457
|
}, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef, playbackStartTimeRef, audioStartPositionRef, getAudioContextTime]);
|
|
1334
|
-
(0,
|
|
1458
|
+
(0, import_react5.useEffect)(() => {
|
|
1335
1459
|
if (!isPlaying && containerRef.current) {
|
|
1336
1460
|
const time = currentTimeRef.current ?? 0;
|
|
1337
1461
|
const pos = time * sampleRate / samplesPerPixel + controlsOffset;
|
|
1338
1462
|
containerRef.current.style.transform = `translate3d(${pos}px, 0, 0)`;
|
|
1339
1463
|
}
|
|
1340
1464
|
});
|
|
1341
|
-
return /* @__PURE__ */ (0,
|
|
1342
|
-
/* @__PURE__ */ (0,
|
|
1343
|
-
/* @__PURE__ */ (0,
|
|
1465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(PlayheadWithMarkerContainer, { ref: containerRef, $color: color, children: [
|
|
1466
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MarkerTriangle, { $color: color }),
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(MarkerLine, { $color: color })
|
|
1344
1468
|
] });
|
|
1345
1469
|
};
|
|
1346
1470
|
|
|
1347
1471
|
// src/components/Playlist.tsx
|
|
1348
1472
|
var import_styled_components16 = __toESM(require("styled-components"));
|
|
1349
|
-
var
|
|
1473
|
+
var import_react6 = require("react");
|
|
1474
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1350
1475
|
var Wrapper2 = import_styled_components16.default.div`
|
|
1351
1476
|
overflow-y: hidden;
|
|
1352
1477
|
overflow-x: auto;
|
|
@@ -1400,16 +1525,21 @@ var Playlist = ({
|
|
|
1400
1525
|
isSelecting,
|
|
1401
1526
|
"data-playlist-state": playlistState
|
|
1402
1527
|
}) => {
|
|
1403
|
-
|
|
1528
|
+
const wrapperRef = (0, import_react6.useRef)(null);
|
|
1529
|
+
const handleRef = (0, import_react6.useCallback)((el) => {
|
|
1530
|
+
wrapperRef.current = el;
|
|
1531
|
+
scrollContainerRef?.(el);
|
|
1532
|
+
}, [scrollContainerRef]);
|
|
1533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Wrapper2, { "data-scroll-container": "true", "data-playlist-state": playlistState, ref: handleRef, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScrollViewportProvider, { containerRef: wrapperRef, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1404
1534
|
ScrollContainer,
|
|
1405
1535
|
{
|
|
1406
1536
|
$backgroundColor: backgroundColor,
|
|
1407
1537
|
$width: scrollContainerWidth,
|
|
1408
1538
|
children: [
|
|
1409
|
-
timescale && /* @__PURE__ */ (0,
|
|
1410
|
-
/* @__PURE__ */ (0,
|
|
1539
|
+
timescale && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TimescaleWrapper, { $width: timescaleWidth, $backgroundColor: timescaleBackgroundColor, children: timescale }),
|
|
1540
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(TracksContainer, { $width: tracksWidth, $backgroundColor: backgroundColor, children: [
|
|
1411
1541
|
children,
|
|
1412
|
-
(onTracksClick || onTracksMouseDown) && /* @__PURE__ */ (0,
|
|
1542
|
+
(onTracksClick || onTracksMouseDown) && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1413
1543
|
ClickOverlay,
|
|
1414
1544
|
{
|
|
1415
1545
|
$controlsWidth: controlsWidth,
|
|
@@ -1423,13 +1553,13 @@ var Playlist = ({
|
|
|
1423
1553
|
] })
|
|
1424
1554
|
]
|
|
1425
1555
|
}
|
|
1426
|
-
) });
|
|
1556
|
+
) }) });
|
|
1427
1557
|
};
|
|
1428
1558
|
var StyledPlaylist = (0, import_styled_components16.withTheme)(Playlist);
|
|
1429
1559
|
|
|
1430
1560
|
// src/components/Selection.tsx
|
|
1431
1561
|
var import_styled_components17 = __toESM(require("styled-components"));
|
|
1432
|
-
var
|
|
1562
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1433
1563
|
var SelectionOverlay = import_styled_components17.default.div.attrs((props) => ({
|
|
1434
1564
|
style: {
|
|
1435
1565
|
left: `${props.$left}px`,
|
|
@@ -1453,13 +1583,13 @@ var Selection = ({
|
|
|
1453
1583
|
if (width <= 0) {
|
|
1454
1584
|
return null;
|
|
1455
1585
|
}
|
|
1456
|
-
return /* @__PURE__ */ (0,
|
|
1586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectionOverlay, { $left: startPosition, $width: width, $color: color, "data-selection": true });
|
|
1457
1587
|
};
|
|
1458
1588
|
|
|
1459
1589
|
// src/components/LoopRegion.tsx
|
|
1460
|
-
var
|
|
1590
|
+
var import_react7 = require("react");
|
|
1461
1591
|
var import_styled_components18 = __toESM(require("styled-components"));
|
|
1462
|
-
var
|
|
1592
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1463
1593
|
var LoopRegionOverlayDiv = import_styled_components18.default.div.attrs((props) => ({
|
|
1464
1594
|
style: {
|
|
1465
1595
|
left: `${props.$left}px`,
|
|
@@ -1508,8 +1638,8 @@ var LoopRegion = ({
|
|
|
1508
1638
|
if (width <= 0) {
|
|
1509
1639
|
return null;
|
|
1510
1640
|
}
|
|
1511
|
-
return /* @__PURE__ */ (0,
|
|
1512
|
-
/* @__PURE__ */ (0,
|
|
1641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1513
1643
|
LoopRegionOverlayDiv,
|
|
1514
1644
|
{
|
|
1515
1645
|
$left: startPosition,
|
|
@@ -1518,7 +1648,7 @@ var LoopRegion = ({
|
|
|
1518
1648
|
"data-loop-region": true
|
|
1519
1649
|
}
|
|
1520
1650
|
),
|
|
1521
|
-
/* @__PURE__ */ (0,
|
|
1651
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1522
1652
|
LoopMarker,
|
|
1523
1653
|
{
|
|
1524
1654
|
$left: startPosition,
|
|
@@ -1527,7 +1657,7 @@ var LoopRegion = ({
|
|
|
1527
1657
|
"data-loop-marker": "start"
|
|
1528
1658
|
}
|
|
1529
1659
|
),
|
|
1530
|
-
/* @__PURE__ */ (0,
|
|
1660
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1531
1661
|
LoopMarker,
|
|
1532
1662
|
{
|
|
1533
1663
|
$left: endPosition - 2,
|
|
@@ -1608,12 +1738,12 @@ var LoopRegionMarkers = ({
|
|
|
1608
1738
|
minPosition = 0,
|
|
1609
1739
|
maxPosition = Infinity
|
|
1610
1740
|
}) => {
|
|
1611
|
-
const [draggingMarker, setDraggingMarker] = (0,
|
|
1612
|
-
const dragStartX = (0,
|
|
1613
|
-
const dragStartPosition = (0,
|
|
1614
|
-
const dragStartEnd = (0,
|
|
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);
|
|
1615
1745
|
const width = Math.max(0, endPosition - startPosition);
|
|
1616
|
-
const handleMarkerMouseDown = (0,
|
|
1746
|
+
const handleMarkerMouseDown = (0, import_react7.useCallback)((e, marker) => {
|
|
1617
1747
|
e.preventDefault();
|
|
1618
1748
|
e.stopPropagation();
|
|
1619
1749
|
setDraggingMarker(marker);
|
|
@@ -1638,7 +1768,7 @@ var LoopRegionMarkers = ({
|
|
|
1638
1768
|
document.addEventListener("mousemove", handleMouseMove);
|
|
1639
1769
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1640
1770
|
}, [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]);
|
|
1641
|
-
const handleRegionMouseDown = (0,
|
|
1771
|
+
const handleRegionMouseDown = (0, import_react7.useCallback)((e) => {
|
|
1642
1772
|
e.preventDefault();
|
|
1643
1773
|
e.stopPropagation();
|
|
1644
1774
|
setDraggingMarker("region");
|
|
@@ -1671,8 +1801,8 @@ var LoopRegionMarkers = ({
|
|
|
1671
1801
|
if (width <= 0) {
|
|
1672
1802
|
return null;
|
|
1673
1803
|
}
|
|
1674
|
-
return /* @__PURE__ */ (0,
|
|
1675
|
-
/* @__PURE__ */ (0,
|
|
1804
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
1805
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1676
1806
|
TimescaleLoopShade,
|
|
1677
1807
|
{
|
|
1678
1808
|
$left: startPosition,
|
|
@@ -1683,7 +1813,7 @@ var LoopRegionMarkers = ({
|
|
|
1683
1813
|
"data-loop-region-timescale": true
|
|
1684
1814
|
}
|
|
1685
1815
|
),
|
|
1686
|
-
/* @__PURE__ */ (0,
|
|
1816
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1687
1817
|
DraggableMarkerHandle,
|
|
1688
1818
|
{
|
|
1689
1819
|
$left: startPosition,
|
|
@@ -1694,7 +1824,7 @@ var LoopRegionMarkers = ({
|
|
|
1694
1824
|
"data-loop-marker-handle": "start"
|
|
1695
1825
|
}
|
|
1696
1826
|
),
|
|
1697
|
-
/* @__PURE__ */ (0,
|
|
1827
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1698
1828
|
DraggableMarkerHandle,
|
|
1699
1829
|
{
|
|
1700
1830
|
$left: endPosition,
|
|
@@ -1729,11 +1859,11 @@ var TimescaleLoopRegion = ({
|
|
|
1729
1859
|
maxPosition = Infinity,
|
|
1730
1860
|
controlsOffset = 0
|
|
1731
1861
|
}) => {
|
|
1732
|
-
const [
|
|
1733
|
-
const createStartX = (0,
|
|
1734
|
-
const containerRef = (0,
|
|
1862
|
+
const [, setIsCreating] = (0, import_react7.useState)(false);
|
|
1863
|
+
const createStartX = (0, import_react7.useRef)(0);
|
|
1864
|
+
const containerRef = (0, import_react7.useRef)(null);
|
|
1735
1865
|
const hasLoopRegion = endPosition > startPosition;
|
|
1736
|
-
const handleBackgroundMouseDown = (0,
|
|
1866
|
+
const handleBackgroundMouseDown = (0, import_react7.useCallback)((e) => {
|
|
1737
1867
|
const target = e.target;
|
|
1738
1868
|
if (target.closest("[data-loop-marker-handle]") || target.closest("[data-loop-region-timescale]")) {
|
|
1739
1869
|
return;
|
|
@@ -1761,14 +1891,14 @@ var TimescaleLoopRegion = ({
|
|
|
1761
1891
|
document.addEventListener("mousemove", handleMouseMove);
|
|
1762
1892
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1763
1893
|
}, [minPosition, maxPosition, onLoopRegionChange]);
|
|
1764
|
-
return /* @__PURE__ */ (0,
|
|
1894
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1765
1895
|
TimescaleLoopCreator,
|
|
1766
1896
|
{
|
|
1767
1897
|
ref: containerRef,
|
|
1768
1898
|
$leftOffset: controlsOffset,
|
|
1769
1899
|
onMouseDown: handleBackgroundMouseDown,
|
|
1770
1900
|
"data-timescale-loop-creator": true,
|
|
1771
|
-
children: hasLoopRegion && /* @__PURE__ */ (0,
|
|
1901
|
+
children: hasLoopRegion && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1772
1902
|
LoopRegionMarkers,
|
|
1773
1903
|
{
|
|
1774
1904
|
startPosition,
|
|
@@ -1787,10 +1917,10 @@ var TimescaleLoopRegion = ({
|
|
|
1787
1917
|
};
|
|
1788
1918
|
|
|
1789
1919
|
// src/components/SelectionTimeInputs.tsx
|
|
1790
|
-
var
|
|
1920
|
+
var import_react9 = require("react");
|
|
1791
1921
|
|
|
1792
1922
|
// src/components/TimeInput.tsx
|
|
1793
|
-
var
|
|
1923
|
+
var import_react8 = require("react");
|
|
1794
1924
|
|
|
1795
1925
|
// src/utils/timeFormat.ts
|
|
1796
1926
|
function clockFormat(seconds, decimals) {
|
|
@@ -1840,7 +1970,7 @@ function parseTime(timeStr, format) {
|
|
|
1840
1970
|
}
|
|
1841
1971
|
|
|
1842
1972
|
// src/components/TimeInput.tsx
|
|
1843
|
-
var
|
|
1973
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1844
1974
|
var TimeInput = ({
|
|
1845
1975
|
id,
|
|
1846
1976
|
label,
|
|
@@ -1850,8 +1980,8 @@ var TimeInput = ({
|
|
|
1850
1980
|
onChange,
|
|
1851
1981
|
readOnly = false
|
|
1852
1982
|
}) => {
|
|
1853
|
-
const [displayValue, setDisplayValue] = (0,
|
|
1854
|
-
(0,
|
|
1983
|
+
const [displayValue, setDisplayValue] = (0, import_react8.useState)("");
|
|
1984
|
+
(0, import_react8.useEffect)(() => {
|
|
1855
1985
|
const formatted = formatTime(value, format);
|
|
1856
1986
|
setDisplayValue(formatted);
|
|
1857
1987
|
}, [value, format, id]);
|
|
@@ -1871,9 +2001,9 @@ var TimeInput = ({
|
|
|
1871
2001
|
e.currentTarget.blur();
|
|
1872
2002
|
}
|
|
1873
2003
|
};
|
|
1874
|
-
return /* @__PURE__ */ (0,
|
|
1875
|
-
/* @__PURE__ */ (0,
|
|
1876
|
-
/* @__PURE__ */ (0,
|
|
2004
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ScreenReaderOnly, { as: "label", htmlFor: id, children: label }),
|
|
2006
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1877
2007
|
BaseInput,
|
|
1878
2008
|
{
|
|
1879
2009
|
type: "text",
|
|
@@ -1890,15 +2020,15 @@ var TimeInput = ({
|
|
|
1890
2020
|
};
|
|
1891
2021
|
|
|
1892
2022
|
// src/components/SelectionTimeInputs.tsx
|
|
1893
|
-
var
|
|
2023
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1894
2024
|
var SelectionTimeInputs = ({
|
|
1895
2025
|
selectionStart,
|
|
1896
2026
|
selectionEnd,
|
|
1897
2027
|
onSelectionChange,
|
|
1898
2028
|
className
|
|
1899
2029
|
}) => {
|
|
1900
|
-
const [timeFormat, setTimeFormat] = (0,
|
|
1901
|
-
(0,
|
|
2030
|
+
const [timeFormat, setTimeFormat] = (0, import_react9.useState)("hh:mm:ss.uuu");
|
|
2031
|
+
(0, import_react9.useEffect)(() => {
|
|
1902
2032
|
const timeFormatSelect = document.querySelector(".time-format");
|
|
1903
2033
|
const handleFormatChange = () => {
|
|
1904
2034
|
if (timeFormatSelect) {
|
|
@@ -1923,8 +2053,8 @@ var SelectionTimeInputs = ({
|
|
|
1923
2053
|
onSelectionChange(selectionStart, value);
|
|
1924
2054
|
}
|
|
1925
2055
|
};
|
|
1926
|
-
return /* @__PURE__ */ (0,
|
|
1927
|
-
/* @__PURE__ */ (0,
|
|
2056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className, children: [
|
|
2057
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1928
2058
|
TimeInput,
|
|
1929
2059
|
{
|
|
1930
2060
|
id: "audio_start",
|
|
@@ -1935,7 +2065,7 @@ var SelectionTimeInputs = ({
|
|
|
1935
2065
|
onChange: handleStartChange
|
|
1936
2066
|
}
|
|
1937
2067
|
),
|
|
1938
|
-
/* @__PURE__ */ (0,
|
|
2068
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1939
2069
|
TimeInput,
|
|
1940
2070
|
{
|
|
1941
2071
|
id: "audio_end",
|
|
@@ -1950,14 +2080,14 @@ var SelectionTimeInputs = ({
|
|
|
1950
2080
|
};
|
|
1951
2081
|
|
|
1952
2082
|
// src/contexts/DevicePixelRatio.tsx
|
|
1953
|
-
var
|
|
1954
|
-
var
|
|
2083
|
+
var import_react10 = require("react");
|
|
2084
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1955
2085
|
function getScale() {
|
|
1956
2086
|
return window.devicePixelRatio;
|
|
1957
2087
|
}
|
|
1958
|
-
var DevicePixelRatioContext = (0,
|
|
2088
|
+
var DevicePixelRatioContext = (0, import_react10.createContext)(getScale());
|
|
1959
2089
|
var DevicePixelRatioProvider = ({ children }) => {
|
|
1960
|
-
const [scale, setScale] = (0,
|
|
2090
|
+
const [scale, setScale] = (0, import_react10.useState)(getScale());
|
|
1961
2091
|
matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
|
|
1962
2092
|
"change",
|
|
1963
2093
|
() => {
|
|
@@ -1965,13 +2095,13 @@ var DevicePixelRatioProvider = ({ children }) => {
|
|
|
1965
2095
|
},
|
|
1966
2096
|
{ once: true }
|
|
1967
2097
|
);
|
|
1968
|
-
return /* @__PURE__ */ (0,
|
|
2098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
|
|
1969
2099
|
};
|
|
1970
|
-
var useDevicePixelRatio = () => (0,
|
|
2100
|
+
var useDevicePixelRatio = () => (0, import_react10.useContext)(DevicePixelRatioContext);
|
|
1971
2101
|
|
|
1972
2102
|
// src/contexts/PlaylistInfo.tsx
|
|
1973
|
-
var
|
|
1974
|
-
var PlaylistInfoContext = (0,
|
|
2103
|
+
var import_react11 = require("react");
|
|
2104
|
+
var PlaylistInfoContext = (0, import_react11.createContext)({
|
|
1975
2105
|
sampleRate: 48e3,
|
|
1976
2106
|
samplesPerPixel: 1e3,
|
|
1977
2107
|
zoomLevels: [1e3, 1500, 2e3, 2500],
|
|
@@ -1985,22 +2115,22 @@ var PlaylistInfoContext = (0, import_react9.createContext)({
|
|
|
1985
2115
|
barWidth: 1,
|
|
1986
2116
|
barGap: 0
|
|
1987
2117
|
});
|
|
1988
|
-
var usePlaylistInfo = () => (0,
|
|
2118
|
+
var usePlaylistInfo = () => (0, import_react11.useContext)(PlaylistInfoContext);
|
|
1989
2119
|
|
|
1990
2120
|
// src/contexts/Theme.tsx
|
|
1991
|
-
var
|
|
2121
|
+
var import_react12 = require("react");
|
|
1992
2122
|
var import_styled_components19 = require("styled-components");
|
|
1993
|
-
var useTheme2 = () => (0,
|
|
2123
|
+
var useTheme2 = () => (0, import_react12.useContext)(import_styled_components19.ThemeContext);
|
|
1994
2124
|
|
|
1995
2125
|
// src/contexts/TrackControls.tsx
|
|
1996
|
-
var
|
|
1997
|
-
var
|
|
1998
|
-
var TrackControlsContext = (0,
|
|
1999
|
-
var useTrackControls = () => (0,
|
|
2126
|
+
var import_react13 = require("react");
|
|
2127
|
+
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);
|
|
2000
2130
|
|
|
2001
2131
|
// src/contexts/Playout.tsx
|
|
2002
|
-
var
|
|
2003
|
-
var
|
|
2132
|
+
var import_react14 = require("react");
|
|
2133
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2004
2134
|
var defaultProgress = 0;
|
|
2005
2135
|
var defaultIsPlaying = false;
|
|
2006
2136
|
var defaultSelectionStart = 0;
|
|
@@ -2011,8 +2141,8 @@ var defaultPlayout = {
|
|
|
2011
2141
|
selectionStart: defaultSelectionStart,
|
|
2012
2142
|
selectionEnd: defaultSelectionEnd
|
|
2013
2143
|
};
|
|
2014
|
-
var PlayoutStatusContext = (0,
|
|
2015
|
-
var PlayoutStatusUpdateContext = (0,
|
|
2144
|
+
var PlayoutStatusContext = (0, import_react14.createContext)(defaultPlayout);
|
|
2145
|
+
var PlayoutStatusUpdateContext = (0, import_react14.createContext)({
|
|
2016
2146
|
setIsPlaying: () => {
|
|
2017
2147
|
},
|
|
2018
2148
|
setProgress: () => {
|
|
@@ -2021,24 +2151,24 @@ var PlayoutStatusUpdateContext = (0, import_react12.createContext)({
|
|
|
2021
2151
|
}
|
|
2022
2152
|
});
|
|
2023
2153
|
var PlayoutProvider = ({ children }) => {
|
|
2024
|
-
const [isPlaying, setIsPlaying] = (0,
|
|
2025
|
-
const [progress, setProgress] = (0,
|
|
2026
|
-
const [selectionStart, setSelectionStart] = (0,
|
|
2027
|
-
const [selectionEnd, setSelectionEnd] = (0,
|
|
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);
|
|
2028
2158
|
const setSelection = (start, end) => {
|
|
2029
2159
|
setSelectionStart(start);
|
|
2030
2160
|
setSelectionEnd(end);
|
|
2031
2161
|
};
|
|
2032
|
-
return /* @__PURE__ */ (0,
|
|
2162
|
+
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 }) });
|
|
2033
2163
|
};
|
|
2034
|
-
var usePlayoutStatus = () => (0,
|
|
2035
|
-
var usePlayoutStatusUpdate = () => (0,
|
|
2164
|
+
var usePlayoutStatus = () => (0, import_react14.useContext)(PlayoutStatusContext);
|
|
2165
|
+
var usePlayoutStatusUpdate = () => (0, import_react14.useContext)(PlayoutStatusUpdateContext);
|
|
2036
2166
|
|
|
2037
2167
|
// src/components/SpectrogramChannel.tsx
|
|
2038
|
-
var
|
|
2168
|
+
var import_react15 = require("react");
|
|
2039
2169
|
var import_styled_components20 = __toESM(require("styled-components"));
|
|
2040
|
-
var
|
|
2041
|
-
var
|
|
2170
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2171
|
+
var LINEAR_FREQUENCY_SCALE = (f, minF, maxF) => (f - minF) / (maxF - minF);
|
|
2042
2172
|
var Wrapper3 = import_styled_components20.default.div.attrs((props) => ({
|
|
2043
2173
|
style: {
|
|
2044
2174
|
top: `${props.$waveHeight * props.$index}px`,
|
|
@@ -2054,11 +2184,13 @@ var Wrapper3 = import_styled_components20.default.div.attrs((props) => ({
|
|
|
2054
2184
|
var SpectrogramCanvas = import_styled_components20.default.canvas.attrs((props) => ({
|
|
2055
2185
|
style: {
|
|
2056
2186
|
width: `${props.$cssWidth}px`,
|
|
2057
|
-
height: `${props.$waveHeight}px
|
|
2187
|
+
height: `${props.$waveHeight}px`,
|
|
2188
|
+
left: `${props.$left}px`
|
|
2058
2189
|
}
|
|
2059
2190
|
}))`
|
|
2060
|
-
|
|
2061
|
-
|
|
2191
|
+
position: absolute;
|
|
2192
|
+
top: 0;
|
|
2193
|
+
/* Promote to own compositing layer for smoother scrolling */
|
|
2062
2194
|
will-change: transform;
|
|
2063
2195
|
image-rendering: pixelated;
|
|
2064
2196
|
image-rendering: crisp-edges;
|
|
@@ -2070,6 +2202,7 @@ function defaultGetColorMap() {
|
|
|
2070
2202
|
}
|
|
2071
2203
|
return lut;
|
|
2072
2204
|
}
|
|
2205
|
+
var DEFAULT_COLOR_LUT = defaultGetColorMap();
|
|
2073
2206
|
var SpectrogramChannel = ({
|
|
2074
2207
|
index,
|
|
2075
2208
|
channelIndex: channelIndexProp,
|
|
@@ -2087,11 +2220,30 @@ var SpectrogramChannel = ({
|
|
|
2087
2220
|
onCanvasesReady
|
|
2088
2221
|
}) => {
|
|
2089
2222
|
const channelIndex = channelIndexProp ?? index;
|
|
2090
|
-
const canvasesRef = (0,
|
|
2091
|
-
const registeredIdsRef = (0,
|
|
2092
|
-
const transferredCanvasesRef = (0,
|
|
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);
|
|
2093
2228
|
const isWorkerMode = !!(workerApi && clipId);
|
|
2094
|
-
const
|
|
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)(
|
|
2095
2247
|
(canvas) => {
|
|
2096
2248
|
if (canvas !== null) {
|
|
2097
2249
|
const idx = parseInt(canvas.dataset.index, 10);
|
|
@@ -2100,53 +2252,101 @@ var SpectrogramChannel = ({
|
|
|
2100
2252
|
},
|
|
2101
2253
|
[]
|
|
2102
2254
|
);
|
|
2103
|
-
|
|
2255
|
+
const lut = colorLUT ?? DEFAULT_COLOR_LUT;
|
|
2256
|
+
const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
|
|
2257
|
+
const scaleFn = frequencyScaleFn ?? LINEAR_FREQUENCY_SCALE;
|
|
2258
|
+
const hasCustomFrequencyScale = Boolean(frequencyScaleFn);
|
|
2259
|
+
(0, import_react15.useEffect)(() => {
|
|
2260
|
+
workerApiRef.current = workerApi;
|
|
2261
|
+
}, [workerApi]);
|
|
2262
|
+
(0, import_react15.useEffect)(() => {
|
|
2263
|
+
onCanvasesReadyRef.current = onCanvasesReady;
|
|
2264
|
+
}, [onCanvasesReady]);
|
|
2265
|
+
(0, import_react15.useEffect)(() => {
|
|
2104
2266
|
if (!isWorkerMode) return;
|
|
2105
|
-
const
|
|
2106
|
-
|
|
2267
|
+
const currentWorkerApi = workerApiRef.current;
|
|
2268
|
+
if (!currentWorkerApi || !clipId) return;
|
|
2107
2269
|
const canvases2 = canvasesRef.current;
|
|
2108
|
-
const
|
|
2109
|
-
const
|
|
2270
|
+
const newIds = [];
|
|
2271
|
+
const newWidths = [];
|
|
2110
2272
|
for (let i = 0; i < canvases2.length; i++) {
|
|
2111
2273
|
const canvas = canvases2[i];
|
|
2112
2274
|
if (!canvas) continue;
|
|
2113
2275
|
if (transferredCanvasesRef.current.has(canvas)) continue;
|
|
2114
|
-
const
|
|
2276
|
+
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
2277
|
+
const canvasId = `${clipId}-ch${channelIndex}-chunk${canvasIdx}`;
|
|
2278
|
+
let offscreen;
|
|
2115
2279
|
try {
|
|
2116
|
-
|
|
2117
|
-
workerApi.registerCanvas(canvasId, offscreen);
|
|
2118
|
-
transferredCanvasesRef.current.add(canvas);
|
|
2119
|
-
ids.push(canvasId);
|
|
2120
|
-
widths.push(Math.min(length - i * MAX_CANVAS_WIDTH2, MAX_CANVAS_WIDTH2));
|
|
2280
|
+
offscreen = canvas.transferControlToOffscreen();
|
|
2121
2281
|
} catch (err) {
|
|
2122
2282
|
console.warn(`[spectrogram] transferControlToOffscreen failed for ${canvasId}:`, err);
|
|
2123
2283
|
continue;
|
|
2124
2284
|
}
|
|
2285
|
+
transferredCanvasesRef.current.add(canvas);
|
|
2286
|
+
try {
|
|
2287
|
+
currentWorkerApi.registerCanvas(canvasId, offscreen);
|
|
2288
|
+
newIds.push(canvasId);
|
|
2289
|
+
newWidths.push(Math.min(length - canvasIdx * MAX_CANVAS_WIDTH, MAX_CANVAS_WIDTH));
|
|
2290
|
+
} catch (err) {
|
|
2291
|
+
console.warn(`[spectrogram] registerCanvas failed for ${canvasId}:`, err);
|
|
2292
|
+
continue;
|
|
2293
|
+
}
|
|
2125
2294
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2295
|
+
if (newIds.length > 0) {
|
|
2296
|
+
registeredIdsRef.current = [...registeredIdsRef.current, ...newIds];
|
|
2297
|
+
onCanvasesReadyRef.current?.(newIds, newWidths);
|
|
2129
2298
|
}
|
|
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);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
}
|
|
2323
|
+
registeredIdsRef.current = remaining;
|
|
2324
|
+
});
|
|
2325
|
+
(0, import_react15.useEffect)(() => {
|
|
2130
2326
|
return () => {
|
|
2327
|
+
const api = workerApiRef.current;
|
|
2328
|
+
if (!api) return;
|
|
2131
2329
|
for (const id of registeredIdsRef.current) {
|
|
2132
|
-
|
|
2330
|
+
try {
|
|
2331
|
+
api.unregisterCanvas(id);
|
|
2332
|
+
} catch (err) {
|
|
2333
|
+
console.warn(`[spectrogram] unregisterCanvas failed for ${id}:`, err);
|
|
2334
|
+
}
|
|
2133
2335
|
}
|
|
2134
2336
|
registeredIdsRef.current = [];
|
|
2135
2337
|
};
|
|
2136
|
-
}, [
|
|
2137
|
-
|
|
2138
|
-
const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
|
|
2139
|
-
const scaleFn = frequencyScaleFn ?? ((f, minF, maxF2) => (f - minF) / (maxF2 - minF));
|
|
2140
|
-
(0, import_react13.useLayoutEffect)(() => {
|
|
2338
|
+
}, []);
|
|
2339
|
+
(0, import_react15.useLayoutEffect)(() => {
|
|
2141
2340
|
if (isWorkerMode || !data) return;
|
|
2142
2341
|
const canvases2 = canvasesRef.current;
|
|
2143
2342
|
const { frequencyBinCount, frameCount, hopSize, sampleRate, gainDb, rangeDb: rawRangeDb } = data;
|
|
2144
2343
|
const rangeDb = rawRangeDb === 0 ? 1 : rawRangeDb;
|
|
2145
|
-
let globalPixelOffset = 0;
|
|
2146
2344
|
const binToFreq = (bin) => bin / frequencyBinCount * (sampleRate / 2);
|
|
2147
|
-
for (let
|
|
2148
|
-
const canvas = canvases2[
|
|
2345
|
+
for (let i = 0; i < canvases2.length; i++) {
|
|
2346
|
+
const canvas = canvases2[i];
|
|
2149
2347
|
if (!canvas) continue;
|
|
2348
|
+
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
2349
|
+
const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
|
|
2150
2350
|
const ctx = canvas.getContext("2d");
|
|
2151
2351
|
if (!ctx) continue;
|
|
2152
2352
|
const canvasWidth = canvas.width / devicePixelRatio;
|
|
@@ -2166,7 +2366,7 @@ var SpectrogramChannel = ({
|
|
|
2166
2366
|
for (let y = 0; y < canvasHeight; y++) {
|
|
2167
2367
|
const normalizedY = 1 - y / canvasHeight;
|
|
2168
2368
|
let bin = Math.floor(normalizedY * frequencyBinCount);
|
|
2169
|
-
if (
|
|
2369
|
+
if (hasCustomFrequencyScale) {
|
|
2170
2370
|
let lo = 0;
|
|
2171
2371
|
let hi = frequencyBinCount - 1;
|
|
2172
2372
|
while (lo < hi) {
|
|
@@ -2205,36 +2405,30 @@ var SpectrogramChannel = ({
|
|
|
2205
2405
|
ctx.imageSmoothingEnabled = false;
|
|
2206
2406
|
ctx.drawImage(tmpCanvas, 0, 0, canvas.width, canvas.height);
|
|
2207
2407
|
}
|
|
2208
|
-
globalPixelOffset += canvasWidth;
|
|
2209
2408
|
}
|
|
2210
|
-
}, [isWorkerMode, data, length, waveHeight, devicePixelRatio, samplesPerPixel, lut,
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
},
|
|
2227
|
-
`${length}-${canvasCount}`
|
|
2228
|
-
)
|
|
2409
|
+
}, [isWorkerMode, data, length, waveHeight, devicePixelRatio, samplesPerPixel, lut, minFrequency, maxF, scaleFn, hasCustomFrequencyScale, visibleChunkKey]);
|
|
2410
|
+
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, import_jsx_runtime20.jsx)(
|
|
2414
|
+
SpectrogramCanvas,
|
|
2415
|
+
{
|
|
2416
|
+
$cssWidth: currentWidth,
|
|
2417
|
+
$left: chunkLeft,
|
|
2418
|
+
width: currentWidth * devicePixelRatio,
|
|
2419
|
+
height: waveHeight * devicePixelRatio,
|
|
2420
|
+
$waveHeight: waveHeight,
|
|
2421
|
+
"data-index": i,
|
|
2422
|
+
ref: canvasRef
|
|
2423
|
+
},
|
|
2424
|
+
`${length}-${i}`
|
|
2229
2425
|
);
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
}
|
|
2233
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Wrapper3, { $index: index, $cssWidth: length, $waveHeight: waveHeight, children: canvases });
|
|
2426
|
+
});
|
|
2427
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Wrapper3, { $index: index, $cssWidth: length, $waveHeight: waveHeight, children: canvases });
|
|
2234
2428
|
};
|
|
2235
2429
|
|
|
2236
2430
|
// src/components/SmartChannel.tsx
|
|
2237
|
-
var
|
|
2431
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2238
2432
|
var SmartChannel = ({
|
|
2239
2433
|
isSelected,
|
|
2240
2434
|
transparentBackground,
|
|
@@ -2259,7 +2453,7 @@ var SmartChannel = ({
|
|
|
2259
2453
|
const drawMode = theme?.waveformDrawMode || "inverted";
|
|
2260
2454
|
const hasSpectrogram = spectrogramData || spectrogramWorkerApi;
|
|
2261
2455
|
if (renderMode === "spectrogram" && hasSpectrogram) {
|
|
2262
|
-
return /* @__PURE__ */ (0,
|
|
2456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2263
2457
|
SpectrogramChannel,
|
|
2264
2458
|
{
|
|
2265
2459
|
index: props.index,
|
|
@@ -2280,8 +2474,8 @@ var SmartChannel = ({
|
|
|
2280
2474
|
}
|
|
2281
2475
|
if (renderMode === "both" && hasSpectrogram) {
|
|
2282
2476
|
const halfHeight = Math.floor(waveHeight / 2);
|
|
2283
|
-
return /* @__PURE__ */ (0,
|
|
2284
|
-
/* @__PURE__ */ (0,
|
|
2477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
2478
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2285
2479
|
SpectrogramChannel,
|
|
2286
2480
|
{
|
|
2287
2481
|
index: props.index * 2,
|
|
@@ -2300,7 +2494,7 @@ var SmartChannel = ({
|
|
|
2300
2494
|
onCanvasesReady: spectrogramOnCanvasesReady
|
|
2301
2495
|
}
|
|
2302
2496
|
),
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { style: { position: "absolute", top: (props.index * 2 + 1) * halfHeight, width: props.length, height: halfHeight }, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2304
2498
|
Channel,
|
|
2305
2499
|
{
|
|
2306
2500
|
...props,
|
|
@@ -2317,7 +2511,7 @@ var SmartChannel = ({
|
|
|
2317
2511
|
) })
|
|
2318
2512
|
] });
|
|
2319
2513
|
}
|
|
2320
|
-
return /* @__PURE__ */ (0,
|
|
2514
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
2321
2515
|
Channel,
|
|
2322
2516
|
{
|
|
2323
2517
|
...props,
|
|
@@ -2334,9 +2528,9 @@ var SmartChannel = ({
|
|
|
2334
2528
|
};
|
|
2335
2529
|
|
|
2336
2530
|
// src/components/SpectrogramLabels.tsx
|
|
2337
|
-
var
|
|
2531
|
+
var import_react16 = require("react");
|
|
2338
2532
|
var import_styled_components21 = __toESM(require("styled-components"));
|
|
2339
|
-
var
|
|
2533
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2340
2534
|
var LABELS_WIDTH = 72;
|
|
2341
2535
|
var LabelsStickyWrapper = import_styled_components21.default.div`
|
|
2342
2536
|
position: sticky;
|
|
@@ -2386,12 +2580,12 @@ var SpectrogramLabels = ({
|
|
|
2386
2580
|
renderMode = "spectrogram",
|
|
2387
2581
|
hasClipHeaders = false
|
|
2388
2582
|
}) => {
|
|
2389
|
-
const canvasRef = (0,
|
|
2583
|
+
const canvasRef = (0, import_react16.useRef)(null);
|
|
2390
2584
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2391
2585
|
const spectrogramHeight = renderMode === "both" ? Math.floor(waveHeight / 2) : waveHeight;
|
|
2392
2586
|
const totalHeight = numChannels * waveHeight;
|
|
2393
2587
|
const clipHeaderOffset = hasClipHeaders ? 22 : 0;
|
|
2394
|
-
(0,
|
|
2588
|
+
(0, import_react16.useLayoutEffect)(() => {
|
|
2395
2589
|
const canvas = canvasRef.current;
|
|
2396
2590
|
if (!canvas) return;
|
|
2397
2591
|
const ctx = canvas.getContext("2d");
|
|
@@ -2418,7 +2612,7 @@ var SpectrogramLabels = ({
|
|
|
2418
2612
|
}
|
|
2419
2613
|
}
|
|
2420
2614
|
}, [waveHeight, numChannels, frequencyScaleFn, minFrequency, maxFrequency, labelsColor, labelsBackground, devicePixelRatio, spectrogramHeight, clipHeaderOffset]);
|
|
2421
|
-
return /* @__PURE__ */ (0,
|
|
2615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(LabelsStickyWrapper, { $height: totalHeight + clipHeaderOffset, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2422
2616
|
"canvas",
|
|
2423
2617
|
{
|
|
2424
2618
|
ref: canvasRef,
|
|
@@ -2434,10 +2628,10 @@ var SpectrogramLabels = ({
|
|
|
2434
2628
|
};
|
|
2435
2629
|
|
|
2436
2630
|
// src/components/SmartScale.tsx
|
|
2437
|
-
var
|
|
2631
|
+
var import_react18 = require("react");
|
|
2438
2632
|
|
|
2439
2633
|
// src/components/TimeScale.tsx
|
|
2440
|
-
var
|
|
2634
|
+
var import_react17 = __toESM(require("react"));
|
|
2441
2635
|
var import_styled_components22 = __toESM(require("styled-components"));
|
|
2442
2636
|
|
|
2443
2637
|
// src/utils/conversions.ts
|
|
@@ -2461,7 +2655,7 @@ function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
|
|
|
2461
2655
|
}
|
|
2462
2656
|
|
|
2463
2657
|
// src/components/TimeScale.tsx
|
|
2464
|
-
var
|
|
2658
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2465
2659
|
function formatTime2(milliseconds) {
|
|
2466
2660
|
const seconds = Math.floor(milliseconds / 1e3);
|
|
2467
2661
|
const s = seconds % 60;
|
|
@@ -2480,16 +2674,17 @@ var PlaylistTimeScaleScroll = import_styled_components22.default.div.attrs((prop
|
|
|
2480
2674
|
border-bottom: 1px solid ${(props) => props.theme.timeColor};
|
|
2481
2675
|
box-sizing: border-box;
|
|
2482
2676
|
`;
|
|
2483
|
-
var
|
|
2677
|
+
var TimeTickChunk = import_styled_components22.default.canvas.attrs((props) => ({
|
|
2484
2678
|
style: {
|
|
2485
2679
|
width: `${props.$cssWidth}px`,
|
|
2486
|
-
height: `${props.$timeScaleHeight}px
|
|
2680
|
+
height: `${props.$timeScaleHeight}px`,
|
|
2681
|
+
left: `${props.$left}px`
|
|
2487
2682
|
}
|
|
2488
2683
|
}))`
|
|
2489
2684
|
position: absolute;
|
|
2490
|
-
left: 0;
|
|
2491
|
-
right: 0;
|
|
2492
2685
|
bottom: 0;
|
|
2686
|
+
/* Promote to own compositing layer for smoother scrolling */
|
|
2687
|
+
will-change: transform;
|
|
2493
2688
|
`;
|
|
2494
2689
|
var TimeStamp = import_styled_components22.default.div.attrs((props) => ({
|
|
2495
2690
|
style: {
|
|
@@ -2511,78 +2706,120 @@ var TimeScale = (props) => {
|
|
|
2511
2706
|
secondStep,
|
|
2512
2707
|
renderTimestamp
|
|
2513
2708
|
} = props;
|
|
2514
|
-
const
|
|
2515
|
-
const timeMarkers = [];
|
|
2516
|
-
const canvasRef = (0, import_react15.useRef)(null);
|
|
2709
|
+
const canvasRefsMap = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
|
|
2517
2710
|
const {
|
|
2518
2711
|
sampleRate,
|
|
2519
2712
|
samplesPerPixel,
|
|
2520
2713
|
timeScaleHeight,
|
|
2521
2714
|
controls: { show: showControls, width: controlWidth }
|
|
2522
|
-
} = (0,
|
|
2715
|
+
} = (0, import_react17.useContext)(PlaylistInfoContext);
|
|
2523
2716
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2524
|
-
(0,
|
|
2525
|
-
if (
|
|
2526
|
-
const
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
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)(() => {
|
|
2724
|
+
const nextCanvasInfo = /* @__PURE__ */ new Map();
|
|
2725
|
+
const nextMarkers = [];
|
|
2726
|
+
const nextWidthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);
|
|
2727
|
+
const pixPerSec = sampleRate / samplesPerPixel;
|
|
2728
|
+
let counter = 0;
|
|
2729
|
+
for (let i = 0; i < nextWidthX; i += pixPerSec * secondStep / 1e3) {
|
|
2730
|
+
const pix = Math.floor(i);
|
|
2731
|
+
if (counter % marker === 0) {
|
|
2732
|
+
const timeMs = counter;
|
|
2733
|
+
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);
|
|
2735
|
+
nextMarkers.push({ pix, element });
|
|
2736
|
+
nextCanvasInfo.set(pix, timeScaleHeight);
|
|
2737
|
+
} else if (counter % bigStep === 0) {
|
|
2738
|
+
nextCanvasInfo.set(pix, Math.floor(timeScaleHeight / 2));
|
|
2739
|
+
} else if (counter % secondStep === 0) {
|
|
2740
|
+
nextCanvasInfo.set(pix, Math.floor(timeScaleHeight / 5));
|
|
2741
|
+
}
|
|
2742
|
+
counter += secondStep;
|
|
2743
|
+
}
|
|
2744
|
+
return {
|
|
2745
|
+
widthX: nextWidthX,
|
|
2746
|
+
canvasInfo: nextCanvasInfo,
|
|
2747
|
+
timeMarkersWithPositions: nextMarkers
|
|
2748
|
+
};
|
|
2749
|
+
}, [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;
|
|
2537
2760
|
}
|
|
2538
2761
|
}
|
|
2762
|
+
indices.push(i);
|
|
2539
2763
|
}
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2764
|
+
return indices.join(",");
|
|
2765
|
+
});
|
|
2766
|
+
const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
|
|
2767
|
+
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, import_jsx_runtime23.jsx)(
|
|
2771
|
+
TimeTickChunk,
|
|
2772
|
+
{
|
|
2773
|
+
$cssWidth: chunkWidth,
|
|
2774
|
+
$left: chunkLeft,
|
|
2775
|
+
$timeScaleHeight: timeScaleHeight,
|
|
2776
|
+
width: chunkWidth * devicePixelRatio,
|
|
2777
|
+
height: timeScaleHeight * devicePixelRatio,
|
|
2778
|
+
"data-index": i,
|
|
2779
|
+
ref: canvasRefCallback
|
|
2780
|
+
},
|
|
2781
|
+
`timescale-${i}`
|
|
2782
|
+
);
|
|
2783
|
+
});
|
|
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;
|
|
2786
|
+
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
|
+
}
|
|
2565
2793
|
}
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2794
|
+
});
|
|
2795
|
+
(0, import_react17.useLayoutEffect)(() => {
|
|
2796
|
+
for (const [chunkIdx, canvas] of canvasRefsMap.current.entries()) {
|
|
2797
|
+
const ctx = canvas.getContext("2d");
|
|
2798
|
+
if (!ctx) continue;
|
|
2799
|
+
const chunkLeft = chunkIdx * MAX_CANVAS_WIDTH;
|
|
2800
|
+
const chunkWidth = canvas.width / devicePixelRatio;
|
|
2801
|
+
ctx.resetTransform();
|
|
2802
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2803
|
+
ctx.imageSmoothingEnabled = false;
|
|
2804
|
+
ctx.fillStyle = timeColor;
|
|
2805
|
+
ctx.scale(devicePixelRatio, devicePixelRatio);
|
|
2806
|
+
for (const [pixLeft, scaleHeight] of canvasInfo.entries()) {
|
|
2807
|
+
if (pixLeft < chunkLeft || pixLeft >= chunkLeft + chunkWidth) continue;
|
|
2808
|
+
const localX = pixLeft - chunkLeft;
|
|
2809
|
+
const scaleY = timeScaleHeight - scaleHeight;
|
|
2810
|
+
ctx.fillRect(localX, scaleY, 1, scaleHeight);
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2813
|
+
}, [duration, devicePixelRatio, timeColor, timeScaleHeight, canvasInfo, visibleChunkKey]);
|
|
2814
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
2569
2815
|
PlaylistTimeScaleScroll,
|
|
2570
2816
|
{
|
|
2571
2817
|
$cssWidth: widthX,
|
|
2572
2818
|
$controlWidth: showControls ? controlWidth : 0,
|
|
2573
2819
|
$timeScaleHeight: timeScaleHeight,
|
|
2574
2820
|
children: [
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
TimeTicks,
|
|
2578
|
-
{
|
|
2579
|
-
$cssWidth: widthX,
|
|
2580
|
-
$timeScaleHeight: timeScaleHeight,
|
|
2581
|
-
width: widthX * devicePixelRatio,
|
|
2582
|
-
height: timeScaleHeight * devicePixelRatio,
|
|
2583
|
-
ref: canvasRef
|
|
2584
|
-
}
|
|
2585
|
-
)
|
|
2821
|
+
visibleMarkers,
|
|
2822
|
+
visibleChunks
|
|
2586
2823
|
]
|
|
2587
2824
|
}
|
|
2588
2825
|
);
|
|
@@ -2590,7 +2827,7 @@ var TimeScale = (props) => {
|
|
|
2590
2827
|
var StyledTimeScale = (0, import_styled_components22.withTheme)(TimeScale);
|
|
2591
2828
|
|
|
2592
2829
|
// src/components/SmartScale.tsx
|
|
2593
|
-
var
|
|
2830
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2594
2831
|
var timeinfo = /* @__PURE__ */ new Map([
|
|
2595
2832
|
[
|
|
2596
2833
|
700,
|
|
@@ -2664,9 +2901,9 @@ function getScaleInfo(samplesPerPixel) {
|
|
|
2664
2901
|
return config;
|
|
2665
2902
|
}
|
|
2666
2903
|
var SmartScale = ({ renderTimestamp }) => {
|
|
2667
|
-
const { samplesPerPixel, duration } = (0,
|
|
2904
|
+
const { samplesPerPixel, duration } = (0, import_react18.useContext)(PlaylistInfoContext);
|
|
2668
2905
|
let config = getScaleInfo(samplesPerPixel);
|
|
2669
|
-
return /* @__PURE__ */ (0,
|
|
2906
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2670
2907
|
StyledTimeScale,
|
|
2671
2908
|
{
|
|
2672
2909
|
marker: config.marker,
|
|
@@ -2680,7 +2917,7 @@ var SmartScale = ({ renderTimestamp }) => {
|
|
|
2680
2917
|
|
|
2681
2918
|
// src/components/TimeFormatSelect.tsx
|
|
2682
2919
|
var import_styled_components23 = __toESM(require("styled-components"));
|
|
2683
|
-
var
|
|
2920
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2684
2921
|
var SelectWrapper = import_styled_components23.default.div`
|
|
2685
2922
|
display: inline-flex;
|
|
2686
2923
|
align-items: center;
|
|
@@ -2703,7 +2940,7 @@ var TimeFormatSelect = ({
|
|
|
2703
2940
|
const handleChange = (e) => {
|
|
2704
2941
|
onChange(e.target.value);
|
|
2705
2942
|
};
|
|
2706
|
-
return /* @__PURE__ */ (0,
|
|
2943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SelectWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2707
2944
|
BaseSelect,
|
|
2708
2945
|
{
|
|
2709
2946
|
className: "time-format",
|
|
@@ -2711,14 +2948,14 @@ var TimeFormatSelect = ({
|
|
|
2711
2948
|
onChange: handleChange,
|
|
2712
2949
|
disabled,
|
|
2713
2950
|
"aria-label": "Time format selection",
|
|
2714
|
-
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0,
|
|
2951
|
+
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("option", { value: option.value, children: option.label }, option.value))
|
|
2715
2952
|
}
|
|
2716
2953
|
) });
|
|
2717
2954
|
};
|
|
2718
2955
|
|
|
2719
2956
|
// src/components/Track.tsx
|
|
2720
2957
|
var import_styled_components24 = __toESM(require("styled-components"));
|
|
2721
|
-
var
|
|
2958
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2722
2959
|
var Container = import_styled_components24.default.div.attrs((props) => ({
|
|
2723
2960
|
style: {
|
|
2724
2961
|
height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`
|
|
@@ -2773,7 +3010,7 @@ var Track = ({
|
|
|
2773
3010
|
controls: { show, width: controlWidth }
|
|
2774
3011
|
} = usePlaylistInfo();
|
|
2775
3012
|
const controls = useTrackControls();
|
|
2776
|
-
return /* @__PURE__ */ (0,
|
|
3013
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
2777
3014
|
Container,
|
|
2778
3015
|
{
|
|
2779
3016
|
$numChannels: numChannels,
|
|
@@ -2784,7 +3021,7 @@ var Track = ({
|
|
|
2784
3021
|
$hasClipHeaders: hasClipHeaders,
|
|
2785
3022
|
$isSelected: isSelected,
|
|
2786
3023
|
children: [
|
|
2787
|
-
/* @__PURE__ */ (0,
|
|
3024
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2788
3025
|
ControlsWrapper,
|
|
2789
3026
|
{
|
|
2790
3027
|
$controlWidth: show ? controlWidth : 0,
|
|
@@ -2792,7 +3029,7 @@ var Track = ({
|
|
|
2792
3029
|
children: controls
|
|
2793
3030
|
}
|
|
2794
3031
|
),
|
|
2795
|
-
/* @__PURE__ */ (0,
|
|
3032
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
2796
3033
|
ChannelContainer,
|
|
2797
3034
|
{
|
|
2798
3035
|
$controlWidth: show ? controlWidth : 0,
|
|
@@ -2899,8 +3136,8 @@ var ButtonGroup = import_styled_components26.default.div`
|
|
|
2899
3136
|
|
|
2900
3137
|
// src/components/TrackControls/CloseButton.tsx
|
|
2901
3138
|
var import_styled_components27 = __toESM(require("styled-components"));
|
|
2902
|
-
var
|
|
2903
|
-
var
|
|
3139
|
+
var import_react19 = require("@phosphor-icons/react");
|
|
3140
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2904
3141
|
var StyledCloseButton = import_styled_components27.default.button`
|
|
2905
3142
|
position: absolute;
|
|
2906
3143
|
left: 0;
|
|
@@ -2925,7 +3162,7 @@ var StyledCloseButton = import_styled_components27.default.button`
|
|
|
2925
3162
|
var CloseButton = ({
|
|
2926
3163
|
onClick,
|
|
2927
3164
|
title = "Remove track"
|
|
2928
|
-
}) => /* @__PURE__ */ (0,
|
|
3165
|
+
}) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StyledCloseButton, { onClick, title, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react19.X, { size: 12, weight: "bold" }) });
|
|
2929
3166
|
|
|
2930
3167
|
// src/components/TrackControls/Controls.tsx
|
|
2931
3168
|
var import_styled_components28 = __toESM(require("styled-components"));
|
|
@@ -2960,24 +3197,24 @@ var Header = import_styled_components29.default.header`
|
|
|
2960
3197
|
`;
|
|
2961
3198
|
|
|
2962
3199
|
// src/components/TrackControls/VolumeDownIcon.tsx
|
|
2963
|
-
var
|
|
2964
|
-
var
|
|
2965
|
-
var VolumeDownIcon = (props) => /* @__PURE__ */ (0,
|
|
3200
|
+
var import_react20 = require("@phosphor-icons/react");
|
|
3201
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3202
|
+
var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_react20.SpeakerLowIcon, { weight: "light", ...props });
|
|
2966
3203
|
|
|
2967
3204
|
// src/components/TrackControls/VolumeUpIcon.tsx
|
|
2968
|
-
var
|
|
2969
|
-
var
|
|
2970
|
-
var VolumeUpIcon = (props) => /* @__PURE__ */ (0,
|
|
3205
|
+
var import_react21 = require("@phosphor-icons/react");
|
|
3206
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
3207
|
+
var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_react21.SpeakerHighIcon, { weight: "light", ...props });
|
|
2971
3208
|
|
|
2972
3209
|
// src/components/TrackControls/TrashIcon.tsx
|
|
2973
|
-
var
|
|
2974
|
-
var
|
|
2975
|
-
var TrashIcon = (props) => /* @__PURE__ */ (0,
|
|
3210
|
+
var import_react22 = require("@phosphor-icons/react");
|
|
3211
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
3212
|
+
var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react22.TrashIcon, { weight: "light", ...props });
|
|
2976
3213
|
|
|
2977
3214
|
// src/components/TrackControls/DotsIcon.tsx
|
|
2978
|
-
var
|
|
2979
|
-
var
|
|
2980
|
-
var DotsIcon = (props) => /* @__PURE__ */ (0,
|
|
3215
|
+
var import_react23 = require("@phosphor-icons/react");
|
|
3216
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
3217
|
+
var DotsIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react23.DotsThreeIcon, { weight: "bold", ...props });
|
|
2981
3218
|
|
|
2982
3219
|
// src/components/TrackControls/Slider.tsx
|
|
2983
3220
|
var import_styled_components30 = __toESM(require("styled-components"));
|
|
@@ -3045,10 +3282,10 @@ var SliderWrapper = import_styled_components31.default.label`
|
|
|
3045
3282
|
`;
|
|
3046
3283
|
|
|
3047
3284
|
// src/components/TrackMenu.tsx
|
|
3048
|
-
var
|
|
3285
|
+
var import_react24 = __toESM(require("react"));
|
|
3049
3286
|
var import_react_dom = require("react-dom");
|
|
3050
3287
|
var import_styled_components32 = __toESM(require("styled-components"));
|
|
3051
|
-
var
|
|
3288
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
3052
3289
|
var MenuContainer = import_styled_components32.default.div`
|
|
3053
3290
|
position: relative;
|
|
3054
3291
|
display: inline-block;
|
|
@@ -3089,13 +3326,13 @@ var Divider = import_styled_components32.default.hr`
|
|
|
3089
3326
|
var TrackMenu = ({
|
|
3090
3327
|
items: itemsProp
|
|
3091
3328
|
}) => {
|
|
3092
|
-
const [open, setOpen] = (0,
|
|
3329
|
+
const [open, setOpen] = (0, import_react24.useState)(false);
|
|
3093
3330
|
const close = () => setOpen(false);
|
|
3094
3331
|
const items = typeof itemsProp === "function" ? itemsProp(close) : itemsProp;
|
|
3095
|
-
const [dropdownPos, setDropdownPos] = (0,
|
|
3096
|
-
const buttonRef = (0,
|
|
3097
|
-
const dropdownRef = (0,
|
|
3098
|
-
(0,
|
|
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)(() => {
|
|
3099
3336
|
if (open && buttonRef.current) {
|
|
3100
3337
|
const rect = buttonRef.current.getBoundingClientRect();
|
|
3101
3338
|
setDropdownPos({
|
|
@@ -3104,7 +3341,7 @@ var TrackMenu = ({
|
|
|
3104
3341
|
});
|
|
3105
3342
|
}
|
|
3106
3343
|
}, [open]);
|
|
3107
|
-
(0,
|
|
3344
|
+
(0, import_react24.useEffect)(() => {
|
|
3108
3345
|
if (!open) return;
|
|
3109
3346
|
const handleClick = (e) => {
|
|
3110
3347
|
const target = e.target;
|
|
@@ -3115,8 +3352,8 @@ var TrackMenu = ({
|
|
|
3115
3352
|
document.addEventListener("mousedown", handleClick);
|
|
3116
3353
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
3117
3354
|
}, [open]);
|
|
3118
|
-
return /* @__PURE__ */ (0,
|
|
3119
|
-
/* @__PURE__ */ (0,
|
|
3355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(MenuContainer, { children: [
|
|
3356
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
3120
3357
|
MenuButton,
|
|
3121
3358
|
{
|
|
3122
3359
|
ref: buttonRef,
|
|
@@ -3127,19 +3364,19 @@ var TrackMenu = ({
|
|
|
3127
3364
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3128
3365
|
title: "Track menu",
|
|
3129
3366
|
"aria-label": "Track menu",
|
|
3130
|
-
children: /* @__PURE__ */ (0,
|
|
3367
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(DotsIcon, { size: 16 })
|
|
3131
3368
|
}
|
|
3132
3369
|
),
|
|
3133
3370
|
open && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
|
|
3134
|
-
/* @__PURE__ */ (0,
|
|
3371
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
3135
3372
|
Dropdown,
|
|
3136
3373
|
{
|
|
3137
3374
|
ref: dropdownRef,
|
|
3138
3375
|
$top: dropdownPos.top,
|
|
3139
3376
|
$left: dropdownPos.left,
|
|
3140
3377
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3141
|
-
children: items.map((item, index) => /* @__PURE__ */ (0,
|
|
3142
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
3378
|
+
children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_react24.default.Fragment, { children: [
|
|
3379
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Divider, {}),
|
|
3143
3380
|
item.content
|
|
3144
3381
|
] }, item.id))
|
|
3145
3382
|
}
|
|
@@ -3180,6 +3417,7 @@ var TrackMenu = ({
|
|
|
3180
3417
|
InlineLabel,
|
|
3181
3418
|
LoopRegion,
|
|
3182
3419
|
LoopRegionMarkers,
|
|
3420
|
+
MAX_CANVAS_WIDTH,
|
|
3183
3421
|
MasterVolumeControl,
|
|
3184
3422
|
Playhead,
|
|
3185
3423
|
PlayheadWithMarker,
|
|
@@ -3188,6 +3426,7 @@ var TrackMenu = ({
|
|
|
3188
3426
|
PlaylistInfoContext,
|
|
3189
3427
|
PlayoutProvider,
|
|
3190
3428
|
ScreenReaderOnly,
|
|
3429
|
+
ScrollViewportProvider,
|
|
3191
3430
|
Selection,
|
|
3192
3431
|
SelectionTimeInputs,
|
|
3193
3432
|
Slider,
|
|
@@ -3223,6 +3462,8 @@ var TrackMenu = ({
|
|
|
3223
3462
|
usePlaylistInfo,
|
|
3224
3463
|
usePlayoutStatus,
|
|
3225
3464
|
usePlayoutStatusUpdate,
|
|
3465
|
+
useScrollViewport,
|
|
3466
|
+
useScrollViewportSelector,
|
|
3226
3467
|
useTheme,
|
|
3227
3468
|
useTrackControls,
|
|
3228
3469
|
waveformColorToCss
|