인용 블록 색상과 라이브 설정 패널 정리

This commit is contained in:
2026-06-04 10:28:43 +09:00
parent 2cb1ff4651
commit b38fc9f154
15 changed files with 222 additions and 221 deletions

View File

@@ -1,9 +1,5 @@
<script setup>
import {
buildCalloutOpenerLine,
CALLOUT_BACKGROUND_OPTIONS,
CALLOUT_EMOJI_OPTIONS
} from '../../lib/markdown-callout.js'
import { buildCalloutOpenerLine } from '../../lib/markdown-callout.js'
import ProseCallout from './ProseCallout.vue'
import ContentMarkdownEditableInline from './ContentMarkdownEditableInline.vue'
@@ -29,37 +25,16 @@ const props = defineProps({
bodySourceLine: {
type: Number,
required: true
},
/** 콜아웃 선언 줄 source-line(0-based) */
blockSourceLine: {
type: Number,
required: true
}
})
const emit = defineEmits(['commit'])
const settingsOpen = ref(false)
const emojiDraft = ref(props.calloutEmoji)
const emojiEnabled = ref(props.calloutEmojiEnabled)
const background = ref(props.calloutBackground)
/** @type {import('vue').ComputedRef<Array<{ value: string, label: string }>>} */
const backgroundOptions = computed(() => CALLOUT_BACKGROUND_OPTIONS.map((value) => ({
value,
label: value
})))
/** @type {import('vue').ComputedRef<string[]>} */
const emojiOptions = computed(() => CALLOUT_EMOJI_OPTIONS)
watch(() => props.calloutEmoji, (value) => {
emojiDraft.value = value
})
watch(() => props.calloutEmojiEnabled, (value) => {
emojiEnabled.value = value
})
watch(() => props.calloutBackground, (value) => {
background.value = value
})
/**
* 콜아웃 마크다운 줄을 반영한다.
* @param {string} body - 본문
@@ -70,9 +45,9 @@ const commitCallout = (body) => {
emit('commit', [
buildCalloutOpenerLine({
calloutEmojiEnabled: emojiEnabled.value,
calloutEmoji: emojiDraft.value,
calloutBackground: background.value
calloutEmojiEnabled: props.calloutEmojiEnabled,
calloutEmoji: props.calloutEmoji,
calloutBackground: props.calloutBackground
}),
...contentLines,
':::'
@@ -87,71 +62,25 @@ const commitCallout = (body) => {
const onBodyCommit = (body) => {
commitCallout(body)
}
/**
* 설정 모달을 연다.
* @returns {void}
*/
const openSettings = () => {
settingsOpen.value = true
}
/**
* 설정 모달을 닫는다.
* @returns {void}
*/
const closeSettings = () => {
settingsOpen.value = false
}
/**
* 이모지 표시를 토글한다.
* @returns {void}
*/
const toggleEmoji = () => {
emojiEnabled.value = !emojiEnabled.value
commitCallout(props.modelValue)
}
/**
* 배경색을 변경한다.
* @param {string} value - 배경 키
* @returns {void}
*/
const setBackground = (value) => {
background.value = value
commitCallout(props.modelValue)
}
/**
* 프리셋 이모지를 선택한다.
* @param {string} value - 이모지
* @returns {void}
*/
const setEmoji = (value) => {
emojiDraft.value = value
emojiEnabled.value = true
commitCallout(props.modelValue)
}
</script>
<template>
<div class="content-markdown-callout-editor relative">
<div
class="content-markdown-callout-editor relative"
:data-source-line="blockSourceLine"
>
<ProseCallout
:emoji-enabled="false"
:background="background"
:background="calloutBackground"
>
<div class="content-markdown-callout-editor__inner flex items-start gap-2">
<button
class="content-markdown-callout-editor__emoji-btn inline-flex size-9 shrink-0 items-center justify-center rounded-md text-xl text-[var(--site-text)] transition-colors hover:bg-black/10"
type="button"
aria-label="콜아웃 아이콘·색상 설정"
@mousedown.prevent
@click.stop="openSettings"
<span
class="content-markdown-callout-editor__emoji inline-flex size-9 shrink-0 items-center justify-center rounded-md text-xl text-[var(--site-text)]"
aria-hidden="true"
>
<span v-if="emojiEnabled">{{ emojiDraft || '💡' }}</span>
<span v-if="calloutEmojiEnabled">{{ calloutEmoji || '💡' }}</span>
<span v-else class="text-base text-[#8e9cac]">+</span>
</button>
</span>
<ContentMarkdownEditableInline
block-class="content-markdown-callout-editor__body min-w-0 flex-1 text-[15px] leading-8 text-[var(--site-text)]"
enter-mode="multiline"
@@ -161,97 +90,5 @@ const setEmoji = (value) => {
/>
</div>
</ProseCallout>
<Teleport to="body">
<div
v-if="settingsOpen"
class="content-markdown-callout-editor__modal fixed inset-0 z-[80] grid place-items-center bg-black/35 px-4"
@click.self="closeSettings"
>
<section
class="content-markdown-callout-editor__panel w-full max-w-sm rounded-lg bg-white p-6 shadow-xl"
role="dialog"
aria-labelledby="callout-settings-title"
@click.stop
>
<header class="content-markdown-callout-editor__panel-header mb-4 flex items-center justify-between gap-3">
<h2 id="callout-settings-title" class="text-base font-semibold text-[#15171a]">
콜아웃 설정
</h2>
<button
class="content-markdown-callout-editor__close rounded px-2 py-1 text-sm text-[#6b7280] hover:bg-[#f1f3f4]"
type="button"
@click="closeSettings"
>
닫기
</button>
</header>
<div class="content-markdown-callout-editor__icon-toggle mb-4 flex items-center justify-between gap-3">
<span class="text-sm font-medium text-[#15171a]">아이콘</span>
<button
class="content-markdown-callout-editor__switch relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#8e9cac]"
:class="emojiEnabled ? 'bg-[#15171a]' : 'bg-[#d0d7de]'"
type="button"
role="switch"
:aria-checked="emojiEnabled"
@click="toggleEmoji"
>
<span
class="content-markdown-callout-editor__switch-knob pointer-events-none inline-block size-5 rounded-full bg-white shadow transition-transform duration-200 ease-out"
:class="emojiEnabled ? 'translate-x-[22px]' : 'translate-x-0.5'"
/>
<span class="sr-only">{{ emojiEnabled ? '아이콘 표시' : '아이콘 숨김' }}</span>
</button>
</div>
<div
v-if="emojiEnabled"
class="content-markdown-callout-editor__emoji-presets mb-4"
>
<ul class="flex flex-wrap gap-2">
<li
v-for="emoji in emojiOptions"
:key="`callout-emoji-${emoji}`"
>
<button
class="content-markdown-callout-editor__emoji-swatch inline-flex size-9 items-center justify-center rounded-full border-2 text-xl transition-transform"
:class="emojiDraft === emoji ? 'border-[#22c55e] scale-110 bg-[#f6f7f8]' : 'border-transparent hover:bg-[#f1f3f4]'"
type="button"
:aria-label="`이모지 ${emoji}`"
@click="setEmoji(emoji)"
>
{{ emoji }}
</button>
</li>
</ul>
</div>
<div class="content-markdown-callout-editor__colors">
<p class="mb-2 text-sm font-medium text-[#15171a]">배경색</p>
<ul class="flex flex-wrap gap-2">
<li v-for="option in backgroundOptions" :key="`callout-bg-${option.value}`">
<button
class="content-markdown-callout-editor__color-swatch size-8 rounded-full border-2 transition-transform"
:class="background === option.value ? 'border-[#22c55e] scale-110' : 'border-transparent'"
type="button"
:aria-label="option.label"
:style="{
background: option.value === 'gray' ? 'rgba(100,116,139,0.28)'
: option.value === 'blue' ? 'rgba(59,130,246,0.3)'
: option.value === 'green' ? 'rgba(34,197,94,0.3)'
: option.value === 'yellow' ? 'rgba(245,158,11,0.34)'
: option.value === 'red' ? 'rgba(239,68,68,0.3)'
: option.value === 'purple' ? 'rgba(168,85,247,0.3)'
: 'rgba(236,72,153,0.3)'
}"
@click="setBackground(option.value)"
/>
</li>
</ul>
</div>
</section>
</div>
</Teleport>
</div>
</template>