관리자 블록 에디터 키보드 흐름 보정

This commit is contained in:
2026-05-01 23:04:50 +09:00
parent c2b3e3a204
commit 3afef9d0d2
7 changed files with 73 additions and 10 deletions

View File

@@ -13,6 +13,7 @@ const blockRefs = ref([])
const activeBlockId = ref('')
const slashQuery = ref('')
const slashMenuDirection = ref('down')
const highlightedCommandIndex = ref(0)
const isApplyingExternalValue = ref(false)
let blockIdSeed = 0
@@ -368,6 +369,8 @@ const updateSlashQuery = (block) => {
slashQuery.value = block.text.startsWith('/')
? block.text.slice(1).trim().toLowerCase()
: ''
highlightedCommandIndex.value = 0
}
const activeBlockIndex = computed(() => editorBlocks.value.findIndex((block) => block.id === activeBlockId.value))
@@ -390,6 +393,8 @@ const visibleCommands = computed(() => {
].some((keyword) => keyword.toLowerCase().includes(slashQuery.value)))
})
const highlightedCommand = computed(() => visibleCommands.value[highlightedCommandIndex.value])
/**
* 슬래시 메뉴 명령 적용
* @param {Object} command - 블록 명령
@@ -425,6 +430,36 @@ const applyCommand = (command) => {
focusBlock(index)
}
/**
* 슬래시 메뉴 선택을 아래로 이동
* @param {KeyboardEvent} event - 키보드 이벤트
* @returns {void}
*/
const highlightNextCommand = (event) => {
if (!visibleCommands.value.length) {
return
}
event.preventDefault()
highlightedCommandIndex.value = (highlightedCommandIndex.value + 1) % visibleCommands.value.length
}
/**
* 슬래시 메뉴 선택을 위로 이동
* @param {KeyboardEvent} event - 키보드 이벤트
* @returns {void}
*/
const highlightPreviousCommand = (event) => {
if (!visibleCommands.value.length) {
return
}
event.preventDefault()
highlightedCommandIndex.value = highlightedCommandIndex.value === 0
? visibleCommands.value.length - 1
: highlightedCommandIndex.value - 1
}
/**
* 엔터 키로 다음 블록 생성
* @param {KeyboardEvent} event - 키보드 이벤트
@@ -434,16 +469,18 @@ const applyCommand = (command) => {
const handleEnter = (event, index) => {
const currentBlock = editorBlocks.value[index]
if (visibleCommands.value.length && currentBlock.text.startsWith('/')) {
event.preventDefault()
applyCommand(highlightedCommand.value || visibleCommands.value[0])
return
}
if (currentBlock.type === 'code' && !event.shiftKey) {
return
}
event.preventDefault()
if (!currentBlock.text.trim() && currentBlock.type === 'paragraph') {
return
}
if (currentBlock.type === 'divider') {
editorBlocks.value.splice(index + 1, 0, createEditorBlock())
emitContent()
@@ -550,6 +587,8 @@ watch(editorBlocks, () => {
@focus="activateBlock(block)"
@input="updateBlockText($event, index)"
@keydown.enter="handleEnter($event, index)"
@keydown.down="highlightNextCommand"
@keydown.up="highlightPreviousCommand"
@keydown.backspace="handleBackspace($event, index)"
/>
@@ -569,9 +608,10 @@ watch(editorBlocks, () => {
:class="slashMenuDirection === 'up' ? 'bottom-full mb-2' : 'top-full mt-2'"
>
<button
v-for="command in visibleCommands"
v-for="(command, commandIndex) in visibleCommands"
:key="`${command.type}-${command.level || 'default'}`"
class="admin-block-editor__slash-item grid w-full gap-0.5 px-4 py-3 text-left hover:bg-surface"
:class="commandIndex === highlightedCommandIndex ? 'bg-surface' : ''"
type="button"
@mousedown.prevent="applyCommand(command)"
>