diff --git a/components/admin/AdminMarkdownEditor.vue b/components/admin/AdminMarkdownEditor.vue index bdaf34e..7a14d16 100644 --- a/components/admin/AdminMarkdownEditor.vue +++ b/components/admin/AdminMarkdownEditor.vue @@ -157,6 +157,10 @@ const liveSlashSuppressedLines = ref(new Set()) /** 키보드로 슬래시 메뉴를 탐색 중일 때 mouseenter 하이라이트 무시 */ const liveSlashKeyboardNav = ref(false) let liveSlashKeyboardNavTimer = null +/** @type {HTMLElement|null} 슬래시 메뉴 위치 갱신을 위해 구독한 미리보기 스크롤 영역 */ +let liveSlashPreviewScrollElement = null +/** @type {HTMLElement|null} 슬래시 메뉴 위치 갱신을 위해 구독한 작성 textarea */ +let liveSlashTextareaScrollElement = null const liveSlashVisible = computed(() => liveSlashSourceLine.value !== null) @@ -1512,6 +1516,7 @@ onMounted(() => { onBeforeUnmount(() => { window.clearTimeout(blockPanelFocusTimer) window.clearTimeout(liveSlashKeyboardNavTimer) + removeLiveSlashRepositionListeners() document.removeEventListener('selectionchange', onSelectionChange) document.removeEventListener('keydown', onDocumentKeydown, true) document.removeEventListener('pointerdown', onDocumentPointerDown, true) @@ -2427,6 +2432,49 @@ const updateLiveSlashMenuPosition = () => { }) } +/** + * 슬래시 메뉴 위치 재계산 이벤트를 실행한다. + * @returns {void} + */ +const repositionLiveSlashMenu = () => { + updateLiveSlashMenuPosition() +} + +/** + * 슬래시 메뉴 위치 재계산 이벤트 리스너를 제거한다. + * @returns {void} + */ +const removeLiveSlashRepositionListeners = () => { + if (!import.meta.client) { + return + } + + window.removeEventListener('scroll', repositionLiveSlashMenu, true) + window.removeEventListener('resize', repositionLiveSlashMenu) + liveSlashPreviewScrollElement?.removeEventListener('scroll', repositionLiveSlashMenu) + liveSlashTextareaScrollElement?.removeEventListener('scroll', repositionLiveSlashMenu) + liveSlashPreviewScrollElement = null + liveSlashTextareaScrollElement = null +} + +/** + * 슬래시 메뉴 위치 재계산 이벤트 리스너를 등록한다. + * @returns {void} + */ +const addLiveSlashRepositionListeners = () => { + if (!import.meta.client) { + return + } + + removeLiveSlashRepositionListeners() + liveSlashPreviewScrollElement = getPreviewSurfaceElement() + liveSlashTextareaScrollElement = getWriteTextareaElement() + window.addEventListener('scroll', repositionLiveSlashMenu, true) + window.addEventListener('resize', repositionLiveSlashMenu) + liveSlashPreviewScrollElement?.addEventListener('scroll', repositionLiveSlashMenu) + liveSlashTextareaScrollElement?.addEventListener('scroll', repositionLiveSlashMenu) +} + /** * 키보드로 선택한 슬래시 메뉴 항목이 보이도록 스크롤한다. * @returns {void} @@ -2528,22 +2576,14 @@ watch(liveSlashVisible, (visible) => { return } - const onReposition = () => updateLiveSlashMenuPosition() - if (visible) { - window.addEventListener('scroll', onReposition, true) - window.addEventListener('resize', onReposition) - getPreviewSurfaceElement()?.addEventListener('scroll', onReposition) - getWriteTextareaElement()?.addEventListener('scroll', onReposition) + addLiveSlashRepositionListeners() updateLiveSlashMenuPosition() scrollLiveSlashHighlightedIntoView() return } - window.removeEventListener('scroll', onReposition, true) - window.removeEventListener('resize', onReposition) - getPreviewSurfaceElement()?.removeEventListener('scroll', onReposition) - getWriteTextareaElement()?.removeEventListener('scroll', onReposition) + removeLiveSlashRepositionListeners() }) /** diff --git a/docs/update.md b/docs/update.md index 7ae28ef..78f7bf9 100644 --- a/docs/update.md +++ b/docs/update.md @@ -1,5 +1,10 @@ # 업데이트 이력 +## v1.11.84 + +- 관리자 Markdown 에디터의 슬래시 메뉴 재배치 이벤트 리스너를 안정적인 참조로 정리. +- 슬래시 메뉴 닫힘·컴포넌트 해제 시 window/편집 표면 scroll·resize 리스너가 제거되도록 보강. + ## v1.11.83 - 관리자 Markdown 에디터의 슬래시 메뉴 뷰포트 위치 보정 계산을 `markdown-slash-menu-position` helper로 분리. diff --git a/package-lock.json b/package-lock.json index 9f27624..31e401e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "sori.studio", - "version": "1.11.83", + "version": "1.11.84", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "sori.studio", - "version": "1.11.83", + "version": "1.11.84", "hasInstallScript": true, "dependencies": { "@nuxtjs/tailwindcss": "^6.14.0", diff --git a/package.json b/package.json index 628cf94..1c65c5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sori.studio", - "version": "1.11.83", + "version": "1.11.84", "private": true, "type": "module", "imports": {