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
@@ -1,18 +1,110 @@
1
1
  <script lang="ts">
2
2
  import * as Dialog from '../../../components/ui/dialog/index.js';
3
3
  import { onMount } from 'svelte';
4
- import FilePreview from '../media/file-preview.svelte';
5
- import { buttonVariants } from '../../../components/ui/button/button.svelte';
6
- import MediaLibrary from '../media/media-library.svelte';
4
+ import Button from '../../../components/ui/button/button.svelte';
7
5
  import type { FileField } from '../../../types/fields.js';
8
- import z from 'zod';
6
+ import type { InterfaceLanguage } from '../../../types/languages.js';
7
+ import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
8
+ import Plus from '@tabler/icons-svelte/icons/plus';
9
+ import X from '@tabler/icons-svelte/icons/x';
10
+ import ChevronLeft from '@tabler/icons-svelte/icons/chevron-left';
11
+ import ChevronRight from '@tabler/icons-svelte/icons/chevron-right';
12
+ import AlertTriangle from '@tabler/icons-svelte/icons/alert-triangle';
13
+ import FileMiniature from '../media/file/file-miniature.svelte';
14
+ import { getRemotes } from '../../../sveltekit/index.js';
15
+ import MediaSelector from '../media/media-selector.svelte';
16
+ import type { MediaFile } from '../../../types/media.js';
17
+ import { formatFileSize, getFileExtension } from '../../utils/fileDisplay.js';
18
+
19
+ const lang: Record<
20
+ InterfaceLanguage,
21
+ {
22
+ selectFile: string;
23
+ addFile: string;
24
+ remove: string;
25
+ change: string;
26
+ of: string;
27
+ missingFile: string;
28
+ removeAria: string;
29
+ }
30
+ > = {
31
+ pl: {
32
+ selectFile: 'Wybierz plik',
33
+ addFile: 'Dodaj plik',
34
+ remove: 'Usuń',
35
+ change: 'Zmień',
36
+ of: 'z',
37
+ missingFile: 'Brakujący plik',
38
+ removeAria: 'Usuń plik'
39
+ },
40
+ en: {
41
+ selectFile: 'Select file',
42
+ addFile: 'Add file',
43
+ remove: 'Remove',
44
+ change: 'Change',
45
+ of: 'of',
46
+ missingFile: 'Missing file',
47
+ removeAria: 'Remove file'
48
+ }
49
+ };
50
+
51
+ const interfaceLanguage = useInterfaceLanguage();
52
+ const remotes = getRemotes();
53
+
54
+ let currentIndex = $state(0);
55
+ let dialogOpen = $state(false);
56
+
57
+ function openPicker() {
58
+ dialogOpen = true;
59
+ }
9
60
 
10
61
  type Props = {
11
62
  field: FileField;
12
63
  value: string | string[] | undefined;
13
64
  };
14
65
 
15
- let { field, value = $bindable(), ...props }: Props = $props();
66
+ let { field, value = $bindable() }: Props = $props();
67
+
68
+ // Single-file state: fetch MediaFile via a plain fetch inside an $effect instead of
69
+ // `$derived(remotes.getFileById(value))`. Reason: wrapping the remote query in a
70
+ // $derived couples its lifecycle to the derivation's refcounting — rapid toggling
71
+ // of value ('' → id) around dialog unmount triggered "query instance is no longer
72
+ // active" errors. Wzorzec z media-field.
73
+ let singleFile = $state<MediaFile | null>(null);
74
+ let singleFileReady = $state(false);
75
+ $effect(() => {
76
+ const v = value;
77
+ if (typeof v !== 'string' || !v) {
78
+ singleFile = null;
79
+ singleFileReady = true;
80
+ return;
81
+ }
82
+ singleFileReady = false;
83
+ let cancelled = false;
84
+ (async () => {
85
+ try {
86
+ const data = await remotes.getFileById(v);
87
+ if (!cancelled) {
88
+ singleFile = data as MediaFile;
89
+ singleFileReady = true;
90
+ }
91
+ } catch {
92
+ if (!cancelled) {
93
+ singleFile = null;
94
+ singleFileReady = true;
95
+ }
96
+ }
97
+ })();
98
+ return () => {
99
+ cancelled = true;
100
+ };
101
+ });
102
+
103
+ const mFilesQuery = $derived(
104
+ Array.isArray(value) && value.length > 0
105
+ ? remotes.getMediaFiles({ data: { ids: value as string[] } })
106
+ : null
107
+ );
16
108
 
17
109
  onMount(() => {
18
110
  if (value === undefined) {
@@ -21,33 +113,255 @@
21
113
  });
22
114
  </script>
23
115
 
24
- {#if value !== undefined}
25
- <Dialog.Root>
26
- <Dialog.Trigger type="button" class={buttonVariants({ variant: 'outline' })}
27
- >Select File</Dialog.Trigger
28
- >
29
- <Dialog.Content class="max-h-[80vh] w-[80vw] !max-w-none overflow-y-scroll">
30
- <MediaLibrary bind:selected={value} multiple={field.multiple} accept={field.accept} />
31
- </Dialog.Content>
32
- </Dialog.Root>
116
+ {#snippet filePreview(file: MediaFile)}
117
+ <div class="aspect-square w-full overflow-hidden rounded-2xl border">
118
+ <FileMiniature {file} />
119
+ </div>
120
+ {/snippet}
33
121
 
34
- <div class="flex flex-wrap gap-2">
35
- {#if field.multiple && Array.isArray(value)}
36
- {#each value as item}
37
- {#if z.string().uuid().safeParse(item).success}
38
- <FilePreview
39
- id={item}
40
- class="aspect-square w-full max-w-[100px] object-cover object-center"
41
- />
122
+ {#snippet missingPlaceholder()}
123
+ <div
124
+ class="flex aspect-square w-full flex-col items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-warning/50 bg-warning/5 p-6"
125
+ >
126
+ <div class="rounded-full bg-warning/10 p-3">
127
+ <AlertTriangle class="h-6 w-6 text-warning" />
128
+ </div>
129
+ <span class="text-sm text-warning">{lang[interfaceLanguage.current].missingFile}</span>
130
+ </div>
131
+ {/snippet}
132
+
133
+ {#snippet listRow(file: MediaFile, onRemove: () => void)}
134
+ {@const ext = getFileExtension(file.url)}
135
+ <div class="flex items-center gap-3 rounded-lg border bg-card p-2 shadow-sm">
136
+ <div class="relative aspect-square w-10 shrink-0 overflow-hidden rounded">
137
+ <FileMiniature {file} mode="thumb" />
138
+ </div>
139
+ <div class="min-w-0 flex-1">
140
+ <div class="flex items-center gap-1.5 min-w-0">
141
+ <p class="truncate text-sm font-medium">{file.name}</p>
142
+ {#if ext}
143
+ <span class="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">{ext}</span>
42
144
  {/if}
43
- {/each}
44
- {:else if typeof value === 'string'}
45
- {#if z.string().uuid().safeParse(value).success}
46
- <FilePreview
47
- id={value}
48
- class="aspect-square w-full max-w-[100px] object-cover object-center"
49
- />
50
- {/if}
145
+ </div>
146
+ <p class="text-xs text-muted-foreground">{formatFileSize(file.size)}</p>
147
+ </div>
148
+ {#if !field.required || (Array.isArray(value) && value.length > 1)}
149
+ <Button
150
+ variant="ghost"
151
+ size="icon"
152
+ class="h-7 w-7 shrink-0 text-muted-foreground hover:text-destructive"
153
+ aria-label={lang[interfaceLanguage.current].removeAria}
154
+ onclick={onRemove}
155
+ >
156
+ <X class="h-4 w-4" />
157
+ </Button>
51
158
  {/if}
52
159
  </div>
160
+ {/snippet}
161
+
162
+ {#snippet listMissingRow(onRemove: () => void)}
163
+ <div class="flex items-center gap-3 rounded-lg border border-warning/40 bg-warning/5 p-2">
164
+ <div class="flex aspect-square w-10 shrink-0 items-center justify-center rounded bg-warning/10">
165
+ <AlertTriangle class="h-4 w-4 text-warning" />
166
+ </div>
167
+ <p class="min-w-0 flex-1 truncate text-sm text-warning">{lang[interfaceLanguage.current].missingFile}</p>
168
+ {#if !field.required || (Array.isArray(value) && value.length > 1)}
169
+ <Button
170
+ variant="ghost"
171
+ size="icon"
172
+ class="h-7 w-7 shrink-0 text-muted-foreground hover:text-destructive"
173
+ aria-label={lang[interfaceLanguage.current].removeAria}
174
+ onclick={onRemove}
175
+ >
176
+ <X class="h-4 w-4" />
177
+ </Button>
178
+ {/if}
179
+ </div>
180
+ {/snippet}
181
+
182
+ {#snippet mediaActions(onRemove: () => void)}
183
+ <div class="flex items-center justify-between gap-2 mt-1.5">
184
+ <Button size="sm" variant="secondary" class="h-8" onclick={openPicker}>
185
+ <Plus class="h-4 w-4" />
186
+ {lang[interfaceLanguage.current].change}
187
+ </Button>
188
+ {#if !field.required}
189
+ <Button variant="destructive" size="sm" class="h-8" onclick={onRemove}>
190
+ <X class="h-4 w-4" />
191
+ {lang[interfaceLanguage.current].remove}
192
+ </Button>
193
+ {/if}
194
+ </div>
195
+ {/snippet}
196
+
197
+ {#if value !== undefined}
198
+ {#if field.display === 'list'}
199
+ <!-- Compact list variant (non-visual files: PDF, audio, raw) -->
200
+ <div class="space-y-2 max-w-md">
201
+ {#if typeof value === 'string' && value !== ''}
202
+ {#if !singleFileReady}
203
+ <div class="animate-pulse bg-muted h-14 rounded-lg"></div>
204
+ {:else if singleFile}
205
+ {@render listRow(singleFile, () => { value = ''; })}
206
+ {:else}
207
+ {@render listMissingRow(() => { value = ''; })}
208
+ {/if}
209
+ {:else if Array.isArray(value) && value.length > 0}
210
+ {#if !mFilesQuery?.ready}
211
+ <div class="animate-pulse bg-muted h-14 rounded-lg"></div>
212
+ {:else if mFilesQuery?.current}
213
+ {@const files = mFilesQuery.current}
214
+ {#each value as id, i (id + '__' + i)}
215
+ {@const file = files.find((f) => f.id === id)}
216
+ {#if file}
217
+ {@render listRow(file, () => {
218
+ if (Array.isArray(value)) {
219
+ value = value.filter((_, idx) => idx !== i);
220
+ }
221
+ })}
222
+ {:else}
223
+ {@render listMissingRow(() => {
224
+ if (Array.isArray(value)) {
225
+ value = value.filter((_, idx) => idx !== i);
226
+ }
227
+ })}
228
+ {/if}
229
+ {/each}
230
+ {/if}
231
+ {/if}
232
+
233
+ {#if field.multiple || !value || (typeof value === 'string' && value === '') || (Array.isArray(value) && value.length === 0)}
234
+ <Button variant="outline" size="sm" onclick={openPicker}>
235
+ <Plus class="h-4 w-4" />
236
+ {field.multiple && Array.isArray(value) && value.length > 0
237
+ ? lang[interfaceLanguage.current].addFile
238
+ : lang[interfaceLanguage.current].selectFile}
239
+ </Button>
240
+ {:else}
241
+ <Button variant="outline" size="sm" onclick={openPicker}>
242
+ <Plus class="h-4 w-4" />
243
+ {lang[interfaceLanguage.current].change}
244
+ </Button>
245
+ {/if}
246
+ </div>
247
+ {:else if value && ((typeof value === 'string' && value !== '') || (Array.isArray(value) && value.length > 0))}
248
+ <div class="max-w-64">
249
+ {#if typeof value === 'string'}
250
+ {#if !singleFileReady}
251
+ <div class="animate-pulse bg-muted w-full aspect-square rounded-2xl"></div>
252
+ {:else if singleFile}
253
+ {@render filePreview(singleFile)}
254
+ {@render mediaActions(() => { value = ''; })}
255
+ {:else}
256
+ {@render missingPlaceholder()}
257
+ {@render mediaActions(() => { value = ''; })}
258
+ {/if}
259
+ {:else if Array.isArray(value) && value.length > 0}
260
+ {@const valueArr = value}
261
+ {#if !mFilesQuery?.ready}
262
+ <div class="animate-pulse bg-muted w-full aspect-square rounded-2xl"></div>
263
+ {:else if mFilesQuery?.current}
264
+ {@const file = mFilesQuery.current[currentIndex]}
265
+ {#if file}
266
+ <div class="relative">
267
+ {@render filePreview(file)}
268
+
269
+ {#if valueArr.length > 1}
270
+ <div class="absolute inset-x-0 top-1/2 flex -translate-y-1/2 justify-between px-1 pointer-events-none">
271
+ <button
272
+ type="button"
273
+ class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
274
+ onclick={() => { currentIndex = currentIndex > 0 ? currentIndex - 1 : valueArr.length - 1; }}
275
+ >
276
+ <ChevronLeft class="h-5 w-5" />
277
+ </button>
278
+ <button
279
+ type="button"
280
+ class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
281
+ onclick={() => { currentIndex = currentIndex < valueArr.length - 1 ? currentIndex + 1 : 0; }}
282
+ >
283
+ <ChevronRight class="h-5 w-5" />
284
+ </button>
285
+ </div>
286
+ <div class="absolute top-2 right-2 rounded-full bg-plum-darker/60 px-2 py-0.5 text-xs font-medium text-white backdrop-blur">
287
+ {currentIndex + 1} / {valueArr.length}
288
+ </div>
289
+ {/if}
290
+ </div>
291
+ {@render mediaActions(() => {
292
+ if (Array.isArray(value)) {
293
+ const next = value.filter((_, i) => i !== currentIndex);
294
+ value = field.multiple ? next : next[0] ?? '';
295
+ if (currentIndex >= next.length) currentIndex = Math.max(0, next.length - 1);
296
+ }
297
+ })}
298
+ {:else}
299
+ <div class="relative">
300
+ {@render missingPlaceholder()}
301
+ {#if valueArr.length > 1}
302
+ <div class="absolute inset-x-0 top-1/2 flex -translate-y-1/2 justify-between px-1 pointer-events-none">
303
+ <button
304
+ type="button"
305
+ class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
306
+ onclick={() => { currentIndex = currentIndex > 0 ? currentIndex - 1 : valueArr.length - 1; }}
307
+ >
308
+ <ChevronLeft class="h-5 w-5" />
309
+ </button>
310
+ <button
311
+ type="button"
312
+ class="pointer-events-auto flex h-8 w-8 items-center justify-center rounded-full bg-white/80 backdrop-blur shadow-md transition hover:bg-white hover:scale-105 dark:bg-background/80 dark:hover:bg-background"
313
+ onclick={() => { currentIndex = currentIndex < valueArr.length - 1 ? currentIndex + 1 : 0; }}
314
+ >
315
+ <ChevronRight class="h-5 w-5" />
316
+ </button>
317
+ </div>
318
+ <div class="absolute top-2 right-2 rounded-full bg-plum-darker/60 px-2 py-0.5 text-xs font-medium text-white backdrop-blur">
319
+ {currentIndex + 1} / {valueArr.length}
320
+ </div>
321
+ {/if}
322
+ </div>
323
+ {@render mediaActions(() => {
324
+ if (Array.isArray(value)) {
325
+ const next = value.filter((_, i) => i !== currentIndex);
326
+ value = field.multiple ? next : next[0] ?? '';
327
+ if (currentIndex >= next.length) currentIndex = Math.max(0, next.length - 1);
328
+ }
329
+ })}
330
+ {/if}
331
+ {:else}
332
+ {@render missingPlaceholder()}
333
+ {@render mediaActions(() => { value = field.multiple ? [] : ''; })}
334
+ {/if}
335
+ {/if}
336
+ </div>
337
+ {:else}
338
+ <button
339
+ type="button"
340
+ class="flex aspect-square max-w-64 w-full flex-col items-center justify-center gap-2 rounded-2xl border-2 border-dashed border-border bg-card/80 p-6 transition-colors hover:border-primary/50 hover:bg-card"
341
+ onclick={openPicker}
342
+ >
343
+ <div class="rounded-full bg-muted p-3">
344
+ <Plus class="h-6 w-6 text-muted-foreground" />
345
+ </div>
346
+ <span class="text-sm text-muted-foreground">{lang[interfaceLanguage.current].selectFile}</span>
347
+ </button>
348
+ {/if}
349
+
350
+ <Dialog.Root bind:open={dialogOpen}>
351
+ <Dialog.Content
352
+ fullscreenMobile
353
+ class="flex h-[85vh] w-full max-w-6xl! flex-col overflow-hidden p-0 sm:max-w-6xl!"
354
+ >
355
+ <Dialog.Title class="sr-only">{lang[interfaceLanguage.current].selectFile}</Dialog.Title>
356
+ <Dialog.Description class="sr-only">{lang[interfaceLanguage.current].selectFile}</Dialog.Description>
357
+ <MediaSelector
358
+ bind:selected={value}
359
+ multiple={field.multiple}
360
+ accept={field.accept}
361
+ maxSizeMB={field.maxSizeMB}
362
+ onConfirm={() => (dialogOpen = false)}
363
+ onCancel={() => (dialogOpen = false)}
364
+ />
365
+ </Dialog.Content>
366
+ </Dialog.Root>
53
367
  {/if}
@@ -332,7 +332,12 @@
332
332
  {/if}
333
333
 
334
334
  <Dialog.Root bind:open={dialogOpen}>
335
- <Dialog.Content class="h-[85vh] w-full max-w-6xl! sm:max-w-6xl! overflow-hidden p-0 flex flex-col">
335
+ <Dialog.Content
336
+ fullscreenMobile
337
+ class="flex h-[85vh] w-full max-w-6xl! flex-col overflow-hidden p-0 sm:max-w-6xl!"
338
+ >
339
+ <Dialog.Title class="sr-only">{lang[interfaceLanguage.current].selectMedia}</Dialog.Title>
340
+ <Dialog.Description class="sr-only">{lang[interfaceLanguage.current].selectMedia}</Dialog.Description>
336
341
  <MediaSelector
337
342
  bind:selected={value}
338
343
  multiple={field.multiple}
@@ -345,7 +350,16 @@
345
350
 
346
351
  <!-- Lightbox for images -->
347
352
  <Dialog.Root bind:open={lightboxOpen}>
348
- <Dialog.Content class="max-w-[90vw] max-h-[90vh] p-2 bg-black/95 border-none">
353
+ <Dialog.Content
354
+ fullscreenMobile
355
+ class="max-h-[90vh] max-w-[90vw]! border-none bg-black/95 p-2"
356
+ >
357
+ <Dialog.Title class="sr-only">
358
+ {lightboxFile?.alt || lightboxFile?.name || ''}
359
+ </Dialog.Title>
360
+ <Dialog.Description class="sr-only">
361
+ {lightboxFile?.alt || lightboxFile?.name || ''}
362
+ </Dialog.Description>
349
363
  {#if lightboxFile}
350
364
  <div class="checkered-lightbox flex items-center justify-center">
351
365
  <img
@@ -15,11 +15,18 @@
15
15
 
16
16
  const interfaceLanguage = useInterfaceLanguage();
17
17
 
18
+ const clearLabel: Record<string, string> = {
19
+ pl: 'Wyczyść wybór',
20
+ en: 'Clear selection'
21
+ };
22
+
18
23
  onMount(() => {
19
24
  if (value === undefined) {
20
25
  value = field.defaultValue ?? '';
21
26
  }
22
27
  });
28
+
29
+ const canClear = $derived(!field.required && typeof value === 'string' && value !== '');
23
30
  </script>
24
31
 
25
32
  {#if value !== undefined}
@@ -35,4 +42,19 @@
35
42
  </div>
36
43
  {/each}
37
44
  </RadioGroup.Root>
45
+
46
+ {#if canClear}
47
+ <!--
48
+ Native radios have no native "uncheck" gesture. For optional fields,
49
+ expose an explicit Clear link so the editor can return to the
50
+ "no value" state without picking a sentinel option.
51
+ -->
52
+ <button
53
+ type="button"
54
+ class="text-muted-foreground hover:text-foreground mt-1 self-start text-xs underline-offset-2 hover:underline"
55
+ onclick={() => (value = '')}
56
+ >
57
+ {clearLabel[interfaceLanguage.current] ?? clearLabel.en}
58
+ </button>
59
+ {/if}
38
60
  {/if}