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
package/API.md CHANGED
@@ -1,8 +1,8 @@
1
- # includio-cms — Public API v0.25.0
1
+ # includio-cms — Public API v0.26.0
2
2
 
3
3
  > Auto-generated by `scripts/generate-api-md.ts`. Do not edit by hand.
4
4
 
5
- Entry points: **15** · Stable: **369** · Experimental: **2**
5
+ Entry points: **18** · Stable: **413** · Experimental: **2**
6
6
 
7
7
  Tags:
8
8
  - `@public` — frozen for v1.0; semver-protected.
@@ -17,7 +17,9 @@ Tags:
17
17
  - `getAuth(): <inferred>` — Returns the underlying `better-auth` instance from the initialized CMS.
18
18
  - `getCMS(): CMS` — Returns the singleton CMS instance. Must be called after `includioCMS()`
19
19
  - `interface ResolvedMedia` — Resolved media file plus its image styles + blur placeholder. Returned by
20
+ - `type ResolvedSeo = { [K in keyof SeoFieldData]: K extends 'ogImage' ? string | MediaFile | undefined : string | unde...` — Normalized SEO data — localized values flattened by `language`. A stable
20
21
  - `resolveMediaWithStyles(mediaIds: string[], styles?: ImageFieldStyle[]): Promise<Record<string, ResolvedMedia>>` — Resolve media files by IDs and generate image styles. Useful for plugins or
22
+ - `resolveSeo(entry: { seo?: Record<string, unknown> } | Record<string,..., language?: string): ResolvedSeo` — Resolve `entry.seo` into flat fields, flattening localized objects by
21
23
 
22
24
  ### `includio-cms/core`
23
25
 
@@ -25,7 +27,9 @@ Tags:
25
27
  - `getAuth(): <inferred>` — Returns the underlying `better-auth` instance from the initialized CMS.
26
28
  - `getCMS(): CMS` — Returns the singleton CMS instance. Must be called after `includioCMS()`
27
29
  - `interface ResolvedMedia` — Resolved media file plus its image styles + blur placeholder. Returned by
30
+ - `type ResolvedSeo = { [K in keyof SeoFieldData]: K extends 'ogImage' ? string | MediaFile | undefined : string | unde...` — Normalized SEO data — localized values flattened by `language`. A stable
28
31
  - `resolveMediaWithStyles(mediaIds: string[], styles?: ImageFieldStyle[]): Promise<Record<string, ResolvedMedia>>` — Resolve media files by IDs and generate image styles. Useful for plugins or
32
+ - `resolveSeo(entry: { seo?: Record<string, unknown> } | Record<string,..., language?: string): ResolvedSeo` — Resolve `entry.seo` into flat fields, flattening localized objects by
29
33
 
30
34
  ### `includio-cms/types`
31
35
 
@@ -77,8 +81,8 @@ Tags:
77
81
  - `interface ImageStyle`
78
82
  - `type Language = 'en' | 'pl'`
79
83
  - `type Layout = LayoutPreset | LayoutNode[]`
80
- - `type LayoutNode = SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode`
81
- - `type LayoutNodeType = 'section' | 'columns' | 'card' | 'accordion' | 'stack'`
84
+ - `type LayoutNode = | SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode | TabsNode | TabNode`
85
+ - `type LayoutNodeType = | 'section' | 'columns' | 'card' | 'accordion' | 'stack' | 'tabs' | 'tab'`
82
86
  - `type LayoutPreset = | 'sidebar-right' | 'two-column' | { preset: 'sidebar-right'; sidebar: string[] } | { preset: 'tw...`
83
87
  - `type Localized = Partial<Record<InterfaceLanguage, string>> | string`
84
88
  - `interface MediaField`
@@ -109,6 +113,8 @@ Tags:
109
113
  - `interface SlugField`
110
114
  - `interface StackNode`
111
115
  - `interface StructuredContentDoc`
116
+ - `interface TabNode` — A single tab. Only valid as a direct child of {@link TabsNode}.
117
+ - `interface TabsNode` — Tab strip. Renders an accessible tablist; each child `tab` becomes a panel.
112
118
  - `interface TextField`
113
119
  - `interface TypographyConfig`
114
120
  - `interface UrlField`
@@ -233,6 +239,8 @@ Tags:
233
239
  - `const reorderEntriesCommand: <inferred>`
234
240
  - `const reorderShippingMethodsCmd: <inferred>`
235
241
  - `const resendOrderEmailCmd: <inferred>`
242
+ - `const searchEntries: <inferred>`
243
+ - `const searchLinkableEntries: <inferred>`
236
244
  - `const setFocalPoint: <inferred>`
237
245
  - `const setMediaFileAlt: <inferred>`
238
246
  - `const setMediaFileTags: <inferred>`
@@ -336,6 +344,51 @@ Tags:
336
344
  - `const verification: <inferred>`
337
345
  - `const videoStylesTable: <inferred>`
338
346
 
347
+ ### `includio-cms/db-postgres/schema-core`
348
+
349
+ - `const consentLogsTable: <inferred>`
350
+ - `const entriesTable: <inferred>`
351
+ - `const entryVersionsTable: <inferred>`
352
+ - `const formSubmissionsTable: <inferred>`
353
+ - `const imageStylesTable: <inferred>`
354
+ - `const mediaFilesTable: <inferred>`
355
+ - `const mediaFileTagsTable: <inferred>`
356
+ - `const mediaTagsTable: <inferred>`
357
+ - `const videoStylesTable: <inferred>`
358
+
359
+ ### `includio-cms/db-postgres/schema-shop`
360
+
361
+ - `type InpostParcelSize = 'A' | 'B' | 'C'`
362
+ - `type InpostServiceType = | 'inpost_locker_standard' | 'inpost_locker_express' | 'inpost_courier_standard' | 'inpost_courie...`
363
+ - `interface ShippingCarrierConfig`
364
+ - `type ShopCarrierType = 'none' | 'inpost' | string`
365
+ - `const shopCouponRedemptionsTable: <inferred>`
366
+ - `const shopCouponsTable: <inferred>`
367
+ - `type ShopCouponType = 'percent' | 'fixed'`
368
+ - `const shopOrderItemsTable: <inferred>`
369
+ - `const shopOrdersTable: <inferred>`
370
+ - `const shopOrderStatusHistoryTable: <inferred>`
371
+ - `const shopPaymentsTable: <inferred>`
372
+ - `type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled'`
373
+ - `const shopProductsTable: <inferred>`
374
+ - `const shopProductVariantsTable: <inferred>`
375
+ - `const shopRefundsTable: <inferred>`
376
+ - `type ShopRefundStatus = 'pending' | 'succeeded' | 'failed'`
377
+ - `const shopShippingMethodsTable: <inferred>`
378
+ - `const shopStockReservationsTable: <inferred>`
379
+ - `const shopWebhookEventsTable: <inferred>`
380
+
381
+ ### `includio-cms/auth-schema`
382
+
383
+ - `const account: <inferred>`
384
+ - `const accountRelations: <inferred>`
385
+ - `const invitation: <inferred>`
386
+ - `const session: <inferred>`
387
+ - `const sessionRelations: <inferred>`
388
+ - `const user: <inferred>`
389
+ - `const userRelations: <inferred>`
390
+ - `const verification: <inferred>`
391
+
339
392
  ### `includio-cms/shop`
340
393
 
341
394
  - `interface CarrierAdapter`
package/CHANGELOG.md CHANGED
@@ -3,6 +3,59 @@
3
3
  All notable changes to includio-cms are documented here.
4
4
  Generated from `src/lib/updates/` — do not edit manually.
5
5
 
6
+ ## 0.26.0 — 2026-05-26
7
+
8
+ UI Normalization → release readiness: slug regex camelCase + S8 detail/edit + S9 fields a11y polish + S10 a11y final audit + S10b/S10c mobile responsiveness full pass (sticky first column DataTable, Dialog fullscreenMobile prop, media library Sheet drawers, entry hybrid preview drawer toggle, dashboard mobile layout flip). 43/43 mobile Playwright pass (3 viewports × 12 widoków, 0 critical axe).
9
+
10
+ ### Added
11
+ - `getFieldA11yProps({ id, hasDescription, hasError, required })` (`src/lib/admin/utils/field-a11y.ts`) — buduje `aria-describedby` chain, `aria-invalid`, `aria-required` dla pól w `ui/form` (formsnap) — bridge bez breaking migracji ui/form ↔ ui/field koegzystencji z S3.
12
+ - `<LiveRegion>` (`src/lib/components/ui/live-region/`) — prosty primitive (`sr-only` + `role="status"` + `aria-live`) zastąpił inline duplicates w relation-field i blocks-field; gotowy do reuse.
13
+ - `field-renderer.svelte` propaguje `Form.Control` `props` (formsnap snippet `children({ props })`) do wszystkich field components (boolean, number, date, datetime, select, media, file, blocks, array, object, slug, seo, shop, url, relation). Dotąd tylko text/radio/checkboxes dostawały aria — reszta była niewired.
14
+ - Blocks field — keyboard reorder/add/remove/duplicate ogłasza przez `<LiveRegion>` ("Przeniesiono X na pozycję Y", "Dodano blok X" itp.). Block picker modal — `aria-labelledby` z Dialog.Title + `aria-live` na search results count.
15
+ - Slug field — live preview slugify'd wartości pod inputem (gdy user typuje wielką literą), copy button z `UseClipboard` + toast "Skopiowano slug". Description default w demo blog-post.
16
+ - Relation field — combobox a11y wzmocnione: `aria-busy` na Command.List podczas async search, picker dialog `Dialog.Title`/`Dialog.Description` (sr-only), reorder LiveRegion przeniesione na primitive.
17
+ - Media + File fields — `Dialog.Title` + `Dialog.Description` (sr-only) na picker dialogs (eliminuje bits-ui ostrzeżenie o brakujących aria-labelledby).
18
+ - Shop field — `aria-pressed` na price mode toggle (Netto/Brutto), `role="group"` + `aria-label` na toggle group, `aria-label="Usuń wariant N"` na trash buttons.
19
+ - SEO field — `aria-live="polite"` na char counter (50/60, 120/160) — SR słyszy zmianę gdy user wpisuje.
20
+ - Storybook fields — nowe `file.stories.svelte` (4 warianty) i `shop.stories.svelte` (4 warianty). Slug stories rozszerzone o WithPreview/ClipboardCopy. Text stories — Required wariant. Slug ma już `tags: ['autodocs']` (zdjęty `no-test`).
21
+ - Slugi pól, kolekcji, singles i form akceptują camelCase (`/^[a-z][a-zA-Z0-9-]*$/`). Można pisać `slug: 'siteName'` zamiast `'site-name'` i odczytywać `entry.data.siteName` bez bracket notation. Walidacja blokuje nadal PascalCase, prefix `_` i digit-leading.
22
+ - Helper `quoteKey()` w `src/lib/core/server/generator/utils.ts` — opakowuje slugi nie-spełniające JS identifier shape w cudzysłowy w wygenerowanym TS.
23
+ - Nowy węzeł layoutu `tabs`/`tab` (`src/lib/types/layout.ts`) — taby konfigurowane per kolekcja w `layout[]`, renderowane przez `LayoutRenderer` (bits-ui Tabs: `role=tab/tablist/tabpanel`, strzałki/Home/End, `aria-selected`). Wszystkie panele pozostają zamontowane (walidacja/dirty-tracking/`showWhen` działają na nieaktywnych tabach), error-summary i klik-w-preview (hybrid) automatycznie przełączają tab i fokusują pole (`activateContainingTabs`), trigger taba z błędem ma wskaźnik (kropka + tekst dla SR, nie sam kolor). Aktywny tab najwyższego poziomu utrwalany w `?tab` (deep-link, przeżywa reload). `tab` przyjmuje `fields` (płaski) lub `children` (sekcje/karty w środku); zakaz zagnieżdżonych tabów + walidacja struktury w `validateLayout`. Stary sztywny tab Content/SEO w `entry.svelte` usunięty — SEO to teraz zwykły `tab` w configu (demo blog-post).
24
+ - `<FormErrorSummary>` (`src/lib/admin/components/forms/`) — banner z listą błędów, anchor links scroll do `[data-field-path]`, focus pierwszego błędnego pola, `role="alert"` + `aria-live="assertive"`. Adoptowany w entry, coupon-form, shipping-method-form, shop-order-detail.
25
+ - `<ConfirmationDialog>` (`src/lib/admin/components/dialogs/`) — typed wrapper na bits-ui AlertDialog z destructive/default variant, default focus na Cancel (bezpieczniejszy), loading state. Zastąpił 5× `confirm()` (form-submissions, entry, shop-order-detail, coupons-list, dashboard) + dodany dla Archive entry.
26
+ - `<DetailPageShell>` (`src/lib/admin/components/layout/`) — wspólny layout (PageHeader + body + opcjonalny sidebar) dla coupon-edit / shipping-method-edit. Skip-link target `#detail-main`.
27
+ - Coupon edit form zmigrowany na sveltekit-superforms + formsnap (jak account/profile-section) — schema zod (`coupon-schema.ts`), SPA mode, error summary + per-field errors.
28
+ - Entry SaveIndicator: nowe stany + COGA copy (`Niezapisane zmiany`, `Zapisuję…`, `Zapisano X temu` z `formatRelativeDate` recompute co 30s, `Błąd zapisu`), `aria-atomic` + role flip alert/status. `<svelte:window>` `beforeunload` guard gdy unsaved.
29
+ - `<A11yHeaderBadge>` (`src/lib/admin/client/entry/header/a11y-header-badge.svelte`) — persistent warning chip w entry-header pokazujący liczbę a11y issues (images bez alt, heading hierarchy, generic link text). Reuse `validateA11y` z `a11y-validator.ts`. Strong-warning UX (B.1) — nie blokuje save, prowadzi autora. Kolumna a11y w collection-entries.svelte (S5) + persistent header badge (S10) + publish-panel sheet detail = pełna ścieżka widoczności.
30
+ - `scripts/lighthouse-audit.ts` (`pnpm audit:lighthouse`) — ad-hoc CLI runner po 11 URL admin (login, dashboard, collections, users, media, forms, account, maintenance, shop ×3). Lighthouse 13 + chrome-launcher + auth cookie z `e2e/.auth/admin.json`. Output `.tmp/lighthouse/<view>.json` + `summary.md`, target a11y ≥95.
31
+ - `e2e/admin/a11y-baseline.spec.ts` rozszerzone 4 → 14 widoków: 10 page-level (login, dashboard, collections-list, entry-edit, users-list, media-library, forms-detail, account, maintenance, user-create-dialog) + 4 shop best-effort (skip jeśli moduł nie configured). Per spec 0 critical violations enforced.
32
+ - TipTap link-dialog `aria-expanded` na 2 collapsible sections (Dostępność + Indeksowanie) — uzupełnia ATAG B.3 author tool a11y. FigureNodeView/image-dialog/publish-panel: `:focus-visible` fallback z `var(--ring)` outline (focus indicator widoczny zawsze, nawet gdy `:focus` zmienia tylko border-color).
33
+ - Publiczny `resolveSeo(entry, language?)` (`includio-cms/core`) — stabilny znormalizowany read-path nad zamrożonym kontraktem `entry.seo.*` (wartości localized spłaszczane po języku; `ogImage` przepuszczany jako string lub MediaFile) do budowy własnego `<head>` lub zasilenia komponentu `<Seo>`. `SlugField`/`SeoField`/`SeoFieldData` oznaczone `@public` + v1.0-frozen.
34
+ - Wewnętrzny `seoFieldDescriptor` — pojedyncze źródło prawdy kształtu pola SEO dla generatorów Zod + TS (wyjście bit-identyczne, pilnowane snapshotami i testami drift-guard). Przygotowuje przyszły plugin-rehoming SEO bez breaking change. Istniejąca niespójność Zod(required)/TS(optional) dla `description`/`ogImage` udokumentowana i zachowana 1:1 (do rozstrzygnięcia post-1.0).
35
+ - Mobile responsiveness full pass (S10c) — pełny mobile UX panelu admina: `DataTable` sticky first column + edge-bleed scroll wrapper (1 fix → wszystkie 8+ list pages, w tym shop), `Dialog.Content` `fullscreenMobile` prop (media/file picker + tiptap image/video dialogi), media library tags sidebar + FileDetails jako Sheet drawer na <md (`hidden md:flex` aside), entry hybrid preview Sheet drawer toggle z `IsMobile(1024)` (<lg pokazuje tylko form + floating "Podgląd" button), shop-order detail items table z `min-w-[640px]` + horizontal scroll, char counter w `text-field-wrapper` na mobile stackowany pod polem zamiast `absolute right`, EntryHeader padding + SaveIndicator text `max-sm:sr-only`, PageHeader text-scale `text-2xl sm:text-3xl lg:text-4xl`, breadcrumb truncacja middle segments `/…/` na <sm, table-toolbar search `w-full min-w-0` na mobile, tiptap toolbar separatory `hidden sm:block`, relation popover `w-[var(--bits-popover-anchor-width)] max-w-[calc(100vw-1rem)]`. Playwright `e2e/admin/mobile-responsive.spec.ts` rozszerzony o iPad portrait (768×1024) + shop-shipping view + `scrollWidth <= window.innerWidth` page-overflow assertion: 43/43 testów pass, 0 critical, 0-2 serious axe per (3 viewports × 12 widoków).
36
+ - Dashboard mobile layout flip (S10c follow-up) — `dashboard-page.svelte`: main wrapper `flex gap-5` → `flex flex-col gap-5 lg:flex-row` + sub-grid `grid-cols-2` → `grid-cols-1 sm:grid-cols-2` + sidebar `max-w-80 flex-1 shrink-0` → `w-full shrink-0 lg:max-w-80 lg:flex-1`. Side-by-side 2-col layout aktywowany dopiero od `lg` (1024px); poniżej stack vertically, sub-grid kolumna pojedyncza do `sm` (640px). Eliminuje cramped 2-col scroll na 375-768px.
37
+
38
+ ### Fixed
39
+ - `runtime/types.ts` generuje poprawny TypeScript dla kebab-case slugów (np. `'published-at'?: string` zamiast gołego `published-at?: string`, który był syntaks błędem). Naprawione w `generateTsTypeFromFields`, `generateFlatTsTypeFromFields`, `generateInlineBlockTypeString`, object/blocks variants oraz form fields generator.
40
+ - Shop order detail: `bg-red-50` / `bg-green-50` zamienione na tokenized `bg-destructive-bg` / `bg-success-bg` z `role="alert"`/`role="status"`. Status form ma teraz SaveIndicator + FormErrorSummary.
41
+ - Shipping-method form: `<fieldset>/<legend>` na payment methods (poprawne grouping dla SR), `aria-live="polite"` na carrier config panel, FormErrorSummary zamiast `bg-red-50` div, `text-amber-700` zamienione na `text-warning` token.
42
+ - Coupons list: delete dialog A11y (focus trap, ESC, return focus) zamiast browser `confirm()`.
43
+ - Form submissions bulk delete: AlertDialog zamiast `confirm()`, plural PL forms ("3 zgłoszenia" vs "5 zgłoszeń").
44
+ - Dashboard delete-orphaned: AlertDialog z liczbą wpisów w description zamiast `confirm()`.
45
+ - `pnpm demo` seed (`scripts/seed-demo.ts`) — twarda bramka walidacji: każdy `entry_version` przed surowym INSERT-em przechodzi przez realny schemat CMS (`generateZodSchemaFromFields(..., { localized: false })` — ten sam oracle co admin/publish). Niezgodne dane przerywają seed z czytelnym `collection/lang/entry: path: message`. Dane demo doprowadzone do zgodności: blog-post `title` bez nierealnego `minLength: 50` (+ usunięte śmieciowe debugowe pole `test`/`dupa` z kolekcji), media jako UUID-string zamiast `{id,url,alt}` (cover/thumbnail/image/logo/favicon/photo), daty pełne ISO, dołożone wymagane obiekty `seo`, `url` jako obiekt, bloki z `_slug` zamiast `_type`, `localizedTags`/`links` w kształcie schematu.
46
+ - Lista entries w kolekcji pokazuje "(bez tytułu)"/"(untitled)" zamiast surowego UUID gdy wpis nie ma tytułu — spójne z breadcrumbem na ekranie edycji. Wspólny helper `getCollectionEntryDisplayLabel` (`src/lib/admin/utils/entryLabel.ts`) używany przez list/grid i breadcrumb (fallback wykrywany po `language === null`, odporny na tytuł = id).
47
+ - Slug first-class: podgląd URL wpisu w adminie (`collection-entries.svelte`) odhardkodowany z wymogu pola typu `seo` — kolekcja ze standalone polem slug + skonfigurowanym `slugField` pokazuje URL; bez `slugField`/`pathTemplate` świadomie brak `_url` (np. kolekcje atrybutów), bez błędu. Wydzielony czysty resolver `slugPath.ts` (bez `getCMS`) współdzielony przez admin client i server.
48
+
49
+ ### Breaking
50
+ - **Entry autosave usunięty** — wcześniej 30s timeout + Ctrl/Cmd+S manual. Teraz tylko manual save (button "Zapisz szkic" zawsze widoczny + Ctrl/Cmd+S shortcut). Powód: stara impl mogła w niejasnych sytuacjach modyfikować published data; bezpieczniejsza re-introdukcja z draft-only guard zaplanowana w ROADMAP backlog. Migracja: użytkownicy muszą explicit zapisać przed nawigacją (jest `beforeunload` guard).
51
+ - EntryHeader props: nowy `lastSavedAt?: Date | null` (default `null`). Niezbędny dla SaveIndicator "Zapisano X temu". Konsumenci niestandardowi (entry-header-story-demo, custom integracje) muszą propagować z entry.svelte.
52
+ - EntryForm props: usunięty hardcoded podział Content/SEO (`tabFilter` nigdy nie trafił do release'u — zastąpiony węzłem layoutu `tabs`). Grupowanie w taby = teraz config `layout[]`. Kolekcje bez `tabs` bez zmian; SEO w demo blog-post wyrażone jako `tab`. Dodany prop `errorPaths?: Set<string>` (EntryForm/LayoutRenderer) do wskaźnika błędu na tabie.
53
+ - `coupon-form.svelte` przepisane od zera na sveltekit-superforms — props identyczne (`initial`, `submitLabel`, `onSubmit`, `onCancel`), ale wewnętrzny mechanizm walidacji zmieniony (zod schema zamiast hand-rolled). Call-sites bez zmian.
54
+
55
+ ### Notes
56
+
57
+ V1-DECISIONS.md sekcja "Sesja 8" zawiera pełny audit decyzji + grep gates. Pełna superForm migracja shipping-method-form odłożona do backlogu (skomplikowany state: net/gross toggle + dynamic carrier + multi-lang record). Storybook entry-page story też w backlogu (wymaga mock setRemotes + RawEntry fixtures — robione w S10 a11y sweep). VoiceOver smoke test (manual user-delegated) — checklist w `V1-UI-AUDIT.md` sekcja "VoiceOver smoke (manual)". Kompatybilność z istniejącymi danymi: pełna (zero schema changes; coupon zachowuje stary kontrakt API).
58
+
6
59
  ## 0.25.0 — 2026-05-06
7
60
 
8
61
  Faza 11.5 — Shop polish. Stripe payment adapter (Checkout Session flow z native webhook signature verify), refund infrastructure (full + partial, cross-adapter Stripe + PayU), webhook idempotency table (`shop_webhook_events` z UNIQUE(provider, event_id)), coupons (% / fixed PLN, expiresAt, maxUses, minOrderAmount, OCC race-safe redemption), low-stock email alert (per-product `lowStockThreshold`), order export CSV w admin, default email templates rozszerzone o `refunded` status, SDK `applyCoupon`/`removeCoupon` + JSDoc body + `@public` tagi, pełna dokumentacja shopa (DOCS.md + adapter guides + cURL examples + Stripe/Coupons/Refund pages). Shop = `@public` w v1.0.
package/DOCS.md CHANGED
@@ -1,4 +1,4 @@
1
- # Includio CMS Documentation (v0.25.0)
1
+ # Includio CMS Documentation (v0.26.0)
2
2
 
3
3
  > This file is auto-generated from the docs site. For the latest version, update the package.
4
4
 
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # includio-cms
2
2
 
3
3
  [![CI](https://github.com/includio/includio-cms/actions/workflows/ci.yml/badge.svg)](https://github.com/includio/includio-cms/actions/workflows/ci.yml)
4
+ [![Storybook](https://img.shields.io/badge/Storybook-deployed-ff4785?logo=storybook&logoColor=white)](https://includio.github.io/includio-cms/)
4
5
 
5
6
  A headless CMS built for SvelteKit. Type-safe, extensible, with a modern admin interface and pluggable adapters for database, files, email, and AI.
6
7
 
@@ -211,6 +212,7 @@ Global flags: `--help, -h` and `--version, -v`.
211
212
  - [Changelog](./CHANGELOG.md)
212
213
  - [Roadmap](./ROADMAP.md)
213
214
  - [Known risks](./KNOWN-RISKS.md)
215
+ - [Storybook](https://includio.github.io/includio-cms/) — visual reference for all 86 UI components (designer source-of-truth)
214
216
 
215
217
  ## For AI assistants
216
218
 
package/ROADMAP.md CHANGED
@@ -20,6 +20,8 @@
20
20
  - [x] `[chore]` `[P1]` Faza 11 — Performance Pass (0.24.0): N+1 elimination (`getImageStyle` batch IN query, `getRawEntries` batch entry versions), Sharp srcset `Promise.allSettled` (one timeout doesn't kill batch), background maintenance in-process lock verified + tested, bench infra (`pnpm bench` + representative benchmarks), lazy adapter imports verified <!-- files: src/lib/core/server/media/styles/operations/, src/lib/core/server/fields/resolveImageFields.ts, src/lib/core/server/entries/operations/get.ts, src/lib/db-postgres/index.ts, src/lib/core/server/media/operations/backgroundMaintenance.spec.ts, src/lib/updates/0.24.0/ -->
21
21
  - [x] `[feature]` `[P0]` Faza 11.5 — Shop polish (0.25.0): Stripe adapter (Checkout Session, sig verify, idempotency), refund infra (full + partial cross-adapter), webhook idempotency table (`shop_webhook_events`), coupons (% / fixed, expiresAt, maxUses, minOrder), low-stock email alert, order export CSV, default email templates (PL/EN), SDK JSDoc + `@public`, pełna dokumentacja shopa <!-- files: src/lib/shop/adapters/stripe/, src/lib/shop/server/{refund,coupons}.ts, src/lib/db-postgres/schema/shop/{refunds,webhookEvents,coupons,couponRedemptions}.ts, src/lib/admin/client/shop/, src/lib/updates/0.25.0/ -->
22
22
  - [ ] `[fix]` `[P1]` Select field — `defaultValue` propagacja do zod schema (full repro: `ideas/post-v1/select-field-defaultvalue-bug.md`); fix planowany w Fazie 12 (RC)
23
+ - [x] `[chore]` `[P2]` Demo orchestrator — `pnpm demo` startuje czystą instancję na tmpfs DB :5436, seeduje 12 blog postów / 6 projektów / 5 contact submissions / 8 gradient PNG-ów, włącza `demo-site` frontend pod `/demo-site`, każdy start = czysty stan <!-- files: scripts/demo.ts, scripts/seed-demo.ts, src/routes/demo-site/, docker-compose.yml, .env.demo -->
24
+ - [x] `[feature]` `[P1]` Slug first-class + SEO v1.0 freeze (0.26.0) — `resolveSeo` public (`includio-cms/core`), `seoFieldDescriptor` SSOT (Zod+TS drift-guard), admin URL un-hardcode (`slugPath.ts` pure resolver, no `seo`-field requirement), `SlugField`/`SeoField`/`SeoFieldData` `@public` v1.0-frozen <!-- files: src/lib/core/fields/slugPath.ts, src/lib/core/fields/seoFieldDescriptor.ts, src/lib/core/fields/resolveSeo.ts, src/lib/types/fields.ts, src/lib/admin/client/collection/collection-entries.svelte, src/lib/updates/0.26.0/ -->
23
25
 
24
26
  ## v1.x — Post-v1.0 deferred
25
27
 
@@ -45,6 +47,10 @@
45
47
 
46
48
  ## Backlog
47
49
 
50
+ - [ ] `[feature]` `[P2]` Date/datetime field — przebudowa na shadcn-svelte (bits-ui Calendar/DatePicker) zamiast natywnego inputu. Zgłoszone w QA Etap 5a (4/5); funkcjonalnie OK, odłożone jako osobny redesign pola daty. <!-- files: src/lib/admin/components/fields/date-field.svelte, datetime-field.svelte -->
51
+ - [ ] `[feature]` `[P1]` Re-introduce entry autosave with strict draft-only guard (opt-in via `cms.config.ts`, never touch published versions, debounced + visual countdown). Removed in 0.26.0 / S8 because old impl could touch published data ambiguously.
52
+ - [ ] `[feature]` `[P2]` Migrate `shipping-method-form` na sveltekit-superforms + formsnap (S8 zostawił hand-rolled validation + FormErrorSummary; pełna migracja wymaga schema dla multi-lang record + dynamic carrier config + price net/gross toggle).
53
+ - [ ] `[feature]` `[P2]` Storybook story dla `entry-page` (Default/Saving/Saved/Error/Draft/WithErrors/Confirmation) — wymaga mock context: `setRemotes` (5 commands), `setBreadcrumbs`, `setContentLanguage`, RawEntry/DbEntryVersion fixtures. S8 odłożone do S10 a11y sweep.
48
54
  - [ ] `[feature]` `[P1]` Server-side pagination API (formalize 0.1.0 fix)
49
55
  - [x] `[feature]` `[P1]` Improved type generation — union types for select/checkboxes, defaultValue makes fields non-optional <!-- files: src/lib/core/server/generator/ -->
50
56
  - [ ] `[feature]` `[P1]` Proper filtering API (SQL-level, not JS post-query)
@@ -24,6 +24,7 @@ export declare const accountLang: Record<string, {
24
24
  strengthStrong: string;
25
25
  strengthVeryStrong: string;
26
26
  strengthLabel: string;
27
+ generatePassword: string;
27
28
  };
28
29
  language: {
29
30
  title: string;
@@ -24,7 +24,8 @@ export const accountLang = {
24
24
  strengthMedium: 'Średnie',
25
25
  strengthStrong: 'Silne',
26
26
  strengthVeryStrong: 'Bardzo silne',
27
- strengthLabel: 'Siła hasła'
27
+ strengthLabel: 'Siła hasła',
28
+ generatePassword: 'Wygeneruj hasło'
28
29
  },
29
30
  language: {
30
31
  title: 'Język interfejsu',
@@ -75,7 +76,8 @@ export const accountLang = {
75
76
  strengthMedium: 'Medium',
76
77
  strengthStrong: 'Strong',
77
78
  strengthVeryStrong: 'Very strong',
78
- strengthLabel: 'Password strength'
79
+ strengthLabel: 'Password strength',
80
+ generatePassword: 'Generate password'
79
81
  },
80
82
  language: {
81
83
  title: 'Interface language',
@@ -88,10 +88,10 @@
88
88
 
89
89
  <!-- Email readonly -->
90
90
  <div class="flex flex-col gap-1">
91
- <!-- svelte-ignore a11y_label_has_associated_control -->
92
- <label class="text-sm font-medium">{lang.profile.email}</label>
91
+ <label for="account-email" class="text-sm font-medium">{lang.profile.email}</label>
93
92
  <div class="acct-input-wrap">
94
93
  <Input
94
+ id="account-email"
95
95
  type="email"
96
96
  value={$session.data.user.email}
97
97
  readonly
@@ -9,6 +9,8 @@
9
9
  import { accountLang } from './lang.js';
10
10
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
11
11
  import { authClient } from '../../auth-client.js';
12
+ import { errorMessages, pickError } from '../../i18n/errors.js';
13
+ import { generatePassword } from '../../shared/password-generate.js';
12
14
  import { toast } from 'svelte-sonner';
13
15
 
14
16
  const interfaceLanguage = useInterfaceLanguage();
@@ -31,7 +33,9 @@
31
33
  newPassword: form.data.newPassword
32
34
  });
33
35
  if (error) {
34
- toast.error(error.message || 'Failed to update password');
36
+ toast.error(
37
+ error.message || pickError(errorMessages.server.saveFailed, interfaceLanguage.current),
38
+ );
35
39
  } else {
36
40
  toast.success(lang.security.passwordUpdated);
37
41
  $passwordFormData.currentPassword = '';
@@ -73,6 +77,14 @@
73
77
  return labels[strength.level];
74
78
  });
75
79
 
80
+ function handleGeneratePassword() {
81
+ const pw = generatePassword();
82
+ $passwordFormData.newPassword = pw;
83
+ $passwordFormData.confirmPassword = pw;
84
+ showNew = true;
85
+ showConfirm = true;
86
+ }
87
+
76
88
  </script>
77
89
 
78
90
  <!-- Password Card -->
@@ -150,9 +162,20 @@
150
162
  {lang.security.strengthLabel}: {strengthLabel}
151
163
  </p>
152
164
  {/if}
153
- <p id="pw-hint" class="text-text-light mt-1 text-xs">
154
- {lang.security.passwordHint}
155
- </p>
165
+ <div class="mt-1 flex items-center justify-between gap-2">
166
+ <p id="pw-hint" class="text-text-light text-xs">
167
+ {lang.security.passwordHint}
168
+ </p>
169
+ <Button
170
+ variant="link"
171
+ size="sm"
172
+ type="button"
173
+ class="h-auto shrink-0 p-0 text-xs"
174
+ onclick={handleGeneratePassword}
175
+ >
176
+ {lang.security.generatePassword}
177
+ </Button>
178
+ </div>
156
179
  {/snippet}
157
180
  </Form.Control>
158
181
  <Form.FieldErrors class="text-sm text-red-500" />
@@ -2,7 +2,7 @@
2
2
  import * as Card from '../../../components/ui/card/index.js';
3
3
  import { accountLang } from './lang.js';
4
4
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
5
- import { toLocaleCode } from '../../utils/formatDate.js';
5
+ import { toLocaleCode } from '../../utils/formatters.js';
6
6
  import { authClient } from '../../auth-client.js';
7
7
  import { toast } from 'svelte-sonner';
8
8
  import Button from '../../../components/ui/button/button.svelte';
@@ -26,7 +26,7 @@
26
26
  <Sidebar.Provider style="--sidebar-width: 16rem; --header-height: calc(var(--spacing) * 13);">
27
27
  <AppSidebar />
28
28
 
29
- <Sidebar.Inset class="h-screen overflow-hidden">
29
+ <Sidebar.Inset id="main-content" tabindex={-1} class="h-screen overflow-hidden outline-none">
30
30
  <SiteHeader />
31
31
  <div class="flex grow flex-col overflow-auto">
32
32
  {@render children()}
@@ -6,6 +6,7 @@
6
6
  import RecentActivity from '../../components/dashboard/recent-activity.svelte';
7
7
  import A11yGauge from '../../components/dashboard/a11y-gauge.svelte';
8
8
  import TipOfTheDay from '../../components/dashboard/tip-of-the-day.svelte';
9
+ import ConfirmationDialog from '../../components/dialogs/confirmation-dialog.svelte';
9
10
  import { sidebarLang } from '../../components/layout/lang.js';
10
11
  import { getBreadcrumbs } from '../../state/breadcrumbs.svelte.js';
11
12
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
@@ -20,6 +21,23 @@
20
21
  let orphanedEntries = $state<OrphanedEntry[]>([]);
21
22
  let loadingOrphaned = $state(true);
22
23
  let deletingOrphaned = $state(false);
24
+ let confirmDeleteOpen = $state(false);
25
+
26
+ const confirmText: Record<
27
+ InterfaceLanguage,
28
+ { title: string; description: (n: number) => string }
29
+ > = {
30
+ pl: {
31
+ title: 'Usunąć osierocone wpisy?',
32
+ description: (n) =>
33
+ `${n} ${n === 1 ? 'wpis zostanie' : 'wpisy zostaną'} trwale usunięty z bazy. Tej akcji nie cofniesz.`
34
+ },
35
+ en: {
36
+ title: 'Delete orphaned entries?',
37
+ description: (n) =>
38
+ `${n} ${n === 1 ? 'entry' : 'entries'} will be permanently removed. This cannot be undone.`
39
+ }
40
+ };
23
41
 
24
42
  async function fetchOrphanedEntries() {
25
43
  try {
@@ -34,13 +52,11 @@
34
52
  }
35
53
  }
36
54
 
37
- async function deleteOrphaned() {
38
- const msg: Record<InterfaceLanguage, string> = {
39
- pl: 'Czy na pewno chcesz usunąć te wpisy? Tej operacji nie można cofnąć.',
40
- en: 'Are you sure you want to delete these entries? This cannot be undone.'
41
- };
42
- if (!confirm(msg[interfaceLanguage.current])) return;
55
+ function deleteOrphaned() {
56
+ confirmDeleteOpen = true;
57
+ }
43
58
 
59
+ async function performDeleteOrphaned() {
44
60
  deletingOrphaned = true;
45
61
  try {
46
62
  const res = await fetch('/admin/api/orphaned', { method: 'DELETE' });
@@ -67,6 +83,14 @@
67
83
  });
68
84
  </script>
69
85
 
86
+ <ConfirmationDialog
87
+ bind:open={confirmDeleteOpen}
88
+ title={confirmText[interfaceLanguage.current].title}
89
+ description={confirmText[interfaceLanguage.current].description(orphanedEntries.length)}
90
+ loading={deletingOrphaned}
91
+ onConfirm={performDeleteOrphaned}
92
+ />
93
+
70
94
  <main class="dash-main">
71
95
  {#if !loadingOrphaned}
72
96
  <OrphanedEntriesNotice
@@ -78,9 +102,9 @@
78
102
 
79
103
  <WelcomeHeader />
80
104
 
81
- <div class="flex gap-5">
82
- <div class="flex-1">
83
- <div class="grid grid-cols-2 gap-5">
105
+ <div class="flex flex-col gap-5 lg:flex-row">
106
+ <div class="min-w-0 flex-1">
107
+ <div class="grid grid-cols-1 gap-5 sm:grid-cols-2">
84
108
  <RecentEntries />
85
109
  <FormSubmissionsWidget />
86
110
  </div>
@@ -88,7 +112,7 @@
88
112
  <RecentActivity />
89
113
  </div>
90
114
  </div>
91
- <div class="max-w-80 flex-1 shrink-0">
115
+ <div class="w-full shrink-0 lg:max-w-80 lg:flex-1">
92
116
  <A11yGauge />
93
117
  <div class="mt-5">
94
118
  <TipOfTheDay />
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import { tick, type Snippet } from 'svelte';
2
3
  import Archive from '@tabler/icons-svelte/icons/archive';
3
4
  import ArchiveOff from '@tabler/icons-svelte/icons/archive-off';
4
5
  import Trash from '@tabler/icons-svelte/icons/trash';
@@ -10,93 +11,134 @@
10
11
 
11
12
  type Props = {
12
13
  selectedCount: number;
13
- onArchive: () => void;
14
+ onArchive?: () => void;
14
15
  onDelete?: () => void;
15
16
  onClear: () => void;
16
17
  onRestore?: () => void;
18
+ actions?: Snippet;
17
19
  };
18
20
 
19
- let { selectedCount, onArchive, onDelete, onClear, onRestore }: Props = $props();
21
+ let { selectedCount, onArchive, onDelete, onClear, onRestore, actions }: Props = $props();
20
22
 
21
23
  const interfaceLanguage = useInterfaceLanguage();
22
24
 
23
- const lang: Record<InterfaceLanguage, {
24
- selected: (n: number) => string;
25
- archive: string;
26
- restore: string;
27
- delete: string;
28
- }> = {
25
+ const lang: Record<
26
+ InterfaceLanguage,
27
+ {
28
+ selected: (n: number) => string;
29
+ archive: string;
30
+ restore: string;
31
+ delete: string;
32
+ bulkActions: string;
33
+ clearSelection: string;
34
+ }
35
+ > = {
29
36
  en: {
30
37
  selected: (n) => `${n} selected`,
31
38
  archive: 'Archive',
32
39
  restore: 'Restore',
33
- delete: 'Delete'
40
+ delete: 'Delete',
41
+ bulkActions: 'Bulk actions',
42
+ clearSelection: 'Clear selection'
34
43
  },
35
44
  pl: {
36
45
  selected: (n) => `Zaznaczono: ${n}`,
37
46
  archive: 'Archiwizuj',
38
47
  restore: 'Przywróć',
39
- delete: 'Usuń'
48
+ delete: 'Usuń',
49
+ bulkActions: 'Akcje masowe',
50
+ clearSelection: 'Wyczyść zaznaczenie'
40
51
  }
41
52
  };
42
53
 
43
54
  const t = $derived(lang[interfaceLanguage.current]);
55
+
56
+ let toolbarRef = $state<HTMLElement | null>(null);
57
+ let prevCount = 0;
58
+
59
+ $effect(() => {
60
+ const count = selectedCount;
61
+ if (prevCount === 0 && count > 0) {
62
+ tick().then(() => {
63
+ const first = toolbarRef?.querySelector<HTMLElement>('button:not([aria-label])');
64
+ first?.focus();
65
+ });
66
+ }
67
+ prevCount = count;
68
+ });
69
+
70
+ function handleKeydown(e: KeyboardEvent) {
71
+ if (e.key === 'Escape') {
72
+ e.stopPropagation();
73
+ onClear();
74
+ }
75
+ }
44
76
  </script>
45
77
 
46
78
  {#if selectedCount > 0}
47
79
  <div
80
+ bind:this={toolbarRef}
48
81
  class="fixed bottom-6 left-1/2 z-50 -translate-x-1/2"
49
82
  transition:fly={{ y: 40, duration: 200 }}
50
- role="status"
51
- aria-live="polite"
83
+ role="toolbar"
84
+ aria-label={t.bulkActions}
85
+ tabindex="-1"
86
+ onkeydown={handleKeydown}
52
87
  >
53
88
  <div
54
- class="flex items-center gap-3 rounded-xl bg-plum-darker px-5 py-3 text-white shadow-xl"
89
+ class="flex max-w-[calc(100vw-2rem)] flex-wrap items-center justify-center gap-3 rounded-xl bg-plum-darker px-5 py-3 text-white shadow-xl"
55
90
  >
56
- <span class="text-sm font-medium">{t.selected(selectedCount)}</span>
91
+ <span class="text-sm font-medium" aria-hidden="true">{t.selected(selectedCount)}</span>
57
92
 
58
- <div class="h-5 w-px bg-white/20"></div>
93
+ <div class="h-5 w-px bg-white/20" aria-hidden="true"></div>
59
94
 
60
95
  {#if onRestore}
61
- <Button
62
- variant="ghost"
63
- size="sm"
64
- class="text-white hover:bg-white/10 hover:text-white"
65
- onclick={onRestore}
66
- >
67
- <ArchiveOff class="mr-1.5 size-3.5" />
68
- {t.restore}
69
- </Button>
70
- {:else}
71
- <Button
72
- variant="ghost"
73
- size="sm"
74
- class="text-white hover:bg-white/10 hover:text-white"
75
- onclick={onArchive}
76
- >
77
- <Archive class="mr-1.5 size-3.5" />
78
- {t.archive}
79
- </Button>
96
+ <Button
97
+ variant="ghost"
98
+ size="sm"
99
+ class="text-white hover:bg-white/10 hover:text-white"
100
+ onclick={onRestore}
101
+ >
102
+ <ArchiveOff class="mr-1.5 size-3.5" />
103
+ {t.restore}
104
+ </Button>
105
+ {:else if onArchive}
106
+ <Button
107
+ variant="ghost"
108
+ size="sm"
109
+ class="text-white hover:bg-white/10 hover:text-white"
110
+ onclick={onArchive}
111
+ >
112
+ <Archive class="mr-1.5 size-3.5" />
113
+ {t.archive}
114
+ </Button>
80
115
  {/if}
81
116
  {#if onDelete}
82
- <Button
83
- variant="ghost"
84
- size="sm"
85
- class="text-white border border-white/20 hover:bg-white/10 hover:text-white"
86
- onclick={onDelete}
87
- >
88
- <Trash class="mr-1.5 size-3.5" />
89
- {t.delete}
90
- </Button>
117
+ <Button
118
+ variant="ghost"
119
+ size="sm"
120
+ class="text-white border border-white/20 hover:bg-white/10 hover:text-white"
121
+ onclick={onDelete}
122
+ >
123
+ <Trash class="mr-1.5 size-3.5" />
124
+ {t.delete}
125
+ </Button>
126
+ {/if}
127
+ {#if actions}
128
+ {@render actions()}
91
129
  {/if}
92
130
 
93
131
  <button
132
+ type="button"
94
133
  class="ml-1 rounded-md p-1 text-white/60 hover:bg-white/10 hover:text-white"
95
134
  onclick={onClear}
96
- aria-label="Clear selection"
135
+ aria-label={t.clearSelection}
97
136
  >
98
137
  <X class="size-4" />
99
138
  </button>
100
139
  </div>
101
140
  </div>
141
+ <div aria-live="polite" aria-atomic="true" class="sr-only">
142
+ {t.selected(selectedCount)}
143
+ </div>
102
144
  {/if}
@@ -1,9 +1,11 @@
1
+ import { type Snippet } from 'svelte';
1
2
  type Props = {
2
3
  selectedCount: number;
3
- onArchive: () => void;
4
+ onArchive?: () => void;
4
5
  onDelete?: () => void;
5
6
  onClear: () => void;
6
7
  onRestore?: () => void;
8
+ actions?: Snippet;
7
9
  };
8
10
  declare const BulkActionsBar: import("svelte").Component<Props, {}, "">;
9
11
  type BulkActionsBar = ReturnType<typeof BulkActionsBar>;