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,1044 @@
1
+ <script setup lang="ts">
2
+ import { computed, nextTick, onBeforeUnmount, reactive, ref, watch } from 'vue'
3
+ import {
4
+ buildFormValues,
5
+ collectPanelDefaults,
6
+ collectVisibleValueKeys,
7
+ DATE_FIELD_FORMATS,
8
+ formatDate,
9
+ isLayoutOnlyFieldType,
10
+ isVisible,
11
+ parseDate,
12
+ validateRequiredFields,
13
+ } from '@katecms/core'
14
+ import type { CollectionStatus, Field, SelectChoice } from '@katecms/core'
15
+ import { resolveField } from '../../utils/helpers'
16
+ import { provideKateCmsFieldValues } from '../../utils/field-values'
17
+ import { provideKateCmsFieldErrors } from '../../utils/field-errors'
18
+ import { slugify } from '../../utils/slugify'
19
+ import type {
20
+ AdminCollectionMeta,
21
+ CollectionDictionaryPicker,
22
+ CollectionEntryFormModel,
23
+ EntryRevisionItem,
24
+ ParentOption,
25
+ } from '../../utils/collections'
26
+ import EntryRevisions from './EntryRevisions.vue'
27
+ import { useKateCmsEntrySidebar } from '../../composables/useKateCmsExtensions'
28
+ import type { KateCmsEntrySidebarTab } from '../../composables/useKateCmsExtensions'
29
+
30
+ const props = defineProps<{
31
+ collection: AdminCollectionMeta
32
+ modelValue: CollectionEntryFormModel
33
+ entryKey?: string | number
34
+ parents?: ParentOption[]
35
+ saving?: boolean
36
+ error?: string | null
37
+ viewUrl?: string | null
38
+ canUpdate?: boolean
39
+ canDelete?: boolean
40
+ /** Saved status from the server (trash vs live form status). */
41
+ savedStatus?: CollectionStatus
42
+ dictionaryPickers?: CollectionDictionaryPicker[]
43
+ revisions?: EntryRevisionItem[]
44
+ revisionsLoading?: boolean
45
+ revisionsError?: string
46
+ }>()
47
+
48
+ const emit = defineEmits<{
49
+ 'update:modelValue': [value: CollectionEntryFormModel]
50
+ 'ready': []
51
+ 'submit': []
52
+ 'trash': []
53
+ 'restore': []
54
+ 'restoreRevision': [id: number]
55
+ 'delete': []
56
+ }>()
57
+
58
+ const rootClass = 'katecms-collection-form'
59
+ const PAGE_TAB = 'page'
60
+ const REVISIONS_TAB = 'revisions'
61
+ const entrySidebar = useKateCmsEntrySidebar()
62
+ const activeSidebarTab = ref(PAGE_TAB)
63
+ const openedSidebarTabs = ref<Record<string, true>>({})
64
+ const showRevisionsTab = computed(() => props.entryKey != null && props.collection.revisions !== false)
65
+
66
+ const sidebarTabs = computed(() => {
67
+ const seen = new Set<string>()
68
+ const tabs: KateCmsEntrySidebarTab[] = []
69
+ for (const tab of entrySidebar.value) {
70
+ if (!tab || typeof tab !== 'object') {
71
+ continue
72
+ }
73
+ const key = tab.key?.trim()
74
+ const label = tab.label?.trim()
75
+ const component = tab.component?.trim()
76
+ if (!key || key === PAGE_TAB || !label || !component || seen.has(key)) {
77
+ continue
78
+ }
79
+ seen.add(key)
80
+ tabs.push({ key, label, component })
81
+ }
82
+ return tabs
83
+ })
84
+
85
+ const showTabBar = computed(() => showRevisionsTab.value || sidebarTabs.value.length > 0)
86
+
87
+ const tabKeys = computed(() => {
88
+ const keys = [PAGE_TAB]
89
+ if (showRevisionsTab.value) {
90
+ keys.push(REVISIONS_TAB)
91
+ }
92
+ for (const tab of sidebarTabs.value) {
93
+ keys.push(tab.key)
94
+ }
95
+ return keys
96
+ })
97
+
98
+ watch(tabKeys, (keys) => {
99
+ if (!keys.includes(activeSidebarTab.value)) {
100
+ activeSidebarTab.value = PAGE_TAB
101
+ }
102
+ })
103
+
104
+ function sidebarTabId(key: string) {
105
+ return `${rootClass}-tab-${key}`
106
+ }
107
+
108
+ function sidebarPanelId(key: string) {
109
+ return `${rootClass}-panel-${key}`
110
+ }
111
+
112
+ function selectSidebarTab(key: string) {
113
+ activeSidebarTab.value = key
114
+ if (key !== PAGE_TAB) {
115
+ openedSidebarTabs.value = { ...openedSidebarTabs.value, [key]: true }
116
+ }
117
+ }
118
+
119
+ function onSidebarTabKeydown(event: KeyboardEvent, index: number) {
120
+ const keys = tabKeys.value
121
+ let next = index
122
+ if (event.key === 'ArrowRight') {
123
+ next = (index + 1) % keys.length
124
+ }
125
+ else if (event.key === 'ArrowLeft') {
126
+ next = (index - 1 + keys.length) % keys.length
127
+ }
128
+ else if (event.key === 'Home') {
129
+ next = 0
130
+ }
131
+ else if (event.key === 'End') {
132
+ next = keys.length - 1
133
+ }
134
+ else {
135
+ return
136
+ }
137
+ event.preventDefault()
138
+ const key = keys[next]
139
+ if (!key) {
140
+ return
141
+ }
142
+ selectSidebarTab(key)
143
+ void nextTick(() => {
144
+ document.getElementById(sidebarTabId(key))?.focus()
145
+ })
146
+ }
147
+
148
+ const PUBLISH_FORMAT = DATE_FIELD_FORMATS.datetime.return
149
+
150
+ const fieldDefs = computed(() => props.collection.fields ?? {})
151
+ const values = reactive<Record<string, unknown>>({})
152
+ provideKateCmsFieldValues(values)
153
+
154
+ const fieldErrors = ref<Record<string, string>>({})
155
+ const attemptedSubmit = ref(false)
156
+ provideKateCmsFieldErrors(fieldErrors)
157
+
158
+ const readOnly = computed(() => !props.canUpdate)
159
+ const isTrash = computed(() => (props.savedStatus ?? props.modelValue.status) === 'trash')
160
+
161
+ const statusChoices: SelectChoice[] = [
162
+ { val: 'published', lbl: 'Published' },
163
+ { val: 'draft', lbl: 'Draft' },
164
+ ]
165
+
166
+ const statusField = {
167
+ type: 'select' as const,
168
+ label: 'Status',
169
+ choices: statusChoices,
170
+ }
171
+
172
+ const parentChoices = computed<SelectChoice[]>(() =>
173
+ (props.parents ?? []).map((parent) => {
174
+ const depth = parent.depth ?? 0
175
+ const title = depth < 1 ? parent.title : `${'— '.repeat(depth)}${parent.title}`
176
+ return {
177
+ val: parent.id,
178
+ lbl: title,
179
+ }
180
+ }),
181
+ )
182
+
183
+ const parentField = computed(() => ({
184
+ type: 'select' as const,
185
+ label: 'Parent',
186
+ allowNull: true,
187
+ placeholder: '— None —',
188
+ choices: parentChoices.value,
189
+ }))
190
+
191
+ const dictionaryPickers = computed(() => props.dictionaryPickers ?? [])
192
+
193
+ function dictionaryChoices(picker: CollectionDictionaryPicker): SelectChoice[] {
194
+ return picker.terms.map((term) => {
195
+ const depth = term.depth ?? 0
196
+ const title = depth < 1 ? term.title : `${'— '.repeat(depth)}${term.title}`
197
+ return {
198
+ val: term.id,
199
+ lbl: title,
200
+ }
201
+ })
202
+ }
203
+
204
+ function dictionaryField(picker: CollectionDictionaryPicker) {
205
+ return {
206
+ type: 'select' as const,
207
+ label: picker.labels.name,
208
+ multiple: picker.multiple,
209
+ allowNull: !picker.multiple,
210
+ placeholder: picker.multiple ? undefined : '— None —',
211
+ search: picker.terms.length > 6,
212
+ choices: dictionaryChoices(picker),
213
+ }
214
+ }
215
+
216
+ function dictionaryValue(picker: CollectionDictionaryPicker) {
217
+ const raw = props.modelValue.dictionaryIds?.[picker.slug]
218
+ if (picker.multiple) {
219
+ return Array.isArray(raw) ? raw : []
220
+ }
221
+ if (Array.isArray(raw)) {
222
+ return raw[0] ?? null
223
+ }
224
+ return raw ?? null
225
+ }
226
+
227
+ function sameDictionaryValue(
228
+ current: unknown,
229
+ next: number | number[] | null,
230
+ multiple: boolean,
231
+ ): boolean {
232
+ if (multiple) {
233
+ const left = Array.isArray(current) ? current : []
234
+ const right = Array.isArray(next) ? next : []
235
+ return left.length === right.length && left.every((id, i) => id === right[i])
236
+ }
237
+ return (current ?? null) === next
238
+ }
239
+
240
+ function setDictionaryValue(picker: CollectionDictionaryPicker, value: unknown) {
241
+ let next: number | number[] | null
242
+ if (picker.multiple) {
243
+ const raw = Array.isArray(value) ? value : []
244
+ next = raw
245
+ .map(item => Number(item))
246
+ .filter(id => Number.isInteger(id) && id > 0)
247
+ }
248
+ else if (value === '' || value === null || value === undefined) {
249
+ next = null
250
+ }
251
+ else {
252
+ const id = Number(value)
253
+ next = Number.isInteger(id) && id > 0 ? id : null
254
+ }
255
+ if (sameDictionaryValue(dictionaryValue(picker), next, picker.multiple)) {
256
+ return
257
+ }
258
+ emit('update:modelValue', {
259
+ ...props.modelValue,
260
+ dictionaryIds: {
261
+ ...props.modelValue.dictionaryIds,
262
+ [picker.slug]: next,
263
+ },
264
+ })
265
+ }
266
+
267
+ const publishedField = {
268
+ type: 'date_time_picker' as const,
269
+ label: 'Publish date',
270
+ returnFormat: PUBLISH_FORMAT,
271
+ }
272
+
273
+ const authorField = {
274
+ type: 'user' as const,
275
+ label: 'Author',
276
+ returnFormat: 'id' as const,
277
+ }
278
+
279
+ const menuOrderField = {
280
+ type: 'number' as const,
281
+ label: 'Order',
282
+ step: 1,
283
+ instructions: 'Lower numbers appear first in lists.',
284
+ }
285
+
286
+ const titleField = { type: 'text' as const, label: 'Title', required: true }
287
+ const slugField = { type: 'text' as const, label: 'Slug', required: true }
288
+
289
+ let syncingFromParent = false
290
+ let hydrating = false
291
+ let hydrateGen = 0
292
+
293
+ function replaceValues(next: Record<string, unknown>) {
294
+ syncingFromParent = true
295
+ for (const key of Object.keys(values)) {
296
+ Reflect.deleteProperty(values, key)
297
+ }
298
+ Object.assign(values, next)
299
+ queueMicrotask(() => {
300
+ syncingFromParent = false
301
+ })
302
+ }
303
+
304
+ function emitFields() {
305
+ emit('update:modelValue', {
306
+ ...props.modelValue,
307
+ fields: { ...values },
308
+ })
309
+ }
310
+
311
+ async function hydrateFromModel() {
312
+ const gen = ++hydrateGen
313
+ hydrating = true
314
+ replaceValues({
315
+ ...buildFormValues(fieldDefs.value),
316
+ ...(props.modelValue.fields ?? {}),
317
+ })
318
+ await nextTick()
319
+ await nextTick()
320
+ if (gen !== hydrateGen) {
321
+ return
322
+ }
323
+ emitFields()
324
+ hydrating = false
325
+ emit('ready')
326
+ }
327
+
328
+ watch(
329
+ () => `${props.collection.slug}:${props.entryKey ?? 'default'}`,
330
+ () => {
331
+ void hydrateFromModel()
332
+ },
333
+ { immediate: true },
334
+ )
335
+
336
+ onBeforeUnmount(() => {
337
+ hydrateGen += 1
338
+ })
339
+
340
+ watch(
341
+ values,
342
+ () => {
343
+ if (syncingFromParent || hydrating) {
344
+ return
345
+ }
346
+ emitFields()
347
+ },
348
+ { deep: true },
349
+ )
350
+
351
+ const visibleFields = computed(() =>
352
+ Object.entries(fieldDefs.value).filter(([, field]) =>
353
+ isVisible(field.conditionalLogic, values),
354
+ ),
355
+ )
356
+
357
+ const mainFields = computed(() =>
358
+ visibleFields.value.filter(([, field]) => (field.position ?? 'main') === 'main'),
359
+ )
360
+
361
+ const sidebarFields = computed(() =>
362
+ visibleFields.value.filter(([, field]) => field.position === 'sidebar'),
363
+ )
364
+
365
+ const hiddenCache: Record<string, unknown> = {}
366
+
367
+ function restoreFieldValue(key: string, field: Field) {
368
+ if (isLayoutOnlyFieldType(field.type)) {
369
+ if (field.type === 'tab' || field.type === 'accordion') {
370
+ for (const [panelKey, panelDefault] of Object.entries(collectPanelDefaults(field))) {
371
+ if (!(panelKey in values)) {
372
+ values[panelKey] = panelKey in hiddenCache
373
+ ? hiddenCache[panelKey]
374
+ : panelDefault
375
+ Reflect.deleteProperty(hiddenCache, panelKey)
376
+ }
377
+ }
378
+ }
379
+ Reflect.deleteProperty(values, key)
380
+ return
381
+ }
382
+
383
+ if (!(key in values)) {
384
+ values[key] = key in hiddenCache
385
+ ? hiddenCache[key]
386
+ : 'defaultValue' in field
387
+ ? field.defaultValue
388
+ : field.type === 'group'
389
+ ? undefined
390
+ : field.type === 'repeater' || field.type === 'flexible_content' || field.type === 'gallery'
391
+ ? []
392
+ : field.type === 'open_street_map' && field.multiple
393
+ ? []
394
+ : undefined
395
+ Reflect.deleteProperty(hiddenCache, key)
396
+ }
397
+ }
398
+
399
+ watch(visibleFields, (visible) => {
400
+ const visibleKeys = collectVisibleValueKeys(visible)
401
+
402
+ for (const key of Object.keys(values)) {
403
+ if (!visibleKeys.has(key)) {
404
+ hiddenCache[key] = values[key]
405
+ Reflect.deleteProperty(values, key)
406
+ }
407
+ }
408
+
409
+ for (const [key, field] of visible) {
410
+ restoreFieldValue(key, field)
411
+ }
412
+ }, { immediate: true })
413
+
414
+ function updateCore<K extends keyof CollectionEntryFormModel>(
415
+ key: K,
416
+ value: CollectionEntryFormModel[K],
417
+ ) {
418
+ emit('update:modelValue', {
419
+ ...props.modelValue,
420
+ [key]: value,
421
+ })
422
+ }
423
+
424
+ const publishedLocal = computed({
425
+ get() {
426
+ const iso = props.modelValue.publishedAt
427
+ if (!iso) {
428
+ return ''
429
+ }
430
+ const date = new Date(iso)
431
+ if (Number.isNaN(date.getTime())) {
432
+ return ''
433
+ }
434
+ return formatDate(date, PUBLISH_FORMAT)
435
+ },
436
+ set(value: string | undefined) {
437
+ if (!value) {
438
+ updateCore('publishedAt', null)
439
+ return
440
+ }
441
+ const date = parseDate(value, PUBLISH_FORMAT)
442
+ updateCore('publishedAt', date ? date.toISOString() : null)
443
+ },
444
+ })
445
+
446
+ const parentModel = computed({
447
+ get() {
448
+ return props.modelValue.parentId
449
+ },
450
+ set(value: unknown) {
451
+ if (value === '' || value === null || value === undefined) {
452
+ updateCore('parentId', null)
453
+ return
454
+ }
455
+ const id = Number(value)
456
+ updateCore('parentId', Number.isInteger(id) && id > 0 ? id : null)
457
+ },
458
+ })
459
+
460
+ const authorModel = computed({
461
+ get() {
462
+ return props.modelValue.authorId
463
+ },
464
+ set(value: unknown) {
465
+ const id = Number(value)
466
+ updateCore('authorId', Number.isInteger(id) && id > 0 ? id : null)
467
+ },
468
+ })
469
+
470
+ const menuOrderModel = computed({
471
+ get() {
472
+ return props.modelValue.menuOrder
473
+ },
474
+ set(value: unknown) {
475
+ if (value === '' || value === null || value === undefined) {
476
+ updateCore('menuOrder', 0)
477
+ return
478
+ }
479
+ const n = typeof value === 'number' ? value : Number(value)
480
+ if (!Number.isFinite(n)) {
481
+ updateCore('menuOrder', 0)
482
+ return
483
+ }
484
+ updateCore('menuOrder', Math.trunc(n))
485
+ },
486
+ })
487
+
488
+ const canSubmit = computed(() =>
489
+ !readOnly.value
490
+ && !isTrash.value
491
+ && !props.saving,
492
+ )
493
+
494
+ const submitLabel = computed(() => {
495
+ if (props.saving) {
496
+ return 'Saving…'
497
+ }
498
+ return props.modelValue.status === 'published' ? 'Publish' : 'Save draft'
499
+ })
500
+
501
+ const requiredNotice = computed(() => {
502
+ const messages = Object.values(fieldErrors.value)
503
+ if (messages.length === 0) {
504
+ return ''
505
+ }
506
+ if (messages.length === 1) {
507
+ return messages[0]
508
+ }
509
+ return 'Please fill in the required fields.'
510
+ })
511
+
512
+ function collectFieldErrors(slug = props.modelValue.slug): Record<string, string> {
513
+ const next: Record<string, string> = {}
514
+ if (!props.modelValue.title.trim()) {
515
+ next['cms-entry-title'] = 'Title is required.'
516
+ }
517
+ if (!slug.trim()) {
518
+ next['cms-entry-slug'] = 'Slug is required.'
519
+ }
520
+ if (props.modelValue.status === 'published') {
521
+ for (const issue of validateRequiredFields(fieldDefs.value, values)) {
522
+ next[issue.key] = issue.message
523
+ }
524
+ }
525
+ return next
526
+ }
527
+
528
+ function scrollToFirstError(errors: Record<string, string>) {
529
+ const key = Object.keys(errors)[0]
530
+ if (!key || typeof document === 'undefined') {
531
+ return
532
+ }
533
+ const target = document.querySelector(`[data-field-key="${CSS.escape(key)}"]`)
534
+ if (target instanceof HTMLElement) {
535
+ target.scrollIntoView({ block: 'center', behavior: 'smooth' })
536
+ }
537
+ }
538
+
539
+ function onSubmit() {
540
+ if (!validateForSubmit()) {
541
+ return
542
+ }
543
+ emit('submit')
544
+ }
545
+
546
+ function validateForSubmit(): boolean {
547
+ if (!canSubmit.value) {
548
+ return false
549
+ }
550
+ let slug = props.modelValue.slug.trim()
551
+ if (!slug && props.modelValue.title.trim()) {
552
+ slug = slugify(props.modelValue.title) || 'entry'
553
+ updateCore('slug', slug)
554
+ }
555
+ attemptedSubmit.value = true
556
+ const errors = collectFieldErrors(slug)
557
+ fieldErrors.value = errors
558
+ if (Object.keys(errors).length > 0) {
559
+ nextTick(() => scrollToFirstError(errors))
560
+ return false
561
+ }
562
+ return true
563
+ }
564
+
565
+ defineExpose({ validateForSubmit })
566
+
567
+ watch(
568
+ [values, () => props.modelValue.title, () => props.modelValue.slug, () => props.modelValue.status],
569
+ () => {
570
+ if (!attemptedSubmit.value) {
571
+ return
572
+ }
573
+ fieldErrors.value = collectFieldErrors()
574
+ },
575
+ { deep: true },
576
+ )
577
+ </script>
578
+
579
+ <template>
580
+ <KateCmsUiNotice
581
+ v-if="requiredNotice"
582
+ placement="fixed"
583
+ variant="danger"
584
+ :message="requiredNotice"
585
+ :closable="false"
586
+ />
587
+ <KateCmsUiNotice
588
+ v-if="error"
589
+ placement="fixed"
590
+ variant="danger"
591
+ :message="error"
592
+ />
593
+
594
+ <form
595
+ :class="rootClass"
596
+ novalidate
597
+ @submit.prevent="onSubmit"
598
+ >
599
+ <div :class="`${rootClass}__main`">
600
+ <div :class="`${rootClass}__main-wrap`">
601
+ <KateCmsFieldWrapper
602
+ field-key="cms-entry-title"
603
+ :field="titleField"
604
+ >
605
+ <KateCmsInputControl
606
+ :model-value="modelValue.title"
607
+ field-key="cms-entry-title"
608
+ :field="titleField"
609
+ @update:model-value="updateCore('title', String($event ?? ''))"
610
+ />
611
+ </KateCmsFieldWrapper>
612
+
613
+ <KateCmsFieldWrapper
614
+ field-key="cms-entry-slug"
615
+ :field="slugField"
616
+ >
617
+ <KateCmsInputControl
618
+ :model-value="modelValue.slug"
619
+ field-key="cms-entry-slug"
620
+ :field="slugField"
621
+ @update:model-value="updateCore('slug', String($event ?? ''))"
622
+ />
623
+ </KateCmsFieldWrapper>
624
+
625
+ <div :class="`${rootClass}__fields`">
626
+ <div
627
+ v-for="[key, field] in mainFields"
628
+ :key="key"
629
+ :class="`${rootClass}__field`"
630
+ :style="field.columnWidth ? { width: `${field.columnWidth}%` } : undefined"
631
+ >
632
+ <component
633
+ :is="resolveField(field.type)"
634
+ v-model="values[key]"
635
+ :field-key="key"
636
+ :field="field"
637
+ />
638
+ </div>
639
+ </div>
640
+ </div>
641
+ </div>
642
+
643
+ <div :class="[`${rootClass}__sidebar`, { [`${rootClass}__sidebar--tabs`]: showTabBar }]">
644
+ <div
645
+ v-if="showTabBar"
646
+ :class="`${rootClass}__tabs`"
647
+ role="tablist"
648
+ >
649
+ <button
650
+ :id="sidebarTabId(PAGE_TAB)"
651
+ type="button"
652
+ role="tab"
653
+ :aria-selected="activeSidebarTab === PAGE_TAB"
654
+ :aria-controls="sidebarPanelId(PAGE_TAB)"
655
+ :tabindex="activeSidebarTab === PAGE_TAB ? 0 : -1"
656
+ :class="[`${rootClass}__tabs-item`, { 'is-active': activeSidebarTab === PAGE_TAB }]"
657
+ @click="selectSidebarTab(PAGE_TAB)"
658
+ @keydown="onSidebarTabKeydown($event, 0)"
659
+ >
660
+ Page
661
+ </button>
662
+ <button
663
+ v-if="showRevisionsTab"
664
+ :id="sidebarTabId(REVISIONS_TAB)"
665
+ type="button"
666
+ role="tab"
667
+ :aria-selected="activeSidebarTab === REVISIONS_TAB"
668
+ :aria-controls="sidebarPanelId(REVISIONS_TAB)"
669
+ :tabindex="activeSidebarTab === REVISIONS_TAB ? 0 : -1"
670
+ :class="[`${rootClass}__tabs-item`, { 'is-active': activeSidebarTab === REVISIONS_TAB }]"
671
+ @click="selectSidebarTab(REVISIONS_TAB)"
672
+ @keydown="onSidebarTabKeydown($event, 1)"
673
+ >
674
+ Revisions
675
+ </button>
676
+ <button
677
+ v-for="(tab, index) in sidebarTabs"
678
+ :id="sidebarTabId(tab.key)"
679
+ :key="tab.key"
680
+ type="button"
681
+ role="tab"
682
+ :aria-selected="activeSidebarTab === tab.key"
683
+ :aria-controls="sidebarPanelId(tab.key)"
684
+ :tabindex="activeSidebarTab === tab.key ? 0 : -1"
685
+ :class="[`${rootClass}__tabs-item`, { 'is-active': activeSidebarTab === tab.key }]"
686
+ @click="selectSidebarTab(tab.key)"
687
+ @keydown="onSidebarTabKeydown($event, index + (showRevisionsTab ? 2 : 1))"
688
+ >
689
+ {{ tab.label }}
690
+ </button>
691
+ </div>
692
+
693
+ <div
694
+ v-show="!showTabBar || activeSidebarTab === PAGE_TAB"
695
+ :id="showTabBar ? sidebarPanelId(PAGE_TAB) : undefined"
696
+ :class="showTabBar ? `${rootClass}__panel` : `${rootClass}__page`"
697
+ :role="showTabBar ? 'tabpanel' : undefined"
698
+ :aria-labelledby="showTabBar ? sidebarTabId(PAGE_TAB) : undefined"
699
+ >
700
+ <div :class="`${rootClass}__block`">
701
+ <div :class="`${rootClass}__block-title`">
702
+ Publish
703
+ </div>
704
+
705
+ <KateCmsUiNotice
706
+ v-if="isTrash"
707
+ placement="static"
708
+ variant="warning"
709
+ message="This entry is in the trash."
710
+ :closable="false"
711
+ />
712
+
713
+ <template v-else>
714
+ <KateCmsSelectField
715
+ :model-value="modelValue.status === 'trash' ? 'draft' : modelValue.status"
716
+ field-key="cms-entry-status"
717
+ :field="statusField"
718
+ @update:model-value="updateCore('status', ($event === 'published' ? 'published' : 'draft') as CollectionStatus)"
719
+ />
720
+
721
+ <KateCmsUserField
722
+ v-model="authorModel"
723
+ field-key="cms-entry-author"
724
+ :field="authorField"
725
+ />
726
+
727
+ <KateCmsDateTimePickerField
728
+ v-model="publishedLocal"
729
+ field-key="cms-entry-published"
730
+ :field="publishedField"
731
+ />
732
+
733
+ <KateCmsNumberField
734
+ v-model="menuOrderModel"
735
+ field-key="cms-entry-menu-order"
736
+ :field="menuOrderField"
737
+ />
738
+
739
+ <KateCmsSelectField
740
+ v-if="collection.hierarchical"
741
+ v-model="parentModel"
742
+ field-key="cms-entry-parent"
743
+ :field="parentField"
744
+ />
745
+ </template>
746
+
747
+ <div :class="`${rootClass}__block-actions`">
748
+ <KateCmsUiButton
749
+ v-if="!isTrash && canUpdate"
750
+ tag="button"
751
+ type="submit"
752
+ variant="full"
753
+ :disabled="!canSubmit"
754
+ >
755
+ {{ submitLabel }}
756
+ </KateCmsUiButton>
757
+
758
+ <KateCmsUiButton
759
+ v-if="viewUrl && !isTrash"
760
+ tag="a"
761
+ :variant="['secondary', 'small', 'full']"
762
+ :link="{ url: viewUrl, title: 'View', target: '_blank' }"
763
+ >
764
+ View
765
+ </KateCmsUiButton>
766
+
767
+ <KateCmsUiButton
768
+ v-if="!isTrash && canUpdate"
769
+ tag="button"
770
+ type="button"
771
+ :variant="['red', 'small', 'full']"
772
+ :disabled="saving"
773
+ @click="emit('trash')"
774
+ >
775
+ Move to trash
776
+ </KateCmsUiButton>
777
+
778
+ <KateCmsUiButton
779
+ v-if="isTrash && canUpdate"
780
+ tag="button"
781
+ type="button"
782
+ :disabled="saving"
783
+ @click="emit('restore')"
784
+ >
785
+ Restore
786
+ </KateCmsUiButton>
787
+
788
+ <KateCmsUiButton
789
+ v-if="isTrash && canDelete"
790
+ tag="button"
791
+ type="button"
792
+ :variant="['red', 'small']"
793
+ :disabled="saving"
794
+ @click="emit('delete')"
795
+ >
796
+ Delete permanently
797
+ </KateCmsUiButton>
798
+ </div>
799
+ </div>
800
+
801
+ <div
802
+ v-if="!isTrash && dictionaryPickers.length"
803
+ :class="`${rootClass}__block`"
804
+ >
805
+ <div :class="`${rootClass}__block-title`">
806
+ Dictionaries
807
+ </div>
808
+ <KateCmsSelectField
809
+ v-for="picker in dictionaryPickers"
810
+ :key="picker.slug"
811
+ :model-value="dictionaryValue(picker)"
812
+ :field-key="`cms-entry-dictionary-${picker.slug}`"
813
+ :field="dictionaryField(picker)"
814
+ @update:model-value="setDictionaryValue(picker, $event)"
815
+ />
816
+ </div>
817
+
818
+ <div
819
+ v-if="sidebarFields.length"
820
+ :class="`${rootClass}__block`"
821
+ >
822
+ <component
823
+ :is="resolveField(field.type)"
824
+ v-for="[key, field] in sidebarFields"
825
+ :key="key"
826
+ v-model="values[key]"
827
+ :field-key="key"
828
+ :field="field"
829
+ />
830
+ </div>
831
+ </div>
832
+
833
+ <div
834
+ v-if="showRevisionsTab && openedSidebarTabs[REVISIONS_TAB]"
835
+ v-show="activeSidebarTab === REVISIONS_TAB"
836
+ :id="sidebarPanelId(REVISIONS_TAB)"
837
+ :class="`${rootClass}__panel`"
838
+ role="tabpanel"
839
+ :aria-labelledby="sidebarTabId(REVISIONS_TAB)"
840
+ >
841
+ <div :class="`${rootClass}__block`">
842
+ <EntryRevisions
843
+ :items="revisions ?? []"
844
+ :loading="revisionsLoading"
845
+ :error="revisionsError"
846
+ :can-restore="canUpdate === true"
847
+ :disabled="saving || canUpdate !== true"
848
+ @restore="emit('restoreRevision', $event)"
849
+ />
850
+ </div>
851
+ </div>
852
+
853
+ <template
854
+ v-for="tab in sidebarTabs"
855
+ :key="tab.key"
856
+ >
857
+ <div
858
+ v-if="openedSidebarTabs[tab.key]"
859
+ v-show="activeSidebarTab === tab.key"
860
+ :id="sidebarPanelId(tab.key)"
861
+ :class="`${rootClass}__panel`"
862
+ role="tabpanel"
863
+ :aria-labelledby="sidebarTabId(tab.key)"
864
+ >
865
+ <component :is="tab.component" />
866
+ </div>
867
+ </template>
868
+ </div>
869
+ </form>
870
+ </template>
871
+
872
+ <style scoped lang="scss">
873
+ @use "../../assets/styles" as *;
874
+
875
+ $root: '.katecms-collection-form';
876
+
877
+ @include katecms-wrapper {
878
+ #{$root} {
879
+ width: 100%;
880
+ height: 100%;
881
+ min-width: 0;
882
+ min-height: 0;
883
+ overflow: hidden;
884
+ display: grid;
885
+ grid-template-columns: minmax(0, 1fr) math-rem(350);
886
+ grid-template-rows: minmax(0, 1fr);
887
+
888
+ @media (max-width: 1100px) {
889
+ grid-template-columns: minmax(0, 1fr);
890
+ grid-template-rows: none;
891
+ overflow: auto;
892
+ }
893
+
894
+ &__main {
895
+ min-width: 0;
896
+ min-height: 0;
897
+ overflow: auto;
898
+ overscroll-behavior: contain;
899
+
900
+ &-wrap {
901
+ padding: math-rem(16) math-rem(8);
902
+ display: flex;
903
+ flex-direction: column;
904
+ gap: math-rem(16);
905
+
906
+ @media (max-width: 1100px) {
907
+ overflow: visible;
908
+ }
909
+ }
910
+ }
911
+
912
+ &__sidebar {
913
+ background: $color-bg;
914
+ border-left: 1px solid $color-border;
915
+ padding: math-rem(16) 0;
916
+ display: flex;
917
+ flex-direction: column;
918
+ gap: math-rem(16);
919
+ min-width: 0;
920
+ min-height: 0;
921
+ overflow: auto;
922
+ overscroll-behavior: contain;
923
+
924
+ @media (max-width: 1100px) {
925
+ overflow: visible;
926
+ }
927
+
928
+ &--tabs {
929
+ padding-top: 0;
930
+ gap: 0;
931
+ }
932
+ }
933
+
934
+ &__tabs {
935
+ position: sticky;
936
+ top: 0;
937
+ z-index: 2;
938
+ display: flex;
939
+ flex-shrink: 0;
940
+ overflow-x: auto;
941
+ background: $color-bg;
942
+ border-bottom: 1px solid $color-border;
943
+
944
+ &-item {
945
+ flex: 1 0 auto;
946
+ min-width: math-rem(72);
947
+ margin: 0;
948
+ padding: math-rem(12) math-rem(14);
949
+ border: 0;
950
+ border-right: 1px solid $color-border;
951
+ background: transparent;
952
+ color: $color-muted;
953
+ font: inherit;
954
+ font-size: math-rem(13);
955
+ font-weight: 600;
956
+ letter-spacing: 0.04em;
957
+ text-transform: uppercase;
958
+ cursor: pointer;
959
+
960
+ &:last-child {
961
+ border-right: 0;
962
+ }
963
+
964
+ &:hover {
965
+ color: $color-ink;
966
+ background: $color-accent-wash;
967
+ }
968
+
969
+ &.is-active {
970
+ color: $color-ink;
971
+ background: $color-surface;
972
+ box-shadow: inset 0 -2px 0 $color-accent;
973
+ }
974
+
975
+ &:focus {
976
+ outline: none;
977
+ }
978
+
979
+ &:focus-visible {
980
+ outline: 2px solid color-alpha($color-accent, 0.35);
981
+ outline-offset: -2px;
982
+ }
983
+ }
984
+ }
985
+
986
+ &__page {
987
+ display: contents;
988
+ }
989
+
990
+ &__panel {
991
+ display: flex;
992
+ flex-direction: column;
993
+ gap: math-rem(16);
994
+ min-width: 0;
995
+ padding-top: math-rem(16);
996
+ }
997
+
998
+ &__fields {
999
+ display: flex;
1000
+ flex-wrap: wrap;
1001
+ row-gap: math-rem(16);
1002
+ margin-left: math-rem(-8);
1003
+ margin-right: math-rem(-8);
1004
+ min-width: 0;
1005
+ }
1006
+
1007
+ &__field {
1008
+ padding-left: math-rem(8);
1009
+ padding-right: math-rem(8);
1010
+ width: 100%;
1011
+ min-width: 0;
1012
+ box-sizing: border-box;
1013
+ }
1014
+
1015
+ &__block {
1016
+ display: flex;
1017
+ flex-direction: column;
1018
+ gap: math-rem(16);
1019
+ padding-left: math-rem(8);
1020
+ padding-right: math-rem(8);
1021
+
1022
+ &:not(:last-child) {
1023
+ padding-bottom: math-rem(16);
1024
+ border-bottom: 1px solid $color-border;
1025
+ }
1026
+
1027
+ &-title {
1028
+ margin: 0;
1029
+ font-size: math-rem(14);
1030
+ font-weight: 600;
1031
+ letter-spacing: 0.04em;
1032
+ text-transform: uppercase;
1033
+ color: $color-ink;
1034
+ }
1035
+
1036
+ &-actions {
1037
+ display: flex;
1038
+ flex-wrap: wrap;
1039
+ gap: math-rem(8);
1040
+ }
1041
+ }
1042
+ }
1043
+ }
1044
+ </style>