includio-cms 0.1.3 → 0.5.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 (313) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/ROADMAP.md +23 -13
  3. package/dist/admin/api/accept-invite.js +1 -5
  4. package/dist/admin/api/invite.js +7 -16
  5. package/dist/admin/client/account/account-page.svelte +20 -50
  6. package/dist/admin/client/account/lang.d.ts +15 -23
  7. package/dist/admin/client/account/lang.js +51 -67
  8. package/dist/admin/client/account/preferences-section.svelte +26 -84
  9. package/dist/admin/client/account/profile-section.svelte +60 -40
  10. package/dist/admin/client/account/schema.d.ts +11 -3
  11. package/dist/admin/client/account/schema.js +25 -16
  12. package/dist/admin/client/account/security-section.svelte +139 -105
  13. package/dist/admin/client/account/sessions-section.svelte +35 -34
  14. package/dist/admin/client/admin/admin-after-login-layout-content.svelte +3 -5
  15. package/dist/admin/client/admin/admin-layout.svelte +3 -2
  16. package/dist/admin/client/admin/admin-preloader.svelte +36 -0
  17. package/dist/admin/client/admin/admin-preloader.svelte.d.ts +18 -0
  18. package/dist/admin/client/admin/dashboard-page.svelte +55 -41
  19. package/dist/admin/client/collection/a11y-score-cell.svelte +45 -0
  20. package/dist/admin/client/collection/a11y-score-cell.svelte.d.ts +6 -0
  21. package/dist/admin/client/collection/bulk-actions-bar.svelte +83 -0
  22. package/dist/admin/client/collection/bulk-actions-bar.svelte.d.ts +9 -0
  23. package/dist/admin/client/collection/collection-entries.svelte +255 -256
  24. package/dist/admin/client/collection/collection-view.svelte.d.ts +4 -3
  25. package/dist/admin/client/collection/collection-view.svelte.js +9 -5
  26. package/dist/admin/client/collection/collection.svelte +22 -12
  27. package/dist/admin/client/collection/data-table.svelte +50 -39
  28. package/dist/admin/client/collection/data-table.svelte.d.ts +1 -0
  29. package/dist/admin/client/collection/date-cell.svelte +7 -5
  30. package/dist/admin/client/collection/date-cell.svelte.d.ts +1 -1
  31. package/dist/admin/client/collection/empty-state.svelte +28 -0
  32. package/dist/admin/client/collection/empty-state.svelte.d.ts +9 -0
  33. package/dist/admin/client/collection/entry-link.svelte +10 -4
  34. package/dist/admin/client/collection/entry-link.svelte.d.ts +1 -0
  35. package/dist/admin/client/collection/grid-view.svelte +21 -23
  36. package/dist/admin/client/collection/grid-view.svelte.d.ts +1 -2
  37. package/dist/admin/client/collection/row-actions.svelte +60 -0
  38. package/dist/admin/client/collection/row-actions.svelte.d.ts +9 -0
  39. package/dist/admin/client/collection/status-badge.svelte +7 -8
  40. package/dist/admin/client/collection/table-pagination.svelte +122 -79
  41. package/dist/admin/client/collection/table-pagination.svelte.d.ts +1 -0
  42. package/dist/admin/client/collection/table-toolbar.svelte +108 -88
  43. package/dist/admin/client/collection/table-toolbar.svelte.d.ts +8 -9
  44. package/dist/admin/client/entry/entry-form.svelte +109 -1
  45. package/dist/admin/client/entry/entry-header.svelte +96 -37
  46. package/dist/admin/client/entry/entry-header.svelte.d.ts +5 -0
  47. package/dist/admin/client/entry/entry.svelte +171 -60
  48. package/dist/admin/client/entry/header/a11y-validator.d.ts +46 -0
  49. package/dist/admin/client/entry/header/a11y-validator.js +311 -0
  50. package/dist/admin/client/entry/header/publish-panel.svelte +373 -131
  51. package/dist/admin/client/entry/header/publish-panel.svelte.d.ts +4 -0
  52. package/dist/admin/client/entry/header/save-indicator.svelte +33 -23
  53. package/dist/admin/client/entry/header/schedule-popover.svelte +1 -1
  54. package/dist/admin/client/entry/header/status-badge.svelte +25 -118
  55. package/dist/admin/client/entry/header/version-history-sheet.svelte +314 -98
  56. package/dist/admin/client/form/form-submission/form-submission.svelte +271 -83
  57. package/dist/admin/client/form/form-submission/submission-field.svelte +12 -12
  58. package/dist/admin/client/form/form-submissions.svelte +421 -139
  59. package/dist/admin/client/form/submission-link.svelte +8 -2
  60. package/dist/admin/client/form/submission-link.svelte.d.ts +1 -0
  61. package/dist/admin/client/form/submission-status-badge.svelte +18 -4
  62. package/dist/admin/client/form/submission-status-badge.svelte.d.ts +1 -0
  63. package/dist/admin/client/login/lang.d.ts +32 -0
  64. package/dist/admin/client/login/lang.js +66 -2
  65. package/dist/admin/client/login/login-form.svelte +237 -95
  66. package/dist/admin/client/login/login-form.svelte.d.ts +2 -17
  67. package/dist/admin/client/login/login-page.svelte +34 -98
  68. package/dist/admin/client/login/reset-password-page.svelte +235 -0
  69. package/dist/admin/client/login/reset-password-page.svelte.d.ts +4 -0
  70. package/dist/admin/client/login/schema.d.ts +15 -0
  71. package/dist/admin/client/login/schema.js +21 -0
  72. package/dist/admin/client/users/accept-invite-page.svelte +166 -37
  73. package/dist/admin/client/users/create-user-dialog.svelte +15 -7
  74. package/dist/admin/client/users/delete-user-dialog.svelte +81 -16
  75. package/dist/admin/client/users/delete-user-dialog.svelte.d.ts +4 -1
  76. package/dist/admin/client/users/edit-user-dialog.svelte +3 -0
  77. package/dist/admin/client/users/invite-user-dialog.svelte +16 -3
  78. package/dist/admin/client/users/lang.d.ts +27 -0
  79. package/dist/admin/client/users/lang.js +64 -10
  80. package/dist/admin/client/users/pending-invitations.svelte +59 -23
  81. package/dist/admin/client/users/users-page.svelte +471 -72
  82. package/dist/admin/components/accessibility/accessibility-overview.svelte +2 -7
  83. package/dist/admin/components/dashboard/a11y-gauge.svelte +90 -0
  84. package/dist/admin/components/dashboard/a11y-gauge.svelte.d.ts +18 -0
  85. package/dist/admin/components/dashboard/accessibility-hub.svelte +13 -12
  86. package/dist/admin/components/dashboard/form-submissions-widget.svelte +71 -113
  87. package/dist/admin/components/dashboard/index.d.ts +4 -2
  88. package/dist/admin/components/dashboard/index.js +4 -2
  89. package/dist/admin/components/dashboard/recent-activity.svelte +53 -75
  90. package/dist/admin/components/dashboard/recent-entries.svelte +94 -0
  91. package/dist/admin/components/dashboard/recent-entries.svelte.d.ts +18 -0
  92. package/dist/admin/components/dashboard/stat-card.svelte +2 -2
  93. package/dist/admin/components/dashboard/tip-of-the-day.svelte +109 -0
  94. package/dist/admin/components/dashboard/tip-of-the-day.svelte.d.ts +3 -0
  95. package/dist/admin/components/dashboard/welcome-header.svelte +45 -0
  96. package/dist/admin/components/dashboard/welcome-header.svelte.d.ts +3 -0
  97. package/dist/admin/components/fields/{array-field.svelte → blocks-field.svelte} +4 -4
  98. package/dist/admin/components/fields/{array-field.svelte.d.ts → blocks-field.svelte.d.ts} +5 -5
  99. package/dist/admin/components/fields/content-field.svelte +27 -0
  100. package/dist/admin/components/fields/content-field.svelte.d.ts +31 -0
  101. package/dist/admin/components/fields/field-renderer.svelte +9 -7
  102. package/dist/admin/components/fields/image-field.svelte +2 -2
  103. package/dist/admin/components/fields/media-field.svelte +2 -2
  104. package/dist/admin/components/fields/seo-field.svelte +205 -25
  105. package/dist/admin/components/fields/simple-array-field.svelte +289 -0
  106. package/dist/admin/components/fields/simple-array-field.svelte.d.ts +30 -0
  107. package/dist/admin/components/fields/slug-field.svelte +3 -2
  108. package/dist/admin/components/fields/standalone-field-renderer.svelte +148 -0
  109. package/dist/admin/components/fields/standalone-field-renderer.svelte.d.ts +9 -0
  110. package/dist/admin/components/fields/text-field-wrapper.svelte +13 -1
  111. package/dist/admin/components/fields/text-field-wrapper.svelte.d.ts +2 -2
  112. package/dist/admin/components/fields/url-field.svelte +5 -4
  113. package/dist/admin/components/layout/app-sidebar.svelte +27 -24
  114. package/dist/admin/components/layout/lang.d.ts +6 -0
  115. package/dist/admin/components/layout/lang.js +13 -1
  116. package/dist/admin/components/layout/layout-renderer.svelte +352 -0
  117. package/dist/admin/components/layout/layout-renderer.svelte.d.ts +14 -0
  118. package/dist/admin/components/layout/nav-breadcrumbs.svelte +4 -4
  119. package/dist/admin/components/layout/nav-collections.svelte +65 -36
  120. package/dist/admin/components/layout/nav-footer.svelte +31 -0
  121. package/dist/admin/components/layout/nav-footer.svelte.d.ts +18 -0
  122. package/dist/admin/components/layout/nav-forms.svelte +55 -30
  123. package/dist/admin/components/layout/nav-main.svelte +14 -52
  124. package/dist/admin/components/layout/nav-search.svelte +4 -3
  125. package/dist/admin/components/layout/nav-singletons.svelte +59 -17
  126. package/dist/admin/components/layout/nav-singletons.svelte.d.ts +17 -8
  127. package/dist/admin/components/layout/site-header.svelte +74 -13
  128. package/dist/admin/components/media/alt-input.svelte +32 -22
  129. package/dist/admin/components/media/bulk-action-bar.svelte +139 -150
  130. package/dist/admin/components/media/file/file-details.svelte +299 -217
  131. package/dist/admin/components/media/file/file-miniature.svelte +54 -41
  132. package/dist/admin/components/media/file/file-miniature.svelte.d.ts +1 -0
  133. package/dist/admin/components/media/file/file-preview.svelte +1 -1
  134. package/dist/admin/components/media/file-upload.svelte +24 -26
  135. package/dist/admin/components/media/files-list.svelte +112 -40
  136. package/dist/admin/components/media/files-list.svelte.d.ts +2 -0
  137. package/dist/admin/components/media/focal-point-input.svelte +122 -26
  138. package/dist/admin/components/media/media-library.svelte +127 -70
  139. package/dist/admin/components/media/media-search.svelte +6 -6
  140. package/dist/admin/components/media/media-sort.svelte +3 -1
  141. package/dist/admin/components/media/multi-file-summary.svelte +88 -68
  142. package/dist/admin/components/media/tag-combobox.svelte +141 -66
  143. package/dist/admin/components/media/tag-combobox.svelte.d.ts +1 -0
  144. package/dist/admin/components/media/tag-sidebar.svelte +139 -121
  145. package/dist/admin/components/tiptap/FigureNodeView.svelte +144 -15
  146. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte +254 -0
  147. package/dist/admin/components/tiptap/InlineBlockNodeView.svelte.d.ts +4 -0
  148. package/dist/admin/components/tiptap/SlashCommandPopup.svelte +212 -0
  149. package/dist/admin/components/tiptap/SlashCommandPopup.svelte.d.ts +8 -0
  150. package/dist/admin/components/tiptap/content-editor.svelte +280 -0
  151. package/dist/admin/components/tiptap/content-editor.svelte.d.ts +9 -0
  152. package/dist/admin/components/tiptap/editor-toolbar.svelte +230 -0
  153. package/dist/admin/components/tiptap/editor-toolbar.svelte.d.ts +16 -0
  154. package/dist/admin/components/tiptap/heading-a11y-plugin.d.ts +2 -0
  155. package/dist/admin/components/tiptap/heading-a11y-plugin.js +67 -0
  156. package/dist/admin/components/tiptap/image-dialog.svelte +172 -11
  157. package/dist/admin/components/tiptap/inline-block-node.d.ts +19 -0
  158. package/dist/admin/components/tiptap/inline-block-node.js +98 -0
  159. package/dist/admin/components/tiptap/link-dialog.svelte +9 -4
  160. package/dist/admin/components/tiptap/slash-command.d.ts +17 -0
  161. package/dist/admin/components/tiptap/slash-command.js +181 -0
  162. package/dist/admin/components/tiptap/structured-content-utils.d.ts +21 -0
  163. package/dist/admin/components/tiptap/structured-content-utils.js +150 -0
  164. package/dist/admin/components/tiptap/tiptap-editor.svelte +18 -190
  165. package/dist/admin/email/invite-template.d.ts +8 -0
  166. package/dist/admin/email/invite-template.js +99 -0
  167. package/dist/admin/email/reset-password-template.d.ts +7 -0
  168. package/dist/admin/email/reset-password-template.js +96 -0
  169. package/dist/admin/remote/ai.remote.d.ts +1 -0
  170. package/dist/admin/remote/ai.remote.js +4 -1
  171. package/dist/admin/remote/entry.remote.d.ts +8 -0
  172. package/dist/admin/remote/entry.remote.js +53 -4
  173. package/dist/admin/remote/preview.remote.js +2 -1
  174. package/dist/admin/shared/password-schema.d.ts +5 -0
  175. package/dist/admin/shared/password-schema.js +10 -0
  176. package/dist/admin/styles/admin.css +1530 -151
  177. package/dist/admin/utils/formatDate.d.ts +1 -0
  178. package/dist/admin/utils/formatDate.js +8 -0
  179. package/dist/admin/utils/roleLabel.d.ts +2 -0
  180. package/dist/admin/utils/roleLabel.js +13 -0
  181. package/dist/ai-claude/index.d.ts +2 -0
  182. package/dist/ai-claude/index.js +56 -0
  183. package/dist/cms/runtime/api.d.ts +6 -1
  184. package/dist/cms/runtime/api.js +3 -0
  185. package/dist/cms/runtime/schemas.d.ts +9 -1
  186. package/dist/cms/runtime/schemas.js +8 -0
  187. package/dist/cms/runtime/types.d.ts +82 -10
  188. package/dist/cms/runtime/types.js +4 -0
  189. package/dist/components/ui/accordion/accordion.stories.svelte +39 -0
  190. package/dist/components/ui/accordion/accordion.stories.svelte.d.ts +27 -0
  191. package/dist/components/ui/alert/alert.stories.svelte +53 -0
  192. package/dist/components/ui/alert/alert.stories.svelte.d.ts +27 -0
  193. package/dist/components/ui/alert/alert.svelte +5 -0
  194. package/dist/components/ui/alert/alert.svelte.d.ts +9 -0
  195. package/dist/components/ui/avatar/avatar.stories.svelte +16 -0
  196. package/dist/components/ui/avatar/avatar.stories.svelte.d.ts +27 -0
  197. package/dist/components/ui/badge/badge.stories.svelte +33 -0
  198. package/dist/components/ui/badge/badge.stories.svelte.d.ts +27 -0
  199. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte +33 -0
  200. package/dist/components/ui/breadcrumb/breadcrumb.stories.svelte.d.ts +27 -0
  201. package/dist/components/ui/button/button.stories.svelte +43 -0
  202. package/dist/components/ui/button/button.stories.svelte.d.ts +27 -0
  203. package/dist/components/ui/button/button.svelte +1 -2
  204. package/dist/components/ui/button/button.svelte.d.ts +0 -3
  205. package/dist/components/ui/button-group/button-group-separator.svelte.d.ts +1 -1
  206. package/dist/components/ui/card/card.stories.svelte +42 -0
  207. package/dist/components/ui/card/card.stories.svelte.d.ts +27 -0
  208. package/dist/components/ui/command/command.stories.svelte +51 -0
  209. package/dist/components/ui/command/command.stories.svelte.d.ts +27 -0
  210. package/dist/components/ui/dialog/dialog.stories.svelte +29 -0
  211. package/dist/components/ui/dialog/dialog.stories.svelte.d.ts +27 -0
  212. package/dist/components/ui/field/field-label.svelte.d.ts +1 -1
  213. package/dist/components/ui/field/field.stories.svelte +21 -0
  214. package/dist/components/ui/field/field.stories.svelte.d.ts +27 -0
  215. package/dist/components/ui/input/input.stories.svelte +40 -0
  216. package/dist/components/ui/input/input.stories.svelte.d.ts +27 -0
  217. package/dist/components/ui/input/input.svelte +2 -4
  218. package/dist/components/ui/item/item-separator.svelte.d.ts +1 -1
  219. package/dist/components/ui/label/label.stories.svelte +20 -0
  220. package/dist/components/ui/label/label.stories.svelte.d.ts +27 -0
  221. package/dist/components/ui/popover/popover.stories.svelte +29 -0
  222. package/dist/components/ui/popover/popover.stories.svelte.d.ts +27 -0
  223. package/dist/components/ui/select/select-group-heading.svelte.d.ts +1 -1
  224. package/dist/components/ui/select/select.stories.svelte +23 -0
  225. package/dist/components/ui/select/select.stories.svelte.d.ts +27 -0
  226. package/dist/components/ui/separator/separator.stories.svelte +24 -0
  227. package/dist/components/ui/separator/separator.stories.svelte.d.ts +27 -0
  228. package/dist/components/ui/sheet/sheet.stories.svelte +29 -0
  229. package/dist/components/ui/sheet/sheet.stories.svelte.d.ts +27 -0
  230. package/dist/components/ui/sidebar/sidebar-group.svelte +3 -3
  231. package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +2 -2
  232. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +28 -30
  233. package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +7 -7
  234. package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +1 -1
  235. package/dist/components/ui/sidebar/sidebar-trigger.svelte +4 -4
  236. package/dist/components/ui/sonner/sonner.stories.svelte +22 -0
  237. package/dist/components/ui/sonner/sonner.stories.svelte.d.ts +26 -0
  238. package/dist/components/ui/sonner/sonner.svelte +8 -2
  239. package/dist/components/ui/sonner/toast-demo.svelte +29 -0
  240. package/dist/components/ui/sonner/toast-demo.svelte.d.ts +6 -0
  241. package/dist/components/ui/textarea/textarea.stories.svelte +22 -0
  242. package/dist/components/ui/textarea/textarea.stories.svelte.d.ts +27 -0
  243. package/dist/components/ui/textarea/textarea.svelte +0 -2
  244. package/dist/components/ui/toggle/toggle.stories.svelte +22 -0
  245. package/dist/components/ui/toggle/toggle.stories.svelte.d.ts +27 -0
  246. package/dist/components/ui/toggle-group/toggle-group.stories.svelte +17 -0
  247. package/dist/components/ui/toggle-group/toggle-group.stories.svelte.d.ts +27 -0
  248. package/dist/components/ui/tooltip/tooltip.stories.svelte +26 -0
  249. package/dist/components/ui/tooltip/tooltip.stories.svelte.d.ts +27 -0
  250. package/dist/core/fields/fieldSchemaToTs.d.ts +1 -0
  251. package/dist/core/fields/fieldSchemaToTs.js +133 -1
  252. package/dist/core/fields/layoutUtils.d.ts +17 -0
  253. package/dist/core/fields/layoutUtils.js +149 -0
  254. package/dist/core/fields/structuredToHtml.d.ts +9 -0
  255. package/dist/core/fields/structuredToHtml.js +161 -0
  256. package/dist/core/server/entries/operations/create.js +2 -1
  257. package/dist/core/server/entries/operations/get.js +8 -6
  258. package/dist/core/server/entries/operations/update.d.ts +3 -0
  259. package/dist/core/server/entries/operations/update.js +30 -2
  260. package/dist/core/server/fields/queryStructuredContent.d.ts +15 -0
  261. package/dist/core/server/fields/queryStructuredContent.js +65 -0
  262. package/dist/core/server/fields/resolveImageFields.js +51 -2
  263. package/dist/core/server/fields/resolveRelationFields.js +2 -2
  264. package/dist/core/server/fields/resolveRichtextLinks.js +80 -13
  265. package/dist/core/server/fields/resolveUrlFields.js +57 -6
  266. package/dist/core/server/fields/slugResolver.d.ts +10 -0
  267. package/dist/core/server/fields/slugResolver.js +34 -0
  268. package/dist/core/server/generator/fields.js +15 -4
  269. package/dist/core/server/generator/generator.js +3 -2
  270. package/dist/files-local/index.js +126 -64
  271. package/dist/paraglide/.prettierignore +3 -0
  272. package/dist/paraglide/messages/_index.d.ts +36 -0
  273. package/dist/paraglide/messages/_index.js +72 -0
  274. package/dist/paraglide/messages/en.d.ts +5 -0
  275. package/dist/paraglide/messages/en.js +14 -0
  276. package/dist/paraglide/messages/pl.d.ts +5 -0
  277. package/dist/paraglide/messages/pl.js +14 -0
  278. package/dist/paraglide/messages.d.ts +2 -0
  279. package/dist/paraglide/messages.js +4 -0
  280. package/dist/paraglide/registry.d.ts +21 -0
  281. package/dist/paraglide/registry.js +31 -0
  282. package/dist/paraglide/runtime.d.ts +583 -0
  283. package/dist/paraglide/runtime.js +1402 -0
  284. package/dist/paraglide/server.d.ts +67 -0
  285. package/dist/paraglide/server.js +175 -0
  286. package/dist/server/auth.d.ts +5 -0
  287. package/dist/server/auth.js +12 -1
  288. package/dist/sveltekit/components/structured-content.svelte +204 -0
  289. package/dist/sveltekit/components/structured-content.svelte.d.ts +21 -0
  290. package/dist/sveltekit/config.d.ts +13 -3
  291. package/dist/sveltekit/index.d.ts +3 -0
  292. package/dist/sveltekit/index.js +3 -0
  293. package/dist/sveltekit/server/handle.js +1 -0
  294. package/dist/types/config.d.ts +3 -0
  295. package/dist/types/fields.d.ts +19 -2
  296. package/dist/types/index.d.ts +2 -0
  297. package/dist/types/index.js +2 -0
  298. package/dist/types/layout.d.ts +54 -0
  299. package/dist/types/layout.js +6 -0
  300. package/dist/types/structured-content.d.ts +63 -0
  301. package/dist/types/structured-content.js +1 -0
  302. package/dist/updates/0.1.4/index.d.ts +2 -0
  303. package/dist/updates/0.1.4/index.js +11 -0
  304. package/dist/updates/0.1.5/index.d.ts +2 -0
  305. package/dist/updates/0.1.5/index.js +18 -0
  306. package/dist/updates/0.2.0/index.d.ts +2 -0
  307. package/dist/updates/0.2.0/index.js +11 -0
  308. package/dist/updates/0.2.2/index.d.ts +2 -0
  309. package/dist/updates/0.2.2/index.js +13 -0
  310. package/dist/updates/0.5.0/index.d.ts +2 -0
  311. package/dist/updates/0.5.0/index.js +14 -0
  312. package/dist/updates/index.js +6 -1
  313. package/package.json +17 -10
@@ -1,107 +1,43 @@
1
1
  <script lang="ts">
2
- import { cn } from '../../../utils.js';
3
2
  import '../../styles/admin.css';
4
3
  import LoginForm from './login-form.svelte';
4
+ import { loginLang } from './lang.js';
5
+ import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
6
+
7
+ const interfaceLanguage = useInterfaceLanguage();
5
8
  </script>
6
9
 
7
- <div
8
- class="relative flex min-h-svh flex-col items-center justify-center overflow-hidden p-6 md:p-10"
9
- style="background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 50%, #cbd5e1 100%);"
10
+ <!-- Skip link (WCAG) -->
11
+ <a
12
+ href="#main-content"
13
+ class="sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-[9999] focus:rounded-lg focus:bg-primary focus:px-4 focus:py-2 focus:text-[13px] focus:font-semibold focus:text-primary-foreground"
10
14
  >
11
- <!-- Dark mode background -->
12
- <div
13
- class="pointer-events-none absolute inset-0 hidden dark:block"
14
- style="background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #2D4A77 100%);"
15
- ></div>
16
-
17
- <div class="relative z-10 w-full max-w-sm md:max-w-4xl">
18
- <div class={cn('flex flex-col gap-6')}>
19
- <!-- Main card with glass effect -->
20
- <div
21
- class="grid overflow-hidden rounded-3xl border border-slate-200/50 bg-white/80 shadow-2xl backdrop-blur-xl dark:border-white/10 dark:bg-slate-900/60 md:grid-cols-2"
22
- >
23
- <!-- Left: Form -->
24
- <LoginForm />
25
-
26
- <!-- Right: Gradient panel with orbs -->
27
- <div
28
- class="relative hidden overflow-hidden md:block"
29
- style="background: linear-gradient(135deg, #2D4A77 0%, #4975AE 50%, #375C92 100%);"
30
- aria-hidden="true"
31
- >
32
- <!-- Dot pattern overlay -->
33
- <div
34
- class="absolute inset-0 opacity-10"
35
- style="background-image: radial-gradient(circle, white 1px, transparent 1px); background-size: 20px 20px;"
36
- ></div>
37
-
38
- <!-- Floating orbs -->
39
- <div
40
- class="animate-float-slow absolute -top-10 -right-10 h-40 w-40 rounded-full bg-white/20 blur-xl"
41
- ></div>
42
- <div
43
- class="animate-float-slow absolute top-1/3 -left-5 h-32 w-32 rounded-full bg-white/15 blur-lg"
44
- style="animation-delay: -3s;"
45
- ></div>
46
- <div
47
- class="animate-float-slow absolute bottom-20 right-10 h-24 w-24 rounded-full bg-white/25 blur-lg"
48
- style="animation-delay: -5s;"
49
- ></div>
50
- <div
51
- class="animate-float-slow absolute bottom-1/4 left-1/3 h-16 w-16 rounded-full bg-white/20 blur-md"
52
- style="animation-delay: -7s;"
53
- ></div>
54
-
55
- <!-- Accent glow -->
56
- <div
57
- class="animate-pulse-glow absolute top-1/2 left-1/2 h-64 w-64 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white/10 blur-3xl"
58
- ></div>
59
-
60
- <!-- Center text/branding -->
61
- <div class="absolute inset-0 flex flex-col items-center justify-center p-8 text-white">
62
- <div class="mb-4 text-5xl font-bold opacity-90">includio</div>
63
- <p class="text-center text-lg text-white/70">Content Management System</p>
64
- </div>
65
- </div>
66
- </div>
67
- </div>
68
- </div>
15
+ {loginLang[interfaceLanguage.current].login.skip_to_content}
16
+ </a>
17
+
18
+ <!-- Background orbs -->
19
+ <div class="fixed inset-0 overflow-hidden pointer-events-none" aria-hidden="true">
20
+ <div class="login-orb login-orb--1"></div>
21
+ <div class="login-orb login-orb--2"></div>
22
+ <div class="login-orb login-orb--3"></div>
69
23
  </div>
70
24
 
71
- <style>
72
- @keyframes float-slow {
73
- 0%,
74
- 100% {
75
- transform: translateY(0px) translateX(0px);
76
- }
77
- 25% {
78
- transform: translateY(-20px) translateX(10px);
79
- }
80
- 50% {
81
- transform: translateY(-10px) translateX(-5px);
82
- }
83
- 75% {
84
- transform: translateY(-25px) translateX(5px);
85
- }
86
- }
87
-
88
- @keyframes pulse-glow {
89
- 0%,
90
- 100% {
91
- opacity: 0.1;
92
- transform: translate(-50%, -50%) scale(1);
93
- }
94
- 50% {
95
- opacity: 0.2;
96
- transform: translate(-50%, -50%) scale(1.1);
97
- }
98
- }
99
-
100
- :global(.animate-float-slow) {
101
- animation: float-slow 10s ease-in-out infinite;
102
- }
25
+ <!-- Main -->
26
+ <main
27
+ id="main-content"
28
+ class="relative z-[1] flex min-h-svh flex-col items-center justify-center p-6"
29
+ >
30
+ <!-- Card -->
31
+ <div
32
+ class="login-card-enter w-full max-w-[400px] rounded-xl border bg-card px-8 py-10 shadow-lg max-[480px]:rounded-lg max-[480px]:px-5 max-[480px]:py-8"
33
+ >
34
+ <LoginForm />
35
+ </div>
103
36
 
104
- :global(.animate-pulse-glow) {
105
- animation: pulse-glow 4s ease-in-out infinite;
106
- }
107
- </style>
37
+ <!-- Footer -->
38
+ <footer class="login-footer-enter mt-6 text-center">
39
+ <p class="text-xs text-text-light">
40
+ {loginLang[interfaceLanguage.current].login.footer_credit}
41
+ </p>
42
+ </footer>
43
+ </main>
@@ -0,0 +1,235 @@
1
+ <script lang="ts">
2
+ import '../../styles/admin.css';
3
+ import { Input } from '../../../components/ui/input/index.js';
4
+ import Label from '../../../components/ui/label/label.svelte';
5
+ import Button from '../../../components/ui/button/button.svelte';
6
+ import Loader2 from '@tabler/icons-svelte/icons/loader-2';
7
+ import * as Alert from '../../../components/ui/alert/index.js';
8
+ import { page } from '$app/state';
9
+ import { loginLang } from './lang.js';
10
+ import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
11
+ import { authClient } from '../../auth-client.js';
12
+
13
+ const interfaceLanguage = useInterfaceLanguage();
14
+ const lang = $derived(loginLang[interfaceLanguage.current]);
15
+
16
+ const token = $derived(page.url.searchParams.get('token'));
17
+
18
+ let password = $state('');
19
+ let confirmPassword = $state('');
20
+ let loading = $state(false);
21
+ let error = $state('');
22
+ let success = $state(false);
23
+ let showPassword = $state(false);
24
+ let showConfirm = $state(false);
25
+
26
+ // Password strength computation
27
+ type StrengthLevel = 'weak' | 'medium' | 'strong' | 'very-strong';
28
+
29
+ const strength = $derived.by((): { level: StrengthLevel; score: number } => {
30
+ if (!password) return { level: 'weak', score: 0 };
31
+
32
+ let score = 0;
33
+ if (password.length >= 8) score++;
34
+ if (/[A-Z]/.test(password)) score++;
35
+ if (/[0-9]/.test(password)) score++;
36
+ if (/[^A-Za-z0-9]/.test(password)) score++;
37
+
38
+ if (score <= 1) return { level: 'weak', score };
39
+ if (score === 2) return { level: 'medium', score };
40
+ if (score === 3) return { level: 'strong', score };
41
+ return { level: 'very-strong', score: 4 };
42
+ });
43
+
44
+ const strengthLabels = $derived({
45
+ weak: interfaceLanguage.current === 'pl' ? 'Słabe' : 'Weak',
46
+ medium: interfaceLanguage.current === 'pl' ? 'Średnie' : 'Medium',
47
+ strong: interfaceLanguage.current === 'pl' ? 'Silne' : 'Strong',
48
+ 'very-strong': interfaceLanguage.current === 'pl' ? 'Bardzo silne' : 'Very strong'
49
+ });
50
+
51
+ const strengthLabelText = $derived(
52
+ interfaceLanguage.current === 'pl' ? 'Siła hasła' : 'Password strength'
53
+ );
54
+
55
+ function validate(): string | null {
56
+ if (password.length < 8) return lang.reset.passwordMinLength;
57
+ if (!/[A-Z]/.test(password) || !/[0-9]/.test(password) || !/[^A-Za-z0-9]/.test(password)) {
58
+ return lang.reset.passwordRequirements;
59
+ }
60
+ if (password !== confirmPassword) return lang.reset.password_mismatch;
61
+ return null;
62
+ }
63
+
64
+ async function handleSubmit(e: Event) {
65
+ e.preventDefault();
66
+ const validationError = validate();
67
+ if (validationError) {
68
+ error = validationError;
69
+ return;
70
+ }
71
+
72
+ loading = true;
73
+ error = '';
74
+
75
+ const { error: apiError } = await authClient.resetPassword({
76
+ newPassword: password,
77
+ token: token!
78
+ });
79
+
80
+ if (apiError) {
81
+ error = lang.reset.invalid_link;
82
+ loading = false;
83
+ return;
84
+ }
85
+
86
+ success = true;
87
+ }
88
+ </script>
89
+
90
+ <!-- Skip link (WCAG) -->
91
+ <a
92
+ href="#main-content"
93
+ class="sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-3 focus:z-[9999] focus:rounded-lg focus:bg-primary focus:px-4 focus:py-2 focus:text-[13px] focus:font-semibold focus:text-primary-foreground"
94
+ >
95
+ {lang.login.skip_to_content}
96
+ </a>
97
+
98
+ <!-- Background orbs -->
99
+ <div class="fixed inset-0 overflow-hidden pointer-events-none" aria-hidden="true">
100
+ <div class="login-orb login-orb--1"></div>
101
+ <div class="login-orb login-orb--2"></div>
102
+ <div class="login-orb login-orb--3"></div>
103
+ </div>
104
+
105
+ <!-- Main -->
106
+ <main
107
+ id="main-content"
108
+ class="relative z-[1] flex min-h-svh flex-col items-center justify-center p-6"
109
+ >
110
+ <!-- Card -->
111
+ <div
112
+ class="login-card-enter w-full max-w-[400px] rounded-xl border bg-card px-8 py-10 shadow-lg max-[480px]:rounded-lg max-[480px]:px-5 max-[480px]:py-8"
113
+ >
114
+ <div class="flex flex-col gap-5">
115
+ <!-- Brand -->
116
+ <div class="mb-2 flex flex-col items-center text-center">
117
+ <div class="mb-2 flex items-baseline gap-0.5" aria-hidden="true">
118
+ <span class="text-primary text-[28px] leading-none font-extrabold max-[480px]:text-[24px]">
119
+ Aria
120
+ </span>
121
+ <span
122
+ class="text-primary text-[16px] leading-none font-light tracking-[0.15em] uppercase max-[480px]:text-[14px]"
123
+ >
124
+ CMS
125
+ </span>
126
+ </div>
127
+ </div>
128
+
129
+ <div class="text-center">
130
+ <h1 class="text-lg font-semibold text-foreground">{lang.reset.heading}</h1>
131
+ <p class="text-muted-foreground mt-1 text-[14px]">{lang.reset.description}</p>
132
+ </div>
133
+
134
+ {#if success}
135
+ <Alert.Root variant="success" class="text-center" role="status">
136
+ <Alert.Description>{lang.reset.success}</Alert.Description>
137
+ </Alert.Root>
138
+ <Button href="/admin/login" class="h-11 w-full text-[15px] font-semibold">
139
+ {lang.reset.go_to_login}
140
+ </Button>
141
+ {:else if !token}
142
+ <Alert.Root variant="destructive" class="text-center">
143
+ <Alert.Description>{lang.reset.invalid_link}</Alert.Description>
144
+ </Alert.Root>
145
+ {:else}
146
+ <form onsubmit={handleSubmit} class="space-y-4" aria-label={lang.reset.form_label}>
147
+ <div class="space-y-2">
148
+ <Label for="reset-password">{lang.reset.new_password}</Label>
149
+ <div class="acct-input-wrap">
150
+ <Input
151
+ id="reset-password"
152
+ type={showPassword ? 'text' : 'password'}
153
+ bind:value={password}
154
+ required
155
+ minlength={8}
156
+ autocomplete="new-password"
157
+ aria-describedby="reset-pw-hint reset-pw-strength"
158
+ class="login-input"
159
+ />
160
+ <button
161
+ type="button"
162
+ class="acct-pw-toggle"
163
+ aria-label={showPassword ? (interfaceLanguage.current === 'pl' ? 'Ukryj hasło' : 'Hide password') : (interfaceLanguage.current === 'pl' ? 'Pokaż hasło' : 'Show password')}
164
+ onclick={() => showPassword = !showPassword}
165
+ >
166
+ {#if showPassword}
167
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
168
+ {:else}
169
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
170
+ {/if}
171
+ </button>
172
+ </div>
173
+
174
+ <!-- Strength meter -->
175
+ {#if password}
176
+ <div class="acct-strength-meter" role="img" aria-label="{strengthLabelText}: {strengthLabels[strength.level]}">
177
+ {#each [1, 2, 3, 4] as i}
178
+ <div class="acct-strength-seg {i <= strength.score ? `filled-${strength.level}` : ''}"></div>
179
+ {/each}
180
+ </div>
181
+ <p id="reset-pw-strength" class="acct-strength-text {strength.level}">
182
+ {strengthLabelText}: {strengthLabels[strength.level]}
183
+ </p>
184
+ {/if}
185
+ <p id="reset-pw-hint" class="text-text-light mt-1 text-xs">
186
+ {lang.reset.passwordHint}
187
+ </p>
188
+ </div>
189
+ <div class="space-y-2">
190
+ <Label for="reset-confirm">{lang.reset.confirm_password}</Label>
191
+ <div class="acct-input-wrap">
192
+ <Input
193
+ id="reset-confirm"
194
+ type={showConfirm ? 'text' : 'password'}
195
+ bind:value={confirmPassword}
196
+ required
197
+ minlength={8}
198
+ autocomplete="new-password"
199
+ class="login-input"
200
+ />
201
+ <button
202
+ type="button"
203
+ class="acct-pw-toggle"
204
+ aria-label={showConfirm ? (interfaceLanguage.current === 'pl' ? 'Ukryj hasło' : 'Hide password') : (interfaceLanguage.current === 'pl' ? 'Pokaż hasło' : 'Show password')}
205
+ onclick={() => showConfirm = !showConfirm}
206
+ >
207
+ {#if showConfirm}
208
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
209
+ {:else}
210
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
211
+ {/if}
212
+ </button>
213
+ </div>
214
+ </div>
215
+ {#if error}
216
+ <p class="text-destructive text-sm" role="alert">{error}</p>
217
+ {/if}
218
+ <Button type="submit" class="h-11 w-full text-[15px] font-semibold" disabled={loading}>
219
+ {#if loading}
220
+ <Loader2 class="mr-2 size-4 animate-spin" />
221
+ {/if}
222
+ {lang.reset.submit}
223
+ </Button>
224
+ </form>
225
+ {/if}
226
+ </div>
227
+ </div>
228
+
229
+ <!-- Footer -->
230
+ <footer class="login-footer-enter mt-6 text-center">
231
+ <p class="text-xs text-text-light">
232
+ {lang.login.footer_credit}
233
+ </p>
234
+ </footer>
235
+ </main>
@@ -0,0 +1,4 @@
1
+ import '../../styles/admin.css';
2
+ declare const ResetPasswordPage: import("svelte").Component<Record<string, never>, {}, "">;
3
+ type ResetPasswordPage = ReturnType<typeof ResetPasswordPage>;
4
+ export default ResetPasswordPage;
@@ -3,3 +3,18 @@ export declare const loginSchema: z.ZodObject<{
3
3
  email: z.ZodString;
4
4
  password: z.ZodString;
5
5
  }, z.core.$strip>;
6
+ export declare const forgotPasswordSchema: z.ZodObject<{
7
+ email: z.ZodString;
8
+ }, z.core.$strip>;
9
+ export declare function createResetPasswordSchema(errors: {
10
+ minLength: string;
11
+ requirements: string;
12
+ mismatch: string;
13
+ }): z.ZodObject<{
14
+ password: z.ZodString;
15
+ confirmPassword: z.ZodString;
16
+ }, z.core.$strip>;
17
+ export declare const resetPasswordSchema: z.ZodObject<{
18
+ password: z.ZodString;
19
+ confirmPassword: z.ZodString;
20
+ }, z.core.$strip>;
@@ -1,5 +1,26 @@
1
1
  import { z } from 'zod';
2
+ import { passwordField } from '../../shared/password-schema.js';
2
3
  export const loginSchema = z.object({
3
4
  email: z.string().email(),
4
5
  password: z.string().min(6).max(255, 'Invalid password (min 6, max 255 characters)')
5
6
  });
7
+ export const forgotPasswordSchema = z.object({
8
+ email: z.string().email()
9
+ });
10
+ export function createResetPasswordSchema(errors) {
11
+ return z
12
+ .object({
13
+ password: passwordField({ minLength: errors.minLength, requirements: errors.requirements }),
14
+ confirmPassword: z.string().min(1)
15
+ })
16
+ .refine((data) => data.password === data.confirmPassword, {
17
+ message: errors.mismatch,
18
+ path: ['confirmPassword']
19
+ });
20
+ }
21
+ // Static schema for backward compat (English defaults)
22
+ export const resetPasswordSchema = createResetPasswordSchema({
23
+ minLength: 'Password must be at least 8 characters',
24
+ requirements: 'Password must contain an uppercase letter, a number and a special character',
25
+ mismatch: 'Passwords do not match'
26
+ });