katecms 0.0.0-stage → 1.0.0-beta.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 (552) hide show
  1. package/README.md +5 -3
  2. package/dist/module.d.mts +93 -0
  3. package/dist/module.json +9 -0
  4. package/dist/module.mjs +579 -0
  5. package/dist/runtime/assets/img/katecms-logo.svg +17 -0
  6. package/dist/runtime/composables/getCollection.d.ts +62 -0
  7. package/dist/runtime/composables/getCollection.js +167 -0
  8. package/dist/runtime/composables/getOptions.d.ts +22 -0
  9. package/dist/runtime/composables/getOptions.js +22 -0
  10. package/dist/runtime/composables/getQueryCollection.d.ts +95 -0
  11. package/dist/runtime/composables/getQueryCollection.js +199 -0
  12. package/dist/runtime/composables/getTerms.d.ts +79 -0
  13. package/dist/runtime/composables/getTerms.js +148 -0
  14. package/dist/runtime/composables/useAuth.d.ts +14 -0
  15. package/dist/runtime/composables/useAuth.js +33 -0
  16. package/dist/runtime/composables/useAuthCooldown.d.ts +6 -0
  17. package/dist/runtime/composables/useAuthCooldown.js +44 -0
  18. package/dist/runtime/composables/useCmsPaths.d.ts +15 -0
  19. package/dist/runtime/composables/useCmsPaths.js +21 -0
  20. package/dist/runtime/composables/useKateCmsExtensions.d.ts +49 -0
  21. package/dist/runtime/composables/useKateCmsExtensions.js +29 -0
  22. package/dist/runtime/composables/useMediaLibrary.d.ts +84 -0
  23. package/dist/runtime/composables/useMediaLibrary.js +140 -0
  24. package/dist/runtime/composables/useMenuAccess.d.ts +8 -0
  25. package/dist/runtime/composables/useMenuAccess.js +16 -0
  26. package/dist/runtime/internal/admin/AdminHeader.d.vue.ts +24 -0
  27. package/dist/runtime/internal/admin/AdminHeader.vue +91 -0
  28. package/dist/runtime/internal/admin/AdminHeader.vue.d.ts +24 -0
  29. package/dist/runtime/internal/admin/AppMenu.d.vue.ts +3 -0
  30. package/dist/runtime/internal/admin/AppMenu.vue +244 -0
  31. package/dist/runtime/internal/admin/AppMenu.vue.d.ts +3 -0
  32. package/dist/runtime/internal/admin/AppUser.d.vue.ts +3 -0
  33. package/dist/runtime/internal/admin/AppUser.vue +227 -0
  34. package/dist/runtime/internal/admin/AppUser.vue.d.ts +3 -0
  35. package/dist/runtime/internal/admin/CollectionEntryForm.d.vue.ts +41 -0
  36. package/dist/runtime/internal/admin/CollectionEntryForm.vue +916 -0
  37. package/dist/runtime/internal/admin/CollectionEntryForm.vue.d.ts +41 -0
  38. package/dist/runtime/internal/admin/ConfirmDialog.d.vue.ts +28 -0
  39. package/dist/runtime/internal/admin/ConfirmDialog.vue +136 -0
  40. package/dist/runtime/internal/admin/ConfirmDialog.vue.d.ts +28 -0
  41. package/dist/runtime/internal/admin/DictionaryTermForm.d.vue.ts +33 -0
  42. package/dist/runtime/internal/admin/DictionaryTermForm.vue +328 -0
  43. package/dist/runtime/internal/admin/DictionaryTermForm.vue.d.ts +33 -0
  44. package/dist/runtime/internal/admin/EntryRevisions.d.vue.ts +15 -0
  45. package/dist/runtime/internal/admin/EntryRevisions.vue +125 -0
  46. package/dist/runtime/internal/admin/EntryRevisions.vue.d.ts +15 -0
  47. package/dist/runtime/internal/admin/MediaLibraryFilters.d.vue.ts +16 -0
  48. package/dist/runtime/internal/admin/MediaLibraryFilters.vue +153 -0
  49. package/dist/runtime/internal/admin/MediaLibraryFilters.vue.d.ts +16 -0
  50. package/dist/runtime/internal/admin/MediaLibraryModal.d.vue.ts +65 -0
  51. package/dist/runtime/internal/admin/MediaLibraryModal.vue +451 -0
  52. package/dist/runtime/internal/admin/MediaLibraryModal.vue.d.ts +65 -0
  53. package/dist/runtime/internal/admin/OptionPageForm.d.vue.ts +26 -0
  54. package/dist/runtime/internal/admin/OptionPageForm.vue +222 -0
  55. package/dist/runtime/internal/admin/OptionPageForm.vue.d.ts +26 -0
  56. package/dist/runtime/internal/admin/UserAvatarField.d.vue.ts +12 -0
  57. package/dist/runtime/internal/admin/UserAvatarField.vue +305 -0
  58. package/dist/runtime/internal/admin/UserAvatarField.vue.d.ts +12 -0
  59. package/dist/runtime/internal/fields/AccordionField.d.vue.ts +0 -0
  60. package/dist/runtime/internal/fields/AccordionField.vue +220 -0
  61. package/dist/runtime/internal/fields/AccordionField.vue.d.ts +0 -0
  62. package/dist/runtime/internal/fields/ButtonGroupField.d.vue.ts +0 -0
  63. package/dist/runtime/internal/fields/ButtonGroupField.vue +109 -0
  64. package/dist/runtime/internal/fields/ButtonGroupField.vue.d.ts +0 -0
  65. package/dist/runtime/internal/fields/CheckboxField.d.vue.ts +0 -0
  66. package/dist/runtime/internal/fields/CheckboxField.vue +190 -0
  67. package/dist/runtime/internal/fields/CheckboxField.vue.d.ts +0 -0
  68. package/dist/runtime/internal/fields/ColorPickerField.d.vue.ts +0 -0
  69. package/dist/runtime/internal/fields/ColorPickerField.vue +791 -0
  70. package/dist/runtime/internal/fields/ColorPickerField.vue.d.ts +0 -0
  71. package/dist/runtime/internal/fields/DatePickerField.d.vue.ts +0 -0
  72. package/dist/runtime/internal/fields/DatePickerField.vue +26 -0
  73. package/dist/runtime/internal/fields/DatePickerField.vue.d.ts +0 -0
  74. package/dist/runtime/internal/fields/DateTimePickerField.d.vue.ts +0 -0
  75. package/dist/runtime/internal/fields/DateTimePickerField.vue +26 -0
  76. package/dist/runtime/internal/fields/DateTimePickerField.vue.d.ts +0 -0
  77. package/dist/runtime/internal/fields/DictionaryField.d.vue.ts +0 -0
  78. package/dist/runtime/internal/fields/DictionaryField.vue +345 -0
  79. package/dist/runtime/internal/fields/DictionaryField.vue.d.ts +0 -0
  80. package/dist/runtime/internal/fields/EmailField.d.vue.ts +0 -0
  81. package/dist/runtime/internal/fields/EmailField.vue +21 -0
  82. package/dist/runtime/internal/fields/EmailField.vue.d.ts +0 -0
  83. package/dist/runtime/internal/fields/FileField.d.vue.ts +0 -0
  84. package/dist/runtime/internal/fields/FileField.vue +408 -0
  85. package/dist/runtime/internal/fields/FileField.vue.d.ts +0 -0
  86. package/dist/runtime/internal/fields/FlexibleContentField.d.vue.ts +0 -0
  87. package/dist/runtime/internal/fields/FlexibleContentField.vue +1114 -0
  88. package/dist/runtime/internal/fields/FlexibleContentField.vue.d.ts +0 -0
  89. package/dist/runtime/internal/fields/GalleryField.d.vue.ts +0 -0
  90. package/dist/runtime/internal/fields/GalleryField.vue +584 -0
  91. package/dist/runtime/internal/fields/GalleryField.vue.d.ts +0 -0
  92. package/dist/runtime/internal/fields/GroupField.d.vue.ts +0 -0
  93. package/dist/runtime/internal/fields/GroupField.vue +111 -0
  94. package/dist/runtime/internal/fields/GroupField.vue.d.ts +0 -0
  95. package/dist/runtime/internal/fields/ImageField.d.vue.ts +0 -0
  96. package/dist/runtime/internal/fields/ImageField.vue +638 -0
  97. package/dist/runtime/internal/fields/ImageField.vue.d.ts +0 -0
  98. package/dist/runtime/internal/fields/ImageSelectField.d.vue.ts +0 -0
  99. package/dist/runtime/internal/fields/ImageSelectField.vue +179 -0
  100. package/dist/runtime/internal/fields/ImageSelectField.vue.d.ts +0 -0
  101. package/dist/runtime/internal/fields/LinkField.d.vue.ts +0 -0
  102. package/dist/runtime/internal/fields/LinkField.vue +303 -0
  103. package/dist/runtime/internal/fields/LinkField.vue.d.ts +0 -0
  104. package/dist/runtime/internal/fields/NumberField.d.vue.ts +0 -0
  105. package/dist/runtime/internal/fields/NumberField.vue +25 -0
  106. package/dist/runtime/internal/fields/NumberField.vue.d.ts +0 -0
  107. package/dist/runtime/internal/fields/OembedField.d.vue.ts +0 -0
  108. package/dist/runtime/internal/fields/OembedField.vue +161 -0
  109. package/dist/runtime/internal/fields/OembedField.vue.d.ts +0 -0
  110. package/dist/runtime/internal/fields/OpenStreetMapField.d.vue.ts +0 -0
  111. package/dist/runtime/internal/fields/OpenStreetMapField.vue +1502 -0
  112. package/dist/runtime/internal/fields/OpenStreetMapField.vue.d.ts +0 -0
  113. package/dist/runtime/internal/fields/PageLinkField.d.vue.ts +0 -0
  114. package/dist/runtime/internal/fields/PageLinkField.vue +153 -0
  115. package/dist/runtime/internal/fields/PageLinkField.vue.d.ts +0 -0
  116. package/dist/runtime/internal/fields/PasswordField.d.vue.ts +0 -0
  117. package/dist/runtime/internal/fields/PasswordField.vue +108 -0
  118. package/dist/runtime/internal/fields/PasswordField.vue.d.ts +0 -0
  119. package/dist/runtime/internal/fields/PostObjectField.d.vue.ts +0 -0
  120. package/dist/runtime/internal/fields/PostObjectField.vue +151 -0
  121. package/dist/runtime/internal/fields/PostObjectField.vue.d.ts +0 -0
  122. package/dist/runtime/internal/fields/RadioField.d.vue.ts +0 -0
  123. package/dist/runtime/internal/fields/RadioField.vue +163 -0
  124. package/dist/runtime/internal/fields/RadioField.vue.d.ts +0 -0
  125. package/dist/runtime/internal/fields/RangeField.d.vue.ts +0 -0
  126. package/dist/runtime/internal/fields/RangeField.vue +48 -0
  127. package/dist/runtime/internal/fields/RangeField.vue.d.ts +0 -0
  128. package/dist/runtime/internal/fields/RelationshipField.d.vue.ts +0 -0
  129. package/dist/runtime/internal/fields/RelationshipField.vue +525 -0
  130. package/dist/runtime/internal/fields/RelationshipField.vue.d.ts +0 -0
  131. package/dist/runtime/internal/fields/RepeaterField.d.vue.ts +0 -0
  132. package/dist/runtime/internal/fields/RepeaterField.vue +856 -0
  133. package/dist/runtime/internal/fields/RepeaterField.vue.d.ts +0 -0
  134. package/dist/runtime/internal/fields/SelectField.d.vue.ts +21 -0
  135. package/dist/runtime/internal/fields/SelectField.vue +101 -0
  136. package/dist/runtime/internal/fields/SelectField.vue.d.ts +21 -0
  137. package/dist/runtime/internal/fields/SeparatorField.d.vue.ts +0 -0
  138. package/dist/runtime/internal/fields/SeparatorField.vue +63 -0
  139. package/dist/runtime/internal/fields/SeparatorField.vue.d.ts +0 -0
  140. package/dist/runtime/internal/fields/TabField.d.vue.ts +0 -0
  141. package/dist/runtime/internal/fields/TabField.vue +210 -0
  142. package/dist/runtime/internal/fields/TabField.vue.d.ts +0 -0
  143. package/dist/runtime/internal/fields/TextField.d.vue.ts +0 -0
  144. package/dist/runtime/internal/fields/TextField.vue +22 -0
  145. package/dist/runtime/internal/fields/TextField.vue.d.ts +0 -0
  146. package/dist/runtime/internal/fields/TextareaField.d.vue.ts +0 -0
  147. package/dist/runtime/internal/fields/TextareaField.vue +62 -0
  148. package/dist/runtime/internal/fields/TextareaField.vue.d.ts +0 -0
  149. package/dist/runtime/internal/fields/TimePickerField.d.vue.ts +0 -0
  150. package/dist/runtime/internal/fields/TimePickerField.vue +24 -0
  151. package/dist/runtime/internal/fields/TimePickerField.vue.d.ts +0 -0
  152. package/dist/runtime/internal/fields/TrueFalseField.d.vue.ts +0 -0
  153. package/dist/runtime/internal/fields/TrueFalseField.vue +151 -0
  154. package/dist/runtime/internal/fields/TrueFalseField.vue.d.ts +0 -0
  155. package/dist/runtime/internal/fields/UrlField.d.vue.ts +0 -0
  156. package/dist/runtime/internal/fields/UrlField.vue +21 -0
  157. package/dist/runtime/internal/fields/UrlField.vue.d.ts +0 -0
  158. package/dist/runtime/internal/fields/UserField.d.vue.ts +0 -0
  159. package/dist/runtime/internal/fields/UserField.vue +164 -0
  160. package/dist/runtime/internal/fields/UserField.vue.d.ts +0 -0
  161. package/dist/runtime/internal/fields/WysiwygField.d.vue.ts +0 -0
  162. package/dist/runtime/internal/fields/WysiwygField.vue +971 -0
  163. package/dist/runtime/internal/fields/WysiwygField.vue.d.ts +0 -0
  164. package/dist/runtime/internal/parts/DateTimeControl.d.vue.ts +90 -0
  165. package/dist/runtime/internal/parts/DateTimeControl.vue +568 -0
  166. package/dist/runtime/internal/parts/DateTimeControl.vue.d.ts +90 -0
  167. package/dist/runtime/internal/parts/FieldAddon.d.vue.ts +0 -0
  168. package/dist/runtime/internal/parts/FieldAddon.vue +43 -0
  169. package/dist/runtime/internal/parts/FieldAddon.vue.d.ts +0 -0
  170. package/dist/runtime/internal/parts/FieldInstructions.d.vue.ts +0 -0
  171. package/dist/runtime/internal/parts/FieldInstructions.vue +24 -0
  172. package/dist/runtime/internal/parts/FieldInstructions.vue.d.ts +0 -0
  173. package/dist/runtime/internal/parts/FieldLabel.d.vue.ts +0 -0
  174. package/dist/runtime/internal/parts/FieldLabel.vue +40 -0
  175. package/dist/runtime/internal/parts/FieldLabel.vue.d.ts +0 -0
  176. package/dist/runtime/internal/parts/FieldWrapper.d.vue.ts +0 -0
  177. package/dist/runtime/internal/parts/FieldWrapper.vue +47 -0
  178. package/dist/runtime/internal/parts/FieldWrapper.vue.d.ts +0 -0
  179. package/dist/runtime/internal/parts/ImageCropper.d.vue.ts +17 -0
  180. package/dist/runtime/internal/parts/ImageCropper.vue +363 -0
  181. package/dist/runtime/internal/parts/ImageCropper.vue.d.ts +17 -0
  182. package/dist/runtime/internal/parts/InputControl.d.vue.ts +0 -0
  183. package/dist/runtime/internal/parts/InputControl.vue +163 -0
  184. package/dist/runtime/internal/parts/InputControl.vue.d.ts +0 -0
  185. package/dist/runtime/internal/ui/UiButton.d.vue.ts +35 -0
  186. package/dist/runtime/internal/ui/UiButton.vue +204 -0
  187. package/dist/runtime/internal/ui/UiButton.vue.d.ts +35 -0
  188. package/dist/runtime/internal/ui/UiNotice.d.vue.ts +40 -0
  189. package/dist/runtime/internal/ui/UiNotice.vue +253 -0
  190. package/dist/runtime/internal/ui/UiNotice.vue.d.ts +40 -0
  191. package/dist/runtime/internal/ui/UiSelect.d.vue.ts +61 -0
  192. package/dist/runtime/internal/ui/UiSelect.vue +1212 -0
  193. package/dist/runtime/internal/ui/UiSelect.vue.d.ts +61 -0
  194. package/dist/runtime/middleware/auth-guard.d.ts +9 -0
  195. package/dist/runtime/middleware/auth-guard.js +37 -0
  196. package/dist/runtime/pages/admin/collections/[id].d.vue.ts +3 -0
  197. package/dist/runtime/pages/admin/collections/[id].vue +423 -0
  198. package/dist/runtime/pages/admin/collections/[id].vue.d.ts +3 -0
  199. package/dist/runtime/pages/admin/collections/create.d.vue.ts +3 -0
  200. package/dist/runtime/pages/admin/collections/create.vue +179 -0
  201. package/dist/runtime/pages/admin/collections/create.vue.d.ts +3 -0
  202. package/dist/runtime/pages/admin/collections/index.d.vue.ts +3 -0
  203. package/dist/runtime/pages/admin/collections/index.vue +828 -0
  204. package/dist/runtime/pages/admin/collections/index.vue.d.ts +3 -0
  205. package/dist/runtime/pages/admin/demo-fields.d.vue.ts +3 -0
  206. package/dist/runtime/pages/admin/demo-fields.vue +1327 -0
  207. package/dist/runtime/pages/admin/demo-fields.vue.d.ts +3 -0
  208. package/dist/runtime/pages/admin/dictionaries/[id].d.vue.ts +3 -0
  209. package/dist/runtime/pages/admin/dictionaries/[id].vue +213 -0
  210. package/dist/runtime/pages/admin/dictionaries/[id].vue.d.ts +3 -0
  211. package/dist/runtime/pages/admin/dictionaries/index.d.vue.ts +3 -0
  212. package/dist/runtime/pages/admin/dictionaries/index.vue +387 -0
  213. package/dist/runtime/pages/admin/dictionaries/index.vue.d.ts +3 -0
  214. package/dist/runtime/pages/admin/index.d.vue.ts +3 -0
  215. package/dist/runtime/pages/admin/index.vue +138 -0
  216. package/dist/runtime/pages/admin/index.vue.d.ts +3 -0
  217. package/dist/runtime/pages/admin/login.d.vue.ts +3 -0
  218. package/dist/runtime/pages/admin/login.vue +373 -0
  219. package/dist/runtime/pages/admin/login.vue.d.ts +3 -0
  220. package/dist/runtime/pages/admin/media.d.vue.ts +3 -0
  221. package/dist/runtime/pages/admin/media.vue +1054 -0
  222. package/dist/runtime/pages/admin/media.vue.d.ts +3 -0
  223. package/dist/runtime/pages/admin/options/[page].d.vue.ts +3 -0
  224. package/dist/runtime/pages/admin/options/[page].vue +151 -0
  225. package/dist/runtime/pages/admin/options/[page].vue.d.ts +3 -0
  226. package/dist/runtime/pages/admin/register.d.vue.ts +3 -0
  227. package/dist/runtime/pages/admin/register.vue +391 -0
  228. package/dist/runtime/pages/admin/register.vue.d.ts +3 -0
  229. package/dist/runtime/pages/admin/users/[id].d.vue.ts +3 -0
  230. package/dist/runtime/pages/admin/users/[id].vue +337 -0
  231. package/dist/runtime/pages/admin/users/[id].vue.d.ts +3 -0
  232. package/dist/runtime/pages/admin/users/create.d.vue.ts +3 -0
  233. package/dist/runtime/pages/admin/users/create.vue +201 -0
  234. package/dist/runtime/pages/admin/users/create.vue.d.ts +3 -0
  235. package/dist/runtime/pages/admin/users/index.d.vue.ts +3 -0
  236. package/dist/runtime/pages/admin/users/index.vue +329 -0
  237. package/dist/runtime/pages/admin/users/index.vue.d.ts +3 -0
  238. package/dist/runtime/pages/index.d.vue.ts +3 -0
  239. package/dist/runtime/pages/index.vue +399 -0
  240. package/dist/runtime/pages/index.vue.d.ts +3 -0
  241. package/dist/runtime/server/api/_katecms/auth/login.post.d.ts +5 -0
  242. package/dist/runtime/server/api/_katecms/auth/login.post.js +44 -0
  243. package/dist/runtime/server/api/_katecms/auth/logout.post.d.ts +4 -0
  244. package/dist/runtime/server/api/_katecms/auth/logout.post.js +6 -0
  245. package/dist/runtime/server/api/_katecms/auth/register.post.d.ts +19 -0
  246. package/dist/runtime/server/api/_katecms/auth/register.post.js +83 -0
  247. package/dist/runtime/server/api/_katecms/auth/state.get.d.ts +9 -0
  248. package/dist/runtime/server/api/_katecms/auth/state.get.js +12 -0
  249. package/dist/runtime/server/api/_katecms/collections/[collection]/[id].delete.d.ts +15 -0
  250. package/dist/runtime/server/api/_katecms/collections/[collection]/[id].delete.js +59 -0
  251. package/dist/runtime/server/api/_katecms/collections/[collection]/[id].get.d.ts +4 -0
  252. package/dist/runtime/server/api/_katecms/collections/[collection]/[id].get.js +50 -0
  253. package/dist/runtime/server/api/_katecms/collections/[collection]/[id].patch.d.ts +4 -0
  254. package/dist/runtime/server/api/_katecms/collections/[collection]/[id].patch.js +130 -0
  255. package/dist/runtime/server/api/_katecms/collections/[collection]/revisions/[revisionId].post.d.ts +4 -0
  256. package/dist/runtime/server/api/_katecms/collections/[collection]/revisions/[revisionId].post.js +123 -0
  257. package/dist/runtime/server/api/_katecms/collections/[collection]/revisions.get.d.ts +6 -0
  258. package/dist/runtime/server/api/_katecms/collections/[collection]/revisions.get.js +31 -0
  259. package/dist/runtime/server/api/_katecms/collections/[collection].get.d.ts +8 -0
  260. package/dist/runtime/server/api/_katecms/collections/[collection].get.js +135 -0
  261. package/dist/runtime/server/api/_katecms/collections/[collection].post.d.ts +4 -0
  262. package/dist/runtime/server/api/_katecms/collections/[collection].post.js +91 -0
  263. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].delete.d.ts +7 -0
  264. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].delete.js +31 -0
  265. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].get.d.ts +4 -0
  266. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].get.js +45 -0
  267. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].patch.d.ts +4 -0
  268. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].patch.js +83 -0
  269. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary].get.d.ts +4 -0
  270. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary].get.js +38 -0
  271. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary].post.d.ts +4 -0
  272. package/dist/runtime/server/api/_katecms/dictionaries/[dictionary].post.js +64 -0
  273. package/dist/runtime/server/api/_katecms/media/[id]/regenerate.post.d.ts +8 -0
  274. package/dist/runtime/server/api/_katecms/media/[id]/regenerate.post.js +30 -0
  275. package/dist/runtime/server/api/_katecms/media/[id].delete.d.ts +7 -0
  276. package/dist/runtime/server/api/_katecms/media/[id].delete.js +22 -0
  277. package/dist/runtime/server/api/_katecms/media/[id].get.d.ts +9 -0
  278. package/dist/runtime/server/api/_katecms/media/[id].get.js +17 -0
  279. package/dist/runtime/server/api/_katecms/media/[id].patch.d.ts +6 -0
  280. package/dist/runtime/server/api/_katecms/media/[id].patch.js +48 -0
  281. package/dist/runtime/server/api/_katecms/media/index.get.d.ts +5 -0
  282. package/dist/runtime/server/api/_katecms/media/index.get.js +75 -0
  283. package/dist/runtime/server/api/_katecms/media/index.post.d.ts +9 -0
  284. package/dist/runtime/server/api/_katecms/media/index.post.js +84 -0
  285. package/dist/runtime/server/api/_katecms/media/regenerate.post.d.ts +7 -0
  286. package/dist/runtime/server/api/_katecms/media/regenerate.post.js +30 -0
  287. package/dist/runtime/server/api/_katecms/menu.get.d.ts +8 -0
  288. package/dist/runtime/server/api/_katecms/menu.get.js +14 -0
  289. package/dist/runtime/server/api/_katecms/oembed.get.d.ts +2 -0
  290. package/dist/runtime/server/api/_katecms/oembed.get.js +53 -0
  291. package/dist/runtime/server/api/_katecms/options/[page].get.d.ts +7 -0
  292. package/dist/runtime/server/api/_katecms/options/[page].get.js +28 -0
  293. package/dist/runtime/server/api/_katecms/options/[page].patch.d.ts +4 -0
  294. package/dist/runtime/server/api/_katecms/options/[page].patch.js +36 -0
  295. package/dist/runtime/server/api/_katecms/query.get.d.ts +24 -0
  296. package/dist/runtime/server/api/_katecms/query.get.js +270 -0
  297. package/dist/runtime/server/api/_katecms/relation/entries.get.d.ts +17 -0
  298. package/dist/runtime/server/api/_katecms/relation/entries.get.js +74 -0
  299. package/dist/runtime/server/api/_katecms/relation/terms.get.d.ts +17 -0
  300. package/dist/runtime/server/api/_katecms/relation/terms.get.js +51 -0
  301. package/dist/runtime/server/api/_katecms/resolve.get.d.ts +17 -0
  302. package/dist/runtime/server/api/_katecms/resolve.get.js +116 -0
  303. package/dist/runtime/server/api/_katecms/terms.get.d.ts +20 -0
  304. package/dist/runtime/server/api/_katecms/terms.get.js +201 -0
  305. package/dist/runtime/server/api/_katecms/users/[id].delete.d.ts +11 -0
  306. package/dist/runtime/server/api/_katecms/users/[id].delete.js +45 -0
  307. package/dist/runtime/server/api/_katecms/users/[id].patch.d.ts +19 -0
  308. package/dist/runtime/server/api/_katecms/users/[id].patch.js +129 -0
  309. package/dist/runtime/server/api/_katecms/users.get.d.ts +10 -0
  310. package/dist/runtime/server/api/_katecms/users.get.js +34 -0
  311. package/dist/runtime/server/api/_katecms/users.post.d.ts +10 -0
  312. package/dist/runtime/server/api/_katecms/users.post.js +62 -0
  313. package/dist/runtime/server/api/uploads/[...key].get.d.ts +3 -0
  314. package/dist/runtime/server/api/uploads/[...key].get.js +28 -0
  315. package/dist/runtime/server/kit.d.ts +5 -0
  316. package/dist/runtime/server/kit.js +5 -0
  317. package/dist/runtime/server/middleware/admin-headers.d.ts +3 -0
  318. package/dist/runtime/server/middleware/admin-headers.js +12 -0
  319. package/dist/runtime/server/plugins/auto-migrate.d.ts +2 -0
  320. package/dist/runtime/server/plugins/auto-migrate.js +45 -0
  321. package/dist/runtime/server/tsconfig.json +3 -0
  322. package/dist/runtime/server/utils/auth-attempts.d.ts +22 -0
  323. package/dist/runtime/server/utils/auth-attempts.js +42 -0
  324. package/dist/runtime/server/utils/auth-rate-limit.d.ts +11 -0
  325. package/dist/runtime/server/utils/auth-rate-limit.js +36 -0
  326. package/dist/runtime/server/utils/client-address.d.ts +16 -0
  327. package/dist/runtime/server/utils/client-address.js +23 -0
  328. package/dist/runtime/server/utils/collections.d.ts +42 -0
  329. package/dist/runtime/server/utils/collections.js +300 -0
  330. package/dist/runtime/server/utils/db.d.ts +3 -0
  331. package/dist/runtime/server/utils/db.js +25 -0
  332. package/dist/runtime/server/utils/dictionaries.d.ts +53 -0
  333. package/dist/runtime/server/utils/dictionaries.js +301 -0
  334. package/dist/runtime/server/utils/media-list.d.ts +18 -0
  335. package/dist/runtime/server/utils/media-list.js +84 -0
  336. package/dist/runtime/server/utils/media.d.ts +12 -0
  337. package/dist/runtime/server/utils/media.js +77 -0
  338. package/dist/runtime/server/utils/oembed-fetch.d.ts +4 -0
  339. package/dist/runtime/server/utils/oembed-fetch.js +142 -0
  340. package/dist/runtime/server/utils/options.d.ts +17 -0
  341. package/dist/runtime/server/utils/options.js +66 -0
  342. package/dist/runtime/server/utils/permissions.d.ts +13 -0
  343. package/dist/runtime/server/utils/permissions.js +20 -0
  344. package/dist/runtime/server/utils/public-fields-query.d.ts +6 -0
  345. package/dist/runtime/server/utils/public-fields-query.js +8 -0
  346. package/dist/runtime/server/utils/public-term.d.ts +8 -0
  347. package/dist/runtime/server/utils/public-term.js +80 -0
  348. package/dist/runtime/server/utils/regenerate.d.ts +12 -0
  349. package/dist/runtime/server/utils/regenerate.js +40 -0
  350. package/dist/runtime/server/utils/relation.d.ts +18 -0
  351. package/dist/runtime/server/utils/relation.js +77 -0
  352. package/dist/runtime/server/utils/request-address.d.ts +6 -0
  353. package/dist/runtime/server/utils/request-address.js +10 -0
  354. package/dist/runtime/server/utils/revisions.d.ts +20 -0
  355. package/dist/runtime/server/utils/revisions.js +172 -0
  356. package/dist/runtime/server/utils/session.d.ts +18 -0
  357. package/dist/runtime/server/utils/session.js +71 -0
  358. package/dist/runtime/server/utils/upload-headers.d.ts +2 -0
  359. package/dist/runtime/server/utils/upload-headers.js +30 -0
  360. package/dist/runtime/server/utils/users.d.ts +13 -0
  361. package/dist/runtime/server/utils/users.js +47 -0
  362. package/dist/runtime/utils/admin-users.d.ts +20 -0
  363. package/dist/runtime/utils/admin-users.js +19 -0
  364. package/dist/runtime/utils/auth-error.d.ts +6 -0
  365. package/dist/runtime/utils/auth-error.js +11 -0
  366. package/dist/runtime/utils/cms-paths.d.ts +5 -0
  367. package/dist/runtime/utils/cms-paths.js +13 -0
  368. package/dist/runtime/utils/collections.d.ts +176 -0
  369. package/dist/runtime/utils/collections.js +30 -0
  370. package/dist/runtime/utils/dictionaries.d.ts +65 -0
  371. package/dist/runtime/utils/dictionaries.js +14 -0
  372. package/dist/runtime/utils/field-errors.d.ts +4 -0
  373. package/dist/runtime/utils/field-errors.js +9 -0
  374. package/dist/runtime/utils/field-values.d.ts +19 -0
  375. package/dist/runtime/utils/field-values.js +82 -0
  376. package/dist/runtime/utils/helpers.d.ts +4 -0
  377. package/dist/runtime/utils/helpers.js +20 -0
  378. package/dist/runtime/utils/media-library-query.d.ts +54 -0
  379. package/dist/runtime/utils/media-library-query.js +190 -0
  380. package/dist/runtime/utils/options.d.ts +19 -0
  381. package/dist/runtime/utils/options.js +3 -0
  382. package/dist/runtime/utils/preview.d.ts +22 -0
  383. package/dist/runtime/utils/preview.js +33 -0
  384. package/dist/runtime/utils/relation.d.ts +33 -0
  385. package/dist/runtime/utils/relation.js +23 -0
  386. package/dist/runtime/utils/slugify.d.ts +2 -0
  387. package/dist/runtime/utils/slugify.js +4 -0
  388. package/dist/types.d.mts +7 -0
  389. package/package.json +84 -3
  390. package/src/admin-components.ts +124 -0
  391. package/src/module.ts +592 -0
  392. package/src/runtime/assets/img/katecms-logo.svg +17 -0
  393. package/src/runtime/assets/styles/_functions.scss +70 -0
  394. package/src/runtime/assets/styles/_index.scss +3 -0
  395. package/src/runtime/assets/styles/_mixins.scss +256 -0
  396. package/src/runtime/assets/styles/_variables.scss +35 -0
  397. package/src/runtime/composables/getCollection.ts +253 -0
  398. package/src/runtime/composables/getOptions.ts +42 -0
  399. package/src/runtime/composables/getQueryCollection.ts +325 -0
  400. package/src/runtime/composables/getTerms.ts +231 -0
  401. package/src/runtime/composables/useAuth.ts +43 -0
  402. package/src/runtime/composables/useAuthCooldown.ts +52 -0
  403. package/src/runtime/composables/useCmsPaths.ts +24 -0
  404. package/src/runtime/composables/useKateCmsExtensions.ts +81 -0
  405. package/src/runtime/composables/useMediaLibrary.ts +168 -0
  406. package/src/runtime/composables/useMenuAccess.ts +25 -0
  407. package/src/runtime/internal/admin/AdminHeader.vue +106 -0
  408. package/src/runtime/internal/admin/AppMenu.vue +290 -0
  409. package/src/runtime/internal/admin/AppUser.vue +260 -0
  410. package/src/runtime/internal/admin/CollectionEntryForm.vue +1044 -0
  411. package/src/runtime/internal/admin/ConfirmDialog.vue +164 -0
  412. package/src/runtime/internal/admin/DictionaryTermForm.vue +400 -0
  413. package/src/runtime/internal/admin/EntryRevisions.vue +145 -0
  414. package/src/runtime/internal/admin/MediaLibraryFilters.vue +186 -0
  415. package/src/runtime/internal/admin/MediaLibraryModal.vue +526 -0
  416. package/src/runtime/internal/admin/OptionPageForm.vue +277 -0
  417. package/src/runtime/internal/admin/UserAvatarField.vue +337 -0
  418. package/src/runtime/internal/fields/AccordionField.vue +258 -0
  419. package/src/runtime/internal/fields/ButtonGroupField.vue +144 -0
  420. package/src/runtime/internal/fields/CheckboxField.vue +228 -0
  421. package/src/runtime/internal/fields/ColorPickerField.vue +926 -0
  422. package/src/runtime/internal/fields/DatePickerField.vue +33 -0
  423. package/src/runtime/internal/fields/DateTimePickerField.vue +33 -0
  424. package/src/runtime/internal/fields/DictionaryField.vue +403 -0
  425. package/src/runtime/internal/fields/EmailField.vue +28 -0
  426. package/src/runtime/internal/fields/FileField.vue +480 -0
  427. package/src/runtime/internal/fields/FlexibleContentField.vue +1296 -0
  428. package/src/runtime/internal/fields/GalleryField.vue +677 -0
  429. package/src/runtime/internal/fields/GroupField.vue +136 -0
  430. package/src/runtime/internal/fields/ImageField.vue +730 -0
  431. package/src/runtime/internal/fields/ImageSelectField.vue +213 -0
  432. package/src/runtime/internal/fields/LinkField.vue +338 -0
  433. package/src/runtime/internal/fields/NumberField.vue +32 -0
  434. package/src/runtime/internal/fields/OembedField.vue +187 -0
  435. package/src/runtime/internal/fields/OpenStreetMapField.vue +1716 -0
  436. package/src/runtime/internal/fields/PageLinkField.vue +186 -0
  437. package/src/runtime/internal/fields/PasswordField.vue +127 -0
  438. package/src/runtime/internal/fields/PostObjectField.vue +187 -0
  439. package/src/runtime/internal/fields/RadioField.vue +195 -0
  440. package/src/runtime/internal/fields/RangeField.vue +62 -0
  441. package/src/runtime/internal/fields/RelationshipField.vue +604 -0
  442. package/src/runtime/internal/fields/RepeaterField.vue +999 -0
  443. package/src/runtime/internal/fields/SelectField.vue +118 -0
  444. package/src/runtime/internal/fields/SeparatorField.vue +77 -0
  445. package/src/runtime/internal/fields/TabField.vue +249 -0
  446. package/src/runtime/internal/fields/TextField.vue +29 -0
  447. package/src/runtime/internal/fields/TextareaField.vue +61 -0
  448. package/src/runtime/internal/fields/TimePickerField.vue +31 -0
  449. package/src/runtime/internal/fields/TrueFalseField.vue +181 -0
  450. package/src/runtime/internal/fields/UrlField.vue +28 -0
  451. package/src/runtime/internal/fields/UserField.vue +203 -0
  452. package/src/runtime/internal/fields/WysiwygField.vue +1061 -0
  453. package/src/runtime/internal/parts/DateTimeControl.vue +657 -0
  454. package/src/runtime/internal/parts/FieldAddon.vue +60 -0
  455. package/src/runtime/internal/parts/FieldInstructions.vue +38 -0
  456. package/src/runtime/internal/parts/FieldLabel.vue +56 -0
  457. package/src/runtime/internal/parts/FieldWrapper.vue +63 -0
  458. package/src/runtime/internal/parts/ImageCropper.vue +415 -0
  459. package/src/runtime/internal/parts/InputControl.vue +189 -0
  460. package/src/runtime/internal/ui/UiButton.vue +274 -0
  461. package/src/runtime/internal/ui/UiNotice.vue +302 -0
  462. package/src/runtime/internal/ui/UiSelect.vue +1420 -0
  463. package/src/runtime/middleware/auth-guard.ts +52 -0
  464. package/src/runtime/pages/admin/collections/[id].vue +486 -0
  465. package/src/runtime/pages/admin/collections/create.vue +208 -0
  466. package/src/runtime/pages/admin/collections/index.vue +955 -0
  467. package/src/runtime/pages/admin/demo-fields.vue +1354 -0
  468. package/src/runtime/pages/admin/dictionaries/[id].vue +246 -0
  469. package/src/runtime/pages/admin/dictionaries/index.vue +438 -0
  470. package/src/runtime/pages/admin/index.vue +155 -0
  471. package/src/runtime/pages/admin/login.vue +159 -0
  472. package/src/runtime/pages/admin/media.vue +1176 -0
  473. package/src/runtime/pages/admin/options/[page].vue +174 -0
  474. package/src/runtime/pages/admin/register.vue +179 -0
  475. package/src/runtime/pages/admin/users/[id].vue +382 -0
  476. package/src/runtime/pages/admin/users/create.vue +232 -0
  477. package/src/runtime/pages/admin/users/index.vue +374 -0
  478. package/src/runtime/pages/index.vue +265 -0
  479. package/src/runtime/server/api/_katecms/auth/login.post.ts +62 -0
  480. package/src/runtime/server/api/_katecms/auth/logout.post.ts +7 -0
  481. package/src/runtime/server/api/_katecms/auth/register.post.ts +112 -0
  482. package/src/runtime/server/api/_katecms/auth/state.get.ts +19 -0
  483. package/src/runtime/server/api/_katecms/collections/[collection]/[id].delete.ts +77 -0
  484. package/src/runtime/server/api/_katecms/collections/[collection]/[id].get.ts +57 -0
  485. package/src/runtime/server/api/_katecms/collections/[collection]/[id].patch.ts +157 -0
  486. package/src/runtime/server/api/_katecms/collections/[collection]/revisions/[revisionId].post.ts +133 -0
  487. package/src/runtime/server/api/_katecms/collections/[collection]/revisions.get.ts +35 -0
  488. package/src/runtime/server/api/_katecms/collections/[collection].get.ts +177 -0
  489. package/src/runtime/server/api/_katecms/collections/[collection].post.ts +111 -0
  490. package/src/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].delete.ts +37 -0
  491. package/src/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].get.ts +51 -0
  492. package/src/runtime/server/api/_katecms/dictionaries/[dictionary]/[id].patch.ts +101 -0
  493. package/src/runtime/server/api/_katecms/dictionaries/[dictionary].get.ts +43 -0
  494. package/src/runtime/server/api/_katecms/dictionaries/[dictionary].post.ts +78 -0
  495. package/src/runtime/server/api/_katecms/media/[id]/regenerate.post.ts +39 -0
  496. package/src/runtime/server/api/_katecms/media/[id].delete.ts +28 -0
  497. package/src/runtime/server/api/_katecms/media/[id].get.ts +25 -0
  498. package/src/runtime/server/api/_katecms/media/[id].patch.ts +60 -0
  499. package/src/runtime/server/api/_katecms/media/index.get.ts +96 -0
  500. package/src/runtime/server/api/_katecms/media/index.post.ts +104 -0
  501. package/src/runtime/server/api/_katecms/media/regenerate.post.ts +38 -0
  502. package/src/runtime/server/api/_katecms/menu.get.ts +19 -0
  503. package/src/runtime/server/api/_katecms/oembed.get.ts +62 -0
  504. package/src/runtime/server/api/_katecms/options/[page].get.ts +35 -0
  505. package/src/runtime/server/api/_katecms/options/[page].patch.ts +46 -0
  506. package/src/runtime/server/api/_katecms/query.get.ts +332 -0
  507. package/src/runtime/server/api/_katecms/relation/entries.get.ts +98 -0
  508. package/src/runtime/server/api/_katecms/relation/terms.get.ts +61 -0
  509. package/src/runtime/server/api/_katecms/resolve.get.ts +148 -0
  510. package/src/runtime/server/api/_katecms/terms.get.ts +258 -0
  511. package/src/runtime/server/api/_katecms/users/[id].delete.ts +57 -0
  512. package/src/runtime/server/api/_katecms/users/[id].patch.ts +177 -0
  513. package/src/runtime/server/api/_katecms/users.get.ts +48 -0
  514. package/src/runtime/server/api/_katecms/users.post.ts +85 -0
  515. package/src/runtime/server/api/uploads/[...key].get.ts +33 -0
  516. package/src/runtime/server/kit.ts +5 -0
  517. package/src/runtime/server/middleware/admin-headers.ts +14 -0
  518. package/src/runtime/server/plugins/auto-migrate.ts +53 -0
  519. package/src/runtime/server/tsconfig.json +3 -0
  520. package/src/runtime/server/utils/auth-attempts.ts +71 -0
  521. package/src/runtime/server/utils/auth-rate-limit.ts +48 -0
  522. package/src/runtime/server/utils/client-address.ts +41 -0
  523. package/src/runtime/server/utils/collections.ts +381 -0
  524. package/src/runtime/server/utils/db.ts +36 -0
  525. package/src/runtime/server/utils/dictionaries.ts +397 -0
  526. package/src/runtime/server/utils/media-list.ts +131 -0
  527. package/src/runtime/server/utils/media.ts +94 -0
  528. package/src/runtime/server/utils/oembed-fetch.ts +157 -0
  529. package/src/runtime/server/utils/options.ts +86 -0
  530. package/src/runtime/server/utils/permissions.ts +44 -0
  531. package/src/runtime/server/utils/public-fields-query.ts +14 -0
  532. package/src/runtime/server/utils/public-term.ts +98 -0
  533. package/src/runtime/server/utils/regenerate.ts +56 -0
  534. package/src/runtime/server/utils/relation.ts +96 -0
  535. package/src/runtime/server/utils/request-address.ts +16 -0
  536. package/src/runtime/server/utils/revisions.ts +256 -0
  537. package/src/runtime/server/utils/session.ts +112 -0
  538. package/src/runtime/server/utils/upload-headers.ts +35 -0
  539. package/src/runtime/server/utils/users.ts +67 -0
  540. package/src/runtime/utils/admin-users.ts +43 -0
  541. package/src/runtime/utils/auth-error.ts +22 -0
  542. package/src/runtime/utils/cms-paths.ts +17 -0
  543. package/src/runtime/utils/collections.ts +228 -0
  544. package/src/runtime/utils/dictionaries.ts +89 -0
  545. package/src/runtime/utils/field-errors.ts +12 -0
  546. package/src/runtime/utils/field-values.ts +101 -0
  547. package/src/runtime/utils/helpers.ts +33 -0
  548. package/src/runtime/utils/media-library-query.ts +263 -0
  549. package/src/runtime/utils/options.ts +25 -0
  550. package/src/runtime/utils/preview.ts +56 -0
  551. package/src/runtime/utils/relation.ts +60 -0
  552. package/src/runtime/utils/slugify.ts +10 -0
@@ -0,0 +1,1061 @@
1
+ <script setup lang="ts">
2
+ import { computed, nextTick, ref, watch } from 'vue'
3
+ import { EditorContent, useEditor } from '@tiptap/vue-3'
4
+ import StarterKit from '@tiptap/starter-kit'
5
+ import { TextStyleKit } from '@tiptap/extension-text-style'
6
+ import TextAlign from '@tiptap/extension-text-align'
7
+ import { TableKit } from '@tiptap/extension-table'
8
+ import Subscript from '@tiptap/extension-subscript'
9
+ import Superscript from '@tiptap/extension-superscript'
10
+ import type { Field } from '@katecms/core'
11
+
12
+ type WysiwygFieldConfig = Extract<Field, { type: 'wysiwyg' }>
13
+ type BlockType = 'paragraph' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'pre'
14
+ type AlignType = 'left' | 'center' | 'right' | 'justify'
15
+ type TableCommand
16
+ = 'insert'
17
+ | 'addRowBefore'
18
+ | 'addRowAfter'
19
+ | 'deleteRow'
20
+ | 'addColumnBefore'
21
+ | 'addColumnAfter'
22
+ | 'deleteColumn'
23
+ | 'deleteTable'
24
+
25
+ const DEFAULT_FONT_SIZES = [
26
+ '8px', '10px', '12px', '14px', '16px', '20px', '24px',
27
+ '28px', '32px', '36px', '48px', '60px', '72px', '96px',
28
+ ]
29
+
30
+ const DEFAULT_COLOR_PALETTE = [
31
+ '#000000', '#1a1d27', '#6b7185', '#9ca3af', '#e2e4ec', '#ffffff',
32
+ '#f0453d', '#d97706', '#22b573', '#2F6FED', '#7c3aed', '#db2777',
33
+ '#fecaca', '#fde68a', '#bbf7d0', '#bfdbfe', '#ddd6fe', '#fbcfe8',
34
+ ]
35
+
36
+ const BLOCK_OPTIONS: { value: BlockType, label: string }[] = [
37
+ { value: 'paragraph', label: 'Paragraph' },
38
+ { value: 'h1', label: 'Heading 1' },
39
+ { value: 'h2', label: 'Heading 2' },
40
+ { value: 'h3', label: 'Heading 3' },
41
+ { value: 'h4', label: 'Heading 4' },
42
+ { value: 'h5', label: 'Heading 5' },
43
+ { value: 'h6', label: 'Heading 6' },
44
+ { value: 'pre', label: 'Preformatted' },
45
+ ]
46
+
47
+ const ALIGN_OPTIONS: { value: AlignType, label: string }[] = [
48
+ { value: 'left', label: 'Left' },
49
+ { value: 'center', label: 'Center' },
50
+ { value: 'right', label: 'Right' },
51
+ { value: 'justify', label: 'Justify' },
52
+ ]
53
+
54
+ const TABLE_OPTIONS: { value: TableCommand, label: string, inTable?: boolean }[] = [
55
+ { value: 'insert', label: 'Insert 3×3 table' },
56
+ { value: 'addRowBefore', label: 'Add row before', inTable: true },
57
+ { value: 'addRowAfter', label: 'Add row after', inTable: true },
58
+ { value: 'deleteRow', label: 'Delete row', inTable: true },
59
+ { value: 'addColumnBefore', label: 'Add column before', inTable: true },
60
+ { value: 'addColumnAfter', label: 'Add column after', inTable: true },
61
+ { value: 'deleteColumn', label: 'Delete column', inTable: true },
62
+ { value: 'deleteTable', label: 'Delete table', inTable: true },
63
+ ]
64
+
65
+ const props = withDefaults(defineProps<{
66
+ fieldKey: string
67
+ field?: WysiwygFieldConfig
68
+ }>(), {
69
+ field: () => ({ type: 'wysiwyg', label: '' }),
70
+ })
71
+
72
+ const model = defineModel<string>({ default: '' })
73
+
74
+ const rootClass = 'katecms-wysiwyg-field'
75
+ const isFullToolbar = computed(() => props.field?.toolbar !== 'basic')
76
+
77
+ const tabsMode = computed(() => props.field?.tabs ?? 'all')
78
+ const showTabSwitch = computed(() => tabsMode.value === 'all')
79
+ const activeTab = ref<'visual' | 'text'>(tabsMode.value === 'text' ? 'text' : 'visual')
80
+
81
+ const fontSizes = computed(() => {
82
+ const custom = props.field?.fontSize
83
+ if (Array.isArray(custom) && custom.length > 0) {
84
+ return custom.map(normalizeFontSize)
85
+ }
86
+ return DEFAULT_FONT_SIZES
87
+ })
88
+
89
+ const colorPalette = computed(() => {
90
+ const custom = props.field?.colorPalette
91
+ if (Array.isArray(custom) && custom.length > 0) {
92
+ return custom
93
+ }
94
+ return DEFAULT_COLOR_PALETTE
95
+ })
96
+
97
+ /** Bumps on every editor transaction so toolbar active-states stay in sync. */
98
+ const editorTick = ref(0)
99
+
100
+ const editor = useEditor({
101
+ content: model.value,
102
+ extensions: [
103
+ StarterKit.configure({
104
+ heading: { levels: [1, 2, 3, 4, 5, 6] },
105
+ link: {
106
+ openOnClick: false,
107
+ HTMLAttributes: {
108
+ rel: 'noopener noreferrer',
109
+ },
110
+ },
111
+ }),
112
+ TextStyleKit.configure({
113
+ backgroundColor: false,
114
+ fontFamily: false,
115
+ lineHeight: false,
116
+ }),
117
+ TextAlign.configure({
118
+ types: ['heading', 'paragraph'],
119
+ }),
120
+ Subscript,
121
+ Superscript,
122
+ TableKit.configure({
123
+ table: { resizable: true },
124
+ }),
125
+ ],
126
+ editorProps: {
127
+ attributes: { class: `${rootClass}__editable` },
128
+ },
129
+ onUpdate: ({ editor: instance }) => {
130
+ model.value = instance.getHTML()
131
+ },
132
+ onTransaction: () => {
133
+ editorTick.value += 1
134
+ },
135
+ })
136
+
137
+ watch(model, (value) => {
138
+ const instance = editor.value
139
+ if (instance && value !== instance.getHTML()) {
140
+ instance.commands.setContent(value || '', { emitUpdate: false })
141
+ }
142
+ })
143
+
144
+ const linkOpen = ref(false)
145
+ const linkUrl = ref('')
146
+ const linkUrlInput = ref<HTMLInputElement | null>(null)
147
+
148
+ function normalizeFontSize(value: string): string {
149
+ const trimmed = value.trim()
150
+ if (!trimmed) return trimmed
151
+ return /^\d+(?:\.\d+)?$/.test(trimmed) ? `${trimmed}px` : trimmed
152
+ }
153
+
154
+ function selectValue(event: Event): string {
155
+ return (event.target as HTMLSelectElement).value
156
+ }
157
+
158
+ const currentFontSize = computed(() => {
159
+ void editorTick.value
160
+ return editor.value?.getAttributes('textStyle').fontSize || ''
161
+ })
162
+
163
+ const currentBlock = computed<BlockType>(() => {
164
+ void editorTick.value
165
+ const e = editor.value
166
+ if (!e) return 'paragraph'
167
+ for (let level = 1; level <= 6; level++) {
168
+ if (e.isActive('heading', { level })) {
169
+ return `h${level}` as BlockType
170
+ }
171
+ }
172
+ if (e.isActive('codeBlock')) return 'pre'
173
+ return 'paragraph'
174
+ })
175
+
176
+ const currentAlign = computed<AlignType>(() => {
177
+ void editorTick.value
178
+ const e = editor.value
179
+ if (!e) return 'left'
180
+ for (const option of ALIGN_OPTIONS) {
181
+ if (e.isActive({ textAlign: option.value })) {
182
+ return option.value
183
+ }
184
+ }
185
+ return 'left'
186
+ })
187
+
188
+ const currentColor = computed(() => {
189
+ void editorTick.value
190
+ return editor.value?.getAttributes('textStyle').color || ''
191
+ })
192
+
193
+ const isInTable = computed(() => {
194
+ void editorTick.value
195
+ return !!editor.value?.isActive('table')
196
+ })
197
+
198
+ const isLinkActive = computed(() => {
199
+ void editorTick.value
200
+ return !!editor.value?.isActive('link')
201
+ })
202
+
203
+ function isMarkActive(name: string) {
204
+ void editorTick.value
205
+ return !!editor.value?.isActive(name)
206
+ }
207
+
208
+ function setFontSize(size: string) {
209
+ const e = editor.value
210
+ if (!e) return
211
+ if (!size) {
212
+ e.chain().focus().unsetFontSize().run()
213
+ }
214
+ else {
215
+ e.chain().focus().setFontSize(normalizeFontSize(size)).run()
216
+ }
217
+ }
218
+
219
+ function setBlockType(type: BlockType) {
220
+ const e = editor.value
221
+ if (!e) return
222
+ const chain = e.chain().focus()
223
+
224
+ if (type === 'paragraph') {
225
+ chain.setParagraph().run()
226
+ }
227
+ else if (type === 'pre') {
228
+ chain.toggleCodeBlock().run()
229
+ }
230
+ else {
231
+ const level = Number(type.slice(1)) as 1 | 2 | 3 | 4 | 5 | 6
232
+ chain.toggleHeading({ level }).run()
233
+ }
234
+ }
235
+
236
+ function setAlign(align: AlignType) {
237
+ editor.value?.chain().focus().setTextAlign(align).run()
238
+ }
239
+
240
+ function setColor(color: string) {
241
+ const e = editor.value
242
+ if (!e) return
243
+ if (!color) {
244
+ e.chain().focus().unsetColor().run()
245
+ }
246
+ else {
247
+ e.chain().focus().setColor(color).run()
248
+ }
249
+ }
250
+
251
+ function onFontSizeChange(event: Event) {
252
+ setFontSize(selectValue(event))
253
+ }
254
+
255
+ function onBlockChange(event: Event) {
256
+ setBlockType(selectValue(event) as BlockType)
257
+ }
258
+
259
+ function onAlignChange(event: Event) {
260
+ setAlign(selectValue(event) as AlignType)
261
+ }
262
+
263
+ function onColorChange(event: Event) {
264
+ setColor(selectValue(event))
265
+ }
266
+
267
+ function onTableChange(event: Event) {
268
+ const select = event.target as HTMLSelectElement
269
+ const command = select.value as TableCommand | ''
270
+ select.value = ''
271
+ if (!command) return
272
+
273
+ const e = editor.value
274
+ if (!e) return
275
+
276
+ if (command === 'insert') {
277
+ e.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
278
+ return
279
+ }
280
+
281
+ e.chain().focus()[command]().run()
282
+ }
283
+
284
+ const visibleTableOptions = computed(() => {
285
+ return TABLE_OPTIONS.filter(option => !option.inTable || isInTable.value)
286
+ })
287
+
288
+ function openLinkDialog() {
289
+ const e = editor.value
290
+ if (!e) return
291
+ linkUrl.value = e.getAttributes('link').href || 'https://'
292
+ linkOpen.value = true
293
+ nextTick(() => {
294
+ linkUrlInput.value?.focus()
295
+ linkUrlInput.value?.select()
296
+ })
297
+ }
298
+
299
+ function applyLink() {
300
+ const e = editor.value
301
+ if (!e) return
302
+
303
+ const href = linkUrl.value.trim()
304
+ if (!href || href === 'https://' || href === 'http://') {
305
+ e.chain().focus().extendMarkRange('link').unsetLink().run()
306
+ }
307
+ else {
308
+ e.chain().focus().extendMarkRange('link').setLink({ href }).run()
309
+ }
310
+
311
+ linkOpen.value = false
312
+ }
313
+
314
+ function removeLink() {
315
+ editor.value?.chain().focus().extendMarkRange('link').unsetLink().run()
316
+ linkOpen.value = false
317
+ }
318
+ </script>
319
+
320
+ <template>
321
+ <KateCmsFieldWrapper
322
+ :field-key="fieldKey"
323
+ :field="field"
324
+ label-tag="div"
325
+ >
326
+ <div :class="rootClass">
327
+ <div :class="`${rootClass}__wrap`">
328
+ <div
329
+ v-if="showTabSwitch"
330
+ :class="`${rootClass}__tabs`"
331
+ >
332
+ <button
333
+ type="button"
334
+ :class="[`${rootClass}__tab`, { 'is-active': activeTab === 'visual' }]"
335
+ @click="activeTab = 'visual'"
336
+ >
337
+ Visual
338
+ </button>
339
+ <button
340
+ type="button"
341
+ :class="[`${rootClass}__tab`, { 'is-active': activeTab === 'text' }]"
342
+ @click="activeTab = 'text'"
343
+ >
344
+ Text
345
+ </button>
346
+ </div>
347
+
348
+ <template v-if="activeTab === 'visual'">
349
+ <div
350
+ v-if="editor"
351
+ :class="`${rootClass}__toolbar`"
352
+ >
353
+ <!-- Font size -->
354
+ <div :class="`${rootClass}__group`">
355
+ <select
356
+ :class="`${rootClass}__select`"
357
+ title="Font size"
358
+ aria-label="Font size"
359
+ :value="currentFontSize"
360
+ @change="onFontSizeChange"
361
+ >
362
+ <option value="">
363
+ Size
364
+ </option>
365
+ <option
366
+ v-for="size in fontSizes"
367
+ :key="size"
368
+ :value="size"
369
+ >
370
+ {{ size }}
371
+ </option>
372
+ </select>
373
+ </div>
374
+
375
+ <!-- Block type -->
376
+ <div :class="`${rootClass}__group`">
377
+ <select
378
+ :class="`${rootClass}__select`"
379
+ title="Block type"
380
+ aria-label="Block type"
381
+ :value="currentBlock"
382
+ @change="onBlockChange"
383
+ >
384
+ <option
385
+ v-for="option in BLOCK_OPTIONS"
386
+ :key="option.value"
387
+ :value="option.value"
388
+ >
389
+ {{ option.label }}
390
+ </option>
391
+ </select>
392
+ </div>
393
+
394
+ <span :class="`${rootClass}__sep`" />
395
+
396
+ <!-- Inline marks -->
397
+ <div :class="`${rootClass}__group`">
398
+ <button
399
+ type="button"
400
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('bold') }]"
401
+ title="Bold"
402
+ aria-label="Bold"
403
+ @click="editor.chain().focus().toggleBold().run()"
404
+ >
405
+ <svg
406
+ xmlns="http://www.w3.org/2000/svg"
407
+ viewBox="0 0 640 640"
408
+ >
409
+ <path
410
+ d="M160 96C142.3 96 128 110.3 128 128C128 145.7 142.3 160 160 160L192 160L192 480L160 480C142.3 480 128 494.3 128 512C128 529.7 142.3 544 160 544L384 544C454.7 544 512 486.7 512 416C512 369.5 487.2 328.7 450 306.3C468.7 284 480 255.3 480 224C480 153.3 422.7 96 352 96L160 96zM416 224C416 259.3 387.3 288 352 288L256 288L256 160L352 160C387.3 160 416 188.7 416 224zM256 480L256 352L384 352C419.3 352 448 380.7 448 416C448 451.3 419.3 480 384 480L256 480z"
411
+ />
412
+ </svg>
413
+ </button>
414
+ <button
415
+ type="button"
416
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('italic') }]"
417
+ title="Italic"
418
+ aria-label="Italic"
419
+ @click="editor.chain().focus().toggleItalic().run()"
420
+ >
421
+ <svg
422
+ xmlns="http://www.w3.org/2000/svg"
423
+ viewBox="0 0 640 640"
424
+ >
425
+ <path
426
+ d="M256 128C256 110.3 270.3 96 288 96L480 96C497.7 96 512 110.3 512 128C512 145.7 497.7 160 480 160L421.3 160L288 480L352 480C369.7 480 384 494.3 384 512C384 529.7 369.7 544 352 544L160 544C142.3 544 128 529.7 128 512C128 494.3 142.3 480 160 480L218.7 480L352 160L288 160C270.3 160 256 145.7 256 128z"
427
+ />
428
+ </svg>
429
+ </button>
430
+ <button
431
+ type="button"
432
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('underline') }]"
433
+ title="Underline"
434
+ aria-label="Underline"
435
+ @click="editor.chain().focus().toggleUnderline().run()"
436
+ >
437
+ <svg
438
+ xmlns="http://www.w3.org/2000/svg"
439
+ viewBox="0 0 640 640"
440
+ >
441
+ <path
442
+ d="M128 96C128 78.3 142.3 64 160 64L224 64C241.7 64 256 78.3 256 96C256 113.7 241.7 128 224 128L224 288C224 341 267 384 320 384C373 384 416 341 416 288L416 128C398.3 128 384 113.7 384 96C384 78.3 398.3 64 416 64L480 64C497.7 64 512 78.3 512 96C512 113.7 497.7 128 480 128L480 288C480 376.4 408.4 448 320 448C231.6 448 160 376.4 160 288L160 128C142.3 128 128 113.7 128 96zM128 544C128 526.3 142.3 512 160 512L480 512C497.7 512 512 526.3 512 544C512 561.7 497.7 576 480 576L160 576C142.3 576 128 561.7 128 544z"
443
+ />
444
+ </svg>
445
+ </button>
446
+ <button
447
+ type="button"
448
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('strike') }]"
449
+ title="Strikethrough"
450
+ aria-label="Strikethrough"
451
+ @click="editor.chain().focus().toggleStrike().run()"
452
+ >
453
+ <svg
454
+ xmlns="http://www.w3.org/2000/svg"
455
+ viewBox="0 0 640 640"
456
+ >
457
+ <path
458
+ d="M160 221.5C160 152.2 216.2 96 285.5 96L432 96C449.7 96 464 110.3 464 128C464 145.7 449.7 160 432 160L285.5 160C251.5 160 224 187.5 224 221.5C224 252.5 247.1 278.7 277.9 282.5L322 288L544 288C561.7 288 576 302.3 576 320C576 337.7 561.7 352 544 352L96 352C78.3 352 64 337.7 64 320C64 302.3 78.3 288 96 288L179.1 288C167 268.6 160 245.8 160 221.5zM413.2 400L478.7 400C479.6 406.1 480.1 412.2 480.1 418.5C480.1 487.8 423.9 544 354.6 544L208 544C190.3 544 176 529.7 176 512C176 494.3 190.3 480 208 480L354.5 480C388.5 480 416 452.5 416 418.5C416 412.1 415 405.8 413.2 400z"
459
+ />
460
+ </svg>
461
+ </button>
462
+ <template v-if="isFullToolbar">
463
+ <button
464
+ type="button"
465
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('superscript') }]"
466
+ title="Superscript"
467
+ aria-label="Superscript"
468
+ @click="editor.chain().focus().toggleSuperscript().run()"
469
+ >
470
+ <svg
471
+ xmlns="http://www.w3.org/2000/svg"
472
+ viewBox="0 0 640 640"
473
+ >
474
+ <path
475
+ d="M576 96C576 84.9 570.3 74.6 560.8 68.8C551.3 63 539.6 62.4 529.7 67.4L497.7 83.4C481.9 91.3 475.5 110.5 483.4 126.3C489 137.5 500.3 144 512 144L512 224C494.3 224 480 238.3 480 256C480 273.7 494.3 288 512 288L576 288C593.7 288 608 273.7 608 256C608 238.3 593.7 224 576 224L576 96zM128 128C110.3 128 96 142.3 96 160C96 177.7 110.3 192 128 192L143.3 192L232.9 320L143.3 448L128 448C110.3 448 96 462.3 96 480C96 497.7 110.3 512 128 512L160 512C170.4 512 180.2 506.9 186.2 498.4L272 375.8L357.8 498.4C363.8 507 373.6 512 384 512L416 512C433.7 512 448 497.7 448 480C448 462.3 433.7 448 416 448L400.7 448L311.1 320L400.7 192L416 192C433.7 192 448 177.7 448 160C448 142.3 433.7 128 416 128L384 128C373.6 128 363.8 133.1 357.8 141.6L272 264.2L186.2 141.6C180.2 133.1 170.4 128 160 128L128 128z"
476
+ />
477
+ </svg>
478
+ </button>
479
+ <button
480
+ type="button"
481
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('subscript') }]"
482
+ title="Subscript"
483
+ aria-label="Subscript"
484
+ @click="editor.chain().focus().toggleSubscript().run()"
485
+ >
486
+ <svg
487
+ xmlns="http://www.w3.org/2000/svg"
488
+ viewBox="0 0 640 640"
489
+ >
490
+ <path
491
+ d="M128 128C110.3 128 96 142.3 96 160C96 177.7 110.3 192 128 192L143.3 192L232.9 320L143.3 448L128 448C110.3 448 96 462.3 96 480C96 497.7 110.3 512 128 512L160 512C170.4 512 180.2 506.9 186.2 498.4L272 375.8L357.8 498.4C363.8 507 373.6 512 384 512L416 512C433.7 512 448 497.7 448 480C448 462.3 433.7 448 416 448L400.7 448L311.1 320L400.7 192L416 192C433.7 192 448 177.7 448 160C448 142.3 433.7 128 416 128L384 128C373.6 128 363.8 133.1 357.8 141.6L272 264.2L186.2 141.6C180.2 133.1 170.4 128 160 128L128 128zM576 384C576 372.9 570.3 362.6 560.8 356.8C551.3 351 539.6 350.4 529.7 355.4L497.7 371.4C481.9 379.3 475.5 398.5 483.4 414.3C489 425.5 500.3 432 512 432L512 512C494.3 512 480 526.3 480 544C480 561.7 494.3 576 512 576L576 576C593.7 576 608 561.7 608 544C608 526.3 593.7 512 576 512L576 384z"
492
+ />
493
+ </svg>
494
+ </button>
495
+ <button
496
+ type="button"
497
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('code') }]"
498
+ title="Code"
499
+ aria-label="Code"
500
+ @click="editor.chain().focus().toggleCode().run()"
501
+ >
502
+ <svg
503
+ xmlns="http://www.w3.org/2000/svg"
504
+ viewBox="0 0 640 640"
505
+ >
506
+ <path
507
+ d="M392.8 65.2C375.8 60.3 358.1 70.2 353.2 87.2L225.2 535.2C220.3 552.2 230.2 569.9 247.2 574.8C264.2 579.7 281.9 569.8 286.8 552.8L414.8 104.8C419.7 87.8 409.8 70.1 392.8 65.2zM457.4 201.3C444.9 213.8 444.9 234.1 457.4 246.6L530.8 320L457.4 393.4C444.9 405.9 444.9 426.2 457.4 438.7C469.9 451.2 490.2 451.2 502.7 438.7L598.7 342.7C611.2 330.2 611.2 309.9 598.7 297.4L502.7 201.4C490.2 188.9 469.9 188.9 457.4 201.4zM182.7 201.3C170.2 188.8 149.9 188.8 137.4 201.3L41.4 297.3C28.9 309.8 28.9 330.1 41.4 342.6L137.4 438.6C149.9 451.1 170.2 451.1 182.7 438.6C195.2 426.1 195.2 405.8 182.7 393.3L109.3 320L182.6 246.6C195.1 234.1 195.1 213.8 182.6 201.3z"
508
+ />
509
+ </svg>
510
+ </button>
511
+ </template>
512
+ </div>
513
+
514
+ <template v-if="isFullToolbar">
515
+ <span :class="`${rootClass}__sep`" />
516
+
517
+ <!-- Align -->
518
+ <div :class="`${rootClass}__group`">
519
+ <select
520
+ :class="`${rootClass}__select`"
521
+ title="Align"
522
+ aria-label="Align"
523
+ :value="currentAlign"
524
+ @change="onAlignChange"
525
+ >
526
+ <option
527
+ v-for="option in ALIGN_OPTIONS"
528
+ :key="option.value"
529
+ :value="option.value"
530
+ >
531
+ {{ option.label }}
532
+ </option>
533
+ </select>
534
+ </div>
535
+
536
+ <span :class="`${rootClass}__sep`" />
537
+ </template>
538
+
539
+ <!-- Blockquote + lists -->
540
+ <div :class="`${rootClass}__group`">
541
+ <button
542
+ v-if="isFullToolbar"
543
+ type="button"
544
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('blockquote') }]"
545
+ title="Blockquote"
546
+ aria-label="Blockquote"
547
+ @click="editor.chain().focus().toggleBlockquote().run()"
548
+ >
549
+ <svg
550
+ xmlns="http://www.w3.org/2000/svg"
551
+ viewBox="0 0 640 640"
552
+ >
553
+ <path
554
+ d="M236.986 199.117C251.137 189.275 269.836 177.665 293.083 164.417L266.55 120C251.137 129.338 232.185 141.452 209.442 156.215C186.7 170.978 165.222 189.022 145.006 210.221C124.952 231.349 108.019 255.228 94.7207 281.136C80.8227 307.256 74 336.404 74 368.455C74 413.88 83.0969 450.474 101.417 478.612C119.611 506.246 150.06 520 192.385 520C219.55 520 240.776 511.167 256.063 493.376C270.94 477.502 279.402 456.689 279.817 434.953C279.817 405.931 270.972 383.975 253.158 369.212C235.848 353.943 211.969 346.246 181.394 346.246H145.764C148.797 320.631 153.977 299.558 161.304 283.407C169.303 266.218 180.057 250.447 193.144 236.719C206.183 222.511 220.982 209.888 236.986 199.117ZM510.776 199.117C525.053 189.275 543.878 177.665 567 164.417L540.468 120C525.053 129.338 506.102 141.452 483.36 156.215C460.617 170.978 439.138 189.022 418.923 210.221C398.869 231.349 381.936 255.228 368.638 281.136C354.739 307.256 347.917 336.404 347.917 368.455C347.917 413.88 357.014 450.474 375.334 478.612C393.527 506.246 423.977 520 466.303 520C493.467 520 514.692 511.167 529.981 493.376C544.856 477.502 553.318 456.689 553.733 434.953C553.733 405.931 544.89 383.975 527.074 369.212C509.766 353.943 485.887 346.246 455.31 346.246H419.681C421.613 324.94 426.635 304.027 434.589 284.164C441.918 267.76 452.784 252.114 467.061 236.845C480.085 222.547 494.759 209.967 510.776 199.117Z"
555
+ />
556
+ </svg>
557
+ </button>
558
+ <button
559
+ type="button"
560
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('bulletList') }]"
561
+ title="Bulleted list"
562
+ aria-label="Bulleted list"
563
+ @click="editor.chain().focus().toggleBulletList().run()"
564
+ >
565
+ <svg
566
+ xmlns="http://www.w3.org/2000/svg"
567
+ viewBox="0 0 640 640"
568
+ >
569
+ <path
570
+ d="M112 208C138.5 208 160 186.5 160 160C160 133.5 138.5 112 112 112C85.5 112 64 133.5 64 160C64 186.5 85.5 208 112 208zM256 128C238.3 128 224 142.3 224 160C224 177.7 238.3 192 256 192L544 192C561.7 192 576 177.7 576 160C576 142.3 561.7 128 544 128L256 128zM256 288C238.3 288 224 302.3 224 320C224 337.7 238.3 352 256 352L544 352C561.7 352 576 337.7 576 320C576 302.3 561.7 288 544 288L256 288zM256 448C238.3 448 224 462.3 224 480C224 497.7 238.3 512 256 512L544 512C561.7 512 576 497.7 576 480C576 462.3 561.7 448 544 448L256 448zM112 528C138.5 528 160 506.5 160 480C160 453.5 138.5 432 112 432C85.5 432 64 453.5 64 480C64 506.5 85.5 528 112 528zM160 320C160 293.5 138.5 272 112 272C85.5 272 64 293.5 64 320C64 346.5 85.5 368 112 368C138.5 368 160 346.5 160 320z"
571
+ />
572
+ </svg>
573
+ </button>
574
+ <button
575
+ type="button"
576
+ :class="[`${rootClass}__btn`, { 'is-active': isMarkActive('orderedList') }]"
577
+ title="Numbered list"
578
+ aria-label="Numbered list"
579
+ @click="editor.chain().focus().toggleOrderedList().run()"
580
+ >
581
+ <svg
582
+ xmlns="http://www.w3.org/2000/svg"
583
+ viewBox="0 0 640 640"
584
+ >
585
+ <path
586
+ d="M64 136C64 122.8 74.7 112 88 112L136 112C149.3 112 160 122.7 160 136L160 240L184 240C197.3 240 208 250.7 208 264C208 277.3 197.3 288 184 288L88 288C74.7 288 64 277.3 64 264C64 250.7 74.7 240 88 240L112 240L112 160L88 160C74.7 160 64 149.3 64 136zM94.4 365.2C105.8 356.6 119.7 352 134 352L138.9 352C172.6 352 200 379.4 200 413.1C200 432.7 190.6 451 174.8 462.5L150.8 480L184 480C197.3 480 208 490.7 208 504C208 517.3 197.3 528 184 528L93.3 528C77.1 528 64 514.9 64 498.7C64 489.3 68.5 480.5 76.1 475L146.6 423.7C150 421.2 152 417.3 152 413.1C152 405.9 146.1 400 138.9 400L134 400C130.1 400 126.3 401.3 123.2 403.6L102.4 419.2C91.8 427.2 76.8 425 68.8 414.4C60.8 403.8 63 388.8 73.6 380.8L94.4 365.2zM288 128L544 128C561.7 128 576 142.3 576 160C576 177.7 561.7 192 544 192L288 192C270.3 192 256 177.7 256 160C256 142.3 270.3 128 288 128zM288 288L544 288C561.7 288 576 302.3 576 320C576 337.7 561.7 352 544 352L288 352C270.3 352 256 337.7 256 320C256 302.3 270.3 288 288 288zM288 448L544 448C561.7 448 576 462.3 576 480C576 497.7 561.7 512 544 512L288 512C270.3 512 256 497.7 256 480C256 462.3 270.3 448 288 448z"
587
+ />
588
+ </svg>
589
+ </button>
590
+ </div>
591
+
592
+ <template v-if="isFullToolbar">
593
+ <span :class="`${rootClass}__sep`" />
594
+
595
+ <!-- Text color -->
596
+ <div :class="`${rootClass}__group`">
597
+ <select
598
+ :class="`${rootClass}__select`"
599
+ title="Text color"
600
+ aria-label="Text color"
601
+ :value="currentColor"
602
+ @change="onColorChange"
603
+ >
604
+ <option value="">
605
+ Color
606
+ </option>
607
+ <option
608
+ v-for="color in colorPalette"
609
+ :key="color"
610
+ :value="color"
611
+ >
612
+ {{ color }}
613
+ </option>
614
+ </select>
615
+ </div>
616
+
617
+ <span :class="`${rootClass}__sep`" />
618
+ </template>
619
+
620
+ <!-- Link -->
621
+ <div :class="`${rootClass}__group`">
622
+ <button
623
+ type="button"
624
+ :class="[`${rootClass}__btn`, { 'is-active': isLinkActive || linkOpen }]"
625
+ title="Link"
626
+ aria-label="Link"
627
+ @click="openLinkDialog"
628
+ >
629
+ <svg
630
+ xmlns="http://www.w3.org/2000/svg"
631
+ viewBox="0 0 640 640"
632
+ >
633
+ <path
634
+ d="M451.5 160C434.9 160 418.8 164.5 404.7 172.7C388.9 156.7 370.5 143.3 350.2 133.2C378.4 109.2 414.3 96 451.5 96C537.9 96 608 166 608 252.5C608 294 591.5 333.8 562.2 363.1L491.1 434.2C461.8 463.5 422 480 380.5 480C294.1 480 224 410 224 323.5C224 322 224 320.5 224.1 319C224.6 301.3 239.3 287.4 257 287.9C274.7 288.4 288.6 303.1 288.1 320.8C288.1 321.7 288.1 322.6 288.1 323.4C288.1 374.5 329.5 415.9 380.6 415.9C405.1 415.9 428.6 406.2 446 388.8L517.1 317.7C534.4 300.4 544.2 276.8 544.2 252.3C544.2 201.2 502.8 159.8 451.7 159.8zM307.2 237.3C305.3 236.5 303.4 235.4 301.7 234.2C289.1 227.7 274.7 224 259.6 224C235.1 224 211.6 233.7 194.2 251.1L123.1 322.2C105.8 339.5 96 363.1 96 387.6C96 438.7 137.4 480.1 188.5 480.1C205 480.1 221.1 475.7 235.2 467.5C251 483.5 269.4 496.9 289.8 507C261.6 530.9 225.8 544.2 188.5 544.2C102.1 544.2 32 474.2 32 387.7C32 346.2 48.5 306.4 77.8 277.1L148.9 206C178.2 176.7 218 160.2 259.5 160.2C346.1 160.2 416 230.8 416 317.1C416 318.4 416 319.7 416 321C415.6 338.7 400.9 352.6 383.2 352.2C365.5 351.8 351.6 337.1 352 319.4C352 318.6 352 317.9 352 317.1C352 283.4 334 253.8 307.2 237.5z"
635
+ />
636
+ </svg>
637
+ </button>
638
+ </div>
639
+
640
+ <template v-if="isFullToolbar">
641
+ <span :class="`${rootClass}__sep`" />
642
+
643
+ <!-- Table -->
644
+ <div :class="`${rootClass}__group`">
645
+ <select
646
+ :class="[`${rootClass}__select`, { 'is-active': isInTable }]"
647
+ title="Table"
648
+ aria-label="Table"
649
+ value=""
650
+ @change="onTableChange"
651
+ >
652
+ <option
653
+ value=""
654
+ disabled
655
+ >
656
+ Table
657
+ </option>
658
+ <option
659
+ v-for="option in visibleTableOptions"
660
+ :key="option.value"
661
+ :value="option.value"
662
+ >
663
+ {{ option.label }}
664
+ </option>
665
+ </select>
666
+ </div>
667
+ </template>
668
+
669
+ <span :class="`${rootClass}__sep`" />
670
+
671
+ <!-- History -->
672
+ <div :class="`${rootClass}__group`">
673
+ <button
674
+ type="button"
675
+ :class="`${rootClass}__btn`"
676
+ title="Undo"
677
+ aria-label="Undo"
678
+ @click="editor.chain().focus().undo().run()"
679
+ >
680
+ Undo
681
+ </button>
682
+ <button
683
+ type="button"
684
+ :class="`${rootClass}__btn`"
685
+ title="Redo"
686
+ aria-label="Redo"
687
+ @click="editor.chain().focus().redo().run()"
688
+ >
689
+ Redo
690
+ </button>
691
+ </div>
692
+ </div>
693
+
694
+ <!-- Link popover -->
695
+ <div
696
+ v-if="linkOpen"
697
+ :class="`${rootClass}__link-bar`"
698
+ >
699
+ <label
700
+ :class="`${rootClass}__link-label`"
701
+ :for="`${fieldKey}-link-url`"
702
+ >
703
+ URL
704
+ </label>
705
+ <input
706
+ :id="`${fieldKey}-link-url`"
707
+ ref="linkUrlInput"
708
+ v-model="linkUrl"
709
+ type="url"
710
+ :class="`${rootClass}__link-input`"
711
+ placeholder="https://"
712
+ @keydown.enter.prevent="applyLink"
713
+ @keydown.esc.prevent="linkOpen = false"
714
+ >
715
+ <KateCmsUiButton
716
+ tag="button"
717
+ variant="small"
718
+ @click="applyLink"
719
+ >
720
+ Apply
721
+ </KateCmsUiButton>
722
+ <KateCmsUiButton
723
+ v-if="isLinkActive"
724
+ tag="button"
725
+ :variant="['red', 'small']"
726
+ @click="removeLink"
727
+ >
728
+ Unlink
729
+ </KateCmsUiButton>
730
+ <KateCmsUiButton
731
+ tag="button"
732
+ :variant="['secondary', 'small']"
733
+ @click="linkOpen = false"
734
+ >
735
+ Cancel
736
+ </KateCmsUiButton>
737
+ </div>
738
+
739
+ <EditorContent
740
+ :editor="editor"
741
+ :class="`${rootClass}__content`"
742
+ />
743
+ </template>
744
+
745
+ <textarea
746
+ v-else
747
+ v-model="model"
748
+ :class="`${rootClass}__textarea`"
749
+ rows="10"
750
+ />
751
+ </div>
752
+ </div>
753
+ </KateCmsFieldWrapper>
754
+ </template>
755
+
756
+ <style scoped lang="scss">
757
+ @use "../../assets/styles" as *;
758
+
759
+ $root: '.katecms-wysiwyg-field';
760
+
761
+ #{$root} {
762
+ &__wrap {
763
+ width: 100%;
764
+ max-width: 100%;
765
+ border: 1px solid $color-border;
766
+ border-radius: $border-radius;
767
+ overflow: hidden;
768
+ background: $color-surface;
769
+ }
770
+
771
+ &__tabs {
772
+ display: flex;
773
+ border-bottom: 1px solid $color-border;
774
+ }
775
+
776
+ &__tab {
777
+ padding: 8px 14px;
778
+ background-color: $color-bg;
779
+ border: 0;
780
+ border-right: 1px solid $color-border;
781
+ color: $color-muted;
782
+ cursor: pointer;
783
+
784
+ &.is-active {
785
+ background-color: $color-surface;
786
+ color: $color-ink;
787
+ font-weight: 600;
788
+ }
789
+
790
+ &:focus-visible {
791
+ outline: 2px solid $color-accent;
792
+ outline-offset: -2px;
793
+ }
794
+ }
795
+
796
+ &__toolbar {
797
+ display: flex;
798
+ flex-wrap: wrap;
799
+ align-items: center;
800
+ gap: 4px;
801
+ padding: 6px;
802
+ background-color: $color-bg;
803
+ border-bottom: 1px solid $color-border;
804
+ }
805
+
806
+ &__group {
807
+ display: inline-flex;
808
+ align-items: center;
809
+ gap: 2px;
810
+ }
811
+
812
+ &__sep {
813
+ width: 1px;
814
+ height: 22px;
815
+ margin: 0 4px;
816
+ background: $color-border;
817
+ }
818
+
819
+ &__select {
820
+ height: 30px;
821
+ max-width: 160px;
822
+ padding: 0 6px;
823
+ background-color: $color-surface;
824
+ border: 1px solid $color-border;
825
+ border-radius: $border-radius-inter;
826
+ color: $color-ink;
827
+ font-size: 12px;
828
+ cursor: pointer;
829
+
830
+ &.is-active {
831
+ border-color: $color-accent;
832
+ color: $color-accent;
833
+ }
834
+
835
+ &:focus-visible {
836
+ outline: 2px solid $color-accent;
837
+ outline-offset: 1px;
838
+ }
839
+ }
840
+
841
+ &__btn {
842
+ min-width: 32px;
843
+ height: 30px;
844
+ padding: 0 5px;
845
+ display: inline-flex;
846
+ align-items: center;
847
+ justify-content: center;
848
+ gap: 4px;
849
+ background-color: $color-surface;
850
+ border: 1px solid $color-border;
851
+ border-radius: $border-radius-inter;
852
+ color: $color-ink;
853
+ font-size: 12px;
854
+ line-height: 1;
855
+ cursor: pointer;
856
+ user-select: none;
857
+
858
+ &.is-active {
859
+ background-color: $color-accent-wash;
860
+ border-color: $color-accent;
861
+ color: $color-accent;
862
+ }
863
+
864
+ &:hover {
865
+ background-color: $color-accent-wash;
866
+ }
867
+
868
+ &:focus-visible {
869
+ outline: 2px solid $color-accent;
870
+ outline-offset: 1px;
871
+ }
872
+
873
+ svg {
874
+ display: block;
875
+
876
+ path {
877
+ fill: $color-muted;
878
+ }
879
+ }
880
+ }
881
+
882
+ &__link {
883
+ &-bar {
884
+ display: flex;
885
+ flex-wrap: wrap;
886
+ align-items: center;
887
+ gap: 6px;
888
+ padding: 8px;
889
+ background: $color-bg;
890
+ border-bottom: 1px solid $color-border;
891
+ }
892
+
893
+ &-label {
894
+ font-size: 12px;
895
+ color: $color-muted;
896
+ }
897
+
898
+ &-input {
899
+ flex: 1;
900
+ min-width: 180px;
901
+ height: 30px;
902
+ padding: 0 8px;
903
+ border: 1px solid $color-border;
904
+ border-radius: $border-radius-inter;
905
+ background: $color-surface;
906
+ color: $color-ink;
907
+
908
+ &:focus {
909
+ outline: none;
910
+ border-color: $color-accent;
911
+ }
912
+ }
913
+ }
914
+
915
+ &__content {
916
+ padding: math-rem(8);
917
+
918
+ :deep(#{$root}__editable) {
919
+ min-height: 180px;
920
+ outline: none;
921
+ color: $color-ink;
922
+
923
+ > * + * {
924
+ margin-top: 0.75em;
925
+ }
926
+
927
+ h1 {
928
+ font-size: 2em;
929
+ font-weight: 700;
930
+ }
931
+
932
+ h2 {
933
+ font-size: 1.5em;
934
+ font-weight: 700;
935
+ }
936
+
937
+ h3 {
938
+ font-size: 1.25em;
939
+ font-weight: 650;
940
+ }
941
+
942
+ h4 {
943
+ font-size: 1.1em;
944
+ font-weight: 650;
945
+ }
946
+
947
+ h5 {
948
+ font-size: 1em;
949
+ font-weight: 600;
950
+ }
951
+
952
+ h6 {
953
+ font-size: 0.9em;
954
+ font-weight: 600;
955
+ }
956
+
957
+ ul,
958
+ ol {
959
+ padding-left: 1.25em;
960
+ }
961
+
962
+ blockquote {
963
+ margin: 0;
964
+ padding-left: 0.9em;
965
+ border-left: 3px solid $color-border;
966
+ color: $color-muted;
967
+ }
968
+
969
+ code {
970
+ padding: 0.1em 0.35em;
971
+ border-radius: 3px;
972
+ background: $color-bg;
973
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
974
+ font-size: 0.9em;
975
+ }
976
+
977
+ pre {
978
+ margin: 0;
979
+ padding: 0.75em 1em;
980
+ border-radius: $border-radius-inter;
981
+ background: $color-bg;
982
+ overflow: auto;
983
+
984
+ code {
985
+ padding: 0;
986
+ background: transparent;
987
+ }
988
+ }
989
+
990
+ a {
991
+ color: $color-accent;
992
+ text-decoration: underline;
993
+ }
994
+
995
+ table {
996
+ width: 100%;
997
+ border-collapse: collapse;
998
+ table-layout: fixed;
999
+ overflow: hidden;
1000
+ }
1001
+
1002
+ td,
1003
+ th {
1004
+ min-width: 80px;
1005
+ padding: 6px 8px;
1006
+ border: 1px solid $color-border;
1007
+ vertical-align: top;
1008
+ box-sizing: border-box;
1009
+ position: relative;
1010
+ }
1011
+
1012
+ th {
1013
+ background: $color-bg;
1014
+ font-weight: 600;
1015
+ text-align: left;
1016
+ }
1017
+
1018
+ .selectedCell::after {
1019
+ content: '';
1020
+ position: absolute;
1021
+ inset: 0;
1022
+ background: color-alpha($color-accent, 0.12);
1023
+ pointer-events: none;
1024
+ z-index: 1;
1025
+ }
1026
+
1027
+ .column-resize-handle {
1028
+ position: absolute;
1029
+ right: -2px;
1030
+ top: 0;
1031
+ bottom: 0;
1032
+ width: 4px;
1033
+ background: $color-accent;
1034
+ pointer-events: none;
1035
+ }
1036
+
1037
+ &.resize-cursor {
1038
+ cursor: col-resize;
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ &__textarea {
1044
+ width: 100%;
1045
+ border: 0;
1046
+ padding: 10px;
1047
+ resize: vertical;
1048
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1049
+ color: $color-ink;
1050
+ background: $color-surface;
1051
+
1052
+ &:focus {
1053
+ outline: none;
1054
+ }
1055
+
1056
+ &:focus-visible {
1057
+ box-shadow: inset 0 0 0 2px $color-accent;
1058
+ }
1059
+ }
1060
+ }
1061
+ </style>