@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.js CHANGED
@@ -44,6 +44,7 @@ __export(index_exports, {
44
44
  Button: () => Button,
45
45
  ButtonGroup: () => ButtonGroup,
46
46
  CLIP_BOUNDARY_WIDTH: () => CLIP_BOUNDARY_WIDTH,
47
+ CLIP_BOUNDARY_WIDTH_TOUCH: () => CLIP_BOUNDARY_WIDTH_TOUCH,
47
48
  CLIP_HEADER_HEIGHT: () => CLIP_HEADER_HEIGHT,
48
49
  Channel: () => Channel,
49
50
  Clip: () => Clip,
@@ -55,6 +56,8 @@ __export(index_exports, {
55
56
  FadeOverlay: () => FadeOverlay,
56
57
  Header: () => Header,
57
58
  InlineLabel: () => InlineLabel,
59
+ LoopRegion: () => LoopRegion,
60
+ LoopRegionMarkers: () => LoopRegionMarkers,
58
61
  MasterVolumeControl: () => MasterVolumeControl,
59
62
  Playhead: () => Playhead,
60
63
  PlayheadWithMarker: () => PlayheadWithMarker,
@@ -73,6 +76,7 @@ __export(index_exports, {
73
76
  TimeFormatSelect: () => TimeFormatSelect,
74
77
  TimeInput: () => TimeInput,
75
78
  TimeScale: () => TimeScale,
79
+ TimescaleLoopRegion: () => TimescaleLoopRegion,
76
80
  Track: () => Track,
77
81
  TrackControlsContext: () => TrackControlsContext,
78
82
  TrackControlsWithDelete: () => TrackControlsWithDelete,
@@ -461,6 +465,10 @@ var defaultTheme = {
461
465
  playheadColor: "#f00",
462
466
  selectionColor: "rgba(255, 105, 180, 0.7)",
463
467
  // hot pink - high contrast on light backgrounds
468
+ loopRegionColor: "rgba(59, 130, 246, 0.3)",
469
+ // Blue - distinct from pink selection
470
+ loopMarkerColor: "#3b82f6",
471
+ // Blue marker triangles
464
472
  clipHeaderBackgroundColor: "rgba(0, 0, 0, 0.1)",
465
473
  clipHeaderBorderColor: "rgba(0, 0, 0, 0.2)",
466
474
  clipHeaderTextColor: "#333",
@@ -532,6 +540,10 @@ var darkTheme = {
532
540
  // Darker Ampelmännchen green playhead
533
541
  selectionColor: "rgba(60, 140, 58, 0.6)",
534
542
  // Darker Ampelmännchen green selection - visible on dark backgrounds
543
+ loopRegionColor: "rgba(96, 165, 250, 0.35)",
544
+ // Light blue - distinct from green selection
545
+ loopMarkerColor: "#60a5fa",
546
+ // Light blue marker triangles
535
547
  clipHeaderBackgroundColor: "rgba(20, 16, 12, 0.85)",
536
548
  // Dark background for clip headers
537
549
  clipHeaderBorderColor: "rgba(200, 160, 120, 0.25)",
@@ -772,6 +784,7 @@ var HeaderContainer = import_styled_components10.default.div`
772
784
  z-index: 110;
773
785
  flex-shrink: 0;
774
786
  pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */
787
+ touch-action: ${(props) => props.$interactive ? "none" : "auto"}; /* Prevent browser scroll during drag on touch devices */
775
788
 
776
789
  ${(props) => props.$interactive && `
777
790
  &:hover {
@@ -844,16 +857,18 @@ var import_react2 = __toESM(require("react"));
844
857
  var import_styled_components11 = __toESM(require("styled-components"));
845
858
  var import_jsx_runtime5 = require("react/jsx-runtime");
846
859
  var CLIP_BOUNDARY_WIDTH = 8;
860
+ var CLIP_BOUNDARY_WIDTH_TOUCH = 24;
847
861
  var BoundaryContainer = import_styled_components11.default.div`
848
862
  position: absolute;
849
863
  ${(props) => props.$edge === "left" ? "left: 0;" : "right: 0;"}
850
864
  top: 0;
851
865
  bottom: 0;
852
- width: ${CLIP_BOUNDARY_WIDTH}px;
866
+ width: ${(props) => props.$touchOptimized ? CLIP_BOUNDARY_WIDTH_TOUCH : CLIP_BOUNDARY_WIDTH}px;
853
867
  cursor: col-resize;
854
868
  user-select: none;
855
869
  z-index: 105; /* Above waveform, below header */
856
870
  pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */
871
+ touch-action: none; /* Prevent browser scroll during drag on touch devices */
857
872
 
858
873
  /* Invisible by default, visible on hover */
859
874
  background: ${(props) => props.$isDragging ? "rgba(255, 255, 255, 0.4)" : props.$isHovered ? "rgba(255, 255, 255, 0.2)" : "transparent"};
@@ -877,7 +892,8 @@ var ClipBoundary = ({
877
892
  trackIndex,
878
893
  clipIndex,
879
894
  edge,
880
- dragHandleProps
895
+ dragHandleProps,
896
+ touchOptimized = false
881
897
  }) => {
882
898
  const [isHovered, setIsHovered] = import_react2.default.useState(false);
883
899
  if (!dragHandleProps) {
@@ -893,6 +909,7 @@ var ClipBoundary = ({
893
909
  $edge: edge,
894
910
  $isDragging: isDragging,
895
911
  $isHovered: isHovered,
912
+ $touchOptimized: touchOptimized,
896
913
  onMouseEnter: () => setIsHovered(true),
897
914
  onMouseLeave: () => setIsHovered(false),
898
915
  ...listeners,
@@ -1015,7 +1032,8 @@ var Clip = ({
1015
1032
  fadeIn,
1016
1033
  fadeOut,
1017
1034
  sampleRate = 44100,
1018
- showFades = false
1035
+ showFades = false,
1036
+ touchOptimized = false
1019
1037
  }) => {
1020
1038
  const left = Math.floor(startSample / samplesPerPixel);
1021
1039
  const endPixel = Math.floor((startSample + durationSamples) / samplesPerPixel);
@@ -1108,6 +1126,7 @@ var Clip = ({
1108
1126
  trackIndex,
1109
1127
  clipIndex,
1110
1128
  edge: "left",
1129
+ touchOptimized,
1111
1130
  dragHandleProps: {
1112
1131
  attributes: leftBoundaryAttributes,
1113
1132
  listeners: leftBoundaryListeners,
@@ -1123,6 +1142,7 @@ var Clip = ({
1123
1142
  trackIndex,
1124
1143
  clipIndex,
1125
1144
  edge: "right",
1145
+ touchOptimized,
1126
1146
  dragHandleProps: {
1127
1147
  attributes: rightBoundaryAttributes,
1128
1148
  listeners: rightBoundaryListeners,
@@ -1300,7 +1320,8 @@ var TimescaleWrapper = import_styled_components16.default.div.attrs((props) => (
1300
1320
  }))`
1301
1321
  background: ${(props) => props.$backgroundColor || "white"};
1302
1322
  width: 100%;
1303
- overflow: visible;
1323
+ position: relative;
1324
+ overflow: hidden; /* Constrain loop region to timescale area */
1304
1325
  `;
1305
1326
  var TracksContainer = import_styled_components16.default.div.attrs((props) => ({
1306
1327
  style: props.$width !== void 0 ? { minWidth: `${props.$width}px` } : {}
@@ -1316,7 +1337,8 @@ var ClickOverlay = import_styled_components16.default.div`
1316
1337
  right: 0;
1317
1338
  bottom: 0;
1318
1339
  cursor: crosshair;
1319
- z-index: 1; /* Low z-index - clip headers and boundaries have higher z-index */
1340
+ /* When selecting, raise z-index above clip boundaries (z-index: 105) to prevent interference */
1341
+ z-index: ${(props) => props.$isSelecting ? 110 : 1};
1320
1342
  `;
1321
1343
  var Playlist = ({
1322
1344
  children,
@@ -1331,7 +1353,8 @@ var Playlist = ({
1331
1353
  onTracksMouseDown,
1332
1354
  onTracksMouseMove,
1333
1355
  onTracksMouseUp,
1334
- scrollContainerRef
1356
+ scrollContainerRef,
1357
+ isSelecting
1335
1358
  }) => {
1336
1359
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Wrapper2, { "data-scroll-container": "true", ref: scrollContainerRef, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1337
1360
  ScrollContainer,
@@ -1346,6 +1369,7 @@ var Playlist = ({
1346
1369
  ClickOverlay,
1347
1370
  {
1348
1371
  $controlsWidth: controlsWidth,
1372
+ $isSelecting: isSelecting,
1349
1373
  onClick: onTracksClick,
1350
1374
  onMouseDown: onTracksMouseDown,
1351
1375
  onMouseMove: onTracksMouseMove,
@@ -1388,11 +1412,341 @@ var Selection = ({
1388
1412
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SelectionOverlay, { $left: startPosition, $width: width, $color: color, "data-selection": true });
1389
1413
  };
1390
1414
 
1415
+ // src/components/LoopRegion.tsx
1416
+ var import_react4 = require("react");
1417
+ var import_styled_components18 = __toESM(require("styled-components"));
1418
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1419
+ var LoopRegionOverlayDiv = import_styled_components18.default.div.attrs((props) => ({
1420
+ style: {
1421
+ left: `${props.$left}px`,
1422
+ width: `${props.$width}px`
1423
+ }
1424
+ }))`
1425
+ position: absolute;
1426
+ top: 0;
1427
+ background: ${(props) => props.$color};
1428
+ height: 100%;
1429
+ z-index: 55; /* Between clips (z-index: 50) and selection (z-index: 60) */
1430
+ pointer-events: none;
1431
+ `;
1432
+ var LoopMarker = import_styled_components18.default.div.attrs((props) => ({
1433
+ style: {
1434
+ left: `${props.$left}px`
1435
+ }
1436
+ }))`
1437
+ position: absolute;
1438
+ top: 0;
1439
+ width: 2px;
1440
+ height: 100%;
1441
+ background: ${(props) => props.$color};
1442
+ z-index: 90; /* Below playhead (z-index: 100) */
1443
+ pointer-events: none;
1444
+
1445
+ /* Triangle marker at top */
1446
+ &::before {
1447
+ content: '';
1448
+ position: absolute;
1449
+ top: 0;
1450
+ ${(props) => props.$isStart ? "left: 0" : "right: 0"};
1451
+ width: 0;
1452
+ height: 0;
1453
+ border-top: 8px solid ${(props) => props.$color};
1454
+ ${(props) => props.$isStart ? "border-right: 8px solid transparent;" : "border-left: 8px solid transparent;"}
1455
+ }
1456
+ `;
1457
+ var LoopRegion = ({
1458
+ startPosition,
1459
+ endPosition,
1460
+ regionColor = "rgba(59, 130, 246, 0.3)",
1461
+ markerColor = "#3b82f6"
1462
+ }) => {
1463
+ const width = Math.max(0, endPosition - startPosition);
1464
+ if (width <= 0) {
1465
+ return null;
1466
+ }
1467
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1468
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1469
+ LoopRegionOverlayDiv,
1470
+ {
1471
+ $left: startPosition,
1472
+ $width: width,
1473
+ $color: regionColor,
1474
+ "data-loop-region": true
1475
+ }
1476
+ ),
1477
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1478
+ LoopMarker,
1479
+ {
1480
+ $left: startPosition,
1481
+ $color: markerColor,
1482
+ $isStart: true,
1483
+ "data-loop-marker": "start"
1484
+ }
1485
+ ),
1486
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1487
+ LoopMarker,
1488
+ {
1489
+ $left: endPosition - 2,
1490
+ $color: markerColor,
1491
+ $isStart: false,
1492
+ "data-loop-marker": "end"
1493
+ }
1494
+ )
1495
+ ] });
1496
+ };
1497
+ var DraggableMarkerHandle = import_styled_components18.default.div.attrs((props) => ({
1498
+ style: {
1499
+ left: `${props.$left}px`
1500
+ }
1501
+ }))`
1502
+ position: absolute;
1503
+ top: 0;
1504
+ width: 12px;
1505
+ height: 100%;
1506
+ cursor: ew-resize;
1507
+ z-index: 100;
1508
+ /* Center the handle on the marker position */
1509
+ transform: translateX(-5px);
1510
+
1511
+ /* Visual marker line */
1512
+ &::before {
1513
+ content: '';
1514
+ position: absolute;
1515
+ top: 0;
1516
+ left: 5px;
1517
+ width: 2px;
1518
+ height: 100%;
1519
+ background: ${(props) => props.$color};
1520
+ opacity: ${(props) => props.$isDragging ? 1 : 0.8};
1521
+ }
1522
+
1523
+ /* Triangle marker at top */
1524
+ &::after {
1525
+ content: '';
1526
+ position: absolute;
1527
+ top: 0;
1528
+ ${(props) => props.$isStart ? "left: 5px" : "left: -1px"};
1529
+ width: 0;
1530
+ height: 0;
1531
+ border-top: 10px solid ${(props) => props.$color};
1532
+ ${(props) => props.$isStart ? "border-right: 10px solid transparent;" : "border-left: 10px solid transparent;"}
1533
+ }
1534
+
1535
+ &:hover::before {
1536
+ opacity: 1;
1537
+ }
1538
+ `;
1539
+ var TimescaleLoopShade = import_styled_components18.default.div.attrs((props) => ({
1540
+ style: {
1541
+ left: `${props.$left}px`,
1542
+ width: `${props.$width}px`
1543
+ }
1544
+ }))`
1545
+ position: absolute;
1546
+ top: 0;
1547
+ height: 100%;
1548
+ background: ${(props) => props.$color};
1549
+ z-index: 50;
1550
+ cursor: grab;
1551
+
1552
+ &:active {
1553
+ cursor: grabbing;
1554
+ }
1555
+ `;
1556
+ var LoopRegionMarkers = ({
1557
+ startPosition,
1558
+ endPosition,
1559
+ markerColor = "#3b82f6",
1560
+ regionColor = "rgba(59, 130, 246, 0.3)",
1561
+ onLoopStartChange,
1562
+ onLoopEndChange,
1563
+ onLoopRegionMove,
1564
+ minPosition = 0,
1565
+ maxPosition = Infinity
1566
+ }) => {
1567
+ const [draggingMarker, setDraggingMarker] = (0, import_react4.useState)(null);
1568
+ const dragStartX = (0, import_react4.useRef)(0);
1569
+ const dragStartPosition = (0, import_react4.useRef)(0);
1570
+ const dragStartEnd = (0, import_react4.useRef)(0);
1571
+ const width = Math.max(0, endPosition - startPosition);
1572
+ const handleMarkerMouseDown = (0, import_react4.useCallback)((e, marker) => {
1573
+ e.preventDefault();
1574
+ e.stopPropagation();
1575
+ setDraggingMarker(marker);
1576
+ dragStartX.current = e.clientX;
1577
+ dragStartPosition.current = marker === "start" ? startPosition : endPosition;
1578
+ const handleMouseMove = (moveEvent) => {
1579
+ const delta = moveEvent.clientX - dragStartX.current;
1580
+ const newPosition = dragStartPosition.current + delta;
1581
+ if (marker === "start") {
1582
+ const clampedPosition = Math.max(minPosition, Math.min(endPosition - 10, newPosition));
1583
+ onLoopStartChange?.(clampedPosition);
1584
+ } else {
1585
+ const clampedPosition = Math.max(startPosition + 10, Math.min(maxPosition, newPosition));
1586
+ onLoopEndChange?.(clampedPosition);
1587
+ }
1588
+ };
1589
+ const handleMouseUp = () => {
1590
+ setDraggingMarker(null);
1591
+ document.removeEventListener("mousemove", handleMouseMove);
1592
+ document.removeEventListener("mouseup", handleMouseUp);
1593
+ };
1594
+ document.addEventListener("mousemove", handleMouseMove);
1595
+ document.addEventListener("mouseup", handleMouseUp);
1596
+ }, [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]);
1597
+ const handleRegionMouseDown = (0, import_react4.useCallback)((e) => {
1598
+ e.preventDefault();
1599
+ e.stopPropagation();
1600
+ setDraggingMarker("region");
1601
+ dragStartX.current = e.clientX;
1602
+ dragStartPosition.current = startPosition;
1603
+ dragStartEnd.current = endPosition;
1604
+ const regionWidth = endPosition - startPosition;
1605
+ const handleMouseMove = (moveEvent) => {
1606
+ const delta = moveEvent.clientX - dragStartX.current;
1607
+ let newStart = dragStartPosition.current + delta;
1608
+ let newEnd = dragStartEnd.current + delta;
1609
+ if (newStart < minPosition) {
1610
+ newStart = minPosition;
1611
+ newEnd = minPosition + regionWidth;
1612
+ }
1613
+ if (newEnd > maxPosition) {
1614
+ newEnd = maxPosition;
1615
+ newStart = maxPosition - regionWidth;
1616
+ }
1617
+ onLoopRegionMove?.(newStart, newEnd);
1618
+ };
1619
+ const handleMouseUp = () => {
1620
+ setDraggingMarker(null);
1621
+ document.removeEventListener("mousemove", handleMouseMove);
1622
+ document.removeEventListener("mouseup", handleMouseUp);
1623
+ };
1624
+ document.addEventListener("mousemove", handleMouseMove);
1625
+ document.addEventListener("mouseup", handleMouseUp);
1626
+ }, [startPosition, endPosition, minPosition, maxPosition, onLoopRegionMove]);
1627
+ if (width <= 0) {
1628
+ return null;
1629
+ }
1630
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1631
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1632
+ TimescaleLoopShade,
1633
+ {
1634
+ $left: startPosition,
1635
+ $width: width,
1636
+ $color: regionColor,
1637
+ $isDragging: draggingMarker === "region",
1638
+ onMouseDown: handleRegionMouseDown,
1639
+ "data-loop-region-timescale": true
1640
+ }
1641
+ ),
1642
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1643
+ DraggableMarkerHandle,
1644
+ {
1645
+ $left: startPosition,
1646
+ $color: markerColor,
1647
+ $isStart: true,
1648
+ $isDragging: draggingMarker === "start",
1649
+ onMouseDown: (e) => handleMarkerMouseDown(e, "start"),
1650
+ "data-loop-marker-handle": "start"
1651
+ }
1652
+ ),
1653
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1654
+ DraggableMarkerHandle,
1655
+ {
1656
+ $left: endPosition,
1657
+ $color: markerColor,
1658
+ $isStart: false,
1659
+ $isDragging: draggingMarker === "end",
1660
+ onMouseDown: (e) => handleMarkerMouseDown(e, "end"),
1661
+ "data-loop-marker-handle": "end"
1662
+ }
1663
+ )
1664
+ ] });
1665
+ };
1666
+ var TimescaleLoopCreator = import_styled_components18.default.div.attrs((props) => ({
1667
+ style: {
1668
+ left: `${props.$leftOffset || 0}px`
1669
+ }
1670
+ }))`
1671
+ position: absolute;
1672
+ top: 0;
1673
+ right: 0;
1674
+ height: 100%; /* Stay within timescale bounds, don't extend into tracks */
1675
+ cursor: crosshair;
1676
+ z-index: 40; /* Below markers and shading */
1677
+ `;
1678
+ var TimescaleLoopRegion = ({
1679
+ startPosition,
1680
+ endPosition,
1681
+ markerColor = "#3b82f6",
1682
+ regionColor = "rgba(59, 130, 246, 0.3)",
1683
+ onLoopRegionChange,
1684
+ minPosition = 0,
1685
+ maxPosition = Infinity,
1686
+ controlsOffset = 0
1687
+ }) => {
1688
+ const [isCreating, setIsCreating] = (0, import_react4.useState)(false);
1689
+ const createStartX = (0, import_react4.useRef)(0);
1690
+ const containerRef = (0, import_react4.useRef)(null);
1691
+ const hasLoopRegion = endPosition > startPosition;
1692
+ const handleBackgroundMouseDown = (0, import_react4.useCallback)((e) => {
1693
+ const target = e.target;
1694
+ if (target.closest("[data-loop-marker-handle]") || target.closest("[data-loop-region-timescale]")) {
1695
+ return;
1696
+ }
1697
+ e.preventDefault();
1698
+ setIsCreating(true);
1699
+ const rect = containerRef.current?.getBoundingClientRect();
1700
+ if (!rect) return;
1701
+ const clickX = e.clientX - rect.left;
1702
+ const clampedX = Math.max(minPosition, Math.min(maxPosition, clickX));
1703
+ createStartX.current = clampedX;
1704
+ onLoopRegionChange?.(clampedX, clampedX);
1705
+ const handleMouseMove = (moveEvent) => {
1706
+ const currentX = moveEvent.clientX - rect.left;
1707
+ const clampedCurrentX = Math.max(minPosition, Math.min(maxPosition, currentX));
1708
+ const newStart = Math.min(createStartX.current, clampedCurrentX);
1709
+ const newEnd = Math.max(createStartX.current, clampedCurrentX);
1710
+ onLoopRegionChange?.(newStart, newEnd);
1711
+ };
1712
+ const handleMouseUp = () => {
1713
+ setIsCreating(false);
1714
+ document.removeEventListener("mousemove", handleMouseMove);
1715
+ document.removeEventListener("mouseup", handleMouseUp);
1716
+ };
1717
+ document.addEventListener("mousemove", handleMouseMove);
1718
+ document.addEventListener("mouseup", handleMouseUp);
1719
+ }, [minPosition, maxPosition, onLoopRegionChange]);
1720
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1721
+ TimescaleLoopCreator,
1722
+ {
1723
+ ref: containerRef,
1724
+ $leftOffset: controlsOffset,
1725
+ onMouseDown: handleBackgroundMouseDown,
1726
+ "data-timescale-loop-creator": true,
1727
+ children: hasLoopRegion && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1728
+ LoopRegionMarkers,
1729
+ {
1730
+ startPosition,
1731
+ endPosition,
1732
+ markerColor,
1733
+ regionColor,
1734
+ minPosition,
1735
+ maxPosition,
1736
+ onLoopStartChange: (newStart) => onLoopRegionChange?.(newStart, endPosition),
1737
+ onLoopEndChange: (newEnd) => onLoopRegionChange?.(startPosition, newEnd),
1738
+ onLoopRegionMove: (newStart, newEnd) => onLoopRegionChange?.(newStart, newEnd)
1739
+ }
1740
+ )
1741
+ }
1742
+ );
1743
+ };
1744
+
1391
1745
  // src/components/SelectionTimeInputs.tsx
1392
- var import_react5 = require("react");
1746
+ var import_react6 = require("react");
1393
1747
 
1394
1748
  // src/components/TimeInput.tsx
1395
- var import_react4 = require("react");
1749
+ var import_react5 = require("react");
1396
1750
 
1397
1751
  // src/utils/timeFormat.ts
1398
1752
  function clockFormat(seconds, decimals) {
@@ -1442,7 +1796,7 @@ function parseTime(timeStr, format) {
1442
1796
  }
1443
1797
 
1444
1798
  // src/components/TimeInput.tsx
1445
- var import_jsx_runtime12 = require("react/jsx-runtime");
1799
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1446
1800
  var TimeInput = ({
1447
1801
  id,
1448
1802
  label,
@@ -1452,8 +1806,8 @@ var TimeInput = ({
1452
1806
  onChange,
1453
1807
  readOnly = false
1454
1808
  }) => {
1455
- const [displayValue, setDisplayValue] = (0, import_react4.useState)("");
1456
- (0, import_react4.useEffect)(() => {
1809
+ const [displayValue, setDisplayValue] = (0, import_react5.useState)("");
1810
+ (0, import_react5.useEffect)(() => {
1457
1811
  const formatted = formatTime(value, format);
1458
1812
  setDisplayValue(formatted);
1459
1813
  }, [value, format, id]);
@@ -1473,9 +1827,9 @@ var TimeInput = ({
1473
1827
  e.currentTarget.blur();
1474
1828
  }
1475
1829
  };
1476
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
1477
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ScreenReaderOnly, { as: "label", htmlFor: id, children: label }),
1478
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1830
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1831
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ScreenReaderOnly, { as: "label", htmlFor: id, children: label }),
1832
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1479
1833
  BaseInput,
1480
1834
  {
1481
1835
  type: "text",
@@ -1492,15 +1846,15 @@ var TimeInput = ({
1492
1846
  };
1493
1847
 
1494
1848
  // src/components/SelectionTimeInputs.tsx
1495
- var import_jsx_runtime13 = require("react/jsx-runtime");
1849
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1496
1850
  var SelectionTimeInputs = ({
1497
1851
  selectionStart,
1498
1852
  selectionEnd,
1499
1853
  onSelectionChange,
1500
1854
  className
1501
1855
  }) => {
1502
- const [timeFormat, setTimeFormat] = (0, import_react5.useState)("hh:mm:ss.uuu");
1503
- (0, import_react5.useEffect)(() => {
1856
+ const [timeFormat, setTimeFormat] = (0, import_react6.useState)("hh:mm:ss.uuu");
1857
+ (0, import_react6.useEffect)(() => {
1504
1858
  const timeFormatSelect = document.querySelector(".time-format");
1505
1859
  const handleFormatChange = () => {
1506
1860
  if (timeFormatSelect) {
@@ -1525,8 +1879,8 @@ var SelectionTimeInputs = ({
1525
1879
  onSelectionChange(selectionStart, value);
1526
1880
  }
1527
1881
  };
1528
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
1529
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1882
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
1883
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1530
1884
  TimeInput,
1531
1885
  {
1532
1886
  id: "audio_start",
@@ -1537,7 +1891,7 @@ var SelectionTimeInputs = ({
1537
1891
  onChange: handleStartChange
1538
1892
  }
1539
1893
  ),
1540
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1894
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1541
1895
  TimeInput,
1542
1896
  {
1543
1897
  id: "audio_end",
@@ -1552,14 +1906,14 @@ var SelectionTimeInputs = ({
1552
1906
  };
1553
1907
 
1554
1908
  // src/contexts/DevicePixelRatio.tsx
1555
- var import_react6 = require("react");
1556
- var import_jsx_runtime14 = require("react/jsx-runtime");
1909
+ var import_react7 = require("react");
1910
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1557
1911
  function getScale() {
1558
1912
  return window.devicePixelRatio;
1559
1913
  }
1560
- var DevicePixelRatioContext = (0, import_react6.createContext)(getScale());
1914
+ var DevicePixelRatioContext = (0, import_react7.createContext)(getScale());
1561
1915
  var DevicePixelRatioProvider = ({ children }) => {
1562
- const [scale, setScale] = (0, import_react6.useState)(getScale());
1916
+ const [scale, setScale] = (0, import_react7.useState)(getScale());
1563
1917
  matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
1564
1918
  "change",
1565
1919
  () => {
@@ -1567,13 +1921,13 @@ var DevicePixelRatioProvider = ({ children }) => {
1567
1921
  },
1568
1922
  { once: true }
1569
1923
  );
1570
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
1924
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
1571
1925
  };
1572
- var useDevicePixelRatio = () => (0, import_react6.useContext)(DevicePixelRatioContext);
1926
+ var useDevicePixelRatio = () => (0, import_react7.useContext)(DevicePixelRatioContext);
1573
1927
 
1574
1928
  // src/contexts/PlaylistInfo.tsx
1575
- var import_react7 = require("react");
1576
- var PlaylistInfoContext = (0, import_react7.createContext)({
1929
+ var import_react8 = require("react");
1930
+ var PlaylistInfoContext = (0, import_react8.createContext)({
1577
1931
  sampleRate: 48e3,
1578
1932
  samplesPerPixel: 1e3,
1579
1933
  zoomLevels: [1e3, 1500, 2e3, 2500],
@@ -1587,22 +1941,22 @@ var PlaylistInfoContext = (0, import_react7.createContext)({
1587
1941
  barWidth: 1,
1588
1942
  barGap: 0
1589
1943
  });
1590
- var usePlaylistInfo = () => (0, import_react7.useContext)(PlaylistInfoContext);
1944
+ var usePlaylistInfo = () => (0, import_react8.useContext)(PlaylistInfoContext);
1591
1945
 
1592
1946
  // src/contexts/Theme.tsx
1593
- var import_react8 = require("react");
1594
- var import_styled_components18 = require("styled-components");
1595
- var useTheme2 = () => (0, import_react8.useContext)(import_styled_components18.ThemeContext);
1596
-
1597
- // src/contexts/TrackControls.tsx
1598
1947
  var import_react9 = require("react");
1599
- var import_jsx_runtime15 = require("react/jsx-runtime");
1600
- var TrackControlsContext = (0, import_react9.createContext)(/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_react9.Fragment, {}));
1601
- var useTrackControls = () => (0, import_react9.useContext)(TrackControlsContext);
1948
+ var import_styled_components19 = require("styled-components");
1949
+ var useTheme2 = () => (0, import_react9.useContext)(import_styled_components19.ThemeContext);
1602
1950
 
1603
- // src/contexts/Playout.tsx
1951
+ // src/contexts/TrackControls.tsx
1604
1952
  var import_react10 = require("react");
1605
1953
  var import_jsx_runtime16 = require("react/jsx-runtime");
1954
+ var TrackControlsContext = (0, import_react10.createContext)(/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_react10.Fragment, {}));
1955
+ var useTrackControls = () => (0, import_react10.useContext)(TrackControlsContext);
1956
+
1957
+ // src/contexts/Playout.tsx
1958
+ var import_react11 = require("react");
1959
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1606
1960
  var defaultProgress = 0;
1607
1961
  var defaultIsPlaying = false;
1608
1962
  var defaultSelectionStart = 0;
@@ -1613,8 +1967,8 @@ var defaultPlayout = {
1613
1967
  selectionStart: defaultSelectionStart,
1614
1968
  selectionEnd: defaultSelectionEnd
1615
1969
  };
1616
- var PlayoutStatusContext = (0, import_react10.createContext)(defaultPlayout);
1617
- var PlayoutStatusUpdateContext = (0, import_react10.createContext)({
1970
+ var PlayoutStatusContext = (0, import_react11.createContext)(defaultPlayout);
1971
+ var PlayoutStatusUpdateContext = (0, import_react11.createContext)({
1618
1972
  setIsPlaying: () => {
1619
1973
  },
1620
1974
  setProgress: () => {
@@ -1623,21 +1977,21 @@ var PlayoutStatusUpdateContext = (0, import_react10.createContext)({
1623
1977
  }
1624
1978
  });
1625
1979
  var PlayoutProvider = ({ children }) => {
1626
- const [isPlaying, setIsPlaying] = (0, import_react10.useState)(defaultIsPlaying);
1627
- const [progress, setProgress] = (0, import_react10.useState)(defaultProgress);
1628
- const [selectionStart, setSelectionStart] = (0, import_react10.useState)(defaultSelectionStart);
1629
- const [selectionEnd, setSelectionEnd] = (0, import_react10.useState)(defaultSelectionEnd);
1980
+ const [isPlaying, setIsPlaying] = (0, import_react11.useState)(defaultIsPlaying);
1981
+ const [progress, setProgress] = (0, import_react11.useState)(defaultProgress);
1982
+ const [selectionStart, setSelectionStart] = (0, import_react11.useState)(defaultSelectionStart);
1983
+ const [selectionEnd, setSelectionEnd] = (0, import_react11.useState)(defaultSelectionEnd);
1630
1984
  const setSelection = (start, end) => {
1631
1985
  setSelectionStart(start);
1632
1986
  setSelectionEnd(end);
1633
1987
  };
1634
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
1988
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
1635
1989
  };
1636
- var usePlayoutStatus = () => (0, import_react10.useContext)(PlayoutStatusContext);
1637
- var usePlayoutStatusUpdate = () => (0, import_react10.useContext)(PlayoutStatusUpdateContext);
1990
+ var usePlayoutStatus = () => (0, import_react11.useContext)(PlayoutStatusContext);
1991
+ var usePlayoutStatusUpdate = () => (0, import_react11.useContext)(PlayoutStatusUpdateContext);
1638
1992
 
1639
1993
  // src/components/SmartChannel.tsx
1640
- var import_jsx_runtime17 = require("react/jsx-runtime");
1994
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1641
1995
  var SmartChannel = ({ isSelected, transparentBackground, ...props }) => {
1642
1996
  const theme = useTheme2();
1643
1997
  const { waveHeight, barWidth, barGap } = usePlaylistInfo();
@@ -1645,7 +1999,7 @@ var SmartChannel = ({ isSelected, transparentBackground, ...props }) => {
1645
1999
  const waveOutlineColor = isSelected && theme ? theme.selectedWaveOutlineColor : theme?.waveOutlineColor;
1646
2000
  const waveFillColor = isSelected && theme ? theme.selectedWaveFillColor : theme?.waveFillColor;
1647
2001
  const drawMode = theme?.waveformDrawMode || "inverted";
1648
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
2002
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1649
2003
  Channel,
1650
2004
  {
1651
2005
  ...props,
@@ -1663,11 +2017,11 @@ var SmartChannel = ({ isSelected, transparentBackground, ...props }) => {
1663
2017
  };
1664
2018
 
1665
2019
  // src/components/SmartScale.tsx
1666
- var import_react12 = require("react");
2020
+ var import_react13 = require("react");
1667
2021
 
1668
2022
  // src/components/TimeScale.tsx
1669
- var import_react11 = __toESM(require("react"));
1670
- var import_styled_components19 = __toESM(require("styled-components"));
2023
+ var import_react12 = __toESM(require("react"));
2024
+ var import_styled_components20 = __toESM(require("styled-components"));
1671
2025
 
1672
2026
  // src/utils/conversions.ts
1673
2027
  function samplesToSeconds(samples, sampleRate) {
@@ -1690,14 +2044,14 @@ function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
1690
2044
  }
1691
2045
 
1692
2046
  // src/components/TimeScale.tsx
1693
- var import_jsx_runtime18 = require("react/jsx-runtime");
2047
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1694
2048
  function formatTime2(milliseconds) {
1695
2049
  const seconds = Math.floor(milliseconds / 1e3);
1696
2050
  const s = seconds % 60;
1697
2051
  const m = (seconds - s) / 60;
1698
2052
  return `${m}:${String(s).padStart(2, "0")}`;
1699
2053
  }
1700
- var PlaylistTimeScaleScroll = import_styled_components19.default.div.attrs((props) => ({
2054
+ var PlaylistTimeScaleScroll = import_styled_components20.default.div.attrs((props) => ({
1701
2055
  style: {
1702
2056
  width: `${props.$cssWidth}px`,
1703
2057
  marginLeft: `${props.$controlWidth}px`,
@@ -1709,7 +2063,7 @@ var PlaylistTimeScaleScroll = import_styled_components19.default.div.attrs((prop
1709
2063
  border-bottom: 1px solid ${(props) => props.theme.timeColor};
1710
2064
  box-sizing: border-box;
1711
2065
  `;
1712
- var TimeTicks = import_styled_components19.default.canvas.attrs((props) => ({
2066
+ var TimeTicks = import_styled_components20.default.canvas.attrs((props) => ({
1713
2067
  style: {
1714
2068
  width: `${props.$cssWidth}px`,
1715
2069
  height: `${props.$timeScaleHeight}px`
@@ -1720,7 +2074,7 @@ var TimeTicks = import_styled_components19.default.canvas.attrs((props) => ({
1720
2074
  right: 0;
1721
2075
  bottom: 0;
1722
2076
  `;
1723
- var TimeStamp = import_styled_components19.default.div.attrs((props) => ({
2077
+ var TimeStamp = import_styled_components20.default.div.attrs((props) => ({
1724
2078
  style: {
1725
2079
  left: `${props.$left + 4}px`
1726
2080
  // Offset 4px to the right of the tick
@@ -1742,15 +2096,15 @@ var TimeScale = (props) => {
1742
2096
  } = props;
1743
2097
  const canvasInfo = /* @__PURE__ */ new Map();
1744
2098
  const timeMarkers = [];
1745
- const canvasRef = (0, import_react11.useRef)(null);
2099
+ const canvasRef = (0, import_react12.useRef)(null);
1746
2100
  const {
1747
2101
  sampleRate,
1748
2102
  samplesPerPixel,
1749
2103
  timeScaleHeight,
1750
2104
  controls: { show: showControls, width: controlWidth }
1751
- } = (0, import_react11.useContext)(PlaylistInfoContext);
2105
+ } = (0, import_react12.useContext)(PlaylistInfoContext);
1752
2106
  const devicePixelRatio = useDevicePixelRatio();
1753
- (0, import_react11.useEffect)(() => {
2107
+ (0, import_react12.useEffect)(() => {
1754
2108
  if (canvasRef.current !== null) {
1755
2109
  const canvas = canvasRef.current;
1756
2110
  const ctx = canvas.getContext("2d");
@@ -1784,7 +2138,7 @@ var TimeScale = (props) => {
1784
2138
  if (counter % marker === 0) {
1785
2139
  const timeMs = counter;
1786
2140
  const timestamp = formatTime2(timeMs);
1787
- const timestampContent = renderTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_react11.default.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
2141
+ const timestampContent = renderTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_react12.default.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
1788
2142
  timeMarkers.push(timestampContent);
1789
2143
  canvasInfo.set(pix, timeScaleHeight);
1790
2144
  } else if (counter % bigStep === 0) {
@@ -1794,7 +2148,7 @@ var TimeScale = (props) => {
1794
2148
  }
1795
2149
  counter += secondStep;
1796
2150
  }
1797
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
2151
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1798
2152
  PlaylistTimeScaleScroll,
1799
2153
  {
1800
2154
  $cssWidth: widthX,
@@ -1802,7 +2156,7 @@ var TimeScale = (props) => {
1802
2156
  $timeScaleHeight: timeScaleHeight,
1803
2157
  children: [
1804
2158
  timeMarkers,
1805
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
2159
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1806
2160
  TimeTicks,
1807
2161
  {
1808
2162
  $cssWidth: widthX,
@@ -1816,10 +2170,10 @@ var TimeScale = (props) => {
1816
2170
  }
1817
2171
  );
1818
2172
  };
1819
- var StyledTimeScale = (0, import_styled_components19.withTheme)(TimeScale);
2173
+ var StyledTimeScale = (0, import_styled_components20.withTheme)(TimeScale);
1820
2174
 
1821
2175
  // src/components/SmartScale.tsx
1822
- var import_jsx_runtime19 = require("react/jsx-runtime");
2176
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1823
2177
  var timeinfo = /* @__PURE__ */ new Map([
1824
2178
  [
1825
2179
  700,
@@ -1893,9 +2247,9 @@ function getScaleInfo(samplesPerPixel) {
1893
2247
  return config;
1894
2248
  }
1895
2249
  var SmartScale = () => {
1896
- const { samplesPerPixel, duration } = (0, import_react12.useContext)(PlaylistInfoContext);
2250
+ const { samplesPerPixel, duration } = (0, import_react13.useContext)(PlaylistInfoContext);
1897
2251
  let config = getScaleInfo(samplesPerPixel);
1898
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
2252
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1899
2253
  StyledTimeScale,
1900
2254
  {
1901
2255
  marker: config.marker,
@@ -1907,9 +2261,9 @@ var SmartScale = () => {
1907
2261
  };
1908
2262
 
1909
2263
  // src/components/TimeFormatSelect.tsx
1910
- var import_styled_components20 = __toESM(require("styled-components"));
1911
- var import_jsx_runtime20 = require("react/jsx-runtime");
1912
- var SelectWrapper = import_styled_components20.default.div`
2264
+ var import_styled_components21 = __toESM(require("styled-components"));
2265
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2266
+ var SelectWrapper = import_styled_components21.default.div`
1913
2267
  display: inline-flex;
1914
2268
  align-items: center;
1915
2269
  gap: 0.5rem;
@@ -1931,7 +2285,7 @@ var TimeFormatSelect = ({
1931
2285
  const handleChange = (e) => {
1932
2286
  onChange(e.target.value);
1933
2287
  };
1934
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SelectWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2288
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SelectWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
1935
2289
  BaseSelect,
1936
2290
  {
1937
2291
  className: "time-format",
@@ -1939,15 +2293,15 @@ var TimeFormatSelect = ({
1939
2293
  onChange: handleChange,
1940
2294
  disabled,
1941
2295
  "aria-label": "Time format selection",
1942
- children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("option", { value: option.value, children: option.label }, option.value))
2296
+ children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("option", { value: option.value, children: option.label }, option.value))
1943
2297
  }
1944
2298
  ) });
1945
2299
  };
1946
2300
 
1947
2301
  // src/components/Track.tsx
1948
- var import_styled_components21 = __toESM(require("styled-components"));
1949
- var import_jsx_runtime21 = require("react/jsx-runtime");
1950
- var Container = import_styled_components21.default.div.attrs((props) => ({
2302
+ var import_styled_components22 = __toESM(require("styled-components"));
2303
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2304
+ var Container = import_styled_components22.default.div.attrs((props) => ({
1951
2305
  style: {
1952
2306
  height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`
1953
2307
  }
@@ -1956,7 +2310,7 @@ var Container = import_styled_components21.default.div.attrs((props) => ({
1956
2310
  display: flex;
1957
2311
  ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}
1958
2312
  `;
1959
- var ChannelContainer = import_styled_components21.default.div.attrs((props) => ({
2313
+ var ChannelContainer = import_styled_components22.default.div.attrs((props) => ({
1960
2314
  style: {
1961
2315
  paddingLeft: `${props.$offset || 0}px`
1962
2316
  }
@@ -1965,7 +2319,7 @@ var ChannelContainer = import_styled_components21.default.div.attrs((props) => (
1965
2319
  background: ${(props) => props.$backgroundColor || "transparent"};
1966
2320
  flex: 1;
1967
2321
  `;
1968
- var ControlsWrapper = import_styled_components21.default.div.attrs((props) => ({
2322
+ var ControlsWrapper = import_styled_components22.default.div.attrs((props) => ({
1969
2323
  style: {
1970
2324
  width: `${props.$controlWidth}px`
1971
2325
  }
@@ -2001,7 +2355,7 @@ var Track = ({
2001
2355
  controls: { show, width: controlWidth }
2002
2356
  } = usePlaylistInfo();
2003
2357
  const controls = useTrackControls();
2004
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2358
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
2005
2359
  Container,
2006
2360
  {
2007
2361
  $numChannels: numChannels,
@@ -2012,7 +2366,7 @@ var Track = ({
2012
2366
  $hasClipHeaders: hasClipHeaders,
2013
2367
  $isSelected: isSelected,
2014
2368
  children: [
2015
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2369
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2016
2370
  ControlsWrapper,
2017
2371
  {
2018
2372
  $controlWidth: show ? controlWidth : 0,
@@ -2020,7 +2374,7 @@ var Track = ({
2020
2374
  children: controls
2021
2375
  }
2022
2376
  ),
2023
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2377
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
2024
2378
  ChannelContainer,
2025
2379
  {
2026
2380
  $controlWidth: show ? controlWidth : 0,
@@ -2037,8 +2391,8 @@ var Track = ({
2037
2391
  };
2038
2392
 
2039
2393
  // src/components/TrackControls/Button.tsx
2040
- var import_styled_components22 = __toESM(require("styled-components"));
2041
- var Button = import_styled_components22.default.button.attrs({
2394
+ var import_styled_components23 = __toESM(require("styled-components"));
2395
+ var Button = import_styled_components23.default.button.attrs({
2042
2396
  type: "button"
2043
2397
  })`
2044
2398
  display: inline-block;
@@ -2110,8 +2464,8 @@ var Button = import_styled_components22.default.button.attrs({
2110
2464
  `;
2111
2465
 
2112
2466
  // src/components/TrackControls/ButtonGroup.tsx
2113
- var import_styled_components23 = __toESM(require("styled-components"));
2114
- var ButtonGroup = import_styled_components23.default.div`
2467
+ var import_styled_components24 = __toESM(require("styled-components"));
2468
+ var ButtonGroup = import_styled_components24.default.div`
2115
2469
  margin-bottom: 0.3rem;
2116
2470
 
2117
2471
  button:not(:first-child) {
@@ -2126,8 +2480,8 @@ var ButtonGroup = import_styled_components23.default.div`
2126
2480
  `;
2127
2481
 
2128
2482
  // src/components/TrackControls/Controls.tsx
2129
- var import_styled_components24 = __toESM(require("styled-components"));
2130
- var Controls = import_styled_components24.default.div`
2483
+ var import_styled_components25 = __toESM(require("styled-components"));
2484
+ var Controls = import_styled_components25.default.div`
2131
2485
  background: transparent;
2132
2486
  width: 100%;
2133
2487
  height: 100%;
@@ -2143,8 +2497,8 @@ var Controls = import_styled_components24.default.div`
2143
2497
  `;
2144
2498
 
2145
2499
  // src/components/TrackControls/Header.tsx
2146
- var import_styled_components25 = __toESM(require("styled-components"));
2147
- var Header = import_styled_components25.default.header`
2500
+ var import_styled_components26 = __toESM(require("styled-components"));
2501
+ var Header = import_styled_components26.default.header`
2148
2502
  overflow: hidden;
2149
2503
  height: 26px;
2150
2504
  width: 100%;
@@ -2158,23 +2512,23 @@ var Header = import_styled_components25.default.header`
2158
2512
  `;
2159
2513
 
2160
2514
  // src/components/TrackControls/VolumeDownIcon.tsx
2161
- var import_react13 = require("@phosphor-icons/react");
2162
- var import_jsx_runtime22 = require("react/jsx-runtime");
2163
- var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react13.SpeakerLowIcon, { weight: "light", ...props });
2164
-
2165
- // src/components/TrackControls/VolumeUpIcon.tsx
2166
2515
  var import_react14 = require("@phosphor-icons/react");
2167
2516
  var import_jsx_runtime23 = require("react/jsx-runtime");
2168
- var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react14.SpeakerHighIcon, { weight: "light", ...props });
2517
+ var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_react14.SpeakerLowIcon, { weight: "light", ...props });
2169
2518
 
2170
- // src/components/TrackControls/TrashIcon.tsx
2519
+ // src/components/TrackControls/VolumeUpIcon.tsx
2171
2520
  var import_react15 = require("@phosphor-icons/react");
2172
2521
  var import_jsx_runtime24 = require("react/jsx-runtime");
2173
- var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react15.TrashIcon, { weight: "light", ...props });
2522
+ var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react15.SpeakerHighIcon, { weight: "light", ...props });
2523
+
2524
+ // src/components/TrackControls/TrashIcon.tsx
2525
+ var import_react16 = require("@phosphor-icons/react");
2526
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2527
+ var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react16.TrashIcon, { weight: "light", ...props });
2174
2528
 
2175
2529
  // src/components/TrackControls/Slider.tsx
2176
- var import_styled_components26 = __toESM(require("styled-components"));
2177
- var Slider = (0, import_styled_components26.default)(BaseSlider)`
2530
+ var import_styled_components27 = __toESM(require("styled-components"));
2531
+ var Slider = (0, import_styled_components27.default)(BaseSlider)`
2178
2532
  width: 75%;
2179
2533
  height: 5px;
2180
2534
  background: ${(props) => props.theme.sliderTrackColor};
@@ -2226,8 +2580,8 @@ var Slider = (0, import_styled_components26.default)(BaseSlider)`
2226
2580
  `;
2227
2581
 
2228
2582
  // src/components/TrackControls/SliderWrapper.tsx
2229
- var import_styled_components27 = __toESM(require("styled-components"));
2230
- var SliderWrapper = import_styled_components27.default.label`
2583
+ var import_styled_components28 = __toESM(require("styled-components"));
2584
+ var SliderWrapper = import_styled_components28.default.label`
2231
2585
  width: 100%;
2232
2586
  display: flex;
2233
2587
  justify-content: space-between;
@@ -2238,15 +2592,15 @@ var SliderWrapper = import_styled_components27.default.label`
2238
2592
  `;
2239
2593
 
2240
2594
  // src/components/TrackControlsWithDelete.tsx
2241
- var import_styled_components28 = __toESM(require("styled-components"));
2242
- var import_jsx_runtime25 = require("react/jsx-runtime");
2243
- var HeaderContainer2 = import_styled_components28.default.div`
2595
+ var import_styled_components29 = __toESM(require("styled-components"));
2596
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2597
+ var HeaderContainer2 = import_styled_components29.default.div`
2244
2598
  display: flex;
2245
2599
  align-items: center;
2246
2600
  gap: 0.25rem;
2247
2601
  padding: 0.5rem 0.5rem 0.25rem 0.5rem;
2248
2602
  `;
2249
- var TrackNameSpan = import_styled_components28.default.span`
2603
+ var TrackNameSpan = import_styled_components29.default.span`
2250
2604
  flex: 1;
2251
2605
  font-weight: 600;
2252
2606
  font-size: 0.875rem;
@@ -2255,7 +2609,7 @@ var TrackNameSpan = import_styled_components28.default.span`
2255
2609
  white-space: nowrap;
2256
2610
  margin: 0 0.25rem;
2257
2611
  `;
2258
- var DeleteIconButton = import_styled_components28.default.button`
2612
+ var DeleteIconButton = import_styled_components29.default.button`
2259
2613
  display: flex;
2260
2614
  align-items: center;
2261
2615
  justify-content: center;
@@ -2293,13 +2647,13 @@ var TrackControlsWithDelete = ({
2293
2647
  onPanChange,
2294
2648
  onDelete
2295
2649
  }) => {
2296
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Controls, { children: [
2297
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(HeaderContainer2, { children: [
2298
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(DeleteIconButton, { onClick: onDelete, title: "Delete track", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TrashIcon, {}) }),
2299
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TrackNameSpan, { children: trackName })
2650
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(Controls, { children: [
2651
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(HeaderContainer2, { children: [
2652
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DeleteIconButton, { onClick: onDelete, title: "Delete track", children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TrashIcon, {}) }),
2653
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(TrackNameSpan, { children: trackName })
2300
2654
  ] }),
2301
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(ButtonGroup, { children: [
2302
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2655
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(ButtonGroup, { children: [
2656
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2303
2657
  Button,
2304
2658
  {
2305
2659
  $variant: muted ? "danger" : "outline",
@@ -2307,7 +2661,7 @@ var TrackControlsWithDelete = ({
2307
2661
  children: "Mute"
2308
2662
  }
2309
2663
  ),
2310
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2664
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2311
2665
  Button,
2312
2666
  {
2313
2667
  $variant: soloed ? "info" : "outline",
@@ -2316,9 +2670,9 @@ var TrackControlsWithDelete = ({
2316
2670
  }
2317
2671
  )
2318
2672
  ] }),
2319
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(SliderWrapper, { children: [
2320
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VolumeDownIcon, {}),
2321
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2673
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(SliderWrapper, { children: [
2674
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VolumeDownIcon, {}),
2675
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2322
2676
  Slider,
2323
2677
  {
2324
2678
  min: "0",
@@ -2328,11 +2682,11 @@ var TrackControlsWithDelete = ({
2328
2682
  onChange: (e) => onVolumeChange(parseFloat(e.target.value))
2329
2683
  }
2330
2684
  ),
2331
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(VolumeUpIcon, {})
2685
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(VolumeUpIcon, {})
2332
2686
  ] }),
2333
- /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(SliderWrapper, { children: [
2334
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "L" }),
2335
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2687
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(SliderWrapper, { children: [
2688
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "L" }),
2689
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2336
2690
  Slider,
2337
2691
  {
2338
2692
  min: "-1",
@@ -2342,7 +2696,7 @@ var TrackControlsWithDelete = ({
2342
2696
  onChange: (e) => onPanChange(parseFloat(e.target.value))
2343
2697
  }
2344
2698
  ),
2345
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { children: "R" })
2699
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { children: "R" })
2346
2700
  ] })
2347
2701
  ] });
2348
2702
  };
@@ -2362,6 +2716,7 @@ var TrackControlsWithDelete = ({
2362
2716
  Button,
2363
2717
  ButtonGroup,
2364
2718
  CLIP_BOUNDARY_WIDTH,
2719
+ CLIP_BOUNDARY_WIDTH_TOUCH,
2365
2720
  CLIP_HEADER_HEIGHT,
2366
2721
  Channel,
2367
2722
  Clip,
@@ -2373,6 +2728,8 @@ var TrackControlsWithDelete = ({
2373
2728
  FadeOverlay,
2374
2729
  Header,
2375
2730
  InlineLabel,
2731
+ LoopRegion,
2732
+ LoopRegionMarkers,
2376
2733
  MasterVolumeControl,
2377
2734
  Playhead,
2378
2735
  PlayheadWithMarker,
@@ -2391,6 +2748,7 @@ var TrackControlsWithDelete = ({
2391
2748
  TimeFormatSelect,
2392
2749
  TimeInput,
2393
2750
  TimeScale,
2751
+ TimescaleLoopRegion,
2394
2752
  Track,
2395
2753
  TrackControlsContext,
2396
2754
  TrackControlsWithDelete,