fix: 메뉴 드래그 시각적 피드백 및 순서변경 버그 수정
- forceFallback: true 추가 (네이티브 드래그 → 자체 구현) → mousemove 이벤트 정상 발생, 인디케이터/하이라이트 작동 - 드래그 중 텍스트 선택 방지 (body.is-dragging + user-select: none) - 순서변경(reorder) 시 원래 부모 유지 (계층 변경 버그 수정) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -122,6 +122,38 @@ class="bg-white rounded-lg shadow-sm overflow-hidden">
|
||||
z-index: 100;
|
||||
transition: width 0.15s, left 0.15s;
|
||||
}
|
||||
|
||||
/* SortableJS fallback 모드 스타일 (forceFallback: true) */
|
||||
.sortable-fallback {
|
||||
opacity: 0.9;
|
||||
background: white !important;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
|
||||
border-radius: 4px;
|
||||
z-index: 9998 !important;
|
||||
}
|
||||
|
||||
/* 드래그 중 텍스트 선택 방지 */
|
||||
.sortable-drag, .sortable-chosen, .sortable-ghost {
|
||||
user-select: none !important;
|
||||
-webkit-user-select: none !important;
|
||||
}
|
||||
|
||||
/* 드래그 핸들 영역 텍스트 선택 방지 */
|
||||
.drag-handle {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
/* 드래그 중 전체 페이지 텍스트 선택 방지 */
|
||||
body.is-dragging {
|
||||
user-select: none !important;
|
||||
-webkit-user-select: none !important;
|
||||
cursor: grabbing !important;
|
||||
}
|
||||
body.is-dragging * {
|
||||
user-select: none !important;
|
||||
-webkit-user-select: none !important;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
||||
@@ -268,9 +300,13 @@ function onDragMove(e) {
|
||||
}
|
||||
|
||||
// SortableJS 초기화 - 노션 스타일 인덴트
|
||||
// forceFallback: true → 네이티브 드래그 대신 자체 구현 사용 (mousemove 이벤트 정상 발생)
|
||||
tbody.sortableInstance = new Sortable(tbody, {
|
||||
handle: '.drag-handle',
|
||||
animation: 150,
|
||||
forceFallback: true, // 브라우저 네이티브 드래그 비활성화 → mousemove 정상 작동
|
||||
fallbackClass: 'sortable-fallback',
|
||||
fallbackOnBody: true,
|
||||
ghostClass: 'bg-blue-50',
|
||||
chosenClass: 'bg-blue-100',
|
||||
dragClass: 'shadow-lg',
|
||||
@@ -281,6 +317,9 @@ function onDragMove(e) {
|
||||
currentDragItem = evt.item;
|
||||
dragIndicator = createDragIndicator();
|
||||
|
||||
// 드래그 중 텍스트 선택 방지
|
||||
document.body.classList.add('is-dragging');
|
||||
|
||||
// 마우스 이동 이벤트 리스너 추가
|
||||
document.addEventListener('mousemove', onDragMove);
|
||||
document.addEventListener('touchmove', onDragMove);
|
||||
@@ -297,6 +336,9 @@ function onDragMove(e) {
|
||||
removeDragIndicator();
|
||||
currentDragItem = null;
|
||||
|
||||
// 드래그 중 텍스트 선택 방지 해제
|
||||
document.body.classList.remove('is-dragging');
|
||||
|
||||
const movedItem = evt.item;
|
||||
const menuId = parseInt(movedItem.dataset.menuId);
|
||||
const currentDepth = parseInt(movedItem.dataset.depth) || 0;
|
||||
@@ -352,17 +394,10 @@ function onDragMove(e) {
|
||||
}
|
||||
// 수평 이동 없음 → 같은 레벨에서 순서만 변경
|
||||
else {
|
||||
// 위 행과 같은 부모로 (기존 동작)
|
||||
if (newIndex > 0) {
|
||||
const prevRow = rows[newIndex - 1];
|
||||
if (prevRow) {
|
||||
const prevParentIdRaw = prevRow.dataset.parentId;
|
||||
newParentId = prevParentIdRaw === '' ? null : (prevParentIdRaw ? parseInt(prevParentIdRaw) : null);
|
||||
}
|
||||
} else {
|
||||
newParentId = null;
|
||||
}
|
||||
console.log('↔ REORDER: 위 행과 같은 레벨로, newParentId:', newParentId);
|
||||
// 원래 부모 유지 (순서만 변경, 계층 변경 안함)
|
||||
newParentId = oldPid;
|
||||
action = 'reorder';
|
||||
console.log('↔ REORDER: 같은 부모 유지, parentId:', newParentId);
|
||||
}
|
||||
|
||||
const parentChanged = oldPid !== newParentId;
|
||||
|
||||
Reference in New Issue
Block a user