diff --git a/apps/web/package.json b/apps/web/package.json index 11c86a45fd..4da2126748 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -32,6 +32,7 @@ "@tiptap/core": "^2.0.3", "@tiptap/extension-color": "^2.0.3", "@tiptap/extension-link": "^2.0.3", + "@tiptap/extension-placeholder": "^2.10.2", "@tiptap/extension-text-align": "^2.0.3", "@tiptap/extension-text-style": "^2.0.3", "@tiptap/extension-underline": "^2.0.3", @@ -53,6 +54,7 @@ "diff-match-patch": "^1.0.5", "echarts": "^5.5.0", "ejs": "^3.1.10", + "hangul-js": "^0.2.6", "hashids": "^2.2.1", "highlight.js": "^11.5.1", "html-to-image": "^1.9.0", diff --git a/apps/web/src/common/components/editor/TextEditor.vue b/apps/web/src/common/components/editor/TextEditor.vue index fc4521d044..f650b49f70 100644 --- a/apps/web/src/common/components/editor/TextEditor.vue +++ b/apps/web/src/common/components/editor/TextEditor.vue @@ -5,6 +5,7 @@ import { import { Color } from '@tiptap/extension-color'; import Link from '@tiptap/extension-link'; +import Placeholder from '@tiptap/extension-placeholder'; import TextAlign from '@tiptap/extension-text-align'; import TextStyle from '@tiptap/extension-text-style'; import Underline from '@tiptap/extension-underline'; @@ -23,6 +24,7 @@ interface Props { imageUploader?: ImageUploader; attachments?: Attachment[]; invalid?: boolean; + placeholder?: string; } const props = withDefaults(defineProps(), { value: '', @@ -32,6 +34,7 @@ const props = withDefaults(defineProps(), { }), attachments: () => [], invalid: false, + placeholder: '', }); const emit = defineEmits<{(e: 'update:value', value: string): void; (e: 'update:attachments', attachments: Attachment[]): void; @@ -60,6 +63,9 @@ onMounted(() => { }, }, }), + Placeholder.configure({ + placeholder: props.placeholder, + }), Underline, Link, TextStyle, @@ -112,6 +118,15 @@ watch([() => props.value, () => props.attachments], ([value, attachments], prev) &:focus { @apply outline-none; } + + /* Placeholder (at the top) */ + p.is-editor-empty:first-child::before { + @apply text-gray-400; + content: attr(data-placeholder); + float: left; + height: 0; + pointer-events: none; + } } } } diff --git a/apps/web/src/common/components/editor/TextEditorViewer.vue b/apps/web/src/common/components/editor/TextEditorViewer.vue index e4cdcf263a..b0af288449 100644 --- a/apps/web/src/common/components/editor/TextEditorViewer.vue +++ b/apps/web/src/common/components/editor/TextEditorViewer.vue @@ -7,12 +7,14 @@ import type { Attachment } from '@/common/components/editor/extensions/image/typ import { loadMonospaceFonts } from '@/styles/fonts'; interface Props { - contents?: string, - attachments?: Attachment[] + contents?: string; + attachments?: Attachment[]; + showInBox?: boolean } const props = withDefaults(defineProps(), { contents: '', attachments: () => [], + showInBox: false, }); loadMonospaceFonts(); @@ -22,6 +24,7 @@ const refinedContents = computed(() => setAttachmentsToContents(props.contents, @@ -31,6 +34,10 @@ const refinedContents = computed(() => setAttachmentsToContents(props.contents, .text-editor-contents { margin-left: 0.1rem; + &.contents-box { + @apply ml-0 p-2 min-h-21 border border-gray-300 rounded-md; + } + @mixin all-nodes-style; img:active { @@ -41,4 +48,4 @@ const refinedContents = computed(() => setAttachmentsToContents(props.contents, @apply ml-1; } } - +ㅕ diff --git a/apps/web/src/common/components/inputs/LabelsInput.vue b/apps/web/src/common/components/inputs/LabelsInput.vue new file mode 100644 index 0000000000..2613ddda97 --- /dev/null +++ b/apps/web/src/common/components/inputs/LabelsInput.vue @@ -0,0 +1,118 @@ + + + diff --git a/apps/web/src/common/components/modals/DeleteModal.vue b/apps/web/src/common/components/modals/DeleteModal.vue index 607ee52c05..52590c4399 100644 --- a/apps/web/src/common/components/modals/DeleteModal.vue +++ b/apps/web/src/common/components/modals/DeleteModal.vue @@ -12,6 +12,7 @@ :hide-header-close-button="hideCloseButton" @confirm="handleConfirm" @close="$emit('close')" + @closed="$emit('closed')" @cancel="$emit('cancel')" >