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