@vc-shell/framework 1.1.43 → 1.1.45

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 (453) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/core/plugins/modularity/loader.ts +120 -74
  3. package/core/services/app-bar-mobile-buttons-service.ts +1 -1
  4. package/dist/core/plugins/modularity/loader.d.ts.map +1 -1
  5. package/dist/core/services/app-bar-mobile-buttons-service.d.ts +1 -1
  6. package/dist/core/services/app-bar-mobile-buttons-service.d.ts.map +1 -1
  7. package/dist/framework.js +33347 -295
  8. package/dist/index.css +1 -9
  9. package/dist/index.d.ts +0 -4
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/locales/de.json +0 -84
  12. package/dist/locales/en.json +0 -84
  13. package/dist/shared/components/blade-navigation/components/vc-blade-navigation/_internal/vc-mobile-back-button.vue.d.ts.map +1 -1
  14. package/dist/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.d.ts +1 -1
  15. package/dist/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.d.ts.map +1 -1
  16. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.d.ts.map +1 -1
  17. package/dist/shared/components/change-password-button/change-password-button.vue.d.ts.map +1 -1
  18. package/dist/shared/components/logout-button/logout-button.vue.d.ts.map +1 -1
  19. package/dist/shared/components/settings-menu-item/settings-menu-item.vue.d.ts.map +1 -1
  20. package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts +2 -2
  21. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts +6 -6
  22. package/dist/shared/modules/dynamic/pages/dynamic-blade-list.vue.d.ts.map +1 -1
  23. package/dist/tsconfig.tsbuildinfo +1 -1
  24. package/dist/ui/components/atoms/vc-hint/vc-hint.vue.d.ts.map +1 -1
  25. package/dist/ui/components/atoms/vc-icon/icons/MenuBurgerIcon.vue.d.ts.map +1 -1
  26. package/dist/ui/components/atoms/vc-icon/icons/index.d.ts +0 -26
  27. package/dist/ui/components/atoms/vc-icon/icons/index.d.ts.map +1 -1
  28. package/dist/ui/components/atoms/vc-icon/vc-bootstrap-icon.vue.d.ts.map +1 -1
  29. package/dist/ui/components/atoms/vc-icon/vc-fontawesome-icon.vue.d.ts.map +1 -1
  30. package/dist/ui/components/atoms/vc-icon/vc-icon.vue.d.ts.map +1 -1
  31. package/dist/ui/components/atoms/vc-icon/vc-lucide-icon.vue.d.ts +0 -5
  32. package/dist/ui/components/atoms/vc-icon/vc-lucide-icon.vue.d.ts.map +1 -1
  33. package/dist/ui/components/atoms/vc-icon/vc-material-icon.vue.d.ts +0 -20
  34. package/dist/ui/components/atoms/vc-icon/vc-material-icon.vue.d.ts.map +1 -1
  35. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts.map +1 -1
  36. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-button.vue.d.ts +36 -0
  37. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-button.vue.d.ts.map +1 -0
  38. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-toolbar.vue.d.ts +17 -0
  39. package/dist/ui/components/molecules/vc-editor/_internal/vc-editor-toolbar.vue.d.ts.map +1 -0
  40. package/dist/ui/components/molecules/vc-editor/vc-editor.vue.d.ts +16 -2381
  41. package/dist/ui/components/molecules/vc-editor/vc-editor.vue.d.ts.map +1 -1
  42. package/dist/ui/components/molecules/vc-form/vc-form.vue.d.ts.map +1 -1
  43. package/dist/ui/components/molecules/vc-input-currency/vc-input-currency.vue.d.ts +1 -1
  44. package/dist/ui/components/molecules/vc-input-currency/vc-input-currency.vue.d.ts.map +1 -1
  45. package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.vue.d.ts +1 -1
  46. package/dist/ui/components/molecules/vc-pagination/vc-pagination.vue.d.ts.map +1 -1
  47. package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue.d.ts.map +1 -1
  48. package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts.map +1 -1
  49. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
  50. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
  51. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts.map +1 -1
  52. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-desktop.vue.d.ts.map +1 -1
  53. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-mobile.vue.d.ts.map +1 -1
  54. package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
  55. package/dist/ui/components/organisms/vc-gallery/_internal/vc-gallery-item/vc-gallery-item.vue.d.ts +2 -2
  56. package/dist/ui/components/organisms/vc-gallery/vc-gallery.vue.d.ts +2 -2
  57. package/dist/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue.d.ts.map +1 -1
  58. package/dist/ui/components/organisms/vc-table/_internal/vc-table-header/vc-table-header.vue.d.ts.map +1 -1
  59. package/dist/vendor-boolbase-Cp9L0GAZ.js +25 -0
  60. package/dist/vendor-cheerio-HN9zIPZn.js +3135 -0
  61. package/dist/vendor-cheerio-select-5Ry0HvBq.js +306 -0
  62. package/dist/vendor-core-js-l0sNRNKZ.js +1 -0
  63. package/dist/vendor-css-select-DRIZ9kfZ.js +966 -0
  64. package/dist/vendor-css-what-DuPJ1HEF.js +448 -0
  65. package/dist/vendor-cypress-signalr-mock-BKdBJpdt.js +778 -0
  66. package/dist/vendor-date-fns-515YWkk-.js +6724 -0
  67. package/dist/vendor-dom-serializer-nQMsqjYW.js +286 -0
  68. package/dist/vendor-dom7-CJLPMwy5.js +941 -0
  69. package/dist/vendor-domelementtype-CjSzQey5.js +53 -0
  70. package/dist/vendor-domhandler-9z8cS16a.js +484 -0
  71. package/dist/vendor-dompurify-CRFzu7ib.js +1336 -0
  72. package/dist/vendor-domutils-Bc-Opz-v.js +981 -0
  73. package/dist/vendor-entities-Bfsx4xOQ.js +636 -0
  74. package/dist/vendor-floating-ui-core-wV8u8QP4.js +511 -0
  75. package/dist/vendor-floating-ui-dom-DDnRPs17.js +706 -0
  76. package/dist/vendor-floating-ui-utils-OMIFy1QU.js +296 -0
  77. package/dist/vendor-floating-ui-vue-D-tCDAMm.js +167 -0
  78. package/dist/vendor-fontsource-plus-jakarta-sans.css +1 -0
  79. package/dist/vendor-headlessui-vue-CY9FRgTb.js +83 -0
  80. package/dist/vendor-htmlparser2-B1dhFPOs.js +1426 -0
  81. package/dist/vendor-iconify-vue-DfRGgyNu.js +1840 -0
  82. package/dist/vendor-intlify-core-base-BuknsFQe.js +1876 -0
  83. package/dist/vendor-intlify-message-compiler-CuOQDWx1.js +1508 -0
  84. package/dist/vendor-intlify-shared-Cz4YRMuC.js +241 -0
  85. package/dist/vendor-iso-639-1-BJCk9DvE.js +819 -0
  86. package/dist/vendor-linkify-it-CKUf4vsc.js +830 -0
  87. package/dist/vendor-linkifyjs-BfyGgbCh.js +1756 -0
  88. package/dist/vendor-lodash-es-BySUOlwf.js +18333 -0
  89. package/dist/vendor-markdown-it-D-apazHa.js +6000 -0
  90. package/dist/vendor-markdown-it-task-lists-rxMVH6Ku.js +131 -0
  91. package/dist/vendor-mdurl-BNh2CCgT.js +537 -0
  92. package/dist/vendor-microsoft-applicationinsights-analytics-js-kG3lLg8X.js +1275 -0
  93. package/dist/vendor-microsoft-applicationinsights-cfgsync-js-C0uQkiQq.js +591 -0
  94. package/dist/vendor-microsoft-applicationinsights-channel-js-Dyd_PXA3.js +2153 -0
  95. package/dist/vendor-microsoft-applicationinsights-common-CfmP1_Qr.js +2470 -0
  96. package/dist/vendor-microsoft-applicationinsights-core-js-Cq4YSEvZ.js +6589 -0
  97. package/dist/vendor-microsoft-applicationinsights-dependencies-js-C56OBFr4.js +1510 -0
  98. package/dist/vendor-microsoft-applicationinsights-properties-js-CBJTBawx.js +761 -0
  99. package/dist/vendor-microsoft-applicationinsights-shims-CX8sJgar.js +70 -0
  100. package/dist/vendor-microsoft-applicationinsights-web-pim2ri-g.js +667 -0
  101. package/dist/vendor-microsoft-dynamicproto-js-CFBBUu9p.js +520 -0
  102. package/dist/vendor-microsoft-signalr-dUnlRsGm.js +3339 -0
  103. package/dist/vendor-moment-Mki5YqAR.js +5679 -0
  104. package/dist/vendor-nevware21-ts-async-CLMApQ9E.js +395 -0
  105. package/dist/vendor-nevware21-ts-utils-e8v8Jty3.js +1160 -0
  106. package/dist/vendor-normalize-css.css +1 -0
  107. package/dist/vendor-nth-check-Bx8TxtJt.js +157 -0
  108. package/dist/vendor-orderedmap-dGG6uMFJ.js +137 -0
  109. package/dist/vendor-parse5-Bt2NhSzR.js +8432 -0
  110. package/dist/vendor-parse5-htmlparser2-tree-adapter-BUUtKzf8.js +216 -0
  111. package/dist/vendor-popperjs-core-Cr2byIky.js +1790 -0
  112. package/dist/vendor-prettier-B4PaeWRQ.js +98 -0
  113. package/dist/vendor-prosemirror-commands-BH9lWGpW.js +561 -0
  114. package/dist/vendor-prosemirror-dropcursor-CeyPcxrA.js +146 -0
  115. package/dist/vendor-prosemirror-gapcursor-U8UoUJII.js +236 -0
  116. package/dist/vendor-prosemirror-history-BDaJkvNx.js +414 -0
  117. package/dist/vendor-prosemirror-keymap-BbWvIWmH.js +128 -0
  118. package/dist/vendor-prosemirror-markdown-gB0PXBbz.js +866 -0
  119. package/dist/vendor-prosemirror-model-BZu3WVcD.js +3463 -0
  120. package/dist/vendor-prosemirror-schema-list-Bl9NpKA7.js +158 -0
  121. package/dist/vendor-prosemirror-state-BvL9Pxph.js +1003 -0
  122. package/dist/vendor-prosemirror-tables-17qAnviK.js +2159 -0
  123. package/dist/vendor-prosemirror-transform-CE9VV3qg.js +2156 -0
  124. package/dist/vendor-prosemirror-view-CU2WTHT7.js +5811 -0
  125. package/dist/vendor-punycode-js-iAs5RxMf.js +441 -0
  126. package/dist/vendor-rope-sequence-BdXDKoGt.js +207 -0
  127. package/dist/vendor-semver-CVLMK-S4.js +2702 -0
  128. package/dist/vendor-ssr-window-s6OpKa3O.js +150 -0
  129. package/dist/vendor-swiper-CdiyNHVt.js +5679 -0
  130. package/dist/vendor-swiper.css +1 -0
  131. package/dist/vendor-tanstack-virtual-core-l0sNRNKZ.js +1 -0
  132. package/dist/vendor-tanstack-vue-virtual-l0sNRNKZ.js +1 -0
  133. package/dist/vendor-tippy-js-DWFe2TfK.js +1647 -0
  134. package/dist/vendor-tiptap-core-NfwGfaQk.js +4910 -0
  135. package/dist/vendor-tiptap-extension-blockquote-jmWBTtsI.js +57 -0
  136. package/dist/vendor-tiptap-extension-bold-p5frh4ak.js +97 -0
  137. package/dist/vendor-tiptap-extension-bubble-menu-KUhZSfrs.js +218 -0
  138. package/dist/vendor-tiptap-extension-bullet-list-COmZRoSB.js +73 -0
  139. package/dist/vendor-tiptap-extension-code-block-DyTARZss.js +221 -0
  140. package/dist/vendor-tiptap-extension-code-jVv6CXpX.js +75 -0
  141. package/dist/vendor-tiptap-extension-document-DssuotYs.js +13 -0
  142. package/dist/vendor-tiptap-extension-dropcursor-BoO0Qv91.js +26 -0
  143. package/dist/vendor-tiptap-extension-floating-menu-CrO8CN5w.js +165 -0
  144. package/dist/vendor-tiptap-extension-gapcursor-KpsWEoMD.js +30 -0
  145. package/dist/vendor-tiptap-extension-hard-break-ldOzhSvf.js +68 -0
  146. package/dist/vendor-tiptap-extension-heading-CKz2llX0.js +77 -0
  147. package/dist/vendor-tiptap-extension-history-DeKZ2VQ9.js +48 -0
  148. package/dist/vendor-tiptap-extension-horizontal-rule-CAjWRyDS.js +92 -0
  149. package/dist/vendor-tiptap-extension-image-ZagcEYuk.js +76 -0
  150. package/dist/vendor-tiptap-extension-italic-CM4xdznY.js +96 -0
  151. package/dist/vendor-tiptap-extension-link-Z-AMC4Ri.js +414 -0
  152. package/dist/vendor-tiptap-extension-list-item-BJi5QpXc.js +37 -0
  153. package/dist/vendor-tiptap-extension-ordered-list-C_TMrfBE.js +97 -0
  154. package/dist/vendor-tiptap-extension-paragraph-CQw0E0Au.js +39 -0
  155. package/dist/vendor-tiptap-extension-placeholder-BBNVKfa_.js +66 -0
  156. package/dist/vendor-tiptap-extension-strike-DUyMYX1Z.js +79 -0
  157. package/dist/vendor-tiptap-extension-table-cell-CoDIMPA5.js +47 -0
  158. package/dist/vendor-tiptap-extension-table-header-DvbGHnmw.js +47 -0
  159. package/dist/vendor-tiptap-extension-table-row-D1uqN5Aj.js +26 -0
  160. package/dist/vendor-tiptap-extension-table-tKS4MOM4.js +354 -0
  161. package/dist/vendor-tiptap-extension-text-DtRBhKB2.js +12 -0
  162. package/dist/vendor-tiptap-extension-underline-DqaSFp_P.js +50 -0
  163. package/dist/vendor-tiptap-markdown-7-PCADTU.js +1017 -0
  164. package/dist/vendor-tiptap-pm-l0sNRNKZ.js +1 -0
  165. package/dist/vendor-tiptap-starter-kit-CDSV_Zuu.js +88 -0
  166. package/dist/vendor-tiptap-vue-3-DZg2fjq_.js +268 -0
  167. package/dist/vendor-truncate-html-3qQY0Djo.js +196 -0
  168. package/dist/vendor-uc-micro-jjt6LQ65.js +23 -0
  169. package/dist/vendor-vee-validate-i18n-v_gHjRmD.js +154 -0
  170. package/dist/vendor-vee-validate-rules-DzV3VY3N.js +536 -0
  171. package/dist/vendor-vue-currency-input-DGAkEFBO.js +545 -0
  172. package/dist/vendor-vue-demi-l0sNRNKZ.js +1 -0
  173. package/dist/vendor-vue-devtools-api-DXYR8qBG.js +169 -0
  174. package/dist/vendor-vue-i18n-Co752uk3.js +1897 -0
  175. package/dist/vendor-vue3-application-insights-CYWFCr_J.js +119 -0
  176. package/dist/vendor-vue3-touch-events-BJEAiSa3.js +416 -0
  177. package/dist/vendor-vuepic-vue-datepicker-BSWXRSiu.js +5019 -0
  178. package/dist/vendor-vuepic-vue-datepicker.css +1 -0
  179. package/dist/vendor-vueuse-components-l1bL12mE.js +339 -0
  180. package/dist/vendor-vueuse-core-DGcJOmwG.js +7743 -0
  181. package/dist/vendor-vueuse-shared-_mOXsFuM.js +1568 -0
  182. package/dist/vendor-w3c-keyname-BOm2dtJm.js +121 -0
  183. package/package.json +22 -11
  184. package/shared/components/blade-navigation/components/vc-blade-navigation/_internal/vc-mobile-back-button.vue +3 -3
  185. package/shared/components/blade-navigation/components/vc-blade-view/vc-blade-view.ts +2 -1
  186. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.ts +1 -0
  187. package/shared/components/change-password-button/change-password-button.vue +1 -2
  188. package/shared/components/logout-button/logout-button.vue +1 -2
  189. package/shared/components/notifications/components/notification-container/index.ts +1 -1
  190. package/shared/components/notifications/core/notification.ts +1 -1
  191. package/shared/components/settings-menu-item/settings-menu-item.vue +1 -0
  192. package/shared/components/sidebar/sidebar.vue +2 -2
  193. package/shared/modules/dynamic/pages/dynamic-blade-list.vue +2 -1
  194. package/ui/components/atoms/vc-hint/vc-hint.vue +2 -0
  195. package/ui/components/atoms/vc-icon/composables/use-icon.ts +1 -1
  196. package/ui/components/atoms/vc-icon/icons/MenuBurgerIcon.vue +18 -14
  197. package/ui/components/atoms/vc-icon/icons/index.ts +1 -27
  198. package/ui/components/atoms/vc-icon/vc-bootstrap-icon.vue +7 -11
  199. package/ui/components/atoms/vc-icon/vc-fontawesome-icon.vue +37 -31
  200. package/ui/components/atoms/vc-icon/vc-icon-examples.vue +1 -1
  201. package/ui/components/atoms/vc-icon/vc-icon.stories.ts +4 -5
  202. package/ui/components/atoms/vc-icon/vc-icon.vue +33 -163
  203. package/ui/components/atoms/vc-icon/vc-lucide-icon.vue +22 -70
  204. package/ui/components/atoms/vc-icon/vc-material-icon.vue +28 -59
  205. package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +2 -3
  206. package/ui/components/molecules/vc-editor/_internal/vc-editor-button.vue +103 -0
  207. package/ui/components/molecules/vc-editor/_internal/vc-editor-toolbar.vue +252 -0
  208. package/ui/components/molecules/vc-editor/vc-editor.stories.ts +1 -4
  209. package/ui/components/molecules/vc-editor/vc-editor.vue +666 -360
  210. package/ui/components/molecules/vc-form/vc-form.vue +7 -5
  211. package/ui/components/molecules/vc-input/vc-input.vue +1 -1
  212. package/ui/components/molecules/vc-pagination/vc-pagination.vue +4 -17
  213. package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarMobileActions.vue +1 -1
  214. package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue +1 -3
  215. package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +1 -4
  216. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +1 -3
  217. package/ui/components/organisms/vc-app/vc-app.backupsb.ts +214 -214
  218. package/ui/components/organisms/vc-app/vc-app.vue +3 -5
  219. package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +3 -10
  220. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/mobile/vc-blade-toolbar-mobile.vue +1 -1
  221. package/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-desktop.vue +2 -2
  222. package/ui/components/organisms/vc-blade/_internal/vc-blade-widget-container/_internal/vc-widget-container-mobile.vue +2 -2
  223. package/ui/components/organisms/vc-blade/vc-blade.vue +4 -5
  224. package/ui/components/organisms/vc-table/_internal/vc-table-filter/vc-table-filter.vue +1 -3
  225. package/ui/components/organisms/vc-table/_internal/vc-table-header/vc-table-header.vue +1 -2
  226. package/ui/components/organisms/vc-table/composables/useTableState.ts +5 -5
  227. package/dist/apl-B2DGVGxc.js +0 -76
  228. package/dist/asciiarmor-2LVJmxlE.js +0 -34
  229. package/dist/asn1-jKiBa2Ya.js +0 -95
  230. package/dist/asterisk-DS281yxp.js +0 -271
  231. package/dist/brainfuck-C_p9pTT8.js +0 -34
  232. package/dist/clike-DGTaUp48.js +0 -620
  233. package/dist/clojure-CCKyeQKf.js +0 -800
  234. package/dist/cmake-CuaCgAKt.js +0 -28
  235. package/dist/cobol-BlTKFDRj.js +0 -72
  236. package/dist/coffeescript-BVCvwO8I.js +0 -179
  237. package/dist/commonlisp-D_kxz07b.js +0 -75
  238. package/dist/crystal-D309uH6_.js +0 -217
  239. package/dist/css-BkF-NPzE.js +0 -1553
  240. package/dist/cypher-BMq4Fwjl.js +0 -68
  241. package/dist/d-BZcgY6La.js +0 -127
  242. package/dist/diff-Cg9d_RX2.js +0 -18
  243. package/dist/dockerfile-DIy8NleC.js +0 -194
  244. package/dist/dtd-CtLokQ-U.js +0 -84
  245. package/dist/dylan-QYeExnWK.js +0 -234
  246. package/dist/ebnf-DUPDuY4r.js +0 -78
  247. package/dist/ecl-CiXN-g_D.js +0 -121
  248. package/dist/eiffel-yQhjl4T1.js +0 -110
  249. package/dist/elm-CNT9vbN0.js +0 -108
  250. package/dist/erlang-CFOYdy9e.js +0 -487
  251. package/dist/factor-DDOC7X6P.js +0 -65
  252. package/dist/fcl-CPC2WYrI.js +0 -103
  253. package/dist/forth-BmxRyE9S.js +0 -60
  254. package/dist/fortran-9bvPyrOW.js +0 -442
  255. package/dist/gas-cpmYfFX2.js +0 -183
  256. package/dist/gherkin-CJuwpceU.js +0 -34
  257. package/dist/groovy-DZeT_VM-.js +0 -146
  258. package/dist/haskell-Bvt3Qq1t.js +0 -375
  259. package/dist/haxe-70NVW1pR.js +0 -359
  260. package/dist/http-D9LttvKF.js +0 -44
  261. package/dist/idl-B6TRFYjl.js +0 -947
  262. package/dist/index-4DWvmoYg.js +0 -71
  263. package/dist/index-52o7mJaX.js +0 -156
  264. package/dist/index-B0KatioT.js +0 -98
  265. package/dist/index-BP3W8zuk.js +0 -268
  266. package/dist/index-BykT5L1A.js +0 -148134
  267. package/dist/index-CfXo9hsG.js +0 -75
  268. package/dist/index-Ch37pBUt.js +0 -308
  269. package/dist/index-D2KGkAYT.js +0 -93
  270. package/dist/index-D83zQom_.js +0 -58
  271. package/dist/index-DuQrVLbu.js +0 -134
  272. package/dist/index-_fdMid5h.js +0 -288
  273. package/dist/index-a1wO-owY.js +0 -545
  274. package/dist/index-crMpNSFe.js +0 -611
  275. package/dist/index-dmBRpHHY.js +0 -137
  276. package/dist/index-kBdB14Fz.js +0 -341
  277. package/dist/index-uBhy41le.js +0 -249
  278. package/dist/index-zZrijNsr.js +0 -299
  279. package/dist/javascript-C2yteZeJ.js +0 -691
  280. package/dist/jinja2-DnB6dQmV.js +0 -154
  281. package/dist/julia-DpvXAuO6.js +0 -241
  282. package/dist/livescript-CanGTf8u.js +0 -272
  283. package/dist/lua-XplVlWi_.js +0 -217
  284. package/dist/mathematica-jaRHnSxC.js +0 -35
  285. package/dist/mbox-BctzC1hL.js +0 -76
  286. package/dist/mirc-CFBPAOaF.js +0 -72
  287. package/dist/mllike-BSnXJBGA.js +0 -272
  288. package/dist/modelica-vUgVs--1.js +0 -93
  289. package/dist/mscgen-Cpl0NYLN.js +0 -104
  290. package/dist/mumps-CQoS1kWX.js +0 -25
  291. package/dist/nginx-zDPm3Z74.js +0 -89
  292. package/dist/nsis-fePjrhq7.js +0 -62
  293. package/dist/ntriples-CsNjv2QF.js +0 -79
  294. package/dist/octave-C8PmmSRH.js +0 -143
  295. package/dist/oz-Ce8aN8oE.js +0 -151
  296. package/dist/pascal-De0D6mP7.js +0 -77
  297. package/dist/perl-B4bSCe1C.js +0 -915
  298. package/dist/pig-D24Z8EXi.js +0 -54
  299. package/dist/powershell-DkYVfTzP.js +0 -249
  300. package/dist/properties-Dn9wna3M.js +0 -26
  301. package/dist/protobuf-BPIjwpzm.js +0 -49
  302. package/dist/pug-CwAQJzGR.js +0 -248
  303. package/dist/puppet-nyd4dhjf.js +0 -45
  304. package/dist/python-BkR3uSy8.js +0 -313
  305. package/dist/q-DXjKs-tC.js +0 -83
  306. package/dist/r-LKEuhEGI.js +0 -104
  307. package/dist/rpm-IznJm2Xc.js +0 -57
  308. package/dist/ruby-CcYfvIk6.js +0 -228
  309. package/dist/sas-7E8yHoCW.js +0 -105
  310. package/dist/scheme-DjibxsNh.js +0 -124
  311. package/dist/shared/modules/dynamic/components/fields/storybook/common/args.d.ts +0 -113
  312. package/dist/shared/modules/dynamic/components/fields/storybook/common/args.d.ts.map +0 -1
  313. package/dist/shared/modules/dynamic/components/fields/storybook/common/templates.d.ts +0 -3
  314. package/dist/shared/modules/dynamic/components/fields/storybook/common/templates.d.ts.map +0 -1
  315. package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts +0 -102
  316. package/dist/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.d.ts.map +0 -1
  317. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceHighlighter.d.ts +0 -4
  318. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceHighlighter.d.ts.map +0 -1
  319. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceTransform.d.ts +0 -3
  320. package/dist/shared/modules/dynamic/components/fields/storybook/utils/sourceTransform.d.ts.map +0 -1
  321. package/dist/shell-C0C2sNA_.js +0 -182
  322. package/dist/sieve-Bwz7vjP5.js +0 -72
  323. package/dist/simple-mode-B0dvCdAA.js +0 -89
  324. package/dist/smalltalk-Bhddl2pB.js +0 -48
  325. package/dist/solr-BNlsLglM.js +0 -41
  326. package/dist/sparql-FarWu_Gb.js +0 -197
  327. package/dist/spreadsheet-C-cy4P5N.js +0 -49
  328. package/dist/sql-CfG5lQ3l.js +0 -282
  329. package/dist/stex-Du4h4KAU.js +0 -129
  330. package/dist/stylus-CAdqWld3.js +0 -250
  331. package/dist/swift-DSxqR9R6.js +0 -230
  332. package/dist/tcl-xfoLljhY.js +0 -81
  333. package/dist/textile-D1AWE-pc.js +0 -295
  334. package/dist/tiddlywiki-5wqsXtSk.js +0 -155
  335. package/dist/tiki-__Kn3CeS.js +0 -181
  336. package/dist/toml-BHiuTcfn.js +0 -49
  337. package/dist/troff-D2UO-fKf.js +0 -35
  338. package/dist/ttcn-Bsa4sfRm.js +0 -123
  339. package/dist/ttcn-cfg-Bac_acMi.js +0 -88
  340. package/dist/turtle-xwJUxoPV.js +0 -80
  341. package/dist/ui/components/atoms/vc-icon/icons/AppWindowIcon.vue.d.ts +0 -7
  342. package/dist/ui/components/atoms/vc-icon/icons/AppWindowIcon.vue.d.ts.map +0 -1
  343. package/dist/ui/components/atoms/vc-icon/icons/ArrowLeftIcon.vue.d.ts +0 -7
  344. package/dist/ui/components/atoms/vc-icon/icons/ArrowLeftIcon.vue.d.ts.map +0 -1
  345. package/dist/ui/components/atoms/vc-icon/icons/ArrowRightIcon.vue.d.ts +0 -7
  346. package/dist/ui/components/atoms/vc-icon/icons/ArrowRightIcon.vue.d.ts.map +0 -1
  347. package/dist/ui/components/atoms/vc-icon/icons/BellIcon.vue.d.ts +0 -7
  348. package/dist/ui/components/atoms/vc-icon/icons/BellIcon.vue.d.ts.map +0 -1
  349. package/dist/ui/components/atoms/vc-icon/icons/ChevronDownIcon.vue.d.ts +0 -7
  350. package/dist/ui/components/atoms/vc-icon/icons/ChevronDownIcon.vue.d.ts.map +0 -1
  351. package/dist/ui/components/atoms/vc-icon/icons/ChevronLeftIcon.vue.d.ts +0 -7
  352. package/dist/ui/components/atoms/vc-icon/icons/ChevronLeftIcon.vue.d.ts.map +0 -1
  353. package/dist/ui/components/atoms/vc-icon/icons/ChevronRightIcon.vue.d.ts +0 -7
  354. package/dist/ui/components/atoms/vc-icon/icons/ChevronRightIcon.vue.d.ts.map +0 -1
  355. package/dist/ui/components/atoms/vc-icon/icons/ChevronUpIcon.vue.d.ts +0 -7
  356. package/dist/ui/components/atoms/vc-icon/icons/ChevronUpIcon.vue.d.ts.map +0 -1
  357. package/dist/ui/components/atoms/vc-icon/icons/CircleDotsIcon.vue.d.ts +0 -7
  358. package/dist/ui/components/atoms/vc-icon/icons/CircleDotsIcon.vue.d.ts.map +0 -1
  359. package/dist/ui/components/atoms/vc-icon/icons/CrossSignIcon.vue.d.ts +0 -7
  360. package/dist/ui/components/atoms/vc-icon/icons/CrossSignIcon.vue.d.ts.map +0 -1
  361. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowLeftIcon.vue.d.ts +0 -7
  362. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowLeftIcon.vue.d.ts.map +0 -1
  363. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowRightIcon.vue.d.ts +0 -7
  364. package/dist/ui/components/atoms/vc-icon/icons/DoubleArrowRightIcon.vue.d.ts.map +0 -1
  365. package/dist/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue.d.ts +0 -7
  366. package/dist/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue.d.ts.map +0 -1
  367. package/dist/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue.d.ts +0 -7
  368. package/dist/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue.d.ts.map +0 -1
  369. package/dist/ui/components/atoms/vc-icon/icons/LogoutIcon.vue.d.ts +0 -7
  370. package/dist/ui/components/atoms/vc-icon/icons/LogoutIcon.vue.d.ts.map +0 -1
  371. package/dist/ui/components/atoms/vc-icon/icons/MinusSignIcon.vue.d.ts +0 -7
  372. package/dist/ui/components/atoms/vc-icon/icons/MinusSignIcon.vue.d.ts.map +0 -1
  373. package/dist/ui/components/atoms/vc-icon/icons/OffersIcon.vue.d.ts +0 -7
  374. package/dist/ui/components/atoms/vc-icon/icons/OffersIcon.vue.d.ts.map +0 -1
  375. package/dist/ui/components/atoms/vc-icon/icons/OrdersIcon.vue.d.ts +0 -7
  376. package/dist/ui/components/atoms/vc-icon/icons/OrdersIcon.vue.d.ts.map +0 -1
  377. package/dist/ui/components/atoms/vc-icon/icons/PeopleIcon.vue.d.ts +0 -7
  378. package/dist/ui/components/atoms/vc-icon/icons/PeopleIcon.vue.d.ts.map +0 -1
  379. package/dist/ui/components/atoms/vc-icon/icons/PlusSignIcon.vue.d.ts +0 -7
  380. package/dist/ui/components/atoms/vc-icon/icons/PlusSignIcon.vue.d.ts.map +0 -1
  381. package/dist/ui/components/atoms/vc-icon/icons/ProductsIcon.vue.d.ts +0 -7
  382. package/dist/ui/components/atoms/vc-icon/icons/ProductsIcon.vue.d.ts.map +0 -1
  383. package/dist/ui/components/atoms/vc-icon/icons/ProfileIcon.vue.d.ts +0 -7
  384. package/dist/ui/components/atoms/vc-icon/icons/ProfileIcon.vue.d.ts.map +0 -1
  385. package/dist/ui/components/atoms/vc-icon/icons/SearchIcon.vue.d.ts +0 -7
  386. package/dist/ui/components/atoms/vc-icon/icons/SearchIcon.vue.d.ts.map +0 -1
  387. package/dist/ui/components/atoms/vc-icon/icons/SettingsBoltIcon.vue.d.ts +0 -7
  388. package/dist/ui/components/atoms/vc-icon/icons/SettingsBoltIcon.vue.d.ts.map +0 -1
  389. package/dist/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue.d.ts +0 -7
  390. package/dist/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue.d.ts.map +0 -1
  391. package/dist/ui/components/atoms/vc-icon/icons/VendorSwitchIcon.vue.d.ts +0 -7
  392. package/dist/ui/components/atoms/vc-icon/icons/VendorSwitchIcon.vue.d.ts.map +0 -1
  393. package/dist/ui/components/atoms/vc-icon/icons/VertDotsIcon.vue.d.ts +0 -7
  394. package/dist/ui/components/atoms/vc-icon/icons/VertDotsIcon.vue.d.ts.map +0 -1
  395. package/dist/vb-c2kQGd6-.js +0 -74
  396. package/dist/vbscript-1f_Dhg5H.js +0 -324
  397. package/dist/velocity-DJd0pTTC.js +0 -96
  398. package/dist/verilog-CiS1jyi5.js +0 -262
  399. package/dist/vhdl-T9HkrbI2.js +0 -106
  400. package/dist/webidl-CjfDENEo.js +0 -155
  401. package/dist/xquery-BUQdORAS.js +0 -422
  402. package/dist/yacas-C0absKBh.js +0 -73
  403. package/dist/z80-Pki2zAjW.js +0 -61
  404. package/shared/modules/dynamic/components/fields/storybook/Button.stories.ts +0 -186
  405. package/shared/modules/dynamic/components/fields/storybook/Card.stories.ts +0 -175
  406. package/shared/modules/dynamic/components/fields/storybook/Checkbox.stories.ts +0 -185
  407. package/shared/modules/dynamic/components/fields/storybook/ContentField.stories.ts +0 -245
  408. package/shared/modules/dynamic/components/fields/storybook/EditorField.stories.ts +0 -192
  409. package/shared/modules/dynamic/components/fields/storybook/Fieldset.stories.ts +0 -347
  410. package/shared/modules/dynamic/components/fields/storybook/GalleryField.stories.ts +0 -239
  411. package/shared/modules/dynamic/components/fields/storybook/ImageField.stories.ts +0 -186
  412. package/shared/modules/dynamic/components/fields/storybook/InputCurrency.stories.ts +0 -281
  413. package/shared/modules/dynamic/components/fields/storybook/InputField.stories.ts +0 -312
  414. package/shared/modules/dynamic/components/fields/storybook/MultivalueField.stories.ts +0 -361
  415. package/shared/modules/dynamic/components/fields/storybook/RadioButtonGroup.stories.ts +0 -224
  416. package/shared/modules/dynamic/components/fields/storybook/RatingField.stories.ts +0 -131
  417. package/shared/modules/dynamic/components/fields/storybook/SelectField.stories.ts +0 -666
  418. package/shared/modules/dynamic/components/fields/storybook/StatusField.stories.ts +0 -202
  419. package/shared/modules/dynamic/components/fields/storybook/SwitchField.stories.ts +0 -178
  420. package/shared/modules/dynamic/components/fields/storybook/TextareaField.stories.ts +0 -203
  421. package/shared/modules/dynamic/components/fields/storybook/VideoField.stories.ts +0 -92
  422. package/shared/modules/dynamic/components/fields/storybook/common/args.ts +0 -130
  423. package/shared/modules/dynamic/components/fields/storybook/common/templates.ts +0 -8
  424. package/shared/modules/dynamic/components/fields/storybook/pages/DynamicRender.ts +0 -54
  425. package/shared/modules/dynamic/components/fields/storybook/utils/sourceHighlighter.ts +0 -16
  426. package/shared/modules/dynamic/components/fields/storybook/utils/sourceTransform.ts +0 -41
  427. package/ui/components/atoms/vc-icon/icons/AppWindowIcon.vue +0 -15
  428. package/ui/components/atoms/vc-icon/icons/ArrowLeftIcon.vue +0 -20
  429. package/ui/components/atoms/vc-icon/icons/ArrowRightIcon.vue +0 -13
  430. package/ui/components/atoms/vc-icon/icons/BellIcon.vue +0 -14
  431. package/ui/components/atoms/vc-icon/icons/ChevronDownIcon.vue +0 -13
  432. package/ui/components/atoms/vc-icon/icons/ChevronLeftIcon.vue +0 -13
  433. package/ui/components/atoms/vc-icon/icons/ChevronRightIcon.vue +0 -13
  434. package/ui/components/atoms/vc-icon/icons/ChevronUpIcon.vue +0 -13
  435. package/ui/components/atoms/vc-icon/icons/CircleDotsIcon.vue +0 -16
  436. package/ui/components/atoms/vc-icon/icons/CrossSignIcon.vue +0 -20
  437. package/ui/components/atoms/vc-icon/icons/DoubleArrowLeftIcon.vue +0 -14
  438. package/ui/components/atoms/vc-icon/icons/DoubleArrowRightIcon.vue +0 -14
  439. package/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue +0 -27
  440. package/ui/components/atoms/vc-icon/icons/GridDotsIcon.vue +0 -22
  441. package/ui/components/atoms/vc-icon/icons/LogoutIcon.vue +0 -13
  442. package/ui/components/atoms/vc-icon/icons/MinusSignIcon.vue +0 -14
  443. package/ui/components/atoms/vc-icon/icons/OffersIcon.vue +0 -23
  444. package/ui/components/atoms/vc-icon/icons/OrdersIcon.vue +0 -19
  445. package/ui/components/atoms/vc-icon/icons/PeopleIcon.vue +0 -21
  446. package/ui/components/atoms/vc-icon/icons/PlusSignIcon.vue +0 -20
  447. package/ui/components/atoms/vc-icon/icons/ProductsIcon.vue +0 -23
  448. package/ui/components/atoms/vc-icon/icons/ProfileIcon.vue +0 -18
  449. package/ui/components/atoms/vc-icon/icons/SearchIcon.vue +0 -14
  450. package/ui/components/atoms/vc-icon/icons/SettingsBoltIcon.vue +0 -21
  451. package/ui/components/atoms/vc-icon/icons/ShoppingCardIcon.vue +0 -16
  452. package/ui/components/atoms/vc-icon/icons/VendorSwitchIcon.vue +0 -26
  453. package/ui/components/atoms/vc-icon/icons/VertDotsIcon.vue +0 -19
@@ -2,14 +2,15 @@
2
2
  <div
3
3
  class="vc-editor"
4
4
  :class="{
5
- 'vc-editor--error': errorMessage,
5
+ 'vc-editor--error': !!errorMessage,
6
6
  'vc-editor--disabled': disabled,
7
7
  'vc-editor--focused': isFocused,
8
+ 'vc-editor--fullscreen': isFullscreen,
9
+ 'vc-editor--side-by-side': currentMode === 'split',
8
10
  }"
9
11
  >
10
- <!-- Editor label -->
11
12
  <VcLabel
12
- v-if="label"
13
+ v-if="label && !isFullscreen"
13
14
  class="vc-editor__label"
14
15
  :required="required"
15
16
  :multilanguage="multilanguage"
@@ -20,52 +21,162 @@
20
21
  <template
21
22
  v-if="tooltip"
22
23
  #tooltip
24
+ >{{ tooltip }}</template
23
25
  >
24
- {{ tooltip }}
25
- </template>
26
26
  </VcLabel>
27
27
 
28
- <!-- Editor field -->
29
- <md-editor
30
- ref="editorRef"
31
- v-model="model"
32
- language="any"
33
- :editor-id="id"
34
- :disabled="disabled"
35
- :read-only="disabled"
36
- :sanitize="sanitize"
37
- :placeholder="placeholder"
38
- :toolbars="toolbars"
39
- no-katex
40
- no-mermaid
41
- tabindex="0"
42
- class="vc-editor__editor"
43
- @on-upload-img="onUploadImage"
44
- @focus="isFocused = true"
45
- @blur="isFocused = false"
28
+ <div
29
+ v-if="editor"
30
+ class="vc-editor__header"
31
+ >
32
+ <VcEditorToolbar
33
+ v-if="currentMode === 'editor' || currentMode === 'split'"
34
+ :editor="editor"
35
+ :disabled="disabled"
36
+ :content-type="detectedType"
37
+ :toolbar="filteredToolbar"
38
+ @upload-image="triggerImageUpload"
39
+ />
40
+
41
+ <div class="vc-editor__header-actions">
42
+ <VcEditorButton
43
+ icon="lucide-eye"
44
+ :active="currentMode === 'preview'"
45
+ :disabled="disabled"
46
+ @action="togglePreview"
47
+ />
48
+ <VcEditorButton
49
+ icon="lucide-columns-2"
50
+ :active="currentMode === 'split'"
51
+ @action="toggleSideBySideView"
52
+ />
53
+ <VcEditorButton
54
+ icon="lucide-code"
55
+ :active="currentMode === 'source'"
56
+ :disabled="disabled"
57
+ @action="toggleSourceView"
58
+ />
59
+ <VcEditorButton
60
+ :icon="isFullscreen ? 'lucide-shrink' : 'lucide-expand'"
61
+ @action="isFullscreen = !isFullscreen"
62
+ />
63
+ </div>
64
+ </div>
65
+
66
+ <div class="vc-editor__body">
67
+ <!-- Normal editor view -->
68
+ <editor-content
69
+ v-if="currentMode === 'editor'"
70
+ :editor="editor"
71
+ class="vc-editor__content"
72
+ />
73
+
74
+ <!-- Full preview view -->
75
+ <div
76
+ v-if="currentMode === 'preview'"
77
+ class="vc-editor__preview ProseMirror"
78
+ v-html="previewContent"
79
+ />
80
+
81
+ <!-- Source code view -->
82
+ <textarea
83
+ v-if="currentMode === 'source'"
84
+ class="vc-editor__source ProseMirror"
85
+ :value="formattedSource"
86
+ :maxlength="maxlength"
87
+ @input="handleSourceInput"
88
+ @focus="isFocused = true"
89
+ @blur="isFocused = false"
90
+ />
91
+
92
+ <!-- Side-by-side view: Editor left, Code right -->
93
+ <div
94
+ v-if="currentMode === 'split'"
95
+ class="vc-editor__split-view"
96
+ >
97
+ <div class="vc-editor__split-editor">
98
+ <editor-content
99
+ :editor="editor"
100
+ class="vc-editor__content"
101
+ />
102
+ </div>
103
+ <div class="vc-editor__split-preview">
104
+ <textarea
105
+ class="vc-editor__source ProseMirror"
106
+ :value="formattedSource"
107
+ :maxlength="maxlength"
108
+ @input="handleSourceInput"
109
+ @focus="isFocused = true"
110
+ @blur="isFocused = false"
111
+ />
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <!-- Character count display -->
117
+ <div
118
+ v-if="maxlength && (currentMode === 'source' || currentMode === 'split')"
119
+ class="vc-editor__char-count"
120
+ :class="{ 'vc-editor__char-count--warning': isNearLimit }"
121
+ >
122
+ {{ characterCount }} / {{ maxlength }}
123
+ </div>
124
+
125
+ <input
126
+ ref="imageInput"
127
+ type="file"
128
+ hidden
129
+ multiple
130
+ accept="image/*"
131
+ @change="handleImageSelection"
46
132
  />
47
133
 
48
134
  <slot
49
- v-if="errorMessage"
135
+ v-if="errorMessage && !isFullscreen"
50
136
  name="error"
51
137
  >
52
- <VcHint class="vc-editor__error">
53
- {{ errorMessage }}
54
- </VcHint>
138
+ <VcHint class="vc-editor__error-hint">{{ errorMessage }}</VcHint>
55
139
  </slot>
56
140
  </div>
57
141
  </template>
58
- <!-- eslint-disable @typescript-eslint/no-explicit-any -->
142
+
59
143
  <script lang="ts" setup>
60
- import { ref, getCurrentInstance, Ref, computed, ComputedRef } from "vue";
144
+ import { ref, watch, onBeforeUnmount, computed } from "vue";
145
+ import { useEditor, EditorContent } from "@tiptap/vue-3";
146
+ import { StarterKit } from "@tiptap/starter-kit";
147
+ import { Underline } from "@tiptap/extension-underline";
148
+ import { Table } from "@tiptap/extension-table";
149
+ import { TableRow } from "@tiptap/extension-table-row";
150
+ import { TableHeader } from "@tiptap/extension-table-header";
151
+ import { TableCell } from "@tiptap/extension-table-cell";
152
+ import { Link } from "@tiptap/extension-link";
153
+ import { Image } from "@tiptap/extension-image";
154
+ import { Placeholder } from "@tiptap/extension-placeholder";
155
+ import { Markdown } from "tiptap-markdown";
156
+ import { format } from "prettier/standalone";
157
+ import * as prettierPluginHtml from "prettier/parser-html";
158
+ // eslint-disable-next-line import/no-named-as-default
61
159
  import DOMPurify from "dompurify";
62
160
  import { VcLabel, VcHint } from "../..";
63
- import { MdEditor, ToolbarNames, config } from "md-editor-v3";
64
- import "md-editor-v3/lib/style.css";
65
- import { useI18n } from "vue-i18n";
66
- import { reactiveComputed } from "@vueuse/core";
67
- import { tags } from "@lezer/highlight";
68
- import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
161
+ import VcEditorToolbar from "./_internal/vc-editor-toolbar.vue";
162
+ import VcEditorButton from "./_internal/vc-editor-button.vue";
163
+
164
+ // Define toolbar button types
165
+ type ToolbarNames =
166
+ | "bold"
167
+ | "italic"
168
+ | "underline"
169
+ | "strikethrough"
170
+ | "heading1"
171
+ | "heading2"
172
+ | "heading3"
173
+ | "bulletList"
174
+ | "orderedList"
175
+ | "blockquote"
176
+ | "link"
177
+ | "image"
178
+ | "table"
179
+ | "separator";
69
180
 
70
181
  export interface Props {
71
182
  placeholder?: string;
@@ -75,7 +186,7 @@ export interface Props {
75
186
  label?: string;
76
187
  tooltip?: string;
77
188
  errorMessage?: string;
78
- assetsFolder: string;
189
+ assetsFolder?: string;
79
190
  multilanguage?: boolean;
80
191
  currentLanguage?: string;
81
192
  maxlength?: number;
@@ -83,378 +194,573 @@ export interface Props {
83
194
  }
84
195
 
85
196
  export interface Emits {
86
- (event: "update:modelValue", value: string | number | Date | null | undefined): void;
197
+ (event: "update:modelValue", value?: string): void;
198
+ (event: "upload-image"): void;
87
199
  }
88
200
 
89
- const props = defineProps<Props>();
90
- const emit = defineEmits<Emits>();
201
+ const props = withDefaults(defineProps<Props>(), {
202
+ modelValue: "",
203
+ disabled: false,
204
+ });
91
205
 
92
- const { t } = useI18n({ useScope: "global" });
206
+ const emit = defineEmits<Emits>();
93
207
 
94
- const uid = getCurrentInstance()?.uid;
95
- const id = `editor-${uid}`;
96
208
  const isFocused = ref(false);
209
+ const isFullscreen = ref(false);
210
+ const imageInput = ref<HTMLInputElement | null>(null);
211
+ const detectedType = ref<"html" | "markdown">("markdown");
212
+
213
+ // Computed property for filtered toolbar based on props
214
+ const filteredToolbar = computed(() => {
215
+ if (!props.toolbar) {
216
+ // Default toolbar if none specified
217
+ return [
218
+ "bold",
219
+ "italic",
220
+ "underline",
221
+ "strikethrough",
222
+ "separator",
223
+ "heading1",
224
+ "heading2",
225
+ "heading3",
226
+ "separator",
227
+ "bulletList",
228
+ "orderedList",
229
+ "blockquote",
230
+ "separator",
231
+ "link",
232
+ "image",
233
+ "table",
234
+ ] as ToolbarNames[];
235
+ }
236
+ return props.toolbar;
237
+ });
238
+
239
+ // Character count for maxlength
240
+ const characterCount = computed(() => {
241
+ return (props.modelValue || "").length;
242
+ });
243
+
244
+ const isNearLimit = computed(() => {
245
+ if (!props.maxlength) return false;
246
+ return characterCount.value > props.maxlength * 0.9;
247
+ });
248
+
249
+ // Function to detect content type
250
+ function detectContentType(content: string): "html" | "markdown" {
251
+ if (!content || content.trim() === "") return "markdown";
252
+
253
+ // HTML indicators
254
+ const htmlPatterns = [
255
+ /<[^>]+>/g, // HTML tags
256
+ /&[a-zA-Z]+;/g, // HTML entities
257
+ ];
258
+
259
+ // Markdown indicators
260
+ const markdownPatterns = [
261
+ /^#{1,6}\s/m, // Headers
262
+ /^\*\s/m, // Bullet lists
263
+ /^\d+\.\s/m, // Numbered lists
264
+ /\*\*[^*]+\*\*/g, // Bold
265
+ /\*[^*]+\*/g, // Italic
266
+ /\[[^\]]+\]\([^)]+\)/g, // Links
267
+ /```[\s\S]*?```/g, // Code blocks
268
+ /`[^`]+`/g, // Inline code
269
+ /^>/m, // Blockquotes
270
+ ];
271
+
272
+ let htmlScore = 0;
273
+ let markdownScore = 0;
274
+
275
+ // Count HTML patterns
276
+ htmlPatterns.forEach((pattern) => {
277
+ const matches = content.match(pattern);
278
+ if (matches) htmlScore += matches.length;
279
+ });
97
280
 
98
- const editorRef = ref(null) as Ref<typeof MdEditor | null>;
99
- defineSlots<{
100
- error?: (props: any) => any;
101
- }>();
102
-
103
- const tagColors = [
104
- { tag: tags.comment, color: "var(--neutrals-500)" },
105
- { tag: tags.lineComment, color: "var(--neutrals-500)" },
106
- { tag: tags.blockComment, color: "var(--neutrals-500)" },
107
- { tag: tags.docComment, color: "var(--neutrals-500)" },
108
-
109
- { tag: tags.name, color: "var(--primary-500)" },
110
- { tag: tags.variableName, color: "var(--primary-500)" },
111
- { tag: tags.propertyName, color: "var(--primary-500)" },
112
- { tag: tags.labelName, color: "var(--primary-500)" },
113
-
114
- { tag: tags.typeName, color: "var(--secondary-500)" },
115
- { tag: tags.tagName, color: "var(--secondary-600)" },
116
- { tag: tags.namespace, color: "var(--secondary-700)" },
117
-
118
- { tag: tags.attributeName, color: "var(--primary-600)" },
119
- { tag: tags.className, color: "var(--primary-700)" },
120
-
121
- { tag: tags.macroName, color: "var(--accent-500)" },
122
-
123
- { tag: tags.literal, color: "var(--info-500)" },
124
- { tag: tags.string, color: "var(--success-500)" },
125
- { tag: tags.docString, color: "var(--success-400)" },
126
- { tag: tags.character, color: "var(--success-300)" },
127
- { tag: tags.attributeValue, color: "var(--success-300)" },
128
-
129
- { tag: tags.number, color: "var(--info-500)" },
130
- { tag: tags.integer, color: "var(--info-500)" },
131
- { tag: tags.float, color: "var(--info-500)" },
132
-
133
- { tag: tags.bool, color: "var(--warning-500)" },
134
- { tag: tags.atom, color: "var(--warning-500)" },
135
- { tag: tags.unit, color: "var(--warning-500)" },
136
-
137
- { tag: tags.regexp, color: "var(--accent-600)" },
138
- { tag: tags.escape, color: "var(--accent-500)" },
139
- { tag: tags.color, color: "var(--accent-500)" },
140
- { tag: tags.url, color: "var(--accent-500)" },
141
-
142
- { tag: tags.keyword, color: "var(--primary-700)" },
143
- { tag: tags.self, color: "var(--primary-700)" },
144
- { tag: tags.operatorKeyword, color: "var(--primary-700)" },
145
- { tag: tags.controlKeyword, color: "var(--primary-700)" },
146
- { tag: tags.definitionKeyword, color: "var(--primary-700)" },
147
- { tag: tags.moduleKeyword, color: "var(--primary-700)" },
148
-
149
- { tag: tags.null, color: "var(--warning-600)" },
150
-
151
- { tag: tags.operator, color: "var(--primary-500)" },
152
- { tag: tags.derefOperator, color: "var(--primary-500)" },
153
- { tag: tags.arithmeticOperator, color: "var(--primary-500)" },
154
- { tag: tags.logicOperator, color: "var(--primary-500)" },
155
- { tag: tags.bitwiseOperator, color: "var(--primary-500)" },
156
- { tag: tags.compareOperator, color: "var(--primary-500)" },
157
- { tag: tags.updateOperator, color: "var(--primary-500)" },
158
- { tag: tags.definitionOperator, color: "var(--primary-500)" },
159
- { tag: tags.typeOperator, color: "var(--primary-500)" },
160
- { tag: tags.controlOperator, color: "var(--primary-500)" },
161
-
162
- { tag: tags.punctuation, color: "var(--neutrals-700)" },
163
- { tag: tags.separator, color: "var(--neutrals-700)" },
164
- { tag: tags.bracket, color: "var(--neutrals-700)" },
165
- { tag: tags.angleBracket, color: "var(--neutrals-700)" },
166
- { tag: tags.squareBracket, color: "var(--neutrals-700)" },
167
- { tag: tags.paren, color: "var(--neutrals-700)" },
168
- { tag: tags.brace, color: "var(--neutrals-700)" },
169
-
170
- { tag: tags.content, color: "var(--neutrals-800)" },
171
-
172
- { tag: tags.heading, color: "var(--primary-700)" },
173
- { tag: tags.heading1, color: "var(--primary-800)" },
174
- { tag: tags.heading2, color: "var(--primary-700)" },
175
- { tag: tags.heading3, color: "var(--primary-600)" },
176
- { tag: tags.heading4, color: "var(--primary-500)" },
177
- { tag: tags.heading5, color: "var(--primary-400)" },
178
- { tag: tags.heading6, color: "var(--primary-300)" },
179
-
180
- { tag: tags.contentSeparator, color: "var(--neutrals-300)" },
181
-
182
- { tag: tags.list, color: "var(--neutrals-900)" },
183
- { tag: tags.quote, color: "var(--neutrals-700)" },
184
-
185
- { tag: tags.emphasis, color: "var(--primary-500)" },
186
- { tag: tags.strong, color: "var(--primary-700)" },
187
-
188
- { tag: tags.link, color: "var(--accent-500)" },
189
-
190
- { tag: tags.monospace, color: "var(--neutrals-900)" },
191
-
192
- { tag: tags.strikethrough, color: "var(--danger-500)" },
193
-
194
- { tag: tags.inserted, color: "var(--success-500)" },
195
- { tag: tags.deleted, color: "var(--danger-500)" },
196
- { tag: tags.changed, color: "var(--warning-500)" },
197
-
198
- { tag: tags.invalid, color: "var(--danger-700)" },
199
-
200
- { tag: tags.meta, color: "var(--neutrals-600)" },
201
- { tag: tags.documentMeta, color: "var(--neutrals-600)" },
202
- { tag: tags.annotation, color: "var(--neutrals-600)" },
203
- { tag: tags.processingInstruction, color: "var(--neutrals-600)" },
281
+ // Count Markdown patterns
282
+ markdownPatterns.forEach((pattern) => {
283
+ const matches = content.match(pattern);
284
+ if (matches) markdownScore += matches.length;
285
+ });
286
+
287
+ // Only switch to HTML if there are significantly more HTML patterns
288
+ if (htmlScore > markdownScore * 2) {
289
+ return "html";
290
+ }
291
+
292
+ // Default to Markdown for most cases
293
+ return "markdown";
294
+ }
295
+
296
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
297
+ const extensions: any[] = [
298
+ StarterKit,
299
+ Underline,
300
+ Table.configure({ resizable: true }),
301
+ TableRow,
302
+ TableHeader,
303
+ TableCell,
304
+ Link.configure({ openOnClick: false }),
305
+ Image,
306
+ Placeholder.configure({ placeholder: props.placeholder }),
307
+ Markdown.configure({
308
+ html: true, // Allow HTML input/output
309
+ tightLists: true, // No <p> inside <li> in markdown output
310
+ tightListClass: "tight", // Add class to <ul> allowing you to remove <p> margins when tight
311
+ bulletListMarker: "-", // <li> prefix in markdown output
312
+ linkify: false, // Create links from "https://..." text
313
+ breaks: true, // New lines (\n) in markdown input are converted to <br>
314
+ transformPastedText: false, // Allow to paste markdown text in the editor
315
+ transformCopiedText: false, // Copied text is transformed to markdown
316
+ }),
204
317
  ];
205
318
 
206
- const myHighlightStyle = HighlightStyle.define(tagColors);
207
-
208
- const toolbars: ComputedRef<ToolbarNames[]> = computed(() =>
209
- props.disabled
210
- ? []
211
- : props.toolbar
212
- ? props.toolbar
213
- : [
214
- "bold",
215
- "underline",
216
- "italic",
217
- "-",
218
- "title",
219
- "strikeThrough",
220
- "quote",
221
- "unorderedList",
222
- "orderedList",
223
- "-",
224
- "link",
225
- "image",
226
- "table",
227
- "-",
228
- "revoke",
229
- "next",
230
- "-",
231
- "pageFullscreen",
232
- "fullscreen",
233
- "preview",
234
- "previewOnly",
235
- ],
319
+ const formattedSource = ref(props.modelValue || "");
320
+
321
+ watch(
322
+ () => props.modelValue,
323
+ async (value) => {
324
+ // Detect content type
325
+ detectedType.value = detectContentType(value || "");
326
+
327
+ if (detectedType.value === "html") {
328
+ try {
329
+ formattedSource.value = await format(value || "", {
330
+ parser: "html",
331
+ plugins: [prettierPluginHtml],
332
+ vueIndentScriptAndStyle: true,
333
+ });
334
+ } catch (e) {
335
+ formattedSource.value = value || "";
336
+ }
337
+ } else {
338
+ formattedSource.value = value || "";
339
+ }
340
+ },
341
+ { immediate: true },
236
342
  );
237
343
 
238
- config({
239
- codeMirrorExtensions: (theme, extensions) => {
240
- return [syntaxHighlighting(myHighlightStyle), ...extensions];
241
- },
242
- editorConfig: {
243
- languageUserDefined: {
244
- any: reactiveComputed(() => ({
245
- toolbarTips: {
246
- bold: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.BOLD"),
247
- underline: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.UNDERLINE"),
248
- italic: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.ITALIC"),
249
- strikeThrough: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.STRIKE_THROUGH"),
250
- title: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.TITLE"),
251
- sub: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.SUB"),
252
- sup: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.SUP"),
253
- quote: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.QUOTE"),
254
- unorderedList: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.UNORDERED_LIST"),
255
- orderedList: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.ORDERED_LIST"),
256
- task: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.TASK"),
257
- codeRow: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.CODE_ROW"),
258
- code: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.CODE"),
259
- link: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.LINK"),
260
- image: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.IMAGE"),
261
- table: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.TABLE"),
262
- mermaid: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.MERMAID"),
263
- katex: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.KATEX"),
264
- revoke: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.REVOKE"),
265
- next: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.NEXT"),
266
- save: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.SAVE"),
267
- prettier: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.PRETTIER"),
268
- pageFullscreen: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.PAGE_FULLSCREEN"),
269
- fullscreen: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.FULLSCREEN"),
270
- preview: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.PREVIEW"),
271
- previewOnly: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.PREVIEW_ONLY"),
272
- htmlPreview: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.HTML_PREVIEW"),
273
- catalog: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.CATALOG"),
274
- github: t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.GITHUB"),
275
- "-": t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.DASH"),
276
- "=": t("COMPONENTS.MOLECULES.VC_EDITOR.TOOLBAR_TIPS.EQUALS"),
277
- },
278
- titleItem: {
279
- h1: t("COMPONENTS.MOLECULES.VC_EDITOR.TITLE_ITEM.H1"),
280
- h2: t("COMPONENTS.MOLECULES.VC_EDITOR.TITLE_ITEM.H2"),
281
- h3: t("COMPONENTS.MOLECULES.VC_EDITOR.TITLE_ITEM.H3"),
282
- h4: t("COMPONENTS.MOLECULES.VC_EDITOR.TITLE_ITEM.H4"),
283
- h5: t("COMPONENTS.MOLECULES.VC_EDITOR.TITLE_ITEM.H5"),
284
- h6: t("COMPONENTS.MOLECULES.VC_EDITOR.TITLE_ITEM.H6"),
285
- },
286
- imgTitleItem: {
287
- link: t("COMPONENTS.MOLECULES.VC_EDITOR.IMG_TITLE_ITEM.LINK"),
288
- upload: t("COMPONENTS.MOLECULES.VC_EDITOR.IMG_TITLE_ITEM.UPLOAD"),
289
- clip2upload: t("COMPONENTS.MOLECULES.VC_EDITOR.IMG_TITLE_ITEM.CLIP2UPLOAD"),
290
- },
291
- linkModalTips: {
292
- linkTitle: t("COMPONENTS.MOLECULES.VC_EDITOR.LINK_MODAL_TIPS.LINK_TITLE"),
293
- imageTitle: t("COMPONENTS.MOLECULES.VC_EDITOR.LINK_MODAL_TIPS.IMAGE_TITLE"),
294
- descLabel: t("COMPONENTS.MOLECULES.VC_EDITOR.LINK_MODAL_TIPS.DESC_LABEL"),
295
- descLabelPlaceHolder: t("COMPONENTS.MOLECULES.VC_EDITOR.LINK_MODAL_TIPS.DESC_LABEL_PLACEHOLDER"),
296
- urlLabel: t("COMPONENTS.MOLECULES.VC_EDITOR.LINK_MODAL_TIPS.URL_LABEL"),
297
- urlLabelPlaceHolder: t("COMPONENTS.MOLECULES.VC_EDITOR.LINK_MODAL_TIPS.URL_LABEL_PLACEHOLDER"),
298
- buttonOK: t("COMPONENTS.MOLECULES.VC_EDITOR.LINK_MODAL_TIPS.BUTTON_OK"),
299
- },
300
- clipModalTips: {
301
- title: t("COMPONENTS.MOLECULES.VC_EDITOR.CLIP_MODAL_TIPS.TITLE"),
302
- buttonUpload: t("COMPONENTS.MOLECULES.VC_EDITOR.CLIP_MODAL_TIPS.BUTTON_UPLOAD"),
303
- },
304
- copyCode: {
305
- text: t("COMPONENTS.MOLECULES.VC_EDITOR.COPY_CODE.TEXT"),
306
- successTips: t("COMPONENTS.MOLECULES.VC_EDITOR.COPY_CODE.SUCCESS_TIPS"),
307
- failTips: t("COMPONENTS.MOLECULES.VC_EDITOR.COPY_CODE.FAIL_TIPS"),
308
- },
309
- mermaid: {
310
- flow: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.FLOW"),
311
- sequence: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.SEQUENCE"),
312
- gantt: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.GANTT"),
313
- class: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.CLASS"),
314
- state: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.STATE"),
315
- pie: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.PIE"),
316
- relationship: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.RELATIONSHIP"),
317
- journey: t("COMPONENTS.MOLECULES.VC_EDITOR.MERMAID.JOURNEY"),
318
- },
319
- katex: {
320
- inline: t("COMPONENTS.MOLECULES.VC_EDITOR.KATEX.INLINE"),
321
- block: t("COMPONENTS.MOLECULES.VC_EDITOR.KATEX.BLOCK"),
322
- },
323
- footer: {
324
- markdownTotal: t("COMPONENTS.MOLECULES.VC_EDITOR.FOOTER.MARKDOWN_TOTAL"),
325
- scrollAuto: t("COMPONENTS.MOLECULES.VC_EDITOR.FOOTER.SCROLL_AUTO"),
326
- },
327
- })),
328
- },
329
- },
344
+ const previewContent = computed(() => {
345
+ let htmlContent = "";
346
+
347
+ if (detectedType.value === "markdown" && editor.value) {
348
+ // Use Tiptap's built-in HTML conversion from Markdown
349
+ htmlContent = editor.value.getHTML();
350
+ } else {
351
+ htmlContent = props.modelValue || "";
352
+ }
353
+
354
+ // Sanitize HTML to prevent XSS attacks
355
+ return DOMPurify.sanitize(htmlContent, {
356
+ // Allow safe HTML tags and attributes
357
+ ALLOWED_TAGS: [
358
+ "p",
359
+ "br",
360
+ "strong",
361
+ "em",
362
+ "u",
363
+ "s",
364
+ "h1",
365
+ "h2",
366
+ "h3",
367
+ "h4",
368
+ "h5",
369
+ "h6",
370
+ "ul",
371
+ "ol",
372
+ "li",
373
+ "blockquote",
374
+ "pre",
375
+ "code",
376
+ "a",
377
+ "img",
378
+ "table",
379
+ "thead",
380
+ "tbody",
381
+ "tr",
382
+ "th",
383
+ "td",
384
+ "hr",
385
+ "div",
386
+ "span",
387
+ ],
388
+ ALLOWED_ATTR: ["href", "src", "alt", "title", "class", "id", "style", "colspan", "rowspan", "align", "valign"],
389
+ // Remove dangerous protocols
390
+ ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.-]+(?:[^a-z+.-:]|$))/i,
391
+ // Keep relative URLs
392
+ KEEP_CONTENT: true,
393
+ // Remove script tags and event handlers
394
+ FORBID_TAGS: ["script", "object", "embed", "form", "input"],
395
+ FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover", "onfocus", "onblur"],
396
+ });
330
397
  });
331
398
 
332
- const model = computed({
333
- get() {
334
- return props.modelValue;
399
+ // Single reactive state for editor mode
400
+ const editorMode = ref<"editor" | "preview" | "source" | "split">("editor");
401
+
402
+ // Computed property for current mode
403
+ const currentMode = computed(() => editorMode.value);
404
+
405
+ function togglePreview() {
406
+ editorMode.value = editorMode.value === "preview" ? "editor" : "preview";
407
+ }
408
+
409
+ function toggleSourceView() {
410
+ editorMode.value = editorMode.value === "source" ? "editor" : "source";
411
+ }
412
+
413
+ function toggleSideBySideView() {
414
+ editorMode.value = editorMode.value === "split" ? "editor" : "split";
415
+ }
416
+
417
+ const editor = useEditor({
418
+ content: props.modelValue,
419
+ editable: !props.disabled,
420
+ extensions,
421
+ onUpdate: ({ editor: tipTapEditor }) => {
422
+ // Always output in Markdown by default, unless HTML is detected
423
+ const output =
424
+ detectedType.value === "html"
425
+ ? tipTapEditor.getHTML()
426
+ : (tipTapEditor.storage.markdown as { getMarkdown: () => string }).getMarkdown();
427
+
428
+ // Check maxlength if specified
429
+ if (props.maxlength && output.length > props.maxlength) {
430
+ return; // Don't emit if exceeds maxlength
431
+ }
432
+
433
+ emit("update:modelValue", output);
434
+ },
435
+ onFocus: () => {
436
+ isFocused.value = true;
335
437
  },
336
- set(value) {
337
- emit("update:modelValue", value);
438
+ onBlur: () => {
439
+ isFocused.value = false;
338
440
  },
339
441
  });
340
442
 
341
- async function onUploadImage(files: File[], callback: (urls: string[]) => void) {
342
- const formData = new FormData();
443
+ watch(
444
+ () => props.modelValue,
445
+ (value) => {
446
+ if (!editor.value) return;
343
447
 
344
- files.forEach((file) => {
345
- formData.append("image", file);
346
- });
448
+ const editorContent =
449
+ detectedType.value === "html"
450
+ ? editor.value.getHTML()
451
+ : (editor.value.storage.markdown as { getMarkdown: () => string }).getMarkdown();
347
452
 
348
- const result = await fetch(`/api/assets?folderUrl=/${props.assetsFolder}`, {
349
- method: "POST",
350
- body: formData,
351
- });
453
+ if (editorContent !== value) {
454
+ editor.value.commands.setContent(value || "", false);
455
+ }
456
+ },
457
+ );
352
458
 
353
- console.log(result);
459
+ watch(
460
+ () => props.disabled,
461
+ (isDisabled) => {
462
+ editor.value?.setEditable(!isDisabled);
463
+ },
464
+ );
354
465
 
355
- const response = await result.json();
466
+ onBeforeUnmount(() => {
467
+ editor.value?.destroy();
468
+ });
356
469
 
357
- callback(
358
- response.map((item: any) => ({
359
- url: item.url,
360
- alt: item.name,
361
- title: item.name,
362
- })),
363
- );
470
+ function triggerImageUpload() {
471
+ imageInput.value?.click();
364
472
  }
365
473
 
366
- function sanitize(html: string) {
367
- return DOMPurify.sanitize(html);
474
+ function handleSourceInput(event: Event) {
475
+ const target = event.target as HTMLTextAreaElement;
476
+ const value = target.value;
477
+
478
+ // Check maxlength if specified
479
+ if (props.maxlength && value.length > props.maxlength) {
480
+ target.value = value.substring(0, props.maxlength);
481
+ return;
482
+ }
483
+
484
+ emit("update:modelValue", value);
368
485
  }
369
486
 
370
- defineExpose({
371
- editorRef,
372
- });
487
+ async function handleImageSelection(event: Event) {
488
+ const target = event.target as HTMLInputElement;
489
+ if (!target.files?.length || !props.assetsFolder) return;
490
+
491
+ const files = Array.from(target.files);
492
+ const formData = new FormData();
493
+ files.forEach((file) => formData.append("image", file));
494
+
495
+ try {
496
+ const result = await fetch(`/api/assets?folderUrl=/${props.assetsFolder}`, {
497
+ method: "POST",
498
+ body: formData,
499
+ });
500
+ const response = await result.json();
501
+
502
+ response.forEach((item: { url: string }) => {
503
+ if (item.url) {
504
+ editor.value?.chain().focus().setImage({ src: item.url }).run();
505
+ }
506
+ });
507
+ } catch (error) {
508
+ console.error("Image upload failed:", error);
509
+ }
510
+ }
373
511
  </script>
374
512
 
375
513
  <style lang="scss">
376
514
  :root {
377
- --editor-border-radius: 4px;
378
- --editor-border-color: var(--neutrals-300);
379
- --editor-border-color-error: var(--danger-500);
380
- --editor-disabled-bg: var(--neutrals-200);
381
- --editor-disabled-text: var(--neutrals-500);
382
- --editor-placeholder-color: var(--neutrals-400);
383
- --editor-text-color: var(--neutrals-800);
384
-
385
- // Focus
386
- --editor-border-color-focus: var(--primary-100);
515
+ // Editor color variables
516
+ --vc-editor-border: var(--neutrals-300);
517
+ --vc-editor-background: var(--neutrals-50);
518
+ --vc-editor-surface: var(--additional-50);
519
+ --vc-editor-text-primary: var(--neutrals-900);
520
+ --vc-editor-text-secondary: var(--neutrals-500);
521
+ --vc-editor-text-muted: var(--neutrals-400);
522
+ --vc-editor-text-disabled: var(--neutrals-400);
523
+ --vc-editor-background-disabled: var(--neutrals-100);
524
+ --vc-editor-focus-border: var(--primary-500);
525
+ --vc-editor-focus-shadow: var(--primary-500);
526
+ --vc-editor-error-border: var(--danger-500);
527
+ --vc-editor-error-text: var(--danger-500);
528
+ --vc-editor-table-header: var(--neutrals-100);
529
+ --vc-editor-separator: var(--neutrals-200);
387
530
  }
388
531
 
389
532
  .vc-editor {
390
- @apply tw-flex tw-flex-col;
533
+ display: flex;
534
+ flex-direction: column;
391
535
 
392
- &--error {
393
- .md-editor {
394
- @apply tw-border-[color:var(--editor-border-color-error)];
395
- }
536
+ &__label {
537
+ margin-bottom: 0.5rem;
396
538
  }
397
539
 
398
- &__label {
399
- @apply tw-mb-2;
540
+ &__header {
541
+ display: flex;
542
+ border: 1px solid var(--vc-editor-border);
543
+ border-bottom: none;
544
+ border-radius: 4px 4px 0 0;
545
+ background-color: var(--vc-editor-background);
546
+ padding: 0.5rem;
547
+ }
548
+
549
+ &__source {
550
+ font-family: monospace;
551
+ resize: vertical;
552
+ }
553
+
554
+ &__header-actions {
555
+ margin-left: auto;
556
+ display: flex;
557
+ gap: 0.25rem;
558
+ }
559
+
560
+ &__body {
561
+ flex-grow: 1;
562
+ display: flex;
400
563
  }
401
564
 
402
- &__error {
403
- @apply tw-text-[color:var(--editor-border-color-error)] tw-mt-1;
565
+ &__content,
566
+ &__preview {
567
+ flex: 1;
404
568
  }
405
569
 
406
- &--focused .vc-editor__editor {
407
- @apply tw-outline-2 tw-outline tw-outline-[color:var(--editor-border-color-focus)] tw-outline-offset-[0px];
570
+ &__split-view {
571
+ display: flex;
572
+ width: 100%;
573
+ gap: 1px;
408
574
  }
409
575
 
410
- &--disabled {
411
- .cm-content *,
412
- .md-editor * {
413
- @apply tw-text-[color:var(--editor-disabled-text)] tw-bg-[var(--editor-disabled-bg)];
576
+ &__split-editor,
577
+ &__split-preview {
578
+ flex: 1;
579
+ }
580
+
581
+ &__split-editor .ProseMirror {
582
+ border-radius: 0 0 0 4px;
583
+ border-right: none;
584
+ }
585
+
586
+ &__split-preview .ProseMirror {
587
+ border-radius: 0 0 4px 0;
588
+ border-left: none;
589
+ }
590
+
591
+ &--side-by-side {
592
+ .vc-editor__body {
593
+ flex-direction: row;
414
594
  }
415
595
  }
416
- }
417
596
 
418
- .md-editor {
419
- --md-color: var(--secondary-800);
420
- --md-hover-color: var(--additional-950);
421
- --md-bk-color: var(--additional-50);
422
- --md-bk-color-outstand: var(--neutrals-100);
423
- --md-bk-hover-color: var(--secondary-50);
424
- --md-border-color: var(--neutrals-300);
425
- --md-border-hover-color: var(--neutrals-400);
426
- --md-border-active-color: var(--neutrals-400);
427
- --md-modal-mask: rgba(0, 0, 0, 0.45);
428
- --md-modal-shadow: 0px 6px 24px 2px rgba(0, 0, 0, 0.1);
429
- --md-scrollbar-bg-color: var(--neutrals-200);
430
- --md-scrollbar-thumb-color: rgba(0, 0, 0, 0.3);
431
- --md-scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.35);
432
- --md-scrollbar-thumb-active-color: rgba(0, 0, 0, 0.38);
433
- color: var(--md-color);
434
- border: 1px solid var(--md-border-color);
435
- background-color: var(--md-bk-color);
436
- height: 350px;
437
- border-radius: var(--editor-border-radius);
438
- @apply tw-font-jakarta #{!important};
439
- }
597
+ .ProseMirror {
598
+ border: 1px solid var(--vc-editor-border);
599
+ border-radius: 0 0 4px 4px;
600
+ padding: 0.5rem 0.75rem;
601
+ min-height: 20rem;
602
+ outline: none;
603
+ transition: border-color 0.2s;
604
+ background-color: var(--vc-editor-surface);
605
+ color: var(--vc-editor-text-primary);
606
+ width: 100%;
607
+
608
+ p.is-editor-empty:first-child::before {
609
+ content: attr(data-placeholder);
610
+ float: left;
611
+ color: var(--vc-editor-text-muted);
612
+ pointer-events: none;
613
+ height: 0;
614
+ }
440
615
 
441
- .ͼ15 {
442
- color: var(--editor-text-color);
443
- }
616
+ h1,
617
+ h2,
618
+ h3 {
619
+ line-height: 1.1;
620
+ margin-top: 1.25em;
621
+ margin-bottom: 0.5em;
622
+ font-weight: bold;
623
+ color: var(--vc-editor-text-primary);
624
+ }
444
625
 
445
- .ͼ1 .cm-placeholder {
446
- color: var(--editor-placeholder-color);
447
- }
626
+ h1 {
627
+ font-size: 2em;
628
+ margin-top: 0.67em;
629
+ margin-bottom: 0.67em;
630
+ }
448
631
 
449
- .cm-content {
450
- color: var(--editor-text-color);
451
- }
632
+ h2 {
633
+ font-size: 1.5em;
634
+ margin-top: 0.83em;
635
+ margin-bottom: 0.83em;
636
+ }
452
637
 
453
- .cm-scroller {
454
- @apply tw-font-jakarta #{!important};
455
- }
638
+ h3 {
639
+ font-size: 1.17em;
640
+ margin-top: 1em;
641
+ margin-bottom: 1em;
642
+ }
643
+
644
+ ul,
645
+ ol {
646
+ padding: 0 1rem;
647
+ }
648
+
649
+ blockquote {
650
+ padding-left: 1rem;
651
+ border-left: 2px solid var(--vc-editor-separator);
652
+ color: var(--vc-editor-text-secondary);
653
+ }
654
+
655
+ hr {
656
+ border: none;
657
+ border-top: 1px solid var(--vc-editor-separator);
658
+ margin: 1rem 0;
659
+ }
456
660
 
457
- .md-editor-preview {
458
- @apply tw-text-sm;
661
+ table {
662
+ border-collapse: collapse;
663
+ table-layout: fixed;
664
+ width: 100%;
665
+ }
666
+
667
+ td,
668
+ th {
669
+ border: 1px solid var(--vc-editor-separator);
670
+ padding: 0.5rem;
671
+ text-align: left;
672
+ }
673
+
674
+ th {
675
+ background-color: var(--vc-editor-table-header);
676
+ font-weight: 600;
677
+ color: var(--vc-editor-text-primary);
678
+ }
679
+
680
+ // Links
681
+ a {
682
+ color: var(--primary-600);
683
+ text-decoration: underline;
684
+
685
+ &:hover {
686
+ color: var(--primary-700);
687
+ }
688
+ }
689
+
690
+ // Code blocks
691
+ pre {
692
+ background-color: var(--vc-editor-background);
693
+ border: 1px solid var(--vc-editor-border);
694
+ border-radius: 4px;
695
+ padding: 0.75rem;
696
+ overflow-x: auto;
697
+ }
698
+
699
+ code {
700
+ background-color: var(--vc-editor-background);
701
+ color: var(--vc-editor-text-primary);
702
+ padding: 0.125rem 0.25rem;
703
+ border-radius: 2px;
704
+ font-size: 0.875em;
705
+ }
706
+ }
707
+
708
+ &--focused .ProseMirror {
709
+ border-color: var(--vc-editor-focus-border);
710
+ box-shadow: 0 0 0 3px rgba(49, 158, 212, 0.2); // primary-500 with 20% opacity
711
+ }
712
+
713
+ &--disabled .ProseMirror {
714
+ background-color: var(--vc-editor-background-disabled);
715
+ cursor: not-allowed;
716
+ color: var(--vc-editor-text-disabled);
717
+ }
718
+
719
+ &--error .ProseMirror {
720
+ border-color: var(--vc-editor-error-border);
721
+ }
722
+
723
+ &__error-hint {
724
+ color: var(--vc-editor-error-text);
725
+ margin-top: 0.25rem;
726
+ }
727
+
728
+ &__char-count {
729
+ font-size: 0.75rem;
730
+ color: var(--vc-editor-text-secondary);
731
+ text-align: right;
732
+ padding: 0.25rem 0.5rem;
733
+ border: 1px solid var(--vc-editor-border);
734
+ border-top: none;
735
+ border-radius: 0 0 4px 4px;
736
+ background-color: var(--vc-editor-background);
737
+
738
+ &--warning {
739
+ color: var(--warning-600);
740
+ font-weight: 600;
741
+ }
742
+ }
743
+
744
+ &--fullscreen {
745
+ position: fixed;
746
+ top: 0;
747
+ left: 0;
748
+ width: 100vw;
749
+ height: 100vh;
750
+ background-color: var(--vc-editor-surface);
751
+ z-index: 1000;
752
+ padding: 1rem;
753
+ display: flex;
754
+ flex-direction: column;
755
+
756
+ .vc-editor__body {
757
+ height: 100%;
758
+ }
759
+
760
+ .ProseMirror {
761
+ height: 100%;
762
+ min-height: 0;
763
+ }
764
+ }
459
765
  }
460
766
  </style>