Files
sori.studio/components/admin/AdminMarkdownWriteSurface.vue

121 lines
3.1 KiB
Vue

<script setup>
import AdminMarkdownUploadingBadge from './AdminMarkdownUploadingBadge.vue'
const props = defineProps({
modelValue: {
type: String,
default: ''
},
gutterLineCount: {
type: Number,
default: 1
},
getGutterLineHeight: {
type: Function,
required: true
},
isUploading: {
type: Boolean,
default: false
}
})
const emit = defineEmits([
'update:modelValue',
'keydown',
'paste',
'drop',
'input',
'compositionstart',
'compositionend',
'click',
'keyup',
'select',
'focus',
'blur'
])
const textareaRef = ref(null)
const gutterRef = ref(null)
/**
* textarea 입력 값을 부모 모델에 반영하고 입력 이벤트를 전달한다.
* @param {Event} event - textarea 입력 이벤트
* @returns {void}
*/
const onInput = (event) => {
emit('update:modelValue', event.target?.value || '')
emit('input', event)
}
/**
* 작성 textarea DOM을 반환한다.
* @returns {HTMLTextAreaElement|null} textarea DOM
*/
const getTextareaElement = () => textareaRef.value
/**
* 줄 번호 gutter DOM을 반환한다.
* @returns {HTMLElement|null} gutter DOM
*/
const getGutterElement = () => gutterRef.value
defineExpose({
getTextareaElement,
getGutterElement
})
</script>
<template>
<div class="admin-markdown-editor__write relative">
<div class="admin-markdown-editor__editor-surface min-h-[620px]">
<div class="admin-markdown-editor__write-columns flex items-start">
<div
ref="gutterRef"
class="admin-markdown-editor__gutter w-10 shrink-0 select-none py-5 pr-2 font-mono text-[13px] leading-7 text-[#a0a8b0]"
aria-hidden="true"
>
<div
v-for="ln in props.gutterLineCount"
:key="`gutter-line-${ln}`"
class="admin-markdown-editor__gutter-line text-right tabular-nums"
:style="{ height: `${props.getGutterLineHeight(ln - 1)}px` }"
>
{{ ln }}
</div>
</div>
<textarea
ref="textareaRef"
:value="modelValue"
class="admin-markdown-editor__textarea min-h-[620px] min-w-0 flex-1 resize-none overflow-hidden break-words border-0 bg-transparent py-5 pl-0 pr-5 text-[15px] leading-7 text-[#15171a] outline-none transition-colors placeholder:text-[#8e9cac] focus:ring-0"
placeholder="마크다운으로 글을 작성하세요."
spellcheck="false"
@keydown="emit('keydown', $event)"
@paste="emit('paste', $event)"
@drop="emit('drop', $event)"
@dragover.prevent
@input="onInput"
@compositionstart="emit('compositionstart', $event)"
@compositionend="emit('compositionend', $event)"
@click="emit('click', $event)"
@keyup="emit('keyup', $event)"
@select="emit('select', $event)"
@focus="emit('focus', $event)"
@blur="emit('blur', $event)"
/>
</div>
</div>
<AdminMarkdownUploadingBadge v-if="isUploading" />
</div>
</template>
<style scoped>
.admin-markdown-editor__gutter {
scrollbar-width: none;
}
.admin-markdown-editor__gutter::-webkit-scrollbar {
display: none;
}
</style>