includio-cms 0.1.4 → 0.5.0

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 (296) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/ROADMAP.md +18 -13
  3. package/dist/admin/api/accept-invite.js +1 -5
  4. package/dist/admin/api/invite.js +7 -16
  5. package/dist/admin/client/account/account-page.svelte +20 -50
  6. package/dist/admin/client/account/lang.d.ts +15 -23
  7. package/dist/admin/client/account/lang.js +51 -67
  8. package/dist/admin/client/account/preferences-section.svelte +26 -84
  9. package/dist/admin/client/account/profile-section.svelte +60 -40
  10. package/dist/admin/client/account/schema.d.ts +11 -3
  11. package/dist/admin/client/account/schema.js +25 -16
  12. package/dist/admin/client/account/security-section.svelte +139 -105
  13. package/dist/admin/client/account/sessions-section.svelte +35 -34
  14. package/dist/admin/client/admin/admin-after-login-layout-content.svelte +3 -5
  15. package/dist/admin/client/admin/admin-layout.svelte +3 -2
  16. package/dist/admin/client/admin/admin-preloader.svelte +36 -0
  17. package/dist/admin/client/admin/admin-preloader.svelte.d.ts +18 -0
  18. package/dist/admin/client/admin/dashboard-page.svelte +55 -41
  19. package/dist/admin/client/collection/a11y-score-cell.svelte +45 -0
  20. package/dist/admin/client/collection/a11y-score-cell.svelte.d.ts +6 -0
  21. package/dist/admin/client/collection/bulk-actions-bar.svelte +83 -0
  22. package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +9 -0
  23. package/dist/admin/client/collection/collection-entries.svelte +255 -260
  24. package/dist/admin/client/collection/collection-view.svelte.d.ts +4 -3
  25. package/dist/admin/client/collection/collection-view.svelte.js +9 -5
  26. package/dist/admin/client/collection/collection.svelte +22 -12
  27. package/dist/admin/client/collection/data-table.svelte +50 -39
  28. package/dist/admin/client/collection/data-table.svelte.d.ts +1 -0
  29. package/dist/admin/client/collection/date-cell.svelte +7 -5
  30. package/dist/admin/client/collection/date-cell.svelte.d.ts +1 -1
  31. package/dist/admin/client/collection/empty-state.svelte +28 -0
  32. package/dist/admin/client/collection/empty-state.svelte.d.ts +9 -0
  33. package/dist/admin/client/collection/entry-link.svelte +10 -4
  34. package/dist/admin/client/collection/entry-link.svelte.d.ts +1 -0
  35. package/dist/admin/client/collection/grid-view.svelte +21 -23
  36. package/dist/admin/client/collection/grid-view.svelte.d.ts +1 -2
  37. package/dist/admin/client/collection/row-actions.svelte +60 -0
  38. package/dist/admin/client/collection/row-actions.svelte.d.ts +9 -0
  39. package/dist/admin/client/collection/status-badge.svelte +7 -8
  40. package/dist/admin/client/collection/table-pagination.svelte +122 -79
  41. package/dist/admin/client/collection/table-pagination.svelte.d.ts +1 -0
  42. package/dist/admin/client/collection/table-toolbar.svelte +108 -88
  43. package/dist/admin/client/collection/table-toolbar.svelte.d.ts +8 -9
  44. package/dist/admin/client/entry/entry-form.svelte +109 -1
  45. package/dist/admin/client/entry/entry-header.svelte +96 -37
  46. package/dist/admin/client/entry/entry-header.svelte.d.ts +5 -0
  47. package/dist/admin/client/entry/entry.svelte +171 -60
  48. package/dist/admin/client/entry/header/a11y-validator.d.ts +46 -0
  49. package/dist/admin/client/entry/header/a11y-validator.js +311 -0
  50. package/dist/admin/client/entry/header/publish-panel.svelte +373 -131
  51. package/dist/admin/client/entry/header/publish-panel.svelte.d.ts +4 -0
  52. package/dist/admin/client/entry/header/save-indicator.svelte +33 -23
  53. package/dist/admin/client/entry/header/schedule-popover.svelte +1 -1
  54. package/dist/admin/client/entry/header/status-badge.svelte +25 -118
  55. package/dist/admin/client/entry/header/version-history-sheet.svelte +314 -98
  56. package/dist/admin/client/form/form-submission/form-submission.svelte +271 -83
  57. package/dist/admin/client/form/form-submission/submission-field.svelte +12 -12
  58. package/dist/admin/client/form/form-submissions.svelte +421 -139
  59. package/dist/admin/client/form/submission-link.svelte +8 -2
  60. package/dist/admin/client/form/submission-link.svelte.d.ts +1 -0
  61. package/dist/admin/client/form/submission-status-badge.svelte +18 -4
  62. package/dist/admin/client/form/submission-status-badge.svelte.d.ts +1 -0
  63. package/dist/admin/client/login/lang.d.ts +32 -0
  64. package/dist/admin/client/login/lang.js +66 -2
  65. package/dist/admin/client/login/login-form.svelte +237 -95
  66. package/dist/admin/client/login/login-form.svelte.d.ts +2 -17
  67. package/dist/admin/client/login/login-page.svelte +34 -98
  68. package/dist/admin/client/login/reset-password-page.svelte +235 -0
  69. package/dist/admin/client/login/reset-password-page.svelte.d.ts +4 -0
  70. package/dist/admin/client/login/schema.d.ts +15 -0
  71. package/dist/admin/client/login/schema.js +21 -0
  72. package/dist/admin/client/users/accept-invite-page.svelte +166 -37
  73. package/dist/admin/client/users/create-user-dialog.svelte +15 -7
  74. package/dist/admin/client/users/delete-user-dialog.svelte +81 -16
  75. package/dist/admin/client/users/delete-user-dialog.svelte.d.ts +4 -1
  76. package/dist/admin/client/users/edit-user-dialog.svelte +3 -0
  77. package/dist/admin/client/users/invite-user-dialog.svelte +16 -3
  78. package/dist/admin/client/users/lang.d.ts +27 -0
  79. package/dist/admin/client/users/lang.js +64 -10
  80. package/dist/admin/client/users/pending-invitations.svelte +59 -23
  81. package/dist/admin/client/users/users-page.svelte +471 -72
  82. package/dist/admin/components/accessibility/accessibility-overview.svelte +2 -7
  83. package/dist/admin/components/dashboard/a11y-gauge.svelte +90 -0
  84. package/dist/admin/components/dashboard/a11y-gauge.svelte.d.ts +18 -0
  85. package/dist/admin/components/dashboard/accessibility-hub.svelte +13 -12
  86. package/dist/admin/components/dashboard/form-submissions-widget.svelte +71 -113
  87. package/dist/admin/components/dashboard/index.d.ts +4 -2
  88. package/dist/admin/components/dashboard/index.js +4 -2
  89. package/dist/admin/components/dashboard/recent-activity.svelte +53 -75
  90. package/dist/admin/components/dashboard/recent-entries.svelte +94 -0
  91. package/dist/admin/components/dashboard/recent-entries.svelte.d.ts +18 -0
  92. package/dist/admin/components/dashboard/stat-card.svelte +2 -2
  93. package/dist/admin/components/dashboard/tip-of-the-day.svelte +109 -0
  94. package/dist/admin/components/dashboard/tip-of-the-day.svelte.d.ts +3 -0
  95. package/dist/admin/components/dashboard/welcome-header.svelte +45 -0
  96. package/dist/admin/components/dashboard/welcome-header.svelte.d.ts +3 -0
  97. package/dist/admin/components/fields/{array-field.svelte → blocks-field.svelte} +4 -4
  98. package/dist/admin/components/fields/{array-field.svelte.d.ts → blocks-field.svelte.d.ts} +5 -5
  99. package/dist/admin/components/fields/content-field.svelte +27 -0
  100. package/dist/admin/components/fields/content-field.svelte.d.ts +31 -0
  101. package/dist/admin/components/fields/field-renderer.svelte +9 -7
  102. package/dist/admin/components/fields/image-field.svelte +2 -2
  103. package/dist/admin/components/fields/media-field.svelte +2 -2
  104. package/dist/admin/components/fields/seo-field.svelte +205 -25
  105. package/dist/admin/components/fields/simple-array-field.svelte +289 -0
  106. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +30 -0
  107. package/dist/admin/components/fields/slug-field.svelte +3 -2
  108. package/dist/admin/components/fields/standalone-field-renderer.svelte +148 -0
  109. package/dist/admin/components/fields/standalone-field-renderer.svelte.d.ts +9 -0
  110. package/dist/admin/components/fields/text-field-wrapper.svelte +13 -1
  111. package/dist/admin/components/fields/text-field-wrapper.svelte.d.ts +2 -2
  112. package/dist/admin/components/fields/url-field.svelte +5 -4
  113. package/dist/admin/components/layout/app-sidebar.svelte +27 -24
  114. package/dist/admin/components/layout/lang.d.ts +6 -0
  115. package/dist/admin/components/layout/lang.js +13 -1
  116. package/dist/admin/components/layout/layout-renderer.svelte +352 -0
  117. package/dist/admin/components/layout/layout-renderer.svelte.d.ts +14 -0
  118. package/dist/admin/components/layout/nav-breadcrumbs.svelte +4 -4
  119. package/dist/admin/components/layout/nav-collections.svelte +65 -36
  120. package/dist/admin/components/layout/nav-footer.svelte +31 -0
  121. package/dist/admin/components/layout/nav-footer.svelte.d.ts +18 -0
  122. package/dist/admin/components/layout/nav-forms.svelte +55 -30
  123. package/dist/admin/components/layout/nav-main.svelte +14 -52
  124. package/dist/admin/components/layout/nav-search.svelte +4 -3
  125. package/dist/admin/components/layout/nav-singletons.svelte +59 -17
  126. package/dist/admin/components/layout/nav-singletons.svelte.d.ts +17 -8
  127. package/dist/admin/components/layout/site-header.svelte +74 -13
  128. package/dist/admin/components/media/alt-input.svelte +32 -22
  129. package/dist/admin/components/media/bulk-action-bar.svelte +139 -150
  130. package/dist/admin/components/media/file/file-details.svelte +299 -217
  131. package/dist/admin/components/media/file/file-miniature.svelte +54 -41
  132. package/dist/admin/components/media/file/file-miniature.svelte.d.ts +1 -0
  133. package/dist/admin/components/media/file/file-preview.svelte +1 -1
  134. package/dist/admin/components/media/file-upload.svelte +24 -26
  135. package/dist/admin/components/media/files-list.svelte +112 -40
  136. package/dist/admin/components/media/files-list.svelte.d.ts +2 -0
  137. package/dist/admin/components/media/focal-point-input.svelte +122 -26
  138. package/dist/admin/components/media/media-library.svelte +127 -70
  139. package/dist/admin/components/media/media-search.svelte +6 -6
  140. package/dist/admin/components/media/media-sort.svelte +3 -1
  141. package/dist/admin/components/media/multi-file-summary.svelte +88 -68
  142. package/dist/admin/components/media/tag-combobox.svelte +141 -66
  143. package/dist/admin/components/media/tag-combobox.svelte.d.ts +1 -0
  144. package/dist/admin/components/media/tag-sidebar.svelte +139 -121
  145. package/dist/admin/components/tiptap/FigureNodeView.svelte +144 -15
  146. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +254 -0
  147. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte.d.ts +4 -0
  148. package/dist/admin/components/tiptap/SlashCommandPopup.svelte +212 -0
  149. package/dist/admin/components/tiptap/SlashCommandPopup.svelte.d.ts +8 -0
  150. package/dist/admin/components/tiptap/content-editor.svelte +280 -0
  151. package/dist/admin/components/tiptap/content-editor.svelte.d.ts +9 -0
  152. package/dist/admin/components/tiptap/editor-toolbar.svelte +230 -0
  153. package/dist/admin/components/tiptap/editor-toolbar.svelte.d.ts +16 -0
  154. package/dist/admin/components/tiptap/heading-a11y-plugin.d.ts +2 -0
  155. package/dist/admin/components/tiptap/heading-a11y-plugin.js +67 -0
  156. package/dist/admin/components/tiptap/image-dialog.svelte +172 -11
  157. package/dist/admin/components/tiptap/inline-block-node.d.ts +19 -0
  158. package/dist/admin/components/tiptap/inline-block-node.js +98 -0
  159. package/dist/admin/components/tiptap/link-dialog.svelte +9 -4
  160. package/dist/admin/components/tiptap/slash-command.d.ts +17 -0
  161. package/dist/admin/components/tiptap/slash-command.js +181 -0
  162. package/dist/admin/components/tiptap/structured-content-utils.d.ts +21 -0
  163. package/dist/admin/components/tiptap/structured-content-utils.js +150 -0
  164. package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -190
  165. package/dist/admin/email/invite-template.d.ts +8 -0
  166. package/dist/admin/email/invite-template.js +99 -0
  167. package/dist/admin/email/reset-password-template.d.ts +7 -0
  168. package/dist/admin/email/reset-password-template.js +96 -0
  169. package/dist/admin/remote/ai.remote.d.ts +1 -0
  170. package/dist/admin/remote/ai.remote.js +4 -1
  171. package/dist/admin/remote/entry.remote.d.ts +8 -0
  172. package/dist/admin/remote/entry.remote.js +53 -4
  173. package/dist/admin/remote/preview.remote.js +2 -1
  174. package/dist/admin/shared/password-schema.d.ts +5 -0
  175. package/dist/admin/shared/password-schema.js +10 -0
  176. package/dist/admin/styles/admin.css +1530 -151
  177. package/dist/admin/utils/formatDate.d.ts +1 -0
  178. package/dist/admin/utils/formatDate.js +8 -0
  179. package/dist/admin/utils/roleLabel.d.ts +2 -0
  180. package/dist/admin/utils/roleLabel.js +13 -0
  181. package/dist/ai-claude/index.d.ts +2 -0
  182. package/dist/ai-claude/index.js +56 -0
  183. package/dist/cms/runtime/api.d.ts +6 -1
  184. package/dist/cms/runtime/api.js +3 -0
  185. package/dist/cms/runtime/schemas.d.ts +9 -1
  186. package/dist/cms/runtime/schemas.js +8 -0
  187. package/dist/cms/runtime/types.d.ts +82 -10
  188. package/dist/cms/runtime/types.js +4 -0
  189. package/dist/components/ui/accordion/accordion.stories.svelte +39 -0
  190. package/dist/components/ui/accordion/accordion.stories.svelte.d.ts +27 -0
  191. package/dist/components/ui/alert/alert.stories.svelte +53 -0
  192. package/dist/components/ui/alert/alert.stories.svelte.d.ts +27 -0
  193. package/dist/components/ui/alert/alert.svelte +5 -0
  194. package/dist/components/ui/alert/alert.svelte.d.ts +9 -0
  195. package/dist/components/ui/avatar/avatar.stories.svelte +16 -0
  196. package/dist/components/ui/avatar/avatar.stories.svelte.d.ts +27 -0
  197. package/dist/components/ui/badge/badge.stories.svelte +33 -0
  198. package/dist/components/ui/badge/badge.stories.svelte.d.ts +27 -0
  199. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +33 -0
  200. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte.d.ts +27 -0
  201. package/dist/components/ui/button/button.stories.svelte +43 -0
  202. package/dist/components/ui/button/button.stories.svelte.d.ts +27 -0
  203. package/dist/components/ui/button/button.svelte +1 -2
  204. package/dist/components/ui/button/button.svelte.d.ts +0 -3
  205. package/dist/components/ui/button-group/button-group-separator.svelte.d.ts +1 -1
  206. package/dist/components/ui/card/card.stories.svelte +42 -0
  207. package/dist/components/ui/card/card.stories.svelte.d.ts +27 -0
  208. package/dist/components/ui/command/command.stories.svelte +51 -0
  209. package/dist/components/ui/command/command.stories.svelte.d.ts +27 -0
  210. package/dist/components/ui/dialog/dialog.stories.svelte +29 -0
  211. package/dist/components/ui/dialog/dialog.stories.svelte.d.ts +27 -0
  212. package/dist/components/ui/field/field-label.svelte.d.ts +1 -1
  213. package/dist/components/ui/field/field.stories.svelte +21 -0
  214. package/dist/components/ui/field/field.stories.svelte.d.ts +27 -0
  215. package/dist/components/ui/input/input.stories.svelte +40 -0
  216. package/dist/components/ui/input/input.stories.svelte.d.ts +27 -0
  217. package/dist/components/ui/input/input.svelte +2 -4
  218. package/dist/components/ui/item/item-separator.svelte.d.ts +1 -1
  219. package/dist/components/ui/label/label.stories.svelte +20 -0
  220. package/dist/components/ui/label/label.stories.svelte.d.ts +27 -0
  221. package/dist/components/ui/popover/popover.stories.svelte +29 -0
  222. package/dist/components/ui/popover/popover.stories.svelte.d.ts +27 -0
  223. package/dist/components/ui/select/select-group-heading.svelte.d.ts +1 -1
  224. package/dist/components/ui/select/select.stories.svelte +23 -0
  225. package/dist/components/ui/select/select.stories.svelte.d.ts +27 -0
  226. package/dist/components/ui/separator/separator.stories.svelte +24 -0
  227. package/dist/components/ui/separator/separator.stories.svelte.d.ts +27 -0
  228. package/dist/components/ui/sheet/sheet.stories.svelte +29 -0
  229. package/dist/components/ui/sheet/sheet.stories.svelte.d.ts +27 -0
  230. package/dist/components/ui/sidebar/sidebar-group.svelte +3 -3
  231. package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +2 -2
  232. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +28 -30
  233. package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +7 -7
  234. package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +1 -1
  235. package/dist/components/ui/sidebar/sidebar-trigger.svelte +4 -4
  236. package/dist/components/ui/sonner/sonner.stories.svelte +22 -0
  237. package/dist/components/ui/sonner/sonner.stories.svelte.d.ts +26 -0
  238. package/dist/components/ui/sonner/sonner.svelte +8 -2
  239. package/dist/components/ui/sonner/toast-demo.svelte +29 -0
  240. package/dist/components/ui/sonner/toast-demo.svelte.d.ts +6 -0
  241. package/dist/components/ui/textarea/textarea.stories.svelte +22 -0
  242. package/dist/components/ui/textarea/textarea.stories.svelte.d.ts +27 -0
  243. package/dist/components/ui/textarea/textarea.svelte +0 -2
  244. package/dist/components/ui/toggle/toggle.stories.svelte +22 -0
  245. package/dist/components/ui/toggle/toggle.stories.svelte.d.ts +27 -0
  246. package/dist/components/ui/toggle-group/toggle-group.stories.svelte +17 -0
  247. package/dist/components/ui/toggle-group/toggle-group.stories.svelte.d.ts +27 -0
  248. package/dist/components/ui/tooltip/tooltip.stories.svelte +26 -0
  249. package/dist/components/ui/tooltip/tooltip.stories.svelte.d.ts +27 -0
  250. package/dist/core/fields/fieldSchemaToTs.d.ts +1 -0
  251. package/dist/core/fields/fieldSchemaToTs.js +133 -1
  252. package/dist/core/fields/layoutUtils.d.ts +17 -0
  253. package/dist/core/fields/layoutUtils.js +149 -0
  254. package/dist/core/fields/structuredToHtml.d.ts +9 -0
  255. package/dist/core/fields/structuredToHtml.js +161 -0
  256. package/dist/core/server/entries/operations/create.js +2 -1
  257. package/dist/core/server/entries/operations/get.js +8 -6
  258. package/dist/core/server/entries/operations/update.d.ts +3 -0
  259. package/dist/core/server/entries/operations/update.js +30 -2
  260. package/dist/core/server/fields/queryStructuredContent.d.ts +15 -0
  261. package/dist/core/server/fields/queryStructuredContent.js +65 -0
  262. package/dist/core/server/fields/resolveImageFields.js +51 -2
  263. package/dist/core/server/fields/resolveRelationFields.js +2 -2
  264. package/dist/core/server/fields/resolveRichtextLinks.js +80 -13
  265. package/dist/core/server/fields/resolveUrlFields.js +57 -6
  266. package/dist/core/server/fields/slugResolver.d.ts +10 -0
  267. package/dist/core/server/fields/slugResolver.js +34 -0
  268. package/dist/core/server/generator/fields.js +15 -4
  269. package/dist/core/server/generator/generator.js +3 -2
  270. package/dist/files-local/index.js +126 -64
  271. package/dist/server/auth.d.ts +5 -0
  272. package/dist/server/auth.js +12 -1
  273. package/dist/sveltekit/components/structured-content.svelte +204 -0
  274. package/dist/sveltekit/components/structured-content.svelte.d.ts +21 -0
  275. package/dist/sveltekit/config.d.ts +13 -3
  276. package/dist/sveltekit/index.d.ts +3 -0
  277. package/dist/sveltekit/index.js +3 -0
  278. package/dist/sveltekit/server/handle.js +1 -0
  279. package/dist/types/config.d.ts +3 -0
  280. package/dist/types/fields.d.ts +19 -2
  281. package/dist/types/index.d.ts +2 -0
  282. package/dist/types/index.js +2 -0
  283. package/dist/types/layout.d.ts +54 -0
  284. package/dist/types/layout.js +6 -0
  285. package/dist/types/structured-content.d.ts +63 -0
  286. package/dist/types/structured-content.js +1 -0
  287. package/dist/updates/0.1.5/index.d.ts +2 -0
  288. package/dist/updates/0.1.5/index.js +18 -0
  289. package/dist/updates/0.2.0/index.d.ts +2 -0
  290. package/dist/updates/0.2.0/index.js +11 -0
  291. package/dist/updates/0.2.2/index.d.ts +2 -0
  292. package/dist/updates/0.2.2/index.js +13 -0
  293. package/dist/updates/0.5.0/index.d.ts +2 -0
  294. package/dist/updates/0.5.0/index.js +14 -0
  295. package/dist/updates/index.js +5 -1
  296. package/package.json +16 -9
@@ -3,24 +3,29 @@
3
3
  import type { DbEntryVersion, EntryStatus, RawEntry } from '../../../../types/entries.js';
4
4
  import type { InterfaceLanguage } from '../../../../types/languages.js';
5
5
  import type { UpdateEntryVersionCommandType } from '../../../../core/server/entries/operations/update.js';
6
+ import type { Field } from '../../../../types/fields.js';
6
7
  import * as Sheet from '../../../../components/ui/sheet/index.js';
7
- import Badge from '../../../../components/ui/badge/badge.svelte';
8
8
  import Button from '../../../../components/ui/button/button.svelte';
9
- import { Input } from '../../../../components/ui/input/index.js';
10
9
  import SettingsIcon from '@tabler/icons-svelte/icons/settings';
11
10
  import CalendarClock from '@tabler/icons-svelte/icons/calendar-clock';
12
11
  import SquareCheckFilled from '@tabler/icons-svelte/icons/square-check-filled';
13
12
  import ClockFilled from '@tabler/icons-svelte/icons/clock-filled';
14
13
  import FileFilled from '@tabler/icons-svelte/icons/file-filled';
14
+ import AlertTriangle from '@tabler/icons-svelte/icons/alert-triangle';
15
+ import Archive from '@tabler/icons-svelte/icons/archive';
16
+ import InfoCircle from '@tabler/icons-svelte/icons/info-circle';
17
+ import Shield from '@tabler/icons-svelte/icons/shield';
18
+ import CircleCheck from '@tabler/icons-svelte/icons/circle-check';
15
19
  import { getEntryStatus } from '../utils.js';
20
+ import { validateA11y, a11yLangPl, a11yLangEn, type A11yIssue } from './a11y-validator.js';
16
21
 
17
22
  const lang: Record<
18
23
  InterfaceLanguage,
19
24
  {
20
25
  title: string;
26
+ description: string;
21
27
  status: string;
22
28
  statusLabels: Record<EntryStatus, string>;
23
- version: string;
24
29
  publishedAt: string;
25
30
  scheduledFor: string;
26
31
  schedulePublish: string;
@@ -31,14 +36,17 @@
31
36
  unpublish: string;
32
37
  cancelSchedule: string;
33
38
  archive: string;
34
- actions: string;
39
+ dangerZone: string;
35
40
  date: string;
36
41
  time: string;
37
42
  publishedVersion: string;
43
+ accessibility: string;
44
+ a11yHint: string;
38
45
  }
39
46
  > = {
40
47
  en: {
41
48
  title: 'Publication',
49
+ description: 'Manage publication status, scheduling, and entry lifecycle',
42
50
  status: 'Status',
43
51
  statusLabels: {
44
52
  draft: 'Draft',
@@ -46,7 +54,6 @@
46
54
  scheduled: 'Scheduled',
47
55
  archived: 'Archived'
48
56
  },
49
- version: 'Version',
50
57
  publishedAt: 'Published at',
51
58
  scheduledFor: 'Scheduled for',
52
59
  schedulePublish: 'Schedule Publish',
@@ -56,22 +63,24 @@
56
63
  cancel: 'Cancel',
57
64
  unpublish: 'Unpublish',
58
65
  cancelSchedule: 'Cancel Schedule',
59
- archive: 'Archive',
60
- actions: 'Actions',
66
+ archive: 'Archive entry',
67
+ dangerZone: 'Danger Zone',
61
68
  date: 'Date',
62
69
  time: 'Time',
63
- publishedVersion: 'Published version'
70
+ publishedVersion: 'Published version',
71
+ accessibility: 'Accessibility',
72
+ a11yHint: 'Resolve issues before publishing'
64
73
  },
65
74
  pl: {
66
75
  title: 'Publikacja',
76
+ description: 'Zarządzaj statusem publikacji, planowaniem i cyklem życia wpisu',
67
77
  status: 'Status',
68
78
  statusLabels: {
69
- draft: 'Szkic',
79
+ draft: 'Wersja robocza',
70
80
  published: 'Opublikowane',
71
81
  scheduled: 'Zaplanowane',
72
82
  archived: 'Zarchiwizowane'
73
83
  },
74
- version: 'Wersja',
75
84
  publishedAt: 'Opublikowano',
76
85
  scheduledFor: 'Zaplanowano na',
77
86
  schedulePublish: 'Zaplanuj publikację',
@@ -81,11 +90,13 @@
81
90
  cancel: 'Anuluj',
82
91
  unpublish: 'Cofnij publikację',
83
92
  cancelSchedule: 'Anuluj planowanie',
84
- archive: 'Zarchiwizuj',
85
- actions: 'Akcje',
93
+ archive: 'Archiwizuj wpis',
94
+ dangerZone: 'Strefa zagrożenia',
86
95
  date: 'Data',
87
96
  time: 'Czas',
88
- publishedVersion: 'Opublikowana wersja'
97
+ publishedVersion: 'Opublikowana wersja',
98
+ accessibility: 'Dostępność',
99
+ a11yHint: 'Rozwiąż problemy przed publikacją'
89
100
  }
90
101
  };
91
102
 
@@ -94,31 +105,24 @@
94
105
  type Props = {
95
106
  entry: RawEntry;
96
107
  version: DbEntryVersion;
108
+ fields?: Field[];
109
+ getFormData?: () => Record<string, unknown>;
97
110
  onSave: (type: UpdateEntryVersionCommandType, scheduledAt?: Date) => void;
98
111
  onArchive: () => void;
112
+ onScrollToIssue?: (fieldSlug: string, nodePos: number) => void;
99
113
  };
100
114
 
101
- let { entry, version, onSave, onArchive }: Props = $props();
115
+ let { entry, version, fields = [], getFormData, onSave, onArchive, onScrollToIssue }: Props = $props();
102
116
 
103
117
  let open = $state(false);
104
118
  let dateValue = $state('');
105
119
  let timeValue = $state('');
120
+ let a11yIssues = $state<A11yIssue[]>([]);
106
121
 
107
122
  const entryStatus = $derived(getEntryStatus(entry));
108
123
  const t = $derived(lang[interfaceLanguage.current]);
109
124
 
110
- const badgeClass = $derived.by(() => {
111
- switch (entryStatus) {
112
- case 'published':
113
- return 'bg-emerald-500/90 hover:bg-emerald-500 text-white border-emerald-600/20';
114
- case 'scheduled':
115
- return 'bg-amber-500/90 hover:bg-amber-500 text-white border-amber-600/20';
116
- case 'archived':
117
- return 'bg-purple-500/90 hover:bg-purple-500 text-white border-purple-600/20';
118
- default:
119
- return 'bg-slate-200/80 dark:bg-slate-700/80 text-slate-600 dark:text-slate-300';
120
- }
121
- });
125
+ const hasA11yWarnings = $derived(a11yIssues.some((i) => i.type === 'warning'));
122
126
 
123
127
  const scheduleLabel = $derived.by(() => {
124
128
  switch (entryStatus) {
@@ -194,9 +198,20 @@
194
198
  });
195
199
  }
196
200
 
201
+ function runA11yValidation() {
202
+ if (!fields.length) {
203
+ a11yIssues = [];
204
+ return;
205
+ }
206
+ const data = getFormData ? getFormData() : version.data;
207
+ const a11yLang = interfaceLanguage.current === 'pl' ? a11yLangPl : a11yLangEn;
208
+ a11yIssues = validateA11y(data, fields, a11yLang);
209
+ }
210
+
197
211
  $effect(() => {
198
212
  if (open) {
199
213
  setDefaultValues();
214
+ runA11yValidation();
200
215
  }
201
216
  });
202
217
  </script>
@@ -204,150 +219,377 @@
204
219
  <Sheet.Root bind:open>
205
220
  <Sheet.Trigger>
206
221
  {#snippet child({ props })}
207
- <Button variant="outline" size="icon" {...props}>
222
+ <Button variant="ghost" size="icon-sm" {...props}>
208
223
  <SettingsIcon class="size-4" />
209
- <span class="sr-only">{t.title}</span>
210
224
  </Button>
211
225
  {/snippet}
212
226
  </Sheet.Trigger>
213
- <Sheet.Content side="right" class="w-[400px] sm:max-w-[400px]">
227
+ <Sheet.Content side="right" class="publish-sheet w-[380px] sm:max-w-[380px]">
214
228
  <Sheet.Header>
215
229
  <Sheet.Title>{t.title}</Sheet.Title>
230
+ <Sheet.Description class="sr-only">{t.description}</Sheet.Description>
216
231
  </Sheet.Header>
217
232
 
218
- <div class="mt-6 space-y-6">
233
+ <div class="sheet-body">
219
234
  <!-- Status section -->
220
- <div class="space-y-3">
221
- <h3 class="text-xs font-medium text-muted-foreground uppercase tracking-wider">
235
+ <div class="sheet-section">
236
+ <div class="sheet-section-title">
237
+ <InfoCircle class="size-3.5" />
222
238
  {t.status}
223
- </h3>
224
-
225
- <div class="space-y-2 text-sm">
226
- <div class="flex items-center justify-between">
227
- <span class="text-muted-foreground">{t.status}</span>
228
- <Badge class="gap-1.5 {badgeClass}">
229
- {#if entryStatus === 'published'}
230
- <SquareCheckFilled class="size-3" />
231
- {:else if entryStatus === 'scheduled'}
232
- <ClockFilled class="size-3" />
233
- {:else}
234
- <FileFilled class="size-3" />
235
- {/if}
236
- {t.statusLabels[entryStatus]}
237
- </Badge>
239
+ </div>
240
+ <div class="publish-status-card">
241
+ <div class="publish-status-icon">
242
+ {#if entryStatus === 'published'}
243
+ <SquareCheckFilled class="size-[18px]" />
244
+ {:else if entryStatus === 'scheduled'}
245
+ <ClockFilled class="size-[18px]" />
246
+ {:else}
247
+ <FileFilled class="size-[18px]" />
248
+ {/if}
238
249
  </div>
239
-
240
- <div class="flex items-center justify-between">
241
- <span class="text-muted-foreground">{t.version}</span>
242
- <span class="font-medium">v{version.versionNumber}</span>
250
+ <div class="publish-status-info">
251
+ <div class="publish-status-label">{t.statusLabels[entryStatus]}</div>
252
+ <div class="publish-status-meta">{formatDateTime(version.createdAt)}</div>
243
253
  </div>
254
+ </div>
244
255
 
245
- {#if entryStatus === 'published' && entry.publishedAt}
246
- <div class="flex items-center justify-between">
247
- <span class="text-muted-foreground">{t.publishedAt}</span>
248
- <span class="font-medium text-xs">{formatDateTime(entry.publishedAt)}</span>
249
- </div>
250
- {/if}
256
+ {#if entryStatus === 'published' && entry.publishedAt}
257
+ <div class="publish-detail-row">
258
+ <span>{t.publishedAt}</span>
259
+ <span class="tabular-nums">{formatDateTime(entry.publishedAt)}</span>
260
+ </div>
261
+ {/if}
251
262
 
252
- {#if entryStatus === 'scheduled' && entry.publishedAt}
253
- <div class="flex items-center justify-between">
254
- <span class="text-muted-foreground">{t.scheduledFor}</span>
255
- <span class="font-medium text-xs">{formatDateTime(entry.publishedAt)}</span>
256
- </div>
257
- {/if}
263
+ {#if entryStatus === 'scheduled' && entry.publishedAt}
264
+ <div class="publish-detail-row">
265
+ <span>{t.scheduledFor}</span>
266
+ <span class="tabular-nums">{formatDateTime(entry.publishedAt)}</span>
267
+ </div>
268
+ {/if}
258
269
 
259
- {#if entry.publishedVersion && entry.publishedVersion.id !== version.id}
260
- <div class="flex items-center justify-between">
261
- <span class="text-muted-foreground">{t.publishedVersion}</span>
262
- <span class="font-medium">v{entry.publishedVersion.versionNumber}</span>
263
- </div>
264
- {/if}
265
- </div>
270
+ {#if entry.publishedVersion && entry.publishedVersion.id !== version.id}
271
+ <div class="publish-detail-row">
272
+ <span>{t.publishedVersion}</span>
273
+ <span class="tabular-nums">{formatDateTime(entry.publishedVersion.createdAt)}</span>
274
+ </div>
275
+ {/if}
266
276
  </div>
267
277
 
268
278
  <!-- Schedule section -->
269
- <div class="space-y-3">
270
- <h3 class="text-xs font-medium text-muted-foreground uppercase tracking-wider flex items-center gap-1.5">
279
+ <div class="sheet-section">
280
+ <div class="sheet-section-title">
271
281
  <CalendarClock class="size-3.5" />
272
282
  {scheduleLabel}
273
- </h3>
274
-
275
- <div class="space-y-2">
276
- <div class="grid grid-cols-2 gap-2">
277
- <div>
278
- <label for="schedule-date" class="text-xs text-muted-foreground mb-1 block">{t.date}</label>
279
- <Input
280
- id="schedule-date"
281
- type="date"
282
- bind:value={dateValue}
283
- min={getMinDate()}
284
- class="w-full"
285
- />
286
- </div>
287
- <div>
288
- <label for="schedule-time" class="text-xs text-muted-foreground mb-1 block">{t.time}</label>
289
- <Input
290
- id="schedule-time"
291
- type="time"
292
- bind:value={timeValue}
293
- min={getMinTime()}
294
- class="w-full"
295
- />
296
- </div>
297
- </div>
298
- <Button
299
- size="sm"
300
- variant="gradient"
301
- class="w-full"
302
- onclick={handleSchedule}
303
- disabled={!dateValue || !timeValue}
304
- >
305
- {scheduleLabel}
306
- </Button>
307
283
  </div>
284
+ <div class="schedule-row">
285
+ <input
286
+ class="schedule-input"
287
+ type="date"
288
+ bind:value={dateValue}
289
+ min={getMinDate()}
290
+ aria-label={t.date}
291
+ />
292
+ <input
293
+ class="schedule-input"
294
+ type="time"
295
+ bind:value={timeValue}
296
+ min={getMinTime()}
297
+ aria-label={t.time}
298
+ />
299
+ </div>
300
+ <button
301
+ class="btn-schedule"
302
+ onclick={handleSchedule}
303
+ disabled={!dateValue || !timeValue}
304
+ >
305
+ {scheduleLabel}
306
+ </button>
308
307
  </div>
309
308
 
310
- <!-- Destructive actions -->
309
+ <!-- Accessibility section -->
310
+ {#if a11yIssues.length > 0}
311
+ <div class="sheet-section">
312
+ <div class="sheet-section-title">
313
+ <Shield class="size-3.5" />
314
+ {t.accessibility}
315
+ </div>
316
+ <div class="a11y-checklist">
317
+ {#each a11yIssues as issue}
318
+ {#if issue.type === 'warning' && issue.fieldSlug && issue.firstNodePos != null && onScrollToIssue}
319
+ <button
320
+ type="button"
321
+ class="a11y-item warning a11y-item-clickable"
322
+ onclick={() => {
323
+ open = false;
324
+ setTimeout(() => onScrollToIssue!(issue.fieldSlug!, issue.firstNodePos!), 200);
325
+ }}
326
+ >
327
+ <div class="a11y-item-icon">
328
+ <AlertTriangle class="size-4" />
329
+ </div>
330
+ <span class="a11y-item-text">{issue.message}</span>
331
+ </button>
332
+ {:else}
333
+ <div class="a11y-item {issue.type}">
334
+ <div class="a11y-item-icon">
335
+ {#if issue.type === 'warning'}
336
+ <AlertTriangle class="size-4" />
337
+ {:else}
338
+ <CircleCheck class="size-4" />
339
+ {/if}
340
+ </div>
341
+ <span class="a11y-item-text">{issue.message}</span>
342
+ </div>
343
+ {/if}
344
+ {/each}
345
+ </div>
346
+ {#if hasA11yWarnings}
347
+ <p class="a11y-hint">{t.a11yHint}</p>
348
+ {/if}
349
+ </div>
350
+ {/if}
351
+
352
+ <!-- Danger zone -->
311
353
  {#if entryStatus !== 'archived'}
312
- <div class="space-y-3">
313
- <h3 class="text-xs font-medium text-muted-foreground uppercase tracking-wider">
314
- {t.actions}
315
- </h3>
354
+ <div class="sheet-section">
355
+ <div class="danger-zone">
356
+ <div class="sheet-section-title danger">
357
+ <AlertTriangle class="size-3.5" />
358
+ {t.dangerZone}
359
+ </div>
316
360
 
317
- <div class="space-y-2">
318
361
  {#if entryStatus === 'published'}
319
- <Button
320
- variant="destructive"
321
- size="sm"
322
- class="w-full"
323
- onclick={handleUnpublish}
324
- >
362
+ <button class="btn-danger-outline" onclick={handleUnpublish}>
325
363
  {t.unpublish}
326
- </Button>
364
+ </button>
327
365
  {/if}
328
366
 
329
367
  {#if entryStatus === 'scheduled'}
330
- <Button
331
- variant="destructive"
332
- size="sm"
333
- class="w-full"
334
- onclick={handleCancelSchedule}
335
- >
368
+ <button class="btn-danger-outline" onclick={handleCancelSchedule}>
336
369
  {t.cancelSchedule}
337
- </Button>
370
+ </button>
338
371
  {/if}
339
372
 
340
- <Button
341
- variant="outline"
342
- size="sm"
343
- class="w-full text-destructive hover:text-destructive"
373
+ <button
374
+ class="btn-danger-outline archive"
344
375
  onclick={handleArchive}
345
376
  >
346
377
  {t.archive}
347
- </Button>
378
+ </button>
348
379
  </div>
349
380
  </div>
350
381
  {/if}
351
382
  </div>
352
383
  </Sheet.Content>
353
384
  </Sheet.Root>
385
+
386
+ <style>
387
+ .sheet-body {
388
+ padding: 18px 20px;
389
+ }
390
+
391
+ .sheet-section {
392
+ margin-bottom: 22px;
393
+ }
394
+ .sheet-section:last-child {
395
+ margin-bottom: 0;
396
+ }
397
+
398
+ .sheet-section-title {
399
+ font-size: 12px;
400
+ font-weight: 700;
401
+ text-transform: uppercase;
402
+ letter-spacing: 0.05em;
403
+ color: var(--text-light);
404
+ margin-bottom: 10px;
405
+ display: flex;
406
+ align-items: center;
407
+ gap: 6px;
408
+ }
409
+ .sheet-section-title.danger {
410
+ color: var(--destructive);
411
+ }
412
+
413
+ /* Status card */
414
+ .publish-status-card {
415
+ padding: 12px 14px;
416
+ border-radius: 8px;
417
+ background: var(--muted);
418
+ display: flex;
419
+ align-items: center;
420
+ gap: 10px;
421
+ margin-bottom: 14px;
422
+ }
423
+ .publish-status-icon {
424
+ width: 34px;
425
+ height: 34px;
426
+ border-radius: 8px;
427
+ display: flex;
428
+ align-items: center;
429
+ justify-content: center;
430
+ background: var(--lavender-lighter);
431
+ color: var(--primary);
432
+ }
433
+ .publish-status-info {
434
+ flex: 1;
435
+ }
436
+ .publish-status-label {
437
+ font-size: 14px;
438
+ font-weight: 700;
439
+ color: var(--foreground);
440
+ }
441
+ .publish-status-meta {
442
+ font-size: 12px;
443
+ color: var(--text-light);
444
+ }
445
+ .publish-detail-row {
446
+ display: flex;
447
+ align-items: center;
448
+ justify-content: space-between;
449
+ padding: 6px 0;
450
+ font-size: 12px;
451
+ color: var(--muted-foreground);
452
+ }
453
+ .publish-detail-row span:last-child {
454
+ font-weight: 500;
455
+ }
456
+
457
+ /* Schedule */
458
+ .schedule-row {
459
+ display: grid;
460
+ grid-template-columns: 1fr 1fr;
461
+ gap: 8px;
462
+ margin-bottom: 10px;
463
+ }
464
+ .schedule-input {
465
+ padding: 7px 10px;
466
+ font-family: inherit;
467
+ font-size: 13px;
468
+ border: 1px solid var(--border);
469
+ border-radius: 6px;
470
+ color: var(--foreground);
471
+ outline: none;
472
+ background: var(--card);
473
+ transition: border-color 0.2s ease;
474
+ }
475
+ .schedule-input:focus {
476
+ border-color: var(--primary);
477
+ }
478
+ .btn-schedule {
479
+ width: 100%;
480
+ padding: 8px;
481
+ font-family: inherit;
482
+ font-size: 13px;
483
+ font-weight: 600;
484
+ color: var(--primary);
485
+ background: var(--lavender-lighter);
486
+ border: 1px solid var(--lavender-light);
487
+ border-radius: 8px;
488
+ cursor: pointer;
489
+ transition: background 0.2s ease;
490
+ }
491
+ .btn-schedule:hover {
492
+ background: var(--lavender-light);
493
+ }
494
+ .btn-schedule:disabled {
495
+ opacity: 0.5;
496
+ cursor: not-allowed;
497
+ }
498
+
499
+ /* A11y checklist */
500
+ .a11y-checklist {
501
+ display: flex;
502
+ flex-direction: column;
503
+ gap: 6px;
504
+ }
505
+ .a11y-item {
506
+ display: flex;
507
+ align-items: flex-start;
508
+ gap: 8px;
509
+ padding: 8px 10px;
510
+ border-radius: 8px;
511
+ }
512
+ .a11y-item.warning {
513
+ background: var(--warning-bg);
514
+ }
515
+ .a11y-item.success {
516
+ background: var(--success-bg);
517
+ }
518
+ .a11y-item-icon {
519
+ width: 18px;
520
+ height: 18px;
521
+ display: flex;
522
+ align-items: center;
523
+ justify-content: center;
524
+ flex-shrink: 0;
525
+ margin-top: 1px;
526
+ }
527
+ :global(.a11y-item.warning .a11y-item-icon) {
528
+ color: var(--warning);
529
+ }
530
+ :global(.a11y-item.success .a11y-item-icon) {
531
+ color: var(--success);
532
+ }
533
+ .a11y-item-text {
534
+ font-size: 13px;
535
+ font-weight: 500;
536
+ }
537
+ .a11y-item.warning .a11y-item-text {
538
+ color: #7a5520;
539
+ }
540
+ .a11y-item.success .a11y-item-text {
541
+ color: #2a6844;
542
+ }
543
+ .a11y-item-clickable {
544
+ cursor: pointer;
545
+ border: none;
546
+ width: 100%;
547
+ text-align: left;
548
+ font-family: inherit;
549
+ transition: opacity 0.15s;
550
+ }
551
+ .a11y-item-clickable:hover {
552
+ opacity: 0.8;
553
+ }
554
+ .a11y-hint {
555
+ font-size: 12px;
556
+ color: var(--text-light);
557
+ font-style: italic;
558
+ margin-top: 4px;
559
+ }
560
+
561
+ /* Danger zone */
562
+ .danger-zone {
563
+ padding-top: 14px;
564
+ border-top: 1px solid var(--border);
565
+ display: flex;
566
+ flex-direction: column;
567
+ gap: 8px;
568
+ }
569
+ .btn-danger-outline {
570
+ width: 100%;
571
+ padding: 8px;
572
+ font-family: inherit;
573
+ font-size: 13px;
574
+ font-weight: 600;
575
+ color: var(--destructive);
576
+ background: transparent;
577
+ border: 1px solid var(--destructive);
578
+ border-radius: 8px;
579
+ cursor: pointer;
580
+ opacity: 0.7;
581
+ transition: all 0.2s ease;
582
+ }
583
+ .btn-danger-outline:hover {
584
+ background: var(--error-bg);
585
+ opacity: 1;
586
+ }
587
+ .btn-danger-outline.archive {
588
+ color: var(--muted-foreground);
589
+ border-color: var(--border);
590
+ }
591
+ .btn-danger-outline.archive:hover {
592
+ color: var(--foreground);
593
+ background: var(--muted);
594
+ }
595
+ </style>
@@ -1,10 +1,14 @@
1
1
  import type { DbEntryVersion, RawEntry } from '../../../../types/entries.js';
2
2
  import type { UpdateEntryVersionCommandType } from '../../../../core/server/entries/operations/update.js';
3
+ import type { Field } from '../../../../types/fields.js';
3
4
  type Props = {
4
5
  entry: RawEntry;
5
6
  version: DbEntryVersion;
7
+ fields?: Field[];
8
+ getFormData?: () => Record<string, unknown>;
6
9
  onSave: (type: UpdateEntryVersionCommandType, scheduledAt?: Date) => void;
7
10
  onArchive: () => void;
11
+ onScrollToIssue?: (fieldSlug: string, nodePos: number) => void;
8
12
  };
9
13
  declare const PublishPanel: import("svelte").Component<Props, {}, "">;
10
14
  type PublishPanel = ReturnType<typeof PublishPanel>;