renusify 2.5.2 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/components/app/index.vue +74 -22
  2. package/components/app/toast/index.vue +76 -71
  3. package/components/app/toast/toast.vue +62 -44
  4. package/components/avatar/index.vue +207 -84
  5. package/components/button/buttonConfirm.vue +53 -26
  6. package/components/button/buttonGroup.js +0 -2
  7. package/components/button/buttonGroup.vue +310 -62
  8. package/components/button/index.vue +584 -100
  9. package/components/calendar/index.js +0 -2
  10. package/components/calendar/index.vue +326 -262
  11. package/components/calendar/month.vue +64 -55
  12. package/components/calendar/year.vue +30 -25
  13. package/components/card/index.vue +139 -59
  14. package/components/codeEditor/highlightCss.vue +38 -39
  15. package/components/codeEditor/highlightHtml.vue +64 -64
  16. package/components/codeEditor/highlightJs.vue +37 -38
  17. package/components/codeEditor/index.vue +129 -79
  18. package/components/codeEditor/run.vue +225 -39
  19. package/components/codeEditor/useCodeFormatter.js +150 -0
  20. package/components/confirm/index.vue +139 -80
  21. package/components/container/col.vue +5 -4
  22. package/components/container/divider.vue +28 -19
  23. package/components/container/index.vue +34 -15
  24. package/components/container/row.vue +26 -9
  25. package/components/container/spacer.vue +2 -4
  26. package/components/container/style.scss +3 -0
  27. package/components/content/index.vue +49 -32
  28. package/components/cropper/index.vue +401 -244
  29. package/components/float/index.vue +542 -415
  30. package/components/form/addressInput/index.vue +184 -109
  31. package/components/form/camInput/index.vue +370 -244
  32. package/components/form/checkInput/index.vue +138 -71
  33. package/components/form/checkboxInput/index.vue +93 -49
  34. package/components/form/colorInput/Alpha.vue +81 -83
  35. package/components/form/colorInput/Hue.vue +91 -68
  36. package/components/form/colorInput/Preview.vue +43 -47
  37. package/components/form/colorInput/Saturation.vue +101 -86
  38. package/components/form/colorInput/index.vue +71 -39
  39. package/components/form/colorInput/picker.vue +111 -106
  40. package/components/form/colorInput/useColor.js +153 -0
  41. package/components/form/dateInput/index.vue +691 -356
  42. package/components/form/dateInput/month.vue +63 -54
  43. package/components/form/dateInput/year.vue +35 -25
  44. package/components/form/fileInput/index.js +0 -1
  45. package/components/form/fileInput/index.vue +263 -106
  46. package/components/form/fileInput/single.vue +332 -168
  47. package/components/form/groupInput/index.vue +199 -101
  48. package/components/form/index.vue +189 -83
  49. package/components/form/input/index.vue +416 -377
  50. package/components/form/jsonInput/JsonView.vue +54 -56
  51. package/components/form/jsonInput/index.vue +247 -165
  52. package/components/form/maskInput/index.vue +252 -132
  53. package/components/form/numberInput/index.js +0 -1
  54. package/components/form/numberInput/index.vue +226 -117
  55. package/components/form/passwordInput/index.js +2 -1
  56. package/components/form/passwordInput/index.vue +269 -102
  57. package/components/form/radioInput/index.vue +143 -72
  58. package/components/form/rangeInput/index.vue +280 -167
  59. package/components/form/ratingInput/index.vue +57 -57
  60. package/components/form/selectInput/index.js +1 -3
  61. package/components/form/selectInput/index.vue +584 -296
  62. package/components/form/switchInput/index.vue +73 -59
  63. package/components/form/telInput/index.js +0 -1
  64. package/components/form/telInput/index.vue +238 -135
  65. package/components/form/textArea/index.vue +72 -35
  66. package/components/form/textEditor/index.vue +739 -0
  67. package/components/form/{text-editor → textEditor}/style.scss +8 -16
  68. package/components/form/textInput/index.vue +54 -32
  69. package/components/form/timeInput/index.vue +82 -55
  70. package/components/form/timeInput/range.vue +115 -94
  71. package/components/form/timeInput/timepicker.vue +382 -449
  72. package/components/form/uniqueInput/index.vue +105 -48
  73. package/components/form/unitInput/index.vue +139 -84
  74. package/components/formCreator/index.js +0 -1
  75. package/components/formCreator/index.vue +314 -148
  76. package/components/highlight/index.vue +41 -25
  77. package/components/highlight/style.scss +2 -2
  78. package/components/highlight/{mixin.js → useHighlight.js} +181 -160
  79. package/components/icon/index.vue +79 -33
  80. package/components/img/index.vue +250 -147
  81. package/components/img/preview.vue +180 -198
  82. package/components/img/svgImg.vue +42 -39
  83. package/components/index.js +5 -20
  84. package/components/infinite/index.js +3 -3
  85. package/components/infinite/index.vue +290 -66
  86. package/components/map/index.vue +428 -261
  87. package/components/map/route.vue +794 -487
  88. package/components/map/select.vue +118 -58
  89. package/components/menu/index.vue +206 -94
  90. package/components/meta/meta.js +26 -3
  91. package/components/modal/index.vue +382 -156
  92. package/components/notify/index.vue +204 -86
  93. package/components/notify/notification.vue +38 -55
  94. package/components/progress/circle.vue +189 -70
  95. package/components/progress/line.vue +266 -46
  96. package/components/searchBox/index.js +1 -3
  97. package/components/searchBox/index.vue +194 -101
  98. package/components/skeleton/index.vue +45 -20
  99. package/components/slider/index.vue +319 -156
  100. package/components/swiper/index.vue +237 -108
  101. package/components/table/crud/footer.vue +77 -53
  102. package/components/table/crud/header.vue +71 -72
  103. package/components/table/crud/index.vue +629 -399
  104. package/components/table/index.vue +721 -278
  105. package/components/timeAgo/index.vue +145 -96
  106. package/components/tour/index.vue +338 -235
  107. package/components/tree/index.vue +235 -89
  108. package/components/tree/tree-element.vue +106 -106
  109. package/directive/animate/index.js +77 -0
  110. package/directive/clickOutSide/index.js +98 -0
  111. package/directive/drag/index.js +153 -0
  112. package/directive/index.js +11 -13
  113. package/directive/intersect/index.js +263 -0
  114. package/directive/mask/index.js +67 -0
  115. package/directive/parallax/index.js +78 -0
  116. package/directive/ripple/index.js +14 -0
  117. package/directive/scroll/index.js +272 -24
  118. package/directive/sortable/index.js +274 -0
  119. package/directive/title/index.js +75 -0
  120. package/directive/touch/index.js +268 -0
  121. package/index.js +11 -19
  122. package/package.json +5 -2
  123. package/plugins/validation/Validate.js +88 -79
  124. package/scripts/generate-docs.mjs +226 -0
  125. package/scripts/menu.mjs +240 -0
  126. package/scripts/parser.mjs +1086 -0
  127. package/style/_index.scss +7 -0
  128. package/style/app.scss +13 -65
  129. package/style/colors.scss +5 -22
  130. package/style/functions/index.scss +8 -0
  131. package/style/mixins/index.scss +17 -5
  132. package/style/variables/base.scss +155 -178
  133. package/style/variables/color.scss +0 -12
  134. package/style/variables/utilities.scss +0 -180
  135. package/tools/helper.js +0 -8
  136. package/tools/icons.js +7 -2
  137. package/tools/root.js +71 -0
  138. package/components/app/style.scss +0 -41
  139. package/components/app/toast/style.scss +0 -20
  140. package/components/avatar/style.scss +0 -32
  141. package/components/bar/bottomNav.js +0 -1
  142. package/components/bar/bottomNav.vue +0 -28
  143. package/components/bar/bottomNavigationCircle.js +0 -2
  144. package/components/bar/bottomNavigationCircle.vue +0 -99
  145. package/components/bar/scss/bottomNav.scss +0 -67
  146. package/components/bar/scss/toolbar.scss +0 -174
  147. package/components/bar/toolbar/index.js +0 -8
  148. package/components/bar/toolbar/index.vue +0 -35
  149. package/components/bar/toolbar/laptop.vue +0 -33
  150. package/components/bar/toolbar/menuChilds.vue +0 -41
  151. package/components/bar/toolbar/menuLaptop.vue +0 -41
  152. package/components/bar/toolbar/menuMob.vue +0 -39
  153. package/components/bar/toolbar/mixin.js +0 -43
  154. package/components/bar/toolbar/mobile.vue +0 -34
  155. package/components/breadcrumb/bredcrumbItem.vue +0 -39
  156. package/components/breadcrumb/index.js +0 -3
  157. package/components/breadcrumb/index.vue +0 -71
  158. package/components/breadcrumb/style.scss +0 -51
  159. package/components/button/style.scss +0 -411
  160. package/components/card/style.scss +0 -86
  161. package/components/chart/chart.js +0 -1
  162. package/components/chart/chart.vue +0 -69
  163. package/components/chart/worldMap.js +0 -2
  164. package/components/chart/worldMap.vue +0 -1112
  165. package/components/chat/MessageList.vue +0 -163
  166. package/components/chat/chatInput.vue +0 -150
  167. package/components/chat/chatMsg.vue +0 -276
  168. package/components/chat/index.js +0 -11
  169. package/components/chat/index.vue +0 -113
  170. package/components/chip/index.js +0 -3
  171. package/components/chip/index.vue +0 -77
  172. package/components/chip/style.scss +0 -199
  173. package/components/codeEditor/mixin.js +0 -145
  174. package/components/countdown/index.js +0 -1
  175. package/components/countdown/index.vue +0 -105
  176. package/components/form/colorInput/mixin.js +0 -132
  177. package/components/form/fileInput/file.js +0 -148
  178. package/components/form/telInput/assets/flags.png +0 -0
  179. package/components/form/telInput/assets/flags@2x.png +0 -0
  180. package/components/form/text-editor/index.vue +0 -705
  181. package/components/icon/style.scss +0 -17
  182. package/components/infinite/div.js +0 -6
  183. package/components/infinite/div.vue +0 -193
  184. package/components/infinite/page.js +0 -3
  185. package/components/infinite/page.vue +0 -105
  186. package/components/list/index.js +0 -3
  187. package/components/list/index.vue +0 -122
  188. package/components/list/style.scss +0 -66
  189. package/components/message/index.js +0 -4
  190. package/components/message/index.vue +0 -40
  191. package/components/modal/style.scss +0 -146
  192. package/components/nestable/NestableItem.vue +0 -307
  193. package/components/nestable/editable.js +0 -44
  194. package/components/nestable/index.js +0 -1
  195. package/components/nestable/index.vue +0 -226
  196. package/components/nestable/methods.js +0 -416
  197. package/components/progress/style.scss +0 -229
  198. package/components/table/style.scss +0 -338
  199. package/components/tabs/index.js +0 -3
  200. package/components/tabs/index.vue +0 -151
  201. package/components/timeline/index.js +0 -6
  202. package/components/timeline/index.vue +0 -76
  203. package/directive/resize/index.js +0 -30
  204. package/directive/skeleton/index.js +0 -27
  205. package/directive/skeleton/style.scss +0 -37
  206. package/plugins/request/Request.js +0 -68
  207. package/style/animation.scss +0 -94
  208. package/style/style.scss +0 -8
  209. package/tools/rootable.js +0 -75
  210. /package/components/form/{text-editor → textEditor}/index.js +0 -0
  211. /package/components/form/{text-editor → textEditor}/preview.js +0 -0
  212. /package/components/form/{text-editor → textEditor}/preview.vue +0 -0
@@ -0,0 +1,739 @@
1
+ <template>
2
+ <r-input
3
+ :class="[`${$r.prefix}text-editor container-fluid`]"
4
+ :model-value="is_object?modelValue.text:modelValue"
5
+ label-active
6
+ >
7
+ <template v-slot="{uid}">
8
+ <r-container>
9
+ <r-row class="editor-header h-center">
10
+ <r-col class="col-auto">
11
+ <r-btn-group :items="items_dir" @update:modelValue="handle_dir"></r-btn-group>
12
+ </r-col>
13
+ <r-col class="col-auto">
14
+ <r-btn-group :items="menu" exact is-select @open="handleOpen" @update:modelValue="addCss">
15
+ <template v-slot:list="{item}">
16
+ <div :class="'color-white-text'===item['value']?'color-black '+item['value']:item['value']"
17
+ class="list-title"
18
+ >{{ item['text'] }}
19
+ </div>
20
+ </template>
21
+ </r-btn-group>
22
+ </r-col>
23
+ <r-col class="col-auto">
24
+ <r-btn-group :items="items_format" exact
25
+ @update:modelValue="format($event)"></r-btn-group>
26
+ </r-col>
27
+
28
+ <r-col class="col-auto">
29
+ <r-btn-group :items="items_handle"
30
+ @update:modelValue="handle($event)"></r-btn-group>
31
+ </r-col>
32
+ <r-col class="col-auto">
33
+ <r-btn-group :items="items_undo" @update:modelValue="format($event)"></r-btn-group>
34
+ </r-col>
35
+ <r-col class="col-auto">
36
+ <r-btn icon text @click.prevent="$helper.copy(content(),$t('editor_content_copy','renusify'))">
37
+ <r-icon v-html="$r.icons.copy"></r-icon>
38
+ </r-btn>
39
+ </r-col>
40
+ </r-row>
41
+ <r-row>
42
+ <r-col v-if="selectElm&&!selectElm.classList.contains('editor-content')" class="col-12">
43
+ <r-select-input :label="$t('class','renusify')" :model-value="[...selectElm.classList]" class="class-select"
44
+ justValue
45
+ multiple
46
+ tags
47
+ @update:model-value="addClass"></r-select-input>
48
+ </r-col>
49
+ <r-col class="col-12 ltr">
50
+ <span v-for="(item,i) in currentPath" :key="i" class="cursor-pointer" @click.prevent="borderd(item)">
51
+ <span :class="{'color-one-text':selectElm===item}">{{ item.nodeName }} > </span>
52
+ </span>
53
+ </r-col>
54
+ <r-col class="col-12">
55
+ <div :id="uid"
56
+ ref="editorContentRef"
57
+ class="editor-content"
58
+ contenteditable="true"
59
+ @input="updateText()"
60
+ @keyup="bordered"
61
+ v-html="text" @click.prevent="bordered">
62
+ </div>
63
+ </r-col>
64
+ <r-col v-if="files&&files.length>0" class="col-12">
65
+ <div v-for="(img,i) in files" :key="i"
66
+ class="ma-1 img-holder">
67
+ <r-btn class="color-error-text" icon size="xs" @click.prevent="deleteImage(img,i)">
68
+ <r-icon v-html="$r.icons.delete"></r-icon>
69
+ </r-btn>
70
+ <r-img
71
+ :src="img"
72
+ alt="img"
73
+ height="100"></r-img>
74
+ </div>
75
+ </r-col>
76
+ </r-row>
77
+ <r-modal v-model="show"
78
+ no-closable no-close-btn>
79
+ <r-form v-model="valid1">
80
+ <r-container>
81
+ <r-row>
82
+ <r-col class="col-12 ltr">
83
+ <r-text-input v-model="link"
84
+ :label="$t('link','renusify')"
85
+ :rules="['required']"></r-text-input>
86
+ </r-col>
87
+ <r-col class="col-12">
88
+ <r-switch-input v-model="target"
89
+ :label="$t('open_new_tab','renusify')"></r-switch-input>
90
+ </r-col>
91
+ </r-row>
92
+ <r-row class="h-end">
93
+ <r-col class="col-auto">
94
+ <r-btn class="color-error-text"
95
+ outlined
96
+ @click.prevent="show=false">{{ $t('cancel', 'renusify') }}
97
+ </r-btn>
98
+ </r-col>
99
+ <r-col class="col-auto">
100
+ <r-btn :disabled="!valid1"
101
+ class="color-success-text"
102
+ outlined
103
+ @click.prevent="handleForm()">{{ $t('send', 'renusify') }}
104
+ </r-btn>
105
+ </r-col>
106
+ </r-row>
107
+ </r-container>
108
+ </r-form>
109
+ </r-modal>
110
+ <r-modal v-model="showImg"
111
+ no-closable no-close-btn>
112
+ <r-form v-model="valid2">
113
+ <r-container>
114
+ <r-file-input v-model="image"
115
+ :headers="headers"
116
+ :label="$t('image','renusify')"
117
+ :rules="['required']"
118
+ :size="1"
119
+ :upload-link="uploadLink"
120
+ accept="image/*"></r-file-input>
121
+ <r-text-input v-model="img_alt"
122
+ :label="$t('img_alt','renusify')"
123
+ :rules="['required']"></r-text-input>
124
+ <r-number-input v-model="img_width" :label="$t('width','renusify')"
125
+ :rules="['required']"></r-number-input>
126
+ <r-row class="h-end">
127
+ <r-col class="col-auto">
128
+ <r-btn class="color-error-text"
129
+ outlined
130
+ @click.prevent="showImg=false">{{ $t('cancel', 'renusify') }}
131
+ </r-btn>
132
+ </r-col>
133
+ <r-col class="col-auto">
134
+ <r-btn :disabled="!valid2"
135
+ class="color-success-text"
136
+ outlined
137
+ @click.prevent="handleImageForm()">{{ $t('send', 'renusify') }}
138
+ </r-btn>
139
+ </r-col>
140
+ </r-row>
141
+ </r-container>
142
+ </r-form>
143
+ </r-modal>
144
+ <r-modal v-model="showVideo"
145
+ no-closable no-close-btn>
146
+ <r-form v-model="valid2">
147
+ <r-container>
148
+ <r-file-input v-model="video"
149
+ :headers="headers"
150
+ :label="$t('video','renusify')"
151
+ :rules="['required']"
152
+ :size="1"
153
+ :upload-link="uploadLink"
154
+ accept="video/mp4,video/webm"></r-file-input>
155
+ <r-number-input v-model="img_width" :label="$t('width','renusify')"
156
+ :rules="['required']"></r-number-input>
157
+ <r-number-input v-model="img_height" :label="$t('height','renusify')"
158
+ :rules="['required']"></r-number-input>
159
+ <r-row class="h-end">
160
+ <r-col class="col-auto">
161
+ <r-btn class="color-error-text"
162
+ outlined
163
+ @click.prevent="showVideo=false">{{ $t('cancel', 'renusify') }}
164
+ </r-btn>
165
+ </r-col>
166
+ <r-col class="col-auto">
167
+ <r-btn :disabled="!valid2"
168
+ class="color-success-text"
169
+ outlined
170
+ @click.prevent="handleVideoForm()">{{ $t('send', 'renusify') }}
171
+ </r-btn>
172
+ </r-col>
173
+ </r-row>
174
+ </r-container>
175
+ </r-form>
176
+ </r-modal>
177
+ <r-modal v-model="showPre"
178
+ no-closable no-close-btn>
179
+ <r-form v-model="valid2">
180
+ <r-container>
181
+ <r-text-input v-model="code_name" :label="$t('name','renusify')"></r-text-input>
182
+ <r-select-input v-model="lang" :items="langs"
183
+ :label="$t('lang','renusify')"
184
+ :rules="['required']"
185
+ just-value></r-select-input>
186
+ <r-text-area v-model="code"
187
+ :label="$t('code','renusify')"
188
+ :rules="['required']"
189
+ ltr></r-text-area>
190
+ <div class="text-end my-3">
191
+ <r-btn class="color-error-text"
192
+ outlined
193
+ @click.prevent="showPre=false">{{ $t('cancel', 'renusify') }}
194
+ </r-btn>
195
+ <r-btn :disabled="!valid2"
196
+ class="color-success-text ms-2"
197
+ outlined
198
+ @click.prevent="handlePreForm()">{{ $t('send', 'renusify') }}
199
+ </r-btn>
200
+ </div>
201
+ </r-container>
202
+ </r-form>
203
+ </r-modal>
204
+ <r-modal v-model="showTable"
205
+ no-closable no-close-btn>
206
+ <r-form v-model="valid2">
207
+ <r-container>
208
+ <r-select-input v-model="table_form.headers"
209
+ :label="$t('headers','renusify')"
210
+ :rules="['required']" just-value multiple tags></r-select-input>
211
+ <r-number-input v-model="table_form.row" :label="$t('row','renusify')"
212
+ :rules="['required']"></r-number-input>
213
+
214
+ <div class="text-end my-3">
215
+ <r-btn class="color-error-text"
216
+ outlined
217
+ @click.prevent="showTable=false">{{ $t('cancel', 'renusify') }}
218
+ </r-btn>
219
+ <r-btn :disabled="!valid2"
220
+ class="color-success-text ms-2"
221
+ outlined
222
+ @click.prevent="handleTableForm()">{{ $t('send', 'renusify') }}
223
+ </r-btn>
224
+ </div>
225
+ </r-container>
226
+ </r-form>
227
+ </r-modal>
228
+
229
+ </r-container>
230
+ </template>
231
+ </r-input>
232
+ </template>
233
+
234
+ <script setup>
235
+ import './style.scss'
236
+ import '../../highlight/style.scss'
237
+ import {useHighlight} from "../../highlight/useHighlight"
238
+ import {ref, computed, onMounted, onBeforeUnmount, inject} from 'vue'
239
+
240
+ const {$toast, $helper, $r} = inject('renusify')
241
+ const axios = inject('axios')
242
+
243
+ const props = defineProps({
244
+ /**
245
+ * API endpoint URL for uploading media files (images/videos)
246
+ * @type {String}
247
+ */
248
+ uploadLink: String,
249
+ /**
250
+ * The editor's model value (object with text and files or plain string)
251
+ * @type {Object|String}
252
+ * @default { text: '', files: [] }
253
+ */
254
+ modelValue: {
255
+ type: [Object, String],
256
+ default: () => ({
257
+ text: '',
258
+ files: []
259
+ })
260
+ },
261
+ /**
262
+ * Additional headers for upload requests
263
+ * @type {Object}
264
+ */
265
+ headers: Object
266
+ })
267
+
268
+ const emit = defineEmits([
269
+ /**
270
+ * Emitted when editor content changes
271
+ * @param {Object} value - Updated editor value with text and files
272
+ * @param {String} value.text - HTML content
273
+ * @param {Array} value.files - Array of uploaded file URLs
274
+ */
275
+ 'update:modelValue'
276
+ ])
277
+
278
+ const {
279
+ highlight,
280
+ } = useHighlight()
281
+
282
+ const text = ref(props.modelValue && typeof props.modelValue === 'object' && 'text' in props.modelValue ? props.modelValue.text : props.modelValue)
283
+ const files = ref(props.modelValue && typeof props.modelValue === 'object' && 'text' in props.modelValue ? props.modelValue.files : [])
284
+ const valid1 = ref(false)
285
+ const valid2 = ref(false)
286
+ const show = ref(false)
287
+ const showImg = ref(false)
288
+ const showVideo = ref(false)
289
+ const img_width = ref(200)
290
+ const img_height = ref(200)
291
+ const video = ref([])
292
+ const image = ref([])
293
+ const img_alt = ref(null)
294
+ const target = ref(false)
295
+ const link = ref(null)
296
+ const preSelected = ref(null)
297
+ const currentPath = ref([])
298
+ const selectElm = ref(null)
299
+ const code_name = ref(null)
300
+ const code = ref('')
301
+ const lang = ref(null)
302
+ const showPre = ref(false)
303
+ const showTable = ref(false)
304
+ const table_form = ref({})
305
+ const editorContentRef = ref(null)
306
+
307
+ const langs = ['asm', 'bash', 'bf', 'c', 'css', 'csv', 'diff', 'docker', 'git', 'go', 'html', 'http', 'ini', 'java', 'js', 'jsdoc', 'json', 'log', 'lua', 'make', 'pl', 'plain', 'py', 'regex', 'rs', 'sql', 'todo', 'toml', 'ts', 'uri', 'xml', 'yaml']
308
+
309
+ const items_undo = {
310
+ 'undo': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M12.5 8c-2.65 0-5.05 1-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88c3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8Z"/></svg>',
311
+ 'redo': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M18.4 10.6C16.55 9 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16a8.002 8.002 0 0 1 7.6-5.5c1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6Z"/></svg>',
312
+ }
313
+
314
+ const items_handle = {
315
+ 'insertDIV': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M4 6v13h16V6H4m14 11H6V8h12v9Z"/></svg>',
316
+ 'insertLINE': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M9 7h2v8h4v2H9V7m3-5a10 10 0 0 1 10 10a10 10 0 0 1-10 10A10 10 0 0 1 2 12A10 10 0 0 1 12 2m0 2a8 8 0 0 0-8 8a8 8 0 0 0 8 8a8 8 0 0 0 8-8a8 8 0 0 0-8-8Z"/></svg>',
317
+ 'BLOCKQUOTE': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4Z"/></svg>',
318
+ 'PRE': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="m12.89 3l1.96.4L11.11 21l-1.96-.4L12.89 3m6.7 9L16 8.41V5.58L22.42 12L16 18.41v-2.83L19.59 12M1.58 12L8 5.58v2.83L4.41 12L8 15.58v2.83L1.58 12Z"/></svg>',
319
+ 'createTable': '<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 4L9 20M15 4L15 20M3 9H21M3 15H21M6.2 20H17.8C18.9201 20 19.4802 20 19.908 19.782C20.2843 19.5903 20.5903 19.2843 20.782 18.908C21 18.4802 21 17.9201 21 16.8V7.2C21 6.0799 21 5.51984 20.782 5.09202C20.5903 4.71569 20.2843 4.40973 19.908 4.21799C19.4802 4 18.9201 4 17.8 4H6.2C5.07989 4 4.51984 4 4.09202 4.21799C3.71569 4.40973 3.40973 4.71569 3.21799 5.09202C3 5.51984 3 6.07989 3 7.2V16.8C3 17.9201 3 18.4802 3.21799 18.908C3.40973 19.2843 3.71569 19.5903 4.09202 19.782C4.51984 20 5.07989 20 6.2 20Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>',
320
+ 'createLink': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7a5 5 0 0 0-5 5a5 5 0 0 0 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1M8 13h8v-2H8v2m9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1c0 1.71-1.39 3.1-3.1 3.1h-4V17h4a5 5 0 0 0 5-5a5 5 0 0 0-5-5Z"/></svg>',
321
+ }
322
+
323
+ const items_format = {
324
+ 'insertOrderedList': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25Z"/></svg>',
325
+ 'insertUnorderedList': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M3 4h4v4H3V4m6 1v2h12V5H9m-6 5h4v4H3v-4m6 1v2h12v-2H9m-6 5h4v4H3v-4m6 1v2h12v-2H9"/></svg>',
326
+ 'subscript': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M16 7.41L11.41 12L16 16.59L14.59 18L10 13.41L5.41 18L4 16.59L8.59 12L4 7.41L5.41 6L10 10.59L14.59 6L16 7.41m5.85 13.62h-4.88v-1l.89-.8c.76-.65 1.32-1.19 1.7-1.63c.37-.44.56-.85.57-1.24a.898.898 0 0 0-.27-.7c-.18-.16-.47-.28-.86-.28c-.31 0-.58.06-.84.18l-.66.38l-.45-1.17c.27-.21.59-.39.98-.53s.82-.24 1.29-.24c.78.04 1.38.25 1.78.66c.4.41.62.93.62 1.57c-.01.56-.19 1.08-.54 1.55c-.34.47-.76.92-1.27 1.36l-.64.52v.02h2.58v1.35Z"/></svg>',
327
+ 'superscript': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M16 7.41L11.41 12L16 16.59L14.59 18L10 13.41L5.41 18L4 16.59L8.59 12L4 7.41L5.41 6L10 10.59L14.59 6L16 7.41M21.85 9h-4.88V8l.89-.82c.76-.64 1.32-1.18 1.7-1.63c.37-.44.56-.85.57-1.23a.884.884 0 0 0-.27-.7c-.18-.19-.47-.28-.86-.29c-.31.01-.58.07-.84.17l-.66.39l-.45-1.17c.27-.22.59-.39.98-.53S18.85 2 19.32 2c.78 0 1.38.2 1.78.61c.4.39.62.93.62 1.57c-.01.56-.19 1.08-.54 1.55c-.34.48-.76.93-1.27 1.36l-.64.52v.02h2.58V9Z"/></svg>',
328
+ 'bold': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M13.5 15.5H10v-3h3.5A1.5 1.5 0 0 1 15 14a1.5 1.5 0 0 1-1.5 1.5m-3.5-9h3A1.5 1.5 0 0 1 14.5 8A1.5 1.5 0 0 1 13 9.5h-3m5.6 1.29c.97-.68 1.65-1.79 1.65-2.79c0-2.26-1.75-4-4-4H7v14h7.04c2.1 0 3.71-1.7 3.71-3.79c0-1.52-.86-2.82-2.15-3.42Z"/></svg>',
329
+ 'italic': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4h-8Z"/></svg>',
330
+ 'strikeThrough': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M3 14h18v-2H3m2-8v3h5v3h4V7h5V4m-9 15h4v-3h-4v3Z"/></svg>',
331
+ 'underline': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M5 21h14v-2H5v2m7-4a6 6 0 0 0 6-6V3h-2.5v8a3.5 3.5 0 0 1-3.5 3.5A3.5 3.5 0 0 1 8.5 11V3H6v8a6 6 0 0 0 6 6Z"/></svg>',
332
+ 'insertHorizontalRule': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M0 24h24v-4H0v4Z"/></svg>',
333
+ 'removeFormat': '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M6 5v.18L8.82 8h2.4l-.72 1.68l2.1 2.1L14.21 8H20V5H6M3.27 5L2 6.27l6.97 6.97L6.5 19h3l1.57-3.66L16.73 21L18 19.73L3.55 5.27L3.27 5Z"/></svg>'
334
+ }
335
+
336
+ const items_dir = [
337
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M3 3h18v2H3V3m0 4h12v2H3V7m0 4h18v2H3v-2m0 4h12v2H3v-2m0 4h18v2H3v-2Z"/></svg>',
338
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M3 3h18v2H3V3m4 4h10v2H7V7m-4 4h18v2H3v-2m4 4h10v2H7v-2m-4 4h18v2H3v-2Z"/></svg>',
339
+ '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M3 3h18v2H3V3m6 4h12v2H9V7m-6 4h18v2H3v-2m6 4h12v2H9v-2m-6 4h18v2H3v-2Z"/></svg>'
340
+ ]
341
+
342
+ const menu = {
343
+ 'font': {
344
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M8.5 7h2L16 21h-2.4l-1.1-3H6.3l-1.1 3H3L8.5 7m-1.4 9h4.8L9.5 9.7L7.1 16M22 5v2h-3v3h-2V7h-3V5h3V2h2v3h3Z"/></svg>',
345
+ items: [
346
+ {text: 'd1', value: 'display-1'},
347
+ {text: 'd2', value: 'display-2'},
348
+ {text: 'd3', value: 'display-3'},
349
+ {text: 'head1', value: 'headline-1'},
350
+ {text: 'head2', value: 'headline-2'},
351
+ {text: 'head3', value: 'headline-3'},
352
+ {text: 'title-1', value: 'title-1'},
353
+ {text: 'title-2', value: 'title-2'},
354
+ {text: 'title-3', value: 'title-3'},
355
+ {text: 'body-1', value: 'body-1'},
356
+ {text: 'body-2', value: 'body-2'},
357
+ {text: 'body-3', value: 'body-3'},
358
+ {text: 'label-1', value: 'label-1'},
359
+ {text: 'label-2', value: 'label-2'},
360
+ {text: 'label-3', value: 'label-3'},
361
+ ]
362
+ },
363
+ 'header': {
364
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M3 4h2v6h4V4h2v14H9v-6H5v6H3V4m10 4h2.31l.32-3h2l-.32 3h2l.32-3h2l-.32 3H23v2h-1.9l-.2 2H23v2h-2.31l-.32 3h-2l.32-3h-2l-.32 3h-2l.32-3H13v-2h1.9l.2-2H13V8m4.1 2l-.2 2h2l.2-2h-2Z"/></svg>',
365
+ items: [
366
+ {text: 'H1', value: 'H1'},
367
+ {text: 'H2', value: 'H2'},
368
+ {text: 'H3', value: 'H3'},
369
+ {text: 'H4', value: 'H4'},
370
+ {text: 'H5', value: 'H5'},
371
+ {text: 'H6', value: 'H6'}
372
+ ]
373
+ },
374
+ 'color': {
375
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M19 11.5s-2 2.17-2 3.5a2 2 0 0 0 2 2a2 2 0 0 0 2-2c0-1.33-2-3.5-2-3.5M5.21 10L10 5.21L14.79 10m1.77-1.06L7.62 0L6.21 1.41l2.38 2.38l-5.15 5.15c-.59.56-.59 1.53 0 2.12l5.5 5.5c.29.29.68.44 1.06.44s.77-.15 1.06-.44l5.5-5.5c.59-.59.59-1.56 0-2.12Z"/></svg>',
376
+ items: [
377
+ {text: 'color', value: 'color-disabled-text'},
378
+ {text: 'color', value: 'color-one-text'},
379
+ {text: 'color', value: 'color-two-text'},
380
+ {text: 'color', value: 'color-three-text'},
381
+ {text: 'color', value: 'color-error-text'},
382
+ {text: 'color', value: 'color-info-text'},
383
+ {text: 'color', value: 'color-warning-text'},
384
+ {text: 'color', value: 'color-success-text'},
385
+ {text: 'color', value: 'color-white-text'},
386
+ {text: 'color', value: 'color-black-text'}
387
+ ]
388
+ },
389
+ 'background': {
390
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M18 4V3a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6h1v4H9v11a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1v-9h8V4h-3Z"/></svg>',
391
+ items: [
392
+ {text: 'color', value: 'color-one'},
393
+ {text: 'color', value: 'color-two'},
394
+ {text: 'color', value: 'color-three'},
395
+ {text: 'color', value: 'color-error'},
396
+ {text: 'color', value: 'color-info'},
397
+ {text: 'color', value: 'color-warning'},
398
+ {text: 'color', value: 'color-success'},
399
+ {text: 'color', value: 'color-black'},
400
+ {text: 'color', value: 'color-white'},
401
+ ]
402
+ }
403
+ }
404
+
405
+ if (props.uploadLink) {
406
+ items_handle['insertImage'] = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M5 3a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h9.09c-.06-.33-.09-.66-.09-1c0-.68.12-1.36.35-2H5l3.5-4.5l2.5 3l3.5-4.5l2.23 2.97c.97-.63 2.11-.97 3.27-.97c.34 0 .67.03 1 .09V5a2 2 0 0 0-2-2H5m14 13v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2Z"/></svg>'
407
+ items_handle['insertVideo'] = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path fill="currentColor" d="M17 10.5V7a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-3.5l4 4v-11l-4 4Z"/></svg>'
408
+ }
409
+
410
+ const is_object = computed(() => {
411
+ return props.modelValue && typeof props.modelValue === 'object' && 'text' in props.modelValue
412
+ })
413
+
414
+ const content = () => {
415
+ return editorContentRef.value?.innerHTML || ''
416
+ }
417
+
418
+ const addClass = (e) => {
419
+ if (selectElm.value) {
420
+ selectElm.value.classList = e.join(' ')
421
+ updateText()
422
+ }
423
+ }
424
+
425
+ const borderd = (el) => {
426
+ if (selectElm.value) {
427
+ selectElm.value.style.border = null
428
+ }
429
+ if (!el.style) {
430
+ el = el.parentNode
431
+ selectElm.value = el
432
+ }
433
+ if (!el.style) {
434
+ selectElm.value = null
435
+ return
436
+ }
437
+ if (el.style.border) {
438
+ el.style.border = null
439
+ selectElm.value = null
440
+ return
441
+ }
442
+ selectElm.value = el
443
+ el.style.border = '1px solid var(--color-one)'
444
+ }
445
+
446
+ const bordered = () => {
447
+ const a = getSelection()
448
+ currentPath.value = []
449
+
450
+ const f = (node) => {
451
+ if (node.classList && node.classList.contains('editor-content')) {
452
+ currentPath.value.reverse()
453
+ return
454
+ }
455
+ currentPath.value.push(node.parentNode)
456
+ f(node.parentNode)
457
+ }
458
+
459
+ if (a) {
460
+ currentPath.value = [a?.anchorNode]
461
+ f(a?.anchorNode)
462
+ if (a?.anchorNode.classList && a?.anchorNode.classList.contains('editor-content')) {
463
+ return
464
+ }
465
+ borderd(a?.anchorNode)
466
+ }
467
+ }
468
+
469
+ const deleteImage = (img, i) => {
470
+ axios.delete(props.uploadLink,
471
+ {
472
+ data: {link: img},
473
+ headers: props.headers
474
+ }
475
+ ).then(() => {
476
+ files.value.splice(i, 1)
477
+ updateText()
478
+ })
479
+ }
480
+
481
+ const handleImageForm = () => {
482
+ if (!getSelection() || !image.value || !img_alt.value) {
483
+ $toast('invalid_data', {type: 'error'})
484
+ return
485
+ }
486
+ let sel = getSelection()
487
+ sel.removeAllRanges()
488
+ sel.addRange(preSelected.value)
489
+ let url = '<img src="' + image.value[0] + '?w=' + img_width.value + '" alt="' + img_alt.value + '" width="' + img_width.value + '" />'
490
+ files.value.push(image.value[0])
491
+ document.execCommand('insertHTML', true, url)
492
+ showImg.value = false
493
+ }
494
+
495
+ const handleVideoForm = () => {
496
+ if (!getSelection() || !video.value) {
497
+ $toast('invalid_data', {type: 'error'})
498
+ return
499
+ }
500
+ let sel = getSelection()
501
+ sel.removeAllRanges()
502
+ sel.addRange(preSelected.value)
503
+ let url = '<video controls="1" src="' + video.value[0] + '" width="' + img_width.value + '" height="' + img_height.value + '"></video>'
504
+ files.value.push(video.value[0])
505
+ document.execCommand('insertHTML', true, url)
506
+ showVideo.value = false
507
+ }
508
+
509
+ const handleTableForm = () => {
510
+ if (!getSelection() || !table_form.value.row || !table_form.value.headers) {
511
+ $toast('invalid_data', {type: 'error'})
512
+ return
513
+ }
514
+ let sel = getSelection()
515
+ sel.removeAllRanges()
516
+ sel.addRange(preSelected.value)
517
+ let t = '<table><thead><tr>'
518
+ for (let i = 0; i < table_form.value.headers.length; i++) {
519
+ t += `<th>${table_form.value.headers[i]}</th>`
520
+ }
521
+ t += '</tr></thead><tbody>'
522
+ for (let i = 0; i < table_form.value.row; i++) {
523
+ t += '<tr>'
524
+ for (let i = 0; i < table_form.value.headers.length; i++) {
525
+ t += `<td></td>`
526
+ }
527
+ t += '</tr>'
528
+ }
529
+ t += '</tbody></table>'
530
+ document.execCommand('insertHTML', true, t)
531
+ showTable.value = false
532
+ }
533
+
534
+ const handlePreForm = async () => {
535
+ if (!getSelection() || !code.value || !lang.value) {
536
+ $toast('invalid_data', {type: 'error'})
537
+ return
538
+ }
539
+ let sel = getSelection()
540
+ sel.removeAllRanges()
541
+ sel.addRange(preSelected.value)
542
+ let url = `<div class="${$r.prefix}highlight" >`
543
+ if (code_name.value) {
544
+ url += `<div class="highlight-name title-3 font-weight-bold mb-3">${code_name.value}</div>`
545
+ }
546
+
547
+ url += `<div class="highlight-code highlight-lang-${lang.value}">${await highlight(code.value, lang.value)}</div></div>`
548
+ document.execCommand('insertHTML', true, url)
549
+ showPre.value = false
550
+ }
551
+
552
+ const handleForm = () => {
553
+ if (!getSelection() || !link.value) {
554
+ $toast('invalid_data', {type: 'error'})
555
+ return
556
+ }
557
+ let sel = getSelection()
558
+ sel.removeAllRanges()
559
+ sel.addRange(preSelected.value)
560
+ let url = '<a href="' + link.value.trim() + '"'
561
+ if (target.value) {
562
+ url += 'target="_blank" rel="nofollow"'
563
+ }
564
+ if (link.value.startsWith('#')) {
565
+ url += `id="${link.value.replace('#', '')}"`
566
+ }
567
+ url += '>' + sel + '</a>'
568
+
569
+ document.execCommand('insertHTML', true, url)
570
+ show.value = false
571
+ }
572
+
573
+ const getSelection = () => {
574
+ if (window.getSelection) {
575
+ return window.getSelection()
576
+ }
577
+ return false
578
+ }
579
+
580
+ const handleOpen = (e) => {
581
+ if (e === true) {
582
+ let sel = window.getSelection()
583
+ if (sel.rangeCount > 0) {
584
+ preSelected.value = sel.getRangeAt(0)
585
+ }
586
+ }
587
+ }
588
+
589
+ const addCss = (e) => {
590
+ let btn = e['menu']
591
+ e = e['item'].value
592
+ if (!getSelection()) {
593
+ return
594
+ }
595
+ let sel = getSelection()
596
+ sel.removeAllRanges()
597
+ sel.addRange(preSelected.value)
598
+ if (btn === 'header') {
599
+ document.execCommand('insertHTML', true, '<' + e.trim() + '>' + sel + '</' + e.trim() + '>')
600
+ return null
601
+ }
602
+ let selectedElement = sel.focusNode.parentNode
603
+ if (selectedElement.tagName === 'SPAN' && selectedElement.innerText === sel.toString()) {
604
+ let cls = selectedElement.classList.value.split(' ')
605
+ for (let c of cls) {
606
+ if (menu[btn]['items'].includes(c.trim())) {
607
+ selectedElement.classList.remove(c.trim())
608
+ }
609
+ }
610
+
611
+ selectedElement.classList.add(e)
612
+ } else {
613
+ let cls = ''
614
+ if (selectedElement.tagName === 'SPAN') {
615
+ cls = selectedElement.classList.value
616
+ }
617
+ e = cls + ' ' + e
618
+
619
+ document.execCommand('insertHTML', true, "<span class='" + e.trim() + "'>" + sel + '</span>')
620
+ }
621
+ }
622
+
623
+ const handle = (e) => {
624
+ let selectedElement = window.getSelection().focusNode.parentNode
625
+
626
+ if (selectedElement.tagName === e) {
627
+ format('formatBlock', '<div>')
628
+ } else {
629
+ if (e === 'createLink') {
630
+ link.value = null
631
+ target.value = false
632
+ handleOpen(true)
633
+ show.value = true
634
+ } else if (e === 'createTable') {
635
+ table_form.value = {}
636
+ handleOpen(true)
637
+ showTable.value = true
638
+ } else if (e === 'PRE') {
639
+ code.value = ''
640
+ lang.value = null
641
+ handleOpen(true)
642
+ showPre.value = true
643
+ } else if (e === 'insertImage') {
644
+ if (props.uploadLink) {
645
+ image.value = []
646
+ img_alt.value = null
647
+ handleOpen(true)
648
+ showImg.value = true
649
+ }
650
+ } else if (e === 'insertVideo') {
651
+ if (props.uploadLink) {
652
+ video.value = []
653
+ handleOpen(true)
654
+ showVideo.value = true
655
+ }
656
+ } else if (e === 'insertDIV') {
657
+ const d = document.createElement('div')
658
+ d.innerText = 'div'
659
+ if (selectElm.value) {
660
+ selectElm.value.appendChild(d)
661
+ } else {
662
+ selectedElement.appendChild(d)
663
+ }
664
+ } else if (e === 'insertLINE') {
665
+ const d = document.createElement('div')
666
+ d.innerText = 'line'
667
+ editorContentRef.value.appendChild(d)
668
+ } else {
669
+ format('formatBlock', e)
670
+ }
671
+ }
672
+ updateText()
673
+ }
674
+
675
+ const handle_dir = (e) => {
676
+ let name = ''
677
+ switch (e) {
678
+ case 0:
679
+ name = 'text-start'
680
+ break
681
+ case 1:
682
+ name = 'text-center'
683
+ break
684
+ case 2:
685
+ name = 'text-end'
686
+ break
687
+ }
688
+ let selectedElement = window.getSelection().focusNode
689
+ if (selectedElement === null) {
690
+ return null
691
+ }
692
+
693
+ let parentNode = selectedElement.parentNode
694
+
695
+ if (parentNode.classList.contains('editor-content')) {
696
+ selectedElement.classList.remove('text-start', 'text-center', 'text-end')
697
+ selectedElement.classList.add(name)
698
+ } else {
699
+ parentNode.classList.remove('text-start', 'text-center', 'text-end')
700
+ parentNode.classList.add(name)
701
+ }
702
+
703
+ updateText()
704
+ }
705
+
706
+ const updateText = () => {
707
+ emit('update:modelValue', {
708
+ text: editorContentRef.value?.innerHTML || '',
709
+ files: files.value
710
+ })
711
+ }
712
+
713
+ const format = (command, value) => {
714
+ if (command === 'removeFormat') {
715
+ document.execCommand('insertHTML', true, '<div>' + getSelection().toString() + '</div>')
716
+ } else {
717
+ document.execCommand(command, false, value)
718
+ }
719
+ }
720
+
721
+ const handlePaste = (e) => {
722
+ e.preventDefault()
723
+ const text = (e.originalEvent || e).clipboardData.getData('text/plain')
724
+ document.execCommand('insertHTML', false, text)
725
+ }
726
+
727
+ onMounted(() => {
728
+ format('defaultParagraphSeparator', 'br')
729
+ if (editorContentRef.value) {
730
+ editorContentRef.value.addEventListener('paste', handlePaste)
731
+ }
732
+ })
733
+
734
+ onBeforeUnmount(() => {
735
+ if (editorContentRef.value) {
736
+ editorContentRef.value.removeEventListener('paste', handlePaste)
737
+ }
738
+ })
739
+ </script>