블록 UX: 삭제/복제 버튼 및 단축키 추가
CI / test (push) Failing after 6m0s
CI / pr_and_merge (push) Has been skipped

This commit is contained in:
2025-11-18 16:28:46 +09:00
parent cf04c6e56c
commit 8494bd64bc
4 changed files with 207 additions and 1 deletions
+59
View File
@@ -67,6 +67,8 @@ export interface EditorState {
moveBlock: (id: string, sectionId: string | null, columnId: string | null) => void;
undo: () => void;
redo: () => void;
removeBlock: (id: string) => void;
duplicateBlock: (id: string) => void;
}
// 간단한 ID 생성기 (추후 uuid 라이브러리로 교체 가능)
@@ -486,6 +488,63 @@ const createEditorState = (set: any, get: any): EditorState => ({
),
}));
},
removeBlock: (id) => {
set((state: EditorState) => {
const current = state.blocks;
const index = current.findIndex((b) => b.id === id);
if (index === -1) {
return state;
}
const nextBlocks = current.filter((b) => b.id !== id);
// 선택 상태는 삭제된 블록의 이전 블록 또는 다음 블록으로 이동한다.
let nextSelected: string | null = null;
if (nextBlocks.length > 0) {
const prevIndex = index - 1;
if (prevIndex >= 0) {
nextSelected = nextBlocks[prevIndex].id;
} else {
// 첫 블록이 삭제된 경우, 새 첫 블록을 선택한다.
nextSelected = nextBlocks[0].id;
}
}
return {
...state,
blocks: nextBlocks,
selectedBlockId: nextSelected,
};
});
},
duplicateBlock: (id) => {
set((state: EditorState) => {
const current = state.blocks;
const index = current.findIndex((b) => b.id === id);
if (index === -1) {
return state;
}
const original = current[index];
const newId = createId();
const cloned: Block = {
...original,
id: newId,
// props 는 얕은 복사로 충분 (현재 props 는 모두 평면 구조)
props: { ...(original.props as any) },
};
const nextBlocks = [...current];
nextBlocks.splice(index + 1, 0, cloned);
return {
...state,
blocks: nextBlocks,
selectedBlockId: newId,
};
});
},
undo: () => {
const { history, blocks } = get();
if (history.length === 0) return;