includio-cms 0.25.0 → 0.26.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 (349) hide show
  1. package/API.md +57 -4
  2. package/CHANGELOG.md +53 -0
  3. package/DOCS.md +1 -1
  4. package/README.md +2 -0
  5. package/ROADMAP.md +6 -0
  6. package/dist/admin/client/account/lang.d.ts +1 -0
  7. package/dist/admin/client/account/lang.js +4 -2
  8. package/dist/admin/client/account/profile-section.svelte +2 -2
  9. package/dist/admin/client/account/security-section.svelte +27 -4
  10. package/dist/admin/client/account/sessions-section.svelte +1 -1
  11. package/dist/admin/client/admin/admin-after-login-layout-content.svelte +1 -1
  12. package/dist/admin/client/admin/dashboard-page.svelte +34 -10
  13. package/dist/admin/client/collection/bulk-actions-bar.svelte +86 -44
  14. package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +3 -1
  15. package/dist/admin/client/collection/collection-entries.svelte +52 -36
  16. package/dist/admin/client/collection/collection-entries.svelte.d.ts +3 -0
  17. package/dist/admin/client/collection/collection.svelte +28 -14
  18. package/dist/admin/client/collection/collection.svelte.d.ts +3 -0
  19. package/dist/admin/client/collection/data-table.svelte +279 -130
  20. package/dist/admin/client/collection/data-table.svelte.d.ts +11 -0
  21. package/dist/admin/client/collection/date-cell.svelte +4 -4
  22. package/dist/admin/client/collection/row-actions.svelte +2 -1
  23. package/dist/admin/client/collection/sortable-header.svelte +33 -9
  24. package/dist/admin/client/collection/state-display.svelte +102 -0
  25. package/dist/admin/client/collection/state-display.svelte.d.ts +12 -0
  26. package/dist/admin/client/collection/status-badge.svelte +99 -11
  27. package/dist/admin/client/collection/status-badge.svelte.d.ts +15 -1
  28. package/dist/admin/client/collection/table-pagination.svelte +21 -6
  29. package/dist/admin/client/collection/table-toolbar.svelte +105 -80
  30. package/dist/admin/client/collection/table-toolbar.svelte.d.ts +11 -8
  31. package/dist/admin/client/entry/entry-form.svelte +36 -11
  32. package/dist/admin/client/entry/entry-form.svelte.d.ts +1 -0
  33. package/dist/admin/client/entry/entry-header.svelte +22 -15
  34. package/dist/admin/client/entry/entry-header.svelte.d.ts +1 -0
  35. package/dist/admin/client/entry/entry.svelte +269 -165
  36. package/dist/admin/client/entry/header/a11y-header-badge.svelte +47 -0
  37. package/dist/admin/client/entry/header/a11y-header-badge.svelte.d.ts +8 -0
  38. package/dist/admin/client/entry/header/publish-panel.svelte +69 -13
  39. package/dist/admin/client/entry/header/save-indicator.svelte +57 -28
  40. package/dist/admin/client/entry/header/save-indicator.svelte.d.ts +1 -0
  41. package/dist/admin/client/entry/header/status-badge.svelte +60 -15
  42. package/dist/admin/client/entry/header/status-badge.svelte.d.ts +1 -2
  43. package/dist/admin/client/entry/header/version-history-sheet.svelte +1 -1
  44. package/dist/admin/client/entry/hybrid/hybrid-layout.svelte +74 -23
  45. package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +1 -1
  46. package/dist/admin/client/entry/utils.d.ts +14 -0
  47. package/dist/admin/client/entry/utils.js +28 -0
  48. package/dist/admin/client/form/form-submission/form-submission.svelte +2 -2
  49. package/dist/admin/client/form/form-submissions.svelte +143 -194
  50. package/dist/admin/client/form/form-submissions.svelte.d.ts +2 -0
  51. package/dist/admin/client/login/lang.d.ts +3 -0
  52. package/dist/admin/client/login/lang.js +10 -4
  53. package/dist/admin/client/login/login-form.svelte +8 -1
  54. package/dist/admin/client/login/reset-password-page.svelte +24 -3
  55. package/dist/admin/client/login/schema.d.ts +14 -2
  56. package/dist/admin/client/login/schema.js +19 -8
  57. package/dist/admin/client/maintenance/maintenance-page.svelte +16 -17
  58. package/dist/admin/client/media/media-page.svelte +1 -1
  59. package/dist/admin/client/shop/coupon-edit-page.svelte +117 -13
  60. package/dist/admin/client/shop/coupon-form.svelte +282 -138
  61. package/dist/admin/client/shop/coupon-form.svelte.d.ts +1 -9
  62. package/dist/admin/client/shop/coupon-new-page.svelte +40 -10
  63. package/dist/admin/client/shop/coupon-new-page.svelte.d.ts +2 -17
  64. package/dist/admin/client/shop/coupon-schema.d.ts +28 -0
  65. package/dist/admin/client/shop/coupon-schema.js +53 -0
  66. package/dist/admin/client/shop/coupons-list-page.svelte +262 -118
  67. package/dist/admin/client/shop/coupons-list-page.svelte.d.ts +16 -1
  68. package/dist/admin/client/shop/shipping-method-edit-page.svelte +108 -59
  69. package/dist/admin/client/shop/shipping-method-form.svelte +36 -9
  70. package/dist/admin/client/shop/shipping-method-new-page.svelte +44 -13
  71. package/dist/admin/client/shop/shipping-methods-list-page.svelte +101 -59
  72. package/dist/admin/client/shop/shop-order-detail-page.svelte +113 -84
  73. package/dist/admin/client/shop/shop-orders-list-page.svelte +302 -152
  74. package/dist/admin/client/shop/shop-orders-list-page.svelte.d.ts +18 -1
  75. package/dist/admin/client/shop/shop-products-list-page.svelte +355 -118
  76. package/dist/admin/client/shop/shop-products-list-page.svelte.d.ts +19 -1
  77. package/dist/admin/client/users/accept-invite-page.svelte +24 -3
  78. package/dist/admin/client/users/create-user-dialog.svelte +3 -8
  79. package/dist/admin/client/users/lang.d.ts +2 -0
  80. package/dist/admin/client/users/lang.js +4 -0
  81. package/dist/admin/client/users/pending-invitations.svelte +2 -9
  82. package/dist/admin/client/users/user-name-cell.svelte +20 -0
  83. package/dist/admin/client/users/user-name-cell.svelte.d.ts +9 -0
  84. package/dist/admin/client/users/user-role-badge.svelte +16 -0
  85. package/dist/admin/client/users/user-role-badge.svelte.d.ts +7 -0
  86. package/dist/admin/client/users/user-row-actions.svelte +72 -0
  87. package/dist/admin/client/users/user-row-actions.svelte.d.ts +20 -0
  88. package/dist/admin/client/users/user-sessions-sheet.svelte +2 -11
  89. package/dist/admin/client/users/users-page.svelte +283 -497
  90. package/dist/admin/client/users/users-page.svelte.d.ts +12 -1
  91. package/dist/admin/components/dashboard/form-submissions-widget.svelte +59 -74
  92. package/dist/admin/components/dashboard/recent-activity.svelte +17 -5
  93. package/dist/admin/components/dashboard/recent-entries.svelte +19 -7
  94. package/dist/admin/components/dialogs/confirmation-dialog.svelte +105 -0
  95. package/dist/admin/components/dialogs/confirmation-dialog.svelte.d.ts +13 -0
  96. package/dist/admin/components/fields/block-picker-modal.svelte +6 -0
  97. package/dist/admin/components/fields/blocks-field.svelte +46 -1
  98. package/dist/admin/components/fields/boolean-field.svelte +1 -1
  99. package/dist/admin/components/fields/field-renderer.svelte +23 -21
  100. package/dist/admin/components/fields/file-field.svelte +344 -30
  101. package/dist/admin/components/fields/media-field.svelte +16 -2
  102. package/dist/admin/components/fields/radio-field.svelte +22 -0
  103. package/dist/admin/components/fields/relation-field.svelte +123 -97
  104. package/dist/admin/components/fields/relation-picker-dialog.svelte +2 -2
  105. package/dist/admin/components/fields/seo-field.svelte +60 -30
  106. package/dist/admin/components/fields/shop-field.svelte +9 -4
  107. package/dist/admin/components/fields/simple-array-field.svelte +321 -151
  108. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +3 -0
  109. package/dist/admin/components/fields/slug-field.svelte +146 -21
  110. package/dist/admin/components/fields/text-field-wrapper.svelte +37 -20
  111. package/dist/admin/components/fields/text-field.svelte +7 -2
  112. package/dist/admin/components/fields/url-field-wrapper.svelte +10 -0
  113. package/dist/admin/components/fields/url-field.svelte +36 -23
  114. package/dist/admin/components/forms/form-error-summary.svelte +143 -0
  115. package/dist/admin/components/forms/form-error-summary.svelte.d.ts +27 -0
  116. package/dist/admin/components/layout/app-sidebar.svelte +7 -2
  117. package/dist/admin/components/layout/detail-page-shell.svelte +71 -0
  118. package/dist/admin/components/layout/detail-page-shell.svelte.d.ts +24 -0
  119. package/dist/admin/components/layout/lang.d.ts +5 -0
  120. package/dist/admin/components/layout/lang.js +10 -0
  121. package/dist/admin/components/layout/layout-renderer.svelte +71 -2
  122. package/dist/admin/components/layout/layout-renderer.svelte.d.ts +1 -0
  123. package/dist/admin/components/layout/layout-tabs.svelte +172 -0
  124. package/dist/admin/components/layout/layout-tabs.svelte.d.ts +24 -0
  125. package/dist/admin/components/layout/nav-breadcrumbs.svelte +25 -7
  126. package/dist/admin/components/layout/nav-collections.svelte +23 -36
  127. package/dist/admin/components/layout/nav-forms.svelte +19 -35
  128. package/dist/admin/components/layout/nav-main.svelte +3 -28
  129. package/dist/admin/components/layout/nav-search.svelte +70 -2
  130. package/dist/admin/components/layout/nav-section.svelte +77 -0
  131. package/dist/admin/components/layout/nav-section.svelte.d.ts +22 -0
  132. package/dist/admin/components/layout/nav-shop.svelte +3 -27
  133. package/dist/admin/components/layout/nav-singletons.svelte +16 -28
  134. package/dist/admin/components/layout/page-header.stories.svelte +93 -0
  135. package/dist/admin/components/layout/page-header.stories.svelte.d.ts +27 -0
  136. package/dist/admin/components/layout/page-header.svelte +68 -0
  137. package/dist/admin/components/layout/page-header.svelte.d.ts +17 -0
  138. package/dist/admin/components/layout/site-header.svelte +9 -0
  139. package/dist/admin/components/layout/site-header.svelte.d.ts +2 -17
  140. package/dist/admin/components/media/file/file-name-input.svelte +6 -2
  141. package/dist/admin/components/media/file/file-preview.svelte +130 -17
  142. package/dist/admin/components/media/file-upload.svelte +16 -7
  143. package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
  144. package/dist/admin/components/media/files-list.svelte +153 -53
  145. package/dist/admin/components/media/files-list.svelte.d.ts +1 -0
  146. package/dist/admin/components/media/media-library.svelte +577 -198
  147. package/dist/admin/components/media/media-library.svelte.d.ts +4 -0
  148. package/dist/admin/components/media/media-selector.svelte +4 -2
  149. package/dist/admin/components/media/media-selector.svelte.d.ts +1 -0
  150. package/dist/admin/components/media/tag-sidebar.svelte +4 -4
  151. package/dist/admin/components/tiptap/FigureNodeView.svelte +10 -0
  152. package/dist/admin/components/tiptap/bubble-menu.svelte +104 -0
  153. package/dist/admin/components/tiptap/bubble-menu.svelte.d.ts +19 -0
  154. package/dist/admin/components/tiptap/content-editor.svelte +28 -24
  155. package/dist/admin/components/tiptap/editor-toolbar.svelte +7 -7
  156. package/dist/admin/components/tiptap/extensions.js +5 -1
  157. package/dist/admin/components/tiptap/image-dialog.svelte +5 -1
  158. package/dist/admin/components/tiptap/link-dialog.svelte +2 -0
  159. package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -20
  160. package/dist/admin/components/tiptap/video-dialog.svelte +1 -1
  161. package/dist/admin/i18n/errors.d.ts +140 -0
  162. package/dist/admin/i18n/errors.js +151 -0
  163. package/dist/admin/remote/entry.remote.d.ts +59 -4
  164. package/dist/admin/remote/entry.remote.js +239 -62
  165. package/dist/admin/remote/shop.remote.d.ts +37 -32
  166. package/dist/admin/remote/shop.remote.js +9 -2
  167. package/dist/admin/shared/password-generate.d.ts +6 -0
  168. package/dist/admin/shared/password-generate.js +40 -0
  169. package/dist/admin/shared/password-schema.d.ts +6 -0
  170. package/dist/admin/shared/password-schema.js +10 -3
  171. package/dist/admin/styles/admin.css +23 -6
  172. package/dist/admin/styles/tokens.md +244 -0
  173. package/dist/admin/utils/accordionActivation.d.ts +13 -0
  174. package/dist/admin/utils/accordionActivation.js +35 -0
  175. package/dist/admin/utils/entryLabel.d.ts +23 -0
  176. package/dist/admin/utils/entryLabel.js +51 -12
  177. package/dist/admin/utils/field-a11y.d.ts +29 -0
  178. package/dist/admin/utils/field-a11y.js +23 -0
  179. package/dist/admin/utils/fieldPathElement.d.ts +9 -0
  180. package/dist/admin/utils/fieldPathElement.js +18 -0
  181. package/dist/admin/utils/fileDisplay.d.ts +10 -0
  182. package/dist/admin/utils/fileDisplay.js +26 -0
  183. package/dist/admin/utils/flattenFormErrors.d.ts +19 -0
  184. package/dist/admin/utils/flattenFormErrors.js +102 -0
  185. package/dist/admin/utils/formatters.d.ts +12 -0
  186. package/dist/admin/utils/{formatDate.js → formatters.js} +23 -2
  187. package/dist/admin/utils/scrollWithin.d.ts +9 -0
  188. package/dist/admin/utils/scrollWithin.js +32 -0
  189. package/dist/admin/utils/tabActivation.d.ts +12 -0
  190. package/dist/admin/utils/tabActivation.js +24 -0
  191. package/dist/cms/runtime/schema.d.ts +1 -0
  192. package/dist/cms/runtime/schema.js +1 -0
  193. package/dist/cms/runtime/types.d.ts +80 -7
  194. package/dist/components/ui/accordion/accordion-content.svelte +17 -3
  195. package/dist/components/ui/accordion/accordion.stories.svelte +21 -1
  196. package/dist/components/ui/alert/alert.stories.svelte +14 -0
  197. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte +45 -0
  198. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte.d.ts +27 -0
  199. package/dist/components/ui/avatar/avatar.stories.svelte +27 -0
  200. package/dist/components/ui/badge/badge.stories.svelte +15 -0
  201. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +47 -0
  202. package/dist/components/ui/breadcrumb/breadcrumb.svelte +1 -1
  203. package/dist/components/ui/button/button.stories.svelte +53 -6
  204. package/dist/components/ui/button/button.svelte +39 -5
  205. package/dist/components/ui/button/button.svelte.d.ts +4 -0
  206. package/dist/components/ui/button-group/button-group.stories.svelte +44 -0
  207. package/dist/components/ui/button-group/button-group.stories.svelte.d.ts +27 -0
  208. package/dist/components/ui/calendar/calendar.stories.svelte +36 -0
  209. package/dist/components/ui/calendar/calendar.stories.svelte.d.ts +27 -0
  210. package/dist/components/ui/card/card.stories.svelte +7 -0
  211. package/dist/components/ui/carousel/carousel.stories.svelte +43 -0
  212. package/dist/components/ui/carousel/carousel.stories.svelte.d.ts +27 -0
  213. package/dist/components/ui/checkbox/checkbox.stories.svelte +67 -0
  214. package/dist/components/ui/checkbox/checkbox.stories.svelte.d.ts +27 -0
  215. package/dist/components/ui/checkbox/checkbox.svelte +3 -3
  216. package/dist/components/ui/command/command.stories.svelte +18 -0
  217. package/dist/components/ui/data-table/data-table.stories.svelte +61 -0
  218. package/dist/components/ui/data-table/data-table.stories.svelte.d.ts +18 -0
  219. package/dist/components/ui/dialog/dialog-content.svelte +5 -0
  220. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +2 -0
  221. package/dist/components/ui/dialog/dialog.stories.svelte +35 -0
  222. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte +74 -0
  223. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte.d.ts +27 -0
  224. package/dist/components/ui/field/field-context.svelte.d.ts +22 -0
  225. package/dist/components/ui/field/field-context.svelte.js +9 -0
  226. package/dist/components/ui/field/field-control.svelte +18 -0
  227. package/dist/components/ui/field/field-control.svelte.d.ts +8 -0
  228. package/dist/components/ui/field/field-description.svelte +12 -0
  229. package/dist/components/ui/field/field-error.svelte +14 -6
  230. package/dist/components/ui/field/field-label.svelte +10 -0
  231. package/dist/components/ui/field/field.stories.svelte +95 -9
  232. package/dist/components/ui/field/field.svelte +57 -0
  233. package/dist/components/ui/field/field.svelte.d.ts +2 -0
  234. package/dist/components/ui/field/index.d.ts +3 -1
  235. package/dist/components/ui/field/index.js +4 -2
  236. package/dist/components/ui/form/form-field-errors.svelte +1 -1
  237. package/dist/components/ui/form/form.stories.svelte +25 -0
  238. package/dist/components/ui/form/form.stories.svelte.d.ts +26 -0
  239. package/dist/components/ui/input/input.stories.svelte +26 -0
  240. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  241. package/dist/components/ui/input-group/input-group.stories.svelte +43 -0
  242. package/dist/components/ui/input-group/input-group.stories.svelte.d.ts +27 -0
  243. package/dist/components/ui/item/item.stories.svelte +61 -0
  244. package/dist/components/ui/item/item.stories.svelte.d.ts +27 -0
  245. package/dist/components/ui/label/label.stories.svelte +7 -0
  246. package/dist/components/ui/live-region/index.d.ts +1 -0
  247. package/dist/components/ui/live-region/index.js +1 -0
  248. package/dist/components/ui/live-region/live-region-demo.svelte +32 -0
  249. package/dist/components/ui/live-region/live-region-demo.svelte.d.ts +7 -0
  250. package/dist/components/ui/live-region/live-region.stories.svelte +23 -0
  251. package/dist/components/ui/live-region/live-region.stories.svelte.d.ts +26 -0
  252. package/dist/components/ui/live-region/live-region.svelte +12 -0
  253. package/dist/components/ui/live-region/live-region.svelte.d.ts +8 -0
  254. package/dist/components/ui/popover/popover.stories.svelte +34 -0
  255. package/dist/components/ui/radio-group/radio-group.stories.svelte +58 -0
  256. package/dist/components/ui/radio-group/radio-group.stories.svelte.d.ts +27 -0
  257. package/dist/components/ui/resizable/resizable.stories.svelte +56 -0
  258. package/dist/components/ui/resizable/resizable.stories.svelte.d.ts +27 -0
  259. package/dist/components/ui/select/select.stories.svelte +49 -0
  260. package/dist/components/ui/separator/separator.stories.svelte +18 -0
  261. package/dist/components/ui/sheet/sheet.stories.svelte +34 -0
  262. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  263. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +1 -0
  264. package/dist/components/ui/sidebar/sidebar-trigger.svelte +1 -1
  265. package/dist/components/ui/sidebar/sidebar.stories.svelte +72 -0
  266. package/dist/components/ui/sidebar/sidebar.stories.svelte.d.ts +27 -0
  267. package/dist/components/ui/skeleton/skeleton.stories.svelte +39 -0
  268. package/dist/components/ui/skeleton/skeleton.stories.svelte.d.ts +27 -0
  269. package/dist/components/ui/skeleton/skeleton.svelte +6 -0
  270. package/dist/components/ui/sonner/index.d.ts +1 -1
  271. package/dist/components/ui/sonner/index.js +1 -1
  272. package/dist/components/ui/sonner/sonner.stories.svelte +7 -0
  273. package/dist/components/ui/sonner/sonner.svelte +17 -1
  274. package/dist/components/ui/sonner/sonner.svelte.d.ts +6 -0
  275. package/dist/components/ui/spinner/spinner.stories.svelte +30 -0
  276. package/dist/components/ui/spinner/spinner.stories.svelte.d.ts +27 -0
  277. package/dist/components/ui/switch/switch.stories.svelte +56 -0
  278. package/dist/components/ui/switch/switch.stories.svelte.d.ts +27 -0
  279. package/dist/components/ui/table/table-cell.svelte +1 -1
  280. package/dist/components/ui/table/table-head.svelte +1 -1
  281. package/dist/components/ui/table/table.stories.svelte +68 -0
  282. package/dist/components/ui/table/table.stories.svelte.d.ts +27 -0
  283. package/dist/components/ui/table/table.svelte +1 -1
  284. package/dist/components/ui/tabs/tabs.stories.svelte +48 -0
  285. package/dist/components/ui/tabs/tabs.stories.svelte.d.ts +27 -0
  286. package/dist/components/ui/textarea/textarea.stories.svelte +21 -0
  287. package/dist/components/ui/toggle/toggle.stories.svelte +23 -0
  288. package/dist/components/ui/toggle-group/toggle-group.stories.svelte +43 -0
  289. package/dist/components/ui/tooltip/tooltip.stories.svelte +46 -6
  290. package/dist/core/fields/fieldSchemaToTs.d.ts +7 -0
  291. package/dist/core/fields/fieldSchemaToTs.js +234 -90
  292. package/dist/core/fields/layoutUtils.d.ts +4 -1
  293. package/dist/core/fields/layoutUtils.js +41 -4
  294. package/dist/core/fields/resolveSeo.d.ts +70 -0
  295. package/dist/core/fields/resolveSeo.js +88 -0
  296. package/dist/core/fields/seoFieldDescriptor.d.ts +43 -0
  297. package/dist/core/fields/seoFieldDescriptor.js +74 -0
  298. package/dist/core/fields/slugPath.d.ts +13 -0
  299. package/dist/core/fields/slugPath.js +32 -0
  300. package/dist/core/fields/urlUtils.d.ts +8 -0
  301. package/dist/core/fields/urlUtils.js +27 -0
  302. package/dist/core/index.d.ts +1 -0
  303. package/dist/core/index.js +1 -0
  304. package/dist/core/server/entries/operations/create.js +13 -0
  305. package/dist/core/server/entries/operations/get.d.ts +7 -0
  306. package/dist/core/server/entries/operations/get.js +10 -6
  307. package/dist/core/server/entries/operations/slugUniqueness.d.ts +37 -0
  308. package/dist/core/server/entries/operations/slugUniqueness.js +116 -0
  309. package/dist/core/server/entries/operations/update.d.ts +6 -1
  310. package/dist/core/server/entries/operations/update.js +24 -1
  311. package/dist/core/server/fields/slugResolver.d.ts +3 -13
  312. package/dist/core/server/fields/slugResolver.js +8 -37
  313. package/dist/core/server/generator/fields.js +10 -17
  314. package/dist/core/server/generator/formFields.js +2 -1
  315. package/dist/core/server/generator/generator.js +4 -4
  316. package/dist/core/server/generator/utils.d.ts +1 -0
  317. package/dist/core/server/generator/utils.js +4 -0
  318. package/dist/paraglide/messages/_index.d.ts +3 -36
  319. package/dist/paraglide/messages/_index.js +3 -71
  320. package/dist/paraglide/messages/hello_world.d.ts +5 -0
  321. package/dist/paraglide/messages/hello_world.js +33 -0
  322. package/dist/paraglide/messages/login_hello.d.ts +16 -0
  323. package/dist/paraglide/messages/login_hello.js +34 -0
  324. package/dist/paraglide/messages/login_please_login.d.ts +16 -0
  325. package/dist/paraglide/messages/login_please_login.js +34 -0
  326. package/dist/shop/server/orders.d.ts +1 -0
  327. package/dist/shop/server/orders.js +14 -0
  328. package/dist/shop/server/shop-data.d.ts +2 -0
  329. package/dist/shop/server/shop-data.js +20 -5
  330. package/dist/sveltekit/server/handle.js +17 -0
  331. package/dist/types/cms.schema.js +4 -2
  332. package/dist/types/fields.d.ts +35 -0
  333. package/dist/types/index.d.ts +1 -1
  334. package/dist/types/layout.d.ts +35 -2
  335. package/dist/updates/0.26.0/index.d.ts +2 -0
  336. package/dist/updates/0.26.0/index.js +51 -0
  337. package/dist/updates/index.js +3 -1
  338. package/package.json +29 -7
  339. package/dist/admin/client/collection/empty-state.svelte +0 -28
  340. package/dist/admin/client/collection/empty-state.svelte.d.ts +0 -9
  341. package/dist/admin/client/form/submission-status-badge.svelte +0 -41
  342. package/dist/admin/client/form/submission-status-badge.svelte.d.ts +0 -7
  343. package/dist/admin/components/media/file-preview.svelte +0 -51
  344. package/dist/admin/components/media/file-preview.svelte.d.ts +0 -6
  345. package/dist/admin/utils/formatDate.d.ts +0 -5
  346. package/dist/paraglide/messages/en.d.ts +0 -5
  347. package/dist/paraglide/messages/en.js +0 -14
  348. package/dist/paraglide/messages/pl.d.ts +0 -5
  349. package/dist/paraglide/messages/pl.js +0 -14
@@ -0,0 +1,47 @@
1
+ <script lang="ts">
2
+ import { useInterfaceLanguage } from '../../../state/interface-language.svelte.js';
3
+ import { getContentLanguage } from '../../../state/content-language.svelte.js';
4
+ import type { Field } from '../../../../types/fields.js';
5
+ import type { InterfaceLanguage } from '../../../../types/languages.js';
6
+ import AlertTriangle from '@tabler/icons-svelte/icons/alert-triangle';
7
+ import { validateA11y, a11yLangPl, a11yLangEn } from './a11y-validator.js';
8
+
9
+ type Props = {
10
+ data: Record<string, unknown>;
11
+ fields: Field[];
12
+ };
13
+
14
+ let { data, fields }: Props = $props();
15
+
16
+ const interfaceLanguage = useInterfaceLanguage();
17
+ const contentLanguage = getContentLanguage();
18
+
19
+ const lang: Record<InterfaceLanguage, { title: (n: number) => string }> = {
20
+ en: {
21
+ title: (n) => `${n} accessibility issue${n === 1 ? '' : 's'} — open settings to review`
22
+ },
23
+ pl: {
24
+ title: (n) =>
25
+ `${n} ${n === 1 ? 'kwestia' : n < 5 ? 'kwestie' : 'kwestii'} dostępności — otwórz ustawienia, by zobaczyć`
26
+ }
27
+ };
28
+
29
+ const warningCount = $derived.by(() => {
30
+ if (!fields.length) return 0;
31
+ const a11yLang = interfaceLanguage.current === 'pl' ? a11yLangPl : a11yLangEn;
32
+ const issues = validateA11y(data, fields, a11yLang, contentLanguage.all);
33
+ return issues.filter((i) => i.type === 'warning').length;
34
+ });
35
+ </script>
36
+
37
+ {#if warningCount > 0}
38
+ <span
39
+ class="text-warning inline-flex items-center gap-1 rounded-md bg-[var(--warning-bg)] px-1.5 py-0.5 text-xs font-medium"
40
+ role="status"
41
+ aria-label={lang[interfaceLanguage.current].title(warningCount)}
42
+ title={lang[interfaceLanguage.current].title(warningCount)}
43
+ >
44
+ <AlertTriangle class="size-3.5" aria-hidden="true" />
45
+ <span aria-hidden="true">{warningCount}</span>
46
+ </span>
47
+ {/if}
@@ -0,0 +1,8 @@
1
+ import type { Field } from '../../../../types/fields.js';
2
+ type Props = {
3
+ data: Record<string, unknown>;
4
+ fields: Field[];
5
+ };
6
+ declare const A11yHeaderBadge: import("svelte").Component<Props, {}, "">;
7
+ type A11yHeaderBadge = ReturnType<typeof A11yHeaderBadge>;
8
+ export default A11yHeaderBadge;
@@ -6,6 +6,7 @@
6
6
  import type { Field } from '../../../../types/fields.js';
7
7
  import * as Sheet from '../../../../components/ui/sheet/index.js';
8
8
  import Button from '../../../../components/ui/button/button.svelte';
9
+ import ConfirmationDialog from '../../../components/dialogs/confirmation-dialog.svelte';
9
10
  import SettingsIcon from '@tabler/icons-svelte/icons/settings';
10
11
  import CalendarClock from '@tabler/icons-svelte/icons/calendar-clock';
11
12
  import SquareCheckFilled from '@tabler/icons-svelte/icons/square-check-filled';
@@ -16,7 +17,7 @@
16
17
  import InfoCircle from '@tabler/icons-svelte/icons/info-circle';
17
18
  import Shield from '@tabler/icons-svelte/icons/shield';
18
19
  import CircleCheck from '@tabler/icons-svelte/icons/circle-check';
19
- import { getEntryStatusForLang } from '../utils.js';
20
+ import { getLangPublishState } from '../utils.js';
20
21
  import { validateA11y, a11yLangPl, a11yLangEn, type A11yIssue } from './a11y-validator.js';
21
22
  import { getContentLanguage } from '../../../state/content-language.svelte.js';
22
23
  import LanguageIcon from '@tabler/icons-svelte/icons/language';
@@ -32,11 +33,14 @@
32
33
  scheduledFor: string;
33
34
  schedulePublish: string;
34
35
  scheduleUpdate: string;
36
+ rescheduleUpdate: string;
37
+ scheduledUpdateAt: string;
35
38
  reschedule: string;
36
39
  schedule: string;
37
40
  cancel: string;
38
41
  unpublish: string;
39
42
  cancelSchedule: string;
43
+ cancelScheduledUpdate: string;
40
44
  archive: string;
41
45
  dangerZone: string;
42
46
  date: string;
@@ -47,6 +51,9 @@
47
51
  translations: string;
48
52
  translationsHint: string;
49
53
  missingFieldsLabel: (lang: string) => string;
54
+ confirmArchiveTitle: string;
55
+ confirmArchiveDescription: string;
56
+ confirmArchiveAction: string;
50
57
  }
51
58
  > = {
52
59
  en: {
@@ -63,11 +70,14 @@
63
70
  scheduledFor: 'Scheduled for',
64
71
  schedulePublish: 'Schedule Publish',
65
72
  scheduleUpdate: 'Schedule Update',
73
+ rescheduleUpdate: 'Reschedule Update',
74
+ scheduledUpdateAt: 'Scheduled update',
66
75
  reschedule: 'Reschedule',
67
76
  schedule: 'Schedule',
68
77
  cancel: 'Cancel',
69
78
  unpublish: 'Unpublish',
70
79
  cancelSchedule: 'Cancel Schedule',
80
+ cancelScheduledUpdate: 'Cancel scheduled update',
71
81
  archive: 'Archive entry',
72
82
  dangerZone: 'Danger Zone',
73
83
  date: 'Date',
@@ -77,7 +87,11 @@
77
87
  a11yHint: 'Resolve issues before publishing',
78
88
  translations: 'Translations',
79
89
  translationsHint: 'Fill in missing fields to publish',
80
- missingFieldsLabel: (lang: string) => `Missing fields (${lang.toUpperCase()})`
90
+ missingFieldsLabel: (lang: string) => `Missing fields (${lang.toUpperCase()})`,
91
+ confirmArchiveTitle: 'Archive this entry?',
92
+ confirmArchiveDescription:
93
+ 'It will disappear from the list and stop being publicly visible. You can restore it from the archive at any time.',
94
+ confirmArchiveAction: 'Archive'
81
95
  },
82
96
  pl: {
83
97
  title: 'Publikacja',
@@ -93,11 +107,14 @@
93
107
  scheduledFor: 'Zaplanowano na',
94
108
  schedulePublish: 'Zaplanuj publikację',
95
109
  scheduleUpdate: 'Zaplanuj aktualizację',
110
+ rescheduleUpdate: 'Zmień termin aktualizacji',
111
+ scheduledUpdateAt: 'Zaplanowana aktualizacja',
96
112
  reschedule: 'Zmień termin',
97
113
  schedule: 'Zaplanuj',
98
114
  cancel: 'Anuluj',
99
115
  unpublish: 'Cofnij publikację',
100
116
  cancelSchedule: 'Anuluj planowanie',
117
+ cancelScheduledUpdate: 'Anuluj zaplanowaną aktualizację',
101
118
  archive: 'Archiwizuj wpis',
102
119
  dangerZone: 'Strefa zagrożenia',
103
120
  date: 'Data',
@@ -107,7 +124,11 @@
107
124
  a11yHint: 'Rozwiąż problemy przed publikacją',
108
125
  translations: 'Tłumaczenia',
109
126
  translationsHint: 'Uzupełnij brakujące pola, żeby opublikować',
110
- missingFieldsLabel: (lang: string) => `Brakujące pola (${lang.toUpperCase()})`
127
+ missingFieldsLabel: (lang: string) => `Brakujące pola (${lang.toUpperCase()})`,
128
+ confirmArchiveTitle: 'Zarchiwizować wpis?',
129
+ confirmArchiveDescription:
130
+ 'Wpis zniknie z listy i przestanie być publicznie widoczny. Możesz go przywrócić z archiwum w każdej chwili.',
131
+ confirmArchiveAction: 'Zarchiwizuj'
111
132
  }
112
133
  };
113
134
 
@@ -132,7 +153,9 @@
132
153
  let a11yIssues = $state<A11yIssue[]>([]);
133
154
 
134
155
  // Status is per current language
135
- const entryStatus = $derived(getEntryStatusForLang(entry, contentLanguage.current));
156
+ const langState = $derived(getLangPublishState(entry, contentLanguage.current));
157
+ const entryStatus = $derived(langState.status);
158
+ const hasScheduledUpdate = $derived(langState.hasScheduledUpdate);
136
159
  const t = $derived(lang[interfaceLanguage.current]);
137
160
 
138
161
  const hasA11yWarnings = $derived(a11yIssues.some((i) => i.type === 'warning'));
@@ -141,7 +164,7 @@
141
164
  const scheduleLabel = $derived.by(() => {
142
165
  switch (entryStatus) {
143
166
  case 'published':
144
- return t.scheduleUpdate;
167
+ return hasScheduledUpdate ? t.rescheduleUpdate : t.scheduleUpdate;
145
168
  case 'scheduled':
146
169
  return t.reschedule;
147
170
  default:
@@ -167,7 +190,7 @@
167
190
 
168
191
  function setDefaultValues() {
169
192
  const scheduledVersion = entry.scheduledVersions[contentLanguage.current];
170
- if (entryStatus === 'scheduled' && scheduledVersion?.publishedAt) {
193
+ if (scheduledVersion?.publishedAt && (entryStatus === 'scheduled' || hasScheduledUpdate)) {
171
194
  const scheduled = new Date(scheduledVersion.publishedAt);
172
195
  dateValue = scheduled.toISOString().slice(0, 10);
173
196
  timeValue = `${String(scheduled.getHours()).padStart(2, '0')}:${String(scheduled.getMinutes()).padStart(2, '0')}`;
@@ -194,12 +217,20 @@
194
217
  }
195
218
 
196
219
  function handleCancelSchedule() {
197
- onSave('cancel-published');
220
+ // Drafts only the future-dated version(s); a live published version (if any) stays online.
221
+ onSave('cancel-scheduled');
198
222
  open = false;
199
223
  }
200
224
 
225
+ let archiveConfirmOpen = $state(false);
226
+
201
227
  function handleArchive() {
228
+ archiveConfirmOpen = true;
229
+ }
230
+
231
+ function performArchive() {
202
232
  onArchive();
233
+ archiveConfirmOpen = false;
203
234
  open = false;
204
235
  }
205
236
 
@@ -234,7 +265,7 @@
234
265
  <Sheet.Root bind:open>
235
266
  <Sheet.Trigger>
236
267
  {#snippet child({ props })}
237
- <Button variant="ghost" size="icon-sm" {...props}>
268
+ <Button variant="ghost" size="icon-sm" aria-label={t.title} {...props}>
238
269
  <SettingsIcon class="size-4" />
239
270
  </Button>
240
271
  {/snippet}
@@ -268,21 +299,28 @@
268
299
  </div>
269
300
  </div>
270
301
 
271
- {#if entryStatus === 'published' && entry.publishedVersions[contentLanguage.current]?.publishedAt}
302
+ {#if entryStatus === 'published' && langState.publishedAt}
272
303
  <div class="publish-detail-row">
273
304
  <span>{t.publishedAt}</span>
274
- <span class="tabular-nums">{formatDateTime(entry.publishedVersions[contentLanguage.current]?.publishedAt)}</span>
305
+ <span class="tabular-nums">{formatDateTime(langState.publishedAt!)}</span>
275
306
  </div>
276
307
  {/if}
277
308
 
278
- {#if entryStatus === 'scheduled' && entry.publishedVersions[contentLanguage.current]?.publishedAt}
309
+ {#if entryStatus === 'scheduled' && langState.scheduledAt}
279
310
  <div class="publish-detail-row">
280
311
  <span>{t.scheduledFor}</span>
281
- <span class="tabular-nums">{formatDateTime(entry.publishedVersions[contentLanguage.current]?.publishedAt)}</span>
312
+ <span class="tabular-nums">{formatDateTime(langState.scheduledAt!)}</span>
282
313
  </div>
283
314
  {/if}
284
315
 
285
- {#if entry.publishedVersions[contentLanguage.current] && entry.publishedVersions[contentLanguage.current].id !== version.id}
316
+ {#if entryStatus === 'published' && hasScheduledUpdate && langState.scheduledAt}
317
+ <div class="publish-detail-row">
318
+ <span>{t.scheduledUpdateAt}</span>
319
+ <span class="tabular-nums">{formatDateTime(langState.scheduledAt)}</span>
320
+ </div>
321
+ {/if}
322
+
323
+ {#if entry.publishedVersions[contentLanguage.current] && entry.publishedVersions[contentLanguage.current].id !== version.id}
286
324
  <div class="publish-detail-row">
287
325
  <span>{t.publishedVersion}</span>
288
326
  <span class="tabular-nums">{formatDateTime(entry.publishedVersions[contentLanguage.current].createdAt)}</span>
@@ -404,6 +442,12 @@
404
442
  {t.dangerZone}
405
443
  </div>
406
444
 
445
+ {#if entryStatus === 'published' && hasScheduledUpdate}
446
+ <button class="btn-danger-outline" onclick={handleCancelSchedule}>
447
+ {t.cancelScheduledUpdate}
448
+ </button>
449
+ {/if}
450
+
407
451
  {#if entryStatus === 'published'}
408
452
  <button class="btn-danger-outline" onclick={handleUnpublish}>
409
453
  {t.unpublish}
@@ -429,6 +473,14 @@
429
473
  </Sheet.Content>
430
474
  </Sheet.Root>
431
475
 
476
+ <ConfirmationDialog
477
+ bind:open={archiveConfirmOpen}
478
+ title={lang[interfaceLanguage.current].confirmArchiveTitle}
479
+ description={lang[interfaceLanguage.current].confirmArchiveDescription}
480
+ confirmLabel={lang[interfaceLanguage.current].confirmArchiveAction}
481
+ onConfirm={performArchive}
482
+ />
483
+
432
484
  <style>
433
485
  .sheet-body {
434
486
  padding: 18px 20px;
@@ -524,6 +576,10 @@
524
576
  .schedule-input:focus {
525
577
  border-color: var(--primary);
526
578
  }
579
+ .schedule-input:focus-visible {
580
+ outline: 2px solid var(--ring);
581
+ outline-offset: 1px;
582
+ }
527
583
  .btn-schedule {
528
584
  width: 100%;
529
585
  padding: 8px;
@@ -1,42 +1,65 @@
1
1
  <script lang="ts">
2
2
  import { useInterfaceLanguage } from '../../../state/interface-language.svelte.js';
3
3
  import type { InterfaceLanguage } from '../../../../types/languages.js';
4
+ import { formatRelativeDate } from '../../../utils/formatters.js';
4
5
  import Loader2 from '@tabler/icons-svelte/icons/loader-2';
5
6
  import Check from '@tabler/icons-svelte/icons/check';
6
7
  import AlertCircle from '@tabler/icons-svelte/icons/alert-circle';
7
8
 
9
+ type SaveStatus = 'idle' | 'saving' | 'saved' | 'unsaved' | 'error';
10
+
11
+ type Props = {
12
+ status: SaveStatus;
13
+ lastSavedAt?: Date | null;
14
+ };
15
+
16
+ let { status, lastSavedAt = null }: Props = $props();
17
+
18
+ const interfaceLanguage = useInterfaceLanguage();
19
+
8
20
  const lang: Record<
9
21
  InterfaceLanguage,
10
22
  {
11
23
  saving: string;
12
- saved: string;
24
+ savedJustNow: string;
25
+ savedAgo: (relative: string) => string;
13
26
  unsaved: string;
14
27
  error: string;
15
28
  }
16
29
  > = {
17
- en: {
18
- saving: 'Saving draft...',
19
- saved: 'Draft saved',
20
- unsaved: 'Unsaved changes',
21
- error: 'Could not save — try again'
22
- },
23
30
  pl: {
24
- saving: 'Zapisywanie szkicu...',
25
- saved: 'Szkic zapisany',
31
+ saving: 'Zapisuję…',
32
+ savedJustNow: 'Zapisano przed chwilą',
33
+ savedAgo: (rel: string) => `Zapisano ${rel}`,
26
34
  unsaved: 'Niezapisane zmiany',
27
- error: 'Nie udało się zapisać — spróbuj ponownie'
35
+ error: 'Błąd zapisu — spróbuj ponownie'
36
+ },
37
+ en: {
38
+ saving: 'Saving…',
39
+ savedJustNow: 'Saved just now',
40
+ savedAgo: (rel: string) => `Saved ${rel}`,
41
+ unsaved: 'Unsaved changes',
42
+ error: 'Save failed — try again'
28
43
  }
29
44
  };
30
45
 
31
- const interfaceLanguage = useInterfaceLanguage();
32
-
33
- type SaveStatus = 'idle' | 'saving' | 'saved' | 'unsaved' | 'error';
46
+ let now = $state(new Date());
34
47
 
35
- type Props = {
36
- status: SaveStatus;
37
- };
48
+ $effect(() => {
49
+ if (status !== 'saved' || !lastSavedAt) return;
50
+ const interval = setInterval(() => {
51
+ now = new Date();
52
+ }, 30000);
53
+ return () => clearInterval(interval);
54
+ });
38
55
 
39
- let { status }: Props = $props();
56
+ const savedLabel = $derived.by(() => {
57
+ if (!lastSavedAt) return lang[interfaceLanguage.current].savedJustNow;
58
+ const diffMs = now.getTime() - lastSavedAt.getTime();
59
+ if (diffMs < 10000) return lang[interfaceLanguage.current].savedJustNow;
60
+ const rel = formatRelativeDate(lastSavedAt, interfaceLanguage.current);
61
+ return lang[interfaceLanguage.current].savedAgo(rel);
62
+ });
40
63
 
41
64
  const isError = $derived(status === 'error');
42
65
  </script>
@@ -45,24 +68,30 @@
45
68
  role={isError ? 'alert' : 'status'}
46
69
  aria-live={isError ? 'assertive' : 'polite'}
47
70
  aria-atomic="true"
48
- class="flex items-center gap-1.5 text-xs font-medium transition-all duration-200 {status === 'idle' ? 'invisible' : ''}"
71
+ class="flex items-center gap-1.5 text-xs font-medium transition-all duration-200 {status ===
72
+ 'idle'
73
+ ? 'invisible'
74
+ : ''}"
49
75
  >
50
76
  {#if status === 'saving'}
51
- <Loader2 class="size-3.5 animate-spin text-muted-foreground" />
52
- <span class="text-muted-foreground">{lang[interfaceLanguage.current].saving}</span>
77
+ <Loader2 class="text-muted-foreground size-3.5 animate-spin" aria-hidden="true" />
78
+ <span class="text-muted-foreground max-sm:sr-only"
79
+ >{lang[interfaceLanguage.current].saving}</span
80
+ >
53
81
  {:else if status === 'saved'}
54
- <Check class="size-3.5 text-emerald-600 dark:text-emerald-400" />
55
- <span class="text-emerald-600 dark:text-emerald-400">{lang[interfaceLanguage.current].saved}</span>
82
+ <Check class="size-3.5 text-emerald-700 dark:text-emerald-400" aria-hidden="true" />
83
+ <span class="text-emerald-700 max-sm:sr-only dark:text-emerald-400">{savedLabel}</span>
56
84
  {:else if status === 'unsaved'}
57
- <span class="size-1.5 rounded-full bg-amber-500 animate-pulse"></span>
58
- <span class="text-amber-600 dark:text-amber-400">{lang[interfaceLanguage.current].unsaved}</span>
85
+ <span class="size-1.5 animate-pulse rounded-full bg-amber-500" aria-hidden="true"></span>
86
+ <span class="text-amber-700 max-sm:sr-only dark:text-amber-400"
87
+ >{lang[interfaceLanguage.current].unsaved}</span
88
+ >
59
89
  {:else if status === 'error'}
60
- <span class="flex items-center gap-1.5 rounded-md bg-red-500/10 px-2 py-0.5">
61
- <AlertCircle class="size-3.5 text-red-600 dark:text-red-400" />
62
- <span class="text-red-600 dark:text-red-400">{lang[interfaceLanguage.current].error}</span>
90
+ <span class="bg-destructive-bg flex items-center gap-1.5 rounded-md px-2 py-0.5">
91
+ <AlertCircle class="text-destructive size-3.5" aria-hidden="true" />
92
+ <span class="text-destructive max-sm:sr-only">{lang[interfaceLanguage.current].error}</span>
63
93
  </span>
64
94
  {:else}
65
- <!-- idle: invisible but in DOM so live region is registered -->
66
95
  <span class="sr-only">&nbsp;</span>
67
96
  {/if}
68
97
  </div>
@@ -1,6 +1,7 @@
1
1
  type SaveStatus = 'idle' | 'saving' | 'saved' | 'unsaved' | 'error';
2
2
  type Props = {
3
3
  status: SaveStatus;
4
+ lastSavedAt?: Date | null;
4
5
  };
5
6
  declare const SaveIndicator: import("svelte").Component<Props, {}, "">;
6
7
  type SaveIndicator = ReturnType<typeof SaveIndicator>;
@@ -1,13 +1,18 @@
1
1
  <script lang="ts">
2
2
  import { useInterfaceLanguage } from '../../../state/interface-language.svelte.js';
3
- import type { DbEntryVersion, EntryVersionStatus, RawEntry } from '../../../../types/entries.js';
3
+ import { getContentLanguage } from '../../../state/content-language.svelte.js';
4
+ import type { EntryVersionStatus, RawEntry } from '../../../../types/entries.js';
4
5
  import type { InterfaceLanguage } from '../../../../types/languages.js';
6
+ import { getLangPublishState } from '../utils.js';
7
+ import ClockFilled from '@tabler/icons-svelte/icons/clock-filled';
5
8
 
6
9
  const lang: Record<
7
10
  InterfaceLanguage,
8
11
  {
9
12
  status: Record<EntryVersionStatus, string>;
10
13
  ariaLabel: Record<EntryVersionStatus, string>;
14
+ scheduledUpdate: (date: string) => string;
15
+ scheduledUpdateAria: (date: string) => string;
11
16
  }
12
17
  > = {
13
18
  en: {
@@ -20,7 +25,9 @@
20
25
  draft: 'You are editing a draft — it is not yet visible to readers',
21
26
  scheduled: 'This entry is scheduled for publication',
22
27
  published: 'This entry is published and visible to readers'
23
- }
28
+ },
29
+ scheduledUpdate: (date) => `update ${date}`,
30
+ scheduledUpdateAria: (date) => `; a content update is scheduled for ${date}`
24
31
  },
25
32
  pl: {
26
33
  status: {
@@ -32,40 +39,78 @@
32
39
  draft: 'Edytujesz szkic — nie jest jeszcze widoczny dla czytelników',
33
40
  scheduled: 'Ten wpis jest zaplanowany do publikacji',
34
41
  published: 'Ten wpis jest opublikowany i widoczny dla czytelników'
35
- }
42
+ },
43
+ scheduledUpdate: (date) => `aktualizacja ${date}`,
44
+ scheduledUpdateAria: (date) => `; zaplanowana aktualizacja treści na ${date}`
36
45
  }
37
46
  };
38
47
 
39
48
  const interfaceLanguage = useInterfaceLanguage();
49
+ const contentLanguage = getContentLanguage();
40
50
 
41
51
  type Props = {
42
52
  entry: RawEntry;
43
- version: DbEntryVersion;
44
53
  };
45
54
 
46
- let { entry, version }: Props = $props();
55
+ let { entry }: Props = $props();
47
56
 
48
- const isPublishedVersion = $derived(entry.publishedVersions[version.lang]?.id === version.id);
49
- const isScheduledVersion = $derived(entry.scheduledVersions[version.lang]?.id === version.id);
57
+ const state = $derived(getLangPublishState(entry, contentLanguage.current));
50
58
 
51
- const currentStatus = $derived.by((): EntryVersionStatus => {
52
- if (isPublishedVersion) return 'published';
53
- if (isScheduledVersion) return 'scheduled';
54
- return 'draft';
55
- });
59
+ // Badge never renders 'archived' here (header hides actions when archived);
60
+ // fall back to 'draft' styling defensively.
61
+ const currentStatus = $derived<EntryVersionStatus>(
62
+ state.status === 'published' || state.status === 'scheduled' ? state.status : 'draft'
63
+ );
56
64
 
57
65
  const dotColor = $derived.by(() => {
58
66
  if (currentStatus === 'published') return 'var(--success)';
59
67
  if (currentStatus === 'scheduled') return 'var(--warning)';
60
68
  return 'var(--text-light)';
61
69
  });
70
+
71
+ const showUpdateHint = $derived(
72
+ state.status === 'published' && state.hasScheduledUpdate && state.scheduledAt != null
73
+ );
74
+
75
+ function formatShort(date: Date): string {
76
+ return date.toLocaleString(interfaceLanguage.current, {
77
+ day: '2-digit',
78
+ month: '2-digit',
79
+ hour: '2-digit',
80
+ minute: '2-digit'
81
+ });
82
+ }
83
+
84
+ const t = $derived(lang[interfaceLanguage.current]);
85
+ const scheduledLabel = $derived(
86
+ showUpdateHint && state.scheduledAt ? formatShort(state.scheduledAt) : ''
87
+ );
88
+ const ariaLabel = $derived(
89
+ t.ariaLabel[currentStatus] +
90
+ (showUpdateHint ? t.scheduledUpdateAria(scheduledLabel) : '')
91
+ );
62
92
  </script>
63
93
 
64
94
  <span
65
95
  role="status"
66
- aria-label={lang[interfaceLanguage.current].ariaLabel[currentStatus]}
96
+ aria-label={ariaLabel}
67
97
  class="inline-flex items-center gap-1.5 rounded-full bg-muted px-2.5 py-1 text-xs font-semibold text-muted-foreground"
68
98
  >
69
- <span class="size-[7px] rounded-full shrink-0" style="background:{dotColor}" aria-hidden="true"></span>
70
- {lang[interfaceLanguage.current].status[currentStatus]}
99
+ <span
100
+ class="size-[7px] rounded-full shrink-0"
101
+ style="background:{dotColor}"
102
+ aria-hidden="true"
103
+ ></span>
104
+ {t.status[currentStatus]}
105
+
106
+ {#if showUpdateHint}
107
+ <span
108
+ class="inline-flex items-center gap-1 border-l border-border/70 pl-1.5"
109
+ style="color: var(--warning)"
110
+ aria-hidden="true"
111
+ >
112
+ <ClockFilled class="size-3" />
113
+ {t.scheduledUpdate(scheduledLabel)}
114
+ </span>
115
+ {/if}
71
116
  </span>
@@ -1,7 +1,6 @@
1
- import type { DbEntryVersion, RawEntry } from '../../../../types/entries.js';
1
+ import type { RawEntry } from '../../../../types/entries.js';
2
2
  type Props = {
3
3
  entry: RawEntry;
4
- version: DbEntryVersion;
5
4
  };
6
5
  declare const StatusBadge: import("svelte").Component<Props, {}, "">;
7
6
  type StatusBadge = ReturnType<typeof StatusBadge>;
@@ -170,7 +170,7 @@
170
170
  <Sheet.Root bind:open>
171
171
  <Sheet.Trigger>
172
172
  {#snippet child({ props })}
173
- <Button variant="ghost" size="icon-sm" {...props}>
173
+ <Button variant="ghost" size="icon-sm" aria-label={t.history} {...props}>
174
174
  <HistoryIcon class="size-4" />
175
175
  </Button>
176
176
  {/snippet}