@signalsandsorcery/plugin-sdk 2.35.1 → 2.35.2
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 +154 -2
- package/dist/index.d.ts +154 -2
- package/dist/index.js +501 -210
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +500 -211
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -62,6 +62,7 @@ __export(index_exports, {
|
|
|
62
62
|
PLUGIN_SDK_VERSION: () => PLUGIN_SDK_VERSION,
|
|
63
63
|
PX_PER_BEAT: () => PX_PER_BEAT,
|
|
64
64
|
PanSlider: () => PanSlider,
|
|
65
|
+
PanelMasterStrip: () => PanelMasterStrip,
|
|
65
66
|
PianoRollEditor: () => PianoRollEditor,
|
|
66
67
|
PluginError: () => PluginError,
|
|
67
68
|
RESIZE_HANDLE_PX: () => RESIZE_HANDLE_PX,
|
|
@@ -126,6 +127,7 @@ __export(index_exports, {
|
|
|
126
127
|
transposeNotes: () => transposeNotes,
|
|
127
128
|
useAnySolo: () => useAnySolo,
|
|
128
129
|
useGeneratorPanelCore: () => useGeneratorPanelCore,
|
|
130
|
+
usePanelBus: () => usePanelBus,
|
|
129
131
|
useSceneState: () => useSceneState,
|
|
130
132
|
useSoundHistory: () => useSoundHistory,
|
|
131
133
|
useTrackLevel: () => useTrackLevel,
|
|
@@ -4265,9 +4267,276 @@ function TransitionDesigner({
|
|
|
4265
4267
|
] });
|
|
4266
4268
|
}
|
|
4267
4269
|
|
|
4268
|
-
// src/components/
|
|
4270
|
+
// src/components/PanelMasterStrip.tsx
|
|
4269
4271
|
var import_react17 = require("react");
|
|
4270
4272
|
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
4273
|
+
function PanelMasterStrip({
|
|
4274
|
+
bus,
|
|
4275
|
+
availableFx = [],
|
|
4276
|
+
fxLoading = false,
|
|
4277
|
+
soloedOut = false,
|
|
4278
|
+
disabled = false,
|
|
4279
|
+
fxPickerOpen,
|
|
4280
|
+
onToggleFxPicker,
|
|
4281
|
+
onRefreshFx,
|
|
4282
|
+
onVolumeChange,
|
|
4283
|
+
onMuteToggle,
|
|
4284
|
+
onSoloToggle,
|
|
4285
|
+
onAddFx,
|
|
4286
|
+
onRemoveFx,
|
|
4287
|
+
onToggleFxEnabled,
|
|
4288
|
+
onShowFxEditor
|
|
4289
|
+
}) {
|
|
4290
|
+
const [search, setSearch] = (0, import_react17.useState)("");
|
|
4291
|
+
const filtered = (0, import_react17.useMemo)(() => {
|
|
4292
|
+
const q = search.trim().toLowerCase();
|
|
4293
|
+
if (!q) return availableFx;
|
|
4294
|
+
return availableFx.filter(
|
|
4295
|
+
(fx) => fx.name.toLowerCase().includes(q) || fx.manufacturer.toLowerCase().includes(q)
|
|
4296
|
+
);
|
|
4297
|
+
}, [availableFx, search]);
|
|
4298
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4299
|
+
"div",
|
|
4300
|
+
{
|
|
4301
|
+
"data-testid": "panel-master-strip",
|
|
4302
|
+
className: `flex flex-col gap-1 px-2 py-1.5 rounded-sm border border-sas-border bg-sas-panel-alt/50 transition-opacity ${soloedOut ? "opacity-40" : ""}`,
|
|
4303
|
+
children: [
|
|
4304
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
4305
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4306
|
+
"span",
|
|
4307
|
+
{
|
|
4308
|
+
className: "text-[9px] font-bold tracking-widest text-sas-muted/70 select-none",
|
|
4309
|
+
title: "Panel mix bus \u2014 volume, mute/solo and FX applied to this panel's summed output",
|
|
4310
|
+
children: "BUS"
|
|
4311
|
+
}
|
|
4312
|
+
),
|
|
4313
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "w-24", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4314
|
+
VolumeSlider,
|
|
4315
|
+
{
|
|
4316
|
+
value: dbToSlider(bus.volume),
|
|
4317
|
+
onChange: (sliderValue) => onVolumeChange(sliderToDb(sliderValue)),
|
|
4318
|
+
disabled
|
|
4319
|
+
}
|
|
4320
|
+
) }),
|
|
4321
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4322
|
+
"button",
|
|
4323
|
+
{
|
|
4324
|
+
"data-testid": "bus-mute-button",
|
|
4325
|
+
onClick: onMuteToggle,
|
|
4326
|
+
disabled,
|
|
4327
|
+
className: `px-1.5 py-0.5 text-xs font-bold rounded transition-colors ${bus.muted ? "bg-red-600 text-white" : "bg-sas-panel-alt text-sas-muted hover:bg-sas-border"} disabled:opacity-50`,
|
|
4328
|
+
title: bus.muted ? "Unmute panel bus" : "Mute panel bus (silences the whole panel)",
|
|
4329
|
+
children: "M"
|
|
4330
|
+
}
|
|
4331
|
+
),
|
|
4332
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4333
|
+
"button",
|
|
4334
|
+
{
|
|
4335
|
+
"data-testid": "bus-solo-button",
|
|
4336
|
+
onClick: onSoloToggle,
|
|
4337
|
+
disabled,
|
|
4338
|
+
className: `px-1.5 py-0.5 text-xs font-bold rounded transition-colors ${bus.soloed ? "bg-amber-500 text-black" : "bg-sas-panel-alt text-sas-muted hover:bg-sas-border"} disabled:opacity-50`,
|
|
4339
|
+
title: bus.soloed ? "Unsolo panel bus" : "Solo this panel (silences other panels/tracks in scope)",
|
|
4340
|
+
children: "S"
|
|
4341
|
+
}
|
|
4342
|
+
),
|
|
4343
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex items-center gap-1 flex-1 min-w-0 overflow-x-auto", children: bus.fx.map((fx) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4344
|
+
"span",
|
|
4345
|
+
{
|
|
4346
|
+
"data-testid": `bus-fx-chip-${fx.index}`,
|
|
4347
|
+
className: `flex items-center gap-1 px-1.5 py-0.5 rounded-sm border text-[10px] whitespace-nowrap ${fx.enabled ? "border-sas-accent/60 text-sas-accent bg-sas-accent/10" : "border-sas-border text-sas-muted/50 bg-sas-panel"}`,
|
|
4348
|
+
title: `${fx.name}${fx.enabled ? "" : " (bypassed)"}`,
|
|
4349
|
+
children: [
|
|
4350
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4351
|
+
"button",
|
|
4352
|
+
{
|
|
4353
|
+
"data-testid": `bus-fx-toggle-${fx.index}`,
|
|
4354
|
+
onClick: () => onToggleFxEnabled(fx.index, !fx.enabled),
|
|
4355
|
+
disabled,
|
|
4356
|
+
className: "hover:opacity-70 disabled:opacity-50",
|
|
4357
|
+
title: fx.enabled ? `Bypass ${fx.name}` : `Enable ${fx.name}`,
|
|
4358
|
+
children: fx.enabled ? "\u25CF" : "\u25CB"
|
|
4359
|
+
}
|
|
4360
|
+
),
|
|
4361
|
+
onShowFxEditor ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4362
|
+
"button",
|
|
4363
|
+
{
|
|
4364
|
+
"data-testid": `bus-fx-edit-${fx.index}`,
|
|
4365
|
+
onClick: () => onShowFxEditor(fx.index),
|
|
4366
|
+
disabled,
|
|
4367
|
+
className: "max-w-[80px] truncate hover:underline disabled:opacity-50",
|
|
4368
|
+
title: `Open ${fx.name} editor`,
|
|
4369
|
+
children: fx.name
|
|
4370
|
+
}
|
|
4371
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "max-w-[80px] truncate", children: fx.name }),
|
|
4372
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4373
|
+
"button",
|
|
4374
|
+
{
|
|
4375
|
+
"data-testid": `bus-fx-remove-${fx.index}`,
|
|
4376
|
+
onClick: () => onRemoveFx(fx.index),
|
|
4377
|
+
disabled,
|
|
4378
|
+
className: "text-sas-muted/60 hover:text-sas-danger disabled:opacity-50",
|
|
4379
|
+
title: `Remove ${fx.name} from the bus`,
|
|
4380
|
+
children: "\u2715"
|
|
4381
|
+
}
|
|
4382
|
+
)
|
|
4383
|
+
]
|
|
4384
|
+
},
|
|
4385
|
+
`${fx.index}:${fx.pluginId}`
|
|
4386
|
+
)) }),
|
|
4387
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4388
|
+
"button",
|
|
4389
|
+
{
|
|
4390
|
+
"data-testid": "bus-fx-add-button",
|
|
4391
|
+
onClick: () => onToggleFxPicker(!fxPickerOpen),
|
|
4392
|
+
disabled,
|
|
4393
|
+
className: `px-1.5 py-0.5 rounded-sm border text-xs whitespace-nowrap transition-colors ${fxPickerOpen ? "border-sas-accent text-sas-accent bg-sas-accent/10" : "border-sas-border text-sas-muted hover:border-sas-accent hover:text-sas-accent"} disabled:opacity-50`,
|
|
4394
|
+
title: "Add an FX plugin to the panel bus",
|
|
4395
|
+
children: "FX +"
|
|
4396
|
+
}
|
|
4397
|
+
)
|
|
4398
|
+
] }),
|
|
4399
|
+
fxPickerOpen && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { "data-testid": "bus-fx-picker", className: "flex flex-col gap-2 pt-1", children: [
|
|
4400
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
4401
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4402
|
+
"input",
|
|
4403
|
+
{
|
|
4404
|
+
type: "text",
|
|
4405
|
+
value: search,
|
|
4406
|
+
onChange: (e) => setSearch(e.target.value),
|
|
4407
|
+
placeholder: "Search FX...",
|
|
4408
|
+
className: "sas-input flex-1 px-2 py-1 text-xs"
|
|
4409
|
+
}
|
|
4410
|
+
),
|
|
4411
|
+
onRefreshFx && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
4412
|
+
"button",
|
|
4413
|
+
{
|
|
4414
|
+
onClick: () => onRefreshFx(),
|
|
4415
|
+
disabled: fxLoading,
|
|
4416
|
+
className: "px-2 py-1 text-xs rounded-sm border border-sas-border text-sas-muted hover:text-sas-accent hover:border-sas-accent transition-colors disabled:opacity-50",
|
|
4417
|
+
title: "Re-scan plugins",
|
|
4418
|
+
children: fxLoading ? "..." : "Refresh"
|
|
4419
|
+
}
|
|
4420
|
+
)
|
|
4421
|
+
] }),
|
|
4422
|
+
fxLoading && availableFx.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "text-xs text-sas-muted/60 text-center py-3", children: "Scanning plugins..." }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "grid grid-cols-3 gap-1 max-h-[140px] overflow-y-auto", children: [
|
|
4423
|
+
filtered.map((fx) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
4424
|
+
"button",
|
|
4425
|
+
{
|
|
4426
|
+
"data-testid": `bus-fx-pick-${fx.pluginId}`,
|
|
4427
|
+
onClick: () => onAddFx(fx.pluginId),
|
|
4428
|
+
className: "flex flex-col items-start px-2 py-1.5 rounded-sm border text-left transition-colors border-sas-border bg-sas-panel-alt text-sas-muted hover:border-sas-accent hover:text-sas-accent",
|
|
4429
|
+
title: `${fx.name} by ${fx.manufacturer} (${fx.type.toUpperCase()})`,
|
|
4430
|
+
children: [
|
|
4431
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-xs font-medium truncate w-full", children: fx.name }),
|
|
4432
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[9px] text-sas-muted/50 truncate w-full", children: fx.manufacturer || fx.type.toUpperCase() })
|
|
4433
|
+
]
|
|
4434
|
+
},
|
|
4435
|
+
fx.pluginId
|
|
4436
|
+
)),
|
|
4437
|
+
filtered.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "col-span-3 text-xs text-sas-muted/60 text-center py-2", children: search.trim() ? "No matches" : "No FX plugins found" })
|
|
4438
|
+
] })
|
|
4439
|
+
] })
|
|
4440
|
+
]
|
|
4441
|
+
}
|
|
4442
|
+
);
|
|
4443
|
+
}
|
|
4444
|
+
|
|
4445
|
+
// src/hooks/usePanelBus.ts
|
|
4446
|
+
var import_react18 = require("react");
|
|
4447
|
+
function usePanelBus(host, activeSceneId) {
|
|
4448
|
+
const supported = typeof host.getPanelBusState === "function";
|
|
4449
|
+
const [bus, setBus] = (0, import_react18.useState)(null);
|
|
4450
|
+
const [availableFx, setAvailableFx] = (0, import_react18.useState)([]);
|
|
4451
|
+
const [fxLoading, setFxLoading] = (0, import_react18.useState)(false);
|
|
4452
|
+
const [fxPickerOpen, setFxPickerOpen] = (0, import_react18.useState)(false);
|
|
4453
|
+
const fxLoadedRef = (0, import_react18.useRef)(false);
|
|
4454
|
+
const loadSeqRef = (0, import_react18.useRef)(0);
|
|
4455
|
+
const reload = (0, import_react18.useCallback)(async () => {
|
|
4456
|
+
if (!supported || !activeSceneId || !host.getPanelBusState) {
|
|
4457
|
+
setBus(null);
|
|
4458
|
+
return;
|
|
4459
|
+
}
|
|
4460
|
+
const seq = ++loadSeqRef.current;
|
|
4461
|
+
try {
|
|
4462
|
+
const state = await host.getPanelBusState(activeSceneId);
|
|
4463
|
+
if (loadSeqRef.current === seq) setBus(state);
|
|
4464
|
+
} catch {
|
|
4465
|
+
}
|
|
4466
|
+
}, [host, activeSceneId, supported]);
|
|
4467
|
+
(0, import_react18.useEffect)(() => {
|
|
4468
|
+
setBus(null);
|
|
4469
|
+
setFxPickerOpen(false);
|
|
4470
|
+
void reload();
|
|
4471
|
+
}, [reload]);
|
|
4472
|
+
const loadFxList = (0, import_react18.useCallback)(
|
|
4473
|
+
async (force) => {
|
|
4474
|
+
if (!supported || !host.getAvailableFx) return;
|
|
4475
|
+
if (fxLoadedRef.current && !force) return;
|
|
4476
|
+
setFxLoading(true);
|
|
4477
|
+
try {
|
|
4478
|
+
const list = await host.getAvailableFx();
|
|
4479
|
+
setAvailableFx(list);
|
|
4480
|
+
fxLoadedRef.current = true;
|
|
4481
|
+
} catch {
|
|
4482
|
+
} finally {
|
|
4483
|
+
setFxLoading(false);
|
|
4484
|
+
}
|
|
4485
|
+
},
|
|
4486
|
+
[host, supported]
|
|
4487
|
+
);
|
|
4488
|
+
const openPicker = (0, import_react18.useCallback)(
|
|
4489
|
+
(open) => {
|
|
4490
|
+
setFxPickerOpen(open);
|
|
4491
|
+
if (open) void loadFxList(false);
|
|
4492
|
+
},
|
|
4493
|
+
[loadFxList]
|
|
4494
|
+
);
|
|
4495
|
+
const mutate = (0, import_react18.useCallback)(
|
|
4496
|
+
(fn) => {
|
|
4497
|
+
if (!fn || !activeSceneId) return;
|
|
4498
|
+
void (async () => {
|
|
4499
|
+
try {
|
|
4500
|
+
await fn();
|
|
4501
|
+
} catch {
|
|
4502
|
+
}
|
|
4503
|
+
await reload();
|
|
4504
|
+
})();
|
|
4505
|
+
},
|
|
4506
|
+
[activeSceneId, reload]
|
|
4507
|
+
);
|
|
4508
|
+
return {
|
|
4509
|
+
supported,
|
|
4510
|
+
bus,
|
|
4511
|
+
availableFx,
|
|
4512
|
+
fxLoading,
|
|
4513
|
+
fxPickerOpen,
|
|
4514
|
+
setFxPickerOpen: openPicker,
|
|
4515
|
+
refreshFx: () => void loadFxList(true),
|
|
4516
|
+
reload,
|
|
4517
|
+
onVolumeChange: (volumeDb) => mutate(host.setPanelBusVolume && (() => host.setPanelBusVolume(activeSceneId, volumeDb))),
|
|
4518
|
+
onMuteToggle: () => mutate(
|
|
4519
|
+
host.setPanelBusMute && (() => host.setPanelBusMute(activeSceneId, !(bus?.muted ?? false)))
|
|
4520
|
+
),
|
|
4521
|
+
onSoloToggle: () => mutate(
|
|
4522
|
+
host.setPanelBusSolo && (() => host.setPanelBusSolo(activeSceneId, !(bus?.soloed ?? false)))
|
|
4523
|
+
),
|
|
4524
|
+
onAddFx: (pluginId) => mutate(host.loadPanelBusFx && (async () => {
|
|
4525
|
+
await host.loadPanelBusFx(activeSceneId, pluginId);
|
|
4526
|
+
})),
|
|
4527
|
+
onRemoveFx: (fxIndex) => mutate(host.removePanelBusFx && (() => host.removePanelBusFx(activeSceneId, fxIndex))),
|
|
4528
|
+
onToggleFxEnabled: (fxIndex, enabled) => mutate(
|
|
4529
|
+
host.setPanelBusFxEnabled && (() => host.setPanelBusFxEnabled(activeSceneId, fxIndex, enabled))
|
|
4530
|
+
),
|
|
4531
|
+
onShowFxEditor: (fxIndex) => mutate(
|
|
4532
|
+
host.showPanelBusFxEditor && (() => host.showPanelBusFxEditor(activeSceneId, fxIndex))
|
|
4533
|
+
)
|
|
4534
|
+
};
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4537
|
+
// src/components/DownloadPackButton.tsx
|
|
4538
|
+
var import_react19 = require("react");
|
|
4539
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
4271
4540
|
function formatSize(bytes) {
|
|
4272
4541
|
if (!bytes || bytes <= 0) return "";
|
|
4273
4542
|
const gb = bytes / 1024 ** 3;
|
|
@@ -4283,10 +4552,10 @@ var DownloadPackButton = ({
|
|
|
4283
4552
|
variant = "compact",
|
|
4284
4553
|
onDownloadComplete
|
|
4285
4554
|
}) => {
|
|
4286
|
-
const [status, setStatus] = (0,
|
|
4287
|
-
const [progress, setProgress] = (0,
|
|
4288
|
-
const [errorMessage, setErrorMessage] = (0,
|
|
4289
|
-
(0,
|
|
4555
|
+
const [status, setStatus] = (0, import_react19.useState)("idle");
|
|
4556
|
+
const [progress, setProgress] = (0, import_react19.useState)(0);
|
|
4557
|
+
const [errorMessage, setErrorMessage] = (0, import_react19.useState)(null);
|
|
4558
|
+
(0, import_react19.useEffect)(() => {
|
|
4290
4559
|
const unsub = host.onSamplePackProgress(packId, (p) => {
|
|
4291
4560
|
setStatus(p.status);
|
|
4292
4561
|
setProgress(p.progress);
|
|
@@ -4301,7 +4570,7 @@ var DownloadPackButton = ({
|
|
|
4301
4570
|
});
|
|
4302
4571
|
return unsub;
|
|
4303
4572
|
}, [host, packId, onDownloadComplete]);
|
|
4304
|
-
const handleClick = (0,
|
|
4573
|
+
const handleClick = (0, import_react19.useCallback)(async () => {
|
|
4305
4574
|
if (status !== "idle" && status !== "error") return;
|
|
4306
4575
|
try {
|
|
4307
4576
|
setStatus("downloading");
|
|
@@ -4355,8 +4624,8 @@ var DownloadPackButton = ({
|
|
|
4355
4624
|
} else {
|
|
4356
4625
|
className = `${baseClasses} text-sas-muted hover:text-sas-accent border-sas-border hover:border-sas-accent`;
|
|
4357
4626
|
}
|
|
4358
|
-
return /* @__PURE__ */ (0,
|
|
4359
|
-
/* @__PURE__ */ (0,
|
|
4627
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
4628
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
4360
4629
|
"button",
|
|
4361
4630
|
{
|
|
4362
4631
|
"data-testid": `download-pack-button-${packId}`,
|
|
@@ -4367,12 +4636,12 @@ var DownloadPackButton = ({
|
|
|
4367
4636
|
children: buttonLabel
|
|
4368
4637
|
}
|
|
4369
4638
|
),
|
|
4370
|
-
variant === "large" && status === "error" && errorMessage && /* @__PURE__ */ (0,
|
|
4639
|
+
variant === "large" && status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "text-xs text-sas-danger mt-2", "data-testid": `download-pack-error-${packId}`, children: errorMessage })
|
|
4371
4640
|
] });
|
|
4372
4641
|
};
|
|
4373
4642
|
|
|
4374
4643
|
// src/components/SamplePackCTACard.tsx
|
|
4375
|
-
var
|
|
4644
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
4376
4645
|
var SamplePackCTACard = ({
|
|
4377
4646
|
host,
|
|
4378
4647
|
pack,
|
|
@@ -4380,7 +4649,7 @@ var SamplePackCTACard = ({
|
|
|
4380
4649
|
onDownloadComplete
|
|
4381
4650
|
}) => {
|
|
4382
4651
|
if (status === "checking") {
|
|
4383
|
-
return /* @__PURE__ */ (0,
|
|
4652
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4384
4653
|
"div",
|
|
4385
4654
|
{
|
|
4386
4655
|
"data-testid": `sample-pack-cta-checking-${pack.packId}`,
|
|
@@ -4391,16 +4660,16 @@ var SamplePackCTACard = ({
|
|
|
4391
4660
|
}
|
|
4392
4661
|
const headline = status === "stale" ? `${pack.displayName} update available` : `${pack.displayName} not installed`;
|
|
4393
4662
|
const sublabel = status === "stale" ? `A newer version is available for download.` : pack.description;
|
|
4394
|
-
return /* @__PURE__ */ (0,
|
|
4663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
4395
4664
|
"div",
|
|
4396
4665
|
{
|
|
4397
4666
|
"data-testid": `sample-pack-cta-${pack.packId}`,
|
|
4398
4667
|
className: "flex flex-col items-center justify-center py-12 px-6 text-center",
|
|
4399
4668
|
children: [
|
|
4400
|
-
/* @__PURE__ */ (0,
|
|
4401
|
-
/* @__PURE__ */ (0,
|
|
4402
|
-
/* @__PURE__ */ (0,
|
|
4403
|
-
/* @__PURE__ */ (0,
|
|
4669
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-sm uppercase tracking-wide text-sas-muted mb-2", children: status === "stale" ? "Update available" : "Sample library not installed" }),
|
|
4670
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-base text-sas-text mb-1", children: headline }),
|
|
4671
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-xs text-sas-muted mb-6 max-w-md", children: sublabel }),
|
|
4672
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
4404
4673
|
DownloadPackButton,
|
|
4405
4674
|
{
|
|
4406
4675
|
host,
|
|
@@ -4417,7 +4686,7 @@ var SamplePackCTACard = ({
|
|
|
4417
4686
|
};
|
|
4418
4687
|
|
|
4419
4688
|
// src/components/WaveformView.tsx
|
|
4420
|
-
var
|
|
4689
|
+
var import_react20 = require("react");
|
|
4421
4690
|
|
|
4422
4691
|
// src/components/waveform.ts
|
|
4423
4692
|
function computePeaks(audioBuffer, bins, targetSamples) {
|
|
@@ -4480,7 +4749,7 @@ function drawWaveform(canvas, peaks, options = {}) {
|
|
|
4480
4749
|
}
|
|
4481
4750
|
|
|
4482
4751
|
// src/components/WaveformView.tsx
|
|
4483
|
-
var
|
|
4752
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
4484
4753
|
var WaveformView = ({
|
|
4485
4754
|
host,
|
|
4486
4755
|
filePath,
|
|
@@ -4489,9 +4758,9 @@ var WaveformView = ({
|
|
|
4489
4758
|
fillStyle,
|
|
4490
4759
|
targetSamples
|
|
4491
4760
|
}) => {
|
|
4492
|
-
const canvasRef = (0,
|
|
4493
|
-
const [peaks, setPeaks] = (0,
|
|
4494
|
-
(0,
|
|
4761
|
+
const canvasRef = (0, import_react20.useRef)(null);
|
|
4762
|
+
const [peaks, setPeaks] = (0, import_react20.useState)(null);
|
|
4763
|
+
(0, import_react20.useEffect)(() => {
|
|
4495
4764
|
let cancelled = false;
|
|
4496
4765
|
let audioContext = null;
|
|
4497
4766
|
(async () => {
|
|
@@ -4517,7 +4786,7 @@ var WaveformView = ({
|
|
|
4517
4786
|
cancelled = true;
|
|
4518
4787
|
};
|
|
4519
4788
|
}, [host, filePath, bins, targetSamples]);
|
|
4520
|
-
(0,
|
|
4789
|
+
(0, import_react20.useEffect)(() => {
|
|
4521
4790
|
if (!peaks) return;
|
|
4522
4791
|
const canvas = canvasRef.current;
|
|
4523
4792
|
if (!canvas) return;
|
|
@@ -4528,7 +4797,7 @@ var WaveformView = ({
|
|
|
4528
4797
|
observer.observe(canvas);
|
|
4529
4798
|
return () => observer.disconnect();
|
|
4530
4799
|
}, [peaks, fillStyle]);
|
|
4531
|
-
return /* @__PURE__ */ (0,
|
|
4800
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
4532
4801
|
"canvas",
|
|
4533
4802
|
{
|
|
4534
4803
|
ref: canvasRef,
|
|
@@ -4539,8 +4808,8 @@ var WaveformView = ({
|
|
|
4539
4808
|
};
|
|
4540
4809
|
|
|
4541
4810
|
// src/components/ScrollingWaveform.tsx
|
|
4542
|
-
var
|
|
4543
|
-
var
|
|
4811
|
+
var import_react21 = require("react");
|
|
4812
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
4544
4813
|
var ScrollingWaveform = ({
|
|
4545
4814
|
getPeakDb,
|
|
4546
4815
|
active,
|
|
@@ -4548,11 +4817,11 @@ var ScrollingWaveform = ({
|
|
|
4548
4817
|
className,
|
|
4549
4818
|
fillStyle
|
|
4550
4819
|
}) => {
|
|
4551
|
-
const canvasRef = (0,
|
|
4552
|
-
const ringRef = (0,
|
|
4553
|
-
const writeIdxRef = (0,
|
|
4554
|
-
const rafRef = (0,
|
|
4555
|
-
(0,
|
|
4820
|
+
const canvasRef = (0, import_react21.useRef)(null);
|
|
4821
|
+
const ringRef = (0, import_react21.useRef)(new Float32Array(columns));
|
|
4822
|
+
const writeIdxRef = (0, import_react21.useRef)(0);
|
|
4823
|
+
const rafRef = (0, import_react21.useRef)(null);
|
|
4824
|
+
(0, import_react21.useEffect)(() => {
|
|
4556
4825
|
if (ringRef.current.length !== columns) {
|
|
4557
4826
|
const next = new Float32Array(columns);
|
|
4558
4827
|
const prev = ringRef.current;
|
|
@@ -4564,7 +4833,7 @@ var ScrollingWaveform = ({
|
|
|
4564
4833
|
writeIdxRef.current = writeIdxRef.current % columns;
|
|
4565
4834
|
}
|
|
4566
4835
|
}, [columns]);
|
|
4567
|
-
(0,
|
|
4836
|
+
(0, import_react21.useEffect)(() => {
|
|
4568
4837
|
if (!active) {
|
|
4569
4838
|
if (rafRef.current !== null) {
|
|
4570
4839
|
cancelAnimationFrame(rafRef.current);
|
|
@@ -4616,7 +4885,7 @@ var ScrollingWaveform = ({
|
|
|
4616
4885
|
}
|
|
4617
4886
|
};
|
|
4618
4887
|
}, [active, getPeakDb, fillStyle]);
|
|
4619
|
-
return /* @__PURE__ */ (0,
|
|
4888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
4620
4889
|
"canvas",
|
|
4621
4890
|
{
|
|
4622
4891
|
ref: canvasRef,
|
|
@@ -4627,8 +4896,8 @@ var ScrollingWaveform = ({
|
|
|
4627
4896
|
};
|
|
4628
4897
|
|
|
4629
4898
|
// src/components/OffsetScrubber.tsx
|
|
4630
|
-
var
|
|
4631
|
-
var
|
|
4899
|
+
var import_react22 = require("react");
|
|
4900
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
4632
4901
|
var SLIDER_HEIGHT_PX = 28;
|
|
4633
4902
|
var TICK_HEIGHT_PX = 14;
|
|
4634
4903
|
var DOWNBEAT_TICK_HEIGHT_PX = 22;
|
|
@@ -4641,40 +4910,40 @@ function OffsetScrubber({
|
|
|
4641
4910
|
onChange,
|
|
4642
4911
|
disabled = false
|
|
4643
4912
|
}) {
|
|
4644
|
-
const trackRef = (0,
|
|
4645
|
-
const [draftOffset, setDraftOffset] = (0,
|
|
4646
|
-
const [isDragging, setIsDragging] = (0,
|
|
4647
|
-
(0,
|
|
4913
|
+
const trackRef = (0, import_react22.useRef)(null);
|
|
4914
|
+
const [draftOffset, setDraftOffset] = (0, import_react22.useState)(offsetSamples);
|
|
4915
|
+
const [isDragging, setIsDragging] = (0, import_react22.useState)(false);
|
|
4916
|
+
(0, import_react22.useEffect)(() => {
|
|
4648
4917
|
if (!isDragging) setDraftOffset(offsetSamples);
|
|
4649
4918
|
}, [offsetSamples, isDragging]);
|
|
4650
4919
|
const sampleRate = cuePoints?.sample_rate ?? 44100;
|
|
4651
4920
|
const detectedBpm = cuePoints?.detected_bpm ?? projectBpm;
|
|
4652
|
-
const beatsForRange = (0,
|
|
4921
|
+
const beatsForRange = (0, import_react22.useMemo)(() => {
|
|
4653
4922
|
return Math.round(60 / projectBpm * sampleRate);
|
|
4654
4923
|
}, [projectBpm, sampleRate]);
|
|
4655
4924
|
const rangeSamples = beatsForRange * meter;
|
|
4656
|
-
const sampleToFraction = (0,
|
|
4925
|
+
const sampleToFraction = (0, import_react22.useCallback)(
|
|
4657
4926
|
(sample) => {
|
|
4658
4927
|
const clamped = Math.max(-rangeSamples, Math.min(rangeSamples, sample));
|
|
4659
4928
|
return (clamped + rangeSamples) / (2 * rangeSamples);
|
|
4660
4929
|
},
|
|
4661
4930
|
[rangeSamples]
|
|
4662
4931
|
);
|
|
4663
|
-
const fractionToSample = (0,
|
|
4932
|
+
const fractionToSample = (0, import_react22.useCallback)(
|
|
4664
4933
|
(fraction) => {
|
|
4665
4934
|
const clamped = Math.max(0, Math.min(1, fraction));
|
|
4666
4935
|
return Math.round(clamped * 2 * rangeSamples - rangeSamples);
|
|
4667
4936
|
},
|
|
4668
4937
|
[rangeSamples]
|
|
4669
4938
|
);
|
|
4670
|
-
const snapTargets = (0,
|
|
4939
|
+
const snapTargets = (0, import_react22.useMemo)(() => {
|
|
4671
4940
|
if (!cuePoints || cuePoints.beats.length === 0) return [];
|
|
4672
4941
|
const downbeat = cuePoints.beats[0];
|
|
4673
4942
|
const positives = cuePoints.beats.map((b) => b - downbeat);
|
|
4674
4943
|
const negatives = positives.slice(1).map((p) => -p);
|
|
4675
4944
|
return [...negatives, ...positives].sort((a, b) => a - b);
|
|
4676
4945
|
}, [cuePoints]);
|
|
4677
|
-
const snapToBeat = (0,
|
|
4946
|
+
const snapToBeat = (0, import_react22.useCallback)(
|
|
4678
4947
|
(sample) => {
|
|
4679
4948
|
if (snapTargets.length === 0) return sample;
|
|
4680
4949
|
let best = snapTargets[0];
|
|
@@ -4690,7 +4959,7 @@ function OffsetScrubber({
|
|
|
4690
4959
|
},
|
|
4691
4960
|
[snapTargets]
|
|
4692
4961
|
);
|
|
4693
|
-
const handlePointerDown = (0,
|
|
4962
|
+
const handlePointerDown = (0, import_react22.useCallback)(
|
|
4694
4963
|
(e) => {
|
|
4695
4964
|
if (disabled || !cuePoints) return;
|
|
4696
4965
|
e.preventDefault();
|
|
@@ -4724,7 +4993,7 @@ function OffsetScrubber({
|
|
|
4724
4993
|
},
|
|
4725
4994
|
[disabled, cuePoints, fractionToSample, onChange, snapToBeat]
|
|
4726
4995
|
);
|
|
4727
|
-
const handleResetToZero = (0,
|
|
4996
|
+
const handleResetToZero = (0, import_react22.useCallback)(() => {
|
|
4728
4997
|
if (disabled) return;
|
|
4729
4998
|
setDraftOffset(0);
|
|
4730
4999
|
onChange(0);
|
|
@@ -4732,7 +5001,7 @@ function OffsetScrubber({
|
|
|
4732
5001
|
const thumbFraction = sampleToFraction(draftOffset);
|
|
4733
5002
|
const thumbLeftPct = `${(thumbFraction * 100).toFixed(2)}%`;
|
|
4734
5003
|
const bpmMismatch = cuePoints?.detected_bpm != null && Math.abs(cuePoints.detected_bpm - projectBpm) > 1;
|
|
4735
|
-
const ticks = (0,
|
|
5004
|
+
const ticks = (0, import_react22.useMemo)(() => {
|
|
4736
5005
|
if (!cuePoints) return [];
|
|
4737
5006
|
const downbeat = cuePoints.beats[0] ?? 0;
|
|
4738
5007
|
return cuePoints.beats.map((b, i) => {
|
|
@@ -4743,9 +5012,9 @@ function OffsetScrubber({
|
|
|
4743
5012
|
});
|
|
4744
5013
|
}, [cuePoints, sampleToFraction]);
|
|
4745
5014
|
const isDisabled = disabled || !cuePoints || cuePoints.beats.length === 0;
|
|
4746
|
-
return /* @__PURE__ */ (0,
|
|
4747
|
-
/* @__PURE__ */ (0,
|
|
4748
|
-
/* @__PURE__ */ (0,
|
|
5015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { "data-testid": "offset-scrubber", className: "flex items-center gap-2 w-full", children: [
|
|
5016
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-[9px] text-sas-muted/60 uppercase tracking-wide flex-shrink-0", children: "Align" }),
|
|
5017
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
4749
5018
|
"div",
|
|
4750
5019
|
{
|
|
4751
5020
|
ref: trackRef,
|
|
@@ -4761,7 +5030,7 @@ function OffsetScrubber({
|
|
|
4761
5030
|
"aria-valuenow": draftOffset,
|
|
4762
5031
|
"aria-disabled": isDisabled,
|
|
4763
5032
|
children: [
|
|
4764
|
-
/* @__PURE__ */ (0,
|
|
5033
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4765
5034
|
"div",
|
|
4766
5035
|
{
|
|
4767
5036
|
"aria-hidden": "true",
|
|
@@ -4769,7 +5038,7 @@ function OffsetScrubber({
|
|
|
4769
5038
|
style: { left: "50%" }
|
|
4770
5039
|
}
|
|
4771
5040
|
),
|
|
4772
|
-
ticks.map((t) => /* @__PURE__ */ (0,
|
|
5041
|
+
ticks.map((t) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4773
5042
|
"div",
|
|
4774
5043
|
{
|
|
4775
5044
|
"data-testid": t.isDownbeat ? "offset-tick-downbeat" : "offset-tick",
|
|
@@ -4784,7 +5053,7 @@ function OffsetScrubber({
|
|
|
4784
5053
|
},
|
|
4785
5054
|
t.i
|
|
4786
5055
|
)),
|
|
4787
|
-
/* @__PURE__ */ (0,
|
|
5056
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4788
5057
|
"div",
|
|
4789
5058
|
{
|
|
4790
5059
|
"data-testid": "offset-scrubber-thumb",
|
|
@@ -4801,7 +5070,7 @@ function OffsetScrubber({
|
|
|
4801
5070
|
]
|
|
4802
5071
|
}
|
|
4803
5072
|
),
|
|
4804
|
-
/* @__PURE__ */ (0,
|
|
5073
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4805
5074
|
"span",
|
|
4806
5075
|
{
|
|
4807
5076
|
"data-testid": "offset-scrubber-readout",
|
|
@@ -4809,7 +5078,7 @@ function OffsetScrubber({
|
|
|
4809
5078
|
children: formatOffset(draftOffset, sampleRate)
|
|
4810
5079
|
}
|
|
4811
5080
|
),
|
|
4812
|
-
/* @__PURE__ */ (0,
|
|
5081
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4813
5082
|
"button",
|
|
4814
5083
|
{
|
|
4815
5084
|
type: "button",
|
|
@@ -4821,7 +5090,7 @@ function OffsetScrubber({
|
|
|
4821
5090
|
children: "\u2316"
|
|
4822
5091
|
}
|
|
4823
5092
|
),
|
|
4824
|
-
bpmMismatch && /* @__PURE__ */ (0,
|
|
5093
|
+
bpmMismatch && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
4825
5094
|
"span",
|
|
4826
5095
|
{
|
|
4827
5096
|
"data-testid": "offset-bpm-mismatch",
|
|
@@ -4893,16 +5162,16 @@ function synthesizeCuePoints({
|
|
|
4893
5162
|
}
|
|
4894
5163
|
|
|
4895
5164
|
// src/panel-core/useGeneratorPanelCore.tsx
|
|
4896
|
-
var
|
|
5165
|
+
var import_react27 = require("react");
|
|
4897
5166
|
|
|
4898
5167
|
// src/hooks/useSceneState.ts
|
|
4899
|
-
var
|
|
5168
|
+
var import_react23 = require("react");
|
|
4900
5169
|
function useSceneState(activeSceneId, initialValue) {
|
|
4901
|
-
const [stateMap, setStateMap] = (0,
|
|
4902
|
-
const activeSceneIdRef = (0,
|
|
5170
|
+
const [stateMap, setStateMap] = (0, import_react23.useState)(() => /* @__PURE__ */ new Map());
|
|
5171
|
+
const activeSceneIdRef = (0, import_react23.useRef)(activeSceneId);
|
|
4903
5172
|
activeSceneIdRef.current = activeSceneId;
|
|
4904
5173
|
const currentValue = activeSceneId !== null && stateMap.has(activeSceneId) ? stateMap.get(activeSceneId) : initialValue;
|
|
4905
|
-
const setForCurrentScene = (0,
|
|
5174
|
+
const setForCurrentScene = (0, import_react23.useCallback)((value) => {
|
|
4906
5175
|
const sid = activeSceneIdRef.current;
|
|
4907
5176
|
if (sid === null) return;
|
|
4908
5177
|
setStateMap((prev) => {
|
|
@@ -4913,7 +5182,7 @@ function useSceneState(activeSceneId, initialValue) {
|
|
|
4913
5182
|
return newMap;
|
|
4914
5183
|
});
|
|
4915
5184
|
}, [initialValue]);
|
|
4916
|
-
const setForScene = (0,
|
|
5185
|
+
const setForScene = (0, import_react23.useCallback)((sceneId, value) => {
|
|
4917
5186
|
setStateMap((prev) => {
|
|
4918
5187
|
const current = prev.has(sceneId) ? prev.get(sceneId) : initialValue;
|
|
4919
5188
|
const next = typeof value === "function" ? value(current) : value;
|
|
@@ -4926,10 +5195,10 @@ function useSceneState(activeSceneId, initialValue) {
|
|
|
4926
5195
|
}
|
|
4927
5196
|
|
|
4928
5197
|
// src/hooks/useAnySolo.ts
|
|
4929
|
-
var
|
|
5198
|
+
var import_react24 = require("react");
|
|
4930
5199
|
function useAnySolo(host) {
|
|
4931
|
-
const [anySolo, setAnySolo] = (0,
|
|
4932
|
-
(0,
|
|
5200
|
+
const [anySolo, setAnySolo] = (0, import_react24.useState)(false);
|
|
5201
|
+
(0, import_react24.useEffect)(() => {
|
|
4933
5202
|
let active = true;
|
|
4934
5203
|
const refresh = () => {
|
|
4935
5204
|
host.isAnySoloActive().then((v) => {
|
|
@@ -4948,7 +5217,7 @@ function useAnySolo(host) {
|
|
|
4948
5217
|
}
|
|
4949
5218
|
|
|
4950
5219
|
// src/hooks/useSoundHistory.ts
|
|
4951
|
-
var
|
|
5220
|
+
var import_react25 = require("react");
|
|
4952
5221
|
var EMPTY = { entries: [], cursor: -1 };
|
|
4953
5222
|
function sameDescriptor(a, b) {
|
|
4954
5223
|
if (a === b) return true;
|
|
@@ -4960,14 +5229,14 @@ function sameDescriptor(a, b) {
|
|
|
4960
5229
|
}
|
|
4961
5230
|
function useSoundHistory(applySound, opts = {}) {
|
|
4962
5231
|
const max = Math.max(2, opts.max ?? 24);
|
|
4963
|
-
const applyRef = (0,
|
|
5232
|
+
const applyRef = (0, import_react25.useRef)(applySound);
|
|
4964
5233
|
applyRef.current = applySound;
|
|
4965
|
-
const onChangeRef = (0,
|
|
5234
|
+
const onChangeRef = (0, import_react25.useRef)(opts.onChange);
|
|
4966
5235
|
onChangeRef.current = opts.onChange;
|
|
4967
|
-
const dataRef = (0,
|
|
4968
|
-
const [, setVersion] = (0,
|
|
4969
|
-
const bump = (0,
|
|
4970
|
-
const commit = (0,
|
|
5236
|
+
const dataRef = (0, import_react25.useRef)({});
|
|
5237
|
+
const [, setVersion] = (0, import_react25.useState)(0);
|
|
5238
|
+
const bump = (0, import_react25.useCallback)(() => setVersion((v) => v + 1), []);
|
|
5239
|
+
const commit = (0, import_react25.useCallback)(
|
|
4971
5240
|
(trackId, next, notify) => {
|
|
4972
5241
|
dataRef.current = { ...dataRef.current, [trackId]: next };
|
|
4973
5242
|
bump();
|
|
@@ -4975,7 +5244,7 @@ function useSoundHistory(applySound, opts = {}) {
|
|
|
4975
5244
|
},
|
|
4976
5245
|
[bump]
|
|
4977
5246
|
);
|
|
4978
|
-
const record = (0,
|
|
5247
|
+
const record = (0, import_react25.useCallback)(
|
|
4979
5248
|
(trackId, descriptor, label) => {
|
|
4980
5249
|
const h = dataRef.current[trackId];
|
|
4981
5250
|
const current = h && h.cursor >= 0 ? h.entries[h.cursor] : void 0;
|
|
@@ -4990,7 +5259,7 @@ function useSoundHistory(applySound, opts = {}) {
|
|
|
4990
5259
|
},
|
|
4991
5260
|
[max, commit]
|
|
4992
5261
|
);
|
|
4993
|
-
const restoreTo = (0,
|
|
5262
|
+
const restoreTo = (0, import_react25.useCallback)(
|
|
4994
5263
|
async (trackId, index) => {
|
|
4995
5264
|
const h = dataRef.current[trackId];
|
|
4996
5265
|
if (!h || index < 0 || index >= h.entries.length || index === h.cursor) return false;
|
|
@@ -5000,7 +5269,7 @@ function useSoundHistory(applySound, opts = {}) {
|
|
|
5000
5269
|
},
|
|
5001
5270
|
[commit]
|
|
5002
5271
|
);
|
|
5003
|
-
const undo = (0,
|
|
5272
|
+
const undo = (0, import_react25.useCallback)(
|
|
5004
5273
|
(trackId) => {
|
|
5005
5274
|
const h = dataRef.current[trackId];
|
|
5006
5275
|
if (!h || h.cursor <= 0) return Promise.resolve(false);
|
|
@@ -5008,7 +5277,7 @@ function useSoundHistory(applySound, opts = {}) {
|
|
|
5008
5277
|
},
|
|
5009
5278
|
[restoreTo]
|
|
5010
5279
|
);
|
|
5011
|
-
const toggleFavorite = (0,
|
|
5280
|
+
const toggleFavorite = (0, import_react25.useCallback)(
|
|
5012
5281
|
(trackId, index) => {
|
|
5013
5282
|
const h = dataRef.current[trackId];
|
|
5014
5283
|
if (!h || index < 0 || index >= h.entries.length) return;
|
|
@@ -5017,7 +5286,7 @@ function useSoundHistory(applySound, opts = {}) {
|
|
|
5017
5286
|
},
|
|
5018
5287
|
[commit]
|
|
5019
5288
|
);
|
|
5020
|
-
const restore = (0,
|
|
5289
|
+
const restore = (0, import_react25.useCallback)(
|
|
5021
5290
|
(trackId, state) => {
|
|
5022
5291
|
const entries = Array.isArray(state?.entries) ? [...state.entries] : [];
|
|
5023
5292
|
const raw = typeof state?.cursor === "number" ? state.cursor : entries.length - 1;
|
|
@@ -5026,15 +5295,15 @@ function useSoundHistory(applySound, opts = {}) {
|
|
|
5026
5295
|
},
|
|
5027
5296
|
[commit]
|
|
5028
5297
|
);
|
|
5029
|
-
const list = (0,
|
|
5298
|
+
const list = (0, import_react25.useCallback)(
|
|
5030
5299
|
(trackId) => dataRef.current[trackId] ?? EMPTY,
|
|
5031
5300
|
[]
|
|
5032
5301
|
);
|
|
5033
|
-
const canUndo = (0,
|
|
5302
|
+
const canUndo = (0, import_react25.useCallback)((trackId) => {
|
|
5034
5303
|
const h = dataRef.current[trackId];
|
|
5035
5304
|
return !!h && h.cursor > 0;
|
|
5036
5305
|
}, []);
|
|
5037
|
-
const clear = (0,
|
|
5306
|
+
const clear = (0, import_react25.useCallback)(
|
|
5038
5307
|
(trackId) => {
|
|
5039
5308
|
if (dataRef.current[trackId]) {
|
|
5040
5309
|
const next = { ...dataRef.current };
|
|
@@ -5046,11 +5315,11 @@ function useSoundHistory(applySound, opts = {}) {
|
|
|
5046
5315
|
},
|
|
5047
5316
|
[bump]
|
|
5048
5317
|
);
|
|
5049
|
-
const reset = (0,
|
|
5318
|
+
const reset = (0, import_react25.useCallback)(() => {
|
|
5050
5319
|
dataRef.current = {};
|
|
5051
5320
|
bump();
|
|
5052
5321
|
}, [bump]);
|
|
5053
|
-
return (0,
|
|
5322
|
+
return (0, import_react25.useMemo)(
|
|
5054
5323
|
() => ({ record, undo, restoreTo, list, canUndo, clear, reset, restore, toggleFavorite }),
|
|
5055
5324
|
[record, undo, restoreTo, list, canUndo, clear, reset, restore, toggleFavorite]
|
|
5056
5325
|
);
|
|
@@ -5183,7 +5452,7 @@ function resolveTrackGroups(parsedGroups, tracks, getDbId, opts = {}) {
|
|
|
5183
5452
|
}
|
|
5184
5453
|
|
|
5185
5454
|
// src/panel-core/useTransitionOps.ts
|
|
5186
|
-
var
|
|
5455
|
+
var import_react26 = require("react");
|
|
5187
5456
|
function useTransitionOps({
|
|
5188
5457
|
host,
|
|
5189
5458
|
adapter,
|
|
@@ -5200,8 +5469,8 @@ function useTransitionOps({
|
|
|
5200
5469
|
resolvedFades
|
|
5201
5470
|
}) {
|
|
5202
5471
|
const { identity } = adapter;
|
|
5203
|
-
const appliedFadeAutomationRef = (0,
|
|
5204
|
-
const applyCrossfadeAutomation = (0,
|
|
5472
|
+
const appliedFadeAutomationRef = (0, import_react26.useRef)(/* @__PURE__ */ new Set());
|
|
5473
|
+
const applyCrossfadeAutomation = (0, import_react26.useCallback)(
|
|
5205
5474
|
async (originTrackId, targetTrackId, bars, bpm, sliderPos) => {
|
|
5206
5475
|
if (host.setTrackVolumeAutomation) {
|
|
5207
5476
|
const curves = buildCrossfadeVolumeCurves(bars, bpm, sliderPos);
|
|
@@ -5218,7 +5487,7 @@ function useTransitionOps({
|
|
|
5218
5487
|
},
|
|
5219
5488
|
[host]
|
|
5220
5489
|
);
|
|
5221
|
-
const applyFadeAutomation = (0,
|
|
5490
|
+
const applyFadeAutomation = (0, import_react26.useCallback)(
|
|
5222
5491
|
async (trackId, direction, bars, bpm, sliderPos, gesture) => {
|
|
5223
5492
|
if (!host.setTrackVolumeAutomation) return;
|
|
5224
5493
|
const points = buildFadeVolumeCurve(bars, bpm, direction, sliderPos, gesture);
|
|
@@ -5227,8 +5496,8 @@ function useTransitionOps({
|
|
|
5227
5496
|
},
|
|
5228
5497
|
[host]
|
|
5229
5498
|
);
|
|
5230
|
-
const [isCreatingCrossfade, setIsCreatingCrossfade] = (0,
|
|
5231
|
-
const handleCreateCrossfade = (0,
|
|
5499
|
+
const [isCreatingCrossfade, setIsCreatingCrossfade] = (0, import_react26.useState)(false);
|
|
5500
|
+
const handleCreateCrossfade = (0, import_react26.useCallback)(
|
|
5232
5501
|
async (origin, target) => {
|
|
5233
5502
|
const scene = activeSceneId;
|
|
5234
5503
|
const fromSceneId = sceneContext?.transitionFromSceneId ?? "";
|
|
@@ -5356,8 +5625,8 @@ function useTransitionOps({
|
|
|
5356
5625
|
loadTracks
|
|
5357
5626
|
]
|
|
5358
5627
|
);
|
|
5359
|
-
const [isCreatingFade, setIsCreatingFade] = (0,
|
|
5360
|
-
const handleCreateFade = (0,
|
|
5628
|
+
const [isCreatingFade, setIsCreatingFade] = (0, import_react26.useState)(false);
|
|
5629
|
+
const handleCreateFade = (0, import_react26.useCallback)(
|
|
5361
5630
|
async (selection, direction, gesture) => {
|
|
5362
5631
|
const scene = activeSceneId;
|
|
5363
5632
|
const fromSceneId = sceneContext?.transitionFromSceneId ?? "";
|
|
@@ -5467,7 +5736,7 @@ function useTransitionOps({
|
|
|
5467
5736
|
loadTracks
|
|
5468
5737
|
]
|
|
5469
5738
|
);
|
|
5470
|
-
const handleCrossfadeMute = (0,
|
|
5739
|
+
const handleCrossfadeMute = (0, import_react26.useCallback)(
|
|
5471
5740
|
(pair) => {
|
|
5472
5741
|
const newMuted = !pair.origin.runtimeState.muted;
|
|
5473
5742
|
for (const id of [pair.origin.handle.id, pair.target.handle.id]) {
|
|
@@ -5482,7 +5751,7 @@ function useTransitionOps({
|
|
|
5482
5751
|
},
|
|
5483
5752
|
[host, setTracks]
|
|
5484
5753
|
);
|
|
5485
|
-
const handleCrossfadeSolo = (0,
|
|
5754
|
+
const handleCrossfadeSolo = (0, import_react26.useCallback)(
|
|
5486
5755
|
(pair) => {
|
|
5487
5756
|
const newSolo = !pair.origin.runtimeState.solo;
|
|
5488
5757
|
for (const id of [pair.origin.handle.id, pair.target.handle.id]) {
|
|
@@ -5497,7 +5766,7 @@ function useTransitionOps({
|
|
|
5497
5766
|
},
|
|
5498
5767
|
[host, setTracks]
|
|
5499
5768
|
);
|
|
5500
|
-
const handleCrossfadeDelete = (0,
|
|
5769
|
+
const handleCrossfadeDelete = (0, import_react26.useCallback)(
|
|
5501
5770
|
async (pair) => {
|
|
5502
5771
|
try {
|
|
5503
5772
|
for (const member of [pair.origin, pair.target]) {
|
|
@@ -5523,8 +5792,8 @@ function useTransitionOps({
|
|
|
5523
5792
|
},
|
|
5524
5793
|
[host, activeSceneId, setCrossfadePairsMeta, setTracks]
|
|
5525
5794
|
);
|
|
5526
|
-
const crossfadeSliderTimers = (0,
|
|
5527
|
-
const handleCrossfadeSlider = (0,
|
|
5795
|
+
const crossfadeSliderTimers = (0, import_react26.useRef)({});
|
|
5796
|
+
const handleCrossfadeSlider = (0, import_react26.useCallback)(
|
|
5528
5797
|
(pair, pos) => {
|
|
5529
5798
|
setCrossfadePairsMeta(
|
|
5530
5799
|
(prev) => prev.map((p) => p.groupId === pair.groupId ? { ...p, sliderPos: pos } : p)
|
|
@@ -5557,7 +5826,7 @@ function useTransitionOps({
|
|
|
5557
5826
|
},
|
|
5558
5827
|
[host, activeSceneId, applyCrossfadeAutomation, setCrossfadePairsMeta]
|
|
5559
5828
|
);
|
|
5560
|
-
const handleFadeDelete = (0,
|
|
5829
|
+
const handleFadeDelete = (0, import_react26.useCallback)(
|
|
5561
5830
|
async (fade) => {
|
|
5562
5831
|
try {
|
|
5563
5832
|
await host.deleteTrack(fade.track.handle.id);
|
|
@@ -5577,8 +5846,8 @@ function useTransitionOps({
|
|
|
5577
5846
|
},
|
|
5578
5847
|
[host, activeSceneId, setFadesMeta, setTracks]
|
|
5579
5848
|
);
|
|
5580
|
-
const fadeSliderTimers = (0,
|
|
5581
|
-
const handleFadeSlider = (0,
|
|
5849
|
+
const fadeSliderTimers = (0, import_react26.useRef)({});
|
|
5850
|
+
const handleFadeSlider = (0, import_react26.useCallback)(
|
|
5582
5851
|
(fade, pos) => {
|
|
5583
5852
|
setFadesMeta(
|
|
5584
5853
|
(prev) => prev.map((f) => f.dbId === fade.dbId ? { ...f, meta: { ...f.meta, sliderPos: pos } } : f)
|
|
@@ -5608,8 +5877,8 @@ function useTransitionOps({
|
|
|
5608
5877
|
},
|
|
5609
5878
|
[host, activeSceneId, applyFadeAutomation, setFadesMeta]
|
|
5610
5879
|
);
|
|
5611
|
-
const lastResyncKeyRef = (0,
|
|
5612
|
-
(0,
|
|
5880
|
+
const lastResyncKeyRef = (0, import_react26.useRef)("");
|
|
5881
|
+
(0, import_react26.useEffect)(() => {
|
|
5613
5882
|
if (!host.getTrackSound || resolvedCrossfadePairs.length === 0 && resolvedFades.length === 0) {
|
|
5614
5883
|
return;
|
|
5615
5884
|
}
|
|
@@ -5650,7 +5919,7 @@ function useTransitionOps({
|
|
|
5650
5919
|
cancelled = true;
|
|
5651
5920
|
};
|
|
5652
5921
|
}, [resolvedCrossfadePairs, resolvedFades, host, adapter]);
|
|
5653
|
-
(0,
|
|
5922
|
+
(0, import_react26.useEffect)(() => {
|
|
5654
5923
|
if (!host.setTrackVolumeAutomation || resolvedFades.length === 0) return;
|
|
5655
5924
|
void (async () => {
|
|
5656
5925
|
const mc = await host.getMusicalContext();
|
|
@@ -5684,7 +5953,7 @@ function useTransitionOps({
|
|
|
5684
5953
|
}
|
|
5685
5954
|
|
|
5686
5955
|
// src/panel-core/useGeneratorPanelCore.tsx
|
|
5687
|
-
var
|
|
5956
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
5688
5957
|
var EMPTY_PLACEHOLDERS = [];
|
|
5689
5958
|
function useGeneratorPanelCore({
|
|
5690
5959
|
ui,
|
|
@@ -5704,8 +5973,8 @@ function useGeneratorPanelCore({
|
|
|
5704
5973
|
} = ui;
|
|
5705
5974
|
const { identity, features } = adapter;
|
|
5706
5975
|
const logTag = identity.logTag;
|
|
5707
|
-
const adapterRef = (0,
|
|
5708
|
-
(0,
|
|
5976
|
+
const adapterRef = (0, import_react27.useRef)(adapter);
|
|
5977
|
+
(0, import_react27.useEffect)(() => {
|
|
5709
5978
|
if (adapterRef.current !== adapter) {
|
|
5710
5979
|
adapterRef.current = adapter;
|
|
5711
5980
|
console.warn(
|
|
@@ -5715,27 +5984,27 @@ function useGeneratorPanelCore({
|
|
|
5715
5984
|
}, [adapter, logTag]);
|
|
5716
5985
|
const supportsMeters = typeof host.getTrackLevels === "function";
|
|
5717
5986
|
const trackLevels = useTrackLevels(host, isExpanded);
|
|
5718
|
-
const [tracks, setTracks] = (0,
|
|
5719
|
-
const [isLoadingTracks, setIsLoadingTracks] = (0,
|
|
5720
|
-
const [importOpen, setImportOpen] = (0,
|
|
5721
|
-
const [soundImportTarget, setSoundImportTarget] = (0,
|
|
5722
|
-
const [designerView, setDesignerView] = (0,
|
|
5723
|
-
const [transitionSourceTotal, setTransitionSourceTotal] = (0,
|
|
5724
|
-
const [crossfadePairsMeta, setCrossfadePairsMeta] = (0,
|
|
5725
|
-
const [fadesMeta, setFadesMeta] = (0,
|
|
5726
|
-
const [genericGroupMetas, setGenericGroupMetas] = (0,
|
|
5987
|
+
const [tracks, setTracks] = (0, import_react27.useState)([]);
|
|
5988
|
+
const [isLoadingTracks, setIsLoadingTracks] = (0, import_react27.useState)(false);
|
|
5989
|
+
const [importOpen, setImportOpen] = (0, import_react27.useState)(false);
|
|
5990
|
+
const [soundImportTarget, setSoundImportTarget] = (0, import_react27.useState)(null);
|
|
5991
|
+
const [designerView, setDesignerView] = (0, import_react27.useState)(false);
|
|
5992
|
+
const [transitionSourceTotal, setTransitionSourceTotal] = (0, import_react27.useState)(0);
|
|
5993
|
+
const [crossfadePairsMeta, setCrossfadePairsMeta] = (0, import_react27.useState)([]);
|
|
5994
|
+
const [fadesMeta, setFadesMeta] = (0, import_react27.useState)([]);
|
|
5995
|
+
const [genericGroupMetas, setGenericGroupMetas] = (0, import_react27.useState)({});
|
|
5727
5996
|
const [isComposing, , setIsComposingForScene] = useSceneState(activeSceneId, false);
|
|
5728
5997
|
const [placeholders, , setPlaceholdersForScene] = useSceneState(
|
|
5729
5998
|
activeSceneId,
|
|
5730
5999
|
EMPTY_PLACEHOLDERS
|
|
5731
6000
|
);
|
|
5732
|
-
const saveTimeoutRefs = (0,
|
|
5733
|
-
const editLoadStartedRef = (0,
|
|
5734
|
-
const [availableInstruments, setAvailableInstruments] = (0,
|
|
5735
|
-
const [instrumentsLoading, setInstrumentsLoading] = (0,
|
|
5736
|
-
const engineToDbIdRef = (0,
|
|
5737
|
-
const tracksLoadedForSceneRef = (0,
|
|
5738
|
-
const persistSoundHistory = (0,
|
|
6001
|
+
const saveTimeoutRefs = (0, import_react27.useRef)({});
|
|
6002
|
+
const editLoadStartedRef = (0, import_react27.useRef)(/* @__PURE__ */ new Set());
|
|
6003
|
+
const [availableInstruments, setAvailableInstruments] = (0, import_react27.useState)([]);
|
|
6004
|
+
const [instrumentsLoading, setInstrumentsLoading] = (0, import_react27.useState)(false);
|
|
6005
|
+
const engineToDbIdRef = (0, import_react27.useRef)(/* @__PURE__ */ new Map());
|
|
6006
|
+
const tracksLoadedForSceneRef = (0, import_react27.useRef)(null);
|
|
6007
|
+
const persistSoundHistory = (0, import_react27.useCallback)(
|
|
5739
6008
|
(trackId, state) => {
|
|
5740
6009
|
if (!activeSceneId) return;
|
|
5741
6010
|
const dbId = engineToDbIdRef.current.get(trackId) ?? trackId;
|
|
@@ -5755,7 +6024,7 @@ function useGeneratorPanelCore({
|
|
|
5755
6024
|
setItems: setTracks,
|
|
5756
6025
|
getId: (t) => t.handle.dbId
|
|
5757
6026
|
});
|
|
5758
|
-
const loadTracks = (0,
|
|
6027
|
+
const loadTracks = (0, import_react27.useCallback)(
|
|
5759
6028
|
async (incremental = false) => {
|
|
5760
6029
|
const sceneAtStart = activeSceneId;
|
|
5761
6030
|
if (!sceneAtStart) {
|
|
@@ -5880,18 +6149,18 @@ function useGeneratorPanelCore({
|
|
|
5880
6149
|
},
|
|
5881
6150
|
[host, activeSceneId, soundHistory, adapter, logTag]
|
|
5882
6151
|
);
|
|
5883
|
-
(0,
|
|
6152
|
+
(0, import_react27.useEffect)(() => {
|
|
5884
6153
|
loadTracks();
|
|
5885
6154
|
}, [loadTracks]);
|
|
5886
|
-
(0,
|
|
6155
|
+
(0, import_react27.useEffect)(() => {
|
|
5887
6156
|
const map = /* @__PURE__ */ new Map();
|
|
5888
6157
|
for (const t of tracks) {
|
|
5889
6158
|
map.set(t.handle.id, t.handle.dbId);
|
|
5890
6159
|
}
|
|
5891
6160
|
engineToDbIdRef.current = map;
|
|
5892
6161
|
}, [tracks]);
|
|
5893
|
-
const loadedCompletedIdsRef = (0,
|
|
5894
|
-
(0,
|
|
6162
|
+
const loadedCompletedIdsRef = (0, import_react27.useRef)(/* @__PURE__ */ new Set());
|
|
6163
|
+
(0, import_react27.useEffect)(() => {
|
|
5895
6164
|
if (placeholders.length === 0) {
|
|
5896
6165
|
loadedCompletedIdsRef.current.clear();
|
|
5897
6166
|
return;
|
|
@@ -5910,16 +6179,16 @@ function useGeneratorPanelCore({
|
|
|
5910
6179
|
loadTracks(true);
|
|
5911
6180
|
}
|
|
5912
6181
|
}, [placeholders, loadTracks, logTag]);
|
|
5913
|
-
const adoptAndLoad = (0,
|
|
6182
|
+
const adoptAndLoad = (0, import_react27.useCallback)(() => {
|
|
5914
6183
|
loadTracks(true);
|
|
5915
6184
|
}, [loadTracks]);
|
|
5916
|
-
(0,
|
|
6185
|
+
(0, import_react27.useEffect)(() => {
|
|
5917
6186
|
const unsub = host.onEngineReady(() => {
|
|
5918
6187
|
adoptAndLoad();
|
|
5919
6188
|
});
|
|
5920
6189
|
return unsub;
|
|
5921
6190
|
}, [host, adoptAndLoad]);
|
|
5922
|
-
(0,
|
|
6191
|
+
(0, import_react27.useEffect)(() => {
|
|
5923
6192
|
if (typeof host.onAfterAgentMutation !== "function") return;
|
|
5924
6193
|
let timer = null;
|
|
5925
6194
|
const unsub = host.onAfterAgentMutation(() => {
|
|
@@ -5934,13 +6203,13 @@ function useGeneratorPanelCore({
|
|
|
5934
6203
|
if (timer) clearTimeout(timer);
|
|
5935
6204
|
};
|
|
5936
6205
|
}, [host, loadTracks]);
|
|
5937
|
-
(0,
|
|
6206
|
+
(0, import_react27.useEffect)(() => {
|
|
5938
6207
|
const unsub = host.onTrackStateChange((trackId, state) => {
|
|
5939
6208
|
setTracks((prev) => prev.map((t) => t.handle.id === trackId ? { ...t, runtimeState: state } : t));
|
|
5940
6209
|
});
|
|
5941
6210
|
return unsub;
|
|
5942
6211
|
}, [host]);
|
|
5943
|
-
(0,
|
|
6212
|
+
(0, import_react27.useEffect)(() => {
|
|
5944
6213
|
if (!features.bulkComposePlaceholders) return;
|
|
5945
6214
|
console.log(`[${logTag}] Subscribing to composeProgress`);
|
|
5946
6215
|
const unsub = host.onComposeProgress((event) => {
|
|
@@ -5974,7 +6243,7 @@ function useGeneratorPanelCore({
|
|
|
5974
6243
|
});
|
|
5975
6244
|
return unsub;
|
|
5976
6245
|
}, [host, setIsComposingForScene, setPlaceholdersForScene, features.bulkComposePlaceholders, logTag]);
|
|
5977
|
-
(0,
|
|
6246
|
+
(0, import_react27.useEffect)(() => {
|
|
5978
6247
|
const refs = saveTimeoutRefs;
|
|
5979
6248
|
return () => {
|
|
5980
6249
|
for (const timeout of Object.values(refs.current)) {
|
|
@@ -5982,9 +6251,9 @@ function useGeneratorPanelCore({
|
|
|
5982
6251
|
}
|
|
5983
6252
|
};
|
|
5984
6253
|
}, []);
|
|
5985
|
-
const isAddingTrackRef = (0,
|
|
5986
|
-
const [isAddingTrack, setIsAddingTrack] = (0,
|
|
5987
|
-
const handleAddTrack = (0,
|
|
6254
|
+
const isAddingTrackRef = (0, import_react27.useRef)(false);
|
|
6255
|
+
const [isAddingTrack, setIsAddingTrack] = (0, import_react27.useState)(false);
|
|
6256
|
+
const handleAddTrack = (0, import_react27.useCallback)(async () => {
|
|
5988
6257
|
if (isAddingTrackRef.current) return;
|
|
5989
6258
|
if (!activeSceneId) {
|
|
5990
6259
|
host.showToast("warning", "Select SCENE");
|
|
@@ -6024,7 +6293,7 @@ function useGeneratorPanelCore({
|
|
|
6024
6293
|
setIsAddingTrack(false);
|
|
6025
6294
|
}
|
|
6026
6295
|
}, [host, adapter, identity, activeSceneId, isConnected, isAuthenticated, tracks.length, onExpandSelf]);
|
|
6027
|
-
const handlePortTrack = (0,
|
|
6296
|
+
const handlePortTrack = (0, import_react27.useCallback)(
|
|
6028
6297
|
async (sel) => {
|
|
6029
6298
|
if (!activeSceneId) {
|
|
6030
6299
|
host.showToast("warning", "Select SCENE");
|
|
@@ -6081,7 +6350,7 @@ function useGeneratorPanelCore({
|
|
|
6081
6350
|
},
|
|
6082
6351
|
[host, adapter, identity, activeSceneId, isConnected, tracks.length, loadTracks]
|
|
6083
6352
|
);
|
|
6084
|
-
const handleSoundImportPick = (0,
|
|
6353
|
+
const handleSoundImportPick = (0, import_react27.useCallback)(
|
|
6085
6354
|
async (sel) => {
|
|
6086
6355
|
const target = soundImportTarget;
|
|
6087
6356
|
if (!target || !host.getTrackSound) {
|
|
@@ -6112,8 +6381,8 @@ function useGeneratorPanelCore({
|
|
|
6112
6381
|
},
|
|
6113
6382
|
[soundImportTarget, host, adapter, identity.familyKey, soundHistory]
|
|
6114
6383
|
);
|
|
6115
|
-
const [isExportingMidi, setIsExportingMidi] = (0,
|
|
6116
|
-
const handleExportMidi = (0,
|
|
6384
|
+
const [isExportingMidi, setIsExportingMidi] = (0, import_react27.useState)(false);
|
|
6385
|
+
const handleExportMidi = (0, import_react27.useCallback)(async () => {
|
|
6117
6386
|
if (isExportingMidi) return;
|
|
6118
6387
|
setIsExportingMidi(true);
|
|
6119
6388
|
try {
|
|
@@ -6144,10 +6413,10 @@ function useGeneratorPanelCore({
|
|
|
6144
6413
|
const xfFromId = sceneContext?.transitionFromSceneId ?? null;
|
|
6145
6414
|
const xfToId = sceneContext?.transitionToSceneId ?? null;
|
|
6146
6415
|
const canCrossfade = features.transitionDesigner && sceneContext?.sceneType === "transition" && !!xfFromId && !!xfToId && !!host.listSceneFamilyTracks;
|
|
6147
|
-
(0,
|
|
6416
|
+
(0, import_react27.useEffect)(() => {
|
|
6148
6417
|
if (!canCrossfade) setDesignerView(false);
|
|
6149
6418
|
}, [canCrossfade]);
|
|
6150
|
-
(0,
|
|
6419
|
+
(0, import_react27.useEffect)(() => {
|
|
6151
6420
|
if (!canCrossfade || !xfFromId || !xfToId || !host.listSceneFamilyTracks) {
|
|
6152
6421
|
setTransitionSourceTotal(0);
|
|
6153
6422
|
return;
|
|
@@ -6163,12 +6432,12 @@ function useGeneratorPanelCore({
|
|
|
6163
6432
|
};
|
|
6164
6433
|
}, [canCrossfade, xfFromId, xfToId, host]);
|
|
6165
6434
|
const transitionDone = crossfadePairsMeta.length * 2 + fadesMeta.length;
|
|
6166
|
-
(0,
|
|
6435
|
+
(0, import_react27.useEffect)(() => {
|
|
6167
6436
|
if (!onHeaderContent) return;
|
|
6168
6437
|
const addDisabled = needsContract || !isConnected || !activeSceneId || tracks.length >= identity.maxTracks || isAddingTrack;
|
|
6169
6438
|
onHeaderContent(
|
|
6170
|
-
/* @__PURE__ */ (0,
|
|
6171
|
-
features.importTracks && (!canCrossfade || !designerView) && host.listImportableTracks && /* @__PURE__ */ (0,
|
|
6439
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex gap-1 items-center", children: [
|
|
6440
|
+
features.importTracks && (!canCrossfade || !designerView) && host.listImportableTracks && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
6172
6441
|
"button",
|
|
6173
6442
|
{
|
|
6174
6443
|
"data-testid": `import-from-scene-${identity.familyKey}-button`,
|
|
@@ -6182,7 +6451,7 @@ function useGeneratorPanelCore({
|
|
|
6182
6451
|
children: identity.importTrackLabel ?? "Import Track"
|
|
6183
6452
|
}
|
|
6184
6453
|
),
|
|
6185
|
-
(!canCrossfade || !designerView) && /* @__PURE__ */ (0,
|
|
6454
|
+
(!canCrossfade || !designerView) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
6186
6455
|
"button",
|
|
6187
6456
|
{
|
|
6188
6457
|
"data-testid": `add-${identity.familyKey}-track-button`,
|
|
@@ -6198,7 +6467,7 @@ function useGeneratorPanelCore({
|
|
|
6198
6467
|
children: identity.addTrackLabel ?? "Add Track"
|
|
6199
6468
|
}
|
|
6200
6469
|
),
|
|
6201
|
-
canCrossfade && /* @__PURE__ */ (0,
|
|
6470
|
+
canCrossfade && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
6202
6471
|
"button",
|
|
6203
6472
|
{
|
|
6204
6473
|
"data-testid": `${identity.familyKey}-view-toggle`,
|
|
@@ -6217,7 +6486,7 @@ function useGeneratorPanelCore({
|
|
|
6217
6486
|
title: designerView ? "Back to the track list" : "Open the transition designer",
|
|
6218
6487
|
className: "relative overflow-hidden px-2 py-0.5 text-[10px] font-medium rounded-sm border border-sas-accent/40 text-sas-accent transition-colors hover:border-sas-accent disabled:opacity-50",
|
|
6219
6488
|
children: [
|
|
6220
|
-
transitionSourceTotal > 0 && /* @__PURE__ */ (0,
|
|
6489
|
+
transitionSourceTotal > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
6221
6490
|
"span",
|
|
6222
6491
|
{
|
|
6223
6492
|
className: "absolute inset-y-0 left-0 bg-sas-accent/25",
|
|
@@ -6225,7 +6494,7 @@ function useGeneratorPanelCore({
|
|
|
6225
6494
|
"aria-hidden": true
|
|
6226
6495
|
}
|
|
6227
6496
|
),
|
|
6228
|
-
/* @__PURE__ */ (0,
|
|
6497
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { className: "relative", children: [
|
|
6229
6498
|
"\u21C4 ",
|
|
6230
6499
|
designerView ? "Transition" : "Tracks",
|
|
6231
6500
|
transitionSourceTotal > 0 ? ` ${transitionDone}/${transitionSourceTotal}` : ""
|
|
@@ -6256,7 +6525,7 @@ function useGeneratorPanelCore({
|
|
|
6256
6525
|
identity,
|
|
6257
6526
|
features.importTracks
|
|
6258
6527
|
]);
|
|
6259
|
-
(0,
|
|
6528
|
+
(0, import_react27.useEffect)(() => {
|
|
6260
6529
|
if (!onLoading) return;
|
|
6261
6530
|
const anyGenerating = tracks.some((t) => t.isGenerating);
|
|
6262
6531
|
onLoading(isLoadingTracks || anyGenerating || isBulkActive);
|
|
@@ -6264,7 +6533,7 @@ function useGeneratorPanelCore({
|
|
|
6264
6533
|
onLoading(false);
|
|
6265
6534
|
};
|
|
6266
6535
|
}, [onLoading, isLoadingTracks, tracks, isBulkActive]);
|
|
6267
|
-
const handleDeleteTrack = (0,
|
|
6536
|
+
const handleDeleteTrack = (0, import_react27.useCallback)(
|
|
6268
6537
|
async (trackId) => {
|
|
6269
6538
|
try {
|
|
6270
6539
|
await host.deleteTrack(trackId);
|
|
@@ -6280,7 +6549,7 @@ function useGeneratorPanelCore({
|
|
|
6280
6549
|
},
|
|
6281
6550
|
[host, activeSceneId]
|
|
6282
6551
|
);
|
|
6283
|
-
const handlePromptChange = (0,
|
|
6552
|
+
const handlePromptChange = (0, import_react27.useCallback)(
|
|
6284
6553
|
(trackId, prompt) => {
|
|
6285
6554
|
setTracks((prev) => prev.map((t) => t.handle.id === trackId ? { ...t, prompt } : t));
|
|
6286
6555
|
const dbId = engineToDbIdRef.current.get(trackId) ?? trackId;
|
|
@@ -6296,7 +6565,7 @@ function useGeneratorPanelCore({
|
|
|
6296
6565
|
},
|
|
6297
6566
|
[host, activeSceneId]
|
|
6298
6567
|
);
|
|
6299
|
-
const resolvedGenericGroups = (0,
|
|
6568
|
+
const resolvedGenericGroups = (0, import_react27.useMemo)(() => {
|
|
6300
6569
|
const out = {};
|
|
6301
6570
|
for (const ext of adapter.groupExtensions ?? []) {
|
|
6302
6571
|
out[ext.metaKey] = resolveTrackGroups(
|
|
@@ -6310,18 +6579,18 @@ function useGeneratorPanelCore({
|
|
|
6310
6579
|
}
|
|
6311
6580
|
return out;
|
|
6312
6581
|
}, [adapter, genericGroupMetas, tracks]);
|
|
6313
|
-
const genericGroupMemberDbIds = (0,
|
|
6582
|
+
const genericGroupMemberDbIds = (0, import_react27.useMemo)(() => {
|
|
6314
6583
|
const s = /* @__PURE__ */ new Set();
|
|
6315
6584
|
for (const r of Object.values(resolvedGenericGroups)) {
|
|
6316
6585
|
for (const dbId of r.memberDbIds) s.add(dbId);
|
|
6317
6586
|
}
|
|
6318
6587
|
return s;
|
|
6319
6588
|
}, [resolvedGenericGroups]);
|
|
6320
|
-
const engineToDbId = (0,
|
|
6589
|
+
const engineToDbId = (0, import_react27.useCallback)(
|
|
6321
6590
|
(trackId) => engineToDbIdRef.current.get(trackId) ?? trackId,
|
|
6322
6591
|
[]
|
|
6323
6592
|
);
|
|
6324
|
-
const updateTrack = (0,
|
|
6593
|
+
const updateTrack = (0, import_react27.useCallback)(
|
|
6325
6594
|
(trackId, patch) => {
|
|
6326
6595
|
setTracks(
|
|
6327
6596
|
(prev) => prev.map(
|
|
@@ -6331,18 +6600,18 @@ function useGeneratorPanelCore({
|
|
|
6331
6600
|
},
|
|
6332
6601
|
[]
|
|
6333
6602
|
);
|
|
6334
|
-
const markEditLoaded = (0,
|
|
6603
|
+
const markEditLoaded = (0, import_react27.useCallback)((trackId) => {
|
|
6335
6604
|
editLoadStartedRef.current.add(trackId);
|
|
6336
6605
|
}, []);
|
|
6337
|
-
const tracksRef = (0,
|
|
6338
|
-
(0,
|
|
6606
|
+
const tracksRef = (0, import_react27.useRef)(tracks);
|
|
6607
|
+
(0, import_react27.useEffect)(() => {
|
|
6339
6608
|
tracksRef.current = tracks;
|
|
6340
6609
|
}, [tracks]);
|
|
6341
|
-
const resolvedGenericGroupsRef = (0,
|
|
6342
|
-
(0,
|
|
6610
|
+
const resolvedGenericGroupsRef = (0, import_react27.useRef)(resolvedGenericGroups);
|
|
6611
|
+
(0, import_react27.useEffect)(() => {
|
|
6343
6612
|
resolvedGenericGroupsRef.current = resolvedGenericGroups;
|
|
6344
6613
|
}, [resolvedGenericGroups]);
|
|
6345
|
-
const makeServices = (0,
|
|
6614
|
+
const makeServices = (0, import_react27.useCallback)(() => {
|
|
6346
6615
|
return {
|
|
6347
6616
|
host,
|
|
6348
6617
|
activeSceneId,
|
|
@@ -6361,7 +6630,7 @@ function useGeneratorPanelCore({
|
|
|
6361
6630
|
resolvedGroups: (metaKey) => resolvedGenericGroupsRef.current[metaKey]?.resolved ?? []
|
|
6362
6631
|
};
|
|
6363
6632
|
}, [host, activeSceneId, updateTrack, loadTracks, soundHistory, engineToDbId, markEditLoaded, identity, adapter]);
|
|
6364
|
-
const handleGenerate = (0,
|
|
6633
|
+
const handleGenerate = (0, import_react27.useCallback)(
|
|
6365
6634
|
async (trackId) => {
|
|
6366
6635
|
const track = tracks.find((t) => t.handle.id === trackId);
|
|
6367
6636
|
if (!track || !track.prompt.trim()) return;
|
|
@@ -6388,7 +6657,7 @@ function useGeneratorPanelCore({
|
|
|
6388
6657
|
},
|
|
6389
6658
|
[host, adapter, tracks, isAuthenticated, makeServices]
|
|
6390
6659
|
);
|
|
6391
|
-
const handleMuteToggle = (0,
|
|
6660
|
+
const handleMuteToggle = (0, import_react27.useCallback)(
|
|
6392
6661
|
(trackId) => {
|
|
6393
6662
|
const track = tracks.find((t) => t.handle.id === trackId);
|
|
6394
6663
|
if (!track) return;
|
|
@@ -6408,7 +6677,7 @@ function useGeneratorPanelCore({
|
|
|
6408
6677
|
},
|
|
6409
6678
|
[host, tracks]
|
|
6410
6679
|
);
|
|
6411
|
-
const handleSoloToggle = (0,
|
|
6680
|
+
const handleSoloToggle = (0, import_react27.useCallback)(
|
|
6412
6681
|
(trackId) => {
|
|
6413
6682
|
const track = tracks.find((t) => t.handle.id === trackId);
|
|
6414
6683
|
if (!track) return;
|
|
@@ -6428,7 +6697,7 @@ function useGeneratorPanelCore({
|
|
|
6428
6697
|
},
|
|
6429
6698
|
[host, tracks]
|
|
6430
6699
|
);
|
|
6431
|
-
const handleVolumeChange = (0,
|
|
6700
|
+
const handleVolumeChange = (0, import_react27.useCallback)(
|
|
6432
6701
|
(trackId, volume) => {
|
|
6433
6702
|
setTracks(
|
|
6434
6703
|
(prev) => prev.map((t) => t.handle.id === trackId ? { ...t, runtimeState: { ...t.runtimeState, volume } } : t)
|
|
@@ -6438,7 +6707,7 @@ function useGeneratorPanelCore({
|
|
|
6438
6707
|
},
|
|
6439
6708
|
[host]
|
|
6440
6709
|
);
|
|
6441
|
-
const handlePanChange = (0,
|
|
6710
|
+
const handlePanChange = (0, import_react27.useCallback)(
|
|
6442
6711
|
(trackId, pan) => {
|
|
6443
6712
|
setTracks(
|
|
6444
6713
|
(prev) => prev.map((t) => t.handle.id === trackId ? { ...t, runtimeState: { ...t.runtimeState, pan } } : t)
|
|
@@ -6448,7 +6717,7 @@ function useGeneratorPanelCore({
|
|
|
6448
6717
|
},
|
|
6449
6718
|
[host]
|
|
6450
6719
|
);
|
|
6451
|
-
const handleShuffle = (0,
|
|
6720
|
+
const handleShuffle = (0, import_react27.useCallback)(
|
|
6452
6721
|
async (trackId) => {
|
|
6453
6722
|
const track = tracks.find((t) => t.handle.id === trackId);
|
|
6454
6723
|
if (!track) return;
|
|
@@ -6490,7 +6759,7 @@ function useGeneratorPanelCore({
|
|
|
6490
6759
|
},
|
|
6491
6760
|
[host, adapter, tracks, soundHistory, logTag]
|
|
6492
6761
|
);
|
|
6493
|
-
const handleCopy = (0,
|
|
6762
|
+
const handleCopy = (0, import_react27.useCallback)(
|
|
6494
6763
|
async (trackId) => {
|
|
6495
6764
|
try {
|
|
6496
6765
|
const newHandle = await host.duplicateTrack(trackId);
|
|
@@ -6503,7 +6772,7 @@ function useGeneratorPanelCore({
|
|
|
6503
6772
|
},
|
|
6504
6773
|
[host, loadTracks]
|
|
6505
6774
|
);
|
|
6506
|
-
const handleFxToggle = (0,
|
|
6775
|
+
const handleFxToggle = (0, import_react27.useCallback)(
|
|
6507
6776
|
(trackId, category, enabled) => {
|
|
6508
6777
|
setTracks(
|
|
6509
6778
|
(prev) => prev.map(
|
|
@@ -6526,7 +6795,7 @@ function useGeneratorPanelCore({
|
|
|
6526
6795
|
},
|
|
6527
6796
|
[host]
|
|
6528
6797
|
);
|
|
6529
|
-
const handleFxPresetChange = (0,
|
|
6798
|
+
const handleFxPresetChange = (0, import_react27.useCallback)(
|
|
6530
6799
|
(trackId, category, presetIndex) => {
|
|
6531
6800
|
setTracks(
|
|
6532
6801
|
(prev) => prev.map(
|
|
@@ -6552,7 +6821,7 @@ function useGeneratorPanelCore({
|
|
|
6552
6821
|
},
|
|
6553
6822
|
[host]
|
|
6554
6823
|
);
|
|
6555
|
-
const handleFxDryWetChange = (0,
|
|
6824
|
+
const handleFxDryWetChange = (0, import_react27.useCallback)(
|
|
6556
6825
|
(trackId, category, value) => {
|
|
6557
6826
|
setTracks(
|
|
6558
6827
|
(prev) => prev.map(
|
|
@@ -6564,7 +6833,7 @@ function useGeneratorPanelCore({
|
|
|
6564
6833
|
},
|
|
6565
6834
|
[host]
|
|
6566
6835
|
);
|
|
6567
|
-
const toggleFxDrawer = (0,
|
|
6836
|
+
const toggleFxDrawer = (0, import_react27.useCallback)(
|
|
6568
6837
|
(trackId) => {
|
|
6569
6838
|
setTracks(
|
|
6570
6839
|
(prev) => prev.map((t) => {
|
|
@@ -6586,7 +6855,7 @@ function useGeneratorPanelCore({
|
|
|
6586
6855
|
},
|
|
6587
6856
|
[host, tracks]
|
|
6588
6857
|
);
|
|
6589
|
-
const loadEditNotes = (0,
|
|
6858
|
+
const loadEditNotes = (0, import_react27.useCallback)(
|
|
6590
6859
|
async (trackId) => {
|
|
6591
6860
|
try {
|
|
6592
6861
|
const mc = await host.getMusicalContext();
|
|
@@ -6604,7 +6873,7 @@ function useGeneratorPanelCore({
|
|
|
6604
6873
|
},
|
|
6605
6874
|
[host, logTag]
|
|
6606
6875
|
);
|
|
6607
|
-
const handleNotesChange = (0,
|
|
6876
|
+
const handleNotesChange = (0, import_react27.useCallback)(
|
|
6608
6877
|
(trackId, notes) => {
|
|
6609
6878
|
setTracks((prev) => prev.map((t) => t.handle.id === trackId ? { ...t, editNotes: notes } : t));
|
|
6610
6879
|
const key = `edit:${trackId}`;
|
|
@@ -6634,7 +6903,7 @@ function useGeneratorPanelCore({
|
|
|
6634
6903
|
},
|
|
6635
6904
|
[host]
|
|
6636
6905
|
);
|
|
6637
|
-
const handleTabChange = (0,
|
|
6906
|
+
const handleTabChange = (0, import_react27.useCallback)(
|
|
6638
6907
|
(trackId, tab) => {
|
|
6639
6908
|
setTracks((prev) => prev.map((t) => t.handle.id === trackId ? { ...t, drawerOpen: true, drawerTab: tab } : t));
|
|
6640
6909
|
if (tab === "fx") {
|
|
@@ -6659,10 +6928,10 @@ function useGeneratorPanelCore({
|
|
|
6659
6928
|
},
|
|
6660
6929
|
[host, availableInstruments.length, instrumentsLoading, loadEditNotes]
|
|
6661
6930
|
);
|
|
6662
|
-
const handleProgressChange = (0,
|
|
6931
|
+
const handleProgressChange = (0, import_react27.useCallback)((trackId, pct) => {
|
|
6663
6932
|
setTracks((prev) => prev.map((t) => t.handle.id === trackId ? { ...t, generationProgress: pct } : t));
|
|
6664
6933
|
}, []);
|
|
6665
|
-
const handleToggleDrawer = (0,
|
|
6934
|
+
const handleToggleDrawer = (0, import_react27.useCallback)((trackId) => {
|
|
6666
6935
|
setTracks(
|
|
6667
6936
|
(prev) => prev.map((t) => {
|
|
6668
6937
|
if (t.handle.id !== trackId) return t;
|
|
@@ -6671,7 +6940,7 @@ function useGeneratorPanelCore({
|
|
|
6671
6940
|
})
|
|
6672
6941
|
);
|
|
6673
6942
|
}, []);
|
|
6674
|
-
const handleInstrumentSelect = (0,
|
|
6943
|
+
const handleInstrumentSelect = (0, import_react27.useCallback)(
|
|
6675
6944
|
async (trackId, pluginId) => {
|
|
6676
6945
|
const isDefaultInstrument = pluginId === (identity.defaultInstrumentPluginId ?? "Surge XT");
|
|
6677
6946
|
if (isDefaultInstrument) {
|
|
@@ -6724,7 +6993,7 @@ function useGeneratorPanelCore({
|
|
|
6724
6993
|
},
|
|
6725
6994
|
[host, identity.defaultInstrumentPluginId, logTag]
|
|
6726
6995
|
);
|
|
6727
|
-
const handleShowEditor = (0,
|
|
6996
|
+
const handleShowEditor = (0, import_react27.useCallback)(
|
|
6728
6997
|
async (trackId) => {
|
|
6729
6998
|
try {
|
|
6730
6999
|
await host.showInstrumentEditor(trackId);
|
|
@@ -6735,12 +7004,12 @@ function useGeneratorPanelCore({
|
|
|
6735
7004
|
},
|
|
6736
7005
|
[host]
|
|
6737
7006
|
);
|
|
6738
|
-
const handleBackToInstruments = (0,
|
|
7007
|
+
const handleBackToInstruments = (0, import_react27.useCallback)((trackId) => {
|
|
6739
7008
|
setTracks(
|
|
6740
7009
|
(prev) => prev.map((t) => t.handle.id === trackId ? { ...t, editorStage: false } : t)
|
|
6741
7010
|
);
|
|
6742
7011
|
}, []);
|
|
6743
|
-
const handleRefreshInstruments = (0,
|
|
7012
|
+
const handleRefreshInstruments = (0, import_react27.useCallback)(() => {
|
|
6744
7013
|
setInstrumentsLoading(true);
|
|
6745
7014
|
host.getAvailableInstruments().then((instruments) => {
|
|
6746
7015
|
setAvailableInstruments(instruments);
|
|
@@ -6749,13 +7018,13 @@ function useGeneratorPanelCore({
|
|
|
6749
7018
|
setInstrumentsLoading(false);
|
|
6750
7019
|
});
|
|
6751
7020
|
}, [host]);
|
|
6752
|
-
const onAuditionNote = (0,
|
|
7021
|
+
const onAuditionNote = (0, import_react27.useCallback)(
|
|
6753
7022
|
(trackId, pitch, velocity, ms) => {
|
|
6754
7023
|
void host.auditionNote(trackId, pitch, velocity, ms);
|
|
6755
7024
|
},
|
|
6756
7025
|
[host]
|
|
6757
7026
|
);
|
|
6758
|
-
const { resolvedCrossfadePairs, crossfadeMemberDbIds } = (0,
|
|
7027
|
+
const { resolvedCrossfadePairs, crossfadeMemberDbIds } = (0, import_react27.useMemo)(() => {
|
|
6759
7028
|
const byDbId = new Map(tracks.map((t) => [t.handle.dbId, t]));
|
|
6760
7029
|
const pairs = [];
|
|
6761
7030
|
const members = /* @__PURE__ */ new Set();
|
|
@@ -6770,7 +7039,7 @@ function useGeneratorPanelCore({
|
|
|
6770
7039
|
}
|
|
6771
7040
|
return { resolvedCrossfadePairs: pairs, crossfadeMemberDbIds: members };
|
|
6772
7041
|
}, [tracks, crossfadePairsMeta]);
|
|
6773
|
-
const { resolvedFades, fadeMemberDbIds } = (0,
|
|
7042
|
+
const { resolvedFades, fadeMemberDbIds } = (0, import_react27.useMemo)(() => {
|
|
6774
7043
|
const byDbId = new Map(tracks.map((t) => [t.handle.dbId, t]));
|
|
6775
7044
|
const list = [];
|
|
6776
7045
|
const members = /* @__PURE__ */ new Set();
|
|
@@ -6798,7 +7067,7 @@ function useGeneratorPanelCore({
|
|
|
6798
7067
|
resolvedCrossfadePairs,
|
|
6799
7068
|
resolvedFades
|
|
6800
7069
|
});
|
|
6801
|
-
const setGroupMute = (0,
|
|
7070
|
+
const setGroupMute = (0, import_react27.useCallback)(
|
|
6802
7071
|
(trackIds, muted) => {
|
|
6803
7072
|
for (const id of trackIds) {
|
|
6804
7073
|
setTracks(
|
|
@@ -6810,7 +7079,7 @@ function useGeneratorPanelCore({
|
|
|
6810
7079
|
},
|
|
6811
7080
|
[host]
|
|
6812
7081
|
);
|
|
6813
|
-
const setGroupSolo = (0,
|
|
7082
|
+
const setGroupSolo = (0, import_react27.useCallback)(
|
|
6814
7083
|
(trackIds, solo) => {
|
|
6815
7084
|
for (const id of trackIds) {
|
|
6816
7085
|
setTracks(
|
|
@@ -6822,7 +7091,7 @@ function useGeneratorPanelCore({
|
|
|
6822
7091
|
},
|
|
6823
7092
|
[host]
|
|
6824
7093
|
);
|
|
6825
|
-
const deleteGroup = (0,
|
|
7094
|
+
const deleteGroup = (0, import_react27.useCallback)(
|
|
6826
7095
|
async (members, cleanupKeySuffixes) => {
|
|
6827
7096
|
for (const member of members) {
|
|
6828
7097
|
try {
|
|
@@ -6842,7 +7111,7 @@ function useGeneratorPanelCore({
|
|
|
6842
7111
|
},
|
|
6843
7112
|
[host, activeSceneId, loadTracks]
|
|
6844
7113
|
);
|
|
6845
|
-
const handlers = (0,
|
|
7114
|
+
const handlers = (0, import_react27.useMemo)(
|
|
6846
7115
|
() => ({
|
|
6847
7116
|
promptChange: handlePromptChange,
|
|
6848
7117
|
generate: (trackId) => {
|
|
@@ -6956,8 +7225,8 @@ function useGeneratorPanelCore({
|
|
|
6956
7225
|
}
|
|
6957
7226
|
|
|
6958
7227
|
// src/panel-core/GeneratorPanelShell.tsx
|
|
6959
|
-
var
|
|
6960
|
-
var
|
|
7228
|
+
var import_react28 = __toESM(require("react"));
|
|
7229
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
6961
7230
|
function GeneratorPanelShell({ core, slots }) {
|
|
6962
7231
|
const {
|
|
6963
7232
|
ui,
|
|
@@ -7010,8 +7279,9 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7010
7279
|
deleteGroup
|
|
7011
7280
|
} = core;
|
|
7012
7281
|
const { host, activeSceneId, isAuthenticated, sceneContext, onSelectScene, onOpenContract } = ui;
|
|
7282
|
+
const panelBus = usePanelBus(host, activeSceneId);
|
|
7013
7283
|
const { identity, features } = adapter;
|
|
7014
|
-
const buildRowProps = (0,
|
|
7284
|
+
const buildRowProps = (0, import_react28.useCallback)(
|
|
7015
7285
|
(track, drag) => {
|
|
7016
7286
|
const id = track.handle.id;
|
|
7017
7287
|
const pickerProps = features.instrumentPicker ? {
|
|
@@ -7110,12 +7380,12 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7110
7380
|
]
|
|
7111
7381
|
);
|
|
7112
7382
|
if (!activeSceneId) {
|
|
7113
|
-
return /* @__PURE__ */ (0,
|
|
7383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7114
7384
|
"div",
|
|
7115
7385
|
{
|
|
7116
7386
|
"data-testid": `no-scene-placeholder-${identity.familyKey}`,
|
|
7117
7387
|
className: "flex items-center justify-center py-8",
|
|
7118
|
-
children: /* @__PURE__ */ (0,
|
|
7388
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7119
7389
|
"button",
|
|
7120
7390
|
{
|
|
7121
7391
|
onClick: () => onSelectScene?.(),
|
|
@@ -7127,12 +7397,12 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7127
7397
|
);
|
|
7128
7398
|
}
|
|
7129
7399
|
if (!sceneContext?.hasContract) {
|
|
7130
|
-
return /* @__PURE__ */ (0,
|
|
7400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7131
7401
|
"div",
|
|
7132
7402
|
{
|
|
7133
7403
|
"data-testid": `no-contract-placeholder-${identity.familyKey}`,
|
|
7134
7404
|
className: "flex items-center justify-center py-8",
|
|
7135
|
-
children: /* @__PURE__ */ (0,
|
|
7405
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7136
7406
|
"button",
|
|
7137
7407
|
{
|
|
7138
7408
|
onClick: () => onOpenContract?.(),
|
|
@@ -7144,7 +7414,7 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7144
7414
|
);
|
|
7145
7415
|
}
|
|
7146
7416
|
if (features.bulkComposePlaceholders && isComposing) {
|
|
7147
|
-
return /* @__PURE__ */ (0,
|
|
7417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { "data-testid": `${identity.familyKey}-section`, className: "p-2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SorceryProgressBar, { isLoading: true, statusText: "COMPOSING...", heightClass: "h-10" }) });
|
|
7148
7418
|
}
|
|
7149
7419
|
const activePlaceholders = features.bulkComposePlaceholders ? placeholders : [];
|
|
7150
7420
|
if (activePlaceholders.length > 0) {
|
|
@@ -7155,18 +7425,18 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7155
7425
|
tracksByDbId.set(t.handle.id, t);
|
|
7156
7426
|
}
|
|
7157
7427
|
}
|
|
7158
|
-
return /* @__PURE__ */ (0,
|
|
7428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { "data-testid": `${identity.familyKey}-section`, className: "p-2 space-y-2", children: activePlaceholders.map((ph) => {
|
|
7159
7429
|
const loadedTrack = ph.status === "completed" ? tracksByDbId.get(ph.id) : void 0;
|
|
7160
7430
|
if (loadedTrack) {
|
|
7161
|
-
return /* @__PURE__ */ (0,
|
|
7431
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TrackRow, { ...buildRowProps(loadedTrack) }, ph.id);
|
|
7162
7432
|
}
|
|
7163
|
-
return /* @__PURE__ */ (0,
|
|
7433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7164
7434
|
"div",
|
|
7165
7435
|
{
|
|
7166
7436
|
"data-testid": "bulk-placeholder-track",
|
|
7167
7437
|
className: "relative rounded-sm border w-full overflow-hidden border-sas-border bg-sas-panel-alt",
|
|
7168
7438
|
style: { borderLeftColor: identity.placeholderAccentColor, borderLeftWidth: "3px" },
|
|
7169
|
-
children: /* @__PURE__ */ (0,
|
|
7439
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SorceryProgressBar, { isLoading: true, statusText: "CONJURING MIDI...", heightClass: "h-10" })
|
|
7170
7440
|
},
|
|
7171
7441
|
ph.id
|
|
7172
7442
|
);
|
|
@@ -7178,13 +7448,13 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7178
7448
|
supportsMeters,
|
|
7179
7449
|
levels: supportsMeters ? trackLevels : void 0,
|
|
7180
7450
|
handlers,
|
|
7181
|
-
renderDefaultTrackRow: (track, overrides, drag) => /* @__PURE__ */ (0,
|
|
7451
|
+
renderDefaultTrackRow: (track, overrides, drag) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TrackRow, { ...{ ...buildRowProps(track, drag), ...overrides ?? {} } }, track.handle.id),
|
|
7182
7452
|
setGroupMute,
|
|
7183
7453
|
setGroupSolo,
|
|
7184
7454
|
deleteGroup
|
|
7185
7455
|
};
|
|
7186
|
-
return /* @__PURE__ */ (0,
|
|
7187
|
-
features.importTracks && host.listImportableTracks && /* @__PURE__ */ (0,
|
|
7456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { "data-testid": `${identity.familyKey}-section`, className: "p-2 space-y-2", children: [
|
|
7457
|
+
features.importTracks && host.listImportableTracks && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7188
7458
|
ImportTrackModal,
|
|
7189
7459
|
{
|
|
7190
7460
|
host,
|
|
@@ -7197,7 +7467,7 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7197
7467
|
testIdPrefix: `${identity.familyKey}-import`
|
|
7198
7468
|
}
|
|
7199
7469
|
),
|
|
7200
|
-
features.importTracks && host.listImportableTracks && host.getTrackSound && /* @__PURE__ */ (0,
|
|
7470
|
+
features.importTracks && host.listImportableTracks && host.getTrackSound && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7201
7471
|
ImportTrackModal,
|
|
7202
7472
|
{
|
|
7203
7473
|
host,
|
|
@@ -7212,7 +7482,7 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7212
7482
|
}
|
|
7213
7483
|
),
|
|
7214
7484
|
slots?.modals,
|
|
7215
|
-
canCrossfade && xfFromId && xfToId && /* @__PURE__ */ (0,
|
|
7485
|
+
canCrossfade && xfFromId && xfToId && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: designerView ? "contents" : "hidden", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7216
7486
|
TransitionDesigner,
|
|
7217
7487
|
{
|
|
7218
7488
|
host,
|
|
@@ -7229,9 +7499,28 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7229
7499
|
testIdPrefix: `${identity.familyKey}-transition-designer`
|
|
7230
7500
|
}
|
|
7231
7501
|
) }),
|
|
7232
|
-
!(designerView && canCrossfade) && (isLoadingTracks ? /* @__PURE__ */ (0,
|
|
7502
|
+
!(designerView && canCrossfade) && (isLoadingTracks ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-sas-muted text-xs text-center py-4", children: "Loading tracks..." }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
7503
|
+
panelBus.supported && panelBus.bus && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7504
|
+
PanelMasterStrip,
|
|
7505
|
+
{
|
|
7506
|
+
bus: panelBus.bus,
|
|
7507
|
+
availableFx: panelBus.availableFx,
|
|
7508
|
+
fxLoading: panelBus.fxLoading,
|
|
7509
|
+
soloedOut: anySolo && !panelBus.bus.soloed,
|
|
7510
|
+
fxPickerOpen: panelBus.fxPickerOpen,
|
|
7511
|
+
onToggleFxPicker: panelBus.setFxPickerOpen,
|
|
7512
|
+
onRefreshFx: panelBus.refreshFx,
|
|
7513
|
+
onVolumeChange: panelBus.onVolumeChange,
|
|
7514
|
+
onMuteToggle: panelBus.onMuteToggle,
|
|
7515
|
+
onSoloToggle: panelBus.onSoloToggle,
|
|
7516
|
+
onAddFx: panelBus.onAddFx,
|
|
7517
|
+
onRemoveFx: panelBus.onRemoveFx,
|
|
7518
|
+
onToggleFxEnabled: panelBus.onToggleFxEnabled,
|
|
7519
|
+
onShowFxEditor: panelBus.onShowFxEditor
|
|
7520
|
+
}
|
|
7521
|
+
),
|
|
7233
7522
|
slots?.beforeRows,
|
|
7234
|
-
resolvedCrossfadePairs.map((pair) => /* @__PURE__ */ (0,
|
|
7523
|
+
resolvedCrossfadePairs.map((pair) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7235
7524
|
CrossfadeTrackRow,
|
|
7236
7525
|
{
|
|
7237
7526
|
accentColor: identity.transitionAccentColor,
|
|
@@ -7268,7 +7557,7 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7268
7557
|
},
|
|
7269
7558
|
pair.groupId
|
|
7270
7559
|
)),
|
|
7271
|
-
resolvedFades.map((fade) => /* @__PURE__ */ (0,
|
|
7560
|
+
resolvedFades.map((fade) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7272
7561
|
FadeTrackRow,
|
|
7273
7562
|
{
|
|
7274
7563
|
accentColor: identity.transitionAccentColor,
|
|
@@ -7294,20 +7583,20 @@ function GeneratorPanelShell({ core, slots }) {
|
|
|
7294
7583
|
fade.dbId
|
|
7295
7584
|
)),
|
|
7296
7585
|
(adapter.groupExtensions ?? []).flatMap(
|
|
7297
|
-
(ext) => (resolvedGenericGroups[ext.metaKey]?.resolved ?? []).map((group) => /* @__PURE__ */ (0,
|
|
7586
|
+
(ext) => (resolvedGenericGroups[ext.metaKey]?.resolved ?? []).map((group) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_react28.default.Fragment, { children: ext.renderGroup(group, groupCtx) }, `${ext.metaKey}:${group.groupId}`))
|
|
7298
7587
|
),
|
|
7299
7588
|
tracks.map((track, index) => {
|
|
7300
7589
|
if (crossfadeMemberDbIds.has(track.handle.dbId) || fadeMemberDbIds.has(track.handle.dbId) || genericGroupMemberDbIds.has(track.handle.dbId)) {
|
|
7301
7590
|
return null;
|
|
7302
7591
|
}
|
|
7303
|
-
return /* @__PURE__ */ (0,
|
|
7592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TrackRow, { ...buildRowProps(track, reorder.dragPropsFor(index)) }, track.handle.id);
|
|
7304
7593
|
}),
|
|
7305
7594
|
slots?.afterRows
|
|
7306
7595
|
] })),
|
|
7307
7596
|
features.exportMidi && !designerView && !isLoadingTracks && tracks.length > 0 && (() => {
|
|
7308
7597
|
const hasAnyMidi = tracks.some((t) => t.hasMidi);
|
|
7309
7598
|
const exportDisabled = isExportingMidi || !hasAnyMidi;
|
|
7310
|
-
return /* @__PURE__ */ (0,
|
|
7599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "pt-2", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
7311
7600
|
"button",
|
|
7312
7601
|
{
|
|
7313
7602
|
"data-testid": "export-midi-tracks-button",
|
|
@@ -7375,7 +7664,7 @@ function createSurgeSoundAdapter(host, overrides = {}) {
|
|
|
7375
7664
|
}
|
|
7376
7665
|
|
|
7377
7666
|
// src/constants/sdk-version.ts
|
|
7378
|
-
var PLUGIN_SDK_VERSION = "2.
|
|
7667
|
+
var PLUGIN_SDK_VERSION = "2.37.0";
|
|
7379
7668
|
|
|
7380
7669
|
// src/utils/format-concurrent-tracks.ts
|
|
7381
7670
|
function formatConcurrentTracks(ctx) {
|
|
@@ -7551,6 +7840,7 @@ function pickTopKWeighted(scored, options = {}) {
|
|
|
7551
7840
|
PLUGIN_SDK_VERSION,
|
|
7552
7841
|
PX_PER_BEAT,
|
|
7553
7842
|
PanSlider,
|
|
7843
|
+
PanelMasterStrip,
|
|
7554
7844
|
PianoRollEditor,
|
|
7555
7845
|
PluginError,
|
|
7556
7846
|
RESIZE_HANDLE_PX,
|
|
@@ -7615,6 +7905,7 @@ function pickTopKWeighted(scored, options = {}) {
|
|
|
7615
7905
|
transposeNotes,
|
|
7616
7906
|
useAnySolo,
|
|
7617
7907
|
useGeneratorPanelCore,
|
|
7908
|
+
usePanelBus,
|
|
7618
7909
|
useSceneState,
|
|
7619
7910
|
useSoundHistory,
|
|
7620
7911
|
useTrackLevel,
|