WysiWyg.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <template>
  2. <div
  3. ref="root"
  4. class="flex flex-col gap-2 rounded-lg p-2 bg-background-100"
  5. >
  6. <div
  7. class="flex items-center justify-center fixed top-0 left-0 right-0 bottom-0 duration-300 transition-all"
  8. :class="{
  9. 'pointer-events-auto': showHeadingPopup,
  10. 'pointer-events-none': !showHeadingPopup,
  11. }"
  12. >
  13. <div
  14. class="absolute left-0 right-0 top-0 bottom-0 duration-300 transition-all z-10"
  15. :class="{
  16. 'bg-background-100/50 backdrop-blur-sm opacity-100': showHeadingPopup,
  17. 'backdrop-blur-none opacity-0': !showHeadingPopup,
  18. }"
  19. @click="toggleHeadingPopup"
  20. />
  21. <div
  22. class="flex flex-col items-center justify-center bg-background-100
  23. rounded-lg p-2 z-20 duration-300 transition-all drop-shadow-lg"
  24. :class="{
  25. 'opacity-100 scale-100': showHeadingPopup,
  26. 'opacity-0 scale-75 translate-y-10': !showHeadingPopup,
  27. }"
  28. >
  29. <p class="font-semibold text-xl">
  30. Выберите стиль заголовка
  31. </p>
  32. <div class="flex flex-col divide-y divide-foreground/20">
  33. <!-- TODO: v-for -->
  34. <h1
  35. class="mt-4 pb-1 w-full px-8 duration-150 cursor-pointer rounded-t-md text-center bg-opacity-0 hover:bg-opacity-30 bg-white"
  36. @click="chooseHeading(1)"
  37. >
  38. Heading 1
  39. </h1>
  40. <h2
  41. class="py-1 w-full px-8 duration-150 cursor-pointer text-center bg-opacity-0 hover:bg-opacity-30 bg-white"
  42. @click="chooseHeading(2)"
  43. >
  44. Heading 2
  45. </h2>
  46. <h3
  47. class="py-1 w-full px-8 duration-150 cursor-pointer text-center bg-opacity-0 hover:bg-opacity-30 bg-white"
  48. @click="chooseHeading(3)"
  49. >
  50. Heading 3
  51. </h3>
  52. <h4
  53. class="pt-1 mb-4 w-full px-8 duration-150 cursor-pointer rounded-b-md text-center bg-opacity-0 hover:bg-opacity-30 bg-white"
  54. @click="chooseHeading(4)"
  55. >
  56. Heading 4
  57. </h4>
  58. </div>
  59. </div>
  60. </div>
  61. <div class="flex flex-wrap gap-2 bg-background-200 rounded-lg p-2">
  62. <!-- TODO: v-for -->
  63. <IBgHeading
  64. class="h-[32px] w-[32px]"
  65. @click="toggleHeadingPopup"
  66. />
  67. <div class="bg-foreground/25 w-[2px]" />
  68. <IBgBold
  69. class="h-[32px] w-[32px]"
  70. @click="applyBold"
  71. />
  72. <IBgItalic
  73. class="h-[32px] w-[32px]"
  74. @click="applyItalic"
  75. />
  76. <div class="bg-foreground/25 w-[2px]" />
  77. <IBgLink
  78. class="h-[32px] w-[32px]"
  79. @click="applyLink"
  80. />
  81. <div class="bg-foreground/25 w-[2px]" />
  82. <IBgLines
  83. class="h-[32px] w-[32px]"
  84. @click="applyList"
  85. />
  86. <div class="bg-foreground/25 w-[2px]" />
  87. <IBlockquote
  88. class="h-[32px] w-[32px]"
  89. @click="applyQuote"
  90. />
  91. </div>
  92. <MilkdownProvider>
  93. <EditorMilkdownEditor ref="editor" />
  94. </MilkdownProvider>
  95. </div>
  96. </template>
  97. <script setup lang="ts">
  98. import { MilkdownProvider } from '@milkdown/vue'
  99. const showHeadingPopup = ref(false)
  100. const root = ref<HTMLElement | null>(null)
  101. const editor = ref<{
  102. content?: string
  103. appendMarkdown?: (str: string) => void
  104. toggleBold?: () => void
  105. toggleItalic?: () => void
  106. toggleLink?: () => void
  107. toggleList?: () => void
  108. toggleQuote?: () => void
  109. getMdText?: () => void
  110. }>()
  111. console.log(editor.value)
  112. function toggleHeadingPopup() {
  113. showHeadingPopup.value = !showHeadingPopup.value
  114. }
  115. function chooseHeading(type: number) {
  116. toggleHeadingPopup()
  117. editor.value?.appendMarkdown!(`\n\n${'#'.repeat(type)} Заголовок`)
  118. }
  119. const applyBold = () => editor.value?.toggleBold!()
  120. const applyItalic = () => editor.value?.toggleItalic!()
  121. const applyLink = () => editor.value?.toggleLink!()
  122. const applyList = () => editor.value?.toggleList!()
  123. const applyQuote = () => editor.value?.toggleQuote!()
  124. const getMdText = () => editor.value?.getMdText!()
  125. defineExpose({
  126. getMdText,
  127. })
  128. </script>