WysiWyg.vue 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. <template>
  2. <div ref="root" class="flex flex-col gap-2 rounded-lg p-2 bg-background-100">
  3. <div
  4. class="flex items-center justify-center fixed top-0 left-0 right-0 bottom-0 duration-300 transition-all"
  5. :class="{
  6. 'pointer-events-auto': showHeadingPopup,
  7. 'pointer-events-none': !showHeadingPopup,
  8. }"
  9. >
  10. <div
  11. class="absolute left-0 right-0 top-0 bottom-0 duration-300 transition-all z-10"
  12. :class="{
  13. 'bg-background-100/50 backdrop-blur-sm opacity-100': showHeadingPopup,
  14. 'backdrop-blur-none opacity-0': !showHeadingPopup,
  15. }"
  16. @click="toggleHeadingPopup"
  17. ></div>
  18. <div
  19. class="flex flex-col items-center justify-center bg-background-100
  20. rounded-lg p-2 z-20 duration-300 transition-all drop-shadow-lg"
  21. :class="{
  22. 'opacity-100 scale-100': showHeadingPopup,
  23. 'opacity-0 scale-75 translate-y-10': !showHeadingPopup,
  24. }"
  25. >
  26. <span>Выберите стиль заголовка</span>
  27. <h1 @click="chooseHeading(1)">Heading 1</h1>
  28. </div>
  29. </div>
  30. <div class="flex flex-wrap gap-2 bg-background-200 rounded-lg p-2">
  31. <img src="@/assets/icons/heading 1.svg" alt="set heading" @click="toggleHeadingPopup">
  32. <div class="bg-foreground/25 w-[2px] min-h-full"></div>
  33. <img src="@/assets/icons/bold 1.svg" alt="set bold" @click="applyBold">
  34. <img src="@/assets/icons/italic 1.svg" alt="set italic" @click="applyItalic">
  35. <div class="bg-foreground/25 w-[2px] min-h-full"></div>
  36. <img src="@/assets/icons/link 1.svg" alt="set link" @click="applyLink" >
  37. <div class="bg-foreground/25 w-[2px] min-h-full"></div>
  38. <img src="@/assets/icons/lines.svg" alt="set list" @click="applyList" >
  39. <div class="bg-foreground/25 w-[2px] min-h-full"></div>
  40. <img src="@/assets/icons/blockquote.svg" alt="set list" @click="applyQuote" >
  41. </div>
  42. <MilkdownProvider>
  43. <EditorMilkdownEditor ref="editor" />
  44. </MilkdownProvider>
  45. </div>
  46. </template>
  47. <script setup lang="ts">
  48. import { MilkdownProvider } from "@milkdown/vue";
  49. const showHeadingPopup = ref(false);
  50. const root = ref<HTMLElement | null>(null);
  51. const editor = ref<{
  52. content?: string,
  53. appendMarkdown?: (str: string) => void,
  54. toggleBold?: () => void,
  55. toggleItalic?: () => void,
  56. toggleLink?: () => void,
  57. toggleList?: () => void,
  58. toggleQuote?: () => void,
  59. getMdText?: () => void,
  60. }>();
  61. function toggleHeadingPopup() {
  62. showHeadingPopup.value = !showHeadingPopup.value;
  63. }
  64. function chooseHeading(type: number) {
  65. toggleHeadingPopup();
  66. editor.value?.appendMarkdown!!(`\n\n${'#'.repeat(type)} Заголовок`);
  67. }
  68. const applyBold = () => editor.value?.toggleBold!!();
  69. const applyItalic = () => editor.value?.toggleItalic!!();
  70. const applyLink = () => editor.value?.toggleLink!!();
  71. const applyList = () => editor.value?.toggleList!!();
  72. const applyQuote = () => editor.value?.toggleQuote!!();
  73. const getMdText = () => editor.value?.getMdText!!();
  74. defineExpose({
  75. getMdText,
  76. })
  77. </script>