includio-cms 0.25.0 → 0.27.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 (411) hide show
  1. package/API.md +97 -4
  2. package/CHANGELOG.md +118 -0
  3. package/DOCS.md +1 -1
  4. package/README.md +2 -0
  5. package/ROADMAP.md +14 -0
  6. package/dist/admin/auth-client.d.ts +42 -42
  7. package/dist/admin/client/account/lang.d.ts +1 -0
  8. package/dist/admin/client/account/lang.js +4 -2
  9. package/dist/admin/client/account/profile-section.svelte +2 -2
  10. package/dist/admin/client/account/security-section.svelte +27 -4
  11. package/dist/admin/client/account/sessions-section.svelte +1 -1
  12. package/dist/admin/client/admin/admin-after-login-layout-content.svelte +1 -1
  13. package/dist/admin/client/admin/admin-layout.svelte +12 -2
  14. package/dist/admin/client/admin/admin-layout.svelte.d.ts +2 -1
  15. package/dist/admin/client/admin/dashboard-page.svelte +34 -10
  16. package/dist/admin/client/collection/bulk-actions-bar.svelte +86 -44
  17. package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +3 -1
  18. package/dist/admin/client/collection/collection-entries.svelte +52 -36
  19. package/dist/admin/client/collection/collection-entries.svelte.d.ts +3 -0
  20. package/dist/admin/client/collection/collection.svelte +28 -14
  21. package/dist/admin/client/collection/collection.svelte.d.ts +3 -0
  22. package/dist/admin/client/collection/data-table.svelte +240 -130
  23. package/dist/admin/client/collection/data-table.svelte.d.ts +9 -0
  24. package/dist/admin/client/collection/date-cell.svelte +4 -4
  25. package/dist/admin/client/collection/row-actions.svelte +2 -1
  26. package/dist/admin/client/collection/sortable-header.svelte +33 -9
  27. package/dist/admin/client/collection/state-display.svelte +102 -0
  28. package/dist/admin/client/collection/state-display.svelte.d.ts +12 -0
  29. package/dist/admin/client/collection/status-badge.svelte +99 -11
  30. package/dist/admin/client/collection/status-badge.svelte.d.ts +15 -1
  31. package/dist/admin/client/collection/table-pagination.svelte +21 -6
  32. package/dist/admin/client/collection/table-toolbar.svelte +105 -80
  33. package/dist/admin/client/collection/table-toolbar.svelte.d.ts +11 -8
  34. package/dist/admin/client/entry/entry-form.svelte +36 -11
  35. package/dist/admin/client/entry/entry-form.svelte.d.ts +1 -0
  36. package/dist/admin/client/entry/entry-header.svelte +22 -15
  37. package/dist/admin/client/entry/entry-header.svelte.d.ts +1 -0
  38. package/dist/admin/client/entry/entry.svelte +269 -165
  39. package/dist/admin/client/entry/header/a11y-header-badge.svelte +47 -0
  40. package/dist/admin/client/entry/header/a11y-header-badge.svelte.d.ts +8 -0
  41. package/dist/admin/client/entry/header/publish-panel.svelte +69 -13
  42. package/dist/admin/client/entry/header/save-indicator.svelte +57 -28
  43. package/dist/admin/client/entry/header/save-indicator.svelte.d.ts +1 -0
  44. package/dist/admin/client/entry/header/status-badge.svelte +60 -15
  45. package/dist/admin/client/entry/header/status-badge.svelte.d.ts +1 -2
  46. package/dist/admin/client/entry/header/version-history-sheet.svelte +1 -1
  47. package/dist/admin/client/entry/hybrid/hybrid-layout.svelte +74 -23
  48. package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +1 -1
  49. package/dist/admin/client/entry/utils.d.ts +14 -0
  50. package/dist/admin/client/entry/utils.js +28 -0
  51. package/dist/admin/client/form/form-submission/form-submission.svelte +2 -2
  52. package/dist/admin/client/form/form-submissions.svelte +143 -194
  53. package/dist/admin/client/form/form-submissions.svelte.d.ts +2 -0
  54. package/dist/admin/client/login/lang.d.ts +3 -0
  55. package/dist/admin/client/login/lang.js +10 -4
  56. package/dist/admin/client/login/login-form.svelte +8 -1
  57. package/dist/admin/client/login/reset-password-page.svelte +24 -3
  58. package/dist/admin/client/login/schema.d.ts +14 -2
  59. package/dist/admin/client/login/schema.js +19 -8
  60. package/dist/admin/client/maintenance/maintenance-page.svelte +16 -17
  61. package/dist/admin/client/media/media-page.svelte +1 -1
  62. package/dist/admin/client/shop/coupon-edit-page.svelte +117 -13
  63. package/dist/admin/client/shop/coupon-form.svelte +282 -138
  64. package/dist/admin/client/shop/coupon-form.svelte.d.ts +1 -9
  65. package/dist/admin/client/shop/coupon-new-page.svelte +40 -10
  66. package/dist/admin/client/shop/coupon-new-page.svelte.d.ts +2 -17
  67. package/dist/admin/client/shop/coupon-schema.d.ts +28 -0
  68. package/dist/admin/client/shop/coupon-schema.js +53 -0
  69. package/dist/admin/client/shop/coupons-list-page.svelte +262 -118
  70. package/dist/admin/client/shop/coupons-list-page.svelte.d.ts +16 -1
  71. package/dist/admin/client/shop/refund-dialog.svelte +37 -1
  72. package/dist/admin/client/shop/refund-dialog.svelte.d.ts +3 -0
  73. package/dist/admin/client/shop/shipping-method-edit-page.svelte +108 -59
  74. package/dist/admin/client/shop/shipping-method-form.svelte +36 -9
  75. package/dist/admin/client/shop/shipping-method-new-page.svelte +44 -13
  76. package/dist/admin/client/shop/shipping-methods-list-page.svelte +101 -59
  77. package/dist/admin/client/shop/shop-order-detail-page.svelte +220 -84
  78. package/dist/admin/client/shop/shop-orders-list-page.svelte +302 -152
  79. package/dist/admin/client/shop/shop-orders-list-page.svelte.d.ts +18 -1
  80. package/dist/admin/client/shop/shop-products-list-page.svelte +355 -118
  81. package/dist/admin/client/shop/shop-products-list-page.svelte.d.ts +19 -1
  82. package/dist/admin/client/users/accept-invite-page.svelte +24 -3
  83. package/dist/admin/client/users/create-user-dialog.svelte +3 -8
  84. package/dist/admin/client/users/lang.d.ts +2 -0
  85. package/dist/admin/client/users/lang.js +4 -0
  86. package/dist/admin/client/users/pending-invitations.svelte +2 -9
  87. package/dist/admin/client/users/user-name-cell.svelte +20 -0
  88. package/dist/admin/client/users/user-name-cell.svelte.d.ts +9 -0
  89. package/dist/admin/client/users/user-role-badge.svelte +16 -0
  90. package/dist/admin/client/users/user-role-badge.svelte.d.ts +7 -0
  91. package/dist/admin/client/users/user-row-actions.svelte +72 -0
  92. package/dist/admin/client/users/user-row-actions.svelte.d.ts +20 -0
  93. package/dist/admin/client/users/user-sessions-sheet.svelte +2 -11
  94. package/dist/admin/client/users/users-page.svelte +283 -497
  95. package/dist/admin/client/users/users-page.svelte.d.ts +12 -1
  96. package/dist/admin/components/dashboard/form-submissions-widget.svelte +59 -74
  97. package/dist/admin/components/dashboard/recent-activity.svelte +17 -5
  98. package/dist/admin/components/dashboard/recent-entries.svelte +19 -7
  99. package/dist/admin/components/dialogs/confirmation-dialog.svelte +105 -0
  100. package/dist/admin/components/dialogs/confirmation-dialog.svelte.d.ts +13 -0
  101. package/dist/admin/components/fields/block-picker-modal.svelte +6 -0
  102. package/dist/admin/components/fields/blocks-field.svelte +46 -1
  103. package/dist/admin/components/fields/boolean-field.svelte +1 -1
  104. package/dist/admin/components/fields/field-renderer.svelte +29 -22
  105. package/dist/admin/components/fields/file-field.svelte +344 -30
  106. package/dist/admin/components/fields/icon-field.svelte +86 -0
  107. package/dist/admin/components/fields/icon-field.svelte.d.ts +8 -0
  108. package/dist/admin/components/fields/icon-picker-dialog.svelte +174 -0
  109. package/dist/admin/components/fields/icon-picker-dialog.svelte.d.ts +11 -0
  110. package/dist/admin/components/fields/media-field.svelte +16 -2
  111. package/dist/admin/components/fields/object-field.svelte +27 -7
  112. package/dist/admin/components/fields/radio-field.svelte +22 -0
  113. package/dist/admin/components/fields/relation-field.svelte +123 -97
  114. package/dist/admin/components/fields/relation-picker-dialog.svelte +2 -2
  115. package/dist/admin/components/fields/seo-field.svelte +60 -30
  116. package/dist/admin/components/fields/shop-field.svelte +219 -24
  117. package/dist/admin/components/fields/simple-array-field.svelte +321 -151
  118. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +3 -0
  119. package/dist/admin/components/fields/slug-field.svelte +146 -21
  120. package/dist/admin/components/fields/text-field-wrapper.svelte +37 -20
  121. package/dist/admin/components/fields/text-field.svelte +7 -2
  122. package/dist/admin/components/fields/url-field-wrapper.svelte +10 -0
  123. package/dist/admin/components/fields/url-field.svelte +36 -23
  124. package/dist/admin/components/forms/form-error-summary.svelte +143 -0
  125. package/dist/admin/components/forms/form-error-summary.svelte.d.ts +27 -0
  126. package/dist/admin/components/layout/app-sidebar.svelte +7 -2
  127. package/dist/admin/components/layout/detail-page-shell.svelte +71 -0
  128. package/dist/admin/components/layout/detail-page-shell.svelte.d.ts +24 -0
  129. package/dist/admin/components/layout/lang.d.ts +5 -0
  130. package/dist/admin/components/layout/lang.js +10 -0
  131. package/dist/admin/components/layout/layout-renderer.svelte +71 -2
  132. package/dist/admin/components/layout/layout-renderer.svelte.d.ts +1 -0
  133. package/dist/admin/components/layout/layout-tabs.svelte +173 -0
  134. package/dist/admin/components/layout/layout-tabs.svelte.d.ts +24 -0
  135. package/dist/admin/components/layout/nav-breadcrumbs.svelte +25 -7
  136. package/dist/admin/components/layout/nav-collections.svelte +23 -36
  137. package/dist/admin/components/layout/nav-forms.svelte +19 -35
  138. package/dist/admin/components/layout/nav-main.svelte +3 -28
  139. package/dist/admin/components/layout/nav-search.svelte +70 -2
  140. package/dist/admin/components/layout/nav-section.svelte +77 -0
  141. package/dist/admin/components/layout/nav-section.svelte.d.ts +22 -0
  142. package/dist/admin/components/layout/nav-shop.svelte +3 -27
  143. package/dist/admin/components/layout/nav-singletons.svelte +16 -28
  144. package/dist/admin/components/layout/page-header.stories.svelte +93 -0
  145. package/dist/admin/components/layout/page-header.stories.svelte.d.ts +27 -0
  146. package/dist/admin/components/layout/page-header.svelte +68 -0
  147. package/dist/admin/components/layout/page-header.svelte.d.ts +17 -0
  148. package/dist/admin/components/layout/site-header.svelte +9 -0
  149. package/dist/admin/components/layout/site-header.svelte.d.ts +2 -17
  150. package/dist/admin/components/media/file/file-name-input.svelte +6 -2
  151. package/dist/admin/components/media/file/file-preview.svelte +130 -17
  152. package/dist/admin/components/media/file-upload.svelte +16 -7
  153. package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
  154. package/dist/admin/components/media/files-list.svelte +153 -53
  155. package/dist/admin/components/media/files-list.svelte.d.ts +1 -0
  156. package/dist/admin/components/media/media-library.svelte +577 -198
  157. package/dist/admin/components/media/media-library.svelte.d.ts +4 -0
  158. package/dist/admin/components/media/media-selector.svelte +4 -2
  159. package/dist/admin/components/media/media-selector.svelte.d.ts +1 -0
  160. package/dist/admin/components/media/tag-sidebar.svelte +4 -4
  161. package/dist/admin/components/tiptap/FigureNodeView.svelte +10 -0
  162. package/dist/admin/components/tiptap/bubble-menu.svelte +104 -0
  163. package/dist/admin/components/tiptap/bubble-menu.svelte.d.ts +19 -0
  164. package/dist/admin/components/tiptap/content-editor.svelte +28 -24
  165. package/dist/admin/components/tiptap/editor-toolbar.svelte +7 -7
  166. package/dist/admin/components/tiptap/extensions.js +5 -1
  167. package/dist/admin/components/tiptap/image-dialog.svelte +5 -1
  168. package/dist/admin/components/tiptap/link-dialog.svelte +2 -0
  169. package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -20
  170. package/dist/admin/components/tiptap/video-dialog.svelte +1 -1
  171. package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte +109 -0
  172. package/dist/admin/components/variant-form/VariantAttributeRenderer.svelte.d.ts +9 -0
  173. package/dist/admin/helpers/build-icon-set-map.d.ts +8 -0
  174. package/dist/admin/helpers/build-icon-set-map.js +16 -0
  175. package/dist/admin/helpers/index.d.ts +2 -0
  176. package/dist/admin/helpers/index.js +2 -0
  177. package/dist/admin/i18n/errors.d.ts +140 -0
  178. package/dist/admin/i18n/errors.js +151 -0
  179. package/dist/admin/remote/entry.remote.d.ts +59 -4
  180. package/dist/admin/remote/entry.remote.js +239 -62
  181. package/dist/admin/remote/shop.remote.d.ts +87 -48
  182. package/dist/admin/remote/shop.remote.js +70 -8
  183. package/dist/admin/shared/password-generate.d.ts +6 -0
  184. package/dist/admin/shared/password-generate.js +40 -0
  185. package/dist/admin/shared/password-schema.d.ts +6 -0
  186. package/dist/admin/shared/password-schema.js +10 -3
  187. package/dist/admin/state/icon-sets.svelte.d.ts +9 -0
  188. package/dist/admin/state/icon-sets.svelte.js +20 -0
  189. package/dist/admin/styles/admin.css +23 -6
  190. package/dist/admin/styles/tokens.md +244 -0
  191. package/dist/admin/utils/accordionActivation.d.ts +13 -0
  192. package/dist/admin/utils/accordionActivation.js +35 -0
  193. package/dist/admin/utils/entryLabel.d.ts +23 -0
  194. package/dist/admin/utils/entryLabel.js +51 -12
  195. package/dist/admin/utils/field-a11y.d.ts +29 -0
  196. package/dist/admin/utils/field-a11y.js +23 -0
  197. package/dist/admin/utils/fieldPathElement.d.ts +9 -0
  198. package/dist/admin/utils/fieldPathElement.js +18 -0
  199. package/dist/admin/utils/fileDisplay.d.ts +10 -0
  200. package/dist/admin/utils/fileDisplay.js +26 -0
  201. package/dist/admin/utils/flattenFormErrors.d.ts +19 -0
  202. package/dist/admin/utils/flattenFormErrors.js +102 -0
  203. package/dist/admin/utils/formatters.d.ts +12 -0
  204. package/dist/admin/utils/{formatDate.js → formatters.js} +23 -2
  205. package/dist/admin/utils/scrollWithin.d.ts +9 -0
  206. package/dist/admin/utils/scrollWithin.js +32 -0
  207. package/dist/admin/utils/tabActivation.d.ts +12 -0
  208. package/dist/admin/utils/tabActivation.js +24 -0
  209. package/dist/cli/scaffold/admin.js +2 -2
  210. package/dist/cms/runtime/schema.d.ts +1 -0
  211. package/dist/cms/runtime/schema.js +1 -0
  212. package/dist/cms/runtime/types.d.ts +80 -7
  213. package/dist/components/ui/accordion/accordion-content.svelte +17 -3
  214. package/dist/components/ui/accordion/accordion.stories.svelte +21 -1
  215. package/dist/components/ui/alert/alert.stories.svelte +14 -0
  216. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte +45 -0
  217. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte.d.ts +27 -0
  218. package/dist/components/ui/avatar/avatar.stories.svelte +27 -0
  219. package/dist/components/ui/badge/badge.stories.svelte +15 -0
  220. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +47 -0
  221. package/dist/components/ui/breadcrumb/breadcrumb.svelte +1 -1
  222. package/dist/components/ui/button/button.stories.svelte +53 -6
  223. package/dist/components/ui/button/button.svelte +39 -5
  224. package/dist/components/ui/button/button.svelte.d.ts +4 -0
  225. package/dist/components/ui/button-group/button-group.stories.svelte +44 -0
  226. package/dist/components/ui/button-group/button-group.stories.svelte.d.ts +27 -0
  227. package/dist/components/ui/calendar/calendar.stories.svelte +36 -0
  228. package/dist/components/ui/calendar/calendar.stories.svelte.d.ts +27 -0
  229. package/dist/components/ui/card/card.stories.svelte +7 -0
  230. package/dist/components/ui/carousel/carousel.stories.svelte +43 -0
  231. package/dist/components/ui/carousel/carousel.stories.svelte.d.ts +27 -0
  232. package/dist/components/ui/checkbox/checkbox.stories.svelte +67 -0
  233. package/dist/components/ui/checkbox/checkbox.stories.svelte.d.ts +27 -0
  234. package/dist/components/ui/checkbox/checkbox.svelte +1 -1
  235. package/dist/components/ui/command/command.stories.svelte +18 -0
  236. package/dist/components/ui/data-table/data-table.stories.svelte +61 -0
  237. package/dist/components/ui/data-table/data-table.stories.svelte.d.ts +18 -0
  238. package/dist/components/ui/dialog/dialog-content.svelte +5 -0
  239. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +2 -0
  240. package/dist/components/ui/dialog/dialog.stories.svelte +35 -0
  241. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte +74 -0
  242. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte.d.ts +27 -0
  243. package/dist/components/ui/field/field-context.svelte.d.ts +22 -0
  244. package/dist/components/ui/field/field-context.svelte.js +9 -0
  245. package/dist/components/ui/field/field-control.svelte +18 -0
  246. package/dist/components/ui/field/field-control.svelte.d.ts +8 -0
  247. package/dist/components/ui/field/field-description.svelte +12 -0
  248. package/dist/components/ui/field/field-error.svelte +14 -6
  249. package/dist/components/ui/field/field-label.svelte +10 -0
  250. package/dist/components/ui/field/field.stories.svelte +95 -9
  251. package/dist/components/ui/field/field.svelte +57 -0
  252. package/dist/components/ui/field/field.svelte.d.ts +2 -0
  253. package/dist/components/ui/field/index.d.ts +3 -1
  254. package/dist/components/ui/field/index.js +4 -2
  255. package/dist/components/ui/form/form-field-errors.svelte +1 -1
  256. package/dist/components/ui/form/form.stories.svelte +25 -0
  257. package/dist/components/ui/form/form.stories.svelte.d.ts +26 -0
  258. package/dist/components/ui/input/input.stories.svelte +26 -0
  259. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  260. package/dist/components/ui/input-group/input-group.stories.svelte +43 -0
  261. package/dist/components/ui/input-group/input-group.stories.svelte.d.ts +27 -0
  262. package/dist/components/ui/item/item.stories.svelte +61 -0
  263. package/dist/components/ui/item/item.stories.svelte.d.ts +27 -0
  264. package/dist/components/ui/label/label.stories.svelte +7 -0
  265. package/dist/components/ui/live-region/index.d.ts +1 -0
  266. package/dist/components/ui/live-region/index.js +1 -0
  267. package/dist/components/ui/live-region/live-region-demo.svelte +32 -0
  268. package/dist/components/ui/live-region/live-region-demo.svelte.d.ts +7 -0
  269. package/dist/components/ui/live-region/live-region.stories.svelte +23 -0
  270. package/dist/components/ui/live-region/live-region.stories.svelte.d.ts +26 -0
  271. package/dist/components/ui/live-region/live-region.svelte +12 -0
  272. package/dist/components/ui/live-region/live-region.svelte.d.ts +8 -0
  273. package/dist/components/ui/popover/popover.stories.svelte +34 -0
  274. package/dist/components/ui/radio-group/radio-group.stories.svelte +58 -0
  275. package/dist/components/ui/radio-group/radio-group.stories.svelte.d.ts +27 -0
  276. package/dist/components/ui/resizable/resizable.stories.svelte +56 -0
  277. package/dist/components/ui/resizable/resizable.stories.svelte.d.ts +27 -0
  278. package/dist/components/ui/select/select.stories.svelte +49 -0
  279. package/dist/components/ui/separator/separator.stories.svelte +18 -0
  280. package/dist/components/ui/sheet/sheet.stories.svelte +34 -0
  281. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  282. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +1 -0
  283. package/dist/components/ui/sidebar/sidebar-trigger.svelte +1 -1
  284. package/dist/components/ui/sidebar/sidebar.stories.svelte +72 -0
  285. package/dist/components/ui/sidebar/sidebar.stories.svelte.d.ts +27 -0
  286. package/dist/components/ui/skeleton/skeleton.stories.svelte +39 -0
  287. package/dist/components/ui/skeleton/skeleton.stories.svelte.d.ts +27 -0
  288. package/dist/components/ui/skeleton/skeleton.svelte +6 -0
  289. package/dist/components/ui/sonner/index.d.ts +1 -1
  290. package/dist/components/ui/sonner/index.js +1 -1
  291. package/dist/components/ui/sonner/sonner.stories.svelte +7 -0
  292. package/dist/components/ui/sonner/sonner.svelte +17 -1
  293. package/dist/components/ui/sonner/sonner.svelte.d.ts +6 -0
  294. package/dist/components/ui/spinner/spinner.stories.svelte +30 -0
  295. package/dist/components/ui/spinner/spinner.stories.svelte.d.ts +27 -0
  296. package/dist/components/ui/switch/switch.stories.svelte +56 -0
  297. package/dist/components/ui/switch/switch.stories.svelte.d.ts +27 -0
  298. package/dist/components/ui/table/table-cell.svelte +1 -1
  299. package/dist/components/ui/table/table-head.svelte +1 -1
  300. package/dist/components/ui/table/table.stories.svelte +68 -0
  301. package/dist/components/ui/table/table.stories.svelte.d.ts +27 -0
  302. package/dist/components/ui/table/table.svelte +1 -1
  303. package/dist/components/ui/tabs/tabs.stories.svelte +48 -0
  304. package/dist/components/ui/tabs/tabs.stories.svelte.d.ts +27 -0
  305. package/dist/components/ui/textarea/textarea.stories.svelte +21 -0
  306. package/dist/components/ui/toggle/toggle.stories.svelte +23 -0
  307. package/dist/components/ui/toggle-group/toggle-group.stories.svelte +43 -0
  308. package/dist/components/ui/tooltip/tooltip.stories.svelte +46 -6
  309. package/dist/core/cms.d.ts +11 -2
  310. package/dist/core/cms.js +29 -0
  311. package/dist/core/fields/fieldSchemaToTs.d.ts +7 -0
  312. package/dist/core/fields/fieldSchemaToTs.js +241 -90
  313. package/dist/core/fields/layoutUtils.d.ts +4 -1
  314. package/dist/core/fields/layoutUtils.js +41 -4
  315. package/dist/core/fields/resolveSeo.d.ts +70 -0
  316. package/dist/core/fields/resolveSeo.js +88 -0
  317. package/dist/core/fields/seoFieldDescriptor.d.ts +43 -0
  318. package/dist/core/fields/seoFieldDescriptor.js +74 -0
  319. package/dist/core/fields/slugPath.d.ts +13 -0
  320. package/dist/core/fields/slugPath.js +32 -0
  321. package/dist/core/fields/urlUtils.d.ts +8 -0
  322. package/dist/core/fields/urlUtils.js +27 -0
  323. package/dist/core/index.d.ts +1 -0
  324. package/dist/core/index.js +1 -0
  325. package/dist/core/server/entries/operations/create.js +13 -0
  326. package/dist/core/server/entries/operations/get.d.ts +7 -0
  327. package/dist/core/server/entries/operations/get.js +10 -6
  328. package/dist/core/server/entries/operations/slugUniqueness.d.ts +37 -0
  329. package/dist/core/server/entries/operations/slugUniqueness.js +116 -0
  330. package/dist/core/server/entries/operations/update.d.ts +6 -1
  331. package/dist/core/server/entries/operations/update.js +24 -1
  332. package/dist/core/server/fields/slugResolver.d.ts +3 -13
  333. package/dist/core/server/fields/slugResolver.js +8 -37
  334. package/dist/core/server/generator/fields.d.ts +2 -0
  335. package/dist/core/server/generator/fields.js +44 -18
  336. package/dist/core/server/generator/formFields.js +2 -1
  337. package/dist/core/server/generator/generator.js +6 -5
  338. package/dist/core/server/generator/utils.d.ts +1 -0
  339. package/dist/core/server/generator/utils.js +4 -0
  340. package/dist/db-postgres/schema/shop/order.d.ts +37 -1
  341. package/dist/db-postgres/schema/shop/order.js +3 -1
  342. package/dist/db-postgres/schema/shop/payment.d.ts +20 -0
  343. package/dist/db-postgres/schema/shop/payment.js +4 -1
  344. package/dist/db-postgres/schema/shop/product.d.ts +20 -0
  345. package/dist/db-postgres/schema/shop/product.js +3 -1
  346. package/dist/db-postgres/schema/shop/productVariant.d.ts +12 -2
  347. package/dist/db-postgres/schema/shop/productVariant.js +22 -0
  348. package/dist/shop/cart/types.d.ts +1 -0
  349. package/dist/shop/client/index.d.ts +54 -0
  350. package/dist/shop/client/index.js +5 -1
  351. package/dist/shop/expiry.d.ts +35 -0
  352. package/dist/shop/expiry.js +68 -0
  353. package/dist/shop/http/balance-handler.d.ts +20 -0
  354. package/dist/shop/http/balance-handler.js +91 -0
  355. package/dist/shop/http/cart-handler.js +19 -0
  356. package/dist/shop/http/checkout-handler.js +19 -1
  357. package/dist/shop/http/index.d.ts +2 -0
  358. package/dist/shop/http/index.js +2 -0
  359. package/dist/shop/http/upcoming-handler.d.ts +16 -0
  360. package/dist/shop/http/upcoming-handler.js +65 -0
  361. package/dist/shop/http/webhook-handler.js +46 -9
  362. package/dist/shop/index.d.ts +4 -1
  363. package/dist/shop/index.js +7 -1
  364. package/dist/shop/server/balance-payment.d.ts +40 -0
  365. package/dist/shop/server/balance-payment.js +140 -0
  366. package/dist/shop/server/cart-hydrate.js +2 -0
  367. package/dist/shop/server/init.d.ts +14 -0
  368. package/dist/shop/server/init.js +35 -0
  369. package/dist/shop/server/orders.d.ts +35 -0
  370. package/dist/shop/server/orders.js +155 -2
  371. package/dist/shop/server/payment-policy.d.ts +35 -0
  372. package/dist/shop/server/payment-policy.js +55 -0
  373. package/dist/shop/server/payments.d.ts +29 -0
  374. package/dist/shop/server/payments.js +64 -0
  375. package/dist/shop/server/populate.d.ts +1 -1
  376. package/dist/shop/server/refund.d.ts +17 -12
  377. package/dist/shop/server/refund.js +96 -13
  378. package/dist/shop/server/shop-data.d.ts +6 -1
  379. package/dist/shop/server/shop-data.js +44 -7
  380. package/dist/shop/template.d.ts +13 -0
  381. package/dist/shop/template.js +98 -0
  382. package/dist/shop/types.d.ts +142 -1
  383. package/dist/shop/variant-attributes.d.ts +28 -0
  384. package/dist/shop/variant-attributes.js +69 -0
  385. package/dist/sveltekit/server/handle.js +17 -0
  386. package/dist/sveltekit/server/index.d.ts +1 -0
  387. package/dist/sveltekit/server/index.js +2 -0
  388. package/dist/types/cms.d.ts +4 -3
  389. package/dist/types/cms.schema.d.ts +1 -1
  390. package/dist/types/cms.schema.js +13 -2
  391. package/dist/types/fields.d.ts +56 -2
  392. package/dist/types/index.d.ts +2 -2
  393. package/dist/types/index.js +1 -1
  394. package/dist/types/layout.d.ts +35 -2
  395. package/dist/types/plugins.d.ts +40 -0
  396. package/dist/types/plugins.js +4 -1
  397. package/dist/updates/0.26.0/index.d.ts +2 -0
  398. package/dist/updates/0.26.0/index.js +51 -0
  399. package/dist/updates/0.26.1/index.d.ts +2 -0
  400. package/dist/updates/0.26.1/index.js +19 -0
  401. package/dist/updates/0.27.0/index.d.ts +2 -0
  402. package/dist/updates/0.27.0/index.js +50 -0
  403. package/dist/updates/index.js +7 -1
  404. package/package.json +29 -7
  405. package/dist/admin/client/collection/empty-state.svelte +0 -28
  406. package/dist/admin/client/collection/empty-state.svelte.d.ts +0 -9
  407. package/dist/admin/client/form/submission-status-badge.svelte +0 -41
  408. package/dist/admin/client/form/submission-status-badge.svelte.d.ts +0 -7
  409. package/dist/admin/components/media/file-preview.svelte +0 -51
  410. package/dist/admin/components/media/file-preview.svelte.d.ts +0 -6
  411. package/dist/admin/utils/formatDate.d.ts +0 -5
package/API.md CHANGED
@@ -1,8 +1,8 @@
1
- # includio-cms — Public API v0.25.0
1
+ # includio-cms — Public API v0.27.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: **448** · Experimental: **4**
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
 
@@ -71,14 +75,18 @@ Tags:
71
75
  - `interface FormSubmission`
72
76
  - `interface FormTextareaField`
73
77
  - `interface FormTextField`
78
+ - `interface IconDefinition`
79
+ - `interface IconField`
74
80
  - `type IconName = keyof typeof iconMap`
81
+ - `interface IconSetPlugin`
75
82
  - `interface ImageFieldData`
76
83
  - `interface ImageFieldStyle`
77
84
  - `interface ImageStyle`
85
+ - `isIconSetPlugin(p: Plugin): p is IconSetPlugin` — Type guard for {@link IconSetPlugin}.
78
86
  - `type Language = 'en' | 'pl'`
79
87
  - `type Layout = LayoutPreset | LayoutNode[]`
80
- - `type LayoutNode = SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode`
81
- - `type LayoutNodeType = 'section' | 'columns' | 'card' | 'accordion' | 'stack'`
88
+ - `type LayoutNode = | SectionNode | ColumnsNode | CardNode | AccordionNode | StackNode | TabsNode | TabNode`
89
+ - `type LayoutNodeType = | 'section' | 'columns' | 'card' | 'accordion' | 'stack' | 'tabs' | 'tab'`
82
90
  - `type LayoutPreset = | 'sidebar-right' | 'two-column' | { preset: 'sidebar-right'; sidebar: string[] } | { preset: 'tw...`
83
91
  - `type Localized = Partial<Record<InterfaceLanguage, string>> | string`
84
92
  - `interface MediaField`
@@ -89,6 +97,7 @@ Tags:
89
97
  - `interface NumberField`
90
98
  - `interface ObjectField`
91
99
  - `type ObjectFieldData = { _id?: string; _slug?: string; } & Record<string, unknown>`
100
+ - `type Plugin = PluginConfig | IconSetPlugin`
92
101
  - `interface RadioField`
93
102
  - `interface RelationField`
94
103
  - `type RelationFieldData = string | string[]`
@@ -109,6 +118,8 @@ Tags:
109
118
  - `interface SlugField`
110
119
  - `interface StackNode`
111
120
  - `interface StructuredContentDoc`
121
+ - `interface TabNode` — A single tab. Only valid as a direct child of {@link TabsNode}.
122
+ - `interface TabsNode` — Tab strip. Renders an accessible tablist; each child `tab` becomes a panel.
112
123
  - `interface TextField`
113
124
  - `interface TypographyConfig`
114
125
  - `interface UrlField`
@@ -126,6 +137,7 @@ Tags:
126
137
  - `const AdminLayout: LegacyComponentType`
127
138
  - `const Badge: LegacyComponentType`
128
139
  - `buildCustomFieldsMap(...plugins: PluginConfig[]): Map<string, CustomFieldDefinition>` — Build a Map<fieldType, CustomFieldDefinition> from plugin configs.
140
+ - `buildIconSetMap(...plugins: IconSetPlugin[]): Map<string, IconSetPlugin>` — Build a Map<slug, IconSetPlugin> from icon-set plugin instances.
129
141
  - `const Button: LegacyComponentType`
130
142
  - `Card`
131
143
  - `const CollectionPage: LegacyComponentType`
@@ -137,6 +149,7 @@ Tags:
137
149
  - `const FormSubmissionPage: LegacyComponentType`
138
150
  - `getContentLanguage`
139
151
  - `getCustomFields(): Map<string, CustomFieldDefinition>`
152
+ - `getIconSets(): Map<string, IconSetPlugin>`
140
153
  - `getLocalizedLabel(label: Localized | undefined, lang: InterfaceLanguage): string`
141
154
  - `getRemotes(): typeof remotes`
142
155
  - `const Input: LegacyComponentType`
@@ -146,6 +159,7 @@ Tags:
146
159
  - `const MediaPage: LegacyComponentType`
147
160
  - `const MediaSelector: LegacyComponentType`
148
161
  - `const ResetPasswordPage: LegacyComponentType`
162
+ - `resolveIconSet(slug?: string): IconSetPlugin | null` — Resolve a single icon set: explicit `slug` (from {@link IconField.set}) takes
149
163
  - `const Separator: LegacyComponentType`
150
164
  - `const ShippingMethodEditPage: LegacyComponentType`
151
165
  - `const ShippingMethodNewPage: LegacyComponentType`
@@ -187,6 +201,7 @@ Tags:
187
201
  - `const exportOrdersCsv: <inferred>`
188
202
  - `const findMediaReferences: <inferred>`
189
203
  - `const generateAltText: <inferred>`
204
+ - `const generateBalanceLinkForOrder: <inferred>`
190
205
  - `const getAltOverview: <inferred>`
191
206
  - `const getCollection: <inferred>`
192
207
  - `const getCollections: <inferred>`
@@ -233,6 +248,8 @@ Tags:
233
248
  - `const reorderEntriesCommand: <inferred>`
234
249
  - `const reorderShippingMethodsCmd: <inferred>`
235
250
  - `const resendOrderEmailCmd: <inferred>`
251
+ - `const searchEntries: <inferred>`
252
+ - `const searchLinkableEntries: <inferred>`
236
253
  - `const setFocalPoint: <inferred>`
237
254
  - `const setMediaFileAlt: <inferred>`
238
255
  - `const setMediaFileTags: <inferred>`
@@ -281,6 +298,7 @@ Tags:
281
298
  - `cmsLayoutLoad(event: RequestEvent): <inferred>` — Returns `cmsContext` from `event.locals` for use in a SvelteKit layout
282
299
  - `countEntries(opts: CountEntriesOptions): Promise<number>` — Count entries matching the same filters as `resolveEntries`, without
283
300
  - `type CountEntriesOptions = Omit< ResolveEntriesOptions, 'limit' | 'offset' | 'populate' | 'orderBy' | 'dataOrderBy' >`
301
+ - `createAdminApiHandler(options?: AdminApiOptions): <inferred>`
284
302
  - `const createConsentLog: <inferred>`
285
303
  - `const createFormSubmission: <inferred>`
286
304
  - `createRestApiHandler(): <inferred>` — REST API handler factory. Returns `{ GET, POST, PUT, DELETE }`
@@ -322,6 +340,8 @@ Tags:
322
340
  - `const shopOrderItemsTable: <inferred>`
323
341
  - `const shopOrdersTable: <inferred>`
324
342
  - `const shopOrderStatusHistoryTable: <inferred>`
343
+ - `type ShopPaymentKind = 'full' | 'deposit' | 'balance'`
344
+ - `const shopPaymentKindEnum: <inferred>`
325
345
  - `const shopPaymentsTable: <inferred>`
326
346
  - `type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled'`
327
347
  - `const shopProductsTable: <inferred>`
@@ -336,6 +356,53 @@ Tags:
336
356
  - `const verification: <inferred>`
337
357
  - `const videoStylesTable: <inferred>`
338
358
 
359
+ ### `includio-cms/db-postgres/schema-core`
360
+
361
+ - `const consentLogsTable: <inferred>`
362
+ - `const entriesTable: <inferred>`
363
+ - `const entryVersionsTable: <inferred>`
364
+ - `const formSubmissionsTable: <inferred>`
365
+ - `const imageStylesTable: <inferred>`
366
+ - `const mediaFilesTable: <inferred>`
367
+ - `const mediaFileTagsTable: <inferred>`
368
+ - `const mediaTagsTable: <inferred>`
369
+ - `const videoStylesTable: <inferred>`
370
+
371
+ ### `includio-cms/db-postgres/schema-shop`
372
+
373
+ - `type InpostParcelSize = 'A' | 'B' | 'C'`
374
+ - `type InpostServiceType = | 'inpost_locker_standard' | 'inpost_locker_express' | 'inpost_courier_standard' | 'inpost_courie...`
375
+ - `interface ShippingCarrierConfig`
376
+ - `type ShopCarrierType = 'none' | 'inpost' | string`
377
+ - `const shopCouponRedemptionsTable: <inferred>`
378
+ - `const shopCouponsTable: <inferred>`
379
+ - `type ShopCouponType = 'percent' | 'fixed'`
380
+ - `const shopOrderItemsTable: <inferred>`
381
+ - `const shopOrdersTable: <inferred>`
382
+ - `const shopOrderStatusHistoryTable: <inferred>`
383
+ - `type ShopPaymentKind = 'full' | 'deposit' | 'balance'`
384
+ - `const shopPaymentKindEnum: <inferred>`
385
+ - `const shopPaymentsTable: <inferred>`
386
+ - `type ShopPaymentStatus = 'pending' | 'paid' | 'failed' | 'refunded' | 'cancelled'`
387
+ - `const shopProductsTable: <inferred>`
388
+ - `const shopProductVariantsTable: <inferred>`
389
+ - `const shopRefundsTable: <inferred>`
390
+ - `type ShopRefundStatus = 'pending' | 'succeeded' | 'failed'`
391
+ - `const shopShippingMethodsTable: <inferred>`
392
+ - `const shopStockReservationsTable: <inferred>`
393
+ - `const shopWebhookEventsTable: <inferred>`
394
+
395
+ ### `includio-cms/auth-schema`
396
+
397
+ - `const account: <inferred>`
398
+ - `const accountRelations: <inferred>`
399
+ - `const invitation: <inferred>`
400
+ - `const session: <inferred>`
401
+ - `const sessionRelations: <inferred>`
402
+ - `const user: <inferred>`
403
+ - `const userRelations: <inferred>`
404
+ - `const verification: <inferred>`
405
+
339
406
  ### `includio-cms/shop`
340
407
 
341
408
  - `interface CarrierAdapter`
@@ -344,19 +411,26 @@ Tags:
344
411
  - `interface CouponRef`
345
412
  - `type Currency = 'PLN'`
346
413
  - `defineShop(config: ShopConfig): ResolvedShopConfig`
414
+ - `type DepositAmount = | { type: 'percent'; value: number } | { type: 'amount'; value: number }` — Deposit amount specifier. `percent` charges `floor(base * value / 100)` of
415
+ - `filterUpcoming(variants: T[], config: VariantExpiryConfig | null, now?: Date): T[]` — Return the subset of `variants` that have not yet expired. Order is
347
416
  - `type GeowidgetConfigPreset = 'parcelcollect' | 'parcelsend' | 'parcelcollect247' | string`
348
417
  - `type I18nText = { [lang: string]: string; }`
349
418
  - `inpostAdapter(opts: InpostAdapterOptions): CarrierAdapter`
350
419
  - `interface InpostAdapterOptions`
351
420
  - `type InpostEnvironment = 'production' | 'sandbox'` — InPost Points API — public, no auth required. Used to validate that a parcel
352
421
  - `interface InpostSenderAddress`
422
+ - `interpolateTemplate(template: string, vars: Record<string, unknown>, locale: string): string` — String interpolation engine used by `defineShop({ variantLabel.template })`
423
+ - `class InvalidVariantAttributesError`
424
+ - `isVariantExpired(variant: VariantLike, config: VariantExpiryConfig | null, now: Date = new Date(Date.now())): boolean` — Check whether a variant has expired under the given config. Fail-open by
353
425
  - `manualAdapter(opts: ManualPaymentAdapterOptions = {}): PaymentAdapter` — Manual payment adapter — order goes to awaitingPayment, admin marks as paid later
354
426
  - `interface OrderRef`
355
427
  - `type OrderStatus = | 'new' | 'awaitingPayment' | 'paid' | 'preparing' | 'sent' | 'done' | 'cancelled' | 'paymentReje...`
428
+ - `interface PartialPayment` — Persisted partial-payment summary on `order.partialPayment` when the order
356
429
  - `interface PaymentAdapter`
357
430
  - `interface PaymentCreateContext`
358
431
  - `interface PaymentCreateResult`
359
432
  - `interface PaymentEvent`
433
+ - `type PaymentPolicy = { type: 'full' } | { type: 'deposit'; depositAmount: DepositAmount }` — Per-product payment policy. `full` (default) charges the full order total
360
434
  - `interface PaymentRefundInput`
361
435
  - `interface PaymentRefundResult`
362
436
  - `payuAdapter(opts: PayuAdapterOptions): PaymentAdapter`
@@ -369,6 +443,18 @@ Tags:
369
443
  - `interface ShopFeatures`
370
444
  - `stripeAdapter(opts: StripeAdapterOptions): PaymentAdapter` — Stripe payment adapter (Checkout Session flow).
371
445
  - `interface StripeAdapterOptions`
446
+ - `type VariantAttribute = | VariantAttributeText | VariantAttributeNumber | VariantAttributeDatetime | VariantAttributeSele...` — Schema descriptor for one product-variant attribute (city, startsAt, …).
447
+ - `interface VariantAttributeBoolean`
448
+ - `interface VariantAttributeDatetime`
449
+ - `interface VariantAttributeEntry`
450
+ - `interface VariantAttributeImage`
451
+ - `interface VariantAttributeNumber`
452
+ - `interface VariantAttributeSelect`
453
+ - `interface VariantAttributeSlug`
454
+ - `interface VariantAttributeText`
455
+ - `class VariantExpiredError` — Thrown by `createOrderFromCart` / cart-add HTTP guard when a referenced
456
+ - `interface VariantExpiryConfig` — Opt-in storefront filter that hides variants whose datetime attribute
457
+ - `interface VariantLabelConfig` — Template used to auto-generate `variant.name` from `variantAttributes`.
372
458
 
373
459
  ### `includio-cms/shop/client`
374
460
 
@@ -387,11 +473,13 @@ Tags:
387
473
  - `type OrderState = OrderStateImpl`
388
474
  - `const OrderStatus: LegacyComponentType`
389
475
  - `interface OrderStatusLabels`
476
+ - `interface PayBalanceResult` — Result of `orders.payBalance` — initiates a payment session for the
390
477
  - `interface RefreshPaymentResult`
391
478
  - `interface RetryPaymentResult`
392
479
  - `interface ShippingMethodPublic`
393
480
  - `interface ShopClient` — Headless shop SDK surface returned by `createShopClient()`.
394
481
  - `interface ShopClientOptions` — Options for `createShopClient()`.
482
+ - `interface VariantPublic` — Public-facing variant row returned by `client.products.listUpcoming`.
395
483
 
396
484
  ### `includio-cms/shop/http`
397
485
 
@@ -431,3 +519,8 @@ Tags:
431
519
 
432
520
  - `interface CustomFieldDefinition` — Defines a custom field type contributed by a plugin.
433
521
  - `interface PluginConfig` — CMS plugin configuration — register custom field types and CRUD lifecycle hooks.
522
+
523
+ ### `includio-cms/shop/http`
524
+
525
+ - `createBalanceHandler(): { GET: RequestHandler; POST: RequestHandler }`
526
+ - `createUpcomingVariantsHandler(): { GET: RequestHandler }` — Build a SvelteKit `GET` handler for upcoming variants of a single product.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,124 @@
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.27.0 — 2026-05-29
7
+
8
+ Shop platformowy — Fazy 1 + 2 + 3 + 4 + 5: schema-driven `variantAttributes` (typed `defineShop` schema, Zod walidacja, GIN index helper, ts-gen typed `variant.attributes`) + admin renderer per attribute type + `variantLabel.template` interpolacja z admin auto-prefill nazwy wariantu + `variantExpiry` opt-in (storefront filter, cart/checkout guard, admin "Zakończony" badge) + `paymentPolicy` A-lite (deposit + balance + signed token + refund per kind + admin balance link + per-kind refund dialog). Faza 6 envet pilot (consumer-side end-to-end QA: szkolenia variants + deposit flow + balance link — nie wymaga zmian w core). Post-Faza-5 hot-fixy uwzględnione w tym wydaniu (single release, nie patch): datetime walidator z offsetem, auto-detect deposit kind przy admin manual mark-paid, admin paymentPolicy UI + preserve-on-undefined w upsert. Additive only — żadnych breaking zmian. Plan: `/Users/patryk/.claude/plans/implementacja-ariacms-0-27-partitioned-kahn.md`.
9
+
10
+ ### Added
11
+ - `defineShop({ variantAttributes })` (`includio-cms/shop`) — typed schema dla atrybutów wariantu: `text | number | datetime | select | boolean | image | entry | slug` z polami `{ type, label, required?, indexable?, options?, entryCollection? }`. Zostaje jedno źródło prawdy: napędza Zod walidację, ts-gen typings, GIN index utility oraz renderer admin form.
12
+ - `VariantAttribute` + per-type interfejsy (`VariantAttributeText/Number/Datetime/Select/Boolean/Image/Entry/Slug`) wyeksportowane jako `@public` z `includio-cms/shop`.
13
+ - `InvalidVariantAttributesError` (code `INVALID_VARIANT_ATTRIBUTES`) — rzucany przez `upsertShopData` gdy `variant.attributes` nie pasują do schemy. Eksport publiczny z `includio-cms/shop`.
14
+ - `runtime/types.ts` — pole `shop` w entry typings generuje teraz typed `variant.attributes` (`{ city: string; startsAt: string; online?: boolean; level: 'basic' | 'advanced' }`) zamiast `Record<string, string>` gdy `defineShop` ma `variantAttributes`. Brak `variantAttributes` = poprzednie `Record<string, string> | null` (backwards-compatible).
15
+ - `createVariantAttributeIndexes(attrs)` w `$lib/db-postgres/schema/shop/productVariant.ts` — zwraca `CREATE INDEX IF NOT EXISTS shop_variant_attr_<key>_gin_idx ON shop_product_variants USING gin ((attributes->'<key>'))` DDL per atrybut z `indexable: true`. Wymusza safe SQL identifier dla klucza (`[A-Za-z][A-Za-z0-9_]*`).
16
+ - `applyVariantAttributeIndexes(shop, db)` w `$lib/shop/server/init.ts` — idempotentny serialized applier indeksów GIN. `initCMS()` odpala go automatycznie fire-and-forget gdy shop jest skonfigurowany (zero ręcznych hooków u konsumenta). `cms.shopInitPromise` wystawiony jako `@internal` punkt synchronizacji dla testów.
17
+ - `VariantAttributeRenderer.svelte` (NEW, `$lib/admin/components/variant-form/`) — switch po `attr.type`, deleguje do field components z `$lib/admin/components/fields/` (text/number/datetime/select/boolean) lub renderuje prosty Input dla slug/image/entry (pełny picker UI dla image/entry defer post-1.0).
18
+ - `shop-field.svelte` (admin variant editor) — variant row pokazuje siatkę atrybutów (responsywna 1/2-col) ponad legacy polami (nazwa/SKU/delta/stock) gdy `shopConfig.variantAttributes` ma wpisy. Brak attrs = legacy behavior bez zmian. Hydratacja + save propaguje `variant.attributes` jako `Record<string, unknown>`.
19
+ - `getShopConfig` remote (admin) — response zawiera teraz `variantAttributes` z `ResolvedShopConfig`, dzięki czemu `shop-field` może lokalnie renderować typed atrybuty bez dodatkowego round-tripa.
20
+ - `upsertShopDataForEntry` (admin remote command) — input schema dla `variant.attributes` zluzowany do `z.record(z.string(), z.unknown())`; typed shape egzekwowany serwerowo przez `validateVariantAttributes` (jedno źródło prawdy).
21
+ - `defineShop({ variantLabel: { template } })` (`includio-cms/shop`) — opcjonalny szablon nazwy wariantu w składni `{key|filter:arg}`. Filtry: `date` (long/medium/short), `currency` (kod waluty, domyślnie PLN), `uppercase`. Nieznany klucz → pusty string + dev warn; nieznany filtr → passthrough; malformed template → surowy template + warn.
22
+ - `interpolateTemplate(template, vars, locale)` (`includio-cms/shop`, `@public`) — silnik interpolacji wykorzystywany wewnętrznie przez admin do pre-fill `variant.name`, dostępny też publicznie dla konsumentów (np. storefront-side derived labels).
23
+ - `VariantLabelConfig` eksportowany jako `@public` typ z `includio-cms/shop`.
24
+ - `getShopConfig` remote response zawiera teraz `variantLabel: shop.variantLabel ?? null`.
25
+ - `shop-field.svelte` (admin variant editor) — gdy `variantLabel.template` zdefiniowany, pole `Nazwa` auto-wypełnia się z interpolacji `variantAttributes` (locale `pl` w 0.27; multi-locale defer post-1.0). Per-variant dirty flag: po hydratacji z niepustym `name` lock = aktywny (nie nadpisujemy editor decision); ręczna edycja w polu `Nazwa` (`oninput`) trwale wyłącza pre-fill dla wariantu w bieżącej sesji.
26
+ - `defineShop({ variantExpiry: { source, offsetDays } })` (`includio-cms/shop`, `@public`) — opt-in filtr wariantów time-bound (events, courses, szkolenia). `source` = klucz atrybutu typu `datetime`; `offsetDays` przesuwa cut-off (`0` = expire dokładnie gdy datetime hits now, `1` = jeden dzień grace, `-1` = jeden dzień przed). Globalny config — brak per-product override.
27
+ - `isVariantExpired(variant, config, now?)` + `filterUpcoming(variants, config, now?)` (`includio-cms/shop`, `@public`) — fail-open helpers: `null` config / brak source attribute / non-string / malformed datetime → variant traktowany jako upcoming (z `console.warn` dla malformed w dev). `filterUpcoming` zachowuje order; sort source-asc realizowany na poziomie HTTP / admin osobno.
28
+ - `VariantExpiredError` (code `VARIANT_EXPIRED`, `variantId`) — eksport `@public`. Rzucany przez `createOrderFromCart` w `server/orders.ts` przed stock reservation (idempotent guard).
29
+ - `POST /api/shop/cart` (add) — preflight `VARIANT_EXPIRED` guard: kiedy `variantExpiry` jest skonfigurowany i variant ma expired source attribute, response 400 JSON `{ error: "VARIANT_EXPIRED", variantId }` bez aktualizacji cart cookie.
30
+ - `createUpcomingVariantsHandler` (`includio-cms/shop/http`, `@experimental`) — nowy GET endpoint `/api/shop/products/[id]/variants/upcoming`. Zwraca `{ items: VariantPublic[] }` przefiltrowanych przez `filterUpcoming` + posortowanych ascendingly po `attributes.<source>` (Date.parse) gdy `variantExpiry` ustawiony, w insertion order gdy brak.
31
+ - `client.products.listUpcoming(productId)` + `VariantPublic` (`includio-cms/shop/client`, `@public`) — nowy namespace SDK. Zwraca upcoming variants per produkt; zero-config passthrough kiedy `variantExpiry` nieustawiony.
32
+ - `getShopConfig` remote (admin) — response zawiera teraz `variantExpiry: shop.variantExpiry ?? null`.
33
+ - `shop-field.svelte` (admin variant editor) — gdy `variantExpiry` skonfigurowany: per-variant badge "Zakończony" (greyed-out, `bg-muted text-muted-foreground` z border), checkbox filter "Pokaż zakończone (N)" w toolbarze wariantów (default off, ukryty gdy zero expired), opacity-60 na expired row, sort wariantów po source ASC (closer terms first). Brak config = zero zmian w UI.
34
+ - `PaymentPolicy` + `DepositAmount` + `PartialPayment` (`includio-cms/shop`, `@public`) — per-product policy `{ type: "full" } | { type: "deposit", depositAmount: { type: "percent" | "amount", value } }` ustawiana w `ShopFieldData.paymentPolicy`. Cart deposit-aware: order zachowuje pełen `totalGross`, `partialPayment.balanceAmount` = co zostaje do dopłaty, `balanceOwed = true` po zapłaconym depozycie. Walidacja: percent w (0, 100], amount = positive integer (minor units). `validatePaymentPolicy` wymusza to przy upsert produktu.
35
+ - `resolvePaymentAmount(policy, lineGross)` + `computeDepositAmount(spec, base)` (`$lib/shop/server/payment-policy.ts`, server-internal — nie eksportowane z publicznego entry pointu) — silnik resolver per linia. `percent` flooruje `base * value / 100`; `amount` klampuje do `base`. Null / `full` policy → pełen `lineGross`, `kind = "full"`, balance 0. 15 spec testów + 10 integration.
36
+ - `MixedPaymentPolicyError` (code `MIXED_PAYMENT_POLICY`) — `createOrderFromCart` odrzuca cart z więcej niż jednym produktem gdy którykolwiek z nich ma deposit policy. Decyzja: deposit orders span ONE product (refund-per-kind + balance link unambiguous). Cart all-`full` mixed-product nadal działa.
37
+ - `shop_orders.partial_payment jsonb + balance_owed boolean` — nowe kolumny. `shop_payments.kind enum ("full" | "deposit" | "balance")` z default `"full"` — back-compat dla istniejących płatności. `shop_products.payment_policy jsonb` przechowuje per-product policy.
38
+ - `shop_payments` zaczyna być aktywnie wypełniane: `checkout-handler` po `adapter.createPayment` insert payment row z odpowiednim `kind` (full lub deposit) + `providerRef`. Webhook handler matchuje (provider, providerRef) → branchuje per kind: `full`/`deposit` przepuszcza `updateOrderStatus(paid, paymentKind)`, `balance` bypasses status flow i woła `markBalancePaid` (stock przy depozycie już permanentnie potwierdzony).
39
+ - `createOrderFromCart` CreateOrderResult: nowe pola `amountToPay` (deposit-aware kwota do pobrania na checkout) + `paymentKind` (`"full" | "deposit"`). `checkout-handler` przekazuje `amountToPay` do adaptera przez OrderRef.totalGross override — adaptery PayU/Stripe/manual działają bez zmian.
40
+ - `generateBalanceToken` + `verifyBalanceToken` (`includio-cms/shop/server`, `@internal`) — HMAC-SHA256 nad JSON payload `{orderId, type: "balance"}`, encoding `base64url(payload).base64url(sig)`. Deterministic per (orderId, secret) — brak rotation, brak exp, server-side invalidation przez `order.balanceOwed === true`. Secret = `INCLUDIO_BALANCE_TOKEN_SECRET` env (≥16 chars, hard-fail przy brak gdy deposit policy aktywne). 8 spec testów (roundtrip, tampered, wrong orderId/secret, malformed, deterministic).
41
+ - `createBalanceSession(orderNumber, token, ctx?)` (`includio-cms/shop/server`, `@experimental`) — customer flow: verify token + `balanceOwed`, reuse `order.paymentMethod` adapter, call `adapter.createPayment` z `amount = partialPayment.balanceAmount`, insert payment row `kind: "balance"`, mirror providerRef na order. `markBalancePaid` (idempotent) clears balanceOwed + bumps `paidAmount` do `totalGross`.
42
+ - `createBalanceHandler` (`includio-cms/shop/http`, `@experimental`) — GET `/api/shop/orders/[number]/balance?token=...` zwraca minimalny widok ({orderNumber, currency, totalGross, amountToPay, paidAmount, paymentMethod, language}); POST inicjuje payment session ({status, redirectUrl, requiresPaymentRedirect}). 403 przy złym tokenie lub wyczyszczonym `balanceOwed`.
43
+ - `client.orders.payBalance(orderNumber, token)` + `PayBalanceResult` (`includio-cms/shop/client`, `@public` / `@experimental`) — REST wrapper dla customer flow dopłaty.
44
+ - `refundOrder({ kind?, releaseStock?, ... })` (`includio-cms/shop/server`) — per-kind routing. `kind: "deposit" | "balance" | "full"` matchuje konkretny payment row; kwota cap = `row.amount - prior refunds`. Domyślnie `kind` = `"full"` z heurystyką: pojedynczy paid row → użyj go, multi-row → wybierz `full`, brak rows → legacy fallback do `order.paymentProviderRef`. Refund row link do `paymentId` dla per-row audit. `getCollectedAmount` decyduje o transition do `refunded` (sum paid rows lub `totalGross` dla legacy). `releaseStock: true` (opt-in) reinkrementuje variant.stock per order item. 6 integration spec.
45
+ - `refundOrderCmd` (admin remote) dostaje `kind` + `releaseStock` w schemacie input. `refund-dialog.svelte` — radio "Która płatność?" (deposit/balance) widoczne gdy `hasPartial`, balance radio disabled gdy `balanceOwed=true` (nic do refund), checkbox "Zwolnij stan magazynowy".
46
+ - `generateBalanceLinkForOrder` (admin remote) — auth-protected, requires `INCLUDIO_BALANCE_TOKEN_SECRET`, builds URL z configured `orderViewUrl` + `?balance=1&balanceToken=...`. Zwraca `{ success, url, balanceAmount }`.
47
+ - `shop-order-detail-page.svelte` — nowa sekcja "Płatność dzielona" widoczna gdy `order.partialPayment != null`: Plum badge "Czeka na dopłatę" przy `balanceOwed=true` / success badge "Opłacone w całości" po dopłacie, paid/owed/total breakdown z `formatCentsPrice`, button "Wyślij link do dopłaty" generuje token + kopiuje URL do clipboard, wyświetla URL w `<code>` blocku jako fallback dla "skopiuj ręcznie".
48
+
49
+ ### Fixed
50
+ - `variant-attributes.ts` — `datetime` walidator używa teraz `z.string().datetime({ offset: true })`: akceptuje pełen ISO 8601 (`Z` UTC z admin `DatetimeField.toISOString()` ORAZ offset `+02:00` z importów/seedów/zewnętrznych systemów). Wcześniej tryb default odrzucał offset, blokując offsetowe wartości atrybutów.
51
+ - `updateOrderStatus` (`server/orders.ts`) — admin manual mark-paid auto-detektuje `deposit` kind: gdy `order.partialPayment.kind === "deposit"` + `!balanceOwed` + `paidAt == null`, `effectiveKind = "deposit"`. Wcześniej `updateOrderStatusCmd` (w przeciwieństwie do webhooka) nie przekazywał `paymentKind`, więc admin oznaczając deposit order jako paid pomijał deposit logic (`paidAmount` nie był bumpowany, `balanceOwed` nie był ustawiany). Pozwala testować pełny deposit flow przez manual adapter bez sandbox PayU; webhook bez zmian (zawsze pass explicit kind).
52
+ - admin `paymentPolicy` — trzy bugi powodujące kasowanie deposit policy przy każdym save naprawione razem: (1) `upsertShopData` (`server/shop-data.ts`) — `undefined` zachowuje istniejącą policy, tylko `null` kasuje (było `?? null` nadpisujące przy każdym upsert innego pola); (2) `shopDataInputSchema` (admin remote) — dodany discriminated union `paymentPolicy` (full/deposit + percent/amount), wcześniej command odrzucał pole; (3) `shop-field.svelte` — sekcja "Zasady płatności" (radio full/deposit + warunkowe inputy percent/amount + live preview kwoty depozytu), wcześniej brak UI do ustawienia deposit.
53
+
54
+ ## 0.26.1 — 2026-05-28
55
+
56
+ Nowy typ pola `icon` + IconSetPlugin (zestaw ikon dostarczany przez aplikację, dialog z gridem + search). Scaffolder fix + DataTable polish: scaffold admin używa publicznych entry points; pierwsza kolumna tabeli bez sticky-first; checkbox visual wraca do 16 px z transparent hit-area 24×24 (WCAG 2.5.5).
57
+
58
+ ### Added
59
+ - Nowy typ pola `icon` (`IconField` @public, `src/lib/types/fields.ts`) — kompaktowy kafelek 96×96 w formularzu (ikona + nazwa, X do wyczyszczenia) otwiera dialog z gridem responsive 3–6 kolumn, wyszukiwarką (filtruje po `key`, lokalizowanym `label`, opcjonalnych `keywords`) i przyciskami Anuluj / OK. Klik na kafelku w dialogu zaznacza, OK zatwierdza; dwuklik = szybki zapis. Stan "missing" (wartość w DB nieobecna w bibliotece) pokazuje placeholder + przyjazne ostrzeżenie zamiast resetować wartość — zgodne z ToV "informuj, nie strasz". i18n PL/EN, `role="listbox"`/`role="option"`/`aria-selected`, LiveRegion z liczbą wyników.
60
+ - `IconSetPlugin` / `IconDefinition` (`@public`, `src/lib/types/plugins.ts`) — nowy rodzaj pluginu rejestrujący nazwany zestaw ikon: `{ slug, type: 'icon-set', icons: Record<key, { component, label: Localized, keywords?: string[] }> }`. Komponenty Svelte (eager import, tree-shakable — np. `Brain` z `@lucide/svelte`) ŻYJĄ w pluginie, bo `cms.config.ts` jest server-only i Zod-validated. `Plugin = PluginConfig | IconSetPlugin` + `isIconSetPlugin` type guard.
61
+ - `buildIconSetMap(...plugins)` (`includio-cms/admin`) + nowy prop `iconSets?: Map<string, IconSetPlugin>` na `AdminLayout` — konsumencki `+layout.svelte` admina przekazuje plugin instancje na klienta (funkcji komponentów nie da się serializować przez SvelteKit data). `getIconSets()` / `resolveIconSet(slug?)` w `includio-cms/admin` — runtime lookup używany przez `icon-field.svelte` przez Svelte context.
62
+ - `CMS.iconSets: Map<slug, IconSetPlugin>` agregowane przy starcie z `cms.config.plugins` przez `isIconSetPlugin` guard; duplikat slug → throw. Generator TS mapuje `icon` → `string` w wygenerowanym `types.ts`; Zod runtime → `z.string()` (analogicznie do `slug` field).
63
+
64
+ ### Fixed
65
+ - `scaffold admin` generuje `src/routes/admin/api/[...path]/+server.ts` z `import { createAdminApiHandler } from 'includio-cms/sveltekit/server'`. Wcześniej generowany import `includio-cms/admin/api/handler` rzucał Vite `Missing "./admin/api/handler" specifier in "includio-cms" package` przy starcie dev/build — `admin/api/handler` nie ma w `exports` (v1.0 frozen 18 ścieżek).
66
+ - `scaffold admin` generuje `src/routes/admin/api/rest/[...restPath]/+server.ts` z `import { createRestApiHandler } from 'includio-cms/sveltekit/server'` (analogicznie — był broken w 0.20.0+ ale scaffolder nie zaktualizowany).
67
+ - `includio-cms/sveltekit/server` re-eksportuje teraz `createAdminApiHandler` (obok istniejącego `createRestApiHandler`).
68
+ - `DataTable`: revert sticky-first column (z 0.26.0 / S10c) — pierwsza kolumna scrolluje razem z resztą, bez wyróżnienia kolorystycznego. Usunięty prop `stickyFirstColumn` i powiązany CSS.
69
+ - `Checkbox` primitive: visual wraca do 16×16 px (z 24×24 w 0.26.0 / S10b), klikalny obszar utrzymany na ≥24×24 przez transparent `::after` pseudo-element (`after:-inset-1`) — WCAG 2.5.5 target-size AA dalej spełniony, lepszy wygląd zgodny z proporcjami pól tekstowych.
70
+
71
+ ## 0.26.0 — 2026-05-26
72
+
73
+ 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).
74
+
75
+ ### Added
76
+ - `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.
77
+ - `<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.
78
+ - `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.
79
+ - 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.
80
+ - 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.
81
+ - 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.
82
+ - Media + File fields — `Dialog.Title` + `Dialog.Description` (sr-only) na picker dialogs (eliminuje bits-ui ostrzeżenie o brakujących aria-labelledby).
83
+ - 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.
84
+ - SEO field — `aria-live="polite"` na char counter (50/60, 120/160) — SR słyszy zmianę gdy user wpisuje.
85
+ - 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`).
86
+ - 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.
87
+ - 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.
88
+ - 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).
89
+ - `<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.
90
+ - `<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.
91
+ - `<DetailPageShell>` (`src/lib/admin/components/layout/`) — wspólny layout (PageHeader + body + opcjonalny sidebar) dla coupon-edit / shipping-method-edit. Skip-link target `#detail-main`.
92
+ - Coupon edit form zmigrowany na sveltekit-superforms + formsnap (jak account/profile-section) — schema zod (`coupon-schema.ts`), SPA mode, error summary + per-field errors.
93
+ - 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.
94
+ - `<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.
95
+ - `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.
96
+ - `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.
97
+ - 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).
98
+ - 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.
99
+ - 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).
100
+ - 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).
101
+ - 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.
102
+
103
+ ### Fixed
104
+ - `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.
105
+ - 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.
106
+ - 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.
107
+ - Coupons list: delete dialog A11y (focus trap, ESC, return focus) zamiast browser `confirm()`.
108
+ - Form submissions bulk delete: AlertDialog zamiast `confirm()`, plural PL forms ("3 zgłoszenia" vs "5 zgłoszeń").
109
+ - Dashboard delete-orphaned: AlertDialog z liczbą wpisów w description zamiast `confirm()`.
110
+ - `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.
111
+ - 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).
112
+ - 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.
113
+
114
+ ### Breaking
115
+ - **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).
116
+ - 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.
117
+ - 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.
118
+ - `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.
119
+
120
+ ### Notes
121
+
122
+ 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).
123
+
6
124
  ## 0.25.0 — 2026-05-06
7
125
 
8
126
  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.27.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,16 @@
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]` Shop platformowy 0.27.0 — schema-driven variants + booking deposit (envet pilot). Plan: 7 faz. <!-- files: docs/superpowers/specs/2026-05-28-shop-platformowy-design.md, /Users/patryk/.claude/plans/implementacja-ariacms-0-27-partitioned-kahn.md -->
25
+ - [x] Faza 1 — Schema-driven `variantAttributes` (typed `defineShop` schema, Zod builder, GIN index util, ts-gen typed `variant.attributes`, `INVALID_VARIANT_ATTRIBUTES` guard w `upsertShopData`). <!-- files: src/lib/shop/types.ts, src/lib/shop/variant-attributes.ts, src/lib/shop/server/{shop-data,init}.ts, src/lib/db-postgres/schema/shop/productVariant.ts, src/lib/core/server/generator/fields.ts -->
26
+ - [x] Faza 2 — Admin dynamic variant attribute form renderer (`VariantAttributeRenderer.svelte`, integracja w `shop-field.svelte`, `getShopConfig` remote response zwraca `variantAttributes`, auto-apply GIN indexes na `initCMS()`). <!-- files: src/lib/admin/components/variant-form/VariantAttributeRenderer.svelte, src/lib/admin/components/fields/shop-field.svelte, src/lib/admin/remote/shop.remote.ts, src/lib/core/cms.ts, src/lib/shop/server/init.ts, src/stories/fields/shop-with-attributes.stories.svelte -->
27
+ - [x] Faza 3 — `variantLabel.template` interpolation + admin pre-fill (`interpolateTemplate` engine z filtrami `date`/`currency`/`uppercase`, `ShopConfig.variantLabel`, `defineShop` przepuszcza, `getShopConfig` remote zwraca, `shop-field.svelte` auto-prefills `variant.name` per locale `pl` z per-variant dirty flag — locked po hydratacji jeśli name istnieje + po `oninput` w name). <!-- files: src/lib/shop/template.ts, src/lib/shop/types.ts, src/lib/shop/index.ts, src/lib/admin/remote/shop.remote.ts, src/lib/admin/components/fields/shop-field.svelte, src/stories/fields/shop-with-attributes-story-demo.svelte, src/stories/fields/shop-with-attributes.stories.svelte -->
28
+ - [x] Faza 4 — `variantExpiry` opt-in (storefront filter + cart-add guard + checkout guard + admin "Zakończony" badge + filter toggle + source-asc sort + upcoming HTTP endpoint + `client.products.listUpcoming` SDK). <!-- files: src/lib/shop/expiry.ts, src/lib/shop/types.ts, src/lib/shop/index.ts, src/lib/shop/server/orders.ts, src/lib/shop/http/{cart-handler,upcoming-handler,index}.ts, src/lib/shop/client/index.ts, src/lib/admin/remote/shop.remote.ts, src/lib/admin/components/fields/shop-field.svelte -->
29
+ - [x] Faza 5 — `paymentPolicy` A-lite (deposit + balance + signed token + refund per kind, admin balance link + refund-per-kind dialog, shop_payments rows tagged by kind). <!-- files: src/lib/shop/types.ts, src/lib/shop/server/{payment-policy,balance-payment,payments,orders,refund,shop-data}.ts, src/lib/shop/http/{balance-handler,checkout-handler,webhook-handler,index}.ts, src/lib/shop/client/index.ts, src/lib/db-postgres/schema/shop/{order,payment,product}.ts, src/lib/admin/{remote/shop.remote.ts,client/shop/{shop-order-detail-page,refund-dialog}.svelte} -->
30
+ - [x] Faza 6 — envet integration (pilot consumer) — szkolenia variants + deposit flow + balance link end-to-end QA. <!-- files: envet repo src/lib/cms/cms.config.ts, src/routes/api/shop/, src/routes/(website)/{szkolenia,koszyk}/, src/lib/components/{CartIcon,AddToCartModal,CoursePage}.svelte, cli/seed.ts -->
31
+ - [x] Faza 7 — Release artifacts (changelog, ROADMAP cleanup, API.md, build) — 3 post-Faza-5 hotfixy w 0.27.0 (single release). <!-- files: src/lib/updates/0.27.0/index.ts, ROADMAP.md, CHANGELOG.md, API.md, MIGRATION-... -->
32
+ - [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
33
 
24
34
  ## v1.x — Post-v1.0 deferred
25
35
 
@@ -45,6 +55,10 @@
45
55
 
46
56
  ## Backlog
47
57
 
58
+ - [ ] `[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 -->
59
+ - [ ] `[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.
60
+ - [ ] `[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).
61
+ - [ ] `[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
62
  - [ ] `[feature]` `[P1]` Server-side pagination API (formalize 0.1.0 fix)
49
63
  - [x] `[feature]` `[P1]` Improved type generation — union types for select/checkboxes, defaultValue makes fields non-optional <!-- files: src/lib/core/server/generator/ -->
50
64
  - [ ] `[feature]` `[P1]` Proper filtering API (SQL-level, not JS post-query)