From 34e2cd9775ee639e96ad13e97c1fe6e1d34cf0f3 Mon Sep 17 00:00:00 2001 From: jisangs Date: Fri, 15 May 2026 18:47:43 +0900 Subject: [PATCH] =?UTF-8?q?Shift=20+=20=EB=93=9C=EB=9E=98=EA=B7=B8?= =?UTF-8?q?=EC=8B=9C=20=ED=8F=AC=ED=95=A8=EB=90=98=EB=8A=94=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=EB=93=A4=EC=9D=98=20=EC=84=A0=ED=83=9D=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EA=B0=80=20=ED=86=A0=EA=B8=80=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderer/handlers/selection.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/renderer/handlers/selection.js b/src/renderer/handlers/selection.js index 3bf03bb..d1cafb2 100644 --- a/src/renderer/handlers/selection.js +++ b/src/renderer/handlers/selection.js @@ -8,6 +8,7 @@ let _rafPending = false; let _lastMoveEvent = null; let lastSelectedIdx = null; +let _rbStartSelection = new Set(); // 러버밴드 시작 시점의 선택 스냅샷 export function resetAnchor() { lastSelectedIdx = null; @@ -95,8 +96,10 @@ function _onStart(e) { }); const preserve = e.shiftKey || e.ctrlKey || e.metaKey; + _rbStartSelection = new Set(_state.selectedIdxs); // 토글 기준점 스냅샷 if (!preserve) { _state.selectedIdxs.clear(); + _rbStartSelection.clear(); lastSelectedIdx = null; _cb.refreshCardSelection(); } @@ -127,12 +130,20 @@ function _processMove() { }); const sel = { left, top, right: left + width, bottom: top + height }; - const preserve = e.shiftKey || e.ctrlKey || e.metaKey; + const shiftToggle = e.shiftKey && !e.ctrlKey && !e.metaKey; + const preserve = e.ctrlKey || e.metaKey; Array.from(_grid.children).forEach((card, i) => { const r = card.getBoundingClientRect(); const overlaps = !(r.right < sel.left || r.left > sel.right || r.bottom < sel.top || r.top > sel.bottom); - if (overlaps) { + if (shiftToggle) { + // 러버밴드 안: 시작 시점 기준으로 토글 (밖: 시작 시점 상태 복원) + if (overlaps ? !_rbStartSelection.has(i) : _rbStartSelection.has(i)) { + _state.selectedIdxs.add(i); + } else { + _state.selectedIdxs.delete(i); + } + } else if (overlaps) { _state.selectedIdxs.add(i); } else if (!preserve) { _state.selectedIdxs.delete(i);