Skip to content

feat: 블록 삭제 — 쓰레기통 드래그 삭제 (#32) - #33

Merged
wook10 merged 2 commits into
mainfrom
feature/32-block-delete
Sep 16, 2026
Merged

wook10 merged 2 commits into
mainfrom
feature/32-block-delete

Conversation

@wook10

@wook10 wook10 commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

개요

Closes #32

Mission & Block 기능명세서에 새로 추가된 블록 삭제 항목 구현 (페이지 필요: NO → 기존 블록 워크스페이스 화면에 통합).

기명서 대조표

기명서 (동작·정책) 구현
블록 편집 화면 오른쪽 구석에 쓰레기통을 고정 표시 BlockWorkspace.tsx 캔버스 우측 하단(right-6 bottom-6)에 고정
쓰레기통 시각 영역 바깥 30px까지를 삭제 감지 영역으로 사용 TRASH_HIT_MARGIN_PX = 30 + isNearRect
드래그 중인 블록이 감지 영역 안으로 들어오면 쓰레기통과 블록을 삭제 예정 상태로 강조 overTrash 상태 → 쓰레기통 확대(scale-110) + 열림 이미지(몸통·뚜껑) 전환
감지 영역 안에서 드롭하면 드래그 중인 블록을 삭제 finish()에서 overTrash면 deleteCarried 호출 후 종료 (스냅/자유배치보다 우선)
연결된 블록 묶음을 드래그한 경우 함께 이동 중인 하위 연결 블록도 같이 삭제 deleteCarried가 carriedBlocks로 잡은 체인 전체를 detachCarried로 제거
드롭 전 감지 영역을 벗어나면 삭제 예정 상태를 즉시 해제 handleMove마다 overTrash 재계산 (pointermove 기반)
감지 영역 밖 드롭 시 삭제하지 않음 / 지나가기만 하면 삭제하지 않음 overTrash는 드롭 순간 값만 사용, false면 기존 스냅/자유배치 로직으로 진행

구현

  • model/blockProgram.ts: deleteCarried — 기존 detachCarried(스냅/자유배치에서 이미 쓰던 "체인을 원래 자리에서 제거" 헬퍼)를 재사용
  • lib/blockDrag.ts: isNearRect — 사각형 시각 영역 + margin 판정 순수 함수
  • lib/useBlockDrag.tsx: registerTrash/trashRef 배선, DragState.overTrash, finish()에서 스냅보다 먼저 검사
  • ui/BlockWorkspace.tsx: 쓰레기통 아이콘 (닫힘 1장 / 열림 몸통+뚜껑 2파츠, Figma 에셋 다운로드·커밋)

테스트

  • blockProgram.test.ts: deleteCarried 4건 (체인 삭제, start 삭제 불가, floating 그룹 전체/부분 삭제)
  • blockDrag.test.ts: isNearRect 3건 (영역 안/margin 안/margin 밖)
  • blockDnd.test.tsx: 통합 3건 (단일 블록 삭제, 연결 묶음 삭제, 감지 영역 밖 미삭제)
  • 전체 84/84 통과, typecheck/lint/build/format:check 클린
  • CDP로 닫힘/열림 상태 렌더 및 실제 드래그→삭제 동작 시각 확인

참고

Figma 좌표계가 이 파일 특성상 절대좌표로 정확히 역산되지 않아(배경 사각형과 기존 구현 요소 간 불일치), 쓰레기통 위치는 코너 기준 여백(right-6 bottom-6)으로 배치 후 CDP로 실제 렌더 위치를 검증했습니다.

🤖 Generated with Claude Code

블록 편집 화면 오른쪽 구석에 쓰레기통을 고정 표시하고, 시각 영역 바깥
30px까지를 삭제 감지 영역으로 사용한다. 감지 영역 안에서 드롭하면 드래그
중인 블록(연결된 하위 블록 포함)을 삭제하고, 감지 영역 밖에서 드롭하거나
지나가기만 하면 삭제하지 않는다.

- deleteCarried: 기존 detachCarried를 재사용해 잡은 체인을 원래 자리에서
  통째로 제거
- isNearRect: 사각형 시각 영역 + margin 안 포함 여부 판정
- useBlockDrag: overTrash 상태 추가, finish()에서 스냅보다 우선 검사
- BlockWorkspace: 쓰레기통 아이콘(닫힘/열림 2파츠) 추가, 드래그 중 강조

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@inryeok-bot inryeok-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 결과

변경된 11개 파일을 검토했으며, 수정이 필요한 문제 1개를 발견했습니다.

심각도 개수
Critical 0
High 0
Medium 1
Low 0

주요 내용

  • MEDIUM · DATA_INTEGRITY — 마지막 이동 위치로 삭제 여부를 결정합니다

검토한 head: 131fd0bf11b3


const latestProgram = programRef.current;
// 삭제 감지 영역은 스냅보다 먼저 확인한다 — 쓰레기통 위에서 놓았는데 스냅되면 안 된다.
if (cur.overTrash) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 MEDIUM · DATA_INTEGRITY

마지막 이동 위치로 삭제 여부를 결정합니다

드롭 시점에는 pointerup의 좌표를 다시 검사하지 않고, 마지막 pointermove에서 계산한 cur.overTrash를 사용합니다. 마지막 이동과 버튼 해제 사이에 포인터 좌표가 달라지거나 마지막 이동 이벤트가 병합·누락되면 실제로 쓰레기통 밖에서 놓아도 블록이 영구 삭제될 수 있고, 반대로 안에서 놓아도 삭제되지 않을 수 있습니다.

pointerup 이벤트의 clientX/clientY와 해당 시점의 trashRef.current.getBoundingClientRect()로 삭제 영역을 다시 계산한 뒤 deleteCarried를 호출해야 합니다.

inryeok-bot: finish() 가 마지막 pointermove 시점의 overTrash 를 그대로
써서, move 이벤트가 씹히면 실제 드롭 위치와 다르게 (되돌릴 수 없는) 삭제
여부가 결정될 수 있었다. pointerup 이벤트의 좌표와 그 시점의 쓰레기통
rect로 다시 판정하도록 수정.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 블록 삭제 — 쓰레기통 드래그

1 participant