@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.mjs
CHANGED
|
@@ -327,7 +327,7 @@ var AutomaticScrollCheckbox = ({
|
|
|
327
327
|
};
|
|
328
328
|
|
|
329
329
|
// src/components/Channel.tsx
|
|
330
|
-
import { useLayoutEffect, useCallback, useRef } from "react";
|
|
330
|
+
import { useLayoutEffect, useEffect as useEffect2, useCallback as useCallback2, useRef as useRef2 } from "react";
|
|
331
331
|
import styled9 from "styled-components";
|
|
332
332
|
|
|
333
333
|
// src/wfpl-theme.ts
|
|
@@ -487,9 +487,112 @@ var darkTheme = {
|
|
|
487
487
|
fontSizeSmall: "12px"
|
|
488
488
|
};
|
|
489
489
|
|
|
490
|
-
// src/
|
|
490
|
+
// src/contexts/ScrollViewport.tsx
|
|
491
|
+
import {
|
|
492
|
+
createContext,
|
|
493
|
+
useContext,
|
|
494
|
+
useEffect,
|
|
495
|
+
useCallback,
|
|
496
|
+
useRef,
|
|
497
|
+
useSyncExternalStore
|
|
498
|
+
} from "react";
|
|
491
499
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
500
|
+
var ViewportStore = class {
|
|
501
|
+
constructor() {
|
|
502
|
+
this._state = null;
|
|
503
|
+
this._listeners = /* @__PURE__ */ new Set();
|
|
504
|
+
this.subscribe = (callback) => {
|
|
505
|
+
this._listeners.add(callback);
|
|
506
|
+
return () => this._listeners.delete(callback);
|
|
507
|
+
};
|
|
508
|
+
this.getSnapshot = () => this._state;
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* Update viewport state. Applies a 100px scroll threshold to skip updates
|
|
512
|
+
* that don't affect chunk visibility (1000px chunks with 1.5× overscan buffer).
|
|
513
|
+
* Only notifies listeners when the state actually changes.
|
|
514
|
+
*/
|
|
515
|
+
update(scrollLeft, containerWidth) {
|
|
516
|
+
const buffer = containerWidth * 1.5;
|
|
517
|
+
const visibleStart = Math.max(0, scrollLeft - buffer);
|
|
518
|
+
const visibleEnd = scrollLeft + containerWidth + buffer;
|
|
519
|
+
if (this._state && this._state.containerWidth === containerWidth && Math.abs(this._state.scrollLeft - scrollLeft) < 100) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
this._state = { scrollLeft, containerWidth, visibleStart, visibleEnd };
|
|
523
|
+
for (const listener of this._listeners) {
|
|
524
|
+
listener();
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
var ViewportStoreContext = createContext(null);
|
|
529
|
+
var EMPTY_SUBSCRIBE = () => () => {
|
|
530
|
+
};
|
|
531
|
+
var NULL_SNAPSHOT = () => null;
|
|
532
|
+
var ScrollViewportProvider = ({
|
|
533
|
+
containerRef,
|
|
534
|
+
children
|
|
535
|
+
}) => {
|
|
536
|
+
const storeRef = useRef(null);
|
|
537
|
+
if (storeRef.current === null) {
|
|
538
|
+
storeRef.current = new ViewportStore();
|
|
539
|
+
}
|
|
540
|
+
const store = storeRef.current;
|
|
541
|
+
const rafIdRef = useRef(null);
|
|
542
|
+
const measure = useCallback(() => {
|
|
543
|
+
const el = containerRef.current;
|
|
544
|
+
if (!el) return;
|
|
545
|
+
store.update(el.scrollLeft, el.clientWidth);
|
|
546
|
+
}, [containerRef, store]);
|
|
547
|
+
const scheduleUpdate = useCallback(() => {
|
|
548
|
+
if (rafIdRef.current !== null) return;
|
|
549
|
+
rafIdRef.current = requestAnimationFrame(() => {
|
|
550
|
+
rafIdRef.current = null;
|
|
551
|
+
measure();
|
|
552
|
+
});
|
|
553
|
+
}, [measure]);
|
|
554
|
+
useEffect(() => {
|
|
555
|
+
const el = containerRef.current;
|
|
556
|
+
if (!el) return;
|
|
557
|
+
measure();
|
|
558
|
+
el.addEventListener("scroll", scheduleUpdate, { passive: true });
|
|
559
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
560
|
+
scheduleUpdate();
|
|
561
|
+
});
|
|
562
|
+
resizeObserver.observe(el);
|
|
563
|
+
return () => {
|
|
564
|
+
el.removeEventListener("scroll", scheduleUpdate);
|
|
565
|
+
resizeObserver.disconnect();
|
|
566
|
+
if (rafIdRef.current !== null) {
|
|
567
|
+
cancelAnimationFrame(rafIdRef.current);
|
|
568
|
+
rafIdRef.current = null;
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
}, [containerRef, measure, scheduleUpdate]);
|
|
572
|
+
return /* @__PURE__ */ jsx3(ViewportStoreContext.Provider, { value: store, children });
|
|
573
|
+
};
|
|
574
|
+
var useScrollViewport = () => {
|
|
575
|
+
const store = useContext(ViewportStoreContext);
|
|
576
|
+
return useSyncExternalStore(
|
|
577
|
+
store ? store.subscribe : EMPTY_SUBSCRIBE,
|
|
578
|
+
store ? store.getSnapshot : NULL_SNAPSHOT,
|
|
579
|
+
NULL_SNAPSHOT
|
|
580
|
+
);
|
|
581
|
+
};
|
|
582
|
+
function useScrollViewportSelector(selector) {
|
|
583
|
+
const store = useContext(ViewportStoreContext);
|
|
584
|
+
return useSyncExternalStore(
|
|
585
|
+
store ? store.subscribe : EMPTY_SUBSCRIBE,
|
|
586
|
+
() => selector(store ? store.getSnapshot() : null),
|
|
587
|
+
() => selector(null)
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// src/constants.ts
|
|
492
592
|
var MAX_CANVAS_WIDTH = 1e3;
|
|
593
|
+
|
|
594
|
+
// src/components/Channel.tsx
|
|
595
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
493
596
|
function createCanvasFillStyle(ctx, color, width, height) {
|
|
494
597
|
if (!isWaveformGradient(color)) {
|
|
495
598
|
return color;
|
|
@@ -508,11 +611,12 @@ function createCanvasFillStyle(ctx, color, width, height) {
|
|
|
508
611
|
var Waveform = styled9.canvas.attrs((props) => ({
|
|
509
612
|
style: {
|
|
510
613
|
width: `${props.$cssWidth}px`,
|
|
511
|
-
height: `${props.$waveHeight}px
|
|
614
|
+
height: `${props.$waveHeight}px`,
|
|
615
|
+
left: `${props.$left}px`
|
|
512
616
|
}
|
|
513
617
|
}))`
|
|
514
|
-
|
|
515
|
-
|
|
618
|
+
position: absolute;
|
|
619
|
+
top: 0;
|
|
516
620
|
/* Promote to own compositing layer for smoother scrolling */
|
|
517
621
|
will-change: transform;
|
|
518
622
|
/* Disable image rendering interpolation */
|
|
@@ -548,8 +652,25 @@ var Channel = (props) => {
|
|
|
548
652
|
transparentBackground = false,
|
|
549
653
|
drawMode = "inverted"
|
|
550
654
|
} = props;
|
|
551
|
-
const canvasesRef =
|
|
552
|
-
const
|
|
655
|
+
const canvasesRef = useRef2([]);
|
|
656
|
+
const visibleChunkKey = useScrollViewportSelector((viewport) => {
|
|
657
|
+
const totalChunks = Math.ceil(length / MAX_CANVAS_WIDTH);
|
|
658
|
+
const indices = [];
|
|
659
|
+
for (let i = 0; i < totalChunks; i++) {
|
|
660
|
+
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
661
|
+
const chunkWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
|
|
662
|
+
if (viewport) {
|
|
663
|
+
const chunkEnd = chunkLeft + chunkWidth;
|
|
664
|
+
if (chunkEnd <= viewport.visibleStart || chunkLeft >= viewport.visibleEnd) {
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
indices.push(i);
|
|
669
|
+
}
|
|
670
|
+
return indices.join(",");
|
|
671
|
+
});
|
|
672
|
+
const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
|
|
673
|
+
const canvasRef = useCallback2(
|
|
553
674
|
(canvas) => {
|
|
554
675
|
if (canvas !== null) {
|
|
555
676
|
const index2 = parseInt(canvas.dataset.index, 10);
|
|
@@ -558,12 +679,22 @@ var Channel = (props) => {
|
|
|
558
679
|
},
|
|
559
680
|
[]
|
|
560
681
|
);
|
|
682
|
+
useEffect2(() => {
|
|
683
|
+
const canvases = canvasesRef.current;
|
|
684
|
+
for (let i = canvases.length - 1; i >= 0; i--) {
|
|
685
|
+
if (canvases[i] && !canvases[i].isConnected) {
|
|
686
|
+
delete canvases[i];
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
});
|
|
561
690
|
useLayoutEffect(() => {
|
|
562
691
|
const canvases = canvasesRef.current;
|
|
563
692
|
const step = barWidth + barGap;
|
|
564
|
-
let globalPixelOffset = 0;
|
|
565
693
|
for (let i = 0; i < canvases.length; i++) {
|
|
566
694
|
const canvas = canvases[i];
|
|
695
|
+
if (!canvas) continue;
|
|
696
|
+
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
697
|
+
const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
|
|
567
698
|
const ctx = canvas.getContext("2d");
|
|
568
699
|
const h2 = Math.floor(waveHeight / 2);
|
|
569
700
|
const maxValue = 2 ** (bits - 1);
|
|
@@ -606,7 +737,6 @@ var Channel = (props) => {
|
|
|
606
737
|
}
|
|
607
738
|
}
|
|
608
739
|
}
|
|
609
|
-
globalPixelOffset += canvas.width / devicePixelRatio;
|
|
610
740
|
}
|
|
611
741
|
}, [
|
|
612
742
|
data,
|
|
@@ -618,32 +748,29 @@ var Channel = (props) => {
|
|
|
618
748
|
length,
|
|
619
749
|
barWidth,
|
|
620
750
|
barGap,
|
|
621
|
-
drawMode
|
|
751
|
+
drawMode,
|
|
752
|
+
visibleChunkKey
|
|
622
753
|
]);
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
const currentWidth = Math.min(totalWidth, MAX_CANVAS_WIDTH);
|
|
628
|
-
const waveform = /* @__PURE__ */ jsx3(
|
|
754
|
+
const waveforms = visibleChunkIndices.map((i) => {
|
|
755
|
+
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
756
|
+
const currentWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
|
|
757
|
+
return /* @__PURE__ */ jsx4(
|
|
629
758
|
Waveform,
|
|
630
759
|
{
|
|
631
760
|
$cssWidth: currentWidth,
|
|
761
|
+
$left: chunkLeft,
|
|
632
762
|
width: currentWidth * devicePixelRatio,
|
|
633
763
|
height: waveHeight * devicePixelRatio,
|
|
634
764
|
$waveHeight: waveHeight,
|
|
635
|
-
"data-index":
|
|
765
|
+
"data-index": i,
|
|
636
766
|
ref: canvasRef
|
|
637
767
|
},
|
|
638
|
-
`${length}-${
|
|
768
|
+
`${length}-${i}`
|
|
639
769
|
);
|
|
640
|
-
|
|
641
|
-
totalWidth -= currentWidth;
|
|
642
|
-
waveformCount += 1;
|
|
643
|
-
}
|
|
770
|
+
});
|
|
644
771
|
const bgColor = waveFillColor;
|
|
645
772
|
const backgroundCss = transparentBackground ? "transparent" : waveformColorToCss(bgColor);
|
|
646
|
-
return /* @__PURE__ */
|
|
773
|
+
return /* @__PURE__ */ jsx4(
|
|
647
774
|
Wrapper,
|
|
648
775
|
{
|
|
649
776
|
$index: index,
|
|
@@ -657,8 +784,8 @@ var Channel = (props) => {
|
|
|
657
784
|
};
|
|
658
785
|
|
|
659
786
|
// src/components/ErrorBoundary.tsx
|
|
660
|
-
import
|
|
661
|
-
import { jsx as
|
|
787
|
+
import React3 from "react";
|
|
788
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
662
789
|
var errorContainerStyle = {
|
|
663
790
|
padding: "16px",
|
|
664
791
|
background: "#1a1a2e",
|
|
@@ -672,7 +799,7 @@ var errorContainerStyle = {
|
|
|
672
799
|
alignItems: "center",
|
|
673
800
|
justifyContent: "center"
|
|
674
801
|
};
|
|
675
|
-
var PlaylistErrorBoundary = class extends
|
|
802
|
+
var PlaylistErrorBoundary = class extends React3.Component {
|
|
676
803
|
constructor(props) {
|
|
677
804
|
super(props);
|
|
678
805
|
this.state = { hasError: false, error: null };
|
|
@@ -688,7 +815,7 @@ var PlaylistErrorBoundary = class extends React2.Component {
|
|
|
688
815
|
if (this.props.fallback) {
|
|
689
816
|
return this.props.fallback;
|
|
690
817
|
}
|
|
691
|
-
return /* @__PURE__ */
|
|
818
|
+
return /* @__PURE__ */ jsx5("div", { style: errorContainerStyle, children: "Waveform playlist encountered an error. Check console for details." });
|
|
692
819
|
}
|
|
693
820
|
return this.props.children;
|
|
694
821
|
}
|
|
@@ -701,7 +828,7 @@ import { CSS } from "@dnd-kit/utilities";
|
|
|
701
828
|
|
|
702
829
|
// src/components/ClipHeader.tsx
|
|
703
830
|
import styled10 from "styled-components";
|
|
704
|
-
import { jsx as
|
|
831
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
705
832
|
var CLIP_HEADER_HEIGHT = 22;
|
|
706
833
|
var HeaderContainer = styled10.div`
|
|
707
834
|
position: relative;
|
|
@@ -741,27 +868,27 @@ var ClipHeaderPresentational = ({
|
|
|
741
868
|
trackName,
|
|
742
869
|
isSelected = false
|
|
743
870
|
}) => {
|
|
744
|
-
return /* @__PURE__ */
|
|
871
|
+
return /* @__PURE__ */ jsx6(
|
|
745
872
|
HeaderContainer,
|
|
746
873
|
{
|
|
747
874
|
$isDragging: false,
|
|
748
875
|
$interactive: false,
|
|
749
876
|
$isSelected: isSelected,
|
|
750
|
-
children: /* @__PURE__ */
|
|
877
|
+
children: /* @__PURE__ */ jsx6(TrackName, { children: trackName })
|
|
751
878
|
}
|
|
752
879
|
);
|
|
753
880
|
};
|
|
754
881
|
var ClipHeader = ({
|
|
755
882
|
clipId,
|
|
756
|
-
trackIndex,
|
|
757
|
-
clipIndex,
|
|
883
|
+
trackIndex: _trackIndex,
|
|
884
|
+
clipIndex: _clipIndex,
|
|
758
885
|
trackName,
|
|
759
886
|
isSelected = false,
|
|
760
887
|
disableDrag = false,
|
|
761
888
|
dragHandleProps
|
|
762
889
|
}) => {
|
|
763
890
|
if (disableDrag || !dragHandleProps) {
|
|
764
|
-
return /* @__PURE__ */
|
|
891
|
+
return /* @__PURE__ */ jsx6(
|
|
765
892
|
ClipHeaderPresentational,
|
|
766
893
|
{
|
|
767
894
|
trackName,
|
|
@@ -770,7 +897,7 @@ var ClipHeader = ({
|
|
|
770
897
|
);
|
|
771
898
|
}
|
|
772
899
|
const { attributes, listeners, setActivatorNodeRef } = dragHandleProps;
|
|
773
|
-
return /* @__PURE__ */
|
|
900
|
+
return /* @__PURE__ */ jsx6(
|
|
774
901
|
HeaderContainer,
|
|
775
902
|
{
|
|
776
903
|
ref: setActivatorNodeRef,
|
|
@@ -779,15 +906,15 @@ var ClipHeader = ({
|
|
|
779
906
|
$isSelected: isSelected,
|
|
780
907
|
...listeners,
|
|
781
908
|
...attributes,
|
|
782
|
-
children: /* @__PURE__ */
|
|
909
|
+
children: /* @__PURE__ */ jsx6(TrackName, { children: trackName })
|
|
783
910
|
}
|
|
784
911
|
);
|
|
785
912
|
};
|
|
786
913
|
|
|
787
914
|
// src/components/ClipBoundary.tsx
|
|
788
|
-
import
|
|
915
|
+
import React4 from "react";
|
|
789
916
|
import styled11 from "styled-components";
|
|
790
|
-
import { jsx as
|
|
917
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
791
918
|
var CLIP_BOUNDARY_WIDTH = 8;
|
|
792
919
|
var CLIP_BOUNDARY_WIDTH_TOUCH = 24;
|
|
793
920
|
var BoundaryContainer = styled11.div`
|
|
@@ -821,18 +948,18 @@ var BoundaryContainer = styled11.div`
|
|
|
821
948
|
`;
|
|
822
949
|
var ClipBoundary = ({
|
|
823
950
|
clipId,
|
|
824
|
-
trackIndex,
|
|
825
|
-
clipIndex,
|
|
951
|
+
trackIndex: _trackIndex,
|
|
952
|
+
clipIndex: _clipIndex,
|
|
826
953
|
edge,
|
|
827
954
|
dragHandleProps,
|
|
828
955
|
touchOptimized = false
|
|
829
956
|
}) => {
|
|
830
|
-
const [isHovered, setIsHovered] =
|
|
957
|
+
const [isHovered, setIsHovered] = React4.useState(false);
|
|
831
958
|
if (!dragHandleProps) {
|
|
832
959
|
return null;
|
|
833
960
|
}
|
|
834
961
|
const { attributes, listeners, setActivatorNodeRef, isDragging } = dragHandleProps;
|
|
835
|
-
return /* @__PURE__ */
|
|
962
|
+
return /* @__PURE__ */ jsx7(
|
|
836
963
|
BoundaryContainer,
|
|
837
964
|
{
|
|
838
965
|
ref: setActivatorNodeRef,
|
|
@@ -852,7 +979,7 @@ var ClipBoundary = ({
|
|
|
852
979
|
|
|
853
980
|
// src/components/FadeOverlay.tsx
|
|
854
981
|
import styled12, { useTheme } from "styled-components";
|
|
855
|
-
import { jsx as
|
|
982
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
856
983
|
var FadeContainer = styled12.div.attrs((props) => ({
|
|
857
984
|
style: {
|
|
858
985
|
left: `${props.$left}px`,
|
|
@@ -909,7 +1036,7 @@ var FadeOverlay = ({
|
|
|
909
1036
|
const theme = useTheme();
|
|
910
1037
|
if (width < 1) return null;
|
|
911
1038
|
const fillColor = color || theme?.fadeOverlayColor || "rgba(0, 0, 0, 0.4)";
|
|
912
|
-
return /* @__PURE__ */
|
|
1039
|
+
return /* @__PURE__ */ jsx8(FadeContainer, { $left: left, $width: width, $type: type, children: /* @__PURE__ */ jsx8(FadeSvg, { $type: type, viewBox: `0 0 ${width} 100`, preserveAspectRatio: "none", children: /* @__PURE__ */ jsx8(
|
|
913
1040
|
"path",
|
|
914
1041
|
{
|
|
915
1042
|
d: generateFadePath(width, 100, curveType),
|
|
@@ -919,7 +1046,7 @@ var FadeOverlay = ({
|
|
|
919
1046
|
};
|
|
920
1047
|
|
|
921
1048
|
// src/components/Clip.tsx
|
|
922
|
-
import { Fragment, jsx as
|
|
1049
|
+
import { Fragment, jsx as jsx9, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
923
1050
|
var ClipContainer = styled13.div.attrs((props) => ({
|
|
924
1051
|
style: props.$isOverlay ? {} : {
|
|
925
1052
|
left: `${props.$left}px`,
|
|
@@ -1017,7 +1144,7 @@ var Clip = ({
|
|
|
1017
1144
|
"data-track-id": trackId,
|
|
1018
1145
|
onMouseDown,
|
|
1019
1146
|
children: [
|
|
1020
|
-
showHeader && /* @__PURE__ */
|
|
1147
|
+
showHeader && /* @__PURE__ */ jsx9(
|
|
1021
1148
|
ClipHeader,
|
|
1022
1149
|
{
|
|
1023
1150
|
clipId,
|
|
@@ -1031,7 +1158,7 @@ var Clip = ({
|
|
|
1031
1158
|
),
|
|
1032
1159
|
/* @__PURE__ */ jsxs2(ChannelsWrapper, { $isOverlay: isOverlay, children: [
|
|
1033
1160
|
children,
|
|
1034
|
-
showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */
|
|
1161
|
+
showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */ jsx9(
|
|
1035
1162
|
FadeOverlay,
|
|
1036
1163
|
{
|
|
1037
1164
|
left: 0,
|
|
@@ -1040,7 +1167,7 @@ var Clip = ({
|
|
|
1040
1167
|
curveType: fadeIn.type
|
|
1041
1168
|
}
|
|
1042
1169
|
),
|
|
1043
|
-
showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */
|
|
1170
|
+
showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */ jsx9(
|
|
1044
1171
|
FadeOverlay,
|
|
1045
1172
|
{
|
|
1046
1173
|
left: width - Math.floor(fadeOut.duration * sampleRate / samplesPerPixel),
|
|
@@ -1051,7 +1178,7 @@ var Clip = ({
|
|
|
1051
1178
|
)
|
|
1052
1179
|
] }),
|
|
1053
1180
|
showHeader && !disableHeaderDrag && !isOverlay && /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
1054
|
-
/* @__PURE__ */
|
|
1181
|
+
/* @__PURE__ */ jsx9(
|
|
1055
1182
|
ClipBoundary,
|
|
1056
1183
|
{
|
|
1057
1184
|
clipId,
|
|
@@ -1067,7 +1194,7 @@ var Clip = ({
|
|
|
1067
1194
|
}
|
|
1068
1195
|
}
|
|
1069
1196
|
),
|
|
1070
|
-
/* @__PURE__ */
|
|
1197
|
+
/* @__PURE__ */ jsx9(
|
|
1071
1198
|
ClipBoundary,
|
|
1072
1199
|
{
|
|
1073
1200
|
clipId,
|
|
@@ -1091,7 +1218,7 @@ var Clip = ({
|
|
|
1091
1218
|
|
|
1092
1219
|
// src/components/MasterVolumeControl.tsx
|
|
1093
1220
|
import styled14 from "styled-components";
|
|
1094
|
-
import { jsx as
|
|
1221
|
+
import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1095
1222
|
var VolumeContainer = styled14.div`
|
|
1096
1223
|
display: inline-flex;
|
|
1097
1224
|
align-items: center;
|
|
@@ -1114,8 +1241,8 @@ var MasterVolumeControl = ({
|
|
|
1114
1241
|
onChange(parseFloat(e.target.value) / 100);
|
|
1115
1242
|
};
|
|
1116
1243
|
return /* @__PURE__ */ jsxs3(VolumeContainer, { className, children: [
|
|
1117
|
-
/* @__PURE__ */
|
|
1118
|
-
/* @__PURE__ */
|
|
1244
|
+
/* @__PURE__ */ jsx10(VolumeLabel, { htmlFor: "master-gain", children: "Master Volume" }),
|
|
1245
|
+
/* @__PURE__ */ jsx10(
|
|
1119
1246
|
VolumeSlider,
|
|
1120
1247
|
{
|
|
1121
1248
|
min: "0",
|
|
@@ -1130,9 +1257,9 @@ var MasterVolumeControl = ({
|
|
|
1130
1257
|
};
|
|
1131
1258
|
|
|
1132
1259
|
// src/components/Playhead.tsx
|
|
1133
|
-
import { useRef as
|
|
1260
|
+
import { useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
1134
1261
|
import styled15 from "styled-components";
|
|
1135
|
-
import { jsx as
|
|
1262
|
+
import { jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1136
1263
|
var PlayheadLine = styled15.div.attrs((props) => ({
|
|
1137
1264
|
style: {
|
|
1138
1265
|
transform: `translate3d(${props.$position}px, 0, 0)`
|
|
@@ -1149,7 +1276,7 @@ var PlayheadLine = styled15.div.attrs((props) => ({
|
|
|
1149
1276
|
will-change: transform;
|
|
1150
1277
|
`;
|
|
1151
1278
|
var Playhead = ({ position, color = "#ff0000" }) => {
|
|
1152
|
-
return /* @__PURE__ */
|
|
1279
|
+
return /* @__PURE__ */ jsx11(PlayheadLine, { $position: position, $color: color });
|
|
1153
1280
|
};
|
|
1154
1281
|
var PlayheadWithMarkerContainer = styled15.div`
|
|
1155
1282
|
position: absolute;
|
|
@@ -1189,9 +1316,9 @@ var PlayheadWithMarker = ({
|
|
|
1189
1316
|
controlsOffset,
|
|
1190
1317
|
getAudioContextTime
|
|
1191
1318
|
}) => {
|
|
1192
|
-
const containerRef =
|
|
1193
|
-
const animationFrameRef =
|
|
1194
|
-
|
|
1319
|
+
const containerRef = useRef3(null);
|
|
1320
|
+
const animationFrameRef = useRef3(null);
|
|
1321
|
+
useEffect3(() => {
|
|
1195
1322
|
const updatePosition = () => {
|
|
1196
1323
|
if (containerRef.current) {
|
|
1197
1324
|
let time;
|
|
@@ -1220,7 +1347,7 @@ var PlayheadWithMarker = ({
|
|
|
1220
1347
|
}
|
|
1221
1348
|
};
|
|
1222
1349
|
}, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef, playbackStartTimeRef, audioStartPositionRef, getAudioContextTime]);
|
|
1223
|
-
|
|
1350
|
+
useEffect3(() => {
|
|
1224
1351
|
if (!isPlaying && containerRef.current) {
|
|
1225
1352
|
const time = currentTimeRef.current ?? 0;
|
|
1226
1353
|
const pos = time * sampleRate / samplesPerPixel + controlsOffset;
|
|
@@ -1228,14 +1355,15 @@ var PlayheadWithMarker = ({
|
|
|
1228
1355
|
}
|
|
1229
1356
|
});
|
|
1230
1357
|
return /* @__PURE__ */ jsxs4(PlayheadWithMarkerContainer, { ref: containerRef, $color: color, children: [
|
|
1231
|
-
/* @__PURE__ */
|
|
1232
|
-
/* @__PURE__ */
|
|
1358
|
+
/* @__PURE__ */ jsx11(MarkerTriangle, { $color: color }),
|
|
1359
|
+
/* @__PURE__ */ jsx11(MarkerLine, { $color: color })
|
|
1233
1360
|
] });
|
|
1234
1361
|
};
|
|
1235
1362
|
|
|
1236
1363
|
// src/components/Playlist.tsx
|
|
1237
1364
|
import styled16, { withTheme } from "styled-components";
|
|
1238
|
-
import {
|
|
1365
|
+
import { useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
1366
|
+
import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1239
1367
|
var Wrapper2 = styled16.div`
|
|
1240
1368
|
overflow-y: hidden;
|
|
1241
1369
|
overflow-x: auto;
|
|
@@ -1289,16 +1417,21 @@ var Playlist = ({
|
|
|
1289
1417
|
isSelecting,
|
|
1290
1418
|
"data-playlist-state": playlistState
|
|
1291
1419
|
}) => {
|
|
1292
|
-
|
|
1420
|
+
const wrapperRef = useRef4(null);
|
|
1421
|
+
const handleRef = useCallback3((el) => {
|
|
1422
|
+
wrapperRef.current = el;
|
|
1423
|
+
scrollContainerRef?.(el);
|
|
1424
|
+
}, [scrollContainerRef]);
|
|
1425
|
+
return /* @__PURE__ */ jsx12(Wrapper2, { "data-scroll-container": "true", "data-playlist-state": playlistState, ref: handleRef, children: /* @__PURE__ */ jsx12(ScrollViewportProvider, { containerRef: wrapperRef, children: /* @__PURE__ */ jsxs5(
|
|
1293
1426
|
ScrollContainer,
|
|
1294
1427
|
{
|
|
1295
1428
|
$backgroundColor: backgroundColor,
|
|
1296
1429
|
$width: scrollContainerWidth,
|
|
1297
1430
|
children: [
|
|
1298
|
-
timescale && /* @__PURE__ */
|
|
1431
|
+
timescale && /* @__PURE__ */ jsx12(TimescaleWrapper, { $width: timescaleWidth, $backgroundColor: timescaleBackgroundColor, children: timescale }),
|
|
1299
1432
|
/* @__PURE__ */ jsxs5(TracksContainer, { $width: tracksWidth, $backgroundColor: backgroundColor, children: [
|
|
1300
1433
|
children,
|
|
1301
|
-
(onTracksClick || onTracksMouseDown) && /* @__PURE__ */
|
|
1434
|
+
(onTracksClick || onTracksMouseDown) && /* @__PURE__ */ jsx12(
|
|
1302
1435
|
ClickOverlay,
|
|
1303
1436
|
{
|
|
1304
1437
|
$controlsWidth: controlsWidth,
|
|
@@ -1312,13 +1445,13 @@ var Playlist = ({
|
|
|
1312
1445
|
] })
|
|
1313
1446
|
]
|
|
1314
1447
|
}
|
|
1315
|
-
) });
|
|
1448
|
+
) }) });
|
|
1316
1449
|
};
|
|
1317
1450
|
var StyledPlaylist = withTheme(Playlist);
|
|
1318
1451
|
|
|
1319
1452
|
// src/components/Selection.tsx
|
|
1320
1453
|
import styled17 from "styled-components";
|
|
1321
|
-
import { jsx as
|
|
1454
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1322
1455
|
var SelectionOverlay = styled17.div.attrs((props) => ({
|
|
1323
1456
|
style: {
|
|
1324
1457
|
left: `${props.$left}px`,
|
|
@@ -1342,13 +1475,13 @@ var Selection = ({
|
|
|
1342
1475
|
if (width <= 0) {
|
|
1343
1476
|
return null;
|
|
1344
1477
|
}
|
|
1345
|
-
return /* @__PURE__ */
|
|
1478
|
+
return /* @__PURE__ */ jsx13(SelectionOverlay, { $left: startPosition, $width: width, $color: color, "data-selection": true });
|
|
1346
1479
|
};
|
|
1347
1480
|
|
|
1348
1481
|
// src/components/LoopRegion.tsx
|
|
1349
|
-
import { useCallback as
|
|
1482
|
+
import { useCallback as useCallback4, useRef as useRef5, useState } from "react";
|
|
1350
1483
|
import styled18 from "styled-components";
|
|
1351
|
-
import { Fragment as Fragment2, jsx as
|
|
1484
|
+
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1352
1485
|
var LoopRegionOverlayDiv = styled18.div.attrs((props) => ({
|
|
1353
1486
|
style: {
|
|
1354
1487
|
left: `${props.$left}px`,
|
|
@@ -1398,7 +1531,7 @@ var LoopRegion = ({
|
|
|
1398
1531
|
return null;
|
|
1399
1532
|
}
|
|
1400
1533
|
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1401
|
-
/* @__PURE__ */
|
|
1534
|
+
/* @__PURE__ */ jsx14(
|
|
1402
1535
|
LoopRegionOverlayDiv,
|
|
1403
1536
|
{
|
|
1404
1537
|
$left: startPosition,
|
|
@@ -1407,7 +1540,7 @@ var LoopRegion = ({
|
|
|
1407
1540
|
"data-loop-region": true
|
|
1408
1541
|
}
|
|
1409
1542
|
),
|
|
1410
|
-
/* @__PURE__ */
|
|
1543
|
+
/* @__PURE__ */ jsx14(
|
|
1411
1544
|
LoopMarker,
|
|
1412
1545
|
{
|
|
1413
1546
|
$left: startPosition,
|
|
@@ -1416,7 +1549,7 @@ var LoopRegion = ({
|
|
|
1416
1549
|
"data-loop-marker": "start"
|
|
1417
1550
|
}
|
|
1418
1551
|
),
|
|
1419
|
-
/* @__PURE__ */
|
|
1552
|
+
/* @__PURE__ */ jsx14(
|
|
1420
1553
|
LoopMarker,
|
|
1421
1554
|
{
|
|
1422
1555
|
$left: endPosition - 2,
|
|
@@ -1498,11 +1631,11 @@ var LoopRegionMarkers = ({
|
|
|
1498
1631
|
maxPosition = Infinity
|
|
1499
1632
|
}) => {
|
|
1500
1633
|
const [draggingMarker, setDraggingMarker] = useState(null);
|
|
1501
|
-
const dragStartX =
|
|
1502
|
-
const dragStartPosition =
|
|
1503
|
-
const dragStartEnd =
|
|
1634
|
+
const dragStartX = useRef5(0);
|
|
1635
|
+
const dragStartPosition = useRef5(0);
|
|
1636
|
+
const dragStartEnd = useRef5(0);
|
|
1504
1637
|
const width = Math.max(0, endPosition - startPosition);
|
|
1505
|
-
const handleMarkerMouseDown =
|
|
1638
|
+
const handleMarkerMouseDown = useCallback4((e, marker) => {
|
|
1506
1639
|
e.preventDefault();
|
|
1507
1640
|
e.stopPropagation();
|
|
1508
1641
|
setDraggingMarker(marker);
|
|
@@ -1527,7 +1660,7 @@ var LoopRegionMarkers = ({
|
|
|
1527
1660
|
document.addEventListener("mousemove", handleMouseMove);
|
|
1528
1661
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1529
1662
|
}, [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]);
|
|
1530
|
-
const handleRegionMouseDown =
|
|
1663
|
+
const handleRegionMouseDown = useCallback4((e) => {
|
|
1531
1664
|
e.preventDefault();
|
|
1532
1665
|
e.stopPropagation();
|
|
1533
1666
|
setDraggingMarker("region");
|
|
@@ -1561,7 +1694,7 @@ var LoopRegionMarkers = ({
|
|
|
1561
1694
|
return null;
|
|
1562
1695
|
}
|
|
1563
1696
|
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1564
|
-
/* @__PURE__ */
|
|
1697
|
+
/* @__PURE__ */ jsx14(
|
|
1565
1698
|
TimescaleLoopShade,
|
|
1566
1699
|
{
|
|
1567
1700
|
$left: startPosition,
|
|
@@ -1572,7 +1705,7 @@ var LoopRegionMarkers = ({
|
|
|
1572
1705
|
"data-loop-region-timescale": true
|
|
1573
1706
|
}
|
|
1574
1707
|
),
|
|
1575
|
-
/* @__PURE__ */
|
|
1708
|
+
/* @__PURE__ */ jsx14(
|
|
1576
1709
|
DraggableMarkerHandle,
|
|
1577
1710
|
{
|
|
1578
1711
|
$left: startPosition,
|
|
@@ -1583,7 +1716,7 @@ var LoopRegionMarkers = ({
|
|
|
1583
1716
|
"data-loop-marker-handle": "start"
|
|
1584
1717
|
}
|
|
1585
1718
|
),
|
|
1586
|
-
/* @__PURE__ */
|
|
1719
|
+
/* @__PURE__ */ jsx14(
|
|
1587
1720
|
DraggableMarkerHandle,
|
|
1588
1721
|
{
|
|
1589
1722
|
$left: endPosition,
|
|
@@ -1618,11 +1751,11 @@ var TimescaleLoopRegion = ({
|
|
|
1618
1751
|
maxPosition = Infinity,
|
|
1619
1752
|
controlsOffset = 0
|
|
1620
1753
|
}) => {
|
|
1621
|
-
const [
|
|
1622
|
-
const createStartX =
|
|
1623
|
-
const containerRef =
|
|
1754
|
+
const [, setIsCreating] = useState(false);
|
|
1755
|
+
const createStartX = useRef5(0);
|
|
1756
|
+
const containerRef = useRef5(null);
|
|
1624
1757
|
const hasLoopRegion = endPosition > startPosition;
|
|
1625
|
-
const handleBackgroundMouseDown =
|
|
1758
|
+
const handleBackgroundMouseDown = useCallback4((e) => {
|
|
1626
1759
|
const target = e.target;
|
|
1627
1760
|
if (target.closest("[data-loop-marker-handle]") || target.closest("[data-loop-region-timescale]")) {
|
|
1628
1761
|
return;
|
|
@@ -1650,14 +1783,14 @@ var TimescaleLoopRegion = ({
|
|
|
1650
1783
|
document.addEventListener("mousemove", handleMouseMove);
|
|
1651
1784
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1652
1785
|
}, [minPosition, maxPosition, onLoopRegionChange]);
|
|
1653
|
-
return /* @__PURE__ */
|
|
1786
|
+
return /* @__PURE__ */ jsx14(
|
|
1654
1787
|
TimescaleLoopCreator,
|
|
1655
1788
|
{
|
|
1656
1789
|
ref: containerRef,
|
|
1657
1790
|
$leftOffset: controlsOffset,
|
|
1658
1791
|
onMouseDown: handleBackgroundMouseDown,
|
|
1659
1792
|
"data-timescale-loop-creator": true,
|
|
1660
|
-
children: hasLoopRegion && /* @__PURE__ */
|
|
1793
|
+
children: hasLoopRegion && /* @__PURE__ */ jsx14(
|
|
1661
1794
|
LoopRegionMarkers,
|
|
1662
1795
|
{
|
|
1663
1796
|
startPosition,
|
|
@@ -1676,10 +1809,10 @@ var TimescaleLoopRegion = ({
|
|
|
1676
1809
|
};
|
|
1677
1810
|
|
|
1678
1811
|
// src/components/SelectionTimeInputs.tsx
|
|
1679
|
-
import { useEffect as
|
|
1812
|
+
import { useEffect as useEffect5, useState as useState3 } from "react";
|
|
1680
1813
|
|
|
1681
1814
|
// src/components/TimeInput.tsx
|
|
1682
|
-
import { useEffect as
|
|
1815
|
+
import { useEffect as useEffect4, useState as useState2 } from "react";
|
|
1683
1816
|
|
|
1684
1817
|
// src/utils/timeFormat.ts
|
|
1685
1818
|
function clockFormat(seconds, decimals) {
|
|
@@ -1729,7 +1862,7 @@ function parseTime(timeStr, format) {
|
|
|
1729
1862
|
}
|
|
1730
1863
|
|
|
1731
1864
|
// src/components/TimeInput.tsx
|
|
1732
|
-
import { Fragment as Fragment3, jsx as
|
|
1865
|
+
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1733
1866
|
var TimeInput = ({
|
|
1734
1867
|
id,
|
|
1735
1868
|
label,
|
|
@@ -1740,7 +1873,7 @@ var TimeInput = ({
|
|
|
1740
1873
|
readOnly = false
|
|
1741
1874
|
}) => {
|
|
1742
1875
|
const [displayValue, setDisplayValue] = useState2("");
|
|
1743
|
-
|
|
1876
|
+
useEffect4(() => {
|
|
1744
1877
|
const formatted = formatTime(value, format);
|
|
1745
1878
|
setDisplayValue(formatted);
|
|
1746
1879
|
}, [value, format, id]);
|
|
@@ -1761,8 +1894,8 @@ var TimeInput = ({
|
|
|
1761
1894
|
}
|
|
1762
1895
|
};
|
|
1763
1896
|
return /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
1764
|
-
/* @__PURE__ */
|
|
1765
|
-
/* @__PURE__ */
|
|
1897
|
+
/* @__PURE__ */ jsx15(ScreenReaderOnly, { as: "label", htmlFor: id, children: label }),
|
|
1898
|
+
/* @__PURE__ */ jsx15(
|
|
1766
1899
|
BaseInput,
|
|
1767
1900
|
{
|
|
1768
1901
|
type: "text",
|
|
@@ -1779,7 +1912,7 @@ var TimeInput = ({
|
|
|
1779
1912
|
};
|
|
1780
1913
|
|
|
1781
1914
|
// src/components/SelectionTimeInputs.tsx
|
|
1782
|
-
import {
|
|
1915
|
+
import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1783
1916
|
var SelectionTimeInputs = ({
|
|
1784
1917
|
selectionStart,
|
|
1785
1918
|
selectionEnd,
|
|
@@ -1787,7 +1920,7 @@ var SelectionTimeInputs = ({
|
|
|
1787
1920
|
className
|
|
1788
1921
|
}) => {
|
|
1789
1922
|
const [timeFormat, setTimeFormat] = useState3("hh:mm:ss.uuu");
|
|
1790
|
-
|
|
1923
|
+
useEffect5(() => {
|
|
1791
1924
|
const timeFormatSelect = document.querySelector(".time-format");
|
|
1792
1925
|
const handleFormatChange = () => {
|
|
1793
1926
|
if (timeFormatSelect) {
|
|
@@ -1812,8 +1945,8 @@ var SelectionTimeInputs = ({
|
|
|
1812
1945
|
onSelectionChange(selectionStart, value);
|
|
1813
1946
|
}
|
|
1814
1947
|
};
|
|
1815
|
-
return /* @__PURE__ */ jsxs8(
|
|
1816
|
-
/* @__PURE__ */
|
|
1948
|
+
return /* @__PURE__ */ jsxs8("div", { className, children: [
|
|
1949
|
+
/* @__PURE__ */ jsx16(
|
|
1817
1950
|
TimeInput,
|
|
1818
1951
|
{
|
|
1819
1952
|
id: "audio_start",
|
|
@@ -1824,7 +1957,7 @@ var SelectionTimeInputs = ({
|
|
|
1824
1957
|
onChange: handleStartChange
|
|
1825
1958
|
}
|
|
1826
1959
|
),
|
|
1827
|
-
/* @__PURE__ */
|
|
1960
|
+
/* @__PURE__ */ jsx16(
|
|
1828
1961
|
TimeInput,
|
|
1829
1962
|
{
|
|
1830
1963
|
id: "audio_end",
|
|
@@ -1839,12 +1972,12 @@ var SelectionTimeInputs = ({
|
|
|
1839
1972
|
};
|
|
1840
1973
|
|
|
1841
1974
|
// src/contexts/DevicePixelRatio.tsx
|
|
1842
|
-
import { useState as useState4, createContext, useContext } from "react";
|
|
1843
|
-
import { jsx as
|
|
1975
|
+
import { useState as useState4, createContext as createContext2, useContext as useContext2 } from "react";
|
|
1976
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1844
1977
|
function getScale() {
|
|
1845
1978
|
return window.devicePixelRatio;
|
|
1846
1979
|
}
|
|
1847
|
-
var DevicePixelRatioContext =
|
|
1980
|
+
var DevicePixelRatioContext = createContext2(getScale());
|
|
1848
1981
|
var DevicePixelRatioProvider = ({ children }) => {
|
|
1849
1982
|
const [scale, setScale] = useState4(getScale());
|
|
1850
1983
|
matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
|
|
@@ -1854,13 +1987,13 @@ var DevicePixelRatioProvider = ({ children }) => {
|
|
|
1854
1987
|
},
|
|
1855
1988
|
{ once: true }
|
|
1856
1989
|
);
|
|
1857
|
-
return /* @__PURE__ */
|
|
1990
|
+
return /* @__PURE__ */ jsx17(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
|
|
1858
1991
|
};
|
|
1859
|
-
var useDevicePixelRatio = () =>
|
|
1992
|
+
var useDevicePixelRatio = () => useContext2(DevicePixelRatioContext);
|
|
1860
1993
|
|
|
1861
1994
|
// src/contexts/PlaylistInfo.tsx
|
|
1862
|
-
import { createContext as
|
|
1863
|
-
var PlaylistInfoContext =
|
|
1995
|
+
import { createContext as createContext3, useContext as useContext3 } from "react";
|
|
1996
|
+
var PlaylistInfoContext = createContext3({
|
|
1864
1997
|
sampleRate: 48e3,
|
|
1865
1998
|
samplesPerPixel: 1e3,
|
|
1866
1999
|
zoomLevels: [1e3, 1500, 2e3, 2500],
|
|
@@ -1874,26 +2007,26 @@ var PlaylistInfoContext = createContext2({
|
|
|
1874
2007
|
barWidth: 1,
|
|
1875
2008
|
barGap: 0
|
|
1876
2009
|
});
|
|
1877
|
-
var usePlaylistInfo = () =>
|
|
2010
|
+
var usePlaylistInfo = () => useContext3(PlaylistInfoContext);
|
|
1878
2011
|
|
|
1879
2012
|
// src/contexts/Theme.tsx
|
|
1880
|
-
import { useContext as
|
|
2013
|
+
import { useContext as useContext4 } from "react";
|
|
1881
2014
|
import { ThemeContext } from "styled-components";
|
|
1882
|
-
var useTheme2 = () =>
|
|
2015
|
+
var useTheme2 = () => useContext4(ThemeContext);
|
|
1883
2016
|
|
|
1884
2017
|
// src/contexts/TrackControls.tsx
|
|
1885
|
-
import { createContext as
|
|
1886
|
-
import { jsx as
|
|
1887
|
-
var TrackControlsContext =
|
|
1888
|
-
var useTrackControls = () =>
|
|
2018
|
+
import { createContext as createContext4, useContext as useContext5, Fragment as Fragment4 } from "react";
|
|
2019
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
2020
|
+
var TrackControlsContext = createContext4(/* @__PURE__ */ jsx18(Fragment4, {}));
|
|
2021
|
+
var useTrackControls = () => useContext5(TrackControlsContext);
|
|
1889
2022
|
|
|
1890
2023
|
// src/contexts/Playout.tsx
|
|
1891
2024
|
import {
|
|
1892
2025
|
useState as useState5,
|
|
1893
|
-
createContext as
|
|
1894
|
-
useContext as
|
|
2026
|
+
createContext as createContext5,
|
|
2027
|
+
useContext as useContext6
|
|
1895
2028
|
} from "react";
|
|
1896
|
-
import { jsx as
|
|
2029
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
1897
2030
|
var defaultProgress = 0;
|
|
1898
2031
|
var defaultIsPlaying = false;
|
|
1899
2032
|
var defaultSelectionStart = 0;
|
|
@@ -1904,8 +2037,8 @@ var defaultPlayout = {
|
|
|
1904
2037
|
selectionStart: defaultSelectionStart,
|
|
1905
2038
|
selectionEnd: defaultSelectionEnd
|
|
1906
2039
|
};
|
|
1907
|
-
var PlayoutStatusContext =
|
|
1908
|
-
var PlayoutStatusUpdateContext =
|
|
2040
|
+
var PlayoutStatusContext = createContext5(defaultPlayout);
|
|
2041
|
+
var PlayoutStatusUpdateContext = createContext5({
|
|
1909
2042
|
setIsPlaying: () => {
|
|
1910
2043
|
},
|
|
1911
2044
|
setProgress: () => {
|
|
@@ -1922,16 +2055,16 @@ var PlayoutProvider = ({ children }) => {
|
|
|
1922
2055
|
setSelectionStart(start);
|
|
1923
2056
|
setSelectionEnd(end);
|
|
1924
2057
|
};
|
|
1925
|
-
return /* @__PURE__ */
|
|
2058
|
+
return /* @__PURE__ */ jsx19(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ jsx19(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
|
|
1926
2059
|
};
|
|
1927
|
-
var usePlayoutStatus = () =>
|
|
1928
|
-
var usePlayoutStatusUpdate = () =>
|
|
2060
|
+
var usePlayoutStatus = () => useContext6(PlayoutStatusContext);
|
|
2061
|
+
var usePlayoutStatusUpdate = () => useContext6(PlayoutStatusUpdateContext);
|
|
1929
2062
|
|
|
1930
2063
|
// src/components/SpectrogramChannel.tsx
|
|
1931
|
-
import { useLayoutEffect as useLayoutEffect2, useCallback as
|
|
2064
|
+
import { useLayoutEffect as useLayoutEffect2, useCallback as useCallback5, useRef as useRef6, useEffect as useEffect6 } from "react";
|
|
1932
2065
|
import styled19 from "styled-components";
|
|
1933
|
-
import { jsx as
|
|
1934
|
-
var
|
|
2066
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
2067
|
+
var LINEAR_FREQUENCY_SCALE = (f, minF, maxF) => (f - minF) / (maxF - minF);
|
|
1935
2068
|
var Wrapper3 = styled19.div.attrs((props) => ({
|
|
1936
2069
|
style: {
|
|
1937
2070
|
top: `${props.$waveHeight * props.$index}px`,
|
|
@@ -1947,11 +2080,13 @@ var Wrapper3 = styled19.div.attrs((props) => ({
|
|
|
1947
2080
|
var SpectrogramCanvas = styled19.canvas.attrs((props) => ({
|
|
1948
2081
|
style: {
|
|
1949
2082
|
width: `${props.$cssWidth}px`,
|
|
1950
|
-
height: `${props.$waveHeight}px
|
|
2083
|
+
height: `${props.$waveHeight}px`,
|
|
2084
|
+
left: `${props.$left}px`
|
|
1951
2085
|
}
|
|
1952
2086
|
}))`
|
|
1953
|
-
|
|
1954
|
-
|
|
2087
|
+
position: absolute;
|
|
2088
|
+
top: 0;
|
|
2089
|
+
/* Promote to own compositing layer for smoother scrolling */
|
|
1955
2090
|
will-change: transform;
|
|
1956
2091
|
image-rendering: pixelated;
|
|
1957
2092
|
image-rendering: crisp-edges;
|
|
@@ -1963,6 +2098,7 @@ function defaultGetColorMap() {
|
|
|
1963
2098
|
}
|
|
1964
2099
|
return lut;
|
|
1965
2100
|
}
|
|
2101
|
+
var DEFAULT_COLOR_LUT = defaultGetColorMap();
|
|
1966
2102
|
var SpectrogramChannel = ({
|
|
1967
2103
|
index,
|
|
1968
2104
|
channelIndex: channelIndexProp,
|
|
@@ -1980,11 +2116,30 @@ var SpectrogramChannel = ({
|
|
|
1980
2116
|
onCanvasesReady
|
|
1981
2117
|
}) => {
|
|
1982
2118
|
const channelIndex = channelIndexProp ?? index;
|
|
1983
|
-
const canvasesRef =
|
|
1984
|
-
const registeredIdsRef =
|
|
1985
|
-
const transferredCanvasesRef =
|
|
2119
|
+
const canvasesRef = useRef6([]);
|
|
2120
|
+
const registeredIdsRef = useRef6([]);
|
|
2121
|
+
const transferredCanvasesRef = useRef6(/* @__PURE__ */ new WeakSet());
|
|
2122
|
+
const workerApiRef = useRef6(workerApi);
|
|
2123
|
+
const onCanvasesReadyRef = useRef6(onCanvasesReady);
|
|
1986
2124
|
const isWorkerMode = !!(workerApi && clipId);
|
|
1987
|
-
const
|
|
2125
|
+
const visibleChunkKey = useScrollViewportSelector((viewport) => {
|
|
2126
|
+
const totalChunks = Math.ceil(length / MAX_CANVAS_WIDTH);
|
|
2127
|
+
const indices = [];
|
|
2128
|
+
for (let i = 0; i < totalChunks; i++) {
|
|
2129
|
+
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
2130
|
+
const chunkWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
|
|
2131
|
+
if (viewport) {
|
|
2132
|
+
const chunkEnd = chunkLeft + chunkWidth;
|
|
2133
|
+
if (chunkEnd <= viewport.visibleStart || chunkLeft >= viewport.visibleEnd) {
|
|
2134
|
+
continue;
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
indices.push(i);
|
|
2138
|
+
}
|
|
2139
|
+
return indices.join(",");
|
|
2140
|
+
});
|
|
2141
|
+
const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
|
|
2142
|
+
const canvasRef = useCallback5(
|
|
1988
2143
|
(canvas) => {
|
|
1989
2144
|
if (canvas !== null) {
|
|
1990
2145
|
const idx = parseInt(canvas.dataset.index, 10);
|
|
@@ -1993,53 +2148,101 @@ var SpectrogramChannel = ({
|
|
|
1993
2148
|
},
|
|
1994
2149
|
[]
|
|
1995
2150
|
);
|
|
1996
|
-
|
|
2151
|
+
const lut = colorLUT ?? DEFAULT_COLOR_LUT;
|
|
2152
|
+
const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
|
|
2153
|
+
const scaleFn = frequencyScaleFn ?? LINEAR_FREQUENCY_SCALE;
|
|
2154
|
+
const hasCustomFrequencyScale = Boolean(frequencyScaleFn);
|
|
2155
|
+
useEffect6(() => {
|
|
2156
|
+
workerApiRef.current = workerApi;
|
|
2157
|
+
}, [workerApi]);
|
|
2158
|
+
useEffect6(() => {
|
|
2159
|
+
onCanvasesReadyRef.current = onCanvasesReady;
|
|
2160
|
+
}, [onCanvasesReady]);
|
|
2161
|
+
useEffect6(() => {
|
|
1997
2162
|
if (!isWorkerMode) return;
|
|
1998
|
-
const
|
|
1999
|
-
|
|
2163
|
+
const currentWorkerApi = workerApiRef.current;
|
|
2164
|
+
if (!currentWorkerApi || !clipId) return;
|
|
2000
2165
|
const canvases2 = canvasesRef.current;
|
|
2001
|
-
const
|
|
2002
|
-
const
|
|
2166
|
+
const newIds = [];
|
|
2167
|
+
const newWidths = [];
|
|
2003
2168
|
for (let i = 0; i < canvases2.length; i++) {
|
|
2004
2169
|
const canvas = canvases2[i];
|
|
2005
2170
|
if (!canvas) continue;
|
|
2006
2171
|
if (transferredCanvasesRef.current.has(canvas)) continue;
|
|
2007
|
-
const
|
|
2172
|
+
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
2173
|
+
const canvasId = `${clipId}-ch${channelIndex}-chunk${canvasIdx}`;
|
|
2174
|
+
let offscreen;
|
|
2008
2175
|
try {
|
|
2009
|
-
|
|
2010
|
-
workerApi.registerCanvas(canvasId, offscreen);
|
|
2011
|
-
transferredCanvasesRef.current.add(canvas);
|
|
2012
|
-
ids.push(canvasId);
|
|
2013
|
-
widths.push(Math.min(length - i * MAX_CANVAS_WIDTH2, MAX_CANVAS_WIDTH2));
|
|
2176
|
+
offscreen = canvas.transferControlToOffscreen();
|
|
2014
2177
|
} catch (err) {
|
|
2015
2178
|
console.warn(`[spectrogram] transferControlToOffscreen failed for ${canvasId}:`, err);
|
|
2016
2179
|
continue;
|
|
2017
2180
|
}
|
|
2181
|
+
transferredCanvasesRef.current.add(canvas);
|
|
2182
|
+
try {
|
|
2183
|
+
currentWorkerApi.registerCanvas(canvasId, offscreen);
|
|
2184
|
+
newIds.push(canvasId);
|
|
2185
|
+
newWidths.push(Math.min(length - canvasIdx * MAX_CANVAS_WIDTH, MAX_CANVAS_WIDTH));
|
|
2186
|
+
} catch (err) {
|
|
2187
|
+
console.warn(`[spectrogram] registerCanvas failed for ${canvasId}:`, err);
|
|
2188
|
+
continue;
|
|
2189
|
+
}
|
|
2018
2190
|
}
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2191
|
+
if (newIds.length > 0) {
|
|
2192
|
+
registeredIdsRef.current = [...registeredIdsRef.current, ...newIds];
|
|
2193
|
+
onCanvasesReadyRef.current?.(newIds, newWidths);
|
|
2194
|
+
}
|
|
2195
|
+
}, [isWorkerMode, clipId, channelIndex, length, visibleChunkKey]);
|
|
2196
|
+
useEffect6(() => {
|
|
2197
|
+
if (!isWorkerMode) return;
|
|
2198
|
+
const currentWorkerApi = workerApiRef.current;
|
|
2199
|
+
if (!currentWorkerApi) return;
|
|
2200
|
+
const remaining = [];
|
|
2201
|
+
for (const id of registeredIdsRef.current) {
|
|
2202
|
+
const match = id.match(/chunk(\d+)$/);
|
|
2203
|
+
if (!match) {
|
|
2204
|
+
remaining.push(id);
|
|
2205
|
+
continue;
|
|
2206
|
+
}
|
|
2207
|
+
const chunkIdx = parseInt(match[1], 10);
|
|
2208
|
+
const canvas = canvasesRef.current[chunkIdx];
|
|
2209
|
+
if (canvas && canvas.isConnected) {
|
|
2210
|
+
remaining.push(id);
|
|
2211
|
+
} else {
|
|
2212
|
+
try {
|
|
2213
|
+
currentWorkerApi.unregisterCanvas(id);
|
|
2214
|
+
} catch (err) {
|
|
2215
|
+
console.warn(`[spectrogram] unregisterCanvas failed for ${id}:`, err);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2022
2218
|
}
|
|
2219
|
+
registeredIdsRef.current = remaining;
|
|
2220
|
+
});
|
|
2221
|
+
useEffect6(() => {
|
|
2023
2222
|
return () => {
|
|
2223
|
+
const api = workerApiRef.current;
|
|
2224
|
+
if (!api) return;
|
|
2024
2225
|
for (const id of registeredIdsRef.current) {
|
|
2025
|
-
|
|
2226
|
+
try {
|
|
2227
|
+
api.unregisterCanvas(id);
|
|
2228
|
+
} catch (err) {
|
|
2229
|
+
console.warn(`[spectrogram] unregisterCanvas failed for ${id}:`, err);
|
|
2230
|
+
}
|
|
2026
2231
|
}
|
|
2027
2232
|
registeredIdsRef.current = [];
|
|
2028
2233
|
};
|
|
2029
|
-
}, [
|
|
2030
|
-
const lut = colorLUT ?? defaultGetColorMap();
|
|
2031
|
-
const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
|
|
2032
|
-
const scaleFn = frequencyScaleFn ?? ((f, minF, maxF2) => (f - minF) / (maxF2 - minF));
|
|
2234
|
+
}, []);
|
|
2033
2235
|
useLayoutEffect2(() => {
|
|
2034
2236
|
if (isWorkerMode || !data) return;
|
|
2035
2237
|
const canvases2 = canvasesRef.current;
|
|
2036
2238
|
const { frequencyBinCount, frameCount, hopSize, sampleRate, gainDb, rangeDb: rawRangeDb } = data;
|
|
2037
2239
|
const rangeDb = rawRangeDb === 0 ? 1 : rawRangeDb;
|
|
2038
|
-
let globalPixelOffset = 0;
|
|
2039
2240
|
const binToFreq = (bin) => bin / frequencyBinCount * (sampleRate / 2);
|
|
2040
|
-
for (let
|
|
2041
|
-
const canvas = canvases2[
|
|
2241
|
+
for (let i = 0; i < canvases2.length; i++) {
|
|
2242
|
+
const canvas = canvases2[i];
|
|
2042
2243
|
if (!canvas) continue;
|
|
2244
|
+
const canvasIdx = parseInt(canvas.dataset.index, 10);
|
|
2245
|
+
const globalPixelOffset = canvasIdx * MAX_CANVAS_WIDTH;
|
|
2043
2246
|
const ctx = canvas.getContext("2d");
|
|
2044
2247
|
if (!ctx) continue;
|
|
2045
2248
|
const canvasWidth = canvas.width / devicePixelRatio;
|
|
@@ -2059,7 +2262,7 @@ var SpectrogramChannel = ({
|
|
|
2059
2262
|
for (let y = 0; y < canvasHeight; y++) {
|
|
2060
2263
|
const normalizedY = 1 - y / canvasHeight;
|
|
2061
2264
|
let bin = Math.floor(normalizedY * frequencyBinCount);
|
|
2062
|
-
if (
|
|
2265
|
+
if (hasCustomFrequencyScale) {
|
|
2063
2266
|
let lo = 0;
|
|
2064
2267
|
let hi = frequencyBinCount - 1;
|
|
2065
2268
|
while (lo < hi) {
|
|
@@ -2098,36 +2301,30 @@ var SpectrogramChannel = ({
|
|
|
2098
2301
|
ctx.imageSmoothingEnabled = false;
|
|
2099
2302
|
ctx.drawImage(tmpCanvas, 0, 0, canvas.width, canvas.height);
|
|
2100
2303
|
}
|
|
2101
|
-
globalPixelOffset += canvasWidth;
|
|
2102
2304
|
}
|
|
2103
|
-
}, [isWorkerMode, data, length, waveHeight, devicePixelRatio, samplesPerPixel, lut,
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
},
|
|
2120
|
-
`${length}-${canvasCount}`
|
|
2121
|
-
)
|
|
2305
|
+
}, [isWorkerMode, data, length, waveHeight, devicePixelRatio, samplesPerPixel, lut, minFrequency, maxF, scaleFn, hasCustomFrequencyScale, visibleChunkKey]);
|
|
2306
|
+
const canvases = visibleChunkIndices.map((i) => {
|
|
2307
|
+
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
2308
|
+
const currentWidth = Math.min(length - chunkLeft, MAX_CANVAS_WIDTH);
|
|
2309
|
+
return /* @__PURE__ */ jsx20(
|
|
2310
|
+
SpectrogramCanvas,
|
|
2311
|
+
{
|
|
2312
|
+
$cssWidth: currentWidth,
|
|
2313
|
+
$left: chunkLeft,
|
|
2314
|
+
width: currentWidth * devicePixelRatio,
|
|
2315
|
+
height: waveHeight * devicePixelRatio,
|
|
2316
|
+
$waveHeight: waveHeight,
|
|
2317
|
+
"data-index": i,
|
|
2318
|
+
ref: canvasRef
|
|
2319
|
+
},
|
|
2320
|
+
`${length}-${i}`
|
|
2122
2321
|
);
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
}
|
|
2126
|
-
return /* @__PURE__ */ jsx19(Wrapper3, { $index: index, $cssWidth: length, $waveHeight: waveHeight, children: canvases });
|
|
2322
|
+
});
|
|
2323
|
+
return /* @__PURE__ */ jsx20(Wrapper3, { $index: index, $cssWidth: length, $waveHeight: waveHeight, children: canvases });
|
|
2127
2324
|
};
|
|
2128
2325
|
|
|
2129
2326
|
// src/components/SmartChannel.tsx
|
|
2130
|
-
import { Fragment as
|
|
2327
|
+
import { Fragment as Fragment5, jsx as jsx21, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2131
2328
|
var SmartChannel = ({
|
|
2132
2329
|
isSelected,
|
|
2133
2330
|
transparentBackground,
|
|
@@ -2152,7 +2349,7 @@ var SmartChannel = ({
|
|
|
2152
2349
|
const drawMode = theme?.waveformDrawMode || "inverted";
|
|
2153
2350
|
const hasSpectrogram = spectrogramData || spectrogramWorkerApi;
|
|
2154
2351
|
if (renderMode === "spectrogram" && hasSpectrogram) {
|
|
2155
|
-
return /* @__PURE__ */
|
|
2352
|
+
return /* @__PURE__ */ jsx21(
|
|
2156
2353
|
SpectrogramChannel,
|
|
2157
2354
|
{
|
|
2158
2355
|
index: props.index,
|
|
@@ -2173,8 +2370,8 @@ var SmartChannel = ({
|
|
|
2173
2370
|
}
|
|
2174
2371
|
if (renderMode === "both" && hasSpectrogram) {
|
|
2175
2372
|
const halfHeight = Math.floor(waveHeight / 2);
|
|
2176
|
-
return /* @__PURE__ */ jsxs9(
|
|
2177
|
-
/* @__PURE__ */
|
|
2373
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
2374
|
+
/* @__PURE__ */ jsx21(
|
|
2178
2375
|
SpectrogramChannel,
|
|
2179
2376
|
{
|
|
2180
2377
|
index: props.index * 2,
|
|
@@ -2193,7 +2390,7 @@ var SmartChannel = ({
|
|
|
2193
2390
|
onCanvasesReady: spectrogramOnCanvasesReady
|
|
2194
2391
|
}
|
|
2195
2392
|
),
|
|
2196
|
-
/* @__PURE__ */
|
|
2393
|
+
/* @__PURE__ */ jsx21("div", { style: { position: "absolute", top: (props.index * 2 + 1) * halfHeight, width: props.length, height: halfHeight }, children: /* @__PURE__ */ jsx21(
|
|
2197
2394
|
Channel,
|
|
2198
2395
|
{
|
|
2199
2396
|
...props,
|
|
@@ -2210,7 +2407,7 @@ var SmartChannel = ({
|
|
|
2210
2407
|
) })
|
|
2211
2408
|
] });
|
|
2212
2409
|
}
|
|
2213
|
-
return /* @__PURE__ */
|
|
2410
|
+
return /* @__PURE__ */ jsx21(
|
|
2214
2411
|
Channel,
|
|
2215
2412
|
{
|
|
2216
2413
|
...props,
|
|
@@ -2227,9 +2424,9 @@ var SmartChannel = ({
|
|
|
2227
2424
|
};
|
|
2228
2425
|
|
|
2229
2426
|
// src/components/SpectrogramLabels.tsx
|
|
2230
|
-
import { useRef as
|
|
2427
|
+
import { useRef as useRef7, useLayoutEffect as useLayoutEffect3 } from "react";
|
|
2231
2428
|
import styled20 from "styled-components";
|
|
2232
|
-
import { jsx as
|
|
2429
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
2233
2430
|
var LABELS_WIDTH = 72;
|
|
2234
2431
|
var LabelsStickyWrapper = styled20.div`
|
|
2235
2432
|
position: sticky;
|
|
@@ -2279,7 +2476,7 @@ var SpectrogramLabels = ({
|
|
|
2279
2476
|
renderMode = "spectrogram",
|
|
2280
2477
|
hasClipHeaders = false
|
|
2281
2478
|
}) => {
|
|
2282
|
-
const canvasRef =
|
|
2479
|
+
const canvasRef = useRef7(null);
|
|
2283
2480
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2284
2481
|
const spectrogramHeight = renderMode === "both" ? Math.floor(waveHeight / 2) : waveHeight;
|
|
2285
2482
|
const totalHeight = numChannels * waveHeight;
|
|
@@ -2311,7 +2508,7 @@ var SpectrogramLabels = ({
|
|
|
2311
2508
|
}
|
|
2312
2509
|
}
|
|
2313
2510
|
}, [waveHeight, numChannels, frequencyScaleFn, minFrequency, maxFrequency, labelsColor, labelsBackground, devicePixelRatio, spectrogramHeight, clipHeaderOffset]);
|
|
2314
|
-
return /* @__PURE__ */
|
|
2511
|
+
return /* @__PURE__ */ jsx22(LabelsStickyWrapper, { $height: totalHeight + clipHeaderOffset, children: /* @__PURE__ */ jsx22(
|
|
2315
2512
|
"canvas",
|
|
2316
2513
|
{
|
|
2317
2514
|
ref: canvasRef,
|
|
@@ -2327,10 +2524,10 @@ var SpectrogramLabels = ({
|
|
|
2327
2524
|
};
|
|
2328
2525
|
|
|
2329
2526
|
// src/components/SmartScale.tsx
|
|
2330
|
-
import { useContext as
|
|
2527
|
+
import { useContext as useContext8 } from "react";
|
|
2331
2528
|
|
|
2332
2529
|
// src/components/TimeScale.tsx
|
|
2333
|
-
import
|
|
2530
|
+
import React15, { useRef as useRef8, useEffect as useEffect7, useLayoutEffect as useLayoutEffect4, useContext as useContext7, useMemo, useCallback as useCallback6 } from "react";
|
|
2334
2531
|
import styled21, { withTheme as withTheme2 } from "styled-components";
|
|
2335
2532
|
|
|
2336
2533
|
// src/utils/conversions.ts
|
|
@@ -2354,7 +2551,7 @@ function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
|
|
|
2354
2551
|
}
|
|
2355
2552
|
|
|
2356
2553
|
// src/components/TimeScale.tsx
|
|
2357
|
-
import { jsx as
|
|
2554
|
+
import { jsx as jsx23, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2358
2555
|
function formatTime2(milliseconds) {
|
|
2359
2556
|
const seconds = Math.floor(milliseconds / 1e3);
|
|
2360
2557
|
const s = seconds % 60;
|
|
@@ -2373,16 +2570,17 @@ var PlaylistTimeScaleScroll = styled21.div.attrs((props) => ({
|
|
|
2373
2570
|
border-bottom: 1px solid ${(props) => props.theme.timeColor};
|
|
2374
2571
|
box-sizing: border-box;
|
|
2375
2572
|
`;
|
|
2376
|
-
var
|
|
2573
|
+
var TimeTickChunk = styled21.canvas.attrs((props) => ({
|
|
2377
2574
|
style: {
|
|
2378
2575
|
width: `${props.$cssWidth}px`,
|
|
2379
|
-
height: `${props.$timeScaleHeight}px
|
|
2576
|
+
height: `${props.$timeScaleHeight}px`,
|
|
2577
|
+
left: `${props.$left}px`
|
|
2380
2578
|
}
|
|
2381
2579
|
}))`
|
|
2382
2580
|
position: absolute;
|
|
2383
|
-
left: 0;
|
|
2384
|
-
right: 0;
|
|
2385
2581
|
bottom: 0;
|
|
2582
|
+
/* Promote to own compositing layer for smoother scrolling */
|
|
2583
|
+
will-change: transform;
|
|
2386
2584
|
`;
|
|
2387
2585
|
var TimeStamp = styled21.div.attrs((props) => ({
|
|
2388
2586
|
style: {
|
|
@@ -2404,60 +2602,111 @@ var TimeScale = (props) => {
|
|
|
2404
2602
|
secondStep,
|
|
2405
2603
|
renderTimestamp
|
|
2406
2604
|
} = props;
|
|
2407
|
-
const
|
|
2408
|
-
const timeMarkers = [];
|
|
2409
|
-
const canvasRef = useRef6(null);
|
|
2605
|
+
const canvasRefsMap = useRef8(/* @__PURE__ */ new Map());
|
|
2410
2606
|
const {
|
|
2411
2607
|
sampleRate,
|
|
2412
2608
|
samplesPerPixel,
|
|
2413
2609
|
timeScaleHeight,
|
|
2414
2610
|
controls: { show: showControls, width: controlWidth }
|
|
2415
|
-
} =
|
|
2611
|
+
} = useContext7(PlaylistInfoContext);
|
|
2416
2612
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2417
|
-
|
|
2418
|
-
if (
|
|
2419
|
-
const
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2613
|
+
const canvasRefCallback = useCallback6((canvas) => {
|
|
2614
|
+
if (canvas !== null) {
|
|
2615
|
+
const idx = parseInt(canvas.dataset.index, 10);
|
|
2616
|
+
canvasRefsMap.current.set(idx, canvas);
|
|
2617
|
+
}
|
|
2618
|
+
}, []);
|
|
2619
|
+
const { widthX, canvasInfo, timeMarkersWithPositions } = useMemo(() => {
|
|
2620
|
+
const nextCanvasInfo = /* @__PURE__ */ new Map();
|
|
2621
|
+
const nextMarkers = [];
|
|
2622
|
+
const nextWidthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);
|
|
2623
|
+
const pixPerSec = sampleRate / samplesPerPixel;
|
|
2624
|
+
let counter = 0;
|
|
2625
|
+
for (let i = 0; i < nextWidthX; i += pixPerSec * secondStep / 1e3) {
|
|
2626
|
+
const pix = Math.floor(i);
|
|
2627
|
+
if (counter % marker === 0) {
|
|
2628
|
+
const timeMs = counter;
|
|
2629
|
+
const timestamp = formatTime2(timeMs);
|
|
2630
|
+
const element = renderTimestamp ? /* @__PURE__ */ jsx23(React15.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ jsx23(TimeStamp, { $left: pix, children: timestamp }, timestamp);
|
|
2631
|
+
nextMarkers.push({ pix, element });
|
|
2632
|
+
nextCanvasInfo.set(pix, timeScaleHeight);
|
|
2633
|
+
} else if (counter % bigStep === 0) {
|
|
2634
|
+
nextCanvasInfo.set(pix, Math.floor(timeScaleHeight / 2));
|
|
2635
|
+
} else if (counter % secondStep === 0) {
|
|
2636
|
+
nextCanvasInfo.set(pix, Math.floor(timeScaleHeight / 5));
|
|
2637
|
+
}
|
|
2638
|
+
counter += secondStep;
|
|
2639
|
+
}
|
|
2640
|
+
return {
|
|
2641
|
+
widthX: nextWidthX,
|
|
2642
|
+
canvasInfo: nextCanvasInfo,
|
|
2643
|
+
timeMarkersWithPositions: nextMarkers
|
|
2644
|
+
};
|
|
2645
|
+
}, [duration, samplesPerPixel, sampleRate, marker, bigStep, secondStep, renderTimestamp, timeScaleHeight]);
|
|
2646
|
+
const visibleChunkKey = useScrollViewportSelector((viewport) => {
|
|
2647
|
+
const totalChunks = Math.ceil(widthX / MAX_CANVAS_WIDTH);
|
|
2648
|
+
const indices = [];
|
|
2649
|
+
for (let i = 0; i < totalChunks; i++) {
|
|
2650
|
+
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
2651
|
+
const chunkWidth = Math.min(widthX - chunkLeft, MAX_CANVAS_WIDTH);
|
|
2652
|
+
if (viewport) {
|
|
2653
|
+
const chunkEnd = chunkLeft + chunkWidth;
|
|
2654
|
+
if (chunkEnd <= viewport.visibleStart || chunkLeft >= viewport.visibleEnd) {
|
|
2655
|
+
continue;
|
|
2430
2656
|
}
|
|
2431
2657
|
}
|
|
2658
|
+
indices.push(i);
|
|
2432
2659
|
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2660
|
+
return indices.join(",");
|
|
2661
|
+
});
|
|
2662
|
+
const visibleChunkIndices = visibleChunkKey ? visibleChunkKey.split(",").map(Number) : [];
|
|
2663
|
+
const visibleChunks = visibleChunkIndices.map((i) => {
|
|
2664
|
+
const chunkLeft = i * MAX_CANVAS_WIDTH;
|
|
2665
|
+
const chunkWidth = Math.min(widthX - chunkLeft, MAX_CANVAS_WIDTH);
|
|
2666
|
+
return /* @__PURE__ */ jsx23(
|
|
2667
|
+
TimeTickChunk,
|
|
2668
|
+
{
|
|
2669
|
+
$cssWidth: chunkWidth,
|
|
2670
|
+
$left: chunkLeft,
|
|
2671
|
+
$timeScaleHeight: timeScaleHeight,
|
|
2672
|
+
width: chunkWidth * devicePixelRatio,
|
|
2673
|
+
height: timeScaleHeight * devicePixelRatio,
|
|
2674
|
+
"data-index": i,
|
|
2675
|
+
ref: canvasRefCallback
|
|
2676
|
+
},
|
|
2677
|
+
`timescale-${i}`
|
|
2678
|
+
);
|
|
2679
|
+
});
|
|
2680
|
+
const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] * MAX_CANVAS_WIDTH : 0;
|
|
2681
|
+
const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) * MAX_CANVAS_WIDTH : Infinity;
|
|
2682
|
+
const visibleMarkers = visibleChunkIndices.length > 0 ? timeMarkersWithPositions.filter(({ pix }) => pix >= firstChunkLeft && pix < lastChunkRight).map(({ element }) => element) : timeMarkersWithPositions.map(({ element }) => element);
|
|
2683
|
+
useEffect7(() => {
|
|
2684
|
+
const currentMap = canvasRefsMap.current;
|
|
2685
|
+
for (const [idx, canvas] of currentMap.entries()) {
|
|
2686
|
+
if (!canvas.isConnected) {
|
|
2687
|
+
currentMap.delete(idx);
|
|
2688
|
+
}
|
|
2458
2689
|
}
|
|
2459
|
-
|
|
2460
|
-
|
|
2690
|
+
});
|
|
2691
|
+
useLayoutEffect4(() => {
|
|
2692
|
+
for (const [chunkIdx, canvas] of canvasRefsMap.current.entries()) {
|
|
2693
|
+
const ctx = canvas.getContext("2d");
|
|
2694
|
+
if (!ctx) continue;
|
|
2695
|
+
const chunkLeft = chunkIdx * MAX_CANVAS_WIDTH;
|
|
2696
|
+
const chunkWidth = canvas.width / devicePixelRatio;
|
|
2697
|
+
ctx.resetTransform();
|
|
2698
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
2699
|
+
ctx.imageSmoothingEnabled = false;
|
|
2700
|
+
ctx.fillStyle = timeColor;
|
|
2701
|
+
ctx.scale(devicePixelRatio, devicePixelRatio);
|
|
2702
|
+
for (const [pixLeft, scaleHeight] of canvasInfo.entries()) {
|
|
2703
|
+
if (pixLeft < chunkLeft || pixLeft >= chunkLeft + chunkWidth) continue;
|
|
2704
|
+
const localX = pixLeft - chunkLeft;
|
|
2705
|
+
const scaleY = timeScaleHeight - scaleHeight;
|
|
2706
|
+
ctx.fillRect(localX, scaleY, 1, scaleHeight);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
}, [duration, devicePixelRatio, timeColor, timeScaleHeight, canvasInfo, visibleChunkKey]);
|
|
2461
2710
|
return /* @__PURE__ */ jsxs10(
|
|
2462
2711
|
PlaylistTimeScaleScroll,
|
|
2463
2712
|
{
|
|
@@ -2465,17 +2714,8 @@ var TimeScale = (props) => {
|
|
|
2465
2714
|
$controlWidth: showControls ? controlWidth : 0,
|
|
2466
2715
|
$timeScaleHeight: timeScaleHeight,
|
|
2467
2716
|
children: [
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
TimeTicks,
|
|
2471
|
-
{
|
|
2472
|
-
$cssWidth: widthX,
|
|
2473
|
-
$timeScaleHeight: timeScaleHeight,
|
|
2474
|
-
width: widthX * devicePixelRatio,
|
|
2475
|
-
height: timeScaleHeight * devicePixelRatio,
|
|
2476
|
-
ref: canvasRef
|
|
2477
|
-
}
|
|
2478
|
-
)
|
|
2717
|
+
visibleMarkers,
|
|
2718
|
+
visibleChunks
|
|
2479
2719
|
]
|
|
2480
2720
|
}
|
|
2481
2721
|
);
|
|
@@ -2483,7 +2723,7 @@ var TimeScale = (props) => {
|
|
|
2483
2723
|
var StyledTimeScale = withTheme2(TimeScale);
|
|
2484
2724
|
|
|
2485
2725
|
// src/components/SmartScale.tsx
|
|
2486
|
-
import { jsx as
|
|
2726
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
2487
2727
|
var timeinfo = /* @__PURE__ */ new Map([
|
|
2488
2728
|
[
|
|
2489
2729
|
700,
|
|
@@ -2557,9 +2797,9 @@ function getScaleInfo(samplesPerPixel) {
|
|
|
2557
2797
|
return config;
|
|
2558
2798
|
}
|
|
2559
2799
|
var SmartScale = ({ renderTimestamp }) => {
|
|
2560
|
-
const { samplesPerPixel, duration } =
|
|
2800
|
+
const { samplesPerPixel, duration } = useContext8(PlaylistInfoContext);
|
|
2561
2801
|
let config = getScaleInfo(samplesPerPixel);
|
|
2562
|
-
return /* @__PURE__ */
|
|
2802
|
+
return /* @__PURE__ */ jsx24(
|
|
2563
2803
|
StyledTimeScale,
|
|
2564
2804
|
{
|
|
2565
2805
|
marker: config.marker,
|
|
@@ -2573,7 +2813,7 @@ var SmartScale = ({ renderTimestamp }) => {
|
|
|
2573
2813
|
|
|
2574
2814
|
// src/components/TimeFormatSelect.tsx
|
|
2575
2815
|
import styled22 from "styled-components";
|
|
2576
|
-
import { jsx as
|
|
2816
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
2577
2817
|
var SelectWrapper = styled22.div`
|
|
2578
2818
|
display: inline-flex;
|
|
2579
2819
|
align-items: center;
|
|
@@ -2596,7 +2836,7 @@ var TimeFormatSelect = ({
|
|
|
2596
2836
|
const handleChange = (e) => {
|
|
2597
2837
|
onChange(e.target.value);
|
|
2598
2838
|
};
|
|
2599
|
-
return /* @__PURE__ */
|
|
2839
|
+
return /* @__PURE__ */ jsx25(SelectWrapper, { className, children: /* @__PURE__ */ jsx25(
|
|
2600
2840
|
BaseSelect,
|
|
2601
2841
|
{
|
|
2602
2842
|
className: "time-format",
|
|
@@ -2604,14 +2844,14 @@ var TimeFormatSelect = ({
|
|
|
2604
2844
|
onChange: handleChange,
|
|
2605
2845
|
disabled,
|
|
2606
2846
|
"aria-label": "Time format selection",
|
|
2607
|
-
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */
|
|
2847
|
+
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsx25("option", { value: option.value, children: option.label }, option.value))
|
|
2608
2848
|
}
|
|
2609
2849
|
) });
|
|
2610
2850
|
};
|
|
2611
2851
|
|
|
2612
2852
|
// src/components/Track.tsx
|
|
2613
2853
|
import styled23 from "styled-components";
|
|
2614
|
-
import { jsx as
|
|
2854
|
+
import { jsx as jsx26, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2615
2855
|
var Container = styled23.div.attrs((props) => ({
|
|
2616
2856
|
style: {
|
|
2617
2857
|
height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`
|
|
@@ -2677,7 +2917,7 @@ var Track = ({
|
|
|
2677
2917
|
$hasClipHeaders: hasClipHeaders,
|
|
2678
2918
|
$isSelected: isSelected,
|
|
2679
2919
|
children: [
|
|
2680
|
-
/* @__PURE__ */
|
|
2920
|
+
/* @__PURE__ */ jsx26(
|
|
2681
2921
|
ControlsWrapper,
|
|
2682
2922
|
{
|
|
2683
2923
|
$controlWidth: show ? controlWidth : 0,
|
|
@@ -2685,7 +2925,7 @@ var Track = ({
|
|
|
2685
2925
|
children: controls
|
|
2686
2926
|
}
|
|
2687
2927
|
),
|
|
2688
|
-
/* @__PURE__ */
|
|
2928
|
+
/* @__PURE__ */ jsx26(
|
|
2689
2929
|
ChannelContainer,
|
|
2690
2930
|
{
|
|
2691
2931
|
$controlWidth: show ? controlWidth : 0,
|
|
@@ -2793,7 +3033,7 @@ var ButtonGroup = styled25.div`
|
|
|
2793
3033
|
// src/components/TrackControls/CloseButton.tsx
|
|
2794
3034
|
import styled26 from "styled-components";
|
|
2795
3035
|
import { X as XIcon } from "@phosphor-icons/react";
|
|
2796
|
-
import { jsx as
|
|
3036
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
2797
3037
|
var StyledCloseButton = styled26.button`
|
|
2798
3038
|
position: absolute;
|
|
2799
3039
|
left: 0;
|
|
@@ -2818,7 +3058,7 @@ var StyledCloseButton = styled26.button`
|
|
|
2818
3058
|
var CloseButton = ({
|
|
2819
3059
|
onClick,
|
|
2820
3060
|
title = "Remove track"
|
|
2821
|
-
}) => /* @__PURE__ */
|
|
3061
|
+
}) => /* @__PURE__ */ jsx27(StyledCloseButton, { onClick, title, children: /* @__PURE__ */ jsx27(XIcon, { size: 12, weight: "bold" }) });
|
|
2822
3062
|
|
|
2823
3063
|
// src/components/TrackControls/Controls.tsx
|
|
2824
3064
|
import styled27 from "styled-components";
|
|
@@ -2854,23 +3094,23 @@ var Header = styled28.header`
|
|
|
2854
3094
|
|
|
2855
3095
|
// src/components/TrackControls/VolumeDownIcon.tsx
|
|
2856
3096
|
import { SpeakerLowIcon } from "@phosphor-icons/react";
|
|
2857
|
-
import { jsx as
|
|
2858
|
-
var VolumeDownIcon = (props) => /* @__PURE__ */
|
|
3097
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
3098
|
+
var VolumeDownIcon = (props) => /* @__PURE__ */ jsx28(SpeakerLowIcon, { weight: "light", ...props });
|
|
2859
3099
|
|
|
2860
3100
|
// src/components/TrackControls/VolumeUpIcon.tsx
|
|
2861
3101
|
import { SpeakerHighIcon } from "@phosphor-icons/react";
|
|
2862
|
-
import { jsx as
|
|
2863
|
-
var VolumeUpIcon = (props) => /* @__PURE__ */
|
|
3102
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
3103
|
+
var VolumeUpIcon = (props) => /* @__PURE__ */ jsx29(SpeakerHighIcon, { weight: "light", ...props });
|
|
2864
3104
|
|
|
2865
3105
|
// src/components/TrackControls/TrashIcon.tsx
|
|
2866
3106
|
import { TrashIcon as PhosphorTrashIcon } from "@phosphor-icons/react";
|
|
2867
|
-
import { jsx as
|
|
2868
|
-
var TrashIcon = (props) => /* @__PURE__ */
|
|
3107
|
+
import { jsx as jsx30 } from "react/jsx-runtime";
|
|
3108
|
+
var TrashIcon = (props) => /* @__PURE__ */ jsx30(PhosphorTrashIcon, { weight: "light", ...props });
|
|
2869
3109
|
|
|
2870
3110
|
// src/components/TrackControls/DotsIcon.tsx
|
|
2871
3111
|
import { DotsThreeIcon } from "@phosphor-icons/react";
|
|
2872
|
-
import { jsx as
|
|
2873
|
-
var DotsIcon = (props) => /* @__PURE__ */
|
|
3112
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
3113
|
+
var DotsIcon = (props) => /* @__PURE__ */ jsx31(DotsThreeIcon, { weight: "bold", ...props });
|
|
2874
3114
|
|
|
2875
3115
|
// src/components/TrackControls/Slider.tsx
|
|
2876
3116
|
import styled29 from "styled-components";
|
|
@@ -2938,10 +3178,10 @@ var SliderWrapper = styled30.label`
|
|
|
2938
3178
|
`;
|
|
2939
3179
|
|
|
2940
3180
|
// src/components/TrackMenu.tsx
|
|
2941
|
-
import
|
|
3181
|
+
import React17, { useState as useState6, useEffect as useEffect8, useRef as useRef9 } from "react";
|
|
2942
3182
|
import { createPortal } from "react-dom";
|
|
2943
3183
|
import styled31 from "styled-components";
|
|
2944
|
-
import { jsx as
|
|
3184
|
+
import { jsx as jsx32, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2945
3185
|
var MenuContainer = styled31.div`
|
|
2946
3186
|
position: relative;
|
|
2947
3187
|
display: inline-block;
|
|
@@ -2986,9 +3226,9 @@ var TrackMenu = ({
|
|
|
2986
3226
|
const close = () => setOpen(false);
|
|
2987
3227
|
const items = typeof itemsProp === "function" ? itemsProp(close) : itemsProp;
|
|
2988
3228
|
const [dropdownPos, setDropdownPos] = useState6({ top: 0, left: 0 });
|
|
2989
|
-
const buttonRef =
|
|
2990
|
-
const dropdownRef =
|
|
2991
|
-
|
|
3229
|
+
const buttonRef = useRef9(null);
|
|
3230
|
+
const dropdownRef = useRef9(null);
|
|
3231
|
+
useEffect8(() => {
|
|
2992
3232
|
if (open && buttonRef.current) {
|
|
2993
3233
|
const rect = buttonRef.current.getBoundingClientRect();
|
|
2994
3234
|
setDropdownPos({
|
|
@@ -2997,7 +3237,7 @@ var TrackMenu = ({
|
|
|
2997
3237
|
});
|
|
2998
3238
|
}
|
|
2999
3239
|
}, [open]);
|
|
3000
|
-
|
|
3240
|
+
useEffect8(() => {
|
|
3001
3241
|
if (!open) return;
|
|
3002
3242
|
const handleClick = (e) => {
|
|
3003
3243
|
const target = e.target;
|
|
@@ -3009,7 +3249,7 @@ var TrackMenu = ({
|
|
|
3009
3249
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
3010
3250
|
}, [open]);
|
|
3011
3251
|
return /* @__PURE__ */ jsxs12(MenuContainer, { children: [
|
|
3012
|
-
/* @__PURE__ */
|
|
3252
|
+
/* @__PURE__ */ jsx32(
|
|
3013
3253
|
MenuButton,
|
|
3014
3254
|
{
|
|
3015
3255
|
ref: buttonRef,
|
|
@@ -3020,19 +3260,19 @@ var TrackMenu = ({
|
|
|
3020
3260
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3021
3261
|
title: "Track menu",
|
|
3022
3262
|
"aria-label": "Track menu",
|
|
3023
|
-
children: /* @__PURE__ */
|
|
3263
|
+
children: /* @__PURE__ */ jsx32(DotsIcon, { size: 16 })
|
|
3024
3264
|
}
|
|
3025
3265
|
),
|
|
3026
3266
|
open && typeof document !== "undefined" && createPortal(
|
|
3027
|
-
/* @__PURE__ */
|
|
3267
|
+
/* @__PURE__ */ jsx32(
|
|
3028
3268
|
Dropdown,
|
|
3029
3269
|
{
|
|
3030
3270
|
ref: dropdownRef,
|
|
3031
3271
|
$top: dropdownPos.top,
|
|
3032
3272
|
$left: dropdownPos.left,
|
|
3033
3273
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3034
|
-
children: items.map((item, index) => /* @__PURE__ */ jsxs12(
|
|
3035
|
-
index > 0 && /* @__PURE__ */
|
|
3274
|
+
children: items.map((item, index) => /* @__PURE__ */ jsxs12(React17.Fragment, { children: [
|
|
3275
|
+
index > 0 && /* @__PURE__ */ jsx32(Divider, {}),
|
|
3036
3276
|
item.content
|
|
3037
3277
|
] }, item.id))
|
|
3038
3278
|
}
|
|
@@ -3072,6 +3312,7 @@ export {
|
|
|
3072
3312
|
InlineLabel,
|
|
3073
3313
|
LoopRegion,
|
|
3074
3314
|
LoopRegionMarkers,
|
|
3315
|
+
MAX_CANVAS_WIDTH,
|
|
3075
3316
|
MasterVolumeControl,
|
|
3076
3317
|
Playhead,
|
|
3077
3318
|
PlayheadWithMarker,
|
|
@@ -3080,6 +3321,7 @@ export {
|
|
|
3080
3321
|
PlaylistInfoContext,
|
|
3081
3322
|
PlayoutProvider,
|
|
3082
3323
|
ScreenReaderOnly,
|
|
3324
|
+
ScrollViewportProvider,
|
|
3083
3325
|
Selection,
|
|
3084
3326
|
SelectionTimeInputs,
|
|
3085
3327
|
Slider,
|
|
@@ -3115,6 +3357,8 @@ export {
|
|
|
3115
3357
|
usePlaylistInfo,
|
|
3116
3358
|
usePlayoutStatus,
|
|
3117
3359
|
usePlayoutStatusUpdate,
|
|
3360
|
+
useScrollViewport,
|
|
3361
|
+
useScrollViewportSelector,
|
|
3118
3362
|
useTheme2 as useTheme,
|
|
3119
3363
|
useTrackControls,
|
|
3120
3364
|
waveformColorToCss
|