@waveform-playlist/ui-components 5.0.0-alpha.1 → 5.0.0-alpha.11

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.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
- overflow: visible;
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
- z-index: 1; /* Low z-index - clip headers and boundaries have higher z-index */
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 useState2 } from "react";
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 Fragment2, jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
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] = useState("");
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__ */ jsxs6(Fragment2, { children: [
1375
- /* @__PURE__ */ jsx12(ScreenReaderOnly, { as: "label", htmlFor: id, children: label }),
1376
- /* @__PURE__ */ jsx12(
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 Fragment3, jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
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] = useState2("hh:mm:ss.uuu");
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__ */ jsxs7(Fragment3, { children: [
1427
- /* @__PURE__ */ jsx13(
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__ */ jsx13(
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 useState3, createContext, useContext } from "react";
1454
- import { jsx as jsx14 } from "react/jsx-runtime";
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] = useState3(getScale());
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__ */ jsx14(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
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 Fragment4 } from "react";
1497
- import { jsx as jsx15 } from "react/jsx-runtime";
1498
- var TrackControlsContext = createContext3(/* @__PURE__ */ jsx15(Fragment4, {}));
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 useState4,
1853
+ useState as useState5,
1504
1854
  createContext as createContext4,
1505
1855
  useContext as useContext5
1506
1856
  } from "react";
1507
- import { jsx as jsx16 } from "react/jsx-runtime";
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] = useState4(defaultIsPlaying);
1529
- const [progress, setProgress] = useState4(defaultProgress);
1530
- const [selectionStart, setSelectionStart] = useState4(defaultSelectionStart);
1531
- const [selectionEnd, setSelectionEnd] = useState4(defaultSelectionEnd);
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__ */ jsx16(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ jsx16(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
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 jsx17 } from "react/jsx-runtime";
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__ */ jsx17(
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 React9, { useRef as useRef3, useEffect as useEffect4, useContext as useContext6 } from "react";
1572
- import styled18, { withTheme as withTheme2 } from "styled-components";
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 jsx18, jsxs as jsxs8 } from "react/jsx-runtime";
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 = styled18.div.attrs((props) => ({
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 = styled18.canvas.attrs((props) => ({
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 = styled18.div.attrs((props) => ({
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 = useRef3(null);
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__ */ jsx18(React9.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ jsx18(TimeStamp, { $left: pix, children: timestamp }, timestamp);
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__ */ jsxs8(
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__ */ jsx18(
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 jsx19 } from "react/jsx-runtime";
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__ */ jsx19(
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 styled19 from "styled-components";
1813
- import { jsx as jsx20 } from "react/jsx-runtime";
1814
- var SelectWrapper = styled19.div`
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__ */ jsx20(SelectWrapper, { className, children: /* @__PURE__ */ jsx20(
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__ */ jsx20("option", { value: option.value, children: option.label }, option.value))
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 styled20 from "styled-components";
1851
- import { jsx as jsx21, jsxs as jsxs9 } from "react/jsx-runtime";
1852
- var Container = styled20.div.attrs((props) => ({
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 = styled20.div.attrs((props) => ({
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 = styled20.div.attrs((props) => ({
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__ */ jsxs9(
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__ */ jsx21(
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__ */ jsx21(
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 styled21 from "styled-components";
1943
- var Button = styled21.button.attrs({
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 styled22 from "styled-components";
2016
- var ButtonGroup = styled22.div`
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 styled23 from "styled-components";
2032
- var Controls = styled23.div`
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 styled24 from "styled-components";
2049
- var Header = styled24.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 jsx22 } from "react/jsx-runtime";
2065
- var VolumeDownIcon = (props) => /* @__PURE__ */ jsx22(SpeakerLowIcon, { weight: "light", ...props });
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 jsx23 } from "react/jsx-runtime";
2070
- var VolumeUpIcon = (props) => /* @__PURE__ */ jsx23(SpeakerHighIcon, { weight: "light", ...props });
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 jsx24 } from "react/jsx-runtime";
2075
- var TrashIcon = (props) => /* @__PURE__ */ jsx24(PhosphorTrashIcon, { weight: "light", ...props });
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 styled25 from "styled-components";
2079
- var Slider = styled25(BaseSlider)`
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 styled26 from "styled-components";
2132
- var SliderWrapper = styled26.label`
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 styled27 from "styled-components";
2144
- import { jsx as jsx25, jsxs as jsxs10 } from "react/jsx-runtime";
2145
- var HeaderContainer2 = styled27.div`
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 = styled27.span`
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 = styled27.button`
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__ */ jsxs10(Controls, { children: [
2199
- /* @__PURE__ */ jsxs10(HeaderContainer2, { children: [
2200
- /* @__PURE__ */ jsx25(DeleteIconButton, { onClick: onDelete, title: "Delete track", children: /* @__PURE__ */ jsx25(TrashIcon, {}) }),
2201
- /* @__PURE__ */ jsx25(TrackNameSpan, { children: trackName })
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__ */ jsxs10(ButtonGroup, { children: [
2204
- /* @__PURE__ */ jsx25(
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__ */ jsx25(
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__ */ jsxs10(SliderWrapper, { children: [
2222
- /* @__PURE__ */ jsx25(VolumeDownIcon, {}),
2223
- /* @__PURE__ */ jsx25(
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__ */ jsx25(VolumeUpIcon, {})
2583
+ /* @__PURE__ */ jsx26(VolumeUpIcon, {})
2234
2584
  ] }),
2235
- /* @__PURE__ */ jsxs10(SliderWrapper, { children: [
2236
- /* @__PURE__ */ jsx25("span", { children: "L" }),
2237
- /* @__PURE__ */ jsx25(
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__ */ jsx25("span", { children: "R" })
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,