에디터 모드 전환 포커스 분리
This commit is contained in:
@@ -68,6 +68,7 @@ import { getTextareaCaretCoordinates } from '../../lib/textarea-caret-coordinate
|
||||
import { useAdminMarkdownSlashMenu } from '../../composables/useAdminMarkdownSlashMenu.js'
|
||||
import { useAdminMarkdownHistory } from '../../composables/useAdminMarkdownHistory.js'
|
||||
import { useAdminMarkdownMediaPicker } from '../../composables/useAdminMarkdownMediaPicker.js'
|
||||
import { useAdminMarkdownFocusBridge } from '../../composables/useAdminMarkdownFocusBridge.js'
|
||||
import {
|
||||
buildDefaultUploadSizeLimits,
|
||||
DEFAULT_UPLOAD_MAX_FILE_COUNT,
|
||||
@@ -121,10 +122,6 @@ const activeLogicalLineIndex = ref(0)
|
||||
const writeModeContextValue = ref(null)
|
||||
/** textarea 자동 줄바꿈을 반영한 논리 줄별 표시 높이(px) */
|
||||
const gutterLineHeights = ref([])
|
||||
/** 라이브 모드에서 소스 모드로 돌아올 때 복원할 줄(0-based) */
|
||||
const pendingWriteFocusLine = ref(null)
|
||||
/** 소스 모드에서 라이브 모드로 넘어갈 때 복원할 줄·오프셋 */
|
||||
const pendingPreviewFocus = ref(null)
|
||||
const lastSelectionState = ref({
|
||||
start: 0,
|
||||
end: 0
|
||||
@@ -667,26 +664,6 @@ const resolvePreviewFocusPosition = (line, offset) => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 textarea 선택 위치를 라이브 모드 포커스 대상으로 저장한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const rememberWritePositionForPreview = () => {
|
||||
const textarea = getWriteTextareaElement()
|
||||
const value = markdownValue.value ?? ''
|
||||
const start = textarea
|
||||
? Math.min(textarea.selectionStart, value.length)
|
||||
: Math.min(lastSelectionState.value.start, value.length)
|
||||
const line = getLineIndexAtOffset(start)
|
||||
const offset = Math.max(0, start - getLineStartOffset(line))
|
||||
const focusPosition = resolvePreviewFocusPosition(line, offset)
|
||||
|
||||
pendingPreviewFocus.value = {
|
||||
line: focusPosition.line,
|
||||
offset: focusPosition.offset
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* textarea와 동일한 폭·폰트로 각 논리 줄의 실제 wrap 높이를 측정한다.
|
||||
* @returns {void}
|
||||
@@ -1069,37 +1046,6 @@ watch(markdownValue, (nextValue, previousValue) => {
|
||||
recordEditorHistory(previousValue)
|
||||
})
|
||||
|
||||
watch(activeMode, (mode) => {
|
||||
if (mode === 'write') {
|
||||
nextTick(() => {
|
||||
syncTextareaHeight()
|
||||
const focusLine = pendingWriteFocusLine.value
|
||||
pendingWriteFocusLine.value = null
|
||||
|
||||
if (typeof focusLine === 'number') {
|
||||
focusTextareaAtLine(focusLine)
|
||||
} else {
|
||||
restoreTextareaFocus()
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
const previewFocus = pendingPreviewFocus.value
|
||||
pendingPreviewFocus.value = null
|
||||
|
||||
if (!previewFocus) {
|
||||
scrollPreviewToTop()
|
||||
return
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
focusPreviewEditableAtLine(previewFocus.line, 0, 'auto', previewFocus.offset, 'center')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* 라이브 미리보기 스크롤을 맨 위로 맞춘다.
|
||||
* @returns {void}
|
||||
@@ -1144,13 +1090,26 @@ const getCurrentPreviewSourceLine = () => {
|
||||
return candidates[0]?.line ?? null
|
||||
}
|
||||
|
||||
/**
|
||||
* 라이브 모드의 현재 위치를 소스 모드 복원 대상으로 저장한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const rememberPreviewPosition = () => {
|
||||
pendingWriteFocusLine.value = getCurrentPreviewSourceLine() ?? activeLogicalLineIndex.value
|
||||
}
|
||||
const {
|
||||
rememberWritePositionForPreview,
|
||||
rememberPreviewPosition,
|
||||
requestPreviewFocus
|
||||
} = useAdminMarkdownFocusBridge({
|
||||
activeMode,
|
||||
value: markdownValue,
|
||||
lastSelectionState,
|
||||
activeLogicalLineIndex,
|
||||
getWriteTextareaElement,
|
||||
getLineIndexAtOffset,
|
||||
getLineStartOffset,
|
||||
resolvePreviewFocusPosition,
|
||||
getCurrentPreviewSourceLine,
|
||||
syncTextareaHeight,
|
||||
focusTextareaAtLine,
|
||||
restoreTextareaFocus,
|
||||
scrollPreviewToTop,
|
||||
focusPreviewEditableAtLine
|
||||
})
|
||||
|
||||
/**
|
||||
* 본문 작성 시작 시 포커스할 첫 줄 인덱스를 반환한다.
|
||||
@@ -2799,10 +2758,10 @@ const updateActiveInlineColor = (color) => {
|
||||
lines.splice(context.sourceLine, 1, `${line.slice(0, absoluteStart)}${replacement}${line.slice(absoluteEnd)}`)
|
||||
markdownValue.value = lines.join('\n')
|
||||
inlineColorSelectionContext.value = null
|
||||
pendingPreviewFocus.value = {
|
||||
requestPreviewFocus({
|
||||
line: context.sourceLine,
|
||||
offset: nextVisibleOffset
|
||||
}
|
||||
})
|
||||
nextTick(() => {
|
||||
focusPreviewEditableAtLine(
|
||||
context.sourceLine,
|
||||
|
||||
Reference in New Issue
Block a user