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
@@ -1,18 +1,57 @@
1
1
  import { getAtPath } from './objectPath.js';
2
- export function getRawCollectionEntryLabel(entry, config, language) {
3
- const publishedVersion = entry.publishedVersions[language];
4
- if (publishedVersion) {
5
- return config.entryAdminTitle
6
- ? String(getAtPath(publishedVersion.data, config.entryAdminTitle) || entry.id)
7
- : entry.id;
2
+ /**
3
+ * Resolve the admin title for a raw collection entry.
4
+ *
5
+ * Prefers the requested `language` (published version, then draft). If that
6
+ * language has no usable title it falls back to any other language (published
7
+ * first, then draft). Returns the entry id as a last resort. `language` in the
8
+ * result tells callers which translation was used — useful for a "(en)" hint
9
+ * when it differs from what was asked for.
10
+ */
11
+ export function getRawCollectionEntryLabelWithLanguage(entry, config, language) {
12
+ const path = config.entryAdminTitle;
13
+ if (!path)
14
+ return { label: entry.id, language: null };
15
+ const titleOf = (version) => {
16
+ if (!version)
17
+ return null;
18
+ const value = getAtPath(version.data, path);
19
+ return value == null || value === '' ? null : String(value);
20
+ };
21
+ // 1. requested language — published, then draft
22
+ for (const bucket of [entry.publishedVersions, entry.draftVersions]) {
23
+ const title = titleOf(bucket?.[language]);
24
+ if (title)
25
+ return { label: title, language };
26
+ }
27
+ // 2. any other language — published first, then draft
28
+ for (const bucket of [entry.publishedVersions, entry.draftVersions]) {
29
+ for (const [lang, version] of Object.entries(bucket ?? {})) {
30
+ if (lang === language)
31
+ continue;
32
+ const title = titleOf(version);
33
+ if (title)
34
+ return { label: title, language: lang };
35
+ }
8
36
  }
9
- const draftVersion = entry.draftVersions[language];
10
- if (draftVersion) {
11
- return config.entryAdminTitle
12
- ? String(getAtPath(draftVersion.data, config.entryAdminTitle) || entry.id)
13
- : entry.id;
37
+ return { label: entry.id, language: null };
38
+ }
39
+ export function getRawCollectionEntryLabel(entry, config, language) {
40
+ return getRawCollectionEntryLabelWithLanguage(entry, config, language).label;
41
+ }
42
+ /**
43
+ * Display label for a raw collection entry in the admin UI.
44
+ *
45
+ * Like {@link getRawCollectionEntryLabel} but, when no title could be resolved
46
+ * in any language, returns a localized "(untitled)" placeholder instead of the
47
+ * raw entry id — so the entries list and the edit breadcrumb stay in sync.
48
+ */
49
+ export function getCollectionEntryDisplayLabel(entry, config, language) {
50
+ const { label, language: resolvedLanguage } = getRawCollectionEntryLabelWithLanguage(entry, config, language);
51
+ if (resolvedLanguage === null) {
52
+ return language === 'pl' ? '(bez tytułu)' : '(untitled)';
14
53
  }
15
- return entry.id;
54
+ return label;
16
55
  }
17
56
  export function getCollectionEntryLabel(entry, config) {
18
57
  return config.entryAdminTitle
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Wejście dla `getFieldA11yProps`.
3
+ */
4
+ export type FieldA11yInput = {
5
+ /** Bazowe ID kontrolki — używane do generowania `{id}-description` / `{id}-error`. */
6
+ id: string;
7
+ hasDescription?: boolean;
8
+ hasError?: boolean;
9
+ required?: boolean;
10
+ };
11
+ /**
12
+ * ARIA atrybuty dla kontrolki formularza wpinanej w `Form.Field` (formsnap)
13
+ * lub równoważny wrapper. Zwracany kształt jest gotowy do spread'u na `<input>`.
14
+ */
15
+ export type FieldA11yProps = {
16
+ 'aria-describedby'?: string;
17
+ 'aria-invalid'?: 'true';
18
+ 'aria-required'?: 'true';
19
+ };
20
+ /**
21
+ * Buduje atrybuty ARIA dla kontrolki — łączy ID-y description/error w `aria-describedby`,
22
+ * ustawia `aria-invalid` przy błędach, `aria-required` przy required.
23
+ *
24
+ * Powstał jako bridge między `ui/form` (formsnap-based, 8 superForm konsumentów)
25
+ * a wzorcem auto-aria z `ui/field` — bez breaking migracji (S3 koegzystencja).
26
+ *
27
+ * @public
28
+ */
29
+ export declare function getFieldA11yProps(o: FieldA11yInput): FieldA11yProps;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Buduje atrybuty ARIA dla kontrolki — łączy ID-y description/error w `aria-describedby`,
3
+ * ustawia `aria-invalid` przy błędach, `aria-required` przy required.
4
+ *
5
+ * Powstał jako bridge między `ui/form` (formsnap-based, 8 superForm konsumentów)
6
+ * a wzorcem auto-aria z `ui/field` — bez breaking migracji (S3 koegzystencja).
7
+ *
8
+ * @public
9
+ */
10
+ export function getFieldA11yProps(o) {
11
+ const ids = [
12
+ o.hasDescription ? `${o.id}-description` : null,
13
+ o.hasError ? `${o.id}-error` : null
14
+ ].filter((v) => v !== null);
15
+ const out = {};
16
+ if (ids.length)
17
+ out['aria-describedby'] = ids.join(' ');
18
+ if (o.hasError)
19
+ out['aria-invalid'] = 'true';
20
+ if (o.required)
21
+ out['aria-required'] = 'true';
22
+ return out;
23
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolves a (possibly nested) field path to its closest rendered element.
3
+ *
4
+ * Tries the full dotted `data-field-path` first, then trims trailing segments
5
+ * so a leaf field without its own marker still resolves to the nearest
6
+ * rendered ancestor (e.g. `highlights.0.title` → `highlights.0` → `highlights`).
7
+ * Returns `null` when no segment prefix is rendered.
8
+ */
9
+ export declare function findFieldPathElement(fieldPath: string): HTMLElement | null;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Resolves a (possibly nested) field path to its closest rendered element.
3
+ *
4
+ * Tries the full dotted `data-field-path` first, then trims trailing segments
5
+ * so a leaf field without its own marker still resolves to the nearest
6
+ * rendered ancestor (e.g. `highlights.0.title` → `highlights.0` → `highlights`).
7
+ * Returns `null` when no segment prefix is rendered.
8
+ */
9
+ export function findFieldPathElement(fieldPath) {
10
+ const segments = fieldPath.split('.');
11
+ for (let end = segments.length; end > 0; end--) {
12
+ const candidate = segments.slice(0, end).join('.');
13
+ const el = document.querySelector(`[data-field-path="${candidate}"]`);
14
+ if (el instanceof HTMLElement)
15
+ return el;
16
+ }
17
+ return null;
18
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Human-readable file size: "0 B" / "12 B" / "3 KB" / "1.42 MB".
3
+ * Bytes shown as integer; KB+ with 2 decimal places.
4
+ */
5
+ export declare function formatFileSize(bytes: number): string;
6
+ /**
7
+ * Extract file extension from a URL (uppercased, no dot). Returns '' if missing or ambiguous.
8
+ * Examples: 'foo/bar.txt' -> 'TXT', 'image.JPEG' -> 'JPEG', 'no-ext' -> ''.
9
+ */
10
+ export declare function getFileExtension(url: string | null | undefined): string;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Human-readable file size: "0 B" / "12 B" / "3 KB" / "1.42 MB".
3
+ * Bytes shown as integer; KB+ with 2 decimal places.
4
+ */
5
+ export function formatFileSize(bytes) {
6
+ if (!bytes || bytes <= 0)
7
+ return '0 B';
8
+ const units = ['B', 'KB', 'MB', 'GB', 'TB'];
9
+ const k = 1024;
10
+ const i = Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(k)));
11
+ const size = bytes / Math.pow(k, i);
12
+ return `${size.toFixed(i > 0 ? 2 : 0)} ${units[i]}`;
13
+ }
14
+ /**
15
+ * Extract file extension from a URL (uppercased, no dot). Returns '' if missing or ambiguous.
16
+ * Examples: 'foo/bar.txt' -> 'TXT', 'image.JPEG' -> 'JPEG', 'no-ext' -> ''.
17
+ */
18
+ export function getFileExtension(url) {
19
+ if (!url)
20
+ return '';
21
+ const fileName = url.split('/').pop() ?? '';
22
+ const dot = fileName.lastIndexOf('.');
23
+ if (dot <= 0 || dot === fileName.length - 1)
24
+ return '';
25
+ return fileName.slice(dot + 1).toUpperCase();
26
+ }
@@ -0,0 +1,19 @@
1
+ import type { Field } from '../../types/fields.js';
2
+ import type { InterfaceLanguage } from '../../types/languages.js';
3
+ import type { FormErrorEntry } from '../components/forms/form-error-summary.svelte';
4
+ /** Recursive validation-error tree (superforms `ValidationErrors` shape). */
5
+ type ErrorTree = Record<string, unknown>;
6
+ /**
7
+ * Flattens a nested superforms validation-error tree into a human-readable
8
+ * list for the error summary.
9
+ *
10
+ * Resolves localized field labels (never raw slugs), turns array/blocks item
11
+ * indices into `Element N` / `Item N` (1-based), descends into `object` /
12
+ * `blocks` / `array` fields, and surfaces container-level `_errors` (e.g. a
13
+ * `blocks` minItems constraint) so the user sees everything blocking the save.
14
+ *
15
+ * `data` is the parallel form data — required to resolve which block variant a
16
+ * `blocks` item index is (via its `_slug` discriminator).
17
+ */
18
+ export declare function flattenFormErrors(errors: ErrorTree, fields: Field[], data: unknown, lang: InterfaceLanguage, prefix?: string, labelPrefix?: string): FormErrorEntry[];
19
+ export {};
@@ -0,0 +1,102 @@
1
+ import { getLocalizedLabel } from './collectionLabel.js';
2
+ /** 1-based item label for array/blocks indices. */
3
+ const indexWord = { pl: 'Element', en: 'Item' };
4
+ /** Label for root-level (`_errors`) form errors. */
5
+ const formWord = { pl: 'Formularz', en: 'Form' };
6
+ function joinLabel(prefix, label) {
7
+ return prefix ? `${prefix} › ${label}` : label;
8
+ }
9
+ /**
10
+ * Flattens a nested superforms validation-error tree into a human-readable
11
+ * list for the error summary.
12
+ *
13
+ * Resolves localized field labels (never raw slugs), turns array/blocks item
14
+ * indices into `Element N` / `Item N` (1-based), descends into `object` /
15
+ * `blocks` / `array` fields, and surfaces container-level `_errors` (e.g. a
16
+ * `blocks` minItems constraint) so the user sees everything blocking the save.
17
+ *
18
+ * `data` is the parallel form data — required to resolve which block variant a
19
+ * `blocks` item index is (via its `_slug` discriminator).
20
+ */
21
+ export function flattenFormErrors(errors, fields, data, lang, prefix = '', labelPrefix = '') {
22
+ const result = [];
23
+ for (const [key, value] of Object.entries(errors)) {
24
+ if (key === '_errors') {
25
+ // Container-level errors for this node itself (e.g. blocks minItems).
26
+ if (Array.isArray(value)) {
27
+ const label = labelPrefix || formWord[lang];
28
+ for (const message of value) {
29
+ result.push({ path: prefix, label, message: String(message) });
30
+ }
31
+ }
32
+ continue;
33
+ }
34
+ const field = fields.find((f) => f.slug === key);
35
+ const path = prefix ? `${prefix}.${key}` : key;
36
+ const baseLabel = field ? getLocalizedLabel(field.label, lang) || field.slug : key;
37
+ const fullLabel = joinLabel(labelPrefix, baseLabel);
38
+ const fieldData = data && typeof data === 'object' && !Array.isArray(data)
39
+ ? data[key]
40
+ : undefined;
41
+ if (Array.isArray(value)) {
42
+ for (const message of value) {
43
+ result.push({ path, label: fullLabel, message: String(message) });
44
+ }
45
+ continue;
46
+ }
47
+ if (!value || typeof value !== 'object')
48
+ continue;
49
+ const childErrors = value;
50
+ if (field?.type === 'object') {
51
+ result.push(...flattenFormErrors(childErrors, field.fields, fieldData, lang, path, fullLabel));
52
+ }
53
+ else if (field?.type === 'blocks' || field?.type === 'array') {
54
+ result.push(...flattenItemErrors(childErrors, field, fieldData, lang, path, fullLabel));
55
+ }
56
+ else {
57
+ // Unknown / untyped nested object — recurse without field context.
58
+ result.push(...flattenFormErrors(childErrors, [], fieldData, lang, path, fullLabel));
59
+ }
60
+ }
61
+ return result;
62
+ }
63
+ /**
64
+ * Handles the index-keyed level of `blocks` / `array` errors: each numeric key
65
+ * becomes `Element N` / `Item N`, and for `blocks` the item's `_slug` selects
66
+ * the block variant whose `fields` resolve the nested labels.
67
+ */
68
+ function flattenItemErrors(errors, field, data, lang, prefix, labelPrefix) {
69
+ const result = [];
70
+ for (const [key, value] of Object.entries(errors)) {
71
+ if (key === '_errors') {
72
+ if (Array.isArray(value)) {
73
+ for (const message of value) {
74
+ result.push({ path: prefix, label: labelPrefix, message: String(message) });
75
+ }
76
+ }
77
+ continue;
78
+ }
79
+ const index = Number(key);
80
+ const itemPath = `${prefix}.${key}`;
81
+ const itemLabel = joinLabel(labelPrefix, `${indexWord[lang]} ${(Number.isNaN(index) ? 0 : index) + 1}`);
82
+ const itemData = Array.isArray(data) ? data[index] : undefined;
83
+ if (Array.isArray(value)) {
84
+ for (const message of value) {
85
+ result.push({ path: itemPath, label: itemLabel, message: String(message) });
86
+ }
87
+ continue;
88
+ }
89
+ if (!value || typeof value !== 'object')
90
+ continue;
91
+ const childErrors = value;
92
+ if (field.type === 'blocks') {
93
+ const slug = itemData?._slug;
94
+ const variant = field.of.find((def) => def.slug === slug);
95
+ result.push(...flattenFormErrors(childErrors, variant?.fields ?? [], itemData, lang, itemPath, itemLabel));
96
+ }
97
+ else {
98
+ result.push(...flattenFormErrors(childErrors, [], itemData, lang, itemPath, itemLabel));
99
+ }
100
+ }
101
+ return result;
102
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared admin formatters (date + price).
3
+ *
4
+ * @internal
5
+ */
6
+ import type { InterfaceLanguage } from '../../types/languages.js';
7
+ export declare function toLocaleCode(lang: string): string;
8
+ export declare function formatRelativeDate(date: Date | string, lang?: InterfaceLanguage): string;
9
+ export declare function formatShortDateOnly(date: Date | string | null, lang?: InterfaceLanguage): string;
10
+ export declare function formatDateTime(date: Date | string, lang?: InterfaceLanguage): string;
11
+ export declare function formatPlnPrice(pln: number): string;
12
+ export declare function formatCentsPrice(cents: number, currency: string): string;
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Shared admin formatters (date + price).
3
+ *
4
+ * @internal
5
+ */
1
6
  export function toLocaleCode(lang) {
2
7
  const map = { pl: 'pl-PL', en: 'en-US' };
3
8
  return map[lang] ?? lang;
@@ -86,7 +91,9 @@ export function formatRelativeDate(date, lang = 'en') {
86
91
  }
87
92
  return labels[lang].justNow;
88
93
  }
89
- export function formatShortDate(date, lang = 'en') {
94
+ export function formatShortDateOnly(date, lang = 'en') {
95
+ if (date === null)
96
+ return '';
90
97
  const d = typeof date === 'string' ? new Date(date) : date;
91
98
  return d.toLocaleDateString(toLocaleCode(lang), {
92
99
  year: 'numeric',
@@ -94,7 +101,7 @@ export function formatShortDate(date, lang = 'en') {
94
101
  day: 'numeric'
95
102
  });
96
103
  }
97
- export function formatAbsoluteDate(date, lang = 'en') {
104
+ export function formatDateTime(date, lang = 'en') {
98
105
  const d = typeof date === 'string' ? new Date(date) : date;
99
106
  return d.toLocaleString(toLocaleCode(lang), {
100
107
  year: 'numeric',
@@ -104,3 +111,17 @@ export function formatAbsoluteDate(date, lang = 'en') {
104
111
  minute: '2-digit'
105
112
  });
106
113
  }
114
+ export function formatPlnPrice(pln) {
115
+ return new Intl.NumberFormat('pl-PL', {
116
+ style: 'currency',
117
+ currency: 'PLN'
118
+ }).format(pln);
119
+ }
120
+ export function formatCentsPrice(cents, currency) {
121
+ const upper = currency.toUpperCase();
122
+ const locale = upper === 'PLN' ? 'pl-PL' : upper === 'EUR' ? 'de-DE' : 'en-US';
123
+ return new Intl.NumberFormat(locale, {
124
+ style: 'currency',
125
+ currency: upper
126
+ }).format(cents / 100);
127
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Scroll `target` into view within its nearest scrollable ancestor only — it
3
+ * does NOT bubble the scroll up to the page/document. Use this instead of
4
+ * `Element.scrollIntoView()` inside fixed-height panes (the entry editor, sheets)
5
+ * where a recursive scroll would push fixed headers out of view.
6
+ *
7
+ * @internal
8
+ */
9
+ export declare function scrollIntoViewWithin(target: HTMLElement, block?: 'center' | 'nearest'): void;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Scroll `target` into view within its nearest scrollable ancestor only — it
3
+ * does NOT bubble the scroll up to the page/document. Use this instead of
4
+ * `Element.scrollIntoView()` inside fixed-height panes (the entry editor, sheets)
5
+ * where a recursive scroll would push fixed headers out of view.
6
+ *
7
+ * @internal
8
+ */
9
+ export function scrollIntoViewWithin(target, block = 'center') {
10
+ if (typeof getComputedStyle !== 'function')
11
+ return;
12
+ let scroller = target.parentElement;
13
+ while (scroller && scroller !== document.body && scroller !== document.documentElement) {
14
+ const overflowY = getComputedStyle(scroller).overflowY;
15
+ const scrollable = overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay';
16
+ if (scrollable && scroller.scrollHeight > scroller.clientHeight + 1)
17
+ break;
18
+ scroller = scroller.parentElement;
19
+ }
20
+ if (!scroller || scroller === document.body || scroller === document.documentElement) {
21
+ // No contained scroll parent — use the gentlest possible scroll.
22
+ target.scrollIntoView?.({ behavior: 'smooth', block: 'nearest' });
23
+ return;
24
+ }
25
+ const scrollerRect = scroller.getBoundingClientRect();
26
+ const targetRect = target.getBoundingClientRect();
27
+ const targetTopWithinScroller = scroller.scrollTop + (targetRect.top - scrollerRect.top);
28
+ const next = block === 'center'
29
+ ? targetTopWithinScroller - scroller.clientHeight / 2 + targetRect.height / 2
30
+ : targetTopWithinScroller;
31
+ scroller.scrollTo({ top: Math.max(0, next), behavior: 'smooth' });
32
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Activate every tab panel that contains `el`, so a field on an inactive tab
3
+ * becomes visible before it is scrolled to / focused.
4
+ *
5
+ * DOM-driven (mirrors the accordion-open behaviour in entry-form): tab panels
6
+ * stay mounted in the DOM (the renderer uses bits-ui `forceMount`), so we can
7
+ * walk up from the target element, find each inactive ancestor panel and click
8
+ * its matching trigger. Works for nested layouts even though `tabs`/`tab` may
9
+ * not nest each other — a tab panel can still sit inside another tab via
10
+ * section/card/columns wrappers, so we climb the full ancestor chain.
11
+ */
12
+ export declare function activateContainingTabs(el: HTMLElement): void;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Activate every tab panel that contains `el`, so a field on an inactive tab
3
+ * becomes visible before it is scrolled to / focused.
4
+ *
5
+ * DOM-driven (mirrors the accordion-open behaviour in entry-form): tab panels
6
+ * stay mounted in the DOM (the renderer uses bits-ui `forceMount`), so we can
7
+ * walk up from the target element, find each inactive ancestor panel and click
8
+ * its matching trigger. Works for nested layouts even though `tabs`/`tab` may
9
+ * not nest each other — a tab panel can still sit inside another tab via
10
+ * section/card/columns wrappers, so we climb the full ancestor chain.
11
+ */
12
+ export function activateContainingTabs(el) {
13
+ let panel = el.closest('[data-slot="tabs-content"]');
14
+ while (panel) {
15
+ const inactive = panel.hasAttribute('hidden') || panel.getAttribute('data-state') === 'inactive';
16
+ if (inactive) {
17
+ const value = panel.getAttribute('data-tab-value');
18
+ const group = panel.getAttribute('data-tabs-group');
19
+ const trigger = document.querySelector(`[data-slot="tabs-trigger"][data-tab-value="${value}"][data-tabs-group="${group}"]`);
20
+ trigger?.click();
21
+ }
22
+ panel = panel.parentElement?.closest('[data-slot="tabs-content"]') ?? null;
23
+ }
24
+ }
@@ -329,7 +329,7 @@ export const { POST } = createRetryPaymentHandler();
329
329
  {
330
330
  path: 'admin/api/[...path]/+server.ts',
331
331
  content: `${GENERATED_COMMENT_TS}
332
- import { createAdminApiHandler } from 'includio-cms/admin/api/handler';
332
+ import { createAdminApiHandler } from 'includio-cms/sveltekit/server';
333
333
 
334
334
  export const { GET, POST, PATCH, PUT, DELETE } = createAdminApiHandler();
335
335
  `
@@ -337,7 +337,7 @@ export const { GET, POST, PATCH, PUT, DELETE } = createAdminApiHandler();
337
337
  {
338
338
  path: 'admin/api/rest/[...restPath]/+server.ts',
339
339
  content: `${GENERATED_COMMENT_TS}
340
- import { createRestApiHandler } from 'includio-cms/admin/api/rest/handler';
340
+ import { createRestApiHandler } from 'includio-cms/sveltekit/server';
341
341
 
342
342
  export const { GET, POST, PUT, DELETE } = createRestApiHandler();
343
343
  `
@@ -1,2 +1,3 @@
1
1
  export * from 'includio-cms/db-postgres/schema-core';
2
2
  export * from 'includio-cms/auth-schema';
3
+ export * from 'includio-cms/db-postgres/schema-shop';
@@ -2,3 +2,4 @@
2
2
  // Point your drizzle.config.ts schema field at this file.
3
3
  export * from 'includio-cms/db-postgres/schema-core';
4
4
  export * from 'includio-cms/auth-schema';
5
+ export * from 'includio-cms/db-postgres/schema-shop';
@@ -1,4 +1,4 @@
1
- import type { ImageFieldData, VideoFieldData, StructuredContentDoc } from 'includio-cms/types';
1
+ import type { MediaFile, ImageFieldData, VideoFieldData, StructuredContentDoc } from 'includio-cms/types';
2
2
  export type SingleSlug = "settings" | "image-showcase";
3
3
  export interface Settings {
4
4
  _id: string;
@@ -11,7 +11,7 @@ export interface Settings {
11
11
  logo?: ImageFieldData | VideoFieldData | null;
12
12
  favicon?: ImageFieldData | VideoFieldData | null;
13
13
  socialLinks?: ({
14
- _slug: 'socialLink';
14
+ _slug: 'social-link';
15
15
  platform: string;
16
16
  url: {
17
17
  url: string;
@@ -33,7 +33,7 @@ export type SingleEntryMap = {
33
33
  settings: Settings;
34
34
  'image-showcase': ImageShowcase;
35
35
  };
36
- export type CollectionSlug = "blog-post" | "project" | "array-test";
36
+ export type CollectionSlug = "blog-post" | "project" | "product" | "array-test";
37
37
  export interface BlogPost {
38
38
  _id: string;
39
39
  _slug: string;
@@ -42,9 +42,11 @@ export interface BlogPost {
42
42
  _url?: string;
43
43
  title: string;
44
44
  slug?: string;
45
+ featured?: boolean;
45
46
  cover?: ImageFieldData | VideoFieldData | null;
46
47
  rating: number;
47
48
  category: 'technology' | 'design' | 'business' | 'tutorial';
49
+ difficulty?: 'beginner' | 'intermediate' | 'advanced';
48
50
  publishedAt?: string;
49
51
  thumbnail?: ImageFieldData | VideoFieldData | null;
50
52
  content?: StructuredContentDoc;
@@ -58,10 +60,6 @@ export interface BlogPost {
58
60
  keywords?: string;
59
61
  customCode?: string;
60
62
  };
61
- test?: ({
62
- _slug: 'test-object';
63
- dupa: string;
64
- })[];
65
63
  }
66
64
  export interface Project {
67
65
  _id: string;
@@ -91,6 +89,41 @@ export interface Project {
91
89
  customCode?: string;
92
90
  };
93
91
  }
92
+ export interface Product {
93
+ _id: string;
94
+ _slug: string;
95
+ _type: string;
96
+ _publishedAt: Date | null;
97
+ _url?: string;
98
+ title: string;
99
+ slug?: string;
100
+ category: 'apparel' | 'accessory' | 'print' | 'digital';
101
+ cover: ImageFieldData | VideoFieldData;
102
+ gallery?: (ImageFieldData | VideoFieldData)[] | null;
103
+ description?: StructuredContentDoc;
104
+ shop?: {
105
+ basePrice: number;
106
+ vatRate: number;
107
+ isActive: boolean;
108
+ variants: Array<{
109
+ id: string;
110
+ sku: string | null;
111
+ name: Record<string, string> | null;
112
+ priceDelta: number;
113
+ stock: number | null;
114
+ attributes: Record<string, string> | null;
115
+ }>;
116
+ } | null;
117
+ seo: {
118
+ slug: string;
119
+ canonicalUrl?: string;
120
+ title: string;
121
+ description?: string;
122
+ ogImage?: string;
123
+ keywords?: string;
124
+ customCode?: string;
125
+ };
126
+ }
94
127
  export interface ArrayTest {
95
128
  _id: string;
96
129
  _slug: string;
@@ -98,6 +131,45 @@ export interface ArrayTest {
98
131
  _publishedAt: Date | null;
99
132
  _url?: string;
100
133
  name: string;
134
+ constrainedText?: string;
135
+ plainUrl?: {
136
+ url: string;
137
+ };
138
+ urlWithText?: {
139
+ url: string;
140
+ text?: string;
141
+ };
142
+ urlWithNewTab?: {
143
+ url: string;
144
+ newTab?: boolean;
145
+ };
146
+ urlRequired: {
147
+ url: string;
148
+ text?: string;
149
+ newTab?: boolean;
150
+ };
151
+ boundedNumber?: number;
152
+ eventAt?: string;
153
+ priority?: 'low' | 'medium' | 'high';
154
+ features?: ('comments' | 'sharing' | 'newsletter')[];
155
+ relatedProject?: Project;
156
+ relatedPosts?: BlogPost[];
157
+ attachment?: MediaFile | null;
158
+ attachments?: MediaFile[] | null;
159
+ attachmentList?: MediaFile | null;
160
+ attachmentsList?: MediaFile[] | null;
161
+ address?: {
162
+ _slug: 'address';
163
+ street: string;
164
+ city?: string;
165
+ country?: 'pl' | 'de' | 'us';
166
+ geo?: {
167
+ _slug: 'geo';
168
+ lat?: number;
169
+ lng?: number;
170
+ };
171
+ };
172
+ introVideo?: ImageFieldData | VideoFieldData | null;
101
173
  tags?: string[];
102
174
  localizedTags?: Record<string, string>[];
103
175
  scores?: number[];
@@ -121,6 +193,7 @@ export interface ArrayTest {
121
193
  export type CollectionEntryMap = {
122
194
  'blog-post': BlogPost;
123
195
  project: Project;
196
+ product: Product;
124
197
  'array-test': ArrayTest;
125
198
  };
126
199
  export type FormSlug = "contact";
@@ -8,15 +8,29 @@
8
8
  children,
9
9
  ...restProps
10
10
  }: WithoutChild<AccordionPrimitive.ContentProps> = $props();
11
+
12
+ // `forceMount` keeps the panel mounted while closed so form validation can
13
+ // reach fields inside a collapsed accordion. The one-shot `animate-accordion-*`
14
+ // keyframe reverts once it finishes, leaving a permanently-mounted panel
15
+ // visible — so for the forced case the collapse is driven by a
16
+ // `grid-template-rows` transition instead: it holds its end state, animates
17
+ // both ways, and never flashes on the initial render. Without `forceMount`
18
+ // bits-ui mounts/unmounts the panel and the keyframe path is correct, so it
19
+ // is left untouched.
20
+ const forced = $derived(restProps.forceMount === true);
11
21
  </script>
12
22
 
13
23
  <AccordionPrimitive.Content
14
24
  bind:ref
15
25
  data-slot="accordion-content"
16
- class="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
26
+ class={forced
27
+ ? "grid text-sm transition-[grid-template-rows] duration-200 ease-out data-[state=closed]:grid-rows-[0fr] data-[state=open]:grid-rows-[1fr]"
28
+ : "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"}
17
29
  {...restProps}
18
30
  >
19
- <div class={cn("pb-4 pt-0", className)}>
20
- {@render children?.()}
31
+ <div class={forced ? "min-h-0 overflow-hidden" : "contents"}>
32
+ <div class={cn("pb-4 pt-0", className)}>
33
+ {@render children?.()}
34
+ </div>
21
35
  </div>
22
36
  </AccordionPrimitive.Content>