글쓰기 스크롤과 블록 드롭 피드백 보정
This commit is contained in:
@@ -13,6 +13,8 @@ const blockRefs = ref([])
|
||||
const activeBlockId = ref('')
|
||||
const selectedBlockId = ref('')
|
||||
const draggingBlockId = ref('')
|
||||
const dragTargetIndex = ref(-1)
|
||||
const dragTargetPosition = ref('')
|
||||
const slashQuery = ref('')
|
||||
const slashMenuDirection = ref('down')
|
||||
const highlightedCommandIndex = ref(0)
|
||||
@@ -24,6 +26,7 @@ const isMediaPickerOpen = ref(false)
|
||||
const isLoadingMedia = ref(false)
|
||||
const isComposingText = ref(false)
|
||||
const isNormalizingTrailingBlock = ref(false)
|
||||
const pendingSoftLineBreakIndex = ref(-1)
|
||||
let blockIdSeed = 0
|
||||
|
||||
const imageWidthOptions = [
|
||||
@@ -684,10 +687,19 @@ const finishTextComposition = (event, index) => {
|
||||
const block = syncTextBlockFromDom(index)
|
||||
|
||||
if (!block) {
|
||||
pendingSoftLineBreakIndex.value = -1
|
||||
return
|
||||
}
|
||||
|
||||
applyMarkdownShortcut(block, index)
|
||||
|
||||
if (pendingSoftLineBreakIndex.value === index && isTextBlock(block) && block.type !== 'code') {
|
||||
pendingSoftLineBreakIndex.value = -1
|
||||
insertSoftLineBreak(index)
|
||||
return
|
||||
}
|
||||
|
||||
pendingSoftLineBreakIndex.value = -1
|
||||
emitContent()
|
||||
}, 0)
|
||||
})
|
||||
@@ -1057,6 +1069,11 @@ const handleEnter = (event, index) => {
|
||||
|
||||
if (isComposingText.value || event.isComposing || event.keyCode === 229) {
|
||||
event.preventDefault()
|
||||
|
||||
if (event.shiftKey && isTextBlock(currentBlock) && currentBlock.type !== 'code') {
|
||||
pendingSoftLineBreakIndex.value = index
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1195,10 +1212,30 @@ const deleteSelectedBlock = (event, index) => {
|
||||
const startBlockDrag = (event, block) => {
|
||||
draggingBlockId.value = block.id
|
||||
selectedBlockId.value = block.id
|
||||
dragTargetIndex.value = -1
|
||||
dragTargetPosition.value = ''
|
||||
event.dataTransfer.effectAllowed = 'move'
|
||||
event.dataTransfer.setData('text/plain', block.id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 블록 드래그 중 드롭 위치 표시 갱신
|
||||
* @param {DragEvent} event - 드래그 이벤트
|
||||
* @param {number} targetIndex - 드래그 중인 대상 인덱스
|
||||
* @returns {void}
|
||||
*/
|
||||
const updateBlockDropTarget = (event, targetIndex) => {
|
||||
if (!draggingBlockId.value) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
event.dataTransfer.dropEffect = 'move'
|
||||
const rect = event.currentTarget.getBoundingClientRect()
|
||||
dragTargetIndex.value = targetIndex
|
||||
dragTargetPosition.value = event.clientY < rect.top + rect.height / 2 ? 'before' : 'after'
|
||||
}
|
||||
|
||||
/**
|
||||
* 블록 드롭 이동 처리
|
||||
* @param {DragEvent} event - 드롭 이벤트
|
||||
@@ -1206,18 +1243,25 @@ const startBlockDrag = (event, block) => {
|
||||
* @returns {void}
|
||||
*/
|
||||
const dropBlock = (event, targetIndex) => {
|
||||
event.preventDefault()
|
||||
const draggedId = event.dataTransfer.getData('text/plain') || draggingBlockId.value
|
||||
const sourceIndex = getBlockIndex(draggedId)
|
||||
const targetPosition = dragTargetIndex.value === targetIndex ? dragTargetPosition.value : 'after'
|
||||
const insertionIndex = targetPosition === 'after' ? targetIndex + 1 : targetIndex
|
||||
|
||||
if (sourceIndex < 0 || targetIndex < 0 || sourceIndex === targetIndex) {
|
||||
if (sourceIndex < 0 || targetIndex < 0) {
|
||||
draggingBlockId.value = ''
|
||||
dragTargetIndex.value = -1
|
||||
dragTargetPosition.value = ''
|
||||
return
|
||||
}
|
||||
|
||||
const [draggedBlock] = editorBlocks.value.splice(sourceIndex, 1)
|
||||
const nextTargetIndex = sourceIndex < targetIndex ? targetIndex - 1 : targetIndex
|
||||
const nextTargetIndex = sourceIndex < insertionIndex ? insertionIndex - 1 : insertionIndex
|
||||
editorBlocks.value.splice(nextTargetIndex, 0, draggedBlock)
|
||||
draggingBlockId.value = ''
|
||||
dragTargetIndex.value = -1
|
||||
dragTargetPosition.value = ''
|
||||
selectedBlockId.value = draggedBlock.id
|
||||
normalizeTrailingTextBlock()
|
||||
emitContent()
|
||||
@@ -1229,6 +1273,8 @@ const dropBlock = (event, targetIndex) => {
|
||||
*/
|
||||
const finishBlockDrag = () => {
|
||||
draggingBlockId.value = ''
|
||||
dragTargetIndex.value = -1
|
||||
dragTargetPosition.value = ''
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1302,11 +1348,13 @@ defineExpose({
|
||||
:class="{
|
||||
'admin-block-editor__row--selected': selectedBlockId === block.id,
|
||||
'admin-block-editor__row--dragging opacity-50': draggingBlockId === block.id,
|
||||
'admin-block-editor__row--drop-before': dragTargetIndex === index && dragTargetPosition === 'before',
|
||||
'admin-block-editor__row--drop-after': dragTargetIndex === index && dragTargetPosition === 'after',
|
||||
'admin-block-editor__row--text': isTextBlock(block),
|
||||
'admin-block-editor__row--structure': !isTextBlock(block)
|
||||
}"
|
||||
:data-editor-block-id="block.id"
|
||||
@dragover.prevent
|
||||
@dragover="updateBlockDropTarget($event, index)"
|
||||
@drop="dropBlock($event, index)"
|
||||
>
|
||||
<button
|
||||
@@ -1574,6 +1622,24 @@ defineExpose({
|
||||
transform 160ms ease;
|
||||
}
|
||||
|
||||
.admin-block-editor__row::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 20;
|
||||
height: 3px;
|
||||
border-radius: 999px;
|
||||
background: #2eb6ea;
|
||||
box-shadow: 0 0 0 1px rgba(46, 182, 234, 0.18);
|
||||
content: "";
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: scaleX(0.98);
|
||||
transition:
|
||||
opacity 120ms ease,
|
||||
transform 120ms ease;
|
||||
}
|
||||
|
||||
.admin-block-editor__row:hover::before,
|
||||
.admin-block-editor__row--selected::before {
|
||||
background: #eff1f2;
|
||||
@@ -1581,6 +1647,18 @@ defineExpose({
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.admin-block-editor__row--drop-before::after {
|
||||
top: -18px;
|
||||
opacity: 1;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.admin-block-editor__row--drop-after::after {
|
||||
bottom: -18px;
|
||||
opacity: 1;
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.admin-block-editor__handle {
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user