어나운스 바 설정 확장 v1.5.38
This commit is contained in:
@@ -131,6 +131,10 @@ const markdownValue = computed({
|
||||
/** textarea 포커스·블록 패널 상호작용 */
|
||||
const isTextareaFocused = ref(false)
|
||||
const isBlockPanelEngaged = ref(false)
|
||||
/** 한글 등 IME 조합 입력 중 여부 */
|
||||
const isTextComposing = ref(false)
|
||||
/** 조합 입력 중 패널 닫힘을 방지하기 위한 마지막 블록 컨텍스트 */
|
||||
const lastStableBlockContext = ref(null)
|
||||
let blockPanelFocusTimer = null
|
||||
|
||||
/**
|
||||
@@ -184,12 +188,24 @@ const activeBlockContext = computed(() => resolveActiveBlockContext(
|
||||
/** @deprecated 내부 호환 alias */
|
||||
const activeMediaBlock = activeBlockContext
|
||||
|
||||
/**
|
||||
* IME 조합 중에는 일시적으로 블록 판별이 비어도 직전 패널을 유지한다.
|
||||
* @returns {Object|null} 패널 표시용 블록 컨텍스트
|
||||
*/
|
||||
const visibleBlockContext = computed(() => {
|
||||
if (activeBlockContext.value) {
|
||||
return activeBlockContext.value
|
||||
}
|
||||
|
||||
return isTextComposing.value ? lastStableBlockContext.value : null
|
||||
})
|
||||
|
||||
/**
|
||||
* 블록 설정 패널 표시 여부
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isBlockPanelVisible = computed(() => (activeMode.value === 'write' || isBlockPanelEngaged.value)
|
||||
&& Boolean(activeBlockContext.value)
|
||||
&& Boolean(visibleBlockContext.value)
|
||||
&& (isTextareaFocused.value || isBlockPanelEngaged.value))
|
||||
|
||||
/**
|
||||
@@ -199,11 +215,17 @@ const isBlockPanelVisible = computed(() => (activeMode.value === 'write' || isBl
|
||||
const syncBlockPanelState = () => {
|
||||
emit('block-panel', {
|
||||
open: isBlockPanelVisible.value,
|
||||
panel: activeBlockContext.value
|
||||
panel: visibleBlockContext.value
|
||||
})
|
||||
}
|
||||
|
||||
watch([isBlockPanelVisible, activeBlockContext], syncBlockPanelState, { deep: true })
|
||||
watch(activeBlockContext, (context) => {
|
||||
if (context) {
|
||||
lastStableBlockContext.value = context
|
||||
}
|
||||
}, { deep: true, immediate: true })
|
||||
|
||||
watch([isBlockPanelVisible, visibleBlockContext], syncBlockPanelState, { deep: true })
|
||||
|
||||
/**
|
||||
* 본문의 논리 줄(`\\n` 기준) 개수. 빈 본문은 1줄로 본다.
|
||||
@@ -400,6 +422,28 @@ const handleBlockPanelFocusOut = () => {
|
||||
}, 50)
|
||||
}
|
||||
|
||||
/**
|
||||
* IME 조합 입력 시작 시 패널 컨텍스트를 유지한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const handleTextareaCompositionStart = () => {
|
||||
isTextComposing.value = true
|
||||
|
||||
if (activeBlockContext.value) {
|
||||
lastStableBlockContext.value = activeBlockContext.value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IME 조합 입력 종료 후 실제 커서 줄 기준으로 패널을 다시 동기화한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const handleTextareaCompositionEnd = () => {
|
||||
isTextComposing.value = false
|
||||
refreshCaretLogicalLine()
|
||||
nextTick(syncBlockPanelState)
|
||||
}
|
||||
|
||||
/**
|
||||
* 커서 위치 기준으로 활성 논리 줄 인덱스를 갱신하고 거터 스크롤을 맞춘다.
|
||||
* @returns {void}
|
||||
@@ -2756,6 +2800,8 @@ const handleKeydown = (event) => {
|
||||
@drop="handleDrop"
|
||||
@dragover.prevent
|
||||
@input="refreshCaretLogicalLine"
|
||||
@compositionstart="handleTextareaCompositionStart"
|
||||
@compositionend="handleTextareaCompositionEnd"
|
||||
@click="refreshCaretLogicalLine"
|
||||
@keyup="refreshCaretLogicalLine"
|
||||
@select="refreshCaretLogicalLine"
|
||||
|
||||
@@ -17,6 +17,7 @@ const { data: siteSettings } = await useFetch('/api/site-settings', {
|
||||
announcementText: '',
|
||||
announcementUrl: '',
|
||||
announcementBackgroundColor: '#15171a',
|
||||
announcementAlignment: 'center',
|
||||
updatedAt: null
|
||||
})
|
||||
})
|
||||
@@ -48,6 +49,8 @@ const announcementLink = computed(() => normalizeAnnouncementUrl(siteSettings.va
|
||||
|
||||
const snoozeLabel = computed(() => `${ANNOUNCEMENT_SNOOZE_DAYS}일간 보지 않기`)
|
||||
|
||||
const announcementAlignment = computed(() => siteSettings.value?.announcementAlignment === 'left' ? 'left' : 'center')
|
||||
|
||||
const barStyle = computed(() => {
|
||||
const backgroundColor = siteSettings.value?.announcementBackgroundColor || '#15171a'
|
||||
return {
|
||||
@@ -158,11 +161,17 @@ onBeforeUnmount(() => {
|
||||
aria-label="사이트 공지"
|
||||
:aria-hidden="(!expanded).toString()"
|
||||
>
|
||||
<div class="site-announcement-bar__inner relative mx-auto flex min-h-9 max-w-[1294px] items-center justify-center gap-3 px-4 py-2.5 sm:px-6 lg:px-8">
|
||||
<div
|
||||
class="site-announcement-bar__inner relative mx-auto flex min-h-9 max-w-[1294px] items-center gap-3 px-4 py-2.5 sm:px-6 lg:px-8"
|
||||
:class="announcementAlignment === 'left' ? 'justify-start' : 'justify-center'"
|
||||
>
|
||||
<component
|
||||
:is="announcementLink ? 'a' : 'span'"
|
||||
class="site-announcement-bar__text min-w-0 flex-1 line-clamp-2 px-6 sm:px-8"
|
||||
:class="announcementLink ? 'hover:underline' : ''"
|
||||
class="site-announcement-bar__text min-w-0 line-clamp-2 px-6 sm:px-8"
|
||||
:class="[
|
||||
announcementLink ? 'hover:underline' : '',
|
||||
announcementAlignment === 'left' ? 'flex-1 text-left' : 'flex-1 text-center'
|
||||
]"
|
||||
:href="announcementLink || undefined"
|
||||
:target="announcementLink ? '_blank' : undefined"
|
||||
:rel="announcementLink ? 'noreferrer' : undefined"
|
||||
|
||||
Reference in New Issue
Block a user