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,1054 @@
1
+ <script setup>
2
+ import { useHead } from "#imports";
3
+ import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from "vue";
4
+ import { isImageMedia, RESERVED_SIZE_NAME } from "@katecms/core";
5
+ import {
6
+ defaultMediaLibraryFilters,
7
+ localUtcOffsetMinutes,
8
+ mediaFiltersActive,
9
+ mediaLibraryQuery,
10
+ mediaMatchesFilters,
11
+ monthKey,
12
+ normalizeMediaLibraryFilters
13
+ } from "../../utils/media-library-query";
14
+ useHead({ title: "Media library" });
15
+ const rootClass = "katecms-media";
16
+ const POLL_MAX_ATTEMPTS = 60;
17
+ const POLL_INTERVAL_MS = 2e3;
18
+ const PAGE_SIZE = 40;
19
+ const items = ref([]);
20
+ const total = ref(0);
21
+ const fetched = ref(0);
22
+ const months = ref([]);
23
+ const filters = ref(defaultMediaLibraryFilters());
24
+ const loading = ref(false);
25
+ const loadingMore = ref(false);
26
+ const uploading = ref(false);
27
+ const saving = ref(false);
28
+ const regenerating = ref(false);
29
+ const deleting = ref(false);
30
+ const markedIds = ref([]);
31
+ const error = ref(null);
32
+ const notice = ref(null);
33
+ const fileInput = ref(null);
34
+ const scroller = ref(null);
35
+ const sentinel = ref(null);
36
+ let loadObserver = null;
37
+ const selected = ref(null);
38
+ const editAlt = ref("");
39
+ const editCaption = ref("");
40
+ const altField = { type: "text", label: "Alt text" };
41
+ const captionField = { type: "textarea", label: "Caption", rows: 3 };
42
+ const FORMAT_ORDER = { avif: 0, webp: 1 };
43
+ function isProcessing(item) {
44
+ return item.variants_status === "pending";
45
+ }
46
+ function errMessage(err, fallback) {
47
+ const e = err;
48
+ return e.data?.statusMessage || e.data?.message || e.statusMessage || fallback;
49
+ }
50
+ function formatSize(bytes) {
51
+ if (bytes < 1024) {
52
+ return `${bytes} B`;
53
+ }
54
+ if (bytes < 1024 * 1024) {
55
+ return `${(bytes / 1024).toFixed(1)} KB`;
56
+ }
57
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
58
+ }
59
+ function formatDate(iso) {
60
+ const date = new Date(iso);
61
+ if (Number.isNaN(date.getTime())) {
62
+ return iso;
63
+ }
64
+ return date.toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric" });
65
+ }
66
+ function pictureSources(item) {
67
+ return item.variants.filter((variant) => variant.size === RESERVED_SIZE_NAME).sort((a, b) => (FORMAT_ORDER[a.format] ?? 9) - (FORMAT_ORDER[b.format] ?? 9));
68
+ }
69
+ function replaceItem(next) {
70
+ items.value = items.value.map((item) => item.id === next.id ? next : item);
71
+ if (selected.value?.id === next.id) {
72
+ selected.value = next;
73
+ }
74
+ }
75
+ const hasMore = computed(() => fetched.value < total.value);
76
+ const filtersActive = computed(() => mediaFiltersActive(filters.value));
77
+ const markedCount = computed(() => markedIds.value.length);
78
+ let requestId = 0;
79
+ function rememberMonth(iso) {
80
+ const key = monthKey(iso, localUtcOffsetMinutes());
81
+ if (!key || months.value.includes(key)) {
82
+ return;
83
+ }
84
+ months.value = [...months.value, key].sort((a, b) => b.localeCompare(a));
85
+ }
86
+ async function fetchPage(offset) {
87
+ return $fetch("/api/_katecms/media", {
88
+ query: mediaLibraryQuery(filters.value, { limit: PAGE_SIZE, offset })
89
+ });
90
+ }
91
+ async function load(options) {
92
+ const id = ++requestId;
93
+ if (!options?.silent) {
94
+ loading.value = true;
95
+ error.value = null;
96
+ items.value = [];
97
+ fetched.value = 0;
98
+ markedIds.value = [];
99
+ }
100
+ try {
101
+ const res = await fetchPage(0);
102
+ if (id !== requestId) {
103
+ return;
104
+ }
105
+ total.value = res.total;
106
+ fetched.value = res.media.length;
107
+ months.value = res.months;
108
+ items.value = res.media;
109
+ pruneMarked();
110
+ if (selected.value) {
111
+ selected.value = items.value.find((entry) => entry.id === selected.value?.id) ?? selected.value;
112
+ }
113
+ pollVariants(res.media.filter((item) => item.variants_status === "pending").map((item) => item.id));
114
+ } catch (err) {
115
+ if (id === requestId) {
116
+ error.value = errMessage(err, "Could not load the media library.");
117
+ }
118
+ } finally {
119
+ if (id === requestId && !options?.silent) {
120
+ loading.value = false;
121
+ }
122
+ }
123
+ }
124
+ async function onLibraryFilters(next) {
125
+ filters.value = normalizeMediaLibraryFilters(next);
126
+ await load();
127
+ }
128
+ async function loadMore() {
129
+ if (loading.value || loadingMore.value || !hasMore.value) {
130
+ return;
131
+ }
132
+ const id = requestId;
133
+ loadingMore.value = true;
134
+ try {
135
+ const res = await fetchPage(fetched.value);
136
+ if (id !== requestId) {
137
+ return;
138
+ }
139
+ total.value = res.total;
140
+ if (!res.media.length) {
141
+ fetched.value = total.value;
142
+ return;
143
+ }
144
+ fetched.value += res.media.length;
145
+ const seen = new Set(items.value.map((item) => item.id));
146
+ const next = res.media.filter((item) => !seen.has(item.id));
147
+ if (!next.length && fetched.value >= total.value) {
148
+ return;
149
+ }
150
+ items.value = [...items.value, ...next];
151
+ pruneMarked();
152
+ pollVariants(next.filter((item) => item.variants_status === "pending").map((item) => item.id));
153
+ } catch (err) {
154
+ if (id === requestId) {
155
+ error.value = errMessage(err, "Could not load more files.");
156
+ }
157
+ } finally {
158
+ loadingMore.value = false;
159
+ }
160
+ void nextTick(() => {
161
+ const root = scroller.value;
162
+ const target = sentinel.value;
163
+ if (!root || !target || !hasMore.value || loadingMore.value) {
164
+ return;
165
+ }
166
+ const rootRect = root.getBoundingClientRect();
167
+ const targetRect = target.getBoundingClientRect();
168
+ if (targetRect.top <= rootRect.bottom + 240) {
169
+ void loadMore();
170
+ }
171
+ });
172
+ }
173
+ function stopLoadObserver() {
174
+ loadObserver?.disconnect();
175
+ loadObserver = null;
176
+ }
177
+ function startLoadObserver() {
178
+ stopLoadObserver();
179
+ const root = scroller.value;
180
+ const target = sentinel.value;
181
+ if (!root || !target || !hasMore.value) {
182
+ return;
183
+ }
184
+ loadObserver = new IntersectionObserver((entries) => {
185
+ if (entries.some((entry) => entry.isIntersecting)) {
186
+ void loadMore();
187
+ }
188
+ }, { root, rootMargin: "240px" });
189
+ loadObserver.observe(target);
190
+ }
191
+ function failedCount(ids) {
192
+ return ids.filter((id) => {
193
+ return items.value.find((entry) => entry.id === id)?.variants_status === "failed";
194
+ }).length;
195
+ }
196
+ function showRegenNotice(ids) {
197
+ const failed = failedCount(ids);
198
+ if (failed && failed === ids.length) {
199
+ notice.value = {
200
+ variant: "danger",
201
+ message: ids.length === 1 ? "Could not regenerate this image." : "Could not regenerate image variants."
202
+ };
203
+ return;
204
+ }
205
+ if (failed) {
206
+ notice.value = {
207
+ variant: "warning",
208
+ message: failed === 1 ? "Regeneration finished. 1 image failed." : `Regeneration finished. ${failed} images failed.`
209
+ };
210
+ return;
211
+ }
212
+ notice.value = {
213
+ variant: "success",
214
+ message: "Image variants regenerated."
215
+ };
216
+ }
217
+ function pollVariants(ids, options = {}) {
218
+ const tracked = ids.slice();
219
+ const maxAttempts = options.maxAttempts ?? POLL_MAX_ATTEMPTS;
220
+ const tick = (remaining, attempt) => {
221
+ if (!remaining.length) {
222
+ options.onComplete?.(tracked);
223
+ return;
224
+ }
225
+ if (maxAttempts > 0 && attempt >= maxAttempts) {
226
+ options.onTimeout?.();
227
+ return;
228
+ }
229
+ setTimeout(async () => {
230
+ await load({ silent: true });
231
+ const next = remaining.filter((id) => {
232
+ const item = items.value.find((entry) => entry.id === id);
233
+ return item?.variants_status === "pending";
234
+ });
235
+ tick(next, attempt + 1);
236
+ }, POLL_INTERVAL_MS);
237
+ };
238
+ tick(tracked, 0);
239
+ }
240
+ async function onFilesSelected(event) {
241
+ const input = event.target;
242
+ const files = Array.from(input.files ?? []);
243
+ if (!files.length) {
244
+ return;
245
+ }
246
+ uploading.value = true;
247
+ error.value = null;
248
+ const pendingIds = [];
249
+ let resort = false;
250
+ try {
251
+ for (const file of files) {
252
+ const form = new FormData();
253
+ form.append("file", file);
254
+ const res = await $fetch("/api/_katecms/media", {
255
+ method: "POST",
256
+ body: form
257
+ });
258
+ if (mediaMatchesFilters(res.media, { ...filters.value, month: "all" })) {
259
+ rememberMonth(res.media.created_at);
260
+ }
261
+ if (mediaMatchesFilters(res.media, filters.value)) {
262
+ if (filters.value.sort === "date-desc") {
263
+ items.value = [res.media, ...items.value.filter((entry) => entry.id !== res.media.id)];
264
+ total.value += 1;
265
+ } else {
266
+ resort = true;
267
+ }
268
+ }
269
+ if (res.media.variants_status === "pending") {
270
+ pendingIds.push(res.media.id);
271
+ }
272
+ }
273
+ } catch (err) {
274
+ error.value = errMessage(err, "Could not upload the file.");
275
+ } finally {
276
+ uploading.value = false;
277
+ input.value = "";
278
+ }
279
+ if (resort) {
280
+ await load({ silent: true });
281
+ }
282
+ pollVariants(pendingIds);
283
+ }
284
+ function openEditor(item) {
285
+ selected.value = item;
286
+ editAlt.value = item.alt ?? "";
287
+ editCaption.value = item.caption ?? "";
288
+ error.value = null;
289
+ }
290
+ function closeEditor() {
291
+ selected.value = null;
292
+ }
293
+ async function saveMeta() {
294
+ if (!selected.value) {
295
+ return;
296
+ }
297
+ saving.value = true;
298
+ error.value = null;
299
+ try {
300
+ const res = await $fetch(`/api/_katecms/media/${selected.value.id}`, {
301
+ method: "PATCH",
302
+ body: { alt: editAlt.value, caption: editCaption.value }
303
+ });
304
+ replaceItem(res.media);
305
+ } catch (err) {
306
+ error.value = errMessage(err, "Could not save changes.");
307
+ } finally {
308
+ saving.value = false;
309
+ }
310
+ }
311
+ function isMarked(id) {
312
+ return markedIds.value.includes(id);
313
+ }
314
+ function toggleMarked(id) {
315
+ markedIds.value = isMarked(id) ? markedIds.value.filter((entry) => entry !== id) : [...markedIds.value, id];
316
+ }
317
+ function pruneMarked() {
318
+ const visible = new Set(items.value.map((item) => item.id));
319
+ markedIds.value = markedIds.value.filter((id) => visible.has(id));
320
+ }
321
+ function dropDeleted(ids) {
322
+ if (!ids.length) {
323
+ return;
324
+ }
325
+ const removed = new Set(ids);
326
+ items.value = items.value.filter((entry) => !removed.has(entry.id));
327
+ markedIds.value = markedIds.value.filter((id) => !removed.has(id));
328
+ total.value = Math.max(0, total.value - ids.length);
329
+ fetched.value = Math.max(0, fetched.value - ids.length);
330
+ if (selected.value && removed.has(selected.value.id)) {
331
+ closeEditor();
332
+ }
333
+ }
334
+ async function remove(item) {
335
+ if (!confirm(`Delete \u201C${item.filename}\u201D?`)) {
336
+ return;
337
+ }
338
+ error.value = null;
339
+ try {
340
+ await $fetch(`/api/_katecms/media/${item.id}`, { method: "DELETE" });
341
+ dropDeleted([item.id]);
342
+ } catch (err) {
343
+ error.value = errMessage(err, "Could not delete the file.");
344
+ }
345
+ }
346
+ async function removeMarked() {
347
+ const ids = markedIds.value.slice();
348
+ if (!ids.length || deleting.value) {
349
+ return;
350
+ }
351
+ const label = ids.length === 1 ? "Delete 1 file?" : `Delete ${ids.length} files?`;
352
+ if (!confirm(label)) {
353
+ return;
354
+ }
355
+ deleting.value = true;
356
+ error.value = null;
357
+ const failed = [];
358
+ await Promise.all(ids.map(async (id) => {
359
+ try {
360
+ await $fetch(`/api/_katecms/media/${id}`, { method: "DELETE" });
361
+ } catch {
362
+ failed.push(id);
363
+ }
364
+ }));
365
+ const failedSet = new Set(failed);
366
+ dropDeleted(ids.filter((id) => !failedSet.has(id)));
367
+ if (failed.length) {
368
+ error.value = failed.length === 1 ? "Could not delete 1 file." : `Could not delete ${failed.length} files.`;
369
+ }
370
+ deleting.value = false;
371
+ if (!items.value.length && hasMore.value) {
372
+ await load();
373
+ }
374
+ }
375
+ async function regenerateAll() {
376
+ if (!confirm("Regenerate image variants for the whole library? This may take a while.")) {
377
+ return;
378
+ }
379
+ regenerating.value = true;
380
+ error.value = null;
381
+ notice.value = null;
382
+ try {
383
+ const res = await $fetch("/api/_katecms/media/regenerate", { method: "POST" });
384
+ await load({ silent: true });
385
+ const pendingIds = items.value.filter((item) => item.variants_status === "pending").map((item) => item.id);
386
+ if (!pendingIds.length) {
387
+ notice.value = {
388
+ variant: "success",
389
+ message: res.count ? "Image variants regenerated." : "No images to regenerate."
390
+ };
391
+ regenerating.value = false;
392
+ return;
393
+ }
394
+ pollVariants(pendingIds, {
395
+ maxAttempts: 0,
396
+ onComplete: (ids) => {
397
+ showRegenNotice(ids);
398
+ regenerating.value = false;
399
+ }
400
+ });
401
+ } catch (err) {
402
+ error.value = errMessage(err, "Could not start regeneration.");
403
+ regenerating.value = false;
404
+ }
405
+ }
406
+ async function regenerateOne(item) {
407
+ error.value = null;
408
+ notice.value = null;
409
+ try {
410
+ const res = await $fetch(`/api/_katecms/media/${item.id}/regenerate`, {
411
+ method: "POST"
412
+ });
413
+ replaceItem(res.media);
414
+ if (res.media.variants_status !== "pending") {
415
+ showRegenNotice([res.media.id]);
416
+ return;
417
+ }
418
+ pollVariants([res.media.id], {
419
+ maxAttempts: 0,
420
+ onComplete: (ids) => showRegenNotice(ids)
421
+ });
422
+ } catch (err) {
423
+ error.value = errMessage(err, "Could not regenerate this image.");
424
+ }
425
+ }
426
+ onMounted(async () => {
427
+ await load();
428
+ });
429
+ onBeforeUnmount(stopLoadObserver);
430
+ watch([scroller, sentinel, hasMore], () => {
431
+ void nextTick(startLoadObserver);
432
+ });
433
+ </script>
434
+
435
+ <template>
436
+ <div :class="rootClass">
437
+ <KateCmsAdminHeader
438
+ title="Media library"
439
+ :count="total === 1 ? '1 item' : `${total} items`"
440
+ >
441
+ <input
442
+ ref="fileInput"
443
+ type="file"
444
+ :class="`${rootClass}__file`"
445
+ multiple
446
+ @change="onFilesSelected"
447
+ >
448
+ <KateCmsUiButton
449
+ v-if="markedCount"
450
+ tag="button"
451
+ variant="red"
452
+ :disabled="deleting"
453
+ @click="removeMarked"
454
+ >
455
+ {{ deleting ? "Deleting\u2026" : `Delete selected (${markedCount})` }}
456
+ </KateCmsUiButton>
457
+ <KateCmsUiButton
458
+ tag="button"
459
+ variant="secondary"
460
+ :disabled="regenerating || !items.length"
461
+ title="Regenerate image variants from the current media config"
462
+ @click="regenerateAll"
463
+ >
464
+ {{ regenerating ? "Regenerating\u2026" : "Regenerate" }}
465
+ </KateCmsUiButton>
466
+ <KateCmsUiButton
467
+ tag="button"
468
+ :disabled="uploading"
469
+ @click="fileInput?.click()"
470
+ >
471
+ {{ uploading ? "Uploading\u2026" : "Upload files" }}
472
+ </KateCmsUiButton>
473
+ </KateCmsAdminHeader>
474
+
475
+ <KateCmsMediaLibraryFilters
476
+ :filters="filters"
477
+ :months="months"
478
+ id-prefix="library"
479
+ :class="`${rootClass}__filters`"
480
+ @update:filters="onLibraryFilters"
481
+ />
482
+
483
+ <KateCmsUiNotice
484
+ v-if="notice"
485
+ placement="fixed"
486
+ :variant="notice.variant"
487
+ :message="notice.message"
488
+ @close="notice = null"
489
+ />
490
+ <KateCmsUiNotice
491
+ v-if="error"
492
+ placement="static"
493
+ variant="danger"
494
+ :message="error"
495
+ @close="error = null"
496
+ />
497
+ <KateCmsUiNotice
498
+ v-if="loading"
499
+ placement="static"
500
+ variant="info"
501
+ message="Loading…"
502
+ :closable="false"
503
+ />
504
+ <KateCmsUiNotice
505
+ v-else-if="!items.length && !error"
506
+ placement="static"
507
+ variant="info"
508
+ :message="filtersActive ? 'No files match.' : 'No files yet. Upload the first one.'"
509
+ :closable="false"
510
+ />
511
+
512
+ <div
513
+ v-else-if="items.length"
514
+ ref="scroller"
515
+ :class="`${rootClass}__scroller`"
516
+ >
517
+ <div :class="`${rootClass}__grid`">
518
+ <div
519
+ v-for="item in items"
520
+ :key="item.id"
521
+ :class="[`${rootClass}__card`, { 'is-marked': isMarked(item.id) }]"
522
+ >
523
+ <label :class="`${rootClass}__check`">
524
+ <input
525
+ type="checkbox"
526
+ :checked="isMarked(item.id)"
527
+ :aria-label="`Select ${item.filename}`"
528
+ @change="toggleMarked(item.id)"
529
+ >
530
+ </label>
531
+ <button
532
+ type="button"
533
+ :class="`${rootClass}__thumb`"
534
+ @click="openEditor(item)"
535
+ >
536
+ <picture v-if="isImageMedia(item)">
537
+ <source
538
+ v-for="variant in pictureSources(item)"
539
+ :key="variant.format"
540
+ :srcset="variant.url"
541
+ :type="`image/${variant.format}`"
542
+ >
543
+ <img
544
+ :src="item.url"
545
+ :alt="item.alt || item.filename"
546
+ loading="lazy"
547
+ >
548
+ </picture>
549
+ <span
550
+ v-else
551
+ :class="`${rootClass}__ext`"
552
+ >{{ item.mime_type }}</span>
553
+ <span
554
+ v-if="isProcessing(item)"
555
+ :class="`${rootClass}__processing`"
556
+ >
557
+ <span :class="`${rootClass}__spinner`" />
558
+ Processing…
559
+ </span>
560
+ </button>
561
+ <div :class="`${rootClass}__meta`">
562
+ <span
563
+ :class="`${rootClass}__name`"
564
+ :title="item.filename"
565
+ >
566
+ {{ item.filename }}
567
+ </span>
568
+ <span :class="`${rootClass}__sub`">
569
+ {{ formatSize(item.filesize) }}
570
+ <template v-if="item.width && item.height">
571
+ · {{ item.width }}×{{ item.height }}
572
+ </template>
573
+ </span>
574
+ </div>
575
+ <KateCmsUiButton
576
+ tag="button"
577
+ :variant="['red', 'small']"
578
+ @click="remove(item)"
579
+ >
580
+ <svg
581
+ viewBox="0 0 24 24"
582
+ fill="none"
583
+ stroke="currentColor"
584
+ stroke-width="2"
585
+ stroke-linecap="round"
586
+ stroke-linejoin="round"
587
+ >
588
+ <path d="M3 6h18" />
589
+ <path d="M8 6V4h8v2" />
590
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" />
591
+ </svg>
592
+ Delete
593
+ </KateCmsUiButton>
594
+ </div>
595
+ </div>
596
+ <div
597
+ v-if="hasMore"
598
+ ref="sentinel"
599
+ :class="`${rootClass}__more`"
600
+ >
601
+ {{ loadingMore ? "Loading\u2026" : "" }}
602
+ </div>
603
+ </div>
604
+
605
+ <div
606
+ v-if="selected"
607
+ :class="`${rootClass}__overlay`"
608
+ @click.self="closeEditor"
609
+ >
610
+ <div :class="`${rootClass}__modal`">
611
+ <div :class="`${rootClass}__modal-head`">
612
+ <div :class="`${rootClass}__modal-title`">
613
+ File details
614
+ </div>
615
+ <KateCmsUiButton
616
+ tag="button"
617
+ :variant="['tertiary', 'small', 'icon']"
618
+ aria-label="Close"
619
+ @click="closeEditor"
620
+ >
621
+ <svg
622
+ xmlns="http://www.w3.org/2000/svg"
623
+ viewBox="0 0 640 640"
624
+ fill="currentColor"
625
+ >
626
+ <path
627
+ d="M183.1 137.4C170.6 124.9 150.3 124.9 137.8 137.4C125.3 149.9 125.3 170.2 137.8 182.7L275.2 320L137.9 457.4C125.4 469.9 125.4 490.2 137.9 502.7C150.4 515.2 170.7 515.2 183.2 502.7L320.5 365.3L457.9 502.6C470.4 515.1 490.7 515.1 503.2 502.6C515.7 490.1 515.7 469.8 503.2 457.3L365.8 320L503.1 182.6C515.6 170.1 515.6 149.8 503.1 137.3C490.6 124.8 470.3 124.8 457.8 137.3L320.5 274.7L183.1 137.4z"
628
+ />
629
+ </svg>
630
+ </KateCmsUiButton>
631
+ </div>
632
+
633
+ <div :class="`${rootClass}__modal-body`">
634
+ <div :class="`${rootClass}__preview`">
635
+ <picture v-if="isImageMedia(selected)">
636
+ <source
637
+ v-for="variant in pictureSources(selected)"
638
+ :key="variant.format"
639
+ :srcset="variant.url"
640
+ :type="`image/${variant.format}`"
641
+ >
642
+ <img
643
+ :src="selected.url"
644
+ :alt="selected.alt || selected.filename"
645
+ >
646
+ </picture>
647
+ <span
648
+ v-else
649
+ :class="`${rootClass}__ext`"
650
+ >{{ selected.mime_type }}</span>
651
+ </div>
652
+
653
+ <div :class="`${rootClass}__side`">
654
+ <div :class="`${rootClass}__details`">
655
+ <div :class="`${rootClass}__row`">
656
+ <div :class="`${rootClass}__term`">
657
+ Uploaded
658
+ </div>
659
+ <div :class="`${rootClass}__def`">
660
+ {{ formatDate(selected.created_at) }}
661
+ </div>
662
+ </div>
663
+ <div :class="`${rootClass}__row`">
664
+ <div :class="`${rootClass}__term`">
665
+ Author
666
+ </div>
667
+ <div :class="`${rootClass}__def`">
668
+ {{ selected.uploaded_by_name || "\u2014" }}
669
+ </div>
670
+ </div>
671
+ <div :class="`${rootClass}__row`">
672
+ <div :class="`${rootClass}__term`">
673
+ File name
674
+ </div>
675
+ <div :class="`${rootClass}__def`">
676
+ {{ selected.filename }}
677
+ </div>
678
+ </div>
679
+ <div :class="`${rootClass}__row`">
680
+ <div :class="`${rootClass}__term`">
681
+ Type
682
+ </div>
683
+ <div :class="`${rootClass}__def`">
684
+ {{ selected.mime_type }}
685
+ </div>
686
+ </div>
687
+ <div :class="`${rootClass}__row`">
688
+ <div :class="`${rootClass}__term`">
689
+ Size
690
+ </div>
691
+ <div :class="`${rootClass}__def`">
692
+ {{ formatSize(selected.filesize) }}
693
+ </div>
694
+ </div>
695
+ <div
696
+ v-if="selected.width && selected.height"
697
+ :class="`${rootClass}__row`"
698
+ >
699
+ <div :class="`${rootClass}__term`">
700
+ Dimensions
701
+ </div>
702
+ <div :class="`${rootClass}__def`">
703
+ {{ selected.width }} × {{ selected.height }} px
704
+ </div>
705
+ </div>
706
+ <div :class="`${rootClass}__row`">
707
+ <div :class="`${rootClass}__term`">
708
+ URL
709
+ </div>
710
+ <div :class="`${rootClass}__def`">
711
+ <a
712
+ :href="selected.url"
713
+ target="_blank"
714
+ rel="noopener"
715
+ >{{ selected.url }}</a>
716
+ </div>
717
+ </div>
718
+ <div
719
+ v-if="isImageMedia(selected) && selected.variants.length"
720
+ :class="`${rootClass}__row`"
721
+ >
722
+ <div :class="`${rootClass}__term`">
723
+ Variants
724
+ </div>
725
+ <div :class="`${rootClass}__def`">
726
+ <div :class="`${rootClass}__variants`">
727
+ <div
728
+ v-for="variant in selected.variants"
729
+ :key="variant.filename"
730
+ >
731
+ <a
732
+ :href="variant.url"
733
+ target="_blank"
734
+ rel="noopener"
735
+ >
736
+ {{ variant.format.toUpperCase() }}
737
+ · {{ variant.size }}
738
+ · {{ variant.width }}×{{ variant.height }}
739
+ · {{ formatSize(variant.filesize) }}
740
+ </a>
741
+ </div>
742
+ </div>
743
+ </div>
744
+ </div>
745
+ </div>
746
+
747
+ <form
748
+ :class="`${rootClass}__form`"
749
+ @submit.prevent="saveMeta"
750
+ >
751
+ <KateCmsFieldWrapper
752
+ field-key="katecms-media-alt"
753
+ :field="altField"
754
+ >
755
+ <KateCmsInputControl
756
+ v-model="editAlt"
757
+ field-key="katecms-media-alt"
758
+ />
759
+ </KateCmsFieldWrapper>
760
+
761
+ <KateCmsTextareaField
762
+ v-model="editCaption"
763
+ field-key="katecms-media-caption"
764
+ :field="captionField"
765
+ />
766
+
767
+ <KateCmsUiButton
768
+ tag="button"
769
+ type="submit"
770
+ :disabled="saving"
771
+ >
772
+ {{ saving ? "Saving\u2026" : "Save" }}
773
+ </KateCmsUiButton>
774
+ </form>
775
+
776
+ <KateCmsUiButton
777
+ v-if="isImageMedia(selected)"
778
+ tag="button"
779
+ variant="secondary"
780
+ :disabled="selected.variants_status === 'pending'"
781
+ @click="regenerateOne(selected)"
782
+ >
783
+ {{ selected.variants_status === "pending" ? "Processing\u2026" : "Regenerate variants" }}
784
+ </KateCmsUiButton>
785
+ </div>
786
+ </div>
787
+ </div>
788
+ </div>
789
+ </div>
790
+ </template>
791
+
792
+ <style scoped>
793
+ body#katecms-body .katecms-media {
794
+ display: flex;
795
+ flex: 1;
796
+ flex-direction: column;
797
+ min-height: 0;
798
+ overflow: hidden;
799
+ padding: 0 0.5rem;
800
+ }
801
+ body#katecms-body .katecms-media__file {
802
+ display: none;
803
+ }
804
+ body#katecms-body .katecms-media__filters {
805
+ position: relative;
806
+ z-index: 2;
807
+ margin-bottom: 0.5rem;
808
+ }
809
+ body#katecms-body .katecms-media__scroller {
810
+ flex: 1;
811
+ min-height: 0;
812
+ padding: 0 0 0.5rem;
813
+ overflow: auto;
814
+ }
815
+ body#katecms-body .katecms-media__grid {
816
+ display: grid;
817
+ grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
818
+ gap: 1rem;
819
+ align-content: start;
820
+ }
821
+ body#katecms-body .katecms-media__more {
822
+ min-height: 2rem;
823
+ padding: 0.5rem 0;
824
+ color: var(--katecms-color-muted);
825
+ font-size: 0.8125rem;
826
+ text-align: center;
827
+ }
828
+ body#katecms-body .katecms-media__card {
829
+ position: relative;
830
+ display: flex;
831
+ flex-direction: column;
832
+ min-width: 0;
833
+ overflow: hidden;
834
+ background: var(--katecms-color-surface);
835
+ border: 1px solid var(--katecms-color-border);
836
+ border-radius: var(--katecms-border-radius);
837
+ box-shadow: var(--katecms-shadow-sm);
838
+ }
839
+ body#katecms-body .katecms-media__card.is-marked {
840
+ border-color: var(--katecms-color-accent);
841
+ box-shadow: 0 0 0 1px var(--katecms-color-accent);
842
+ }
843
+ body#katecms-body .katecms-media__card :deep(.katecms-btn) {
844
+ width: calc(100% - 1rem);
845
+ margin: 0 0.5rem 0.5rem;
846
+ }
847
+ body#katecms-body .katecms-media__check {
848
+ position: absolute;
849
+ z-index: 1;
850
+ top: 0.5rem;
851
+ left: 0.5rem;
852
+ display: flex;
853
+ align-items: center;
854
+ justify-content: center;
855
+ width: 1.75rem;
856
+ height: 1.75rem;
857
+ margin: 0;
858
+ border-radius: var(--katecms-border-radius);
859
+ background: rgb(from var(--katecms-color-surface) r g b / 0.92);
860
+ box-shadow: var(--katecms-shadow-sm);
861
+ cursor: pointer;
862
+ }
863
+ body#katecms-body .katecms-media__check input {
864
+ width: 1rem;
865
+ height: 1rem;
866
+ margin: 0;
867
+ accent-color: var(--katecms-color-accent);
868
+ cursor: pointer;
869
+ }
870
+ body#katecms-body .katecms-media__thumb {
871
+ position: relative;
872
+ display: flex;
873
+ flex: none;
874
+ align-items: center;
875
+ justify-content: center;
876
+ width: 100%;
877
+ aspect-ratio: 4/3;
878
+ padding: 0;
879
+ overflow: hidden;
880
+ border: none;
881
+ background: var(--katecms-color-bg);
882
+ cursor: pointer;
883
+ }
884
+ body#katecms-body .katecms-media__thumb picture {
885
+ width: 100%;
886
+ height: 100%;
887
+ }
888
+ body#katecms-body .katecms-media__thumb img {
889
+ width: 100%;
890
+ height: 100%;
891
+ object-fit: cover;
892
+ }
893
+ body#katecms-body .katecms-media__processing {
894
+ position: absolute;
895
+ inset: 0;
896
+ display: flex;
897
+ align-items: center;
898
+ justify-content: center;
899
+ gap: 0.375rem;
900
+ background: var(--katecms-color-overlay);
901
+ color: var(--katecms-color-on-accent);
902
+ font-size: 0.75rem;
903
+ font-weight: 600;
904
+ }
905
+ body#katecms-body .katecms-media__spinner {
906
+ width: 0.875rem;
907
+ height: 0.875rem;
908
+ border: 2px solid rgb(from var(--katecms-color-on-accent) r g b / 0.4);
909
+ border-top-color: var(--katecms-color-on-accent);
910
+ border-radius: 50%;
911
+ animation: katecms-media-spin 0.7s linear infinite;
912
+ }
913
+ @keyframes katecms-media-spin {
914
+ to {
915
+ transform: rotate(360deg);
916
+ }
917
+ }
918
+ body#katecms-body .katecms-media__ext {
919
+ padding: 0 0.5rem;
920
+ color: var(--katecms-color-muted);
921
+ font-size: 0.75rem;
922
+ text-align: center;
923
+ word-break: break-all;
924
+ }
925
+ body#katecms-body .katecms-media__meta {
926
+ display: flex;
927
+ flex-direction: column;
928
+ gap: 0.125rem;
929
+ min-width: 0;
930
+ padding: 0.5rem 0.625rem;
931
+ }
932
+ body#katecms-body .katecms-media__name {
933
+ overflow: hidden;
934
+ color: var(--katecms-color-ink);
935
+ font-size: 0.8125rem;
936
+ font-weight: 600;
937
+ white-space: nowrap;
938
+ text-overflow: ellipsis;
939
+ }
940
+ body#katecms-body .katecms-media__sub {
941
+ color: var(--katecms-color-muted);
942
+ font-size: 0.75rem;
943
+ }
944
+ body#katecms-body .katecms-media__overlay {
945
+ position: fixed;
946
+ inset: 0;
947
+ z-index: 1000;
948
+ display: flex;
949
+ align-items: center;
950
+ justify-content: center;
951
+ padding: 1.5rem;
952
+ background: var(--katecms-color-overlay);
953
+ }
954
+ body#katecms-body .katecms-media__modal {
955
+ display: flex;
956
+ flex-direction: column;
957
+ width: 100%;
958
+ max-width: 87.5rem;
959
+ max-height: 90vh;
960
+ overflow: hidden;
961
+ background: var(--katecms-color-surface);
962
+ border-radius: var(--katecms-border-radius);
963
+ box-shadow: var(--katecms-shadow-md);
964
+ }
965
+ body#katecms-body .katecms-media__modal-head {
966
+ display: flex;
967
+ align-items: center;
968
+ justify-content: space-between;
969
+ padding: 0.875rem 1rem;
970
+ border-bottom: 1px solid var(--katecms-color-border);
971
+ }
972
+ body#katecms-body .katecms-media__modal-title {
973
+ margin: 0;
974
+ font-size: 1rem;
975
+ font-weight: 600;
976
+ color: var(--katecms-color-ink);
977
+ }
978
+ body#katecms-body .katecms-media__modal-body {
979
+ display: grid;
980
+ grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
981
+ gap: 1.25rem;
982
+ padding: 1rem;
983
+ overflow: auto;
984
+ }
985
+ @media (max-width: 800px) {
986
+ body#katecms-body .katecms-media__modal-body {
987
+ grid-template-columns: 1fr;
988
+ }
989
+ }
990
+ body#katecms-body .katecms-media__preview {
991
+ min-height: 14rem;
992
+ overflow: hidden;
993
+ background: var(--katecms-color-bg);
994
+ border-radius: var(--katecms-border-radius);
995
+ }
996
+ body#katecms-body .katecms-media__preview picture {
997
+ width: 100%;
998
+ height: 100%;
999
+ }
1000
+ body#katecms-body .katecms-media__preview img {
1001
+ width: 100%;
1002
+ height: 100%;
1003
+ object-fit: contain;
1004
+ }
1005
+ body#katecms-body .katecms-media__side {
1006
+ display: flex;
1007
+ flex-direction: column;
1008
+ gap: 1rem;
1009
+ min-width: 0;
1010
+ }
1011
+ body#katecms-body .katecms-media__details {
1012
+ display: flex;
1013
+ flex-direction: column;
1014
+ gap: 0.375rem;
1015
+ margin: 0;
1016
+ font-size: 0.8125rem;
1017
+ }
1018
+ body#katecms-body .katecms-media__variants {
1019
+ display: flex;
1020
+ flex-direction: column;
1021
+ gap: 0.25rem;
1022
+ margin: 0;
1023
+ padding: 0;
1024
+ list-style: none;
1025
+ font-size: 0.75rem;
1026
+ }
1027
+ body#katecms-body .katecms-media__term {
1028
+ color: var(--katecms-color-muted);
1029
+ }
1030
+ body#katecms-body .katecms-media__def {
1031
+ margin: 0;
1032
+ color: var(--katecms-color-ink);
1033
+ word-break: break-word;
1034
+ }
1035
+ body#katecms-body .katecms-media__row {
1036
+ display: grid;
1037
+ grid-template-columns: 7rem minmax(0, 1fr);
1038
+ gap: 0.5rem;
1039
+ }
1040
+ body#katecms-body .katecms-media__row a {
1041
+ color: var(--katecms-color-accent);
1042
+ text-decoration: none;
1043
+ }
1044
+ body#katecms-body .katecms-media__row a:hover {
1045
+ text-decoration: underline;
1046
+ }
1047
+ body#katecms-body .katecms-media__form {
1048
+ display: flex;
1049
+ flex-direction: column;
1050
+ gap: 0.75rem;
1051
+ padding-top: 1rem;
1052
+ border-top: 1px solid var(--katecms-color-border);
1053
+ }
1054
+ </style>