@waveform-playlist/ui-components 9.1.2 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +45 -7
- package/dist/index.d.ts +45 -7
- package/dist/index.js +309 -302
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +265 -257
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -38,9 +38,12 @@ __export(index_exports, {
|
|
|
38
38
|
BaseCheckboxWrapper: () => BaseCheckboxWrapper,
|
|
39
39
|
BaseControlButton: () => BaseControlButton,
|
|
40
40
|
BaseInput: () => BaseInput,
|
|
41
|
+
BaseInputSmall: () => BaseInputSmall,
|
|
41
42
|
BaseLabel: () => BaseLabel,
|
|
42
43
|
BaseSelect: () => BaseSelect,
|
|
44
|
+
BaseSelectSmall: () => BaseSelectSmall,
|
|
43
45
|
BaseSlider: () => BaseSlider,
|
|
46
|
+
BeatsAndBarsProvider: () => BeatsAndBarsProvider,
|
|
44
47
|
Button: () => Button,
|
|
45
48
|
ButtonGroup: () => ButtonGroup,
|
|
46
49
|
CLIP_BOUNDARY_WIDTH: () => CLIP_BOUNDARY_WIDTH,
|
|
@@ -94,14 +97,16 @@ __export(index_exports, {
|
|
|
94
97
|
darkTheme: () => darkTheme,
|
|
95
98
|
defaultTheme: () => defaultTheme,
|
|
96
99
|
formatTime: () => formatTime,
|
|
100
|
+
getScaleInfo: () => getScaleInfo,
|
|
97
101
|
isWaveformGradient: () => isWaveformGradient,
|
|
98
102
|
parseTime: () => parseTime,
|
|
99
103
|
pixelsToSamples: () => pixelsToSamples,
|
|
100
104
|
pixelsToSeconds: () => pixelsToSeconds,
|
|
101
|
-
samplesToPixels: () =>
|
|
105
|
+
samplesToPixels: () => samplesToPixels2,
|
|
102
106
|
samplesToSeconds: () => samplesToSeconds,
|
|
103
|
-
secondsToPixels: () =>
|
|
107
|
+
secondsToPixels: () => secondsToPixels2,
|
|
104
108
|
secondsToSamples: () => secondsToSamples,
|
|
109
|
+
useBeatsAndBars: () => useBeatsAndBars,
|
|
105
110
|
useClipViewportOrigin: () => useClipViewportOrigin,
|
|
106
111
|
useDevicePixelRatio: () => useDevicePixelRatio,
|
|
107
112
|
usePlaylistInfo: () => usePlaylistInfo,
|
|
@@ -890,7 +895,6 @@ var Channel = (props) => {
|
|
|
890
895
|
const clipOriginX = useClipViewportOrigin();
|
|
891
896
|
const visibleChunkIndices = useVisibleChunkIndices(length, import_core.MAX_CANVAS_WIDTH, clipOriginX);
|
|
892
897
|
(0, import_react4.useEffect)(() => {
|
|
893
|
-
const tDraw = performance.now();
|
|
894
898
|
const step = barWidth + barGap;
|
|
895
899
|
for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
|
|
896
900
|
const globalPixelOffset = canvasIdx * import_core.MAX_CANVAS_WIDTH;
|
|
@@ -926,9 +930,6 @@ var Channel = (props) => {
|
|
|
926
930
|
}
|
|
927
931
|
}
|
|
928
932
|
}
|
|
929
|
-
console.log(
|
|
930
|
-
`[waveform] draw ch${index}: ${canvasMapRef.current.size} chunks, ${(performance.now() - tDraw).toFixed(1)}ms`
|
|
931
|
-
);
|
|
932
933
|
}, [
|
|
933
934
|
canvasMapRef,
|
|
934
935
|
data,
|
|
@@ -1268,20 +1269,20 @@ var Clip = ({
|
|
|
1268
1269
|
isDragSource
|
|
1269
1270
|
} = (0, import_react7.useDraggable)({
|
|
1270
1271
|
id: draggableId,
|
|
1271
|
-
data: { clipId, trackIndex, clipIndex },
|
|
1272
|
+
data: { clipId, trackIndex, clipIndex, startSample, durationSamples },
|
|
1272
1273
|
disabled: !enableDrag
|
|
1273
1274
|
});
|
|
1274
1275
|
const leftBoundaryId = `clip-boundary-left-${trackIndex}-${clipIndex}`;
|
|
1275
1276
|
const { ref: leftBoundaryRef, isDragSource: isLeftBoundaryDragging } = (0, import_react7.useDraggable)({
|
|
1276
1277
|
id: leftBoundaryId,
|
|
1277
|
-
data: { clipId, trackIndex, clipIndex, boundary: "left" },
|
|
1278
|
+
data: { clipId, trackIndex, clipIndex, boundary: "left", startSample, durationSamples },
|
|
1278
1279
|
disabled: !enableDrag,
|
|
1279
1280
|
feedback: "none"
|
|
1280
1281
|
});
|
|
1281
1282
|
const rightBoundaryId = `clip-boundary-right-${trackIndex}-${clipIndex}`;
|
|
1282
1283
|
const { ref: rightBoundaryRef, isDragSource: isRightBoundaryDragging } = (0, import_react7.useDraggable)({
|
|
1283
1284
|
id: rightBoundaryId,
|
|
1284
|
-
data: { clipId, trackIndex, clipIndex, boundary: "right" },
|
|
1285
|
+
data: { clipId, trackIndex, clipIndex, boundary: "right", startSample, durationSamples },
|
|
1285
1286
|
disabled: !enableDrag,
|
|
1286
1287
|
feedback: "none"
|
|
1287
1288
|
});
|
|
@@ -1466,7 +1467,6 @@ var PianoRollChannel = ({
|
|
|
1466
1467
|
}, [midiNotes]);
|
|
1467
1468
|
const color = isSelected ? selectedNoteColor : noteColor;
|
|
1468
1469
|
(0, import_react8.useEffect)(() => {
|
|
1469
|
-
const tDraw = performance.now();
|
|
1470
1470
|
const noteRange = maxMidi - minMidi + 1;
|
|
1471
1471
|
const noteHeight = Math.max(2, waveHeight / noteRange);
|
|
1472
1472
|
const pixelsPerSecond = sampleRate / samplesPerPixel;
|
|
@@ -1498,9 +1498,6 @@ var PianoRollChannel = ({
|
|
|
1498
1498
|
}
|
|
1499
1499
|
ctx.globalAlpha = 1;
|
|
1500
1500
|
}
|
|
1501
|
-
console.log(
|
|
1502
|
-
`[piano-roll] draw ch${index}: ${canvasMapRef.current.size} chunks, ${midiNotes.length} notes, ${(performance.now() - tDraw).toFixed(1)}ms`
|
|
1503
|
-
);
|
|
1504
1501
|
}, [
|
|
1505
1502
|
canvasMapRef,
|
|
1506
1503
|
midiNotes,
|
|
@@ -2292,15 +2289,45 @@ var SelectionTimeInputs = ({
|
|
|
2292
2289
|
] });
|
|
2293
2290
|
};
|
|
2294
2291
|
|
|
2295
|
-
// src/contexts/
|
|
2292
|
+
// src/contexts/BeatsAndBars.tsx
|
|
2296
2293
|
var import_react14 = require("react");
|
|
2294
|
+
var import_core4 = require("@waveform-playlist/core");
|
|
2297
2295
|
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
2296
|
+
var BeatsAndBarsContext = (0, import_react14.createContext)(null);
|
|
2297
|
+
function BeatsAndBarsProvider({
|
|
2298
|
+
bpm,
|
|
2299
|
+
timeSignature,
|
|
2300
|
+
snapTo,
|
|
2301
|
+
children
|
|
2302
|
+
}) {
|
|
2303
|
+
const [numerator, denominator] = timeSignature;
|
|
2304
|
+
const value = (0, import_react14.useMemo)(() => {
|
|
2305
|
+
const ts = [numerator, denominator];
|
|
2306
|
+
const tpBeat = (0, import_core4.ticksPerBeat)(ts);
|
|
2307
|
+
const tpBar = (0, import_core4.ticksPerBar)(ts);
|
|
2308
|
+
return {
|
|
2309
|
+
bpm,
|
|
2310
|
+
timeSignature: ts,
|
|
2311
|
+
snapTo,
|
|
2312
|
+
ticksPerBeat: tpBeat,
|
|
2313
|
+
ticksPerBar: tpBar
|
|
2314
|
+
};
|
|
2315
|
+
}, [bpm, numerator, denominator, snapTo]);
|
|
2316
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(BeatsAndBarsContext.Provider, { value, children });
|
|
2317
|
+
}
|
|
2318
|
+
function useBeatsAndBars() {
|
|
2319
|
+
return (0, import_react14.useContext)(BeatsAndBarsContext);
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
// src/contexts/DevicePixelRatio.tsx
|
|
2323
|
+
var import_react15 = require("react");
|
|
2324
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2298
2325
|
function getScale() {
|
|
2299
2326
|
return window.devicePixelRatio;
|
|
2300
2327
|
}
|
|
2301
|
-
var DevicePixelRatioContext = (0,
|
|
2328
|
+
var DevicePixelRatioContext = (0, import_react15.createContext)(getScale());
|
|
2302
2329
|
var DevicePixelRatioProvider = ({ children }) => {
|
|
2303
|
-
const [scale, setScale] = (0,
|
|
2330
|
+
const [scale, setScale] = (0, import_react15.useState)(getScale());
|
|
2304
2331
|
matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(
|
|
2305
2332
|
"change",
|
|
2306
2333
|
() => {
|
|
@@ -2308,13 +2335,13 @@ var DevicePixelRatioProvider = ({ children }) => {
|
|
|
2308
2335
|
},
|
|
2309
2336
|
{ once: true }
|
|
2310
2337
|
);
|
|
2311
|
-
return /* @__PURE__ */ (0,
|
|
2338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });
|
|
2312
2339
|
};
|
|
2313
|
-
var useDevicePixelRatio = () => (0,
|
|
2340
|
+
var useDevicePixelRatio = () => (0, import_react15.useContext)(DevicePixelRatioContext);
|
|
2314
2341
|
|
|
2315
2342
|
// src/contexts/PlaylistInfo.tsx
|
|
2316
|
-
var
|
|
2317
|
-
var PlaylistInfoContext = (0,
|
|
2343
|
+
var import_react16 = require("react");
|
|
2344
|
+
var PlaylistInfoContext = (0, import_react16.createContext)({
|
|
2318
2345
|
sampleRate: 48e3,
|
|
2319
2346
|
samplesPerPixel: 1e3,
|
|
2320
2347
|
zoomLevels: [1e3, 1500, 2e3, 2500],
|
|
@@ -2328,22 +2355,22 @@ var PlaylistInfoContext = (0, import_react15.createContext)({
|
|
|
2328
2355
|
barWidth: 1,
|
|
2329
2356
|
barGap: 0
|
|
2330
2357
|
});
|
|
2331
|
-
var usePlaylistInfo = () => (0,
|
|
2358
|
+
var usePlaylistInfo = () => (0, import_react16.useContext)(PlaylistInfoContext);
|
|
2332
2359
|
|
|
2333
2360
|
// src/contexts/Theme.tsx
|
|
2334
|
-
var
|
|
2361
|
+
var import_react17 = require("react");
|
|
2335
2362
|
var import_styled_components20 = require("styled-components");
|
|
2336
|
-
var useTheme2 = () => (0,
|
|
2363
|
+
var useTheme2 = () => (0, import_react17.useContext)(import_styled_components20.ThemeContext);
|
|
2337
2364
|
|
|
2338
2365
|
// src/contexts/TrackControls.tsx
|
|
2339
|
-
var import_react17 = require("react");
|
|
2340
|
-
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
2341
|
-
var TrackControlsContext = (0, import_react17.createContext)(/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_react17.Fragment, {}));
|
|
2342
|
-
var useTrackControls = () => (0, import_react17.useContext)(TrackControlsContext);
|
|
2343
|
-
|
|
2344
|
-
// src/contexts/Playout.tsx
|
|
2345
2366
|
var import_react18 = require("react");
|
|
2346
2367
|
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
2368
|
+
var TrackControlsContext = (0, import_react18.createContext)(/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_react18.Fragment, {}));
|
|
2369
|
+
var useTrackControls = () => (0, import_react18.useContext)(TrackControlsContext);
|
|
2370
|
+
|
|
2371
|
+
// src/contexts/Playout.tsx
|
|
2372
|
+
var import_react19 = require("react");
|
|
2373
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
2347
2374
|
var defaultProgress = 0;
|
|
2348
2375
|
var defaultIsPlaying = false;
|
|
2349
2376
|
var defaultSelectionStart = 0;
|
|
@@ -2354,8 +2381,8 @@ var defaultPlayout = {
|
|
|
2354
2381
|
selectionStart: defaultSelectionStart,
|
|
2355
2382
|
selectionEnd: defaultSelectionEnd
|
|
2356
2383
|
};
|
|
2357
|
-
var PlayoutStatusContext = (0,
|
|
2358
|
-
var PlayoutStatusUpdateContext = (0,
|
|
2384
|
+
var PlayoutStatusContext = (0, import_react19.createContext)(defaultPlayout);
|
|
2385
|
+
var PlayoutStatusUpdateContext = (0, import_react19.createContext)({
|
|
2359
2386
|
setIsPlaying: () => {
|
|
2360
2387
|
},
|
|
2361
2388
|
setProgress: () => {
|
|
@@ -2364,24 +2391,24 @@ var PlayoutStatusUpdateContext = (0, import_react18.createContext)({
|
|
|
2364
2391
|
}
|
|
2365
2392
|
});
|
|
2366
2393
|
var PlayoutProvider = ({ children }) => {
|
|
2367
|
-
const [isPlaying, setIsPlaying] = (0,
|
|
2368
|
-
const [progress, setProgress] = (0,
|
|
2369
|
-
const [selectionStart, setSelectionStart] = (0,
|
|
2370
|
-
const [selectionEnd, setSelectionEnd] = (0,
|
|
2394
|
+
const [isPlaying, setIsPlaying] = (0, import_react19.useState)(defaultIsPlaying);
|
|
2395
|
+
const [progress, setProgress] = (0, import_react19.useState)(defaultProgress);
|
|
2396
|
+
const [selectionStart, setSelectionStart] = (0, import_react19.useState)(defaultSelectionStart);
|
|
2397
|
+
const [selectionEnd, setSelectionEnd] = (0, import_react19.useState)(defaultSelectionEnd);
|
|
2371
2398
|
const setSelection = (start, end) => {
|
|
2372
2399
|
setSelectionStart(start);
|
|
2373
2400
|
setSelectionEnd(end);
|
|
2374
2401
|
};
|
|
2375
|
-
return /* @__PURE__ */ (0,
|
|
2402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });
|
|
2376
2403
|
};
|
|
2377
|
-
var usePlayoutStatus = () => (0,
|
|
2378
|
-
var usePlayoutStatusUpdate = () => (0,
|
|
2404
|
+
var usePlayoutStatus = () => (0, import_react19.useContext)(PlayoutStatusContext);
|
|
2405
|
+
var usePlayoutStatusUpdate = () => (0, import_react19.useContext)(PlayoutStatusUpdateContext);
|
|
2379
2406
|
|
|
2380
2407
|
// src/components/SpectrogramChannel.tsx
|
|
2381
|
-
var
|
|
2408
|
+
var import_react20 = require("react");
|
|
2382
2409
|
var import_styled_components21 = __toESM(require("styled-components"));
|
|
2383
|
-
var
|
|
2384
|
-
var
|
|
2410
|
+
var import_core5 = require("@waveform-playlist/core");
|
|
2411
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
2385
2412
|
var LINEAR_FREQUENCY_SCALE = (f, minF, maxF) => (f - minF) / (maxF - minF);
|
|
2386
2413
|
var Wrapper4 = import_styled_components21.default.div.attrs((props) => ({
|
|
2387
2414
|
style: {
|
|
@@ -2433,24 +2460,24 @@ var SpectrogramChannel = ({
|
|
|
2433
2460
|
}) => {
|
|
2434
2461
|
const channelIndex = channelIndexProp ?? index;
|
|
2435
2462
|
const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
|
|
2436
|
-
const registeredIdsRef = (0,
|
|
2437
|
-
const transferredCanvasesRef = (0,
|
|
2438
|
-
const workerApiRef = (0,
|
|
2439
|
-
const onCanvasesReadyRef = (0,
|
|
2463
|
+
const registeredIdsRef = (0, import_react20.useRef)([]);
|
|
2464
|
+
const transferredCanvasesRef = (0, import_react20.useRef)(/* @__PURE__ */ new WeakSet());
|
|
2465
|
+
const workerApiRef = (0, import_react20.useRef)(workerApi);
|
|
2466
|
+
const onCanvasesReadyRef = (0, import_react20.useRef)(onCanvasesReady);
|
|
2440
2467
|
const isWorkerMode = !!(workerApi && clipId);
|
|
2441
2468
|
const clipOriginX = useClipViewportOrigin();
|
|
2442
|
-
const visibleChunkIndices = useVisibleChunkIndices(length,
|
|
2469
|
+
const visibleChunkIndices = useVisibleChunkIndices(length, import_core5.MAX_CANVAS_WIDTH, clipOriginX);
|
|
2443
2470
|
const lut = colorLUT ?? DEFAULT_COLOR_LUT;
|
|
2444
2471
|
const maxF = maxFrequency ?? (data ? data.sampleRate / 2 : 22050);
|
|
2445
2472
|
const scaleFn = frequencyScaleFn ?? LINEAR_FREQUENCY_SCALE;
|
|
2446
2473
|
const hasCustomFrequencyScale = Boolean(frequencyScaleFn);
|
|
2447
|
-
(0,
|
|
2474
|
+
(0, import_react20.useEffect)(() => {
|
|
2448
2475
|
workerApiRef.current = workerApi;
|
|
2449
2476
|
}, [workerApi]);
|
|
2450
|
-
(0,
|
|
2477
|
+
(0, import_react20.useEffect)(() => {
|
|
2451
2478
|
onCanvasesReadyRef.current = onCanvasesReady;
|
|
2452
2479
|
}, [onCanvasesReady]);
|
|
2453
|
-
(0,
|
|
2480
|
+
(0, import_react20.useEffect)(() => {
|
|
2454
2481
|
if (!isWorkerMode) return;
|
|
2455
2482
|
const currentWorkerApi = workerApiRef.current;
|
|
2456
2483
|
if (!currentWorkerApi || !clipId) return;
|
|
@@ -2505,15 +2532,15 @@ var SpectrogramChannel = ({
|
|
|
2505
2532
|
const match = id.match(/chunk(\d+)$/);
|
|
2506
2533
|
if (!match) {
|
|
2507
2534
|
console.warn(`[spectrogram] Unexpected canvas ID format: ${id}`);
|
|
2508
|
-
return
|
|
2535
|
+
return import_core5.MAX_CANVAS_WIDTH;
|
|
2509
2536
|
}
|
|
2510
2537
|
const chunkIdx = parseInt(match[1], 10);
|
|
2511
|
-
return Math.min(length - chunkIdx *
|
|
2538
|
+
return Math.min(length - chunkIdx * import_core5.MAX_CANVAS_WIDTH, import_core5.MAX_CANVAS_WIDTH);
|
|
2512
2539
|
});
|
|
2513
2540
|
onCanvasesReadyRef.current?.(allIds, allWidths);
|
|
2514
2541
|
}
|
|
2515
2542
|
}, [canvasMapRef, isWorkerMode, clipId, channelIndex, length, visibleChunkIndices]);
|
|
2516
|
-
(0,
|
|
2543
|
+
(0, import_react20.useEffect)(() => {
|
|
2517
2544
|
return () => {
|
|
2518
2545
|
const api = workerApiRef.current;
|
|
2519
2546
|
if (!api) return;
|
|
@@ -2527,7 +2554,7 @@ var SpectrogramChannel = ({
|
|
|
2527
2554
|
registeredIdsRef.current = [];
|
|
2528
2555
|
};
|
|
2529
2556
|
}, []);
|
|
2530
|
-
(0,
|
|
2557
|
+
(0, import_react20.useEffect)(() => {
|
|
2531
2558
|
if (isWorkerMode || !data) return;
|
|
2532
2559
|
const {
|
|
2533
2560
|
frequencyBinCount,
|
|
@@ -2540,7 +2567,7 @@ var SpectrogramChannel = ({
|
|
|
2540
2567
|
const rangeDb = rawRangeDb === 0 ? 1 : rawRangeDb;
|
|
2541
2568
|
const binToFreq = (bin) => bin / frequencyBinCount * (sampleRate / 2);
|
|
2542
2569
|
for (const [canvasIdx, canvas] of canvasMapRef.current.entries()) {
|
|
2543
|
-
const globalPixelOffset = canvasIdx *
|
|
2570
|
+
const globalPixelOffset = canvasIdx * import_core5.MAX_CANVAS_WIDTH;
|
|
2544
2571
|
const ctx = canvas.getContext("2d");
|
|
2545
2572
|
if (!ctx) continue;
|
|
2546
2573
|
const canvasWidth = canvas.width / devicePixelRatio;
|
|
@@ -2616,9 +2643,9 @@ var SpectrogramChannel = ({
|
|
|
2616
2643
|
visibleChunkIndices
|
|
2617
2644
|
]);
|
|
2618
2645
|
const canvases = visibleChunkIndices.map((i) => {
|
|
2619
|
-
const chunkLeft = i *
|
|
2620
|
-
const currentWidth = Math.min(length - chunkLeft,
|
|
2621
|
-
return /* @__PURE__ */ (0,
|
|
2646
|
+
const chunkLeft = i * import_core5.MAX_CANVAS_WIDTH;
|
|
2647
|
+
const currentWidth = Math.min(length - chunkLeft, import_core5.MAX_CANVAS_WIDTH);
|
|
2648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
2622
2649
|
SpectrogramCanvas,
|
|
2623
2650
|
{
|
|
2624
2651
|
$cssWidth: currentWidth,
|
|
@@ -2632,11 +2659,11 @@ var SpectrogramChannel = ({
|
|
|
2632
2659
|
`${length}-${i}`
|
|
2633
2660
|
);
|
|
2634
2661
|
});
|
|
2635
|
-
return /* @__PURE__ */ (0,
|
|
2662
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Wrapper4, { $index: index, $cssWidth: length, $waveHeight: waveHeight, children: canvases });
|
|
2636
2663
|
};
|
|
2637
2664
|
|
|
2638
2665
|
// src/components/SmartChannel.tsx
|
|
2639
|
-
var
|
|
2666
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
2640
2667
|
var SmartChannel = ({
|
|
2641
2668
|
isSelected,
|
|
2642
2669
|
transparentBackground,
|
|
@@ -2670,7 +2697,7 @@ var SmartChannel = ({
|
|
|
2670
2697
|
const drawMode = theme?.waveformDrawMode || "inverted";
|
|
2671
2698
|
const hasSpectrogram = spectrogramData || spectrogramWorkerApi;
|
|
2672
2699
|
if (renderMode === "spectrogram" && hasSpectrogram) {
|
|
2673
|
-
return /* @__PURE__ */ (0,
|
|
2700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2674
2701
|
SpectrogramChannel,
|
|
2675
2702
|
{
|
|
2676
2703
|
index: props.index,
|
|
@@ -2691,8 +2718,8 @@ var SmartChannel = ({
|
|
|
2691
2718
|
}
|
|
2692
2719
|
if (renderMode === "both" && hasSpectrogram) {
|
|
2693
2720
|
const halfHeight = Math.floor(waveHeight / 2);
|
|
2694
|
-
return /* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
2722
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2696
2723
|
SpectrogramChannel,
|
|
2697
2724
|
{
|
|
2698
2725
|
index: props.index * 2,
|
|
@@ -2711,7 +2738,7 @@ var SmartChannel = ({
|
|
|
2711
2738
|
onCanvasesReady: spectrogramOnCanvasesReady
|
|
2712
2739
|
}
|
|
2713
2740
|
),
|
|
2714
|
-
/* @__PURE__ */ (0,
|
|
2741
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2715
2742
|
"div",
|
|
2716
2743
|
{
|
|
2717
2744
|
style: {
|
|
@@ -2720,7 +2747,7 @@ var SmartChannel = ({
|
|
|
2720
2747
|
width: props.length,
|
|
2721
2748
|
height: halfHeight
|
|
2722
2749
|
},
|
|
2723
|
-
children: /* @__PURE__ */ (0,
|
|
2750
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2724
2751
|
Channel,
|
|
2725
2752
|
{
|
|
2726
2753
|
...props,
|
|
@@ -2740,7 +2767,7 @@ var SmartChannel = ({
|
|
|
2740
2767
|
] });
|
|
2741
2768
|
}
|
|
2742
2769
|
if (renderMode === "piano-roll") {
|
|
2743
|
-
return /* @__PURE__ */ (0,
|
|
2770
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2744
2771
|
PianoRollChannel,
|
|
2745
2772
|
{
|
|
2746
2773
|
index: props.index,
|
|
@@ -2759,7 +2786,7 @@ var SmartChannel = ({
|
|
|
2759
2786
|
}
|
|
2760
2787
|
);
|
|
2761
2788
|
}
|
|
2762
|
-
return /* @__PURE__ */ (0,
|
|
2789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2763
2790
|
Channel,
|
|
2764
2791
|
{
|
|
2765
2792
|
...props,
|
|
@@ -2776,9 +2803,9 @@ var SmartChannel = ({
|
|
|
2776
2803
|
};
|
|
2777
2804
|
|
|
2778
2805
|
// src/components/SpectrogramLabels.tsx
|
|
2779
|
-
var
|
|
2806
|
+
var import_react21 = require("react");
|
|
2780
2807
|
var import_styled_components22 = __toESM(require("styled-components"));
|
|
2781
|
-
var
|
|
2808
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2782
2809
|
var LABELS_WIDTH = 72;
|
|
2783
2810
|
var LabelsStickyWrapper = import_styled_components22.default.div`
|
|
2784
2811
|
position: sticky;
|
|
@@ -2828,12 +2855,12 @@ var SpectrogramLabels = ({
|
|
|
2828
2855
|
renderMode = "spectrogram",
|
|
2829
2856
|
hasClipHeaders = false
|
|
2830
2857
|
}) => {
|
|
2831
|
-
const canvasRef = (0,
|
|
2858
|
+
const canvasRef = (0, import_react21.useRef)(null);
|
|
2832
2859
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2833
2860
|
const spectrogramHeight = renderMode === "both" ? Math.floor(waveHeight / 2) : waveHeight;
|
|
2834
2861
|
const totalHeight = numChannels * waveHeight;
|
|
2835
2862
|
const clipHeaderOffset = hasClipHeaders ? 22 : 0;
|
|
2836
|
-
(0,
|
|
2863
|
+
(0, import_react21.useLayoutEffect)(() => {
|
|
2837
2864
|
const canvas = canvasRef.current;
|
|
2838
2865
|
if (!canvas) return;
|
|
2839
2866
|
const ctx = canvas.getContext("2d");
|
|
@@ -2871,7 +2898,7 @@ var SpectrogramLabels = ({
|
|
|
2871
2898
|
spectrogramHeight,
|
|
2872
2899
|
clipHeaderOffset
|
|
2873
2900
|
]);
|
|
2874
|
-
return /* @__PURE__ */ (0,
|
|
2901
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(LabelsStickyWrapper, { $height: totalHeight + clipHeaderOffset, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2875
2902
|
"canvas",
|
|
2876
2903
|
{
|
|
2877
2904
|
ref: canvasRef,
|
|
@@ -2887,41 +2914,14 @@ var SpectrogramLabels = ({
|
|
|
2887
2914
|
};
|
|
2888
2915
|
|
|
2889
2916
|
// src/components/SmartScale.tsx
|
|
2890
|
-
var
|
|
2917
|
+
var import_react23 = __toESM(require("react"));
|
|
2918
|
+
var import_styled_components24 = __toESM(require("styled-components"));
|
|
2891
2919
|
|
|
2892
2920
|
// src/components/TimeScale.tsx
|
|
2893
|
-
var
|
|
2921
|
+
var import_react22 = require("react");
|
|
2894
2922
|
var import_styled_components23 = __toESM(require("styled-components"));
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
function samplesToSeconds(samples, sampleRate) {
|
|
2898
|
-
return samples / sampleRate;
|
|
2899
|
-
}
|
|
2900
|
-
function secondsToSamples(seconds, sampleRate) {
|
|
2901
|
-
return Math.ceil(seconds * sampleRate);
|
|
2902
|
-
}
|
|
2903
|
-
function samplesToPixels(samples, samplesPerPixel) {
|
|
2904
|
-
return Math.floor(samples / samplesPerPixel);
|
|
2905
|
-
}
|
|
2906
|
-
function pixelsToSamples(pixels, samplesPerPixel) {
|
|
2907
|
-
return Math.floor(pixels * samplesPerPixel);
|
|
2908
|
-
}
|
|
2909
|
-
function pixelsToSeconds(pixels, samplesPerPixel, sampleRate) {
|
|
2910
|
-
return pixels * samplesPerPixel / sampleRate;
|
|
2911
|
-
}
|
|
2912
|
-
function secondsToPixels(seconds, samplesPerPixel, sampleRate) {
|
|
2913
|
-
return Math.ceil(seconds * sampleRate / samplesPerPixel);
|
|
2914
|
-
}
|
|
2915
|
-
|
|
2916
|
-
// src/components/TimeScale.tsx
|
|
2917
|
-
var import_core5 = require("@waveform-playlist/core");
|
|
2918
|
-
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2919
|
-
function formatTime2(milliseconds) {
|
|
2920
|
-
const seconds = Math.floor(milliseconds / 1e3);
|
|
2921
|
-
const s = seconds % 60;
|
|
2922
|
-
const m = (seconds - s) / 60;
|
|
2923
|
-
return `${m}:${String(s).padStart(2, "0")}`;
|
|
2924
|
-
}
|
|
2923
|
+
var import_core6 = require("@waveform-playlist/core");
|
|
2924
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2925
2925
|
var PlaylistTimeScaleScroll = import_styled_components23.default.div.attrs((props) => ({
|
|
2926
2926
|
style: {
|
|
2927
2927
|
width: `${props.$cssWidth}px`,
|
|
@@ -2943,70 +2943,20 @@ var TimeTickChunk = import_styled_components23.default.canvas.attrs((props) => (
|
|
|
2943
2943
|
position: absolute;
|
|
2944
2944
|
bottom: 0;
|
|
2945
2945
|
`;
|
|
2946
|
-
var TimeStamp = import_styled_components23.default.div.attrs((props) => ({
|
|
2947
|
-
style: {
|
|
2948
|
-
left: `${props.$left + 4}px`
|
|
2949
|
-
// Offset 4px to the right of the tick
|
|
2950
|
-
}
|
|
2951
|
-
}))`
|
|
2952
|
-
position: absolute;
|
|
2953
|
-
font-size: 0.75rem; /* Smaller font to prevent overflow */
|
|
2954
|
-
white-space: nowrap; /* Prevent text wrapping */
|
|
2955
|
-
color: ${(props) => props.theme.timeColor}; /* Use theme color instead of inheriting */
|
|
2956
|
-
`;
|
|
2957
2946
|
var TimeScale = (props) => {
|
|
2958
2947
|
const {
|
|
2959
2948
|
theme: { timeColor },
|
|
2960
|
-
|
|
2961
|
-
marker,
|
|
2962
|
-
bigStep,
|
|
2963
|
-
secondStep,
|
|
2964
|
-
renderTimestamp
|
|
2949
|
+
tickData
|
|
2965
2950
|
} = props;
|
|
2966
2951
|
const { canvasRef, canvasMapRef } = useChunkedCanvasRefs();
|
|
2967
|
-
const {
|
|
2952
|
+
const { timeScaleHeight } = (0, import_react22.useContext)(PlaylistInfoContext);
|
|
2968
2953
|
const devicePixelRatio = useDevicePixelRatio();
|
|
2969
|
-
const { widthX, canvasInfo, timeMarkersWithPositions } =
|
|
2970
|
-
|
|
2971
|
-
const nextMarkers = [];
|
|
2972
|
-
const nextWidthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);
|
|
2973
|
-
const pixPerSec = sampleRate / samplesPerPixel;
|
|
2974
|
-
let counter = 0;
|
|
2975
|
-
for (let i = 0; i < nextWidthX; i += pixPerSec * secondStep / 1e3) {
|
|
2976
|
-
const pix = Math.floor(i);
|
|
2977
|
-
if (counter % marker === 0) {
|
|
2978
|
-
const timeMs = counter;
|
|
2979
|
-
const timestamp = formatTime2(timeMs);
|
|
2980
|
-
const element = renderTimestamp ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react21.default.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
|
|
2981
|
-
nextMarkers.push({ pix, element });
|
|
2982
|
-
nextCanvasInfo.set(pix, timeScaleHeight);
|
|
2983
|
-
} else if (counter % bigStep === 0) {
|
|
2984
|
-
nextCanvasInfo.set(pix, Math.floor(timeScaleHeight / 2));
|
|
2985
|
-
} else if (counter % secondStep === 0) {
|
|
2986
|
-
nextCanvasInfo.set(pix, Math.floor(timeScaleHeight / 5));
|
|
2987
|
-
}
|
|
2988
|
-
counter += secondStep;
|
|
2989
|
-
}
|
|
2990
|
-
return {
|
|
2991
|
-
widthX: nextWidthX,
|
|
2992
|
-
canvasInfo: nextCanvasInfo,
|
|
2993
|
-
timeMarkersWithPositions: nextMarkers
|
|
2994
|
-
};
|
|
2995
|
-
}, [
|
|
2996
|
-
duration,
|
|
2997
|
-
samplesPerPixel,
|
|
2998
|
-
sampleRate,
|
|
2999
|
-
marker,
|
|
3000
|
-
bigStep,
|
|
3001
|
-
secondStep,
|
|
3002
|
-
renderTimestamp,
|
|
3003
|
-
timeScaleHeight
|
|
3004
|
-
]);
|
|
3005
|
-
const visibleChunkIndices = useVisibleChunkIndices(widthX, import_core5.MAX_CANVAS_WIDTH);
|
|
2954
|
+
const { widthX, canvasInfo, timeMarkersWithPositions } = tickData;
|
|
2955
|
+
const visibleChunkIndices = useVisibleChunkIndices(widthX, import_core6.MAX_CANVAS_WIDTH);
|
|
3006
2956
|
const visibleChunks = visibleChunkIndices.map((i) => {
|
|
3007
|
-
const chunkLeft = i *
|
|
3008
|
-
const chunkWidth = Math.min(widthX - chunkLeft,
|
|
3009
|
-
return /* @__PURE__ */ (0,
|
|
2957
|
+
const chunkLeft = i * import_core6.MAX_CANVAS_WIDTH;
|
|
2958
|
+
const chunkWidth = Math.min(widthX - chunkLeft, import_core6.MAX_CANVAS_WIDTH);
|
|
2959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
3010
2960
|
TimeTickChunk,
|
|
3011
2961
|
{
|
|
3012
2962
|
$cssWidth: chunkWidth,
|
|
@@ -3020,14 +2970,14 @@ var TimeScale = (props) => {
|
|
|
3020
2970
|
`timescale-${i}`
|
|
3021
2971
|
);
|
|
3022
2972
|
});
|
|
3023
|
-
const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] *
|
|
3024
|
-
const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) *
|
|
2973
|
+
const firstChunkLeft = visibleChunkIndices.length > 0 ? visibleChunkIndices[0] * import_core6.MAX_CANVAS_WIDTH : 0;
|
|
2974
|
+
const lastChunkRight = visibleChunkIndices.length > 0 ? (visibleChunkIndices[visibleChunkIndices.length - 1] + 1) * import_core6.MAX_CANVAS_WIDTH : Infinity;
|
|
3025
2975
|
const visibleMarkers = visibleChunkIndices.length > 0 ? timeMarkersWithPositions.filter(({ pix }) => pix >= firstChunkLeft && pix < lastChunkRight).map(({ element }) => element) : timeMarkersWithPositions.map(({ element }) => element);
|
|
3026
|
-
(0,
|
|
2976
|
+
(0, import_react22.useLayoutEffect)(() => {
|
|
3027
2977
|
for (const [chunkIdx, canvas] of canvasMapRef.current.entries()) {
|
|
3028
2978
|
const ctx = canvas.getContext("2d");
|
|
3029
2979
|
if (!ctx) continue;
|
|
3030
|
-
const chunkLeft = chunkIdx *
|
|
2980
|
+
const chunkLeft = chunkIdx * import_core6.MAX_CANVAS_WIDTH;
|
|
3031
2981
|
const chunkWidth = canvas.width / devicePixelRatio;
|
|
3032
2982
|
ctx.resetTransform();
|
|
3033
2983
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
@@ -3041,16 +2991,8 @@ var TimeScale = (props) => {
|
|
|
3041
2991
|
ctx.fillRect(localX, scaleY, 1, scaleHeight);
|
|
3042
2992
|
}
|
|
3043
2993
|
}
|
|
3044
|
-
}, [
|
|
3045
|
-
|
|
3046
|
-
duration,
|
|
3047
|
-
devicePixelRatio,
|
|
3048
|
-
timeColor,
|
|
3049
|
-
timeScaleHeight,
|
|
3050
|
-
canvasInfo,
|
|
3051
|
-
visibleChunkIndices
|
|
3052
|
-
]);
|
|
3053
|
-
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(PlaylistTimeScaleScroll, { $cssWidth: widthX, $timeScaleHeight: timeScaleHeight, children: [
|
|
2994
|
+
}, [canvasMapRef, devicePixelRatio, timeColor, timeScaleHeight, canvasInfo, visibleChunkIndices]);
|
|
2995
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(PlaylistTimeScaleScroll, { $cssWidth: widthX, $timeScaleHeight: timeScaleHeight, children: [
|
|
3054
2996
|
visibleMarkers,
|
|
3055
2997
|
visibleChunks
|
|
3056
2998
|
] });
|
|
@@ -3058,64 +3000,16 @@ var TimeScale = (props) => {
|
|
|
3058
3000
|
var StyledTimeScale = (0, import_styled_components23.withTheme)(TimeScale);
|
|
3059
3001
|
|
|
3060
3002
|
// src/components/SmartScale.tsx
|
|
3061
|
-
var
|
|
3003
|
+
var import_core7 = require("@waveform-playlist/core");
|
|
3004
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
3062
3005
|
var timeinfo = /* @__PURE__ */ new Map([
|
|
3063
|
-
[
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
],
|
|
3071
|
-
[
|
|
3072
|
-
1500,
|
|
3073
|
-
{
|
|
3074
|
-
marker: 2e3,
|
|
3075
|
-
bigStep: 1e3,
|
|
3076
|
-
smallStep: 200
|
|
3077
|
-
}
|
|
3078
|
-
],
|
|
3079
|
-
[
|
|
3080
|
-
2500,
|
|
3081
|
-
{
|
|
3082
|
-
marker: 2e3,
|
|
3083
|
-
bigStep: 1e3,
|
|
3084
|
-
smallStep: 500
|
|
3085
|
-
}
|
|
3086
|
-
],
|
|
3087
|
-
[
|
|
3088
|
-
5e3,
|
|
3089
|
-
{
|
|
3090
|
-
marker: 5e3,
|
|
3091
|
-
bigStep: 1e3,
|
|
3092
|
-
smallStep: 500
|
|
3093
|
-
}
|
|
3094
|
-
],
|
|
3095
|
-
[
|
|
3096
|
-
1e4,
|
|
3097
|
-
{
|
|
3098
|
-
marker: 1e4,
|
|
3099
|
-
bigStep: 5e3,
|
|
3100
|
-
smallStep: 1e3
|
|
3101
|
-
}
|
|
3102
|
-
],
|
|
3103
|
-
[
|
|
3104
|
-
12e3,
|
|
3105
|
-
{
|
|
3106
|
-
marker: 15e3,
|
|
3107
|
-
bigStep: 5e3,
|
|
3108
|
-
smallStep: 1e3
|
|
3109
|
-
}
|
|
3110
|
-
],
|
|
3111
|
-
[
|
|
3112
|
-
Infinity,
|
|
3113
|
-
{
|
|
3114
|
-
marker: 3e4,
|
|
3115
|
-
bigStep: 1e4,
|
|
3116
|
-
smallStep: 5e3
|
|
3117
|
-
}
|
|
3118
|
-
]
|
|
3006
|
+
[700, { marker: 1e3, bigStep: 500, smallStep: 100 }],
|
|
3007
|
+
[1500, { marker: 2e3, bigStep: 1e3, smallStep: 200 }],
|
|
3008
|
+
[2500, { marker: 2e3, bigStep: 1e3, smallStep: 500 }],
|
|
3009
|
+
[5e3, { marker: 5e3, bigStep: 1e3, smallStep: 500 }],
|
|
3010
|
+
[1e4, { marker: 1e4, bigStep: 5e3, smallStep: 1e3 }],
|
|
3011
|
+
[12e3, { marker: 15e3, bigStep: 5e3, smallStep: 1e3 }],
|
|
3012
|
+
[Infinity, { marker: 3e4, bigStep: 1e4, smallStep: 5e3 }]
|
|
3119
3013
|
]);
|
|
3120
3014
|
function getScaleInfo(samplesPerPixel) {
|
|
3121
3015
|
const keys = timeinfo.keys();
|
|
@@ -3131,25 +3025,113 @@ function getScaleInfo(samplesPerPixel) {
|
|
|
3131
3025
|
}
|
|
3132
3026
|
return config;
|
|
3133
3027
|
}
|
|
3134
|
-
|
|
3135
|
-
const
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3028
|
+
function formatTime2(milliseconds) {
|
|
3029
|
+
const seconds = Math.floor(milliseconds / 1e3);
|
|
3030
|
+
const s = seconds % 60;
|
|
3031
|
+
const m = (seconds - s) / 60;
|
|
3032
|
+
return `${m}:${String(s).padStart(2, "0")}`;
|
|
3033
|
+
}
|
|
3034
|
+
var TimeStamp = import_styled_components24.default.div.attrs((props) => ({
|
|
3035
|
+
style: {
|
|
3036
|
+
left: `${props.$left + 4}px`
|
|
3037
|
+
// Offset 4px to the right of the tick
|
|
3038
|
+
}
|
|
3039
|
+
}))`
|
|
3040
|
+
position: absolute;
|
|
3041
|
+
font-size: 0.75rem; /* Smaller font to prevent overflow */
|
|
3042
|
+
white-space: nowrap; /* Prevent text wrapping */
|
|
3043
|
+
color: ${(props) => props.theme.timeColor}; /* Use theme color instead of inheriting */
|
|
3044
|
+
`;
|
|
3045
|
+
var SmartScale = ({ renderTick }) => {
|
|
3046
|
+
const { samplesPerPixel, sampleRate, duration, timeScaleHeight } = (0, import_react23.useContext)(PlaylistInfoContext);
|
|
3047
|
+
const beatsAndBars = useBeatsAndBars();
|
|
3048
|
+
const tickData = (0, import_react23.useMemo)(() => {
|
|
3049
|
+
const widthX = (0, import_core7.secondsToPixels)(duration / 1e3, samplesPerPixel, sampleRate);
|
|
3050
|
+
if (beatsAndBars) {
|
|
3051
|
+
const { bpm, timeSignature, ticksPerBar: tpBar, ticksPerBeat: tpBeat } = beatsAndBars;
|
|
3052
|
+
const canvasInfo2 = /* @__PURE__ */ new Map();
|
|
3053
|
+
const timeMarkersWithPositions2 = [];
|
|
3054
|
+
const durationSeconds = duration / 1e3;
|
|
3055
|
+
const totalTicks = Math.ceil(durationSeconds * bpm * import_core7.PPQN / 60);
|
|
3056
|
+
const pixelsPerBeat = (0, import_core7.ticksToSamples)(tpBeat, bpm, sampleRate) / samplesPerPixel;
|
|
3057
|
+
const pixelsPerBar = (0, import_core7.ticksToSamples)(tpBar, bpm, sampleRate) / samplesPerPixel;
|
|
3058
|
+
const MIN_TICK_PX = 10;
|
|
3059
|
+
const MIN_LABEL_PX = 30;
|
|
3060
|
+
let tickStep;
|
|
3061
|
+
if (pixelsPerBeat >= MIN_TICK_PX) {
|
|
3062
|
+
tickStep = tpBeat;
|
|
3063
|
+
} else if (pixelsPerBar >= MIN_TICK_PX) {
|
|
3064
|
+
tickStep = tpBar;
|
|
3065
|
+
} else {
|
|
3066
|
+
const barsPerTick = Math.ceil(MIN_TICK_PX / pixelsPerBar);
|
|
3067
|
+
tickStep = tpBar * barsPerTick;
|
|
3068
|
+
}
|
|
3069
|
+
let labelStep;
|
|
3070
|
+
if (pixelsPerBeat >= MIN_LABEL_PX) {
|
|
3071
|
+
labelStep = tpBeat;
|
|
3072
|
+
} else if (pixelsPerBar >= MIN_LABEL_PX) {
|
|
3073
|
+
labelStep = tpBar;
|
|
3074
|
+
} else {
|
|
3075
|
+
const barsPerLabel = Math.ceil(MIN_LABEL_PX / pixelsPerBar);
|
|
3076
|
+
labelStep = tpBar * barsPerLabel;
|
|
3077
|
+
}
|
|
3078
|
+
for (let tick = 0; tick <= totalTicks; tick += tickStep) {
|
|
3079
|
+
const samples = (0, import_core7.ticksToSamples)(tick, bpm, sampleRate);
|
|
3080
|
+
const pix = (0, import_core7.samplesToPixels)(samples, samplesPerPixel);
|
|
3081
|
+
if (pix >= widthX) break;
|
|
3082
|
+
const isBarLine = tick % tpBar === 0;
|
|
3083
|
+
const isLabelTick = tick % labelStep === 0;
|
|
3084
|
+
const tickHeight = isBarLine ? timeScaleHeight : isLabelTick ? Math.floor(timeScaleHeight / 2) : Math.floor(timeScaleHeight / 5);
|
|
3085
|
+
canvasInfo2.set(pix, tickHeight);
|
|
3086
|
+
if (isLabelTick) {
|
|
3087
|
+
const label = (0, import_core7.ticksToBarBeatLabel)(tick, timeSignature);
|
|
3088
|
+
const element = renderTick ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react23.default.Fragment, { children: renderTick(label, pix) }, `bb-${tick}`) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3089
|
+
"div",
|
|
3090
|
+
{
|
|
3091
|
+
style: {
|
|
3092
|
+
position: "absolute",
|
|
3093
|
+
left: `${pix + 4}px`,
|
|
3094
|
+
fontSize: "0.75rem",
|
|
3095
|
+
whiteSpace: "nowrap"
|
|
3096
|
+
},
|
|
3097
|
+
children: label
|
|
3098
|
+
},
|
|
3099
|
+
`bb-${tick}`
|
|
3100
|
+
);
|
|
3101
|
+
timeMarkersWithPositions2.push({ pix, element });
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
return { widthX, canvasInfo: canvasInfo2, timeMarkersWithPositions: timeMarkersWithPositions2 };
|
|
3145
3105
|
}
|
|
3146
|
-
|
|
3106
|
+
const config = getScaleInfo(samplesPerPixel);
|
|
3107
|
+
const { marker, bigStep, smallStep } = config;
|
|
3108
|
+
const canvasInfo = /* @__PURE__ */ new Map();
|
|
3109
|
+
const timeMarkersWithPositions = [];
|
|
3110
|
+
const pixPerSec = sampleRate / samplesPerPixel;
|
|
3111
|
+
let counter = 0;
|
|
3112
|
+
for (let i = 0; i < widthX; i += pixPerSec * smallStep / 1e3) {
|
|
3113
|
+
const pix = Math.floor(i);
|
|
3114
|
+
if (counter % marker === 0) {
|
|
3115
|
+
const timestamp = formatTime2(counter);
|
|
3116
|
+
const element = renderTick ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_react23.default.Fragment, { children: renderTick(timestamp, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TimeStamp, { $left: pix, children: timestamp }, timestamp);
|
|
3117
|
+
timeMarkersWithPositions.push({ pix, element });
|
|
3118
|
+
canvasInfo.set(pix, timeScaleHeight);
|
|
3119
|
+
} else if (counter % bigStep === 0) {
|
|
3120
|
+
canvasInfo.set(pix, Math.floor(timeScaleHeight / 2));
|
|
3121
|
+
} else if (counter % smallStep === 0) {
|
|
3122
|
+
canvasInfo.set(pix, Math.floor(timeScaleHeight / 5));
|
|
3123
|
+
}
|
|
3124
|
+
counter += smallStep;
|
|
3125
|
+
}
|
|
3126
|
+
return { widthX, canvasInfo, timeMarkersWithPositions };
|
|
3127
|
+
}, [beatsAndBars, duration, samplesPerPixel, sampleRate, timeScaleHeight, renderTick]);
|
|
3128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(StyledTimeScale, { tickData });
|
|
3147
3129
|
};
|
|
3148
3130
|
|
|
3149
3131
|
// src/components/TimeFormatSelect.tsx
|
|
3150
|
-
var
|
|
3151
|
-
var
|
|
3152
|
-
var SelectWrapper =
|
|
3132
|
+
var import_styled_components25 = __toESM(require("styled-components"));
|
|
3133
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
3134
|
+
var SelectWrapper = import_styled_components25.default.div`
|
|
3153
3135
|
display: inline-flex;
|
|
3154
3136
|
align-items: center;
|
|
3155
3137
|
gap: 0.5rem;
|
|
@@ -3171,7 +3153,7 @@ var TimeFormatSelect = ({
|
|
|
3171
3153
|
const handleChange = (e) => {
|
|
3172
3154
|
onChange(e.target.value);
|
|
3173
3155
|
};
|
|
3174
|
-
return /* @__PURE__ */ (0,
|
|
3156
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SelectWrapper, { className, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
3175
3157
|
BaseSelect,
|
|
3176
3158
|
{
|
|
3177
3159
|
className: "time-format",
|
|
@@ -3179,15 +3161,15 @@ var TimeFormatSelect = ({
|
|
|
3179
3161
|
onChange: handleChange,
|
|
3180
3162
|
disabled,
|
|
3181
3163
|
"aria-label": "Time format selection",
|
|
3182
|
-
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0,
|
|
3164
|
+
children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("option", { value: option.value, children: option.label }, option.value))
|
|
3183
3165
|
}
|
|
3184
3166
|
) });
|
|
3185
3167
|
};
|
|
3186
3168
|
|
|
3187
3169
|
// src/components/Track.tsx
|
|
3188
|
-
var
|
|
3189
|
-
var
|
|
3190
|
-
var Container =
|
|
3170
|
+
var import_styled_components26 = __toESM(require("styled-components"));
|
|
3171
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
3172
|
+
var Container = import_styled_components26.default.div.attrs((props) => ({
|
|
3191
3173
|
style: {
|
|
3192
3174
|
height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`
|
|
3193
3175
|
}
|
|
@@ -3195,7 +3177,7 @@ var Container = import_styled_components25.default.div.attrs((props) => ({
|
|
|
3195
3177
|
position: relative;
|
|
3196
3178
|
${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}
|
|
3197
3179
|
`;
|
|
3198
|
-
var ChannelContainer =
|
|
3180
|
+
var ChannelContainer = import_styled_components26.default.div.attrs((props) => ({
|
|
3199
3181
|
style: {
|
|
3200
3182
|
paddingLeft: `${props.$offset || 0}px`
|
|
3201
3183
|
}
|
|
@@ -3217,7 +3199,7 @@ var Track = ({
|
|
|
3217
3199
|
isSelected: _isSelected = false
|
|
3218
3200
|
}) => {
|
|
3219
3201
|
const { waveHeight } = usePlaylistInfo();
|
|
3220
|
-
return /* @__PURE__ */ (0,
|
|
3202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
3221
3203
|
Container,
|
|
3222
3204
|
{
|
|
3223
3205
|
$numChannels: numChannels,
|
|
@@ -3225,7 +3207,7 @@ var Track = ({
|
|
|
3225
3207
|
$waveHeight: waveHeight,
|
|
3226
3208
|
$width: width,
|
|
3227
3209
|
$hasClipHeaders: hasClipHeaders,
|
|
3228
|
-
children: /* @__PURE__ */ (0,
|
|
3210
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
3229
3211
|
ChannelContainer,
|
|
3230
3212
|
{
|
|
3231
3213
|
$backgroundColor: backgroundColor,
|
|
@@ -3240,8 +3222,8 @@ var Track = ({
|
|
|
3240
3222
|
};
|
|
3241
3223
|
|
|
3242
3224
|
// src/components/TrackControls/Button.tsx
|
|
3243
|
-
var
|
|
3244
|
-
var Button =
|
|
3225
|
+
var import_styled_components27 = __toESM(require("styled-components"));
|
|
3226
|
+
var Button = import_styled_components27.default.button.attrs({
|
|
3245
3227
|
type: "button"
|
|
3246
3228
|
})`
|
|
3247
3229
|
display: inline-block;
|
|
@@ -3316,8 +3298,8 @@ var Button = import_styled_components26.default.button.attrs({
|
|
|
3316
3298
|
`;
|
|
3317
3299
|
|
|
3318
3300
|
// src/components/TrackControls/ButtonGroup.tsx
|
|
3319
|
-
var
|
|
3320
|
-
var ButtonGroup =
|
|
3301
|
+
var import_styled_components28 = __toESM(require("styled-components"));
|
|
3302
|
+
var ButtonGroup = import_styled_components28.default.div`
|
|
3321
3303
|
margin-bottom: 0.3rem;
|
|
3322
3304
|
|
|
3323
3305
|
button:not(:first-child) {
|
|
@@ -3332,10 +3314,10 @@ var ButtonGroup = import_styled_components27.default.div`
|
|
|
3332
3314
|
`;
|
|
3333
3315
|
|
|
3334
3316
|
// src/components/TrackControls/CloseButton.tsx
|
|
3335
|
-
var
|
|
3336
|
-
var
|
|
3337
|
-
var
|
|
3338
|
-
var StyledCloseButton =
|
|
3317
|
+
var import_styled_components29 = __toESM(require("styled-components"));
|
|
3318
|
+
var import_react24 = require("@phosphor-icons/react");
|
|
3319
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
3320
|
+
var StyledCloseButton = import_styled_components29.default.button`
|
|
3339
3321
|
position: absolute;
|
|
3340
3322
|
left: 0;
|
|
3341
3323
|
top: 0;
|
|
@@ -3358,11 +3340,11 @@ var StyledCloseButton = import_styled_components28.default.button`
|
|
|
3358
3340
|
color: #dc3545;
|
|
3359
3341
|
}
|
|
3360
3342
|
`;
|
|
3361
|
-
var CloseButton = ({ onClick, title = "Remove track" }) => /* @__PURE__ */ (0,
|
|
3343
|
+
var CloseButton = ({ onClick, title = "Remove track" }) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(StyledCloseButton, { onClick, title, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react24.X, { size: 12, weight: "bold" }) });
|
|
3362
3344
|
|
|
3363
3345
|
// src/components/TrackControls/Controls.tsx
|
|
3364
|
-
var
|
|
3365
|
-
var Controls =
|
|
3346
|
+
var import_styled_components30 = __toESM(require("styled-components"));
|
|
3347
|
+
var Controls = import_styled_components30.default.div`
|
|
3366
3348
|
background: transparent;
|
|
3367
3349
|
width: 100%;
|
|
3368
3350
|
height: 100%;
|
|
@@ -3378,8 +3360,8 @@ var Controls = import_styled_components29.default.div`
|
|
|
3378
3360
|
`;
|
|
3379
3361
|
|
|
3380
3362
|
// src/components/TrackControls/Header.tsx
|
|
3381
|
-
var
|
|
3382
|
-
var Header =
|
|
3363
|
+
var import_styled_components31 = __toESM(require("styled-components"));
|
|
3364
|
+
var Header = import_styled_components31.default.header`
|
|
3383
3365
|
overflow: hidden;
|
|
3384
3366
|
height: 26px;
|
|
3385
3367
|
width: 100%;
|
|
@@ -3393,28 +3375,28 @@ var Header = import_styled_components30.default.header`
|
|
|
3393
3375
|
`;
|
|
3394
3376
|
|
|
3395
3377
|
// src/components/TrackControls/VolumeDownIcon.tsx
|
|
3396
|
-
var import_react24 = require("@phosphor-icons/react");
|
|
3397
|
-
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
3398
|
-
var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_react24.SpeakerLowIcon, { weight: "light", ...props });
|
|
3399
|
-
|
|
3400
|
-
// src/components/TrackControls/VolumeUpIcon.tsx
|
|
3401
3378
|
var import_react25 = require("@phosphor-icons/react");
|
|
3402
3379
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
3403
|
-
var
|
|
3380
|
+
var VolumeDownIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_react25.SpeakerLowIcon, { weight: "light", ...props });
|
|
3404
3381
|
|
|
3405
|
-
// src/components/TrackControls/
|
|
3382
|
+
// src/components/TrackControls/VolumeUpIcon.tsx
|
|
3406
3383
|
var import_react26 = require("@phosphor-icons/react");
|
|
3407
3384
|
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
3408
|
-
var
|
|
3385
|
+
var VolumeUpIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_react26.SpeakerHighIcon, { weight: "light", ...props });
|
|
3409
3386
|
|
|
3410
|
-
// src/components/TrackControls/
|
|
3387
|
+
// src/components/TrackControls/TrashIcon.tsx
|
|
3411
3388
|
var import_react27 = require("@phosphor-icons/react");
|
|
3412
3389
|
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
3413
|
-
var
|
|
3390
|
+
var TrashIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_react27.TrashIcon, { weight: "light", ...props });
|
|
3391
|
+
|
|
3392
|
+
// src/components/TrackControls/DotsIcon.tsx
|
|
3393
|
+
var import_react28 = require("@phosphor-icons/react");
|
|
3394
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
3395
|
+
var DotsIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_react28.DotsThreeIcon, { weight: "bold", ...props });
|
|
3414
3396
|
|
|
3415
3397
|
// src/components/TrackControls/Slider.tsx
|
|
3416
|
-
var
|
|
3417
|
-
var Slider = (0,
|
|
3398
|
+
var import_styled_components32 = __toESM(require("styled-components"));
|
|
3399
|
+
var Slider = (0, import_styled_components32.default)(BaseSlider)`
|
|
3418
3400
|
width: 75%;
|
|
3419
3401
|
height: 5px;
|
|
3420
3402
|
background: ${(props) => props.theme.sliderTrackColor};
|
|
@@ -3466,8 +3448,8 @@ var Slider = (0, import_styled_components31.default)(BaseSlider)`
|
|
|
3466
3448
|
`;
|
|
3467
3449
|
|
|
3468
3450
|
// src/components/TrackControls/SliderWrapper.tsx
|
|
3469
|
-
var
|
|
3470
|
-
var SliderWrapper =
|
|
3451
|
+
var import_styled_components33 = __toESM(require("styled-components"));
|
|
3452
|
+
var SliderWrapper = import_styled_components33.default.label`
|
|
3471
3453
|
width: 100%;
|
|
3472
3454
|
display: flex;
|
|
3473
3455
|
justify-content: space-between;
|
|
@@ -3478,15 +3460,15 @@ var SliderWrapper = import_styled_components32.default.label`
|
|
|
3478
3460
|
`;
|
|
3479
3461
|
|
|
3480
3462
|
// src/components/TrackMenu.tsx
|
|
3481
|
-
var
|
|
3463
|
+
var import_react29 = __toESM(require("react"));
|
|
3482
3464
|
var import_react_dom = require("react-dom");
|
|
3483
|
-
var
|
|
3484
|
-
var
|
|
3485
|
-
var MenuContainer =
|
|
3465
|
+
var import_styled_components34 = __toESM(require("styled-components"));
|
|
3466
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
3467
|
+
var MenuContainer = import_styled_components34.default.div`
|
|
3486
3468
|
position: relative;
|
|
3487
3469
|
display: inline-block;
|
|
3488
3470
|
`;
|
|
3489
|
-
var MenuButton =
|
|
3471
|
+
var MenuButton = import_styled_components34.default.button`
|
|
3490
3472
|
background: none;
|
|
3491
3473
|
border: none;
|
|
3492
3474
|
cursor: pointer;
|
|
@@ -3502,7 +3484,7 @@ var MenuButton = import_styled_components33.default.button`
|
|
|
3502
3484
|
}
|
|
3503
3485
|
`;
|
|
3504
3486
|
var DROPDOWN_MIN_WIDTH = 180;
|
|
3505
|
-
var Dropdown =
|
|
3487
|
+
var Dropdown = import_styled_components34.default.div`
|
|
3506
3488
|
position: fixed;
|
|
3507
3489
|
top: ${(p) => p.$top}px;
|
|
3508
3490
|
left: ${(p) => p.$left}px;
|
|
@@ -3515,19 +3497,19 @@ var Dropdown = import_styled_components33.default.div`
|
|
|
3515
3497
|
min-width: ${DROPDOWN_MIN_WIDTH}px;
|
|
3516
3498
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
3517
3499
|
`;
|
|
3518
|
-
var Divider =
|
|
3500
|
+
var Divider = import_styled_components34.default.hr`
|
|
3519
3501
|
border: none;
|
|
3520
3502
|
border-top: 1px solid rgba(128, 128, 128, 0.3);
|
|
3521
3503
|
margin: 0.35rem 0;
|
|
3522
3504
|
`;
|
|
3523
3505
|
var TrackMenu = ({ items: itemsProp }) => {
|
|
3524
|
-
const [open, setOpen] = (0,
|
|
3525
|
-
const close = (0,
|
|
3506
|
+
const [open, setOpen] = (0, import_react29.useState)(false);
|
|
3507
|
+
const close = (0, import_react29.useCallback)(() => setOpen(false), []);
|
|
3526
3508
|
const items = typeof itemsProp === "function" ? itemsProp(close) : itemsProp;
|
|
3527
|
-
const [dropdownPos, setDropdownPos] = (0,
|
|
3528
|
-
const buttonRef = (0,
|
|
3529
|
-
const dropdownRef = (0,
|
|
3530
|
-
const updatePosition = (0,
|
|
3509
|
+
const [dropdownPos, setDropdownPos] = (0, import_react29.useState)({ top: 0, left: 0 });
|
|
3510
|
+
const buttonRef = (0, import_react29.useRef)(null);
|
|
3511
|
+
const dropdownRef = (0, import_react29.useRef)(null);
|
|
3512
|
+
const updatePosition = (0, import_react29.useCallback)(() => {
|
|
3531
3513
|
if (!buttonRef.current) return;
|
|
3532
3514
|
const rect = buttonRef.current.getBoundingClientRect();
|
|
3533
3515
|
const vw = window.innerWidth;
|
|
@@ -3544,7 +3526,7 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3544
3526
|
}
|
|
3545
3527
|
setDropdownPos({ top, left });
|
|
3546
3528
|
}, []);
|
|
3547
|
-
(0,
|
|
3529
|
+
(0, import_react29.useEffect)(() => {
|
|
3548
3530
|
if (!open) return;
|
|
3549
3531
|
updatePosition();
|
|
3550
3532
|
const rafId = requestAnimationFrame(() => updatePosition());
|
|
@@ -3558,7 +3540,7 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3558
3540
|
window.removeEventListener("resize", onResize);
|
|
3559
3541
|
};
|
|
3560
3542
|
}, [open, updatePosition]);
|
|
3561
|
-
(0,
|
|
3543
|
+
(0, import_react29.useEffect)(() => {
|
|
3562
3544
|
if (!open) return;
|
|
3563
3545
|
const handleClick = (e) => {
|
|
3564
3546
|
const target = e.target;
|
|
@@ -3578,8 +3560,8 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3578
3560
|
document.removeEventListener("keydown", handleKeyDown);
|
|
3579
3561
|
};
|
|
3580
3562
|
}, [open]);
|
|
3581
|
-
return /* @__PURE__ */ (0,
|
|
3582
|
-
/* @__PURE__ */ (0,
|
|
3563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(MenuContainer, { children: [
|
|
3564
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3583
3565
|
MenuButton,
|
|
3584
3566
|
{
|
|
3585
3567
|
ref: buttonRef,
|
|
@@ -3590,19 +3572,19 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3590
3572
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3591
3573
|
title: "Track menu",
|
|
3592
3574
|
"aria-label": "Track menu",
|
|
3593
|
-
children: /* @__PURE__ */ (0,
|
|
3575
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(DotsIcon, { size: 16 })
|
|
3594
3576
|
}
|
|
3595
3577
|
),
|
|
3596
3578
|
open && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
|
|
3597
|
-
/* @__PURE__ */ (0,
|
|
3579
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
3598
3580
|
Dropdown,
|
|
3599
3581
|
{
|
|
3600
3582
|
ref: dropdownRef,
|
|
3601
3583
|
$top: dropdownPos.top,
|
|
3602
3584
|
$left: dropdownPos.left,
|
|
3603
3585
|
onMouseDown: (e) => e.stopPropagation(),
|
|
3604
|
-
children: items.map((item, index) => /* @__PURE__ */ (0,
|
|
3605
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
3586
|
+
children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_react29.default.Fragment, { children: [
|
|
3587
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(Divider, {}),
|
|
3606
3588
|
item.content
|
|
3607
3589
|
] }, item.id))
|
|
3608
3590
|
}
|
|
@@ -3611,6 +3593,26 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3611
3593
|
)
|
|
3612
3594
|
] });
|
|
3613
3595
|
};
|
|
3596
|
+
|
|
3597
|
+
// src/utils/conversions.ts
|
|
3598
|
+
function samplesToSeconds(samples, sampleRate) {
|
|
3599
|
+
return samples / sampleRate;
|
|
3600
|
+
}
|
|
3601
|
+
function secondsToSamples(seconds, sampleRate) {
|
|
3602
|
+
return Math.ceil(seconds * sampleRate);
|
|
3603
|
+
}
|
|
3604
|
+
function samplesToPixels2(samples, samplesPerPixel) {
|
|
3605
|
+
return Math.floor(samples / samplesPerPixel);
|
|
3606
|
+
}
|
|
3607
|
+
function pixelsToSamples(pixels, samplesPerPixel) {
|
|
3608
|
+
return Math.floor(pixels * samplesPerPixel);
|
|
3609
|
+
}
|
|
3610
|
+
function pixelsToSeconds(pixels, samplesPerPixel, sampleRate) {
|
|
3611
|
+
return pixels * samplesPerPixel / sampleRate;
|
|
3612
|
+
}
|
|
3613
|
+
function secondsToPixels2(seconds, samplesPerPixel, sampleRate) {
|
|
3614
|
+
return Math.ceil(seconds * sampleRate / samplesPerPixel);
|
|
3615
|
+
}
|
|
3614
3616
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3615
3617
|
0 && (module.exports = {
|
|
3616
3618
|
AudioPosition,
|
|
@@ -3621,9 +3623,12 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3621
3623
|
BaseCheckboxWrapper,
|
|
3622
3624
|
BaseControlButton,
|
|
3623
3625
|
BaseInput,
|
|
3626
|
+
BaseInputSmall,
|
|
3624
3627
|
BaseLabel,
|
|
3625
3628
|
BaseSelect,
|
|
3629
|
+
BaseSelectSmall,
|
|
3626
3630
|
BaseSlider,
|
|
3631
|
+
BeatsAndBarsProvider,
|
|
3627
3632
|
Button,
|
|
3628
3633
|
ButtonGroup,
|
|
3629
3634
|
CLIP_BOUNDARY_WIDTH,
|
|
@@ -3677,6 +3682,7 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3677
3682
|
darkTheme,
|
|
3678
3683
|
defaultTheme,
|
|
3679
3684
|
formatTime,
|
|
3685
|
+
getScaleInfo,
|
|
3680
3686
|
isWaveformGradient,
|
|
3681
3687
|
parseTime,
|
|
3682
3688
|
pixelsToSamples,
|
|
@@ -3685,6 +3691,7 @@ var TrackMenu = ({ items: itemsProp }) => {
|
|
|
3685
3691
|
samplesToSeconds,
|
|
3686
3692
|
secondsToPixels,
|
|
3687
3693
|
secondsToSamples,
|
|
3694
|
+
useBeatsAndBars,
|
|
3688
3695
|
useClipViewportOrigin,
|
|
3689
3696
|
useDevicePixelRatio,
|
|
3690
3697
|
usePlaylistInfo,
|