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
@@ -16,6 +16,7 @@
16
16
  import Spinner from '../../../components/ui/spinner/spinner.svelte';
17
17
  import type { InterfaceLanguage } from '../../../types/languages.js';
18
18
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
19
+ import { getContentLanguage } from '../../state/content-language.svelte.js';
19
20
  import { getLocalizedLabel } from '../../utils/collectionLabel.js';
20
21
  import { droppable, draggable } from '@thisux/sveltednd';
21
22
  import { arrayMove } from '../../utils/arrayMove.js';
@@ -23,6 +24,7 @@
23
24
  import { flip } from 'svelte/animate';
24
25
  import { fade } from 'svelte/transition';
25
26
  import RelationPickerDialog from './relation-picker-dialog.svelte';
27
+ import { LiveRegion } from '../../../components/ui/live-region/index.js';
26
28
 
27
29
  const lang: Record<
28
30
  InterfaceLanguage,
@@ -79,6 +81,7 @@
79
81
 
80
82
  const remotes = getRemotes();
81
83
  const interfaceLanguage = useInterfaceLanguage();
84
+ const contentLanguage = getContentLanguage();
82
85
 
83
86
  type Props = {
84
87
  field: RelationField;
@@ -90,6 +93,13 @@
90
93
  const multiple = $derived(field.multiple === true);
91
94
  const t = $derived(lang[interfaceLanguage.current]);
92
95
 
96
+ // Collection singular labels come from config Pascal/Title-cased (it is the
97
+ // noun's nominative — "Projekt", "Post"). Inside a sentence it should be
98
+ // lowercase ("Wybierz projekt"). Cheap rule: first char to lowercase.
99
+ function inSentence(label: string): string {
100
+ return label ? label.charAt(0).toLowerCase() + label.slice(1) : label;
101
+ }
102
+
93
103
  // Ensure value is array when multiple
94
104
  onMount(() => {
95
105
  if (multiple && !Array.isArray(value)) {
@@ -140,7 +150,8 @@
140
150
 
141
151
  const results = await remotes.getEntryLabels({
142
152
  slug: field.collection,
143
- ids: missing
153
+ ids: missing,
154
+ language: contentLanguage.current
144
155
  });
145
156
  const newCache = new Map(labelCache);
146
157
  for (const r of results) {
@@ -181,7 +192,8 @@
181
192
  slug: field.collection,
182
193
  search: search || undefined,
183
194
  status: 'published',
184
- limit: 100
195
+ limit: 100,
196
+ language: contentLanguage.current
185
197
  });
186
198
  pickerOptions = results.map((r) => ({ id: r.id, label: r.label }));
187
199
  if (results.length > 0) {
@@ -200,7 +212,8 @@
200
212
  const results = await remotes.getEntryLabels({
201
213
  slug: field.collection,
202
214
  status: 'published',
203
- limit: 100
215
+ limit: 100,
216
+ language: contentLanguage.current
204
217
  });
205
218
  pickerOptions = results.map((r) => ({ id: r.id, label: r.label }));
206
219
  totalCount = results.length > 0 ? results[0].total : 0;
@@ -366,7 +379,7 @@
366
379
  aria-haspopup="dialog"
367
380
  >
368
381
  <Plus class="h-4 w-4" />
369
- {t.add} {singularLabel}
382
+ {t.select} {inSentence(singularLabel)}
370
383
  </button>
371
384
 
372
385
  <RelationPickerDialog
@@ -393,10 +406,12 @@
393
406
  aria-expanded={popoverOpen}
394
407
  >
395
408
  <Plus class="h-4 w-4" />
396
- {t.add} {singularLabel}
409
+ {t.select} {inSentence(singularLabel)}
397
410
  </Popover.Trigger>
398
411
 
399
- <Popover.Content class="min-w-[280px] p-0">
412
+ <Popover.Content
413
+ class="w-[var(--bits-popover-anchor-width)] min-w-[280px] max-w-[calc(100vw-1rem)] p-0"
414
+ >
400
415
  <Command.Root>
401
416
  <Command.Input
402
417
  autofocus
@@ -434,107 +449,118 @@
434
449
  </Popover.Root>
435
450
  {/if}
436
451
 
437
- <!-- Live region for screen readers -->
438
- <div class="sr-only" aria-live="polite" role="status">
439
- {liveMessage || `${getArrayValue().length} ${t.selected}`}
440
- </div>
452
+ <LiveRegion message={liveMessage || `${getArrayValue().length} ${t.selected}`} />
441
453
  {:else}
442
- <!-- Single-select mode -->
443
- {#if value}
444
- <!-- Show selected chip -->
445
- <div class="flex items-center gap-2 rounded-md border bg-background px-3 py-2 text-sm">
446
- <span class="flex-1 truncate">{singleLabel}</span>
454
+ <!-- Single-select mode: the combobox trigger shows the selected label
455
+ (or a placeholder), with an inline X to clear. Standard shadcn/bits-ui
456
+ combobox UX replaces the previous chip + separate trigger pair. -->
457
+ {@const placeholder = `${t.select} ${inSentence(singularLabel)}`}
458
+ {@const triggerLabel = singleLabel || placeholder}
459
+
460
+ <div class="relative">
461
+ {#if useDialog}
447
462
  <button
448
463
  type="button"
449
- class="shrink-0 text-muted-foreground hover:text-destructive"
450
- onclick={clearValue}
451
- aria-label={t.clear}
452
- >
453
- <X class="h-3.5 w-3.5" />
454
- </button>
455
- </div>
456
- {/if}
457
-
458
- {#if useDialog}
459
- <button
460
- type="button"
461
- class={cn(
462
- buttonVariants({ variant: 'outline' }),
463
- 'w-full justify-between',
464
- !value && 'text-muted-foreground',
465
- value && 'mt-1.5'
466
- )}
467
- onclick={openPicker}
468
- role="combobox"
469
- aria-expanded={pickerOpen}
470
- aria-haspopup="dialog"
471
- {...props}
472
- >
473
- {`${t.select} ${singularLabel}`}
474
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 opacity-50" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
475
- </button>
476
-
477
- <RelationPickerDialog
478
- bind:open={pickerOpen}
479
- title="{t.dialogTitle} {singularLabel}"
480
- searchPlaceholder="{t.search} {collectionLabel}..."
481
- noResults={t.noResults}
482
- closeLabel={t.closeDialog}
483
- {multiple}
484
- selected={value ? [value as string] : []}
485
- options={pickerOptions}
486
- loading={pickerLoading}
487
- bind:searchValue
488
- onSearchChange={handleSearchChange}
489
- onSelect={toggleItem}
490
- onClose={closePicker}
491
- />
492
- {:else}
493
- <Popover.Root bind:open={popoverOpen}>
494
- <Popover.Trigger
495
- id={triggerId}
496
464
  class={cn(
497
465
  buttonVariants({ variant: 'outline' }),
498
466
  'w-full justify-between',
499
467
  !value && 'text-muted-foreground',
500
- value && 'mt-1.5'
468
+ value && 'pr-16'
501
469
  )}
470
+ onclick={openPicker}
502
471
  role="combobox"
503
- aria-expanded={popoverOpen}
472
+ aria-expanded={pickerOpen}
473
+ aria-haspopup="dialog"
504
474
  {...props}
505
475
  >
506
- {`${t.select} ${singularLabel}`}
507
- <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 opacity-50" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
508
- </Popover.Trigger>
476
+ <span class="truncate text-left">{triggerLabel}</span>
477
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0 opacity-50" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
478
+ </button>
509
479
 
510
- <Popover.Content class="min-w-[280px] p-0">
511
- <Command.Root>
512
- <Command.Input
513
- autofocus
514
- placeholder="{t.search} {collectionLabel}..."
515
- class="h-9"
516
- />
517
- <Command.List>
518
- <Command.Empty>{t.noResults}</Command.Empty>
519
- <Command.Group>
520
- {#each pickerOptions as option (option.id)}
521
- <Command.Item
522
- value={option.label}
523
- onSelect={() => {
524
- value = option.id;
525
- closePopoverAndFocus();
526
- }}
527
- >
528
- {option.label}
529
- <Check
530
- class={cn('ml-auto', option.id !== value && 'text-transparent')}
531
- />
532
- </Command.Item>
533
- {/each}
534
- </Command.Group>
535
- </Command.List>
536
- </Command.Root>
537
- </Popover.Content>
538
- </Popover.Root>
539
- {/if}
480
+ <RelationPickerDialog
481
+ bind:open={pickerOpen}
482
+ title="{t.dialogTitle} {inSentence(singularLabel)}"
483
+ searchPlaceholder="{t.search} {collectionLabel}..."
484
+ noResults={t.noResults}
485
+ closeLabel={t.closeDialog}
486
+ {multiple}
487
+ selected={value ? [value as string] : []}
488
+ options={pickerOptions}
489
+ loading={pickerLoading}
490
+ bind:searchValue
491
+ onSearchChange={handleSearchChange}
492
+ onSelect={toggleItem}
493
+ onClose={closePicker}
494
+ />
495
+ {:else}
496
+ <Popover.Root bind:open={popoverOpen}>
497
+ <Popover.Trigger
498
+ id={triggerId}
499
+ class={cn(
500
+ buttonVariants({ variant: 'outline' }),
501
+ 'w-full justify-between',
502
+ !value && 'text-muted-foreground',
503
+ value && 'pr-16'
504
+ )}
505
+ role="combobox"
506
+ aria-expanded={popoverOpen}
507
+ {...props}
508
+ >
509
+ <span class="truncate text-left">{triggerLabel}</span>
510
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 shrink-0 opacity-50" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
511
+ </Popover.Trigger>
512
+
513
+ <Popover.Content
514
+ class="w-[var(--bits-popover-anchor-width)] min-w-[280px] max-w-[calc(100vw-1rem)] p-0"
515
+ >
516
+ <Command.Root>
517
+ <Command.Input
518
+ autofocus
519
+ placeholder="{t.search} {collectionLabel}..."
520
+ class="h-9"
521
+ />
522
+ <Command.List>
523
+ <Command.Empty>{t.noResults}</Command.Empty>
524
+ <Command.Group>
525
+ {#each pickerOptions as option (option.id)}
526
+ <Command.Item
527
+ value={option.label}
528
+ onSelect={() => {
529
+ value = option.id;
530
+ closePopoverAndFocus();
531
+ }}
532
+ >
533
+ {option.label}
534
+ <Check
535
+ class={cn('ml-auto', option.id !== value && 'text-transparent')}
536
+ />
537
+ </Command.Item>
538
+ {/each}
539
+ </Command.Group>
540
+ </Command.List>
541
+ </Command.Root>
542
+ </Popover.Content>
543
+ </Popover.Root>
544
+ {/if}
545
+
546
+ {#if value}
547
+ <!--
548
+ Absolute-positioned clear button next to the chevron. Sits inside
549
+ the trigger's right padding (`pr-16` above) so it doesn't overlap
550
+ the label, and stops propagation to avoid opening the picker.
551
+ -->
552
+ <button
553
+ type="button"
554
+ class="text-muted-foreground hover:text-destructive absolute top-1/2 right-9 -translate-y-1/2 rounded-sm p-0.5"
555
+ onclick={(e) => {
556
+ e.preventDefault();
557
+ e.stopPropagation();
558
+ clearValue();
559
+ }}
560
+ aria-label={t.clear}
561
+ >
562
+ <X class="h-3.5 w-3.5" />
563
+ </button>
564
+ {/if}
565
+ </div>
540
566
  {/if}
@@ -67,9 +67,9 @@
67
67
  onValueChange={(v) => onSearchChange(v)}
68
68
  class="h-10"
69
69
  />
70
- <Command.List class="max-h-[50vh] flex-1 overflow-y-auto">
70
+ <Command.List class="max-h-[50vh] flex-1 overflow-y-auto" aria-busy={loading}>
71
71
  {#if loading}
72
- <div class="flex items-center justify-center py-6">
72
+ <div class="flex items-center justify-center py-6" role="status" aria-label="Ładowanie wyników">
73
73
  <Spinner class="size-5" />
74
74
  </div>
75
75
  {:else if options.length === 0}
@@ -103,14 +103,6 @@
103
103
  required: false
104
104
  };
105
105
 
106
- const titleField: TextField = {
107
- type: 'text',
108
- slug: 'title',
109
- label: labels.title.label,
110
- description: labels.title.description,
111
- required: true
112
- };
113
-
114
106
  const descriptionField: TextField = {
115
107
  type: 'text',
116
108
  slug: 'description',
@@ -149,7 +141,6 @@
149
141
 
150
142
  const fields: Field[] = [
151
143
  canonicalUrlField,
152
- titleField,
153
144
  descriptionField,
154
145
  keyWordsField,
155
146
  ogImageField,
@@ -179,9 +170,11 @@
179
170
  return 'text-destructive';
180
171
  }
181
172
 
182
- // Slug field proxy for direct input binding
173
+ // Slug + title field proxies for direct input binding
183
174
  const slugPath = joinPath(String(path), 'slug');
175
+ const titlePath = joinPath(String(path), 'title');
184
176
  const { value: slugValue } = formFieldProxy(form, slugPath as FormPathLeaves<Record<string, unknown>>);
177
+ const { value: titleValue } = formFieldProxy(form, titlePath as FormPathLeaves<Record<string, unknown>>);
185
178
 
186
179
  // Auto-gen: track last auto-generated value
187
180
  let lastAutoSlug = '';
@@ -229,24 +222,46 @@
229
222
  $formData = $formData;
230
223
  }
231
224
 
232
- // titleSource auto-fill seo.title (flat)
225
+ // Auto title toggle (analogiczne do autoSlug)
226
+ let autoTitle = $state((() => {
227
+ if (!field.titleSource) return false;
228
+ if (wasPublished) return false;
229
+ const sourceRaw = ($formData as Record<string, unknown>)[field.titleSource];
230
+ if (!sourceRaw || typeof sourceRaw !== 'string') return true;
231
+ const current = getAtPath($formData as Record<string, unknown>, titlePath) as string | undefined;
232
+ if (current != null && current !== '' && current !== sourceRaw) return false;
233
+ return true;
234
+ })());
235
+
236
+ // titleSource → auto-fill seo.title (flat) — tylko gdy autoTitle włączony
233
237
  $effect(() => {
234
- if (!field.titleSource) return;
238
+ if (!field.titleSource || !autoTitle) return;
235
239
  const sourceRaw = ($formData as Record<string, unknown>)[field.titleSource];
236
240
  if (!sourceRaw || typeof sourceRaw !== 'string') return;
237
241
 
238
242
  untrack(() => {
239
- const titlePath = joinPath(String(path), 'title');
240
243
  const current = getAtPath($formData as Record<string, unknown>, titlePath) as string | undefined;
241
- if (!current || current === lastAutoTitle) {
242
- if (sourceRaw !== current) {
243
- setAtPath($formData as Record<string, unknown>, titlePath, sourceRaw);
244
- $formData = $formData;
245
- }
246
- lastAutoTitle = sourceRaw;
244
+ if (sourceRaw !== current) {
245
+ setAtPath($formData as Record<string, unknown>, titlePath, sourceRaw);
246
+ $formData = $formData;
247
247
  }
248
+ lastAutoTitle = sourceRaw;
248
249
  });
249
250
  });
251
+
252
+ function onAutoTitleToggle(checked: boolean) {
253
+ if (!checked || !field.titleSource) return;
254
+ const sourceRaw = ($formData as Record<string, unknown>)[field.titleSource];
255
+ if (!sourceRaw || typeof sourceRaw !== 'string') return;
256
+ setAtPath($formData as Record<string, unknown>, titlePath, sourceRaw);
257
+ lastAutoTitle = sourceRaw;
258
+ $formData = $formData;
259
+ }
260
+
261
+ // User edycja inputa tytułu → wyłącz auto (analogiczne do slug-field cichy flip)
262
+ function onTitleInput() {
263
+ if (autoTitle) autoTitle = false;
264
+ }
250
265
  </script>
251
266
 
252
267
  <div class="space-y-4">
@@ -267,6 +282,31 @@
267
282
  </div>
268
283
  <Form.Description>{getLocalizedLabel(labels.slug.description, interfaceLanguage.current)}</Form.Description>
269
284
  </Form.Field>
285
+
286
+ <!-- Title field with auto/manual toggle (analogiczne do slug) -->
287
+ <Form.Field {form} name={titlePath} class="space-y-1">
288
+ <div class="flex items-center justify-between">
289
+ <Form.Label>{getLocalizedLabel(labels.title.label, interfaceLanguage.current)}</Form.Label>
290
+ {#if field.titleSource}
291
+ <div class="flex items-center gap-2">
292
+ <span class="text-sm font-medium text-muted-foreground">Auto</span>
293
+ <Switch bind:checked={autoTitle} onCheckedChange={onAutoTitleToggle} />
294
+ </div>
295
+ {/if}
296
+ </div>
297
+ <Input bind:value={$titleValue} readonly={autoTitle} oninput={onTitleInput} />
298
+ <Form.Description>{getLocalizedLabel(labels.title.description, interfaceLanguage.current)}</Form.Description>
299
+ <p class="mt-1 text-xs {charHintClass(titleLength, 50, 60)}" aria-live="polite">
300
+ {titleLength}/60
301
+ {#if titleLength > 0 && titleLength < 50}
302
+ — {getLocalizedLabel({ en: 'a bit short', pl: 'trochę za krótko' }, interfaceLanguage.current)}
303
+ {:else if titleLength > 60}
304
+ — {getLocalizedLabel({ en: 'too long', pl: 'za długo' }, interfaceLanguage.current)}
305
+ {/if}
306
+ </p>
307
+ <Form.FieldErrors />
308
+ </Form.Field>
309
+
270
310
  {#each fields as f}
271
311
  <div>
272
312
  <FieldRenderer
@@ -274,18 +314,8 @@
274
314
  {form}
275
315
  path={joinPath(path, f.slug)}
276
316
  />
277
- {#if f.slug === 'title'}
278
- <p class="mt-1 text-xs {charHintClass(titleLength, 50, 60)}">
279
- {titleLength}/60
280
- {#if titleLength > 0 && titleLength < 50}
281
- — {getLocalizedLabel({ en: 'a bit short', pl: 'trochę za krótko' }, interfaceLanguage.current)}
282
- {:else if titleLength > 60}
283
- — {getLocalizedLabel({ en: 'too long', pl: 'za długo' }, interfaceLanguage.current)}
284
- {/if}
285
- </p>
286
- {/if}
287
317
  {#if f.slug === 'description'}
288
- <p class="mt-1 text-xs {charHintClass(descLength, 120, 160)}">
318
+ <p class="mt-1 text-xs {charHintClass(descLength, 120, 160)}" aria-live="polite">
289
319
  {descLength}/160
290
320
  {#if descLength > 0 && descLength < 120}
291
321
  — {getLocalizedLabel({ en: 'a bit short', pl: 'trochę za krótko' }, interfaceLanguage.current)}
@@ -6,6 +6,7 @@
6
6
  import PlusIcon from '@tabler/icons-svelte/icons/plus';
7
7
  import BuildingStoreIcon from '@tabler/icons-svelte/icons/building-store';
8
8
  import { getRemotes } from '../../../sveltekit/index.js';
9
+ import { errorMessages } from '../../i18n/errors.js';
9
10
  import type { ShopField } from '../../../types/fields.js';
10
11
 
11
12
  type Props = { field: ShopField };
@@ -150,7 +151,7 @@
150
151
  await dataQuery.refresh();
151
152
  successMessage = 'Zapisano dane sklepu.';
152
153
  } catch (err) {
153
- errorMessage = err instanceof Error ? err.message : 'Nie udało się zapisać';
154
+ errorMessage = err instanceof Error ? err.message : errorMessages.server.saveFailed.pl;
154
155
  } finally {
155
156
  saving = false;
156
157
  }
@@ -183,9 +184,10 @@
183
184
  <span class="text-muted-foreground text-xs font-semibold">
184
185
  Cena bazowa ({inputMode === 'net' ? 'netto' : 'brutto'}, PLN)
185
186
  </span>
186
- <div class="bg-muted inline-flex rounded-md p-0.5 text-xs">
187
+ <div class="bg-muted inline-flex rounded-md p-0.5 text-xs" role="group" aria-label="Tryb wpisywania ceny">
187
188
  <button
188
189
  type="button"
190
+ aria-pressed={inputMode === 'net'}
189
191
  class="rounded px-2 py-0.5 {inputMode === 'net'
190
192
  ? 'bg-background text-primary font-semibold shadow-sm'
191
193
  : 'text-muted-foreground'}"
@@ -195,6 +197,7 @@
195
197
  </button>
196
198
  <button
197
199
  type="button"
200
+ aria-pressed={inputMode === 'gross'}
198
201
  class="rounded px-2 py-0.5 {inputMode === 'gross'
199
202
  ? 'bg-background text-primary font-semibold shadow-sm'
200
203
  : 'text-muted-foreground'}"
@@ -274,9 +277,10 @@
274
277
  <span class="text-muted-foreground text-xs">
275
278
  Zmiana ceny ({v.priceDeltaMode === 'net' ? 'netto' : 'brutto'}, PLN)
276
279
  </span>
277
- <div class="bg-muted inline-flex rounded-md p-0.5 text-[10px]">
280
+ <div class="bg-muted inline-flex rounded-md p-0.5 text-[10px]" role="group" aria-label="Tryb zmiany ceny wariantu {i + 1}">
278
281
  <button
279
282
  type="button"
283
+ aria-pressed={v.priceDeltaMode === 'net'}
280
284
  class="rounded px-1.5 py-0.5 {v.priceDeltaMode === 'net'
281
285
  ? 'bg-background text-primary font-semibold shadow-sm'
282
286
  : 'text-muted-foreground'}"
@@ -286,6 +290,7 @@
286
290
  </button>
287
291
  <button
288
292
  type="button"
293
+ aria-pressed={v.priceDeltaMode === 'gross'}
289
294
  class="rounded px-1.5 py-0.5 {v.priceDeltaMode === 'gross'
290
295
  ? 'bg-background text-primary font-semibold shadow-sm'
291
296
  : 'text-muted-foreground'}"
@@ -314,7 +319,7 @@
314
319
  </label>
315
320
  {/if}
316
321
  <div class="col-span-2 flex justify-end">
317
- <Button type="button" variant="ghost" size="sm" onclick={() => removeVariant(i)}>
322
+ <Button type="button" variant="ghost" size="sm" onclick={() => removeVariant(i)} aria-label="Usuń wariant {i + 1}">
318
323
  <TrashIcon class="size-4" />
319
324
  </Button>
320
325
  </div>