includio-cms 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (349) hide show
  1. package/API.md +57 -4
  2. package/CHANGELOG.md +53 -0
  3. package/DOCS.md +1 -1
  4. package/README.md +2 -0
  5. package/ROADMAP.md +6 -0
  6. package/dist/admin/client/account/lang.d.ts +1 -0
  7. package/dist/admin/client/account/lang.js +4 -2
  8. package/dist/admin/client/account/profile-section.svelte +2 -2
  9. package/dist/admin/client/account/security-section.svelte +27 -4
  10. package/dist/admin/client/account/sessions-section.svelte +1 -1
  11. package/dist/admin/client/admin/admin-after-login-layout-content.svelte +1 -1
  12. package/dist/admin/client/admin/dashboard-page.svelte +34 -10
  13. package/dist/admin/client/collection/bulk-actions-bar.svelte +86 -44
  14. package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +3 -1
  15. package/dist/admin/client/collection/collection-entries.svelte +52 -36
  16. package/dist/admin/client/collection/collection-entries.svelte.d.ts +3 -0
  17. package/dist/admin/client/collection/collection.svelte +28 -14
  18. package/dist/admin/client/collection/collection.svelte.d.ts +3 -0
  19. package/dist/admin/client/collection/data-table.svelte +279 -130
  20. package/dist/admin/client/collection/data-table.svelte.d.ts +11 -0
  21. package/dist/admin/client/collection/date-cell.svelte +4 -4
  22. package/dist/admin/client/collection/row-actions.svelte +2 -1
  23. package/dist/admin/client/collection/sortable-header.svelte +33 -9
  24. package/dist/admin/client/collection/state-display.svelte +102 -0
  25. package/dist/admin/client/collection/state-display.svelte.d.ts +12 -0
  26. package/dist/admin/client/collection/status-badge.svelte +99 -11
  27. package/dist/admin/client/collection/status-badge.svelte.d.ts +15 -1
  28. package/dist/admin/client/collection/table-pagination.svelte +21 -6
  29. package/dist/admin/client/collection/table-toolbar.svelte +105 -80
  30. package/dist/admin/client/collection/table-toolbar.svelte.d.ts +11 -8
  31. package/dist/admin/client/entry/entry-form.svelte +36 -11
  32. package/dist/admin/client/entry/entry-form.svelte.d.ts +1 -0
  33. package/dist/admin/client/entry/entry-header.svelte +22 -15
  34. package/dist/admin/client/entry/entry-header.svelte.d.ts +1 -0
  35. package/dist/admin/client/entry/entry.svelte +269 -165
  36. package/dist/admin/client/entry/header/a11y-header-badge.svelte +47 -0
  37. package/dist/admin/client/entry/header/a11y-header-badge.svelte.d.ts +8 -0
  38. package/dist/admin/client/entry/header/publish-panel.svelte +69 -13
  39. package/dist/admin/client/entry/header/save-indicator.svelte +57 -28
  40. package/dist/admin/client/entry/header/save-indicator.svelte.d.ts +1 -0
  41. package/dist/admin/client/entry/header/status-badge.svelte +60 -15
  42. package/dist/admin/client/entry/header/status-badge.svelte.d.ts +1 -2
  43. package/dist/admin/client/entry/header/version-history-sheet.svelte +1 -1
  44. package/dist/admin/client/entry/hybrid/hybrid-layout.svelte +74 -23
  45. package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +1 -1
  46. package/dist/admin/client/entry/utils.d.ts +14 -0
  47. package/dist/admin/client/entry/utils.js +28 -0
  48. package/dist/admin/client/form/form-submission/form-submission.svelte +2 -2
  49. package/dist/admin/client/form/form-submissions.svelte +143 -194
  50. package/dist/admin/client/form/form-submissions.svelte.d.ts +2 -0
  51. package/dist/admin/client/login/lang.d.ts +3 -0
  52. package/dist/admin/client/login/lang.js +10 -4
  53. package/dist/admin/client/login/login-form.svelte +8 -1
  54. package/dist/admin/client/login/reset-password-page.svelte +24 -3
  55. package/dist/admin/client/login/schema.d.ts +14 -2
  56. package/dist/admin/client/login/schema.js +19 -8
  57. package/dist/admin/client/maintenance/maintenance-page.svelte +16 -17
  58. package/dist/admin/client/media/media-page.svelte +1 -1
  59. package/dist/admin/client/shop/coupon-edit-page.svelte +117 -13
  60. package/dist/admin/client/shop/coupon-form.svelte +282 -138
  61. package/dist/admin/client/shop/coupon-form.svelte.d.ts +1 -9
  62. package/dist/admin/client/shop/coupon-new-page.svelte +40 -10
  63. package/dist/admin/client/shop/coupon-new-page.svelte.d.ts +2 -17
  64. package/dist/admin/client/shop/coupon-schema.d.ts +28 -0
  65. package/dist/admin/client/shop/coupon-schema.js +53 -0
  66. package/dist/admin/client/shop/coupons-list-page.svelte +262 -118
  67. package/dist/admin/client/shop/coupons-list-page.svelte.d.ts +16 -1
  68. package/dist/admin/client/shop/shipping-method-edit-page.svelte +108 -59
  69. package/dist/admin/client/shop/shipping-method-form.svelte +36 -9
  70. package/dist/admin/client/shop/shipping-method-new-page.svelte +44 -13
  71. package/dist/admin/client/shop/shipping-methods-list-page.svelte +101 -59
  72. package/dist/admin/client/shop/shop-order-detail-page.svelte +113 -84
  73. package/dist/admin/client/shop/shop-orders-list-page.svelte +302 -152
  74. package/dist/admin/client/shop/shop-orders-list-page.svelte.d.ts +18 -1
  75. package/dist/admin/client/shop/shop-products-list-page.svelte +355 -118
  76. package/dist/admin/client/shop/shop-products-list-page.svelte.d.ts +19 -1
  77. package/dist/admin/client/users/accept-invite-page.svelte +24 -3
  78. package/dist/admin/client/users/create-user-dialog.svelte +3 -8
  79. package/dist/admin/client/users/lang.d.ts +2 -0
  80. package/dist/admin/client/users/lang.js +4 -0
  81. package/dist/admin/client/users/pending-invitations.svelte +2 -9
  82. package/dist/admin/client/users/user-name-cell.svelte +20 -0
  83. package/dist/admin/client/users/user-name-cell.svelte.d.ts +9 -0
  84. package/dist/admin/client/users/user-role-badge.svelte +16 -0
  85. package/dist/admin/client/users/user-role-badge.svelte.d.ts +7 -0
  86. package/dist/admin/client/users/user-row-actions.svelte +72 -0
  87. package/dist/admin/client/users/user-row-actions.svelte.d.ts +20 -0
  88. package/dist/admin/client/users/user-sessions-sheet.svelte +2 -11
  89. package/dist/admin/client/users/users-page.svelte +283 -497
  90. package/dist/admin/client/users/users-page.svelte.d.ts +12 -1
  91. package/dist/admin/components/dashboard/form-submissions-widget.svelte +59 -74
  92. package/dist/admin/components/dashboard/recent-activity.svelte +17 -5
  93. package/dist/admin/components/dashboard/recent-entries.svelte +19 -7
  94. package/dist/admin/components/dialogs/confirmation-dialog.svelte +105 -0
  95. package/dist/admin/components/dialogs/confirmation-dialog.svelte.d.ts +13 -0
  96. package/dist/admin/components/fields/block-picker-modal.svelte +6 -0
  97. package/dist/admin/components/fields/blocks-field.svelte +46 -1
  98. package/dist/admin/components/fields/boolean-field.svelte +1 -1
  99. package/dist/admin/components/fields/field-renderer.svelte +23 -21
  100. package/dist/admin/components/fields/file-field.svelte +344 -30
  101. package/dist/admin/components/fields/media-field.svelte +16 -2
  102. package/dist/admin/components/fields/radio-field.svelte +22 -0
  103. package/dist/admin/components/fields/relation-field.svelte +123 -97
  104. package/dist/admin/components/fields/relation-picker-dialog.svelte +2 -2
  105. package/dist/admin/components/fields/seo-field.svelte +60 -30
  106. package/dist/admin/components/fields/shop-field.svelte +9 -4
  107. package/dist/admin/components/fields/simple-array-field.svelte +321 -151
  108. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +3 -0
  109. package/dist/admin/components/fields/slug-field.svelte +146 -21
  110. package/dist/admin/components/fields/text-field-wrapper.svelte +37 -20
  111. package/dist/admin/components/fields/text-field.svelte +7 -2
  112. package/dist/admin/components/fields/url-field-wrapper.svelte +10 -0
  113. package/dist/admin/components/fields/url-field.svelte +36 -23
  114. package/dist/admin/components/forms/form-error-summary.svelte +143 -0
  115. package/dist/admin/components/forms/form-error-summary.svelte.d.ts +27 -0
  116. package/dist/admin/components/layout/app-sidebar.svelte +7 -2
  117. package/dist/admin/components/layout/detail-page-shell.svelte +71 -0
  118. package/dist/admin/components/layout/detail-page-shell.svelte.d.ts +24 -0
  119. package/dist/admin/components/layout/lang.d.ts +5 -0
  120. package/dist/admin/components/layout/lang.js +10 -0
  121. package/dist/admin/components/layout/layout-renderer.svelte +71 -2
  122. package/dist/admin/components/layout/layout-renderer.svelte.d.ts +1 -0
  123. package/dist/admin/components/layout/layout-tabs.svelte +172 -0
  124. package/dist/admin/components/layout/layout-tabs.svelte.d.ts +24 -0
  125. package/dist/admin/components/layout/nav-breadcrumbs.svelte +25 -7
  126. package/dist/admin/components/layout/nav-collections.svelte +23 -36
  127. package/dist/admin/components/layout/nav-forms.svelte +19 -35
  128. package/dist/admin/components/layout/nav-main.svelte +3 -28
  129. package/dist/admin/components/layout/nav-search.svelte +70 -2
  130. package/dist/admin/components/layout/nav-section.svelte +77 -0
  131. package/dist/admin/components/layout/nav-section.svelte.d.ts +22 -0
  132. package/dist/admin/components/layout/nav-shop.svelte +3 -27
  133. package/dist/admin/components/layout/nav-singletons.svelte +16 -28
  134. package/dist/admin/components/layout/page-header.stories.svelte +93 -0
  135. package/dist/admin/components/layout/page-header.stories.svelte.d.ts +27 -0
  136. package/dist/admin/components/layout/page-header.svelte +68 -0
  137. package/dist/admin/components/layout/page-header.svelte.d.ts +17 -0
  138. package/dist/admin/components/layout/site-header.svelte +9 -0
  139. package/dist/admin/components/layout/site-header.svelte.d.ts +2 -17
  140. package/dist/admin/components/media/file/file-name-input.svelte +6 -2
  141. package/dist/admin/components/media/file/file-preview.svelte +130 -17
  142. package/dist/admin/components/media/file-upload.svelte +16 -7
  143. package/dist/admin/components/media/file-upload.svelte.d.ts +1 -0
  144. package/dist/admin/components/media/files-list.svelte +153 -53
  145. package/dist/admin/components/media/files-list.svelte.d.ts +1 -0
  146. package/dist/admin/components/media/media-library.svelte +577 -198
  147. package/dist/admin/components/media/media-library.svelte.d.ts +4 -0
  148. package/dist/admin/components/media/media-selector.svelte +4 -2
  149. package/dist/admin/components/media/media-selector.svelte.d.ts +1 -0
  150. package/dist/admin/components/media/tag-sidebar.svelte +4 -4
  151. package/dist/admin/components/tiptap/FigureNodeView.svelte +10 -0
  152. package/dist/admin/components/tiptap/bubble-menu.svelte +104 -0
  153. package/dist/admin/components/tiptap/bubble-menu.svelte.d.ts +19 -0
  154. package/dist/admin/components/tiptap/content-editor.svelte +28 -24
  155. package/dist/admin/components/tiptap/editor-toolbar.svelte +7 -7
  156. package/dist/admin/components/tiptap/extensions.js +5 -1
  157. package/dist/admin/components/tiptap/image-dialog.svelte +5 -1
  158. package/dist/admin/components/tiptap/link-dialog.svelte +2 -0
  159. package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -20
  160. package/dist/admin/components/tiptap/video-dialog.svelte +1 -1
  161. package/dist/admin/i18n/errors.d.ts +140 -0
  162. package/dist/admin/i18n/errors.js +151 -0
  163. package/dist/admin/remote/entry.remote.d.ts +59 -4
  164. package/dist/admin/remote/entry.remote.js +239 -62
  165. package/dist/admin/remote/shop.remote.d.ts +37 -32
  166. package/dist/admin/remote/shop.remote.js +9 -2
  167. package/dist/admin/shared/password-generate.d.ts +6 -0
  168. package/dist/admin/shared/password-generate.js +40 -0
  169. package/dist/admin/shared/password-schema.d.ts +6 -0
  170. package/dist/admin/shared/password-schema.js +10 -3
  171. package/dist/admin/styles/admin.css +23 -6
  172. package/dist/admin/styles/tokens.md +244 -0
  173. package/dist/admin/utils/accordionActivation.d.ts +13 -0
  174. package/dist/admin/utils/accordionActivation.js +35 -0
  175. package/dist/admin/utils/entryLabel.d.ts +23 -0
  176. package/dist/admin/utils/entryLabel.js +51 -12
  177. package/dist/admin/utils/field-a11y.d.ts +29 -0
  178. package/dist/admin/utils/field-a11y.js +23 -0
  179. package/dist/admin/utils/fieldPathElement.d.ts +9 -0
  180. package/dist/admin/utils/fieldPathElement.js +18 -0
  181. package/dist/admin/utils/fileDisplay.d.ts +10 -0
  182. package/dist/admin/utils/fileDisplay.js +26 -0
  183. package/dist/admin/utils/flattenFormErrors.d.ts +19 -0
  184. package/dist/admin/utils/flattenFormErrors.js +102 -0
  185. package/dist/admin/utils/formatters.d.ts +12 -0
  186. package/dist/admin/utils/{formatDate.js → formatters.js} +23 -2
  187. package/dist/admin/utils/scrollWithin.d.ts +9 -0
  188. package/dist/admin/utils/scrollWithin.js +32 -0
  189. package/dist/admin/utils/tabActivation.d.ts +12 -0
  190. package/dist/admin/utils/tabActivation.js +24 -0
  191. package/dist/cms/runtime/schema.d.ts +1 -0
  192. package/dist/cms/runtime/schema.js +1 -0
  193. package/dist/cms/runtime/types.d.ts +80 -7
  194. package/dist/components/ui/accordion/accordion-content.svelte +17 -3
  195. package/dist/components/ui/accordion/accordion.stories.svelte +21 -1
  196. package/dist/components/ui/alert/alert.stories.svelte +14 -0
  197. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte +45 -0
  198. package/dist/components/ui/alert-dialog/alert-dialog.stories.svelte.d.ts +27 -0
  199. package/dist/components/ui/avatar/avatar.stories.svelte +27 -0
  200. package/dist/components/ui/badge/badge.stories.svelte +15 -0
  201. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +47 -0
  202. package/dist/components/ui/breadcrumb/breadcrumb.svelte +1 -1
  203. package/dist/components/ui/button/button.stories.svelte +53 -6
  204. package/dist/components/ui/button/button.svelte +39 -5
  205. package/dist/components/ui/button/button.svelte.d.ts +4 -0
  206. package/dist/components/ui/button-group/button-group.stories.svelte +44 -0
  207. package/dist/components/ui/button-group/button-group.stories.svelte.d.ts +27 -0
  208. package/dist/components/ui/calendar/calendar.stories.svelte +36 -0
  209. package/dist/components/ui/calendar/calendar.stories.svelte.d.ts +27 -0
  210. package/dist/components/ui/card/card.stories.svelte +7 -0
  211. package/dist/components/ui/carousel/carousel.stories.svelte +43 -0
  212. package/dist/components/ui/carousel/carousel.stories.svelte.d.ts +27 -0
  213. package/dist/components/ui/checkbox/checkbox.stories.svelte +67 -0
  214. package/dist/components/ui/checkbox/checkbox.stories.svelte.d.ts +27 -0
  215. package/dist/components/ui/checkbox/checkbox.svelte +3 -3
  216. package/dist/components/ui/command/command.stories.svelte +18 -0
  217. package/dist/components/ui/data-table/data-table.stories.svelte +61 -0
  218. package/dist/components/ui/data-table/data-table.stories.svelte.d.ts +18 -0
  219. package/dist/components/ui/dialog/dialog-content.svelte +5 -0
  220. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +2 -0
  221. package/dist/components/ui/dialog/dialog.stories.svelte +35 -0
  222. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte +74 -0
  223. package/dist/components/ui/dropdown-menu/dropdown-menu.stories.svelte.d.ts +27 -0
  224. package/dist/components/ui/field/field-context.svelte.d.ts +22 -0
  225. package/dist/components/ui/field/field-context.svelte.js +9 -0
  226. package/dist/components/ui/field/field-control.svelte +18 -0
  227. package/dist/components/ui/field/field-control.svelte.d.ts +8 -0
  228. package/dist/components/ui/field/field-description.svelte +12 -0
  229. package/dist/components/ui/field/field-error.svelte +14 -6
  230. package/dist/components/ui/field/field-label.svelte +10 -0
  231. package/dist/components/ui/field/field.stories.svelte +95 -9
  232. package/dist/components/ui/field/field.svelte +57 -0
  233. package/dist/components/ui/field/field.svelte.d.ts +2 -0
  234. package/dist/components/ui/field/index.d.ts +3 -1
  235. package/dist/components/ui/field/index.js +4 -2
  236. package/dist/components/ui/form/form-field-errors.svelte +1 -1
  237. package/dist/components/ui/form/form.stories.svelte +25 -0
  238. package/dist/components/ui/form/form.stories.svelte.d.ts +26 -0
  239. package/dist/components/ui/input/input.stories.svelte +26 -0
  240. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  241. package/dist/components/ui/input-group/input-group.stories.svelte +43 -0
  242. package/dist/components/ui/input-group/input-group.stories.svelte.d.ts +27 -0
  243. package/dist/components/ui/item/item.stories.svelte +61 -0
  244. package/dist/components/ui/item/item.stories.svelte.d.ts +27 -0
  245. package/dist/components/ui/label/label.stories.svelte +7 -0
  246. package/dist/components/ui/live-region/index.d.ts +1 -0
  247. package/dist/components/ui/live-region/index.js +1 -0
  248. package/dist/components/ui/live-region/live-region-demo.svelte +32 -0
  249. package/dist/components/ui/live-region/live-region-demo.svelte.d.ts +7 -0
  250. package/dist/components/ui/live-region/live-region.stories.svelte +23 -0
  251. package/dist/components/ui/live-region/live-region.stories.svelte.d.ts +26 -0
  252. package/dist/components/ui/live-region/live-region.svelte +12 -0
  253. package/dist/components/ui/live-region/live-region.svelte.d.ts +8 -0
  254. package/dist/components/ui/popover/popover.stories.svelte +34 -0
  255. package/dist/components/ui/radio-group/radio-group.stories.svelte +58 -0
  256. package/dist/components/ui/radio-group/radio-group.stories.svelte.d.ts +27 -0
  257. package/dist/components/ui/resizable/resizable.stories.svelte +56 -0
  258. package/dist/components/ui/resizable/resizable.stories.svelte.d.ts +27 -0
  259. package/dist/components/ui/select/select.stories.svelte +49 -0
  260. package/dist/components/ui/separator/separator.stories.svelte +18 -0
  261. package/dist/components/ui/sheet/sheet.stories.svelte +34 -0
  262. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  263. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +1 -0
  264. package/dist/components/ui/sidebar/sidebar-trigger.svelte +1 -1
  265. package/dist/components/ui/sidebar/sidebar.stories.svelte +72 -0
  266. package/dist/components/ui/sidebar/sidebar.stories.svelte.d.ts +27 -0
  267. package/dist/components/ui/skeleton/skeleton.stories.svelte +39 -0
  268. package/dist/components/ui/skeleton/skeleton.stories.svelte.d.ts +27 -0
  269. package/dist/components/ui/skeleton/skeleton.svelte +6 -0
  270. package/dist/components/ui/sonner/index.d.ts +1 -1
  271. package/dist/components/ui/sonner/index.js +1 -1
  272. package/dist/components/ui/sonner/sonner.stories.svelte +7 -0
  273. package/dist/components/ui/sonner/sonner.svelte +17 -1
  274. package/dist/components/ui/sonner/sonner.svelte.d.ts +6 -0
  275. package/dist/components/ui/spinner/spinner.stories.svelte +30 -0
  276. package/dist/components/ui/spinner/spinner.stories.svelte.d.ts +27 -0
  277. package/dist/components/ui/switch/switch.stories.svelte +56 -0
  278. package/dist/components/ui/switch/switch.stories.svelte.d.ts +27 -0
  279. package/dist/components/ui/table/table-cell.svelte +1 -1
  280. package/dist/components/ui/table/table-head.svelte +1 -1
  281. package/dist/components/ui/table/table.stories.svelte +68 -0
  282. package/dist/components/ui/table/table.stories.svelte.d.ts +27 -0
  283. package/dist/components/ui/table/table.svelte +1 -1
  284. package/dist/components/ui/tabs/tabs.stories.svelte +48 -0
  285. package/dist/components/ui/tabs/tabs.stories.svelte.d.ts +27 -0
  286. package/dist/components/ui/textarea/textarea.stories.svelte +21 -0
  287. package/dist/components/ui/toggle/toggle.stories.svelte +23 -0
  288. package/dist/components/ui/toggle-group/toggle-group.stories.svelte +43 -0
  289. package/dist/components/ui/tooltip/tooltip.stories.svelte +46 -6
  290. package/dist/core/fields/fieldSchemaToTs.d.ts +7 -0
  291. package/dist/core/fields/fieldSchemaToTs.js +234 -90
  292. package/dist/core/fields/layoutUtils.d.ts +4 -1
  293. package/dist/core/fields/layoutUtils.js +41 -4
  294. package/dist/core/fields/resolveSeo.d.ts +70 -0
  295. package/dist/core/fields/resolveSeo.js +88 -0
  296. package/dist/core/fields/seoFieldDescriptor.d.ts +43 -0
  297. package/dist/core/fields/seoFieldDescriptor.js +74 -0
  298. package/dist/core/fields/slugPath.d.ts +13 -0
  299. package/dist/core/fields/slugPath.js +32 -0
  300. package/dist/core/fields/urlUtils.d.ts +8 -0
  301. package/dist/core/fields/urlUtils.js +27 -0
  302. package/dist/core/index.d.ts +1 -0
  303. package/dist/core/index.js +1 -0
  304. package/dist/core/server/entries/operations/create.js +13 -0
  305. package/dist/core/server/entries/operations/get.d.ts +7 -0
  306. package/dist/core/server/entries/operations/get.js +10 -6
  307. package/dist/core/server/entries/operations/slugUniqueness.d.ts +37 -0
  308. package/dist/core/server/entries/operations/slugUniqueness.js +116 -0
  309. package/dist/core/server/entries/operations/update.d.ts +6 -1
  310. package/dist/core/server/entries/operations/update.js +24 -1
  311. package/dist/core/server/fields/slugResolver.d.ts +3 -13
  312. package/dist/core/server/fields/slugResolver.js +8 -37
  313. package/dist/core/server/generator/fields.js +10 -17
  314. package/dist/core/server/generator/formFields.js +2 -1
  315. package/dist/core/server/generator/generator.js +4 -4
  316. package/dist/core/server/generator/utils.d.ts +1 -0
  317. package/dist/core/server/generator/utils.js +4 -0
  318. package/dist/paraglide/messages/_index.d.ts +3 -36
  319. package/dist/paraglide/messages/_index.js +3 -71
  320. package/dist/paraglide/messages/hello_world.d.ts +5 -0
  321. package/dist/paraglide/messages/hello_world.js +33 -0
  322. package/dist/paraglide/messages/login_hello.d.ts +16 -0
  323. package/dist/paraglide/messages/login_hello.js +34 -0
  324. package/dist/paraglide/messages/login_please_login.d.ts +16 -0
  325. package/dist/paraglide/messages/login_please_login.js +34 -0
  326. package/dist/shop/server/orders.d.ts +1 -0
  327. package/dist/shop/server/orders.js +14 -0
  328. package/dist/shop/server/shop-data.d.ts +2 -0
  329. package/dist/shop/server/shop-data.js +20 -5
  330. package/dist/sveltekit/server/handle.js +17 -0
  331. package/dist/types/cms.schema.js +4 -2
  332. package/dist/types/fields.d.ts +35 -0
  333. package/dist/types/index.d.ts +1 -1
  334. package/dist/types/layout.d.ts +35 -2
  335. package/dist/updates/0.26.0/index.d.ts +2 -0
  336. package/dist/updates/0.26.0/index.js +51 -0
  337. package/dist/updates/index.js +3 -1
  338. package/package.json +29 -7
  339. package/dist/admin/client/collection/empty-state.svelte +0 -28
  340. package/dist/admin/client/collection/empty-state.svelte.d.ts +0 -9
  341. package/dist/admin/client/form/submission-status-badge.svelte +0 -41
  342. package/dist/admin/client/form/submission-status-badge.svelte.d.ts +0 -7
  343. package/dist/admin/components/media/file-preview.svelte +0 -51
  344. package/dist/admin/components/media/file-preview.svelte.d.ts +0 -6
  345. package/dist/admin/utils/formatDate.d.ts +0 -5
  346. package/dist/paraglide/messages/en.d.ts +0 -5
  347. package/dist/paraglide/messages/en.js +0 -14
  348. package/dist/paraglide/messages/pl.d.ts +0 -5
  349. package/dist/paraglide/messages/pl.js +0 -14
@@ -0,0 +1,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
+ }
@@ -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>
@@ -8,12 +8,32 @@
8
8
  title: 'UI/Layout/Accordion',
9
9
  component: Accordion,
10
10
  tags: ['autodocs'],
11
+ parameters: {
12
+ docs: {
13
+ description: {
14
+ component:
15
+ 'Składana sekcja treści. Używaj do ukrywania pól rzadziej edytowanych (np. SEO, indeksowanie). Każdy `AccordionTrigger` musi mieć tekst — screen reader sam zapowie stan rozwinięcia.',
16
+ },
17
+ },
18
+ },
19
+ argTypes: {
20
+ type: {
21
+ description: '`single` — tylko jedna sekcja otwarta naraz; `multiple` — wiele równocześnie.',
22
+ control: 'select',
23
+ options: ['single', 'multiple'],
24
+ },
25
+ collapsible: {
26
+ description: 'Czy sekcja może być w pełni zwinięta (dla `type=single`).',
27
+ control: 'boolean',
28
+ },
29
+ },
11
30
  });
12
31
  </script>
13
32
 
14
33
  <Story name="SEO Section">
15
34
  <div style="max-width:320px;border:1px solid var(--border);border-radius:12px;overflow:hidden;">
16
- <Accordion type="single" collapsible>
35
+ <!-- SUGESTIA(S3): wrapper Accordion drops bits-ui `collapsible` flag; re-expose lub udokumentuj -->
36
+ <Accordion type="single">
17
37
  <AccordionItem value="seo">
18
38
  <AccordionTrigger>
19
39
  <span style="display:flex;align-items:center;gap:8px;">
@@ -6,6 +6,20 @@
6
6
  title: 'UI/Feedback/Alert',
7
7
  component: Alert,
8
8
  tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: 'Komunikat o stanie systemu lub kontekstowa informacja. Niski priorytet — `default`. Wysoki — `destructive`. Zawsze trzymaj się jednego zdania w treści.',
13
+ },
14
+ },
15
+ },
16
+ argTypes: {
17
+ variant: {
18
+ control: 'select',
19
+ options: ['default', 'destructive'],
20
+ description: 'Wariant kolorystyczny — używaj `destructive` dla błędów lub akcji wymagających uwagi.',
21
+ },
22
+ },
9
23
  });
10
24
  </script>
11
25