@waveform-playlist/ui-components 5.0.0-alpha.1 → 5.0.0-alpha.10
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 +69 -1
- package/dist/index.d.ts +69 -1
- package/dist/index.js +477 -119
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +451 -97
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -359,6 +359,10 @@ var defaultTheme = {
|
|
|
359
359
|
playheadColor: "#f00",
|
|
360
360
|
selectionColor: "rgba(255, 105, 180, 0.7)",
|
|
361
361
|
// hot pink - high contrast on light backgrounds
|
|
362
|
+
loopRegionColor: "rgba(59, 130, 246, 0.3)",
|
|
363
|
+
// Blue - distinct from pink selection
|
|
364
|
+
loopMarkerColor: "#3b82f6",
|
|
365
|
+
// Blue marker triangles
|
|
362
366
|
clipHeaderBackgroundColor: "rgba(0, 0, 0, 0.1)",
|
|
363
367
|
clipHeaderBorderColor: "rgba(0, 0, 0, 0.2)",
|
|
364
368
|
clipHeaderTextColor: "#333",
|
|
@@ -430,6 +434,10 @@ var darkTheme = {
|
|
|
430
434
|
// Darker Ampelmännchen green playhead
|
|
431
435
|
selectionColor: "rgba(60, 140, 58, 0.6)",
|
|
432
436
|
// Darker Ampelmännchen green selection - visible on dark backgrounds
|
|
437
|
+
loopRegionColor: "rgba(96, 165, 250, 0.35)",
|
|
438
|
+
// Light blue - distinct from green selection
|
|
439
|
+
loopMarkerColor: "#60a5fa",
|
|
440
|
+
// Light blue marker triangles
|
|
433
441
|
clipHeaderBackgroundColor: "rgba(20, 16, 12, 0.85)",
|
|
434
442
|
// Dark background for clip headers
|
|
435
443
|
clipHeaderBorderColor: "rgba(200, 160, 120, 0.25)",
|
|
@@ -670,6 +678,7 @@ var HeaderContainer = styled10.div`
|
|
|
670
678
|
z-index: 110;
|
|
671
679
|
flex-shrink: 0;
|
|
672
680
|
pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */
|
|
681
|
+
touch-action: ${(props) => props.$interactive ? "none" : "auto"}; /* Prevent browser scroll during drag on touch devices */
|
|
673
682
|
|
|
674
683
|
${(props) => props.$interactive && `
|
|
675
684
|
&:hover {
|
|
@@ -742,16 +751,18 @@ import React2 from "react";
|
|
|
742
751
|
import styled11 from "styled-components";
|
|
743
752
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
744
753
|
var CLIP_BOUNDARY_WIDTH = 8;
|
|
754
|
+
var CLIP_BOUNDARY_WIDTH_TOUCH = 24;
|
|
745
755
|
var BoundaryContainer = styled11.div`
|
|
746
756
|
position: absolute;
|
|
747
757
|
${(props) => props.$edge === "left" ? "left: 0;" : "right: 0;"}
|
|
748
758
|
top: 0;
|
|
749
759
|
bottom: 0;
|
|
750
|
-
width: ${CLIP_BOUNDARY_WIDTH}px;
|
|
760
|
+
width: ${(props) => props.$touchOptimized ? CLIP_BOUNDARY_WIDTH_TOUCH : CLIP_BOUNDARY_WIDTH}px;
|
|
751
761
|
cursor: col-resize;
|
|
752
762
|
user-select: none;
|
|
753
763
|
z-index: 105; /* Above waveform, below header */
|
|
754
764
|
pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */
|
|
765
|
+
touch-action: none; /* Prevent browser scroll during drag on touch devices */
|
|
755
766
|
|
|
756
767
|
/* Invisible by default, visible on hover */
|
|
757
768
|
background: ${(props) => props.$isDragging ? "rgba(255, 255, 255, 0.4)" : props.$isHovered ? "rgba(255, 255, 255, 0.2)" : "transparent"};
|
|
@@ -775,7 +786,8 @@ var ClipBoundary = ({
|
|
|
775
786
|
trackIndex,
|
|
776
787
|
clipIndex,
|
|
777
788
|
edge,
|
|
778
|
-
dragHandleProps
|
|
789
|
+
dragHandleProps,
|
|
790
|
+
touchOptimized = false
|
|
779
791
|
}) => {
|
|
780
792
|
const [isHovered, setIsHovered] = React2.useState(false);
|
|
781
793
|
if (!dragHandleProps) {
|
|
@@ -791,6 +803,7 @@ var ClipBoundary = ({
|
|
|
791
803
|
$edge: edge,
|
|
792
804
|
$isDragging: isDragging,
|
|
793
805
|
$isHovered: isHovered,
|
|
806
|
+
$touchOptimized: touchOptimized,
|
|
794
807
|
onMouseEnter: () => setIsHovered(true),
|
|
795
808
|
onMouseLeave: () => setIsHovered(false),
|
|
796
809
|
...listeners,
|
|
@@ -913,7 +926,8 @@ var Clip = ({
|
|
|
913
926
|
fadeIn,
|
|
914
927
|
fadeOut,
|
|
915
928
|
sampleRate = 44100,
|
|
916
|
-
showFades = false
|
|
929
|
+
showFades = false,
|
|
930
|
+
touchOptimized = false
|
|
917
931
|
}) => {
|
|
918
932
|
const left = Math.floor(startSample / samplesPerPixel);
|
|
919
933
|
const endPixel = Math.floor((startSample + durationSamples) / samplesPerPixel);
|
|
@@ -1006,6 +1020,7 @@ var Clip = ({
|
|
|
1006
1020
|
trackIndex,
|
|
1007
1021
|
clipIndex,
|
|
1008
1022
|
edge: "left",
|
|
1023
|
+
touchOptimized,
|
|
1009
1024
|
dragHandleProps: {
|
|
1010
1025
|
attributes: leftBoundaryAttributes,
|
|
1011
1026
|
listeners: leftBoundaryListeners,
|
|
@@ -1021,6 +1036,7 @@ var Clip = ({
|
|
|
1021
1036
|
trackIndex,
|
|
1022
1037
|
clipIndex,
|
|
1023
1038
|
edge: "right",
|
|
1039
|
+
touchOptimized,
|
|
1024
1040
|
dragHandleProps: {
|
|
1025
1041
|
attributes: rightBoundaryAttributes,
|
|
1026
1042
|
listeners: rightBoundaryListeners,
|
|
@@ -1198,7 +1214,8 @@ var TimescaleWrapper = styled16.div.attrs((props) => ({
|
|
|
1198
1214
|
}))`
|
|
1199
1215
|
background: ${(props) => props.$backgroundColor || "white"};
|
|
1200
1216
|
width: 100%;
|
|
1201
|
-
|
|
1217
|
+
position: relative;
|
|
1218
|
+
overflow: hidden; /* Constrain loop region to timescale area */
|
|
1202
1219
|
`;
|
|
1203
1220
|
var TracksContainer = styled16.div.attrs((props) => ({
|
|
1204
1221
|
style: props.$width !== void 0 ? { minWidth: `${props.$width}px` } : {}
|
|
@@ -1214,7 +1231,8 @@ var ClickOverlay = styled16.div`
|
|
|
1214
1231
|
right: 0;
|
|
1215
1232
|
bottom: 0;
|
|
1216
1233
|
cursor: crosshair;
|
|
1217
|
-
|
|
1234
|
+
/* When selecting, raise z-index above clip boundaries (z-index: 105) to prevent interference */
|
|
1235
|
+
z-index: ${(props) => props.$isSelecting ? 110 : 1};
|
|
1218
1236
|
`;
|
|
1219
1237
|
var Playlist = ({
|
|
1220
1238
|
children,
|
|
@@ -1229,7 +1247,8 @@ var Playlist = ({
|
|
|
1229
1247
|
onTracksMouseDown,
|
|
1230
1248
|
onTracksMouseMove,
|
|
1231
1249
|
onTracksMouseUp,
|
|
1232
|
-
scrollContainerRef
|
|
1250
|
+
scrollContainerRef,
|
|
1251
|
+
isSelecting
|
|
1233
1252
|
}) => {
|
|
1234
1253
|
return /* @__PURE__ */ jsx10(Wrapper2, { "data-scroll-container": "true", ref: scrollContainerRef, children: /* @__PURE__ */ jsxs5(
|
|
1235
1254
|
ScrollContainer,
|
|
@@ -1244,6 +1263,7 @@ var Playlist = ({
|
|
|
1244
1263
|
ClickOverlay,
|
|
1245
1264
|
{
|
|
1246
1265
|
$controlsWidth: controlsWidth,
|
|
1266
|
+
$isSelecting: isSelecting,
|
|
1247
1267
|
onClick: onTracksClick,
|
|
1248
1268
|
onMouseDown: onTracksMouseDown,
|
|
1249
1269
|
onMouseMove: onTracksMouseMove,
|
|
@@ -1286,11 +1306,341 @@ var Selection = ({
|
|
|
1286
1306
|
return /* @__PURE__ */ jsx11(SelectionOverlay, { $left: startPosition, $width: width, $color: color, "data-selection": true });
|
|
1287
1307
|
};
|
|
1288
1308
|
|
|
1309
|
+
// src/components/LoopRegion.tsx
|
|
1310
|
+
import { useCallback as useCallback2, useRef as useRef3, useState } from "react";
|
|
1311
|
+
import styled18 from "styled-components";
|
|
1312
|
+
import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1313
|
+
var LoopRegionOverlayDiv = styled18.div.attrs((props) => ({
|
|
1314
|
+
style: {
|
|
1315
|
+
left: `${props.$left}px`,
|
|
1316
|
+
width: `${props.$width}px`
|
|
1317
|
+
}
|
|
1318
|
+
}))`
|
|
1319
|
+
position: absolute;
|
|
1320
|
+
top: 0;
|
|
1321
|
+
background: ${(props) => props.$color};
|
|
1322
|
+
height: 100%;
|
|
1323
|
+
z-index: 55; /* Between clips (z-index: 50) and selection (z-index: 60) */
|
|
1324
|
+
pointer-events: none;
|
|
1325
|
+
`;
|
|
1326
|
+
var LoopMarker = styled18.div.attrs((props) => ({
|
|
1327
|
+
style: {
|
|
1328
|
+
left: `${props.$left}px`
|
|
1329
|
+
}
|
|
1330
|
+
}))`
|
|
1331
|
+
position: absolute;
|
|
1332
|
+
top: 0;
|
|
1333
|
+
width: 2px;
|
|
1334
|
+
height: 100%;
|
|
1335
|
+
background: ${(props) => props.$color};
|
|
1336
|
+
z-index: 90; /* Below playhead (z-index: 100) */
|
|
1337
|
+
pointer-events: none;
|
|
1338
|
+
|
|
1339
|
+
/* Triangle marker at top */
|
|
1340
|
+
&::before {
|
|
1341
|
+
content: '';
|
|
1342
|
+
position: absolute;
|
|
1343
|
+
top: 0;
|
|
1344
|
+
${(props) => props.$isStart ? "left: 0" : "right: 0"};
|
|
1345
|
+
width: 0;
|
|
1346
|
+
height: 0;
|
|
1347
|
+
border-top: 8px solid ${(props) => props.$color};
|
|
1348
|
+
${(props) => props.$isStart ? "border-right: 8px solid transparent;" : "border-left: 8px solid transparent;"}
|
|
1349
|
+
}
|
|
1350
|
+
`;
|
|
1351
|
+
var LoopRegion = ({
|
|
1352
|
+
startPosition,
|
|
1353
|
+
endPosition,
|
|
1354
|
+
regionColor = "rgba(59, 130, 246, 0.3)",
|
|
1355
|
+
markerColor = "#3b82f6"
|
|
1356
|
+
}) => {
|
|
1357
|
+
const width = Math.max(0, endPosition - startPosition);
|
|
1358
|
+
if (width <= 0) {
|
|
1359
|
+
return null;
|
|
1360
|
+
}
|
|
1361
|
+
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1362
|
+
/* @__PURE__ */ jsx12(
|
|
1363
|
+
LoopRegionOverlayDiv,
|
|
1364
|
+
{
|
|
1365
|
+
$left: startPosition,
|
|
1366
|
+
$width: width,
|
|
1367
|
+
$color: regionColor,
|
|
1368
|
+
"data-loop-region": true
|
|
1369
|
+
}
|
|
1370
|
+
),
|
|
1371
|
+
/* @__PURE__ */ jsx12(
|
|
1372
|
+
LoopMarker,
|
|
1373
|
+
{
|
|
1374
|
+
$left: startPosition,
|
|
1375
|
+
$color: markerColor,
|
|
1376
|
+
$isStart: true,
|
|
1377
|
+
"data-loop-marker": "start"
|
|
1378
|
+
}
|
|
1379
|
+
),
|
|
1380
|
+
/* @__PURE__ */ jsx12(
|
|
1381
|
+
LoopMarker,
|
|
1382
|
+
{
|
|
1383
|
+
$left: endPosition - 2,
|
|
1384
|
+
$color: markerColor,
|
|
1385
|
+
$isStart: false,
|
|
1386
|
+
"data-loop-marker": "end"
|
|
1387
|
+
}
|
|
1388
|
+
)
|
|
1389
|
+
] });
|
|
1390
|
+
};
|
|
1391
|
+
var DraggableMarkerHandle = styled18.div.attrs((props) => ({
|
|
1392
|
+
style: {
|
|
1393
|
+
left: `${props.$left}px`
|
|
1394
|
+
}
|
|
1395
|
+
}))`
|
|
1396
|
+
position: absolute;
|
|
1397
|
+
top: 0;
|
|
1398
|
+
width: 12px;
|
|
1399
|
+
height: 100%;
|
|
1400
|
+
cursor: ew-resize;
|
|
1401
|
+
z-index: 100;
|
|
1402
|
+
/* Center the handle on the marker position */
|
|
1403
|
+
transform: translateX(-5px);
|
|
1404
|
+
|
|
1405
|
+
/* Visual marker line */
|
|
1406
|
+
&::before {
|
|
1407
|
+
content: '';
|
|
1408
|
+
position: absolute;
|
|
1409
|
+
top: 0;
|
|
1410
|
+
left: 5px;
|
|
1411
|
+
width: 2px;
|
|
1412
|
+
height: 100%;
|
|
1413
|
+
background: ${(props) => props.$color};
|
|
1414
|
+
opacity: ${(props) => props.$isDragging ? 1 : 0.8};
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
/* Triangle marker at top */
|
|
1418
|
+
&::after {
|
|
1419
|
+
content: '';
|
|
1420
|
+
position: absolute;
|
|
1421
|
+
top: 0;
|
|
1422
|
+
${(props) => props.$isStart ? "left: 5px" : "left: -1px"};
|
|
1423
|
+
width: 0;
|
|
1424
|
+
height: 0;
|
|
1425
|
+
border-top: 10px solid ${(props) => props.$color};
|
|
1426
|
+
${(props) => props.$isStart ? "border-right: 10px solid transparent;" : "border-left: 10px solid transparent;"}
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
&:hover::before {
|
|
1430
|
+
opacity: 1;
|
|
1431
|
+
}
|
|
1432
|
+
`;
|
|
1433
|
+
var TimescaleLoopShade = styled18.div.attrs((props) => ({
|
|
1434
|
+
style: {
|
|
1435
|
+
left: `${props.$left}px`,
|
|
1436
|
+
width: `${props.$width}px`
|
|
1437
|
+
}
|
|
1438
|
+
}))`
|
|
1439
|
+
position: absolute;
|
|
1440
|
+
top: 0;
|
|
1441
|
+
height: 100%;
|
|
1442
|
+
background: ${(props) => props.$color};
|
|
1443
|
+
z-index: 50;
|
|
1444
|
+
cursor: grab;
|
|
1445
|
+
|
|
1446
|
+
&:active {
|
|
1447
|
+
cursor: grabbing;
|
|
1448
|
+
}
|
|
1449
|
+
`;
|
|
1450
|
+
var LoopRegionMarkers = ({
|
|
1451
|
+
startPosition,
|
|
1452
|
+
endPosition,
|
|
1453
|
+
markerColor = "#3b82f6",
|
|
1454
|
+
regionColor = "rgba(59, 130, 246, 0.3)",
|
|
1455
|
+
onLoopStartChange,
|
|
1456
|
+
onLoopEndChange,
|
|
1457
|
+
onLoopRegionMove,
|
|
1458
|
+
minPosition = 0,
|
|
1459
|
+
maxPosition = Infinity
|
|
1460
|
+
}) => {
|
|
1461
|
+
const [draggingMarker, setDraggingMarker] = useState(null);
|
|
1462
|
+
const dragStartX = useRef3(0);
|
|
1463
|
+
const dragStartPosition = useRef3(0);
|
|
1464
|
+
const dragStartEnd = useRef3(0);
|
|
1465
|
+
const width = Math.max(0, endPosition - startPosition);
|
|
1466
|
+
const handleMarkerMouseDown = useCallback2((e, marker) => {
|
|
1467
|
+
e.preventDefault();
|
|
1468
|
+
e.stopPropagation();
|
|
1469
|
+
setDraggingMarker(marker);
|
|
1470
|
+
dragStartX.current = e.clientX;
|
|
1471
|
+
dragStartPosition.current = marker === "start" ? startPosition : endPosition;
|
|
1472
|
+
const handleMouseMove = (moveEvent) => {
|
|
1473
|
+
const delta = moveEvent.clientX - dragStartX.current;
|
|
1474
|
+
const newPosition = dragStartPosition.current + delta;
|
|
1475
|
+
if (marker === "start") {
|
|
1476
|
+
const clampedPosition = Math.max(minPosition, Math.min(endPosition - 10, newPosition));
|
|
1477
|
+
onLoopStartChange?.(clampedPosition);
|
|
1478
|
+
} else {
|
|
1479
|
+
const clampedPosition = Math.max(startPosition + 10, Math.min(maxPosition, newPosition));
|
|
1480
|
+
onLoopEndChange?.(clampedPosition);
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
const handleMouseUp = () => {
|
|
1484
|
+
setDraggingMarker(null);
|
|
1485
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1486
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
1487
|
+
};
|
|
1488
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1489
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
1490
|
+
}, [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]);
|
|
1491
|
+
const handleRegionMouseDown = useCallback2((e) => {
|
|
1492
|
+
e.preventDefault();
|
|
1493
|
+
e.stopPropagation();
|
|
1494
|
+
setDraggingMarker("region");
|
|
1495
|
+
dragStartX.current = e.clientX;
|
|
1496
|
+
dragStartPosition.current = startPosition;
|
|
1497
|
+
dragStartEnd.current = endPosition;
|
|
1498
|
+
const regionWidth = endPosition - startPosition;
|
|
1499
|
+
const handleMouseMove = (moveEvent) => {
|
|
1500
|
+
const delta = moveEvent.clientX - dragStartX.current;
|
|
1501
|
+
let newStart = dragStartPosition.current + delta;
|
|
1502
|
+
let newEnd = dragStartEnd.current + delta;
|
|
1503
|
+
if (newStart < minPosition) {
|
|
1504
|
+
newStart = minPosition;
|
|
1505
|
+
newEnd = minPosition + regionWidth;
|
|
1506
|
+
}
|
|
1507
|
+
if (newEnd > maxPosition) {
|
|
1508
|
+
newEnd = maxPosition;
|
|
1509
|
+
newStart = maxPosition - regionWidth;
|
|
1510
|
+
}
|
|
1511
|
+
onLoopRegionMove?.(newStart, newEnd);
|
|
1512
|
+
};
|
|
1513
|
+
const handleMouseUp = () => {
|
|
1514
|
+
setDraggingMarker(null);
|
|
1515
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1516
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
1517
|
+
};
|
|
1518
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1519
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
1520
|
+
}, [startPosition, endPosition, minPosition, maxPosition, onLoopRegionMove]);
|
|
1521
|
+
if (width <= 0) {
|
|
1522
|
+
return null;
|
|
1523
|
+
}
|
|
1524
|
+
return /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1525
|
+
/* @__PURE__ */ jsx12(
|
|
1526
|
+
TimescaleLoopShade,
|
|
1527
|
+
{
|
|
1528
|
+
$left: startPosition,
|
|
1529
|
+
$width: width,
|
|
1530
|
+
$color: regionColor,
|
|
1531
|
+
$isDragging: draggingMarker === "region",
|
|
1532
|
+
onMouseDown: handleRegionMouseDown,
|
|
1533
|
+
"data-loop-region-timescale": true
|
|
1534
|
+
}
|
|
1535
|
+
),
|
|
1536
|
+
/* @__PURE__ */ jsx12(
|
|
1537
|
+
DraggableMarkerHandle,
|
|
1538
|
+
{
|
|
1539
|
+
$left: startPosition,
|
|
1540
|
+
$color: markerColor,
|
|
1541
|
+
$isStart: true,
|
|
1542
|
+
$isDragging: draggingMarker === "start",
|
|
1543
|
+
onMouseDown: (e) => handleMarkerMouseDown(e, "start"),
|
|
1544
|
+
"data-loop-marker-handle": "start"
|
|
1545
|
+
}
|
|
1546
|
+
),
|
|
1547
|
+
/* @__PURE__ */ jsx12(
|
|
1548
|
+
DraggableMarkerHandle,
|
|
1549
|
+
{
|
|
1550
|
+
$left: endPosition,
|
|
1551
|
+
$color: markerColor,
|
|
1552
|
+
$isStart: false,
|
|
1553
|
+
$isDragging: draggingMarker === "end",
|
|
1554
|
+
onMouseDown: (e) => handleMarkerMouseDown(e, "end"),
|
|
1555
|
+
"data-loop-marker-handle": "end"
|
|
1556
|
+
}
|
|
1557
|
+
)
|
|
1558
|
+
] });
|
|
1559
|
+
};
|
|
1560
|
+
var TimescaleLoopCreator = styled18.div.attrs((props) => ({
|
|
1561
|
+
style: {
|
|
1562
|
+
left: `${props.$leftOffset || 0}px`
|
|
1563
|
+
}
|
|
1564
|
+
}))`
|
|
1565
|
+
position: absolute;
|
|
1566
|
+
top: 0;
|
|
1567
|
+
right: 0;
|
|
1568
|
+
height: 100%; /* Stay within timescale bounds, don't extend into tracks */
|
|
1569
|
+
cursor: crosshair;
|
|
1570
|
+
z-index: 40; /* Below markers and shading */
|
|
1571
|
+
`;
|
|
1572
|
+
var TimescaleLoopRegion = ({
|
|
1573
|
+
startPosition,
|
|
1574
|
+
endPosition,
|
|
1575
|
+
markerColor = "#3b82f6",
|
|
1576
|
+
regionColor = "rgba(59, 130, 246, 0.3)",
|
|
1577
|
+
onLoopRegionChange,
|
|
1578
|
+
minPosition = 0,
|
|
1579
|
+
maxPosition = Infinity,
|
|
1580
|
+
controlsOffset = 0
|
|
1581
|
+
}) => {
|
|
1582
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
1583
|
+
const createStartX = useRef3(0);
|
|
1584
|
+
const containerRef = useRef3(null);
|
|
1585
|
+
const hasLoopRegion = endPosition > startPosition;
|
|
1586
|
+
const handleBackgroundMouseDown = useCallback2((e) => {
|
|
1587
|
+
const target = e.target;
|
|
1588
|
+
if (target.closest("[data-loop-marker-handle]") || target.closest("[data-loop-region-timescale]")) {
|
|
1589
|
+
return;
|
|
1590
|
+
}
|
|
1591
|
+
e.preventDefault();
|
|
1592
|
+
setIsCreating(true);
|
|
1593
|
+
const rect = containerRef.current?.getBoundingClientRect();
|
|
1594
|
+
if (!rect) return;
|
|
1595
|
+
const clickX = e.clientX - rect.left;
|
|
1596
|
+
const clampedX = Math.max(minPosition, Math.min(maxPosition, clickX));
|
|
1597
|
+
createStartX.current = clampedX;
|
|
1598
|
+
onLoopRegionChange?.(clampedX, clampedX);
|
|
1599
|
+
const handleMouseMove = (moveEvent) => {
|
|
1600
|
+
const currentX = moveEvent.clientX - rect.left;
|
|
1601
|
+
const clampedCurrentX = Math.max(minPosition, Math.min(maxPosition, currentX));
|
|
1602
|
+
const newStart = Math.min(createStartX.current, clampedCurrentX);
|
|
1603
|
+
const newEnd = Math.max(createStartX.current, clampedCurrentX);
|
|
1604
|
+
onLoopRegionChange?.(newStart, newEnd);
|
|
1605
|
+
};
|
|
1606
|
+
const handleMouseUp = () => {
|
|
1607
|
+
setIsCreating(false);
|
|
1608
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
1609
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
1610
|
+
};
|
|
1611
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
1612
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
1613
|
+
}, [minPosition, maxPosition, onLoopRegionChange]);
|
|
1614
|
+
return /* @__PURE__ */ jsx12(
|
|
1615
|
+
TimescaleLoopCreator,
|
|
1616
|
+
{
|
|
1617
|
+
ref: containerRef,
|
|
1618
|
+
$leftOffset: controlsOffset,
|
|
1619
|
+
onMouseDown: handleBackgroundMouseDown,
|
|
1620
|
+
"data-timescale-loop-creator": true,
|
|
1621
|
+
children: hasLoopRegion && /* @__PURE__ */ jsx12(
|
|
1622
|
+
LoopRegionMarkers,
|
|
1623
|
+
{
|
|
1624
|
+
startPosition,
|
|
1625
|
+
endPosition,
|
|
1626
|
+
markerColor,
|
|
1627
|
+
regionColor,
|
|
1628
|
+
minPosition,
|
|
1629
|
+
maxPosition,
|
|
1630
|
+
onLoopStartChange: (newStart) => onLoopRegionChange?.(newStart, endPosition),
|
|
1631
|
+
onLoopEndChange: (newEnd) => onLoopRegionChange?.(startPosition, newEnd),
|
|
1632
|
+
onLoopRegionMove: (newStart, newEnd) => onLoopRegionChange?.(newStart, newEnd)
|
|
1633
|
+
}
|
|
1634
|
+
)
|
|
1635
|
+
}
|
|
1636
|
+
);
|
|
1637
|
+
};
|
|
1638
|
+
|
|
1289
1639
|
// src/components/SelectionTimeInputs.tsx
|
|
1290
|
-
import { useEffect as useEffect3, useState as
|
|
1640
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
1291
1641
|
|
|
1292
1642
|
// src/components/TimeInput.tsx
|
|
1293
|
-
import { useEffect as useEffect2, useState } from "react";
|
|
1643
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1294
1644
|
|
|
1295
1645
|
// src/utils/timeFormat.ts
|
|
1296
1646
|
function clockFormat(seconds, decimals) {
|
|
@@ -1340,7 +1690,7 @@ function parseTime(timeStr, format) {
|
|
|
1340
1690
|
}
|
|
1341
1691
|
|
|
1342
1692
|
// src/components/TimeInput.tsx
|
|
1343
|
-
import { Fragment as
|
|
1693
|
+
import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1344
1694
|
var TimeInput = ({
|
|
1345
1695
|
id,
|
|
1346
1696
|
label,
|
|
@@ -1350,7 +1700,7 @@ var TimeInput = ({
|
|
|
1350
1700
|
onChange,
|
|
1351
1701
|
readOnly = false
|
|
1352
1702
|
}) => {
|
|
1353
|
-
const [displayValue, setDisplayValue] =
|
|
1703
|
+
const [displayValue, setDisplayValue] = useState2("");
|
|
1354
1704
|
useEffect2(() => {
|
|
1355
1705
|
const formatted = formatTime(value, format);
|
|
1356
1706
|
setDisplayValue(formatted);
|
|
@@ -1371,9 +1721,9 @@ var TimeInput = ({
|
|
|
1371
1721
|
e.currentTarget.blur();
|
|
1372
1722
|
}
|
|
1373
1723
|
};
|
|
1374
|
-
return /* @__PURE__ */
|
|
1375
|
-
/* @__PURE__ */
|
|
1376
|
-
/* @__PURE__ */
|
|
1724
|
+
return /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
1725
|
+
/* @__PURE__ */ jsx13(ScreenReaderOnly, { as: "label", htmlFor: id, children: label }),
|
|
1726
|
+
/* @__PURE__ */ jsx13(
|
|
1377
1727
|
BaseInput,
|
|
1378
1728
|
{
|
|
1379
1729
|
type: "text",
|
|
@@ -1390,14 +1740,14 @@ var TimeInput = ({
|
|
|
1390
1740
|
};
|
|
1391
1741
|
|
|
1392
1742
|
// src/components/SelectionTimeInputs.tsx
|
|
1393
|
-
import { Fragment as
|
|
1743
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1394
1744
|
var SelectionTimeInputs = ({
|
|
1395
1745
|
selectionStart,
|
|
1396
1746
|
selectionEnd,
|
|
1397
1747
|
onSelectionChange,
|
|
1398
1748
|
className
|
|
1399
1749
|
}) => {
|
|
1400
|
-
const [timeFormat, setTimeFormat] =
|
|
1750
|
+
const [timeFormat, setTimeFormat] = useState3("hh:mm:ss.uuu");
|
|
1401
1751
|
useEffect3(() => {
|
|
1402
1752
|
const timeFormatSelect = document.querySelector(".time-format");
|
|
1403
1753
|
const handleFormatChange = () => {
|
|
@@ -1423,8 +1773,8 @@ var SelectionTimeInputs = ({
|
|
|
1423
1773
|
onSelectionChange(selectionStart, value);
|
|
1424
1774
|
}
|
|
1425
1775
|
};
|
|
1426
|
-
return /* @__PURE__ */
|
|
1427
|
-
/* @__PURE__ */
|
|
1776
|
+
return /* @__PURE__ */ jsxs8(Fragment4, { children: [
|
|
1777
|
+
/* @__PURE__ */ jsx14(
|
|
1428
1778
|
TimeInput,
|
|
1429
1779
|
{
|
|
1430
1780
|
id: "audio_start",
|
|
@@ -1435,7 +1785,7 @@ var SelectionTimeInputs = ({
|
|
|
1435
1785
|
onChange: handleStartChange
|
|
1436
1786
|
}
|
|
1437
1787
|
),
|
|
1438
|
-
/* @__PURE__ */
|
|
1788
|
+
/* @__PURE__ */ jsx14(
|
|
1439
1789
|
TimeInput,
|
|
1440
1790
|
{
|
|
1441
1791
|
id: "audio_end",
|
|
@@ -1450,14 +1800,14 @@ var SelectionTimeInputs = ({
|
|
|
1450
1800
|
};
|
|
1451
1801
|
|
|
1452
1802
|
// src/contexts/DevicePixelRatio.tsx
|
|
1453
|
-
import { useState as
|
|
1454
|
-
import { jsx as
|
|
1803
|
+
import { useState as useState4, createContext, useContext } from "react";
|
|
1804
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1455
1805
|
function getScale() {
|
|
1456
1806
|
return window.devicePixelRatio;
|
|
1457
1807
|
}
|
|
1458
1808
|
var DevicePixelRatioContext = createContext(getScale());
|
|
1459
1809
|
var DevicePixelRatioProvider = ({ children }) => {
|
|
1460
|
-
const [scale, setScale] =
|
|
1810
|
+
const [scale, setScale] = useState4(getScale());
|
|
1461
1811
|
matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
|
|
1462
1812
|
"change",
|
|
1463
1813
|
() => {
|
|
@@ -1465,7 +1815,7 @@ var DevicePixelRatioProvider = ({ children }) => {
|
|
|
1465
1815
|
},
|
|
1466
1816
|
{ once: true }
|
|
1467
1817
|
);
|
|
1468
|
-
return /* @__PURE__ */
|
|
1818
|
+
return /* @__PURE__ */ jsx15(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
|
|
1469
1819
|
};
|
|
1470
1820
|
var useDevicePixelRatio = () => useContext(DevicePixelRatioContext);
|
|
1471
1821
|
|
|
@@ -1493,18 +1843,18 @@ import { ThemeContext } from "styled-components";
|
|
|
1493
1843
|
var useTheme2 = () => useContext3(ThemeContext);
|
|
1494
1844
|
|
|
1495
1845
|
// src/contexts/TrackControls.tsx
|
|
1496
|
-
import { createContext as createContext3, useContext as useContext4, Fragment as
|
|
1497
|
-
import { jsx as
|
|
1498
|
-
var TrackControlsContext = createContext3(/* @__PURE__ */
|
|
1846
|
+
import { createContext as createContext3, useContext as useContext4, Fragment as Fragment5 } from "react";
|
|
1847
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1848
|
+
var TrackControlsContext = createContext3(/* @__PURE__ */ jsx16(Fragment5, {}));
|
|
1499
1849
|
var useTrackControls = () => useContext4(TrackControlsContext);
|
|
1500
1850
|
|
|
1501
1851
|
// src/contexts/Playout.tsx
|
|
1502
1852
|
import {
|
|
1503
|
-
useState as
|
|
1853
|
+
useState as useState5,
|
|
1504
1854
|
createContext as createContext4,
|
|
1505
1855
|
useContext as useContext5
|
|
1506
1856
|
} from "react";
|
|
1507
|
-
import { jsx as
|
|
1857
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1508
1858
|
var defaultProgress = 0;
|
|
1509
1859
|
var defaultIsPlaying = false;
|
|
1510
1860
|
var defaultSelectionStart = 0;
|
|
@@ -1525,21 +1875,21 @@ var PlayoutStatusUpdateContext = createContext4({
|
|
|
1525
1875
|
}
|
|
1526
1876
|
});
|
|
1527
1877
|
var PlayoutProvider = ({ children }) => {
|
|
1528
|
-
const [isPlaying, setIsPlaying] =
|
|
1529
|
-
const [progress, setProgress] =
|
|
1530
|
-
const [selectionStart, setSelectionStart] =
|
|
1531
|
-
const [selectionEnd, setSelectionEnd] =
|
|
1878
|
+
const [isPlaying, setIsPlaying] = useState5(defaultIsPlaying);
|
|
1879
|
+
const [progress, setProgress] = useState5(defaultProgress);
|
|
1880
|
+
const [selectionStart, setSelectionStart] = useState5(defaultSelectionStart);
|
|
1881
|
+
const [selectionEnd, setSelectionEnd] = useState5(defaultSelectionEnd);
|
|
1532
1882
|
const setSelection = (start, end) => {
|
|
1533
1883
|
setSelectionStart(start);
|
|
1534
1884
|
setSelectionEnd(end);
|
|
1535
1885
|
};
|
|
1536
|
-
return /* @__PURE__ */
|
|
1886
|
+
return /* @__PURE__ */ jsx17(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ jsx17(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
|
|
1537
1887
|
};
|
|
1538
1888
|
var usePlayoutStatus = () => useContext5(PlayoutStatusContext);
|
|
1539
1889
|
var usePlayoutStatusUpdate = () => useContext5(PlayoutStatusUpdateContext);
|
|
1540
1890
|
|
|
1541
1891
|
// src/components/SmartChannel.tsx
|
|
1542
|
-
import { jsx as
|
|
1892
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
1543
1893
|
var SmartChannel = ({ isSelected, transparentBackground, ...props }) => {
|
|
1544
1894
|
const theme = useTheme2();
|
|
1545
1895
|
const { waveHeight, barWidth, barGap } = usePlaylistInfo();
|
|
@@ -1547,7 +1897,7 @@ var SmartChannel = ({ isSelected, transparentBackground, ...props }) => {
|
|
|
1547
1897
|
const waveOutlineColor = isSelected && theme ? theme.selectedWaveOutlineColor : theme?.waveOutlineColor;
|
|
1548
1898
|
const waveFillColor = isSelected && theme ? theme.selectedWaveFillColor : theme?.waveFillColor;
|
|
1549
1899
|
const drawMode = theme?.waveformDrawMode || "inverted";
|
|
1550
|
-
return /* @__PURE__ */
|
|
1900
|
+
return /* @__PURE__ */ jsx18(
|
|
1551
1901
|
Channel,
|
|
1552
1902
|
{
|
|
1553
1903
|
...props,
|
|
@@ -1568,8 +1918,8 @@ var SmartChannel = ({ isSelected, transparentBackground, ...props }) => {
|
|
|
1568
1918
|
import { useContext as useContext7 } from "react";
|
|
1569
1919
|
|
|
1570
1920
|
// src/components/TimeScale.tsx
|
|
1571
|
-
import
|
|
1572
|
-
import
|
|
1921
|
+
import React10, { useRef as useRef4, useEffect as useEffect4, useContext as useContext6 } from "react";
|
|
1922
|
+
import styled19, { withTheme as withTheme2 } from "styled-components";
|
|
1573
1923
|
|
|
1574
1924
|
// src/utils/conversions.ts
|
|
1575
1925
|
function samplesToSeconds(samples, sampleRate) {
|
|
@@ -1592,14 +1942,14 @@ function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
|
|
|
1592
1942
|
}
|
|
1593
1943
|
|
|
1594
1944
|
// src/components/TimeScale.tsx
|
|
1595
|
-
import { jsx as
|
|
1945
|
+
import { jsx as jsx19, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1596
1946
|
function formatTime2(milliseconds) {
|
|
1597
1947
|
const seconds = Math.floor(milliseconds / 1e3);
|
|
1598
1948
|
const s = seconds % 60;
|
|
1599
1949
|
const m = (seconds - s) / 60;
|
|
1600
1950
|
return `${m}:${String(s).padStart(2, "0")}`;
|
|
1601
1951
|
}
|
|
1602
|
-
var PlaylistTimeScaleScroll =
|
|
1952
|
+
var PlaylistTimeScaleScroll = styled19.div.attrs((props) => ({
|
|
1603
1953
|
style: {
|
|
1604
1954
|
width: `${props.$cssWidth}px`,
|
|
1605
1955
|
marginLeft: `${props.$controlWidth}px`,
|
|
@@ -1611,7 +1961,7 @@ var PlaylistTimeScaleScroll = styled18.div.attrs((props) => ({
|
|
|
1611
1961
|
border-bottom: 1px solid ${(props) => props.theme.timeColor};
|
|
1612
1962
|
box-sizing: border-box;
|
|
1613
1963
|
`;
|
|
1614
|
-
var TimeTicks =
|
|
1964
|
+
var TimeTicks = styled19.canvas.attrs((props) => ({
|
|
1615
1965
|
style: {
|
|
1616
1966
|
width: `${props.$cssWidth}px`,
|
|
1617
1967
|
height: `${props.$timeScaleHeight}px`
|
|
@@ -1622,7 +1972,7 @@ var TimeTicks = styled18.canvas.attrs((props) => ({
|
|
|
1622
1972
|
right: 0;
|
|
1623
1973
|
bottom: 0;
|
|
1624
1974
|
`;
|
|
1625
|
-
var TimeStamp =
|
|
1975
|
+
var TimeStamp = styled19.div.attrs((props) => ({
|
|
1626
1976
|
style: {
|
|
1627
1977
|
left: `${props.$left + 4}px`
|
|
1628
1978
|
// Offset 4px to the right of the tick
|
|
@@ -1644,7 +1994,7 @@ var TimeScale = (props) => {
|
|
|
1644
1994
|
} = props;
|
|
1645
1995
|
const canvasInfo = /* @__PURE__ */ new Map();
|
|
1646
1996
|
const timeMarkers = [];
|
|
1647
|
-
const canvasRef =
|
|
1997
|
+
const canvasRef = useRef4(null);
|
|
1648
1998
|
const {
|
|
1649
1999
|
sampleRate,
|
|
1650
2000
|
samplesPerPixel,
|
|
@@ -1686,7 +2036,7 @@ var TimeScale = (props) => {
|
|
|
1686
2036
|
if (counter % marker === 0) {
|
|
1687
2037
|
const timeMs = counter;
|
|
1688
2038
|
const timestamp = formatTime2(timeMs);
|
|
1689
|
-
const timestampContent = renderTimestamp ? /* @__PURE__ */
|
|
2039
|
+
const timestampContent = renderTimestamp ? /* @__PURE__ */ jsx19(React10.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ jsx19(TimeStamp, { $left: pix, children: timestamp }, timestamp);
|
|
1690
2040
|
timeMarkers.push(timestampContent);
|
|
1691
2041
|
canvasInfo.set(pix, timeScaleHeight);
|
|
1692
2042
|
} else if (counter % bigStep === 0) {
|
|
@@ -1696,7 +2046,7 @@ var TimeScale = (props) => {
|
|
|
1696
2046
|
}
|
|
1697
2047
|
counter += secondStep;
|
|
1698
2048
|
}
|
|
1699
|
-
return /* @__PURE__ */
|
|
2049
|
+
return /* @__PURE__ */ jsxs9(
|
|
1700
2050
|
PlaylistTimeScaleScroll,
|
|
1701
2051
|
{
|
|
1702
2052
|
$cssWidth: widthX,
|
|
@@ -1704,7 +2054,7 @@ var TimeScale = (props) => {
|
|
|
1704
2054
|
$timeScaleHeight: timeScaleHeight,
|
|
1705
2055
|
children: [
|
|
1706
2056
|
timeMarkers,
|
|
1707
|
-
/* @__PURE__ */
|
|
2057
|
+
/* @__PURE__ */ jsx19(
|
|
1708
2058
|
TimeTicks,
|
|
1709
2059
|
{
|
|
1710
2060
|
$cssWidth: widthX,
|
|
@@ -1721,7 +2071,7 @@ var TimeScale = (props) => {
|
|
|
1721
2071
|
var StyledTimeScale = withTheme2(TimeScale);
|
|
1722
2072
|
|
|
1723
2073
|
// src/components/SmartScale.tsx
|
|
1724
|
-
import { jsx as
|
|
2074
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
1725
2075
|
var timeinfo = /* @__PURE__ */ new Map([
|
|
1726
2076
|
[
|
|
1727
2077
|
700,
|
|
@@ -1797,7 +2147,7 @@ function getScaleInfo(samplesPerPixel) {
|
|
|
1797
2147
|
var SmartScale = () => {
|
|
1798
2148
|
const { samplesPerPixel, duration } = useContext7(PlaylistInfoContext);
|
|
1799
2149
|
let config = getScaleInfo(samplesPerPixel);
|
|
1800
|
-
return /* @__PURE__ */
|
|
2150
|
+
return /* @__PURE__ */ jsx20(
|
|
1801
2151
|
StyledTimeScale,
|
|
1802
2152
|
{
|
|
1803
2153
|
marker: config.marker,
|
|
@@ -1809,9 +2159,9 @@ var SmartScale = () => {
|
|
|
1809
2159
|
};
|
|
1810
2160
|
|
|
1811
2161
|
// src/components/TimeFormatSelect.tsx
|
|
1812
|
-
import
|
|
1813
|
-
import { jsx as
|
|
1814
|
-
var SelectWrapper =
|
|
2162
|
+
import styled20 from "styled-components";
|
|
2163
|
+
import { jsx as jsx21 } from "react/jsx-runtime";
|
|
2164
|
+
var SelectWrapper = styled20.div`
|
|
1815
2165
|
display: inline-flex;
|
|
1816
2166
|
align-items: center;
|
|
1817
2167
|
gap: 0.5rem;
|
|
@@ -1833,7 +2183,7 @@ var TimeFormatSelect = ({
|
|
|
1833
2183
|
const handleChange = (e) => {
|
|
1834
2184
|
onChange(e.target.value);
|
|
1835
2185
|
};
|
|
1836
|
-
return /* @__PURE__ */
|
|
2186
|
+
return /* @__PURE__ */ jsx21(SelectWrapper, { className, children: /* @__PURE__ */ jsx21(
|
|
1837
2187
|
BaseSelect,
|
|
1838
2188
|
{
|
|
1839
2189
|
className: "time-format",
|
|
@@ -1841,15 +2191,15 @@ var TimeFormatSelect = ({
|
|
|
1841
2191
|
onChange: handleChange,
|
|
1842
2192
|
disabled,
|
|
1843
2193
|
"aria-label": "Time format selection",
|
|
1844
|
-
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */
|
|
2194
|
+
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsx21("option", { value: option.value, children: option.label }, option.value))
|
|
1845
2195
|
}
|
|
1846
2196
|
) });
|
|
1847
2197
|
};
|
|
1848
2198
|
|
|
1849
2199
|
// src/components/Track.tsx
|
|
1850
|
-
import
|
|
1851
|
-
import { jsx as
|
|
1852
|
-
var Container =
|
|
2200
|
+
import styled21 from "styled-components";
|
|
2201
|
+
import { jsx as jsx22, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2202
|
+
var Container = styled21.div.attrs((props) => ({
|
|
1853
2203
|
style: {
|
|
1854
2204
|
height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`
|
|
1855
2205
|
}
|
|
@@ -1858,7 +2208,7 @@ var Container = styled20.div.attrs((props) => ({
|
|
|
1858
2208
|
display: flex;
|
|
1859
2209
|
${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}
|
|
1860
2210
|
`;
|
|
1861
|
-
var ChannelContainer =
|
|
2211
|
+
var ChannelContainer = styled21.div.attrs((props) => ({
|
|
1862
2212
|
style: {
|
|
1863
2213
|
paddingLeft: `${props.$offset || 0}px`
|
|
1864
2214
|
}
|
|
@@ -1867,7 +2217,7 @@ var ChannelContainer = styled20.div.attrs((props) => ({
|
|
|
1867
2217
|
background: ${(props) => props.$backgroundColor || "transparent"};
|
|
1868
2218
|
flex: 1;
|
|
1869
2219
|
`;
|
|
1870
|
-
var ControlsWrapper =
|
|
2220
|
+
var ControlsWrapper = styled21.div.attrs((props) => ({
|
|
1871
2221
|
style: {
|
|
1872
2222
|
width: `${props.$controlWidth}px`
|
|
1873
2223
|
}
|
|
@@ -1903,7 +2253,7 @@ var Track = ({
|
|
|
1903
2253
|
controls: { show, width: controlWidth }
|
|
1904
2254
|
} = usePlaylistInfo();
|
|
1905
2255
|
const controls = useTrackControls();
|
|
1906
|
-
return /* @__PURE__ */
|
|
2256
|
+
return /* @__PURE__ */ jsxs10(
|
|
1907
2257
|
Container,
|
|
1908
2258
|
{
|
|
1909
2259
|
$numChannels: numChannels,
|
|
@@ -1914,7 +2264,7 @@ var Track = ({
|
|
|
1914
2264
|
$hasClipHeaders: hasClipHeaders,
|
|
1915
2265
|
$isSelected: isSelected,
|
|
1916
2266
|
children: [
|
|
1917
|
-
/* @__PURE__ */
|
|
2267
|
+
/* @__PURE__ */ jsx22(
|
|
1918
2268
|
ControlsWrapper,
|
|
1919
2269
|
{
|
|
1920
2270
|
$controlWidth: show ? controlWidth : 0,
|
|
@@ -1922,7 +2272,7 @@ var Track = ({
|
|
|
1922
2272
|
children: controls
|
|
1923
2273
|
}
|
|
1924
2274
|
),
|
|
1925
|
-
/* @__PURE__ */
|
|
2275
|
+
/* @__PURE__ */ jsx22(
|
|
1926
2276
|
ChannelContainer,
|
|
1927
2277
|
{
|
|
1928
2278
|
$controlWidth: show ? controlWidth : 0,
|
|
@@ -1939,8 +2289,8 @@ var Track = ({
|
|
|
1939
2289
|
};
|
|
1940
2290
|
|
|
1941
2291
|
// src/components/TrackControls/Button.tsx
|
|
1942
|
-
import
|
|
1943
|
-
var Button =
|
|
2292
|
+
import styled22 from "styled-components";
|
|
2293
|
+
var Button = styled22.button.attrs({
|
|
1944
2294
|
type: "button"
|
|
1945
2295
|
})`
|
|
1946
2296
|
display: inline-block;
|
|
@@ -2012,8 +2362,8 @@ var Button = styled21.button.attrs({
|
|
|
2012
2362
|
`;
|
|
2013
2363
|
|
|
2014
2364
|
// src/components/TrackControls/ButtonGroup.tsx
|
|
2015
|
-
import
|
|
2016
|
-
var ButtonGroup =
|
|
2365
|
+
import styled23 from "styled-components";
|
|
2366
|
+
var ButtonGroup = styled23.div`
|
|
2017
2367
|
margin-bottom: 0.3rem;
|
|
2018
2368
|
|
|
2019
2369
|
button:not(:first-child) {
|
|
@@ -2028,8 +2378,8 @@ var ButtonGroup = styled22.div`
|
|
|
2028
2378
|
`;
|
|
2029
2379
|
|
|
2030
2380
|
// src/components/TrackControls/Controls.tsx
|
|
2031
|
-
import
|
|
2032
|
-
var Controls =
|
|
2381
|
+
import styled24 from "styled-components";
|
|
2382
|
+
var Controls = styled24.div`
|
|
2033
2383
|
background: transparent;
|
|
2034
2384
|
width: 100%;
|
|
2035
2385
|
height: 100%;
|
|
@@ -2045,8 +2395,8 @@ var Controls = styled23.div`
|
|
|
2045
2395
|
`;
|
|
2046
2396
|
|
|
2047
2397
|
// src/components/TrackControls/Header.tsx
|
|
2048
|
-
import
|
|
2049
|
-
var Header =
|
|
2398
|
+
import styled25 from "styled-components";
|
|
2399
|
+
var Header = styled25.header`
|
|
2050
2400
|
overflow: hidden;
|
|
2051
2401
|
height: 26px;
|
|
2052
2402
|
width: 100%;
|
|
@@ -2061,22 +2411,22 @@ var Header = styled24.header`
|
|
|
2061
2411
|
|
|
2062
2412
|
// src/components/TrackControls/VolumeDownIcon.tsx
|
|
2063
2413
|
import { SpeakerLowIcon } from "@phosphor-icons/react";
|
|
2064
|
-
import { jsx as
|
|
2065
|
-
var VolumeDownIcon = (props) => /* @__PURE__ */
|
|
2414
|
+
import { jsx as jsx23 } from "react/jsx-runtime";
|
|
2415
|
+
var VolumeDownIcon = (props) => /* @__PURE__ */ jsx23(SpeakerLowIcon, { weight: "light", ...props });
|
|
2066
2416
|
|
|
2067
2417
|
// src/components/TrackControls/VolumeUpIcon.tsx
|
|
2068
2418
|
import { SpeakerHighIcon } from "@phosphor-icons/react";
|
|
2069
|
-
import { jsx as
|
|
2070
|
-
var VolumeUpIcon = (props) => /* @__PURE__ */
|
|
2419
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
2420
|
+
var VolumeUpIcon = (props) => /* @__PURE__ */ jsx24(SpeakerHighIcon, { weight: "light", ...props });
|
|
2071
2421
|
|
|
2072
2422
|
// src/components/TrackControls/TrashIcon.tsx
|
|
2073
2423
|
import { TrashIcon as PhosphorTrashIcon } from "@phosphor-icons/react";
|
|
2074
|
-
import { jsx as
|
|
2075
|
-
var TrashIcon = (props) => /* @__PURE__ */
|
|
2424
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
2425
|
+
var TrashIcon = (props) => /* @__PURE__ */ jsx25(PhosphorTrashIcon, { weight: "light", ...props });
|
|
2076
2426
|
|
|
2077
2427
|
// src/components/TrackControls/Slider.tsx
|
|
2078
|
-
import
|
|
2079
|
-
var Slider =
|
|
2428
|
+
import styled26 from "styled-components";
|
|
2429
|
+
var Slider = styled26(BaseSlider)`
|
|
2080
2430
|
width: 75%;
|
|
2081
2431
|
height: 5px;
|
|
2082
2432
|
background: ${(props) => props.theme.sliderTrackColor};
|
|
@@ -2128,8 +2478,8 @@ var Slider = styled25(BaseSlider)`
|
|
|
2128
2478
|
`;
|
|
2129
2479
|
|
|
2130
2480
|
// src/components/TrackControls/SliderWrapper.tsx
|
|
2131
|
-
import
|
|
2132
|
-
var SliderWrapper =
|
|
2481
|
+
import styled27 from "styled-components";
|
|
2482
|
+
var SliderWrapper = styled27.label`
|
|
2133
2483
|
width: 100%;
|
|
2134
2484
|
display: flex;
|
|
2135
2485
|
justify-content: space-between;
|
|
@@ -2140,15 +2490,15 @@ var SliderWrapper = styled26.label`
|
|
|
2140
2490
|
`;
|
|
2141
2491
|
|
|
2142
2492
|
// src/components/TrackControlsWithDelete.tsx
|
|
2143
|
-
import
|
|
2144
|
-
import { jsx as
|
|
2145
|
-
var HeaderContainer2 =
|
|
2493
|
+
import styled28 from "styled-components";
|
|
2494
|
+
import { jsx as jsx26, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2495
|
+
var HeaderContainer2 = styled28.div`
|
|
2146
2496
|
display: flex;
|
|
2147
2497
|
align-items: center;
|
|
2148
2498
|
gap: 0.25rem;
|
|
2149
2499
|
padding: 0.5rem 0.5rem 0.25rem 0.5rem;
|
|
2150
2500
|
`;
|
|
2151
|
-
var TrackNameSpan =
|
|
2501
|
+
var TrackNameSpan = styled28.span`
|
|
2152
2502
|
flex: 1;
|
|
2153
2503
|
font-weight: 600;
|
|
2154
2504
|
font-size: 0.875rem;
|
|
@@ -2157,7 +2507,7 @@ var TrackNameSpan = styled27.span`
|
|
|
2157
2507
|
white-space: nowrap;
|
|
2158
2508
|
margin: 0 0.25rem;
|
|
2159
2509
|
`;
|
|
2160
|
-
var DeleteIconButton =
|
|
2510
|
+
var DeleteIconButton = styled28.button`
|
|
2161
2511
|
display: flex;
|
|
2162
2512
|
align-items: center;
|
|
2163
2513
|
justify-content: center;
|
|
@@ -2195,13 +2545,13 @@ var TrackControlsWithDelete = ({
|
|
|
2195
2545
|
onPanChange,
|
|
2196
2546
|
onDelete
|
|
2197
2547
|
}) => {
|
|
2198
|
-
return /* @__PURE__ */
|
|
2199
|
-
/* @__PURE__ */
|
|
2200
|
-
/* @__PURE__ */
|
|
2201
|
-
/* @__PURE__ */
|
|
2548
|
+
return /* @__PURE__ */ jsxs11(Controls, { children: [
|
|
2549
|
+
/* @__PURE__ */ jsxs11(HeaderContainer2, { children: [
|
|
2550
|
+
/* @__PURE__ */ jsx26(DeleteIconButton, { onClick: onDelete, title: "Delete track", children: /* @__PURE__ */ jsx26(TrashIcon, {}) }),
|
|
2551
|
+
/* @__PURE__ */ jsx26(TrackNameSpan, { children: trackName })
|
|
2202
2552
|
] }),
|
|
2203
|
-
/* @__PURE__ */
|
|
2204
|
-
/* @__PURE__ */
|
|
2553
|
+
/* @__PURE__ */ jsxs11(ButtonGroup, { children: [
|
|
2554
|
+
/* @__PURE__ */ jsx26(
|
|
2205
2555
|
Button,
|
|
2206
2556
|
{
|
|
2207
2557
|
$variant: muted ? "danger" : "outline",
|
|
@@ -2209,7 +2559,7 @@ var TrackControlsWithDelete = ({
|
|
|
2209
2559
|
children: "Mute"
|
|
2210
2560
|
}
|
|
2211
2561
|
),
|
|
2212
|
-
/* @__PURE__ */
|
|
2562
|
+
/* @__PURE__ */ jsx26(
|
|
2213
2563
|
Button,
|
|
2214
2564
|
{
|
|
2215
2565
|
$variant: soloed ? "info" : "outline",
|
|
@@ -2218,9 +2568,9 @@ var TrackControlsWithDelete = ({
|
|
|
2218
2568
|
}
|
|
2219
2569
|
)
|
|
2220
2570
|
] }),
|
|
2221
|
-
/* @__PURE__ */
|
|
2222
|
-
/* @__PURE__ */
|
|
2223
|
-
/* @__PURE__ */
|
|
2571
|
+
/* @__PURE__ */ jsxs11(SliderWrapper, { children: [
|
|
2572
|
+
/* @__PURE__ */ jsx26(VolumeDownIcon, {}),
|
|
2573
|
+
/* @__PURE__ */ jsx26(
|
|
2224
2574
|
Slider,
|
|
2225
2575
|
{
|
|
2226
2576
|
min: "0",
|
|
@@ -2230,11 +2580,11 @@ var TrackControlsWithDelete = ({
|
|
|
2230
2580
|
onChange: (e) => onVolumeChange(parseFloat(e.target.value))
|
|
2231
2581
|
}
|
|
2232
2582
|
),
|
|
2233
|
-
/* @__PURE__ */
|
|
2583
|
+
/* @__PURE__ */ jsx26(VolumeUpIcon, {})
|
|
2234
2584
|
] }),
|
|
2235
|
-
/* @__PURE__ */
|
|
2236
|
-
/* @__PURE__ */
|
|
2237
|
-
/* @__PURE__ */
|
|
2585
|
+
/* @__PURE__ */ jsxs11(SliderWrapper, { children: [
|
|
2586
|
+
/* @__PURE__ */ jsx26("span", { children: "L" }),
|
|
2587
|
+
/* @__PURE__ */ jsx26(
|
|
2238
2588
|
Slider,
|
|
2239
2589
|
{
|
|
2240
2590
|
min: "-1",
|
|
@@ -2244,7 +2594,7 @@ var TrackControlsWithDelete = ({
|
|
|
2244
2594
|
onChange: (e) => onPanChange(parseFloat(e.target.value))
|
|
2245
2595
|
}
|
|
2246
2596
|
),
|
|
2247
|
-
/* @__PURE__ */
|
|
2597
|
+
/* @__PURE__ */ jsx26("span", { children: "R" })
|
|
2248
2598
|
] })
|
|
2249
2599
|
] });
|
|
2250
2600
|
};
|
|
@@ -2263,6 +2613,7 @@ export {
|
|
|
2263
2613
|
Button,
|
|
2264
2614
|
ButtonGroup,
|
|
2265
2615
|
CLIP_BOUNDARY_WIDTH,
|
|
2616
|
+
CLIP_BOUNDARY_WIDTH_TOUCH,
|
|
2266
2617
|
CLIP_HEADER_HEIGHT,
|
|
2267
2618
|
Channel,
|
|
2268
2619
|
Clip,
|
|
@@ -2274,6 +2625,8 @@ export {
|
|
|
2274
2625
|
FadeOverlay,
|
|
2275
2626
|
Header,
|
|
2276
2627
|
InlineLabel,
|
|
2628
|
+
LoopRegion,
|
|
2629
|
+
LoopRegionMarkers,
|
|
2277
2630
|
MasterVolumeControl,
|
|
2278
2631
|
Playhead,
|
|
2279
2632
|
PlayheadWithMarker,
|
|
@@ -2292,6 +2645,7 @@ export {
|
|
|
2292
2645
|
TimeFormatSelect,
|
|
2293
2646
|
TimeInput,
|
|
2294
2647
|
TimeScale,
|
|
2648
|
+
TimescaleLoopRegion,
|
|
2295
2649
|
Track,
|
|
2296
2650
|
TrackControlsContext,
|
|
2297
2651
|
TrackControlsWithDelete,
|