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
@@ -8,46 +8,44 @@
8
8
  import Button from '../../../../components/ui/button/button.svelte';
9
9
  import HistoryIcon from '@tabler/icons-svelte/icons/history';
10
10
  import SquareCheckFilled from '@tabler/icons-svelte/icons/square-check-filled';
11
+ import ClockFilled from '@tabler/icons-svelte/icons/clock-filled';
11
12
  import { getEntryStatus } from '../utils.js';
12
13
 
13
14
  const lang: Record<
14
15
  InterfaceLanguage,
15
16
  {
16
17
  history: string;
17
- today: string;
18
- yesterday: string;
19
- version: string;
18
+ description: string;
20
19
  published: string;
21
20
  scheduled: string;
22
- draft: string;
21
+ currentDraft: string;
22
+ previous: string;
23
23
  changedFields: string;
24
- noChanges: string;
25
- versionsCount: string;
24
+ triggerLabel: string;
25
+ editing: string;
26
26
  }
27
27
  > = {
28
28
  en: {
29
29
  history: 'Version History',
30
- today: 'Today',
31
- yesterday: 'Yesterday',
32
- version: 'Version',
30
+ description: 'Browse and restore previous versions of this entry',
33
31
  published: 'Published',
34
32
  scheduled: 'Scheduled',
35
- draft: 'Draft',
33
+ currentDraft: 'Current draft',
34
+ previous: 'Previous',
36
35
  changedFields: 'Changed fields',
37
- noChanges: 'No changes',
38
- versionsCount: 'versions'
36
+ triggerLabel: 'History',
37
+ editing: 'Editing'
39
38
  },
40
39
  pl: {
41
40
  history: 'Historia wersji',
42
- today: 'Dzisiaj',
43
- yesterday: 'Wczoraj',
44
- version: 'Wersja',
41
+ description: 'Przeglądaj i przywracaj wcześniejsze wersje tego wpisu',
45
42
  published: 'Opublikowana',
46
43
  scheduled: 'Zaplanowana',
47
- draft: 'Szkic',
44
+ currentDraft: 'Aktualny szkic',
45
+ previous: 'Poprzednie',
48
46
  changedFields: 'Zmienione pola',
49
- noChanges: 'Brak zmian',
50
- versionsCount: 'wersji'
47
+ triggerLabel: 'Historia',
48
+ editing: 'Edytujesz'
51
49
  }
52
50
  };
53
51
 
@@ -64,41 +62,10 @@
64
62
 
65
63
  const entryStatus = $derived(getEntryStatus(entry));
66
64
 
67
- function formatRelativeTime(date: Date): string {
68
- const now = new Date();
69
- const diff = now.getTime() - date.getTime();
70
- const seconds = Math.floor(diff / 1000);
71
- const minutes = Math.floor(seconds / 60);
72
- const hours = Math.floor(minutes / 60);
73
-
74
- if (interfaceLanguage.current === 'pl') {
75
- if (hours > 0) return `${hours} godz. temu`;
76
- if (minutes > 0) return `${minutes} min temu`;
77
- return 'przed chwilą';
78
- }
79
-
80
- if (hours > 0) return `${hours}h ago`;
81
- if (minutes > 0) return `${minutes}m ago`;
82
- return 'just now';
83
- }
84
-
85
- function getDateKey(date: Date): string {
86
- const now = new Date();
87
- const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
88
- const yesterday = new Date(today);
89
- yesterday.setDate(yesterday.getDate() - 1);
90
- const dateDay = new Date(date.getFullYear(), date.getMonth(), date.getDate());
91
-
92
- if (dateDay.getTime() === today.getTime()) {
93
- return lang[interfaceLanguage.current].today;
94
- }
95
- if (dateDay.getTime() === yesterday.getTime()) {
96
- return lang[interfaceLanguage.current].yesterday;
97
- }
98
- return date.toLocaleDateString(interfaceLanguage.current, {
99
- day: 'numeric',
100
- month: 'long',
101
- year: date.getFullYear() !== now.getFullYear() ? 'numeric' : undefined
65
+ function formatTime(date: Date): string {
66
+ return date.toLocaleTimeString(interfaceLanguage.current, {
67
+ hour: '2-digit',
68
+ minute: '2-digit'
102
69
  });
103
70
  }
104
71
 
@@ -119,15 +86,62 @@
119
86
  return changed;
120
87
  }
121
88
 
89
+ function getDotClass(version: DbEntryVersion): string {
90
+ const isPublished = entry.publishedVersionId === version.id && entryStatus === 'published';
91
+ const isScheduled = entry.publishedVersionId === version.id && entryStatus === 'scheduled';
92
+ const isCurrent = version.id === currentVersionId;
93
+
94
+ if (isPublished) return 'dot-published';
95
+ if (isScheduled) return 'dot-scheduled';
96
+ if (isCurrent) return 'dot-current';
97
+ return 'dot-default';
98
+ }
99
+
122
100
  const sortedVersions = $derived(
123
101
  [...entry.versions].sort((a, b) => b.versionNumber - a.versionNumber)
124
102
  );
125
103
 
126
- const groupedVersions = $derived.by(() => {
104
+ // Filter: keep current, published, scheduled, and versions with actual changes
105
+ const meaningfulVersions = $derived.by(() => {
106
+ return sortedVersions.filter((version, idx) => {
107
+ // Always keep current version
108
+ if (version.id === currentVersionId) return true;
109
+ // Always keep published/scheduled
110
+ if (entry.publishedVersionId === version.id) return true;
111
+ // Keep versions with actual data changes vs previous
112
+ const prevVersion = sortedVersions[idx + 1];
113
+ if (!prevVersion) return true; // first version
114
+ return JSON.stringify(version.data) !== JSON.stringify(prevVersion.data);
115
+ });
116
+ });
117
+
118
+ // Pinned: currently editing version
119
+ const currentVersion = $derived(
120
+ meaningfulVersions.find((v) => v.id === currentVersionId)
121
+ );
122
+
123
+ // Timeline versions: everything except the currently editing one
124
+ const timelineVersions = $derived(
125
+ meaningfulVersions.filter((v) => v.id !== currentVersionId)
126
+ );
127
+
128
+ // Semantic groups for timeline (Published / Previous only)
129
+ const semanticGroups = $derived.by(() => {
127
130
  const groups: Map<string, DbEntryVersion[]> = new Map();
128
131
 
129
- for (const version of sortedVersions) {
130
- const key = getDateKey(version.createdAt);
132
+ for (const version of timelineVersions) {
133
+ const isPublished = entry.publishedVersionId === version.id && entryStatus === 'published';
134
+ const isScheduled = entry.publishedVersionId === version.id && entryStatus === 'scheduled';
135
+
136
+ let key: string;
137
+ if (isPublished) {
138
+ key = t.published;
139
+ } else if (isScheduled) {
140
+ key = t.scheduled;
141
+ } else {
142
+ key = t.previous;
143
+ }
144
+
131
145
  if (!groups.has(key)) {
132
146
  groups.set(key, []);
133
147
  }
@@ -141,37 +155,78 @@
141
155
  goto(`/admin/entries/${entry.id}?version=${versionId}`);
142
156
  open = false;
143
157
  }
158
+
159
+ const t = $derived(lang[interfaceLanguage.current]);
144
160
  </script>
145
161
 
146
162
  <Sheet.Root bind:open>
147
163
  <Sheet.Trigger>
148
164
  {#snippet child({ props })}
149
- <Button variant="outline" size="icon" {...props}>
165
+ <Button variant="ghost" size="icon-sm" {...props}>
150
166
  <HistoryIcon class="size-4" />
151
- <span class="sr-only">{lang[interfaceLanguage.current].history}</span>
152
167
  </Button>
153
168
  {/snippet}
154
169
  </Sheet.Trigger>
155
- <Sheet.Content side="right" class="w-[400px] sm:max-w-[400px]">
170
+ <Sheet.Content side="right" class="version-history-sheet w-[380px] sm:max-w-[380px]">
156
171
  <Sheet.Header>
157
- <Sheet.Title>{lang[interfaceLanguage.current].history}</Sheet.Title>
158
- <Sheet.Description>
159
- {sortedVersions.length} {lang[interfaceLanguage.current].versionsCount}
160
- </Sheet.Description>
172
+ <Sheet.Title class="flex items-center gap-2">
173
+ {t.history}
174
+ <Badge variant="secondary" class="tabular-nums">{meaningfulVersions.length}</Badge>
175
+ </Sheet.Title>
176
+ <Sheet.Description class="sr-only">{t.description}</Sheet.Description>
161
177
  </Sheet.Header>
162
178
 
163
- <div class="mt-6 -mx-6 px-6 overflow-y-auto max-h-[calc(100vh-160px)]">
164
- {#each groupedVersions as [dateKey, versions]}
165
- <div class="mb-6">
166
- <h3 class="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-3">
167
- {dateKey}
168
- </h3>
179
+ <div class="vh-body">
180
+ <!-- Pinned: currently editing -->
181
+ {#if currentVersion}
182
+ <div class="vh-pinned">
183
+ <div class="vh-pinned-inner">
184
+ <div class="vh-item-header">
185
+ <div class="vh-item-left">
186
+ <span class="vh-time">{formatTime(currentVersion.createdAt)}</span>
187
+ <Badge class="vh-badge-editing">{t.editing}</Badge>
188
+ {#if entry.publishedVersionId === currentVersion.id && entryStatus === 'published'}
189
+ <Badge class="vh-badge-published">
190
+ <SquareCheckFilled class="size-2.5 mr-0.5" />
191
+ {t.published}
192
+ </Badge>
193
+ {:else if entry.publishedVersionId === currentVersion.id && entryStatus === 'scheduled'}
194
+ <Badge class="vh-badge-scheduled">
195
+ {t.scheduled}
196
+ </Badge>
197
+ {/if}
198
+ </div>
199
+ <span class="vh-date">
200
+ {currentVersion.createdAt.toLocaleDateString(interfaceLanguage.current, {
201
+ day: 'numeric',
202
+ month: 'short'
203
+ })}
204
+ </span>
205
+ </div>
206
+ </div>
207
+ </div>
208
+ {/if}
209
+
210
+ {#each semanticGroups as [groupLabel, versions]}
211
+ <div class="vh-group" class:vh-group-previous={groupLabel === t.previous}>
212
+ <div class="sheet-section-title">
213
+ {#if groupLabel === t.published}
214
+ <SquareCheckFilled class="size-3.5" />
215
+ {:else if groupLabel === t.scheduled}
216
+ <ClockFilled class="size-3.5" />
217
+ {:else}
218
+ <HistoryIcon class="size-3.5" />
219
+ {/if}
220
+ {groupLabel}
221
+ </div>
222
+
223
+ <!-- Timeline -->
224
+ <div class="vh-timeline" class:vh-timeline-published={groupLabel === t.published}>
225
+ <div class="vh-timeline-line"></div>
169
226
 
170
- <div class="space-y-2">
171
- {#each versions as version, idx}
227
+ {#each versions as version}
172
228
  {@const isPublished = entry.publishedVersionId === version.id && entryStatus === 'published'}
173
229
  {@const isScheduled = entry.publishedVersionId === version.id && entryStatus === 'scheduled'}
174
- {@const isCurrent = version.id === currentVersionId}
175
230
  {@const prevVersion = sortedVersions.find(
176
231
  (v) => v.versionNumber === version.versionNumber - 1
177
232
  )}
@@ -180,44 +235,40 @@
180
235
  <button
181
236
  type="button"
182
237
  onclick={() => selectVersion(version.id)}
183
- class="w-full text-left p-3 rounded-lg border transition-colors
184
- {isCurrent
185
- ? 'border-primary/50 bg-primary/5'
186
- : 'border-transparent hover:bg-muted/50'}"
238
+ class="vh-item"
187
239
  >
188
- <div class="flex items-center justify-between mb-1">
189
- <div class="flex items-center gap-2">
190
- <span class="font-medium">v{version.versionNumber}</span>
240
+ <div class="vh-dot {getDotClass(version)}"></div>
241
+
242
+ <div class="vh-item-header">
243
+ <div class="vh-item-left">
244
+ <span class="vh-time">{formatTime(version.createdAt)}</span>
191
245
  {#if isPublished}
192
- <Badge
193
- class="bg-emerald-500/90 text-white border-emerald-600/20 text-[10px] px-1.5 py-0"
194
- >
246
+ <Badge class="vh-badge-published">
195
247
  <SquareCheckFilled class="size-2.5 mr-0.5" />
196
- {lang[interfaceLanguage.current].published}
248
+ {t.published}
197
249
  </Badge>
198
250
  {:else if isScheduled}
199
- <Badge
200
- class="bg-amber-500/90 text-white border-amber-600/20 text-[10px] px-1.5 py-0"
201
- >
202
- {lang[interfaceLanguage.current].scheduled}
251
+ <Badge class="vh-badge-scheduled">
252
+ {t.scheduled}
203
253
  </Badge>
204
254
  {/if}
205
255
  </div>
206
- <span class="text-xs text-muted-foreground">
207
- {formatRelativeTime(version.createdAt)}
256
+ <span class="vh-date">
257
+ {version.createdAt.toLocaleDateString(interfaceLanguage.current, {
258
+ day: 'numeric',
259
+ month: 'short'
260
+ })}
208
261
  </span>
209
262
  </div>
210
263
 
211
264
  {#if changedFields.length > 0}
212
- <div class="text-xs text-muted-foreground">
213
- <span class="text-muted-foreground/70"
214
- >{lang[interfaceLanguage.current].changedFields}:</span
215
- >
216
- {changedFields.slice(0, 3).join(', ')}{changedFields.length > 3 ? '...' : ''}
217
- </div>
218
- {:else if idx < versions.length - 1 || prevVersion}
219
- <div class="text-xs text-muted-foreground/50">
220
- {lang[interfaceLanguage.current].noChanges}
265
+ <div class="vh-changed-fields">
266
+ {#each changedFields.slice(0, 4) as field}
267
+ <span class="vh-field-badge">{field}</span>
268
+ {/each}
269
+ {#if changedFields.length > 4}
270
+ <span class="vh-field-badge">+{changedFields.length - 4}</span>
271
+ {/if}
221
272
  </div>
222
273
  {/if}
223
274
  </button>
@@ -228,3 +279,168 @@
228
279
  </div>
229
280
  </Sheet.Content>
230
281
  </Sheet.Root>
282
+
283
+ <style>
284
+ .vh-body {
285
+ padding: 18px 20px;
286
+ overflow-y: auto;
287
+ max-height: calc(100vh - 80px);
288
+ }
289
+
290
+ /* Pinned: currently editing */
291
+ .vh-pinned {
292
+ margin-bottom: 16px;
293
+ padding: 0 0 16px;
294
+ border-bottom: 1px solid var(--border);
295
+ }
296
+ .vh-pinned-inner {
297
+ background: color-mix(in oklch, var(--primary) 5%, transparent);
298
+ border-left: 2px solid var(--primary);
299
+ border-radius: 8px;
300
+ padding: 10px 12px;
301
+ }
302
+
303
+ .vh-group {
304
+ margin-bottom: 16px;
305
+ }
306
+ .vh-group:last-child {
307
+ margin-bottom: 0;
308
+ }
309
+ .vh-group-previous {
310
+ opacity: 0.7;
311
+ }
312
+
313
+ .sheet-section-title {
314
+ font-size: 12px;
315
+ font-weight: 700;
316
+ text-transform: uppercase;
317
+ letter-spacing: 0.05em;
318
+ color: var(--text-light);
319
+ margin-bottom: 10px;
320
+ display: flex;
321
+ align-items: center;
322
+ gap: 6px;
323
+ }
324
+
325
+ /* Timeline */
326
+ .vh-timeline {
327
+ position: relative;
328
+ margin-left: 12px;
329
+ }
330
+ .vh-timeline-line {
331
+ position: absolute;
332
+ left: 0;
333
+ top: 0;
334
+ bottom: 0;
335
+ width: 1px;
336
+ background: var(--border);
337
+ }
338
+ .vh-timeline-published .vh-timeline-line {
339
+ background: var(--success);
340
+ }
341
+
342
+ .vh-item {
343
+ position: relative;
344
+ width: 100%;
345
+ text-align: left;
346
+ padding: 8px 8px 8px 20px;
347
+ border-radius: 8px;
348
+ border: none;
349
+ background: transparent;
350
+ cursor: pointer;
351
+ font-family: inherit;
352
+ transition: background 0.2s ease;
353
+ }
354
+ .vh-item:hover {
355
+ background: var(--muted);
356
+ }
357
+
358
+ /* Dot */
359
+ .vh-dot {
360
+ position: absolute;
361
+ left: -3.5px;
362
+ top: 14px;
363
+ width: 7px;
364
+ height: 7px;
365
+ border-radius: 50%;
366
+ box-shadow: 0 0 0 2px var(--card);
367
+ }
368
+ .dot-published {
369
+ background: var(--success);
370
+ }
371
+ .dot-scheduled {
372
+ background: var(--warning);
373
+ }
374
+ .dot-current {
375
+ background: var(--primary);
376
+ }
377
+ .dot-default {
378
+ background: var(--border);
379
+ }
380
+
381
+ .vh-item-header {
382
+ display: flex;
383
+ align-items: center;
384
+ justify-content: space-between;
385
+ margin-bottom: 2px;
386
+ }
387
+ .vh-item-left {
388
+ display: flex;
389
+ align-items: center;
390
+ gap: 6px;
391
+ }
392
+ .vh-time {
393
+ font-size: 13px;
394
+ font-weight: 600;
395
+ color: var(--foreground);
396
+ font-variant-numeric: tabular-nums;
397
+ }
398
+ .vh-date {
399
+ font-size: 12px;
400
+ color: var(--muted-foreground);
401
+ font-variant-numeric: tabular-nums;
402
+ }
403
+
404
+ /* Badges */
405
+ :global(.vh-badge-editing) {
406
+ background: color-mix(in oklch, var(--primary) 12%, transparent) !important;
407
+ color: var(--primary) !important;
408
+ border-color: var(--primary) !important;
409
+ font-size: 10px !important;
410
+ padding: 0 6px !important;
411
+ height: 18px !important;
412
+ }
413
+ :global(.vh-badge-published) {
414
+ background: var(--success-bg) !important;
415
+ color: var(--success) !important;
416
+ border-color: var(--success) !important;
417
+ font-size: 10px !important;
418
+ padding: 0 6px !important;
419
+ height: 18px !important;
420
+ }
421
+ :global(.vh-badge-scheduled) {
422
+ background: var(--warning-bg) !important;
423
+ color: var(--warning) !important;
424
+ border-color: var(--warning) !important;
425
+ font-size: 10px !important;
426
+ padding: 0 6px !important;
427
+ height: 18px !important;
428
+ }
429
+
430
+ /* Changed fields */
431
+ .vh-changed-fields {
432
+ display: flex;
433
+ flex-wrap: wrap;
434
+ gap: 4px;
435
+ margin-top: 4px;
436
+ }
437
+ .vh-field-badge {
438
+ display: inline-block;
439
+ padding: 1px 6px;
440
+ background: var(--muted);
441
+ border-radius: 4px;
442
+ font-size: 10px;
443
+ font-weight: 500;
444
+ color: var(--muted-foreground);
445
+ }
446
+ </style>