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,25 +1,155 @@
1
1
  <script lang="ts">
2
2
  import { getRemotes } from '../../../sveltekit/index.js';
3
3
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
4
+ import { getBreadcrumbs } from '../../state/breadcrumbs.svelte.js';
5
+ import { sidebarLang } from '../../components/layout/lang.js';
4
6
  import { getLocalizedLabel } from '../../utils/collectionLabel.js';
5
7
  import { Button } from '../../../components/ui/button/index.js';
6
8
  import * as DropdownMenu from '../../../components/ui/dropdown-menu/index.js';
7
9
  import PlusIcon from '@tabler/icons-svelte/icons/plus';
8
10
  import ChevronDownIcon from '@tabler/icons-svelte/icons/chevron-down';
11
+ import { formatPlnPrice } from '../../utils/formatters.js';
12
+ import PageHeader from '../../components/layout/page-header.svelte';
13
+ import DataTable from '../collection/data-table.svelte';
14
+ import TableToolbar from '../collection/table-toolbar.svelte';
15
+ import TablePagination from '../collection/table-pagination.svelte';
16
+ import StateDisplay from '../collection/state-display.svelte';
17
+ import StatusBadge from '../collection/status-badge.svelte';
18
+ import SortableHeader from '../collection/sortable-header.svelte';
19
+ import EntryLink from '../collection/entry-link.svelte';
20
+ import { renderComponent } from '../../../components/ui/data-table/render-helpers.js';
21
+ import type { ColumnDef, PaginationState, SortingState } from '@tanstack/table-core';
22
+ import type { InterfaceLanguage } from '../../../types/languages.js';
23
+
24
+ export type ShopProductRow = {
25
+ entryId: string;
26
+ collectionSlug: string;
27
+ basePrice: number;
28
+ vatRate: number;
29
+ isActive: boolean;
30
+ variantCount: number;
31
+ totalStock: number | null;
32
+ publishedData: Record<string, unknown> | null;
33
+ draftData: Record<string, unknown> | null;
34
+ publishedByLang?: Record<string, Record<string, unknown>>;
35
+ draftByLang?: Record<string, Record<string, unknown>>;
36
+ published: boolean;
37
+ };
38
+
39
+ type Props = {
40
+ data?: ShopProductRow[];
41
+ state?: 'loading' | 'error' | 'ok';
42
+ };
43
+
44
+ let { data: injectedData, state: injectedState }: Props = $props();
45
+ const useInjectedData = $derived(injectedData !== undefined);
9
46
 
10
47
  const remotes = getRemotes();
11
48
  const interfaceLanguage = useInterfaceLanguage();
49
+ const breadcrumbs = getBreadcrumbs();
50
+
51
+ $effect(() => {
52
+ const s = sidebarLang[interfaceLanguage.current].shop;
53
+ breadcrumbs.state = [{ label: s.title }, { label: s.products }];
54
+ });
12
55
 
13
- const entriesQuery = $derived(remotes.listShopProductEntries());
56
+ const entriesQuery = $derived(useInjectedData ? null : remotes.listShopProductEntries());
14
57
  const collectionsQuery = $derived(remotes.listShopableCollections());
15
58
 
16
- function formatPrice(pln: number) {
17
- return new Intl.NumberFormat('pl-PL', {
18
- style: 'currency',
19
- currency: 'PLN',
20
- minimumFractionDigits: 2
21
- }).format(pln);
22
- }
59
+ const allRows = $derived<ShopProductRow[]>(
60
+ useInjectedData
61
+ ? (injectedData ?? [])
62
+ : ((entriesQuery?.current as ShopProductRow[] | undefined) ?? [])
63
+ );
64
+ const isLoading = $derived(
65
+ useInjectedData ? injectedState === 'loading' : !(entriesQuery?.ready ?? false)
66
+ );
67
+ const isError = $derived(
68
+ useInjectedData ? injectedState === 'error' : Boolean(entriesQuery?.error)
69
+ );
70
+
71
+ let searchQuery = $state('');
72
+ let publishedFilter = $state<string | null>(null);
73
+ let activeFilter = $state<string | null>(null);
74
+ let sorting = $state<SortingState>([]);
75
+ let pagination = $state<PaginationState>({ pageIndex: 0, pageSize: 20 });
76
+
77
+ const lang: Record<
78
+ InterfaceLanguage,
79
+ {
80
+ title: string;
81
+ search: string;
82
+ searchPlaceholder: string;
83
+ filterPublished: string;
84
+ filterActive: string;
85
+ statusPublished: string;
86
+ statusDraft: string;
87
+ activeYes: string;
88
+ activeNo: string;
89
+ addProduct: string;
90
+ emptyTitle: string;
91
+ emptyDescription: string;
92
+ columnName: string;
93
+ columnCollection: string;
94
+ columnBasePrice: string;
95
+ columnVat: string;
96
+ columnVariants: string;
97
+ columnStock: string;
98
+ columnStatus: string;
99
+ unlimited: string;
100
+ noResults: string;
101
+ }
102
+ > = {
103
+ en: {
104
+ title: 'Products',
105
+ search: 'Search',
106
+ searchPlaceholder: 'Search by name…',
107
+ filterPublished: 'Status',
108
+ filterActive: 'Active',
109
+ statusPublished: 'Published',
110
+ statusDraft: 'Draft',
111
+ activeYes: 'Active',
112
+ activeNo: 'Inactive',
113
+ addProduct: 'Add product',
114
+ emptyTitle: 'No products yet',
115
+ emptyDescription:
116
+ "Add a field { type: 'shop' } to a collection, then create an entry and fill out the Shop section.",
117
+ columnName: 'Name',
118
+ columnCollection: 'Collection',
119
+ columnBasePrice: 'Base price',
120
+ columnVat: 'VAT',
121
+ columnVariants: 'Variants',
122
+ columnStock: 'Stock',
123
+ columnStatus: 'Status',
124
+ unlimited: 'unlimited',
125
+ noResults: 'No results.'
126
+ },
127
+ pl: {
128
+ title: 'Produkty',
129
+ search: 'Szukaj',
130
+ searchPlaceholder: 'Szukaj po nazwie…',
131
+ filterPublished: 'Status',
132
+ filterActive: 'Aktywność',
133
+ statusPublished: 'Opublikowany',
134
+ statusDraft: 'Szkic',
135
+ activeYes: 'Aktywny',
136
+ activeNo: 'Nieaktywny',
137
+ addProduct: 'Dodaj produkt',
138
+ emptyTitle: 'Brak produktów',
139
+ emptyDescription:
140
+ "Dodaj pole { type: 'shop' } do kolekcji, a następnie utwórz wpis i wypełnij sekcję „Sklep”.",
141
+ columnName: 'Nazwa',
142
+ columnCollection: 'Kolekcja',
143
+ columnBasePrice: 'Cena bazowa',
144
+ columnVat: 'VAT',
145
+ columnVariants: 'Warianty',
146
+ columnStock: 'Magazyn',
147
+ columnStatus: 'Status',
148
+ unlimited: 'nieograniczony',
149
+ noResults: 'Brak wyników.'
150
+ }
151
+ };
152
+ const t = $derived(lang[interfaceLanguage.current]);
23
153
 
24
154
  function resolveTitle(data: Record<string, unknown> | null, fallback: string): string {
25
155
  if (!data) return fallback;
@@ -30,6 +160,80 @@
30
160
  return fallback;
31
161
  }
32
162
 
163
+ function pickByLang(
164
+ byLang: Record<string, Record<string, unknown>> | undefined,
165
+ preferred: string
166
+ ): Record<string, unknown> | null {
167
+ if (!byLang) return null;
168
+ if (byLang[preferred]) return byLang[preferred];
169
+ const first = Object.values(byLang)[0];
170
+ return first ?? null;
171
+ }
172
+
173
+ type EnrichedRow = ShopProductRow & { _title: string };
174
+
175
+ const enrichedRows = $derived<EnrichedRow[]>(
176
+ allRows.map((row) => {
177
+ const published = pickByLang(row.publishedByLang, interfaceLanguage.current) ?? row.publishedData;
178
+ const draft = pickByLang(row.draftByLang, interfaceLanguage.current) ?? row.draftData;
179
+ return {
180
+ ...row,
181
+ _title: resolveTitle(published ?? draft, row.collectionSlug)
182
+ };
183
+ })
184
+ );
185
+
186
+ const filteredRows = $derived.by(() => {
187
+ const q = searchQuery.trim().toLowerCase();
188
+ let list = enrichedRows;
189
+ if (q) list = list.filter((row) => row._title.toLowerCase().includes(q));
190
+ if (publishedFilter !== null) {
191
+ const wantPublished = publishedFilter === 'published';
192
+ list = list.filter((row) => row.published === wantPublished);
193
+ }
194
+ if (activeFilter !== null) {
195
+ const wantActive = activeFilter === 'active';
196
+ list = list.filter((row) => row.isActive === wantActive);
197
+ }
198
+ if (sorting.length > 0) {
199
+ const [{ id, desc }] = sorting;
200
+ list = [...list].sort((a, b) => {
201
+ const av = (a as unknown as Record<string, unknown>)[id];
202
+ const bv = (b as unknown as Record<string, unknown>)[id];
203
+ if (av == null && bv == null) return 0;
204
+ if (av == null) return desc ? 1 : -1;
205
+ if (bv == null) return desc ? -1 : 1;
206
+ if (av < bv) return desc ? 1 : -1;
207
+ if (av > bv) return desc ? -1 : 1;
208
+ return 0;
209
+ });
210
+ }
211
+ return list;
212
+ });
213
+
214
+ const totalItems = $derived(filteredRows.length);
215
+ const pageCount = $derived(Math.max(1, Math.ceil(totalItems / pagination.pageSize)));
216
+
217
+ const dataFilters = $derived([
218
+ {
219
+ slug: 'published',
220
+ label: t.filterPublished,
221
+ options: [
222
+ { value: 'published', label: t.statusPublished },
223
+ { value: 'draft', label: t.statusDraft }
224
+ ]
225
+ },
226
+ {
227
+ slug: 'isActive',
228
+ label: t.filterActive,
229
+ options: [
230
+ { value: 'active', label: t.activeYes },
231
+ { value: 'inactive', label: t.activeNo }
232
+ ]
233
+ }
234
+ ]);
235
+ const activeDataFilters = $derived({ published: publishedFilter, isActive: activeFilter });
236
+
33
237
  async function createInCollection(slug: string) {
34
238
  try {
35
239
  const newEntry = await remotes.createEntry({ type: 'collection', slug });
@@ -38,121 +242,154 @@
38
242
  alert(err instanceof Error ? err.message : 'Nie udało się utworzyć wpisu');
39
243
  }
40
244
  }
245
+
246
+ const columns = $derived.by<ColumnDef<EnrichedRow>[]>(() => [
247
+ {
248
+ accessorKey: '_title',
249
+ header: ({ column }) =>
250
+ renderComponent(SortableHeader<EnrichedRow>, { column, label: t.columnName, sorting }),
251
+ cell: (info) =>
252
+ renderComponent(EntryLink, {
253
+ name: info.row.original._title,
254
+ url: `/admin/entries/${info.row.original.entryId}`
255
+ })
256
+ },
257
+ {
258
+ accessorKey: 'collectionSlug',
259
+ header: t.columnCollection,
260
+ cell: (info) => info.row.original.collectionSlug
261
+ },
262
+ {
263
+ accessorKey: 'basePrice',
264
+ header: ({ column }) =>
265
+ renderComponent(SortableHeader<EnrichedRow>, {
266
+ column,
267
+ label: t.columnBasePrice,
268
+ sorting
269
+ }),
270
+ cell: (info) => formatPlnPrice(info.row.original.basePrice)
271
+ },
272
+ {
273
+ accessorKey: 'vatRate',
274
+ header: t.columnVat,
275
+ cell: (info) => `${info.row.original.vatRate}%`
276
+ },
277
+ {
278
+ accessorKey: 'variantCount',
279
+ header: t.columnVariants,
280
+ cell: (info) => info.row.original.variantCount
281
+ },
282
+ {
283
+ accessorKey: 'totalStock',
284
+ header: t.columnStock,
285
+ cell: (info) => info.row.original.totalStock ?? t.unlimited
286
+ },
287
+ {
288
+ id: 'status',
289
+ header: t.columnStatus,
290
+ cell: (info) =>
291
+ renderComponent(StatusBadge, {
292
+ variant: 'boolean',
293
+ active: info.row.original.published,
294
+ activeLabel: t.statusPublished,
295
+ inactiveLabel: t.statusDraft
296
+ })
297
+ },
298
+ {
299
+ id: 'isActive',
300
+ header: t.filterActive,
301
+ cell: (info) =>
302
+ renderComponent(StatusBadge, {
303
+ variant: 'boolean',
304
+ active: info.row.original.isActive,
305
+ activeLabel: t.activeYes,
306
+ inactiveLabel: t.activeNo
307
+ })
308
+ }
309
+ ]);
310
+
311
+ const collections = $derived(collectionsQuery?.current ?? []);
41
312
  </script>
42
313
 
43
- <div class="flex items-center justify-between gap-4 p-6">
44
- <div>
45
- <h1 class="text-2xl font-extrabold tracking-tight">Produkty</h1>
46
- <p class="text-muted-foreground text-sm">
47
- {#if entriesQuery.ready}
48
- {entriesQuery.current?.length ?? 0}
49
- {(entriesQuery.current?.length ?? 0) === 1 ? 'produkt' : 'produktów'}
50
- {:else}
51
- Ładowanie…
314
+ <div class="p-5 pb-24 md:p-7">
315
+ <PageHeader title={t.title} count={!isLoading && !isError ? allRows.length : undefined}>
316
+ {#snippet primaryActions()}
317
+ {#if collections.length === 1}
318
+ {@const only = collections[0]}
319
+ <Button onclick={() => createInCollection(only.slug)}>
320
+ <PlusIcon class="size-4" />
321
+ {t.addProduct}
322
+ </Button>
323
+ {:else if collections.length > 1}
324
+ <DropdownMenu.Root>
325
+ <DropdownMenu.Trigger>
326
+ {#snippet child({ props })}
327
+ <Button {...props}>
328
+ <PlusIcon class="size-4" />
329
+ {t.addProduct}
330
+ <ChevronDownIcon class="size-4" />
331
+ </Button>
332
+ {/snippet}
333
+ </DropdownMenu.Trigger>
334
+ <DropdownMenu.Content>
335
+ {#each collections as c (c.slug)}
336
+ <DropdownMenu.Item onclick={() => createInCollection(c.slug)}>
337
+ {getLocalizedLabel(c.labels?.singular, interfaceLanguage.current) ?? c.slug}
338
+ </DropdownMenu.Item>
339
+ {/each}
340
+ </DropdownMenu.Content>
341
+ </DropdownMenu.Root>
52
342
  {/if}
53
- </p>
54
- </div>
55
- {#if collectionsQuery.ready && collectionsQuery.current && collectionsQuery.current.length > 0}
56
- {#if collectionsQuery.current.length === 1}
57
- {@const only = collectionsQuery.current[0]}
58
- <Button onclick={() => createInCollection(only.slug)}>
59
- <PlusIcon class="mr-1 size-4" />
60
- Dodaj produkt
61
- </Button>
62
- {:else}
63
- <DropdownMenu.Root>
64
- <DropdownMenu.Trigger>
65
- {#snippet child({ props })}
66
- <Button {...props}>
67
- <PlusIcon class="mr-1 size-4" />
68
- Dodaj produkt
69
- <ChevronDownIcon class="ml-1 size-4" />
70
- </Button>
71
- {/snippet}
72
- </DropdownMenu.Trigger>
73
- <DropdownMenu.Content>
74
- {#each collectionsQuery.current as c (c.slug)}
75
- <DropdownMenu.Item onclick={() => createInCollection(c.slug)}>
76
- {getLocalizedLabel(c.labels?.singular, interfaceLanguage.current) ?? c.slug}
77
- </DropdownMenu.Item>
78
- {/each}
79
- </DropdownMenu.Content>
80
- </DropdownMenu.Root>
81
- {/if}
82
- {/if}
83
- </div>
343
+ {/snippet}
344
+ </PageHeader>
84
345
 
85
- <div class="px-6 pb-12">
86
- {#if !entriesQuery.ready}
87
- <div class="text-muted-foreground">Ładowanie…</div>
88
- {:else if (entriesQuery.current?.length ?? 0) === 0}
89
- <div class="bg-lavender-lighter/40 border-border rounded-xl border p-8 text-center text-sm">
90
- <p class="mb-2 font-semibold">Brak produktów</p>
91
- <p class="text-muted-foreground">
92
- Dodaj pole <code class="text-primary">&lbrace; type: 'shop' &rbrace;</code> do kolekcji, a następnie
93
- utwórz wpis i wypełnij sekcję „Sklep".
94
- </p>
95
- </div>
346
+ {#if isError}
347
+ <StateDisplay kind="error" />
348
+ {:else if isLoading}
349
+ <StateDisplay kind="loading" />
350
+ {:else if allRows.length === 0}
351
+ <StateDisplay kind="empty" title={t.emptyTitle} description={t.emptyDescription} />
96
352
  {:else}
97
- <div class="border-border overflow-hidden rounded-xl border">
98
- <table class="w-full text-sm">
99
- <thead class="bg-muted/50 text-left text-xs tracking-wide uppercase">
100
- <tr>
101
- <th class="px-4 py-3 font-semibold">Nazwa</th>
102
- <th class="px-4 py-3 font-semibold">Kolekcja</th>
103
- <th class="px-4 py-3 font-semibold">Cena bazowa</th>
104
- <th class="px-4 py-3 font-semibold">VAT</th>
105
- <th class="px-4 py-3 font-semibold">Warianty</th>
106
- <th class="px-4 py-3 font-semibold">Magazyn</th>
107
- <th class="px-4 py-3 font-semibold">Status</th>
108
- </tr>
109
- </thead>
110
- <tbody>
111
- {#each entriesQuery.current ?? [] as row (row.entryId)}
112
- {@const title = resolveTitle(row.publishedData ?? row.draftData, row.collectionSlug)}
113
- <tr class="border-border hover:bg-muted/30 border-t">
114
- <td class="px-4 py-3">
115
- <a href={`/admin/entries/${row.entryId}`} class="text-primary hover:underline">
116
- {title}
117
- </a>
118
- </td>
119
- <td class="text-muted-foreground px-4 py-3 font-mono text-xs">{row.collectionSlug}</td
120
- >
121
- <td class="px-4 py-3">{formatPrice(row.basePrice)}</td>
122
- <td class="px-4 py-3">{row.vatRate}%</td>
123
- <td class="px-4 py-3">{row.variantCount}</td>
124
- <td class="px-4 py-3">
125
- {#if row.totalStock == null}
126
- <span class="text-muted-foreground text-xs">nieograniczony</span>
127
- {:else}
128
- {row.totalStock}
129
- {/if}
130
- </td>
131
- <td class="px-4 py-3">
132
- <div class="flex gap-1.5">
133
- {#if row.published}
134
- <span
135
- class="inline-flex rounded-full bg-green-100 px-2 py-0.5 text-xs text-green-800"
136
- >Opublikowany</span
137
- >
138
- {:else}
139
- <span
140
- class="inline-flex rounded-full bg-yellow-100 px-2 py-0.5 text-xs text-yellow-800"
141
- >Szkic</span
142
- >
143
- {/if}
144
- {#if !row.isActive}
145
- <span
146
- class="inline-flex rounded-full bg-gray-100 px-2 py-0.5 text-xs text-gray-800"
147
- >Nieaktywny</span
148
- >
149
- {/if}
150
- </div>
151
- </td>
152
- </tr>
153
- {/each}
154
- </tbody>
155
- </table>
353
+ <TableToolbar
354
+ {searchQuery}
355
+ searchPlaceholder={t.searchPlaceholder}
356
+ searchLabel={t.search}
357
+ onSearchChange={(q) => {
358
+ searchQuery = q;
359
+ pagination = { ...pagination, pageIndex: 0 };
360
+ }}
361
+ hideStatusFilter
362
+ hideViewToggle
363
+ {dataFilters}
364
+ {activeDataFilters}
365
+ onDataFilterChange={(slug, value) => {
366
+ if (slug === 'published') publishedFilter = value;
367
+ else if (slug === 'isActive') activeFilter = value;
368
+ pagination = { ...pagination, pageIndex: 0 };
369
+ }}
370
+ />
371
+
372
+ <div class="overflow-hidden rounded-xl border bg-card shadow-sm">
373
+ <DataTable
374
+ data={filteredRows}
375
+ {columns}
376
+ enableSorting
377
+ enablePagination
378
+ {sorting}
379
+ onSortingChange={(s) => (sorting = s)}
380
+ {pagination}
381
+ onPaginationChange={(p) => (pagination = p)}
382
+ emptyTitle={t.noResults}
383
+ />
384
+
385
+ <TablePagination
386
+ pageIndex={pagination.pageIndex}
387
+ pageSize={pagination.pageSize}
388
+ {pageCount}
389
+ {totalItems}
390
+ onPageChange={(p) => (pagination = { ...pagination, pageIndex: p })}
391
+ onPageSizeChange={(s) => (pagination = { pageIndex: 0, pageSize: s })}
392
+ />
156
393
  </div>
157
394
  {/if}
158
395
  </div>
@@ -1,3 +1,21 @@
1
- declare const ShopProductsListPage: import("svelte").Component<Record<string, never>, {}, "">;
1
+ export type ShopProductRow = {
2
+ entryId: string;
3
+ collectionSlug: string;
4
+ basePrice: number;
5
+ vatRate: number;
6
+ isActive: boolean;
7
+ variantCount: number;
8
+ totalStock: number | null;
9
+ publishedData: Record<string, unknown> | null;
10
+ draftData: Record<string, unknown> | null;
11
+ publishedByLang?: Record<string, Record<string, unknown>>;
12
+ draftByLang?: Record<string, Record<string, unknown>>;
13
+ published: boolean;
14
+ };
15
+ type Props = {
16
+ data?: ShopProductRow[];
17
+ state?: 'loading' | 'error' | 'ok';
18
+ };
19
+ declare const ShopProductsListPage: import("svelte").Component<Props, {}, "">;
2
20
  type ShopProductsListPage = ReturnType<typeof ShopProductsListPage>;
3
21
  export default ShopProductsListPage;
@@ -8,6 +8,7 @@
8
8
  import { page } from '$app/state';
9
9
  import { usersLang } from './lang.js';
10
10
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
11
+ import { generatePassword } from '../../shared/password-generate.js';
11
12
 
12
13
  const interfaceLanguage = useInterfaceLanguage();
13
14
  const lang = $derived(usersLang[interfaceLanguage.current]);
@@ -61,6 +62,15 @@
61
62
  return null;
62
63
  }
63
64
 
65
+ function handleGeneratePassword() {
66
+ const pw = generatePassword();
67
+ password = pw;
68
+ confirmPassword = pw;
69
+ showPassword = true;
70
+ showConfirm = true;
71
+ error = '';
72
+ }
73
+
64
74
  async function handleSubmit(e: Event) {
65
75
  e.preventDefault();
66
76
  const validationError = validate();
@@ -198,9 +208,20 @@
198
208
  {strengthLabelText}: {strengthLabels[strength.level]}
199
209
  </p>
200
210
  {/if}
201
- <p id="invite-pw-hint" class="text-text-light mt-1 text-xs">
202
- {lang.passwordHint}
203
- </p>
211
+ <div class="mt-1 flex items-center justify-between gap-2">
212
+ <p id="invite-pw-hint" class="text-text-light text-xs">
213
+ {lang.passwordHint}
214
+ </p>
215
+ <Button
216
+ variant="link"
217
+ size="sm"
218
+ type="button"
219
+ class="h-auto shrink-0 p-0 text-xs"
220
+ onclick={handleGeneratePassword}
221
+ >
222
+ {lang.generatePassword}
223
+ </Button>
224
+ </div>
204
225
  </div>
205
226
  <div class="space-y-2">
206
227
  <Label for="invite-confirm">{lang.invite.confirmPassword}</Label>
@@ -11,6 +11,7 @@
11
11
  import { toast } from 'svelte-sonner';
12
12
  import { usersLang } from './lang.js';
13
13
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
14
+ import { generatePassword } from '../../shared/password-generate.js';
14
15
  import type { UserRole } from '../../../types/roles.js';
15
16
 
16
17
  type Props = {
@@ -32,13 +33,6 @@
32
33
  let error = $state('');
33
34
  let showPassword = $state(false);
34
35
 
35
- function generatePassword(length = 20): string {
36
- const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%&*';
37
- const array = new Uint8Array(length);
38
- crypto.getRandomValues(array);
39
- return Array.from(array, (b) => chars[b % chars.length]).join('');
40
- }
41
-
42
36
  function reset() {
43
37
  name = '';
44
38
  email = '';
@@ -111,6 +105,7 @@
111
105
  type="button"
112
106
  class="absolute right-2 top-1/2 -translate-y-1/2"
113
107
  style="color: var(--text-light);"
108
+ aria-label={showPassword ? lang.hidePassword : lang.showPassword}
114
109
  onclick={() => (showPassword = !showPassword)}
115
110
  >
116
111
  {#if showPassword}
@@ -126,7 +121,7 @@
126
121
  size="sm"
127
122
  class="shrink-0 gap-1.5"
128
123
  onclick={() => {
129
- password = generatePassword();
124
+ password = generatePassword(20);
130
125
  showPassword = true;
131
126
  }}
132
127
  >
@@ -15,6 +15,8 @@ export declare const usersLang: Record<InterfaceLanguage, {
15
15
  cancel: string;
16
16
  password: string;
17
17
  passwordHint: string;
18
+ showPassword: string;
19
+ hidePassword: string;
18
20
  passwordMinLength: string;
19
21
  passwordRequirements: string;
20
22
  passwordMismatch: string;
@@ -15,6 +15,8 @@ export const usersLang = {
15
15
  cancel: 'Cancel',
16
16
  password: 'Password',
17
17
  passwordHint: 'Min. 8 characters, uppercase, number and special character',
18
+ showPassword: 'Show password',
19
+ hidePassword: 'Hide password',
18
20
  passwordMinLength: 'Password must be at least 8 characters',
19
21
  passwordRequirements: 'Password must contain an uppercase letter, a number and a special character',
20
22
  passwordMismatch: 'Passwords do not match',
@@ -101,6 +103,8 @@ export const usersLang = {
101
103
  cancel: 'Anuluj',
102
104
  password: 'Hasło',
103
105
  passwordHint: 'Min. 8 znaków, wielka litera, cyfra i znak specjalny',
106
+ showPassword: 'Pokaż hasło',
107
+ hidePassword: 'Ukryj hasło',
104
108
  passwordMinLength: 'Hasło musi mieć min. 8 znaków',
105
109
  passwordRequirements: 'Hasło musi zawierać wielką literę, cyfrę i znak specjalny',
106
110
  passwordMismatch: 'Hasła nie są zgodne',
@@ -7,7 +7,7 @@
7
7
  import { toast } from 'svelte-sonner';
8
8
  import { usersLang } from './lang.js';
9
9
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
10
- import { toLocaleCode } from '../../utils/formatDate.js';
10
+ import { formatShortDateOnly } from '../../utils/formatters.js';
11
11
  import { getRoleLabel } from '../../utils/roleLabel.js';
12
12
 
13
13
  type Props = {
@@ -82,13 +82,6 @@
82
82
  }
83
83
  }
84
84
 
85
- function formatDate(date: string): string {
86
- return new Date(date).toLocaleString(toLocaleCode(interfaceLanguage.current), {
87
- year: 'numeric',
88
- month: 'short',
89
- day: 'numeric'
90
- });
91
- }
92
85
  </script>
93
86
 
94
87
  <section class="mt-10 users-fade-up" aria-labelledby="invitations-heading">
@@ -144,7 +137,7 @@
144
137
  class:users-expiring-soon={isExpiringSoon(inv.expiresAt)}
145
138
  style={isExpiringSoon(inv.expiresAt) ? '' : 'color: var(--muted-foreground);'}
146
139
  >
147
- {formatDate(inv.expiresAt)}
140
+ {formatShortDateOnly(inv.expiresAt, interfaceLanguage.current)}
148
141
  {#if isExpiringSoon(inv.expiresAt)}
149
142
  — {lang.invite.expiringSoon}
150
143
  {/if}