fix: ghost border, track buttons clickable, per-track instrument silent

- Remove dashed border from ghost notes (fill-only at 25% opacity)
- Track column: replaced div overlay with natural flex child; use
  <button> elements with border-l-2 indicator; removed pointer-events
- Ghost playback: skip layers with no instrument assigned (silent)
  instead of playing with default piano
This commit is contained in:
2026-07-27 18:31:12 +07:00
parent 0500d16bc7
commit 509e171c20
2 changed files with 11 additions and 17 deletions
+7 -14
View File
@@ -4912,10 +4912,6 @@ const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, activeTracks, onClos
var w = note.duration_beats * pixelsPerBeat; var w = note.duration_beats * pixelsPerBeat;
var h = NoteHeight - 1; var h = NoteHeight - 1;
ctx.fillRect(x, y, w, h); ctx.fillRect(x, y, w, h);
ctx.setLineDash([2, 2]);
ctx.lineWidth = 1;
ctx.strokeRect(x, y, w, h);
ctx.setLineDash([]);
}); });
ctx.restore(); ctx.restore();
}); });
@@ -6127,11 +6123,9 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
/* 3. MAIN PIANO ROLL GRID (KEYBOARD + TRACK COL + CANVAS) */ /* 3. MAIN PIANO ROLL GRID (KEYBOARD + TRACK COL + CANVAS) */
React.createElement("div", { React.createElement("div", {
className: "flex-1 flex overflow-hidden min-h-0 relative" className: "flex-1 flex overflow-hidden min-h-0 relative"
}, /* Track column overlay — always visible */ React.createElement("div", { }, /* Track column */ React.createElement("div", {
className: "absolute left-0 top-0 w-[120px] bg-[#16161a] border-r border-zinc-800 z-10 flex flex-col overflow-hidden pointer-events-none", className: "w-[120px] bg-[#16161a] border-r border-zinc-800 shrink-0 flex flex-col z-10",
style: { height: KeybedPixelHeight + 'px' } style: { height: KeybedPixelHeight + 'px' }
}, React.createElement("div", {
className: "pointer-events-auto flex flex-col"
}, (allMidiItems.length > 0 ? function() { }, (allMidiItems.length > 0 ? function() {
var seenTracks = {}; var seenTracks = {};
var els = []; var els = [];
@@ -6141,7 +6135,7 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
var track = (activeTracks || []).find(function(t) { return t.id === m._trackId; }); var track = (activeTracks || []).find(function(t) { return t.id === m._trackId; });
var isActive = m._trackId === st.trackId && m.id === st.target_id; var isActive = m._trackId === st.trackId && m.id === st.target_id;
var isPlayOn = activePlayTrackIds === null || activePlayTrackIds.has(m._trackId); var isPlayOn = activePlayTrackIds === null || activePlayTrackIds.has(m._trackId);
els.push(React.createElement("div", { els.push(React.createElement("button", {
key: m._trackId, key: m._trackId,
onClick: function() { onClick: function() {
if (isActive) return; if (isActive) return;
@@ -6152,19 +6146,17 @@ const beatSec = 60.0 / (parseInt(bpm) || 120);
return s.size === 0 ? null : s; return s.size === 0 ? null : s;
}); });
}, },
className: "flex items-center justify-center h-[18px] border-b border-zinc-900 cursor-pointer select-none " + (isActive ? 'bg-yellow-600 text-black font-bold' : (isPlayOn ? 'bg-purple-700 text-white font-semibold' : 'bg-zinc-800 text-zinc-500 hover:bg-zinc-700')) className: "w-full flex items-center justify-center h-[18px] border-b border-zinc-900 cursor-pointer outline-none " + (isActive ? 'bg-yellow-600 text-black font-bold border-l-2 border-l-yellow-300' : (isPlayOn ? 'bg-purple-700 text-white font-semibold border-l-2 border-l-purple-400' : 'bg-zinc-800 text-zinc-500 hover:bg-zinc-700 border-l-2 border-l-transparent'))
}, React.createElement("span", { }, React.createElement("span", {
className: "text-[12px] font-sans truncate px-1", className: "text-[12px] font-sans truncate px-1",
title: track ? track.name : m._trackName title: track ? track.name : m._trackName
}, track ? track.name : m._trackName))); }, track ? track.name : m._trackName)));
}); });
return els; return els;
}() : null))), React.createElement("div", { }() : null)), React.createElement("div", {
className: "w-[120px] shrink-0" className: "w-[60px] shrink-0 flex flex-col border-r border-zinc-900 overflow-y-auto",
}), React.createElement("div", {
ref: keybedRef, ref: keybedRef,
onScroll: handleKeybedScroll, onScroll: handleKeybedScroll,
className: "w-[60px] overflow-y-auto flex flex-col border-r border-zinc-900 shrink-0",
style: { style: {
scrollbarWidth: 'none', scrollbarWidth: 'none',
msOverflowStyle: 'none' msOverflowStyle: 'none'
@@ -10421,6 +10413,7 @@ const App = () => {
var ghostTrack = allTracks.find(function(t) { return t.id === layer.trackId; }); var ghostTrack = allTracks.find(function(t) { return t.id === layer.trackId; });
var ghostProg = layer.instrumentProgram !== undefined ? layer.instrumentProgram : (ghostTrack ? ghostTrack.instrumentProgram : undefined); var ghostProg = layer.instrumentProgram !== undefined ? layer.instrumentProgram : (ghostTrack ? ghostTrack.instrumentProgram : undefined);
var ghostSynth = layer.synthEngine || (ghostTrack ? ghostTrack.synth_engine : undefined); var ghostSynth = layer.synthEngine || (ghostTrack ? ghostTrack.synth_engine : undefined);
if (ghostProg === undefined && !ghostSynth) return; // skip tracks with no instrument
var ghostDest = getOrCreateTrackNode(ghostTrack, context); var ghostDest = getOrCreateTrackNode(ghostTrack, context);
var ghostCh = 0; var ghostCh = 0;
for (var i = 0; i < allTracks.length; i++) { if (allTracks[i].id === layer.trackId) { ghostCh = i >= 9 ? i + 1 : i; if (ghostCh >= 16) ghostCh = 0; break; } } for (var i = 0; i < allTracks.length; i++) { if (allTracks[i].id === layer.trackId) { ghostCh = i >= 9 ? i + 1 : i; if (ghostCh >= 16) ghostCh = 0; break; } }
File diff suppressed because one or more lines are too long