@nextsparkjs/core 0.1.0-beta.187 → 0.1.0-beta.189

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 (414) hide show
  1. package/dist/components/api/keys/ApiKeyDisplay.js +19 -19
  2. package/dist/components/api/keys/CreateApiKeyDialog.js +21 -21
  3. package/dist/components/app/layouts/PublicNavbar.d.ts.map +1 -1
  4. package/dist/components/app/layouts/PublicNavbar.js +34 -16
  5. package/dist/components/app/misc/ThemeToggle.d.ts.map +1 -1
  6. package/dist/components/app/misc/ThemeToggle.js +3 -4
  7. package/dist/components/auth/SessionCookieRefresher.d.ts +5 -0
  8. package/dist/components/auth/SessionCookieRefresher.d.ts.map +1 -1
  9. package/dist/components/auth/SessionCookieRefresher.js +7 -1
  10. package/dist/components/auth/forms/LoginForm.d.ts.map +1 -1
  11. package/dist/components/auth/forms/LoginForm.js +49 -12
  12. package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
  13. package/dist/components/auth/forms/SignupForm.js +4 -3
  14. package/dist/components/dashboard/block-editor/block-settings-panel.js +1 -1
  15. package/dist/components/dashboard/block-editor/floating-block-toolbar.js +1 -1
  16. package/dist/components/dashboard/block-editor/sortable-block.js +1 -1
  17. package/dist/components/dashboard/layouts/Sidebar.d.ts.map +1 -1
  18. package/dist/components/dashboard/layouts/Sidebar.js +8 -6
  19. package/dist/components/dashboard/layouts/TopNavbar.d.ts.map +1 -1
  20. package/dist/components/dashboard/layouts/TopNavbar.js +51 -54
  21. package/dist/components/dashboard/misc/NotificationsDropdown.d.ts.map +1 -1
  22. package/dist/components/dashboard/misc/NotificationsDropdown.js +17 -15
  23. package/dist/components/dashboard/misc/SearchDropdown.d.ts.map +1 -1
  24. package/dist/components/dashboard/misc/SearchDropdown.js +19 -22
  25. package/dist/components/dashboard/mobile/MobileBottomNav.js +1 -1
  26. package/dist/components/dashboard/mobile/MobileTopBar.d.ts +10 -1
  27. package/dist/components/dashboard/mobile/MobileTopBar.d.ts.map +1 -1
  28. package/dist/components/dashboard/mobile/MobileTopBar.js +4 -3
  29. package/dist/components/dashboard/navigation/DynamicNavigation.js +5 -5
  30. package/dist/components/devtools/BlockDetailViewer.js +1 -1
  31. package/dist/components/devtools/BlocksViewer.js +1 -1
  32. package/dist/components/entities/EntityChildManager.js +5 -5
  33. package/dist/components/entities/EntityDetailPage.d.ts.map +1 -1
  34. package/dist/components/entities/EntityDetailPage.js +16 -15
  35. package/dist/components/entities/EntityFieldRenderer.d.ts.map +1 -1
  36. package/dist/components/entities/EntityFieldRenderer.js +12 -7
  37. package/dist/components/entities/EntityPageHeader.js +5 -5
  38. package/dist/components/entities/ErrorBoundary.d.ts.map +1 -1
  39. package/dist/components/entities/ErrorBoundary.js +20 -21
  40. package/dist/components/entities/wrappers/EntityDetailWrapper.js +5 -5
  41. package/dist/components/entities/wrappers/EntityFormWrapper.js +2 -2
  42. package/dist/components/entities/wrappers/EntityListWrapper.js +3 -3
  43. package/dist/components/permissions/NoPermission.js +10 -10
  44. package/dist/components/public/pageBuilder/PageRenderer.d.ts.map +1 -1
  45. package/dist/components/public/pageBuilder/PageRenderer.js +2 -1
  46. package/dist/components/settings/SettingsPageSkeleton.js +4 -4
  47. package/dist/components/settings/layouts/SettingsSidebar.js +6 -6
  48. package/dist/components/shared/MultiSelectFilter.d.ts +3 -1
  49. package/dist/components/shared/MultiSelectFilter.d.ts.map +1 -1
  50. package/dist/components/shared/MultiSelectFilter.js +7 -3
  51. package/dist/components/shared/SearchInput.d.ts +2 -0
  52. package/dist/components/shared/SearchInput.d.ts.map +1 -1
  53. package/dist/components/shared/SearchInput.js +64 -6
  54. package/dist/components/ui/address-input.js +18 -18
  55. package/dist/components/ui/audio-upload.js +9 -9
  56. package/dist/components/ui/combobox.d.ts.map +1 -1
  57. package/dist/components/ui/combobox.js +4 -4
  58. package/dist/components/ui/country-select.d.ts.map +1 -1
  59. package/dist/components/ui/country-select.js +3 -3
  60. package/dist/components/ui/currency-select.d.ts.map +1 -1
  61. package/dist/components/ui/currency-select.js +3 -3
  62. package/dist/components/ui/dynamic-icon.d.ts.map +1 -1
  63. package/dist/components/ui/dynamic-icon.js +3 -2
  64. package/dist/components/ui/file-upload.js +7 -7
  65. package/dist/components/ui/image-upload.js +8 -8
  66. package/dist/components/ui/multi-select.d.ts +2 -1
  67. package/dist/components/ui/multi-select.d.ts.map +1 -1
  68. package/dist/components/ui/multi-select.js +4 -3
  69. package/dist/components/ui/phone-input.d.ts.map +1 -1
  70. package/dist/components/ui/phone-input.js +3 -3
  71. package/dist/components/ui/relation-display.js +1 -1
  72. package/dist/components/ui/simple-relation-select.d.ts +2 -1
  73. package/dist/components/ui/simple-relation-select.d.ts.map +1 -1
  74. package/dist/components/ui/simple-relation-select.js +7 -6
  75. package/dist/components/ui/tags-input.d.ts.map +1 -1
  76. package/dist/components/ui/tags-input.js +1 -1
  77. package/dist/components/ui/timezone-select.d.ts.map +1 -1
  78. package/dist/components/ui/timezone-select.js +3 -3
  79. package/dist/components/ui/user-display.js +4 -4
  80. package/dist/components/ui/user-select.d.ts.map +1 -1
  81. package/dist/components/ui/user-select.js +9 -9
  82. package/dist/components/ui/video-upload.js +9 -9
  83. package/dist/contexts/SubscriptionContext.d.ts.map +1 -1
  84. package/dist/contexts/SubscriptionContext.js +5 -1
  85. package/dist/contexts/TeamContext.d.ts.map +1 -1
  86. package/dist/contexts/TeamContext.js +83 -26
  87. package/dist/emails/otp-verification.d.ts.map +1 -1
  88. package/dist/emails/otp-verification.js +3 -2
  89. package/dist/hooks/useAccountPreferencesSync.d.ts +13 -0
  90. package/dist/hooks/useAccountPreferencesSync.d.ts.map +1 -0
  91. package/dist/hooks/useAccountPreferencesSync.js +95 -0
  92. package/dist/hooks/useAuth.d.ts +202 -15
  93. package/dist/hooks/useAuth.d.ts.map +1 -1
  94. package/dist/hooks/useAuth.js +49 -13
  95. package/dist/hooks/useEntityConfig.js +2 -2
  96. package/dist/hooks/useEntitySearch.js +10 -10
  97. package/dist/hooks/useNotifications.js +12 -12
  98. package/dist/hooks/usePrefetch.d.ts.map +1 -1
  99. package/dist/hooks/usePrefetch.js +6 -2
  100. package/dist/hooks/useSearch.js +15 -15
  101. package/dist/hooks/useSessionCookieRefresh.d.ts +18 -1
  102. package/dist/hooks/useSessionCookieRefresh.d.ts.map +1 -1
  103. package/dist/hooks/useSessionCookieRefresh.js +17 -4
  104. package/dist/hooks/useSessionHint.d.ts +12 -0
  105. package/dist/hooks/useSessionHint.d.ts.map +1 -0
  106. package/dist/hooks/useSessionHint.js +15 -0
  107. package/dist/hooks/useTranslationPreload.js +6 -6
  108. package/dist/i18n.d.ts +13 -0
  109. package/dist/i18n.d.ts.map +1 -1
  110. package/dist/i18n.js +2 -27
  111. package/dist/lib/actions/entity.actions.d.ts.map +1 -1
  112. package/dist/lib/actions/entity.actions.js +3 -2
  113. package/dist/lib/api/auth/dual-auth.d.ts +4 -1
  114. package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
  115. package/dist/lib/api/auth/dual-auth.js +5 -16
  116. package/dist/lib/api/entities.js +33 -33
  117. package/dist/lib/api/keys.d.ts +27 -27
  118. package/dist/lib/api/keys.js +27 -27
  119. package/dist/lib/auth/callback-url.d.ts +11 -0
  120. package/dist/lib/auth/callback-url.d.ts.map +1 -0
  121. package/dist/lib/auth/callback-url.js +14 -0
  122. package/dist/lib/auth/otp-config.d.ts +55 -0
  123. package/dist/lib/auth/otp-config.d.ts.map +1 -0
  124. package/dist/lib/auth/otp-config.js +48 -0
  125. package/dist/lib/auth/registration-helpers.d.ts.map +1 -1
  126. package/dist/lib/auth/registration-helpers.js +3 -1
  127. package/dist/lib/auth/session-hint.d.ts +31 -0
  128. package/dist/lib/auth/session-hint.d.ts.map +1 -0
  129. package/dist/lib/auth/session-hint.js +37 -0
  130. package/dist/lib/auth.d.ts.map +1 -1
  131. package/dist/lib/auth.js +6 -4
  132. package/dist/lib/blocks/loader.d.ts +3 -11
  133. package/dist/lib/blocks/loader.d.ts.map +1 -1
  134. package/dist/lib/blocks/loader.js +1 -9
  135. package/dist/lib/blocks/loader.server.d.ts +18 -0
  136. package/dist/lib/blocks/loader.server.d.ts.map +1 -0
  137. package/dist/lib/blocks/loader.server.js +11 -0
  138. package/dist/lib/blocks/sanitize-html.d.ts +31 -0
  139. package/dist/lib/blocks/sanitize-html.d.ts.map +1 -0
  140. package/dist/lib/blocks/sanitize-html.js +60 -0
  141. package/dist/lib/config/config-sync.d.ts +1 -0
  142. package/dist/lib/config/config-sync.d.ts.map +1 -1
  143. package/dist/lib/config/config-sync.js +4 -1
  144. package/dist/lib/config/types.d.ts +48 -0
  145. package/dist/lib/config/types.d.ts.map +1 -1
  146. package/dist/lib/email/types.d.ts +6 -0
  147. package/dist/lib/email/types.d.ts.map +1 -1
  148. package/dist/lib/entities/serialization.d.ts.map +1 -1
  149. package/dist/lib/entities/serialization.js +3 -6
  150. package/dist/lib/icons.d.ts +12 -0
  151. package/dist/lib/icons.d.ts.map +1 -0
  152. package/dist/lib/icons.js +30 -0
  153. package/dist/lib/locale.d.ts +25 -1
  154. package/dist/lib/locale.d.ts.map +1 -1
  155. package/dist/lib/locale.js +49 -35
  156. package/dist/lib/mcp/engine.js +1 -1
  157. package/dist/lib/mcp/errors.js +17 -17
  158. package/dist/lib/mcp/schema-builder.js +16 -16
  159. package/dist/lib/mcp/tool-generator.js +18 -18
  160. package/dist/lib/search-highlighting.d.ts +7 -0
  161. package/dist/lib/search-highlighting.d.ts.map +1 -1
  162. package/dist/lib/search-highlighting.js +6 -2
  163. package/dist/lib/selectors/core-selectors.d.ts +2 -0
  164. package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
  165. package/dist/lib/selectors/domains/auth.selectors.d.ts +1 -0
  166. package/dist/lib/selectors/domains/auth.selectors.d.ts.map +1 -1
  167. package/dist/lib/selectors/domains/auth.selectors.js +1 -0
  168. package/dist/lib/selectors/domains/entities.selectors.d.ts +2 -0
  169. package/dist/lib/selectors/domains/entities.selectors.d.ts.map +1 -1
  170. package/dist/lib/selectors/domains/entities.selectors.js +2 -0
  171. package/dist/lib/selectors/selectors.d.ts +4 -0
  172. package/dist/lib/selectors/selectors.d.ts.map +1 -1
  173. package/dist/lib/services/block.service.js +1 -1
  174. package/dist/lib/teams/active-team-cookie.d.ts +24 -0
  175. package/dist/lib/teams/active-team-cookie.d.ts.map +1 -0
  176. package/dist/lib/teams/active-team-cookie.js +17 -0
  177. package/dist/lib/teams/dashboard-team.d.ts +20 -0
  178. package/dist/lib/teams/dashboard-team.d.ts.map +1 -0
  179. package/dist/lib/teams/dashboard-team.js +38 -0
  180. package/dist/lib/teams/schema.d.ts.map +1 -1
  181. package/dist/lib/teams/schema.js +1 -1
  182. package/dist/lib/template-resolver.d.ts.map +1 -1
  183. package/dist/lib/template-resolver.js +0 -1
  184. package/dist/lib/theme/get-default-theme-mode.d.ts +7 -4
  185. package/dist/lib/theme/get-default-theme-mode.d.ts.map +1 -1
  186. package/dist/lib/theme/get-default-theme-mode.js +2 -44
  187. package/dist/messages/de/auth.json +4 -2
  188. package/dist/messages/de/common.json +83 -3
  189. package/dist/messages/de/email.json +1 -1
  190. package/dist/messages/de/index.d.ts +87 -0
  191. package/dist/messages/de/index.d.ts.map +1 -1
  192. package/dist/messages/de/settings.json +5 -0
  193. package/dist/messages/en/auth.json +4 -2
  194. package/dist/messages/en/common.json +83 -3
  195. package/dist/messages/en/email.json +1 -1
  196. package/dist/messages/en/index.d.ts +86 -0
  197. package/dist/messages/en/index.d.ts.map +1 -1
  198. package/dist/messages/en/settings.json +4 -0
  199. package/dist/messages/es/auth.json +4 -2
  200. package/dist/messages/es/common.json +83 -3
  201. package/dist/messages/es/email.json +1 -1
  202. package/dist/messages/es/index.d.ts +86 -0
  203. package/dist/messages/es/index.d.ts.map +1 -1
  204. package/dist/messages/es/settings.json +4 -0
  205. package/dist/messages/fr/auth.json +4 -2
  206. package/dist/messages/fr/common.json +83 -3
  207. package/dist/messages/fr/email.json +1 -1
  208. package/dist/messages/fr/index.d.ts +87 -0
  209. package/dist/messages/fr/index.d.ts.map +1 -1
  210. package/dist/messages/fr/settings.json +5 -0
  211. package/dist/messages/it/auth.json +4 -2
  212. package/dist/messages/it/common.json +83 -3
  213. package/dist/messages/it/email.json +1 -1
  214. package/dist/messages/it/index.d.ts +87 -0
  215. package/dist/messages/it/index.d.ts.map +1 -1
  216. package/dist/messages/it/settings.json +5 -0
  217. package/dist/messages/pt/auth.json +4 -2
  218. package/dist/messages/pt/common.json +83 -3
  219. package/dist/messages/pt/email.json +1 -1
  220. package/dist/messages/pt/index.d.ts +87 -0
  221. package/dist/messages/pt/index.d.ts.map +1 -1
  222. package/dist/messages/pt/settings.json +5 -0
  223. package/dist/nextspark-registries.d.ts +54 -0
  224. package/dist/providers/DashboardProviders.d.ts +13 -10
  225. package/dist/providers/DashboardProviders.d.ts.map +1 -1
  226. package/dist/providers/DashboardProviders.js +7 -1
  227. package/dist/templates/app/(auth)/forgot-password/page.tsx +2 -2
  228. package/dist/templates/app/(auth)/reset-password/page.tsx +6 -6
  229. package/dist/templates/app/403/page.tsx +6 -6
  230. package/dist/templates/app/api/v1/teams/switch/route.ts +24 -5
  231. package/dist/templates/app/dashboard/(main)/[entity]/layout.tsx +9 -7
  232. package/dist/templates/app/dashboard/(main)/layout.tsx +4 -3
  233. package/dist/templates/app/dashboard/settings/api-keys/page.tsx +36 -34
  234. package/dist/templates/app/dashboard/settings/profile/page.tsx +7 -6
  235. package/dist/templates/app/dashboard/settings/security/page.tsx +5 -4
  236. package/dist/templates/app/layout.ppr.tsx +8 -8
  237. package/dist/templates/app/layout.tsx +12 -17
  238. package/dist/templates/blocks/cta-section/component.tsx +5 -2
  239. package/dist/templates/blocks/cta-section/config.ts +3 -2
  240. package/dist/templates/blocks/cta-section/fields.ts +2 -2
  241. package/dist/templates/blocks/cta-section/schema.ts +2 -2
  242. package/dist/templates/blocks/features-grid/component.tsx +10 -2
  243. package/dist/templates/blocks/features-grid/config.ts +3 -2
  244. package/dist/templates/blocks/features-grid/fields.ts +2 -2
  245. package/dist/templates/blocks/features-grid/schema.ts +2 -2
  246. package/dist/templates/blocks/hero/component.tsx +6 -3
  247. package/dist/templates/blocks/hero/config.ts +3 -2
  248. package/dist/templates/blocks/hero/fields.ts +2 -2
  249. package/dist/templates/blocks/hero/schema.ts +2 -2
  250. package/dist/templates/blocks/testimonials/component.tsx +6 -3
  251. package/dist/templates/blocks/testimonials/config.ts +3 -2
  252. package/dist/templates/blocks/testimonials/fields.ts +2 -2
  253. package/dist/templates/blocks/testimonials/schema.ts +2 -2
  254. package/dist/templates/blocks/text-content/component.tsx +7 -3
  255. package/dist/templates/blocks/text-content/config.ts +3 -2
  256. package/dist/templates/blocks/text-content/fields.ts +2 -2
  257. package/dist/templates/blocks/text-content/schema.ts +2 -2
  258. package/dist/templates/contents/themes/starter/blocks/cta-section/component.tsx +102 -0
  259. package/dist/templates/contents/themes/starter/blocks/cta-section/config.ts +11 -0
  260. package/dist/templates/contents/themes/starter/blocks/cta-section/fields.ts +89 -0
  261. package/dist/templates/contents/themes/starter/blocks/cta-section/index.ts +6 -0
  262. package/dist/templates/contents/themes/starter/blocks/cta-section/schema.ts +32 -0
  263. package/dist/templates/contents/themes/starter/blocks/cta-section/thumbnail.png +0 -0
  264. package/dist/templates/contents/themes/starter/blocks/features-grid/component.tsx +119 -0
  265. package/dist/templates/contents/themes/starter/blocks/features-grid/config.ts +11 -0
  266. package/dist/templates/contents/themes/starter/blocks/features-grid/fields.ts +97 -0
  267. package/dist/templates/contents/themes/starter/blocks/features-grid/index.ts +6 -0
  268. package/dist/templates/contents/themes/starter/blocks/features-grid/schema.ts +40 -0
  269. package/dist/templates/contents/themes/starter/blocks/features-grid/thumbnail.png +0 -0
  270. package/dist/templates/contents/themes/starter/blocks/hero/component.tsx +105 -0
  271. package/dist/templates/contents/themes/starter/blocks/hero/config.ts +11 -0
  272. package/dist/templates/contents/themes/starter/blocks/hero/fields.ts +60 -0
  273. package/dist/templates/contents/themes/starter/blocks/hero/index.ts +6 -0
  274. package/dist/templates/contents/themes/starter/blocks/hero/schema.ts +33 -0
  275. package/dist/templates/contents/themes/starter/blocks/hero/thumbnail.png +0 -0
  276. package/dist/templates/contents/themes/starter/blocks/testimonials/component.tsx +116 -0
  277. package/dist/templates/contents/themes/starter/blocks/testimonials/config.ts +11 -0
  278. package/dist/templates/contents/themes/starter/blocks/testimonials/fields.ts +105 -0
  279. package/dist/templates/contents/themes/starter/blocks/testimonials/index.ts +6 -0
  280. package/dist/templates/contents/themes/starter/blocks/testimonials/schema.ts +41 -0
  281. package/dist/templates/contents/themes/starter/blocks/testimonials/thumbnail.png +0 -0
  282. package/dist/templates/contents/themes/starter/blocks/text-content/component.tsx +100 -0
  283. package/dist/templates/contents/themes/starter/blocks/text-content/config.ts +11 -0
  284. package/dist/templates/contents/themes/starter/blocks/text-content/fields.ts +88 -0
  285. package/dist/templates/contents/themes/starter/blocks/text-content/index.ts +6 -0
  286. package/dist/templates/contents/themes/starter/blocks/text-content/schema.ts +30 -0
  287. package/dist/templates/contents/themes/starter/blocks/text-content/thumbnail.png +0 -0
  288. package/dist/templates/contents/themes/starter/config/app.config.ts +8 -0
  289. package/dist/templates/contents/themes/starter/entities/tasks/tasks.config.ts +7 -0
  290. package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/devtools/access.cy.ts +9 -1
  291. package/dist/templates/contents/themes/starter/tests/cypress/e2e/api/entities/tasks/TaskAPIController.js +2 -2
  292. package/dist/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +45 -38
  293. package/dist/templates/contents/themes/starter/tests/cypress/fixtures/entities.json +16 -0
  294. package/dist/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +3 -1
  295. package/dist/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +3 -3
  296. package/dist/templates/contents/themes/starter/tests/cypress/src/entities/PagesPOM.ts +137 -0
  297. package/dist/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +2 -0
  298. package/dist/templates/contents/themes/starter/tests/cypress/src/index.ts +1 -0
  299. package/dist/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +42 -11
  300. package/dist/templates/contents/themes/starter/tests/cypress/support/commands.ts +29 -18
  301. package/dist/templates/features/blog/blocks/post-content/component.tsx +5 -1
  302. package/dist/templates/features/blog/blocks/post-content/schema.ts +1 -1
  303. package/dist/templates/features/pages/blocks/hero/component.tsx +3 -0
  304. package/dist/templates/features/pages/blocks/hero/schema.ts +1 -1
  305. package/dist/templates/proxy.ts +138 -53
  306. package/dist/types/blocks.d.ts.map +1 -1
  307. package/dist/types/blocks.js +1 -1
  308. package/dist/types/task.types.d.ts +1 -1
  309. package/dist/types/task.types.js +7 -7
  310. package/dist/utils/dev/TranslationDebugger.js +2 -2
  311. package/package.json +14 -5
  312. package/scripts/build/registry/__tests__/block-registry.test.mjs +73 -0
  313. package/scripts/build/registry/__tests__/icons-discovery.test.mjs +130 -0
  314. package/scripts/build/registry/__tests__/identifier.test.mjs +65 -0
  315. package/scripts/build/registry/__tests__/page-generator.test.mjs +430 -0
  316. package/scripts/build/registry/__tests__/scheduled-actions-registry.test.mjs +41 -0
  317. package/scripts/build/registry/__tests__/template-registry.test.mjs +89 -0
  318. package/scripts/build/registry/discovery/icons.mjs +275 -0
  319. package/scripts/build/registry/discovery/index.mjs +1 -0
  320. package/scripts/build/registry/generators/block-registry.mjs +203 -55
  321. package/scripts/build/registry/generators/feature-registry.mjs +9 -2
  322. package/scripts/build/registry/generators/icon-registry.mjs +56 -0
  323. package/scripts/build/registry/generators/identifier.mjs +28 -0
  324. package/scripts/build/registry/generators/index.mjs +1 -0
  325. package/scripts/build/registry/generators/plugin-registry.mjs +4 -3
  326. package/scripts/build/registry/generators/scheduled-actions-registry.mjs +4 -2
  327. package/scripts/build/registry/generators/template-registry.mjs +49 -41
  328. package/scripts/build/registry/generators/theme-registry.mjs +6 -7
  329. package/scripts/build/registry/post-build/page-generator.mjs +380 -59
  330. package/scripts/build/registry.mjs +9 -1
  331. package/templates/app/(auth)/forgot-password/page.tsx +2 -2
  332. package/templates/app/(auth)/reset-password/page.tsx +6 -6
  333. package/templates/app/403/page.tsx +6 -6
  334. package/templates/app/api/v1/teams/switch/route.ts +24 -5
  335. package/templates/app/dashboard/(main)/[entity]/layout.tsx +9 -7
  336. package/templates/app/dashboard/(main)/layout.tsx +4 -3
  337. package/templates/app/dashboard/settings/api-keys/page.tsx +36 -34
  338. package/templates/app/dashboard/settings/profile/page.tsx +7 -6
  339. package/templates/app/dashboard/settings/security/page.tsx +5 -4
  340. package/templates/app/layout.ppr.tsx +8 -8
  341. package/templates/app/layout.tsx +12 -17
  342. package/templates/blocks/cta-section/component.tsx +5 -2
  343. package/templates/blocks/cta-section/config.ts +3 -2
  344. package/templates/blocks/cta-section/fields.ts +2 -2
  345. package/templates/blocks/cta-section/schema.ts +2 -2
  346. package/templates/blocks/features-grid/component.tsx +10 -2
  347. package/templates/blocks/features-grid/config.ts +3 -2
  348. package/templates/blocks/features-grid/fields.ts +2 -2
  349. package/templates/blocks/features-grid/schema.ts +2 -2
  350. package/templates/blocks/hero/component.tsx +6 -3
  351. package/templates/blocks/hero/config.ts +3 -2
  352. package/templates/blocks/hero/fields.ts +2 -2
  353. package/templates/blocks/hero/schema.ts +2 -2
  354. package/templates/blocks/testimonials/component.tsx +6 -3
  355. package/templates/blocks/testimonials/config.ts +3 -2
  356. package/templates/blocks/testimonials/fields.ts +2 -2
  357. package/templates/blocks/testimonials/schema.ts +2 -2
  358. package/templates/blocks/text-content/component.tsx +7 -3
  359. package/templates/blocks/text-content/config.ts +3 -2
  360. package/templates/blocks/text-content/fields.ts +2 -2
  361. package/templates/blocks/text-content/schema.ts +2 -2
  362. package/templates/contents/themes/starter/blocks/cta-section/component.tsx +102 -0
  363. package/templates/contents/themes/starter/blocks/cta-section/config.ts +11 -0
  364. package/templates/contents/themes/starter/blocks/cta-section/fields.ts +89 -0
  365. package/templates/contents/themes/starter/blocks/cta-section/index.ts +6 -0
  366. package/templates/contents/themes/starter/blocks/cta-section/schema.ts +32 -0
  367. package/templates/contents/themes/starter/blocks/cta-section/thumbnail.png +0 -0
  368. package/templates/contents/themes/starter/blocks/features-grid/component.tsx +119 -0
  369. package/templates/contents/themes/starter/blocks/features-grid/config.ts +11 -0
  370. package/templates/contents/themes/starter/blocks/features-grid/fields.ts +97 -0
  371. package/templates/contents/themes/starter/blocks/features-grid/index.ts +6 -0
  372. package/templates/contents/themes/starter/blocks/features-grid/schema.ts +40 -0
  373. package/templates/contents/themes/starter/blocks/features-grid/thumbnail.png +0 -0
  374. package/templates/contents/themes/starter/blocks/hero/component.tsx +105 -0
  375. package/templates/contents/themes/starter/blocks/hero/config.ts +11 -0
  376. package/templates/contents/themes/starter/blocks/hero/fields.ts +60 -0
  377. package/templates/contents/themes/starter/blocks/hero/index.ts +6 -0
  378. package/templates/contents/themes/starter/blocks/hero/schema.ts +33 -0
  379. package/templates/contents/themes/starter/blocks/hero/thumbnail.png +0 -0
  380. package/templates/contents/themes/starter/blocks/testimonials/component.tsx +116 -0
  381. package/templates/contents/themes/starter/blocks/testimonials/config.ts +11 -0
  382. package/templates/contents/themes/starter/blocks/testimonials/fields.ts +105 -0
  383. package/templates/contents/themes/starter/blocks/testimonials/index.ts +6 -0
  384. package/templates/contents/themes/starter/blocks/testimonials/schema.ts +41 -0
  385. package/templates/contents/themes/starter/blocks/testimonials/thumbnail.png +0 -0
  386. package/templates/contents/themes/starter/blocks/text-content/component.tsx +100 -0
  387. package/templates/contents/themes/starter/blocks/text-content/config.ts +11 -0
  388. package/templates/contents/themes/starter/blocks/text-content/fields.ts +88 -0
  389. package/templates/contents/themes/starter/blocks/text-content/index.ts +6 -0
  390. package/templates/contents/themes/starter/blocks/text-content/schema.ts +30 -0
  391. package/templates/contents/themes/starter/blocks/text-content/thumbnail.png +0 -0
  392. package/templates/contents/themes/starter/config/app.config.ts +8 -0
  393. package/templates/contents/themes/starter/entities/tasks/tasks.config.ts +7 -0
  394. package/templates/contents/themes/starter/tests/cypress/e2e/_utils/devtools/access.cy.ts +9 -1
  395. package/templates/contents/themes/starter/tests/cypress/e2e/api/entities/tasks/TaskAPIController.js +2 -2
  396. package/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +45 -38
  397. package/templates/contents/themes/starter/tests/cypress/fixtures/entities.json +16 -0
  398. package/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +3 -1
  399. package/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +3 -3
  400. package/templates/contents/themes/starter/tests/cypress/src/entities/PagesPOM.ts +137 -0
  401. package/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +2 -0
  402. package/templates/contents/themes/starter/tests/cypress/src/index.ts +1 -0
  403. package/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +42 -11
  404. package/templates/contents/themes/starter/tests/cypress/support/commands.ts +29 -18
  405. package/templates/features/blog/blocks/post-content/component.tsx +5 -1
  406. package/templates/features/blog/blocks/post-content/schema.ts +1 -1
  407. package/templates/features/pages/blocks/hero/component.tsx +3 -0
  408. package/templates/features/pages/blocks/hero/schema.ts +1 -1
  409. package/templates/proxy.ts +138 -53
  410. package/tests/jest/__mocks__/@nextsparkjs/registries/block-registry.client.ts +9 -0
  411. package/tests/jest/__mocks__/@nextsparkjs/registries/block-registry.lazy.ts +5 -0
  412. package/tests/jest/__mocks__/@nextsparkjs/registries/icon-registry.ts +42 -0
  413. package/tests/jest/__mocks__/next-intl-server.js +85 -5
  414. package/tests/jest/__mocks__/next-server.js +32 -0
@@ -27,7 +27,7 @@ function ApiKeyDisplay({ apiKey, keyName, warning, onClose }) {
27
27
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
28
28
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
29
29
  /* @__PURE__ */ jsx(CheckCircle, { className: "h-5 w-5 text-green-600" }),
30
- /* @__PURE__ */ jsx(CardTitle, { className: "text-green-800", children: "API Key creada exitosamente" })
30
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-green-800", children: "API Key created successfully" })
31
31
  ] }),
32
32
  /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClose, children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" }) })
33
33
  ] }),
@@ -37,13 +37,13 @@ function ApiKeyDisplay({ apiKey, keyName, warning, onClose }) {
37
37
  warning && /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
38
38
  /* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4" }),
39
39
  /* @__PURE__ */ jsxs(AlertDescription, { children: [
40
- /* @__PURE__ */ jsx("strong", { children: "\xA1Importante!" }),
40
+ /* @__PURE__ */ jsx("strong", { children: "Important!" }),
41
41
  " ",
42
42
  warning
43
43
  ] })
44
44
  ] }),
45
45
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
46
- /* @__PURE__ */ jsx("label", { className: "text-sm font-medium text-green-800", children: "Tu nueva API Key:" }),
46
+ /* @__PURE__ */ jsx("label", { className: "text-sm font-medium text-green-800", children: "Your new API Key:" }),
47
47
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
48
48
  /* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
49
49
  /* @__PURE__ */ jsx(
@@ -76,29 +76,29 @@ function ApiKeyDisplay({ apiKey, keyName, warning, onClose }) {
76
76
  "data-cy": sel("settings.apiKeys.newKeyDisplay.copyButton"),
77
77
  children: [
78
78
  /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4 mr-2" }),
79
- copied ? "Copiado!" : "Copiar"
79
+ copied ? "Copied!" : "Copy"
80
80
  ]
81
81
  }
82
82
  )
83
83
  ] })
84
84
  ] }),
85
85
  /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
86
- /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-green-800", children: "C\xF3mo usar tu API Key:" }),
86
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-green-800", children: "How to use your API Key:" }),
87
87
  /* @__PURE__ */ jsxs("div", { className: "space-y-2 text-sm", children: [
88
88
  /* @__PURE__ */ jsxs("div", { children: [
89
- /* @__PURE__ */ jsx("strong", { children: "1. Incluye la API key en el header Authorization:" }),
89
+ /* @__PURE__ */ jsx("strong", { children: "1. Include the API key in the Authorization header:" }),
90
90
  /* @__PURE__ */ jsxs("div", { className: "mt-1 p-2 bg-gray-100 rounded font-mono text-xs overflow-x-auto", children: [
91
91
  "Authorization: Bearer ",
92
92
  isVisible ? apiKey : "sk_live_\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022"
93
93
  ] })
94
94
  ] }),
95
95
  /* @__PURE__ */ jsxs("div", { children: [
96
- /* @__PURE__ */ jsx("strong", { children: "2. Ejemplo con curl:" }),
96
+ /* @__PURE__ */ jsx("strong", { children: "2. Example with curl:" }),
97
97
  /* @__PURE__ */ jsx("div", { className: "mt-1 p-2 bg-gray-100 rounded font-mono text-xs overflow-x-auto", children: `curl -H "Authorization: Bearer ${isVisible ? apiKey : "YOUR_API_KEY"}" \\
98
98
  https://yourapp.com/api/v1/users` })
99
99
  ] }),
100
100
  /* @__PURE__ */ jsxs("div", { children: [
101
- /* @__PURE__ */ jsx("strong", { children: "3. Ejemplo con JavaScript:" }),
101
+ /* @__PURE__ */ jsx("strong", { children: "3. Example with JavaScript:" }),
102
102
  /* @__PURE__ */ jsx("div", { className: "mt-1 p-2 bg-gray-100 rounded font-mono text-xs overflow-x-auto", children: `fetch('/api/v1/users', {
103
103
  headers: {
104
104
  'Authorization': 'Bearer ${isVisible ? apiKey : "YOUR_API_KEY"}',
@@ -109,20 +109,20 @@ function ApiKeyDisplay({ apiKey, keyName, warning, onClose }) {
109
109
  ] })
110
110
  ] }),
111
111
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
112
- /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-green-800", children: "Consejos de seguridad:" }),
112
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-green-800", children: "Security tips:" }),
113
113
  /* @__PURE__ */ jsxs("ul", { className: "text-sm text-green-700 space-y-1 list-disc list-inside", children: [
114
- /* @__PURE__ */ jsx("li", { children: "Nunca compartas tu API key p\xFAblicamente" }),
115
- /* @__PURE__ */ jsx("li", { children: "Gu\xE1rdala como variable de entorno en tu aplicaci\xF3n" }),
116
- /* @__PURE__ */ jsx("li", { children: "Revoca la key inmediatamente si crees que est\xE1 comprometida" }),
117
- /* @__PURE__ */ jsx("li", { children: "Usa HTTPS siempre al hacer requests a la API" })
114
+ /* @__PURE__ */ jsx("li", { children: "Never share your API key publicly" }),
115
+ /* @__PURE__ */ jsx("li", { children: "Store it as an environment variable in your application" }),
116
+ /* @__PURE__ */ jsx("li", { children: "Revoke the key immediately if you think it's compromised" }),
117
+ /* @__PURE__ */ jsx("li", { children: "Always use HTTPS when making requests to the API" })
118
118
  ] })
119
119
  ] }),
120
120
  /* @__PURE__ */ jsxs("div", { className: "p-3 bg-blue-50 rounded-lg border border-blue-200", children: [
121
- /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-blue-800 mb-1", children: "L\xEDmites de la API:" }),
121
+ /* @__PURE__ */ jsx("h4", { className: "text-sm font-medium text-blue-800 mb-1", children: "API limits:" }),
122
122
  /* @__PURE__ */ jsxs("div", { className: "text-sm text-blue-700 space-y-1", children: [
123
- /* @__PURE__ */ jsx("div", { children: "\u2022 1,000 requests por minuto" }),
124
- /* @__PURE__ */ jsx("div", { children: "\u2022 Headers de rate limiting incluidos en respuestas" }),
125
- /* @__PURE__ */ jsx("div", { children: "\u2022 Documentaci\xF3n completa disponible en /docs" })
123
+ /* @__PURE__ */ jsx("div", { children: "\u2022 1,000 requests per minute" }),
124
+ /* @__PURE__ */ jsx("div", { children: "\u2022 Rate limiting headers included in responses" }),
125
+ /* @__PURE__ */ jsx("div", { children: "\u2022 Full documentation available at /docs" })
126
126
  ] })
127
127
  ] }),
128
128
  /* @__PURE__ */ jsxs("div", { className: "flex gap-2 pt-2", children: [
@@ -134,11 +134,11 @@ function ApiKeyDisplay({ apiKey, keyName, warning, onClose }) {
134
134
  className: "flex-1",
135
135
  children: [
136
136
  /* @__PURE__ */ jsx(Copy, { className: "h-4 w-4 mr-2" }),
137
- copied ? "API Key Copiada!" : "Copiar API Key"
137
+ copied ? "API Key Copied!" : "Copy API Key"
138
138
  ]
139
139
  }
140
140
  ),
141
- /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "outline", children: "Entendido" })
141
+ /* @__PURE__ */ jsx(Button, { onClick: onClose, variant: "outline", children: "Got it" })
142
142
  ] })
143
143
  ] })
144
144
  ] });
@@ -35,8 +35,8 @@ function useScopeCatalogue() {
35
35
  return {
36
36
  ...SCOPE_CATEGORIES,
37
37
  app: {
38
- name: "Aplicaci\xF3n",
39
- description: "Scopes que esta aplicaci\xF3n define para sus propias rutas",
38
+ name: "Application",
39
+ description: "Scopes this application defines for its own routes",
40
40
  scopes: appScopes
41
41
  }
42
42
  };
@@ -134,35 +134,35 @@ function CreateApiKeyDialog({ open, onClose, onSuccess }) {
134
134
  };
135
135
  return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: handleClose, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-2xl max-h-[90vh] overflow-y-auto", "data-cy": sel("settings.apiKeys.createDialog.container"), children: [
136
136
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
137
- /* @__PURE__ */ jsx(DialogTitle, { children: "Crear nueva API Key" }),
138
- /* @__PURE__ */ jsx(DialogDescription, { children: "Crea una API key para acceder a los endpoints externos de forma segura." })
137
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Create new API Key" }),
138
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Create an API key to securely access the external endpoints." })
139
139
  ] }),
140
140
  /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-6", children: [
141
141
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
142
- /* @__PURE__ */ jsx(Label, { htmlFor: "name", children: "Nombre de la API Key" }),
142
+ /* @__PURE__ */ jsx(Label, { htmlFor: "name", children: "API Key Name" }),
143
143
  /* @__PURE__ */ jsx(
144
144
  Input,
145
145
  {
146
146
  id: "name",
147
147
  value: name,
148
148
  onChange: (e) => setName(e.target.value),
149
- placeholder: "ej. Mi aplicaci\xF3n m\xF3vil",
149
+ placeholder: "e.g. My mobile app",
150
150
  maxLength: 100,
151
151
  "data-cy": sel("settings.apiKeys.createDialog.nameInput")
152
152
  }
153
153
  ),
154
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Un nombre descriptivo para identificar esta API key" })
154
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "A descriptive name to identify this API key" })
155
155
  ] }),
156
156
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
157
- /* @__PURE__ */ jsx(Label, { children: "Expiraci\xF3n" }),
157
+ /* @__PURE__ */ jsx(Label, { children: "Expiration" }),
158
158
  /* @__PURE__ */ jsxs(Select, { value: expiryOption, onValueChange: (value) => setExpiryOption(value), children: [
159
159
  /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
160
160
  /* @__PURE__ */ jsxs(SelectContent, { children: [
161
- /* @__PURE__ */ jsx(SelectItem, { value: "never", children: "Nunca expira" }),
162
- /* @__PURE__ */ jsx(SelectItem, { value: "30d", children: "30 d\xEDas" }),
163
- /* @__PURE__ */ jsx(SelectItem, { value: "90d", children: "90 d\xEDas" }),
164
- /* @__PURE__ */ jsx(SelectItem, { value: "1y", children: "1 a\xF1o" }),
165
- /* @__PURE__ */ jsx(SelectItem, { value: "custom", children: "Fecha personalizada" })
161
+ /* @__PURE__ */ jsx(SelectItem, { value: "never", children: "Never expires" }),
162
+ /* @__PURE__ */ jsx(SelectItem, { value: "30d", children: "30 days" }),
163
+ /* @__PURE__ */ jsx(SelectItem, { value: "90d", children: "90 days" }),
164
+ /* @__PURE__ */ jsx(SelectItem, { value: "1y", children: "1 year" }),
165
+ /* @__PURE__ */ jsx(SelectItem, { value: "custom", children: "Custom date" })
166
166
  ] })
167
167
  ] }),
168
168
  expiryOption === "custom" && /* @__PURE__ */ jsx(
@@ -177,12 +177,12 @@ function CreateApiKeyDialog({ open, onClose, onSuccess }) {
177
177
  ] }),
178
178
  /* @__PURE__ */ jsxs("div", { className: "space-y-4", "data-cy": sel("settings.apiKeys.createDialog.scopesContainer"), children: [
179
179
  /* @__PURE__ */ jsxs("div", { children: [
180
- /* @__PURE__ */ jsx(Label, { children: "Permisos (Scopes)" }),
181
- /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Selecciona los permisos que tendr\xE1 esta API key" })
180
+ /* @__PURE__ */ jsx(Label, { children: "Permissions (Scopes)" }),
181
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Choose the permissions this API key will have" })
182
182
  ] }),
183
183
  /* @__PURE__ */ jsxs(Alert, { children: [
184
184
  /* @__PURE__ */ jsx(Info, { className: "h-4 w-4" }),
185
- /* @__PURE__ */ jsx(AlertDescription, { children: "Solo puedes asignar permisos que tu rol actual permite. Los permisos no se pueden cambiar despu\xE9s de crear la API key." })
185
+ /* @__PURE__ */ jsx(AlertDescription, { children: "You can only assign permissions that your current role allows. Permissions cannot be changed after creating the API key." })
186
186
  ] }),
187
187
  /* @__PURE__ */ jsx("div", { className: "space-y-4", children: Object.entries(scopeCatalogue).map(([categoryKey, category]) => {
188
188
  const isFullySelected = isCategoryFullySelected(category.scopes);
@@ -232,7 +232,7 @@ function CreateApiKeyDialog({ open, onClose, onSuccess }) {
232
232
  }) }),
233
233
  selectedScopes.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
234
234
  /* @__PURE__ */ jsxs(Label, { children: [
235
- "Permisos seleccionados (",
235
+ "Selected permissions (",
236
236
  selectedScopes.length,
237
237
  ")"
238
238
  ] }),
@@ -242,20 +242,20 @@ function CreateApiKeyDialog({ open, onClose, onSuccess }) {
242
242
  /* @__PURE__ */ jsxs(Alert, { variant: "destructive", children: [
243
243
  /* @__PURE__ */ jsx(AlertTriangle, { className: "h-4 w-4" }),
244
244
  /* @__PURE__ */ jsxs(AlertDescription, { children: [
245
- /* @__PURE__ */ jsx("strong", { children: "Importante:" }),
246
- " La API key se mostrar\xE1 solo una vez despu\xE9s de crearla. Gu\xE1rdala en un lugar seguro ya que no podr\xE1s verla nuevamente."
245
+ /* @__PURE__ */ jsx("strong", { children: "Important:" }),
246
+ " The API key will only be shown once after creation. Store it somewhere safe, as you won't be able to see it again."
247
247
  ] })
248
248
  ] })
249
249
  ] }),
250
250
  /* @__PURE__ */ jsxs(DialogFooter, { "data-cy": sel("settings.apiKeys.createDialog.footer"), children: [
251
- /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, disabled: createApiKey.isPending, children: "Cancelar" }),
251
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, disabled: createApiKey.isPending, children: "Cancel" }),
252
252
  /* @__PURE__ */ jsx(
253
253
  Button,
254
254
  {
255
255
  onClick: handleSubmit,
256
256
  disabled: createApiKey.isPending || selectedScopes.length === 0 || !name.trim(),
257
257
  "data-cy": sel("settings.apiKeys.createDialog.submitButton"),
258
- children: createApiKey.isPending ? "Creando..." : "Crear API Key"
258
+ children: createApiKey.isPending ? "Creating..." : "Create API Key"
259
259
  }
260
260
  )
261
261
  ] })
@@ -1 +1 @@
1
- {"version":3,"file":"PublicNavbar.d.ts","sourceRoot":"","sources":["../../../../src/components/app/layouts/PublicNavbar.tsx"],"names":[],"mappings":"AAaA,wBAAgB,YAAY,4CAyJ3B"}
1
+ {"version":3,"file":"PublicNavbar.d.ts","sourceRoot":"","sources":["../../../../src/components/app/layouts/PublicNavbar.tsx"],"names":[],"mappings":"AAqGA,wBAAgB,YAAY,4CAsG3B"}
@@ -2,6 +2,7 @@
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import Link from "next/link";
4
4
  import { useAuth } from "../../../hooks/useAuth.js";
5
+ import { useSessionHint } from "../../../hooks/useSessionHint.js";
5
6
  import { Button } from "../../ui/button.js";
6
7
  import { ThemeToggle } from "../misc/ThemeToggle.js";
7
8
  import { Menu, X } from "lucide-react";
@@ -9,11 +10,40 @@ import { useState } from "react";
9
10
  import { sel } from "../../../lib/test/index.js";
10
11
  import { useTranslations } from "next-intl";
11
12
  import { APP_NAME } from "../../../lib/config/index.js";
12
- function PublicNavbar() {
13
+ function AuthActionsSkeleton({ layout }) {
14
+ return layout === "desktop" ? /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
15
+ /* @__PURE__ */ jsx("div", { className: "h-9 w-16 bg-muted animate-pulse rounded-md" }),
16
+ /* @__PURE__ */ jsx("div", { className: "h-9 w-20 bg-muted animate-pulse rounded-md" })
17
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-2", children: [
18
+ /* @__PURE__ */ jsx("div", { className: "h-9 bg-muted animate-pulse rounded-md" }),
19
+ /* @__PURE__ */ jsx("div", { className: "h-9 bg-muted animate-pulse rounded-md" })
20
+ ] });
21
+ }
22
+ function SignedOutActions({ layout, onNavigate }) {
23
+ const tHome = useTranslations("home");
24
+ return layout === "desktop" ? /* @__PURE__ */ jsxs(Fragment, { children: [
25
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", asChild: true, "data-cy": sel("public.navbar.loginButton"), children: /* @__PURE__ */ jsx(Link, { href: "/login", children: tHome("auth.signIn") }) }),
26
+ /* @__PURE__ */ jsx(Button, { asChild: true, "data-cy": sel("public.navbar.signupButton"), children: /* @__PURE__ */ jsx(Link, { href: "/signup", children: tHome("auth.createAccount") }) })
27
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
28
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", asChild: true, className: "w-full", children: /* @__PURE__ */ jsx(Link, { href: "/login", onClick: onNavigate, children: tHome("auth.signIn") }) }),
29
+ /* @__PURE__ */ jsx(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsx(Link, { href: "/signup", onClick: onNavigate, children: tHome("auth.createAccount") }) })
30
+ ] });
31
+ }
32
+ function SessionActions({ layout, onNavigate }) {
13
33
  const { user, isLoading } = useAuth();
34
+ const tHome = useTranslations("home");
35
+ if (isLoading) return /* @__PURE__ */ jsx(AuthActionsSkeleton, { layout });
36
+ if (!user) return /* @__PURE__ */ jsx(SignedOutActions, { layout, onNavigate });
37
+ return layout === "desktop" ? /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href: "/dashboard", children: tHome("auth.goToDashboard") }) }) : /* @__PURE__ */ jsx(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsx(Link, { href: "/dashboard", onClick: onNavigate, children: tHome("auth.goToDashboard") }) });
38
+ }
39
+ function AuthActions(props) {
40
+ const { ready, signedIn } = useSessionHint();
41
+ if (!ready) return /* @__PURE__ */ jsx(AuthActionsSkeleton, { layout: props.layout });
42
+ return signedIn ? /* @__PURE__ */ jsx(SessionActions, { ...props }) : /* @__PURE__ */ jsx(SignedOutActions, { ...props });
43
+ }
44
+ function PublicNavbar() {
14
45
  const [isMenuOpen, setIsMenuOpen] = useState(false);
15
46
  const tNav = useTranslations("navigation");
16
- const tHome = useTranslations("home");
17
47
  const appName = APP_NAME;
18
48
  const navigationItems = [
19
49
  { name: "features", href: "/features" },
@@ -53,13 +83,7 @@ function PublicNavbar() {
53
83
  /* @__PURE__ */ jsx("div", { className: "w-full flex-1 md:w-auto md:flex-none" }),
54
84
  /* @__PURE__ */ jsxs("div", { className: "hidden md:flex items-center gap-2", children: [
55
85
  /* @__PURE__ */ jsx(ThemeToggle, {}),
56
- isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
57
- /* @__PURE__ */ jsx("div", { className: "h-9 w-16 bg-muted animate-pulse rounded-md" }),
58
- /* @__PURE__ */ jsx("div", { className: "h-9 w-20 bg-muted animate-pulse rounded-md" })
59
- ] }) : user ? /* @__PURE__ */ jsx(Button, { asChild: true, children: /* @__PURE__ */ jsx(Link, { href: "/dashboard", children: tHome("auth.goToDashboard") }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
60
- /* @__PURE__ */ jsx(Button, { variant: "ghost", asChild: true, "data-cy": sel("public.navbar.loginButton"), children: /* @__PURE__ */ jsx(Link, { href: "/login", children: tHome("auth.signIn") }) }),
61
- /* @__PURE__ */ jsx(Button, { asChild: true, "data-cy": sel("public.navbar.signupButton"), children: /* @__PURE__ */ jsx(Link, { href: "/signup", children: tHome("auth.createAccount") }) })
62
- ] })
86
+ /* @__PURE__ */ jsx(AuthActions, { layout: "desktop" })
63
87
  ] }),
64
88
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 md:hidden", children: [
65
89
  /* @__PURE__ */ jsx(ThemeToggle, {}),
@@ -86,13 +110,7 @@ function PublicNavbar() {
86
110
  },
87
111
  item.name
88
112
  )) }),
89
- /* @__PURE__ */ jsx("div", { className: "flex flex-col space-y-2 pt-4 border-t border-border", children: isLoading ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-2", children: [
90
- /* @__PURE__ */ jsx("div", { className: "h-9 bg-muted animate-pulse rounded-md" }),
91
- /* @__PURE__ */ jsx("div", { className: "h-9 bg-muted animate-pulse rounded-md" })
92
- ] }) : user ? /* @__PURE__ */ jsx(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsx(Link, { href: "/dashboard", onClick: () => setIsMenuOpen(false), children: tHome("auth.goToDashboard") }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
93
- /* @__PURE__ */ jsx(Button, { variant: "ghost", asChild: true, className: "w-full", children: /* @__PURE__ */ jsx(Link, { href: "/login", onClick: () => setIsMenuOpen(false), children: tHome("auth.signIn") }) }),
94
- /* @__PURE__ */ jsx(Button, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsx(Link, { href: "/signup", onClick: () => setIsMenuOpen(false), children: tHome("auth.createAccount") }) })
95
- ] }) })
113
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col space-y-2 pt-4 border-t border-border", children: /* @__PURE__ */ jsx(AuthActions, { layout: "mobile", onNavigate: () => setIsMenuOpen(false) }) })
96
114
  ] }) })
97
115
  ]
98
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../../../src/components/app/misc/ThemeToggle.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,WAAW,4CA4H1B"}
1
+ {"version":3,"file":"ThemeToggle.d.ts","sourceRoot":"","sources":["../../../../src/components/app/misc/ThemeToggle.tsx"],"names":[],"mappings":"AAiBA,wBAAgB,WAAW,4CA6H1B"}
@@ -12,10 +12,9 @@ import {
12
12
  import { useEffect, useState, useCallback } from "react";
13
13
  import { createAriaLabel, sel } from "../../../lib/test/index.js";
14
14
  import { useTranslations } from "next-intl";
15
- import { useAuth } from "../../../hooks/useAuth.js";
15
+ import { hasSessionHint } from "../../../lib/auth/session-hint.js";
16
16
  function ThemeToggle() {
17
17
  const { setTheme, theme, forcedTheme } = useTheme();
18
- const { user } = useAuth();
19
18
  const [mounted, setMounted] = useState(false);
20
19
  const [statusMessage, setStatusMessage] = useState("");
21
20
  const t = useTranslations("common");
@@ -30,7 +29,7 @@ function ThemeToggle() {
30
29
  system: t("theme.system")
31
30
  };
32
31
  setStatusMessage(`${t("theme.changed")} ${themeNames[newTheme]}`);
33
- if (user == null ? void 0 : user.id) {
32
+ if (hasSessionHint()) {
34
33
  try {
35
34
  await fetch("/api/user/profile", {
36
35
  method: "PATCH",
@@ -49,7 +48,7 @@ function ThemeToggle() {
49
48
  console.error("[ThemeToggle] Failed to save theme preference:", error);
50
49
  }
51
50
  }
52
- }, [setTheme, t, user]);
51
+ }, [setTheme, t]);
53
52
  if (forcedTheme) {
54
53
  return null;
55
54
  }
@@ -9,6 +9,11 @@ import { type UseSessionCookieRefreshOptions } from '../../hooks/useSessionCooki
9
9
  * `useSessionCookieRefresh` for the options and `lib/auth/session-refresh.ts`
10
10
  * for why render-time session reads cannot do this themselves.
11
11
  *
12
+ * It only asks while the browser is signed in (see `lib/auth/session-hint`),
13
+ * following the hint as a sign-in or sign-out on the page changes it, so an
14
+ * anonymous visitor makes no request; and each answer brings the locale cookie
15
+ * and the theme in line with the account (`useAccountPreferencesSync`).
16
+ *
12
17
  * @example
13
18
  * ```tsx
14
19
  * // app/layout.tsx
@@ -1 +1 @@
1
- {"version":3,"file":"SessionCookieRefresher.d.ts","sourceRoot":"","sources":["../../../src/components/auth/SessionCookieRefresher.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,qCAAqC,CAAA;AAE5C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,GAAE,8BAAmC,OAGhF"}
1
+ {"version":3,"file":"SessionCookieRefresher.d.ts","sourceRoot":"","sources":["../../../src/components/auth/SessionCookieRefresher.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,qCAAqC,CAAA;AAM5C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,GAAE,8BAAmC,OAOhF"}
@@ -1,9 +1,15 @@
1
1
  "use client";
2
+ import { useSyncExternalStore } from "react";
2
3
  import {
3
4
  useSessionCookieRefresh
4
5
  } from "../../hooks/useSessionCookieRefresh.js";
6
+ import { useAccountPreferencesSync } from "../../hooks/useAccountPreferencesSync.js";
7
+ import { hasSessionHint, subscribeSessionHint } from "../../lib/auth/session-hint.js";
8
+ const signedOutOnServer = () => false;
5
9
  function SessionCookieRefresher(props = {}) {
6
- useSessionCookieRefresh(props);
10
+ const signedIn = useSyncExternalStore(subscribeSessionHint, hasSessionHint, signedOutOnServer);
11
+ const onRefresh = useAccountPreferencesSync();
12
+ useSessionCookieRefresh({ ...props, enabled: (props.enabled ?? true) && signedIn, onRefresh });
7
13
  return null;
8
14
  }
9
15
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/LoginForm.tsx"],"names":[],"mappings":"AAmIA,wBAAgB,SAAS,4CAisBxB"}
1
+ {"version":3,"file":"LoginForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/LoginForm.tsx"],"names":[],"mappings":"AAsIA,wBAAgB,SAAS,4CAmvBxB"}
@@ -6,7 +6,8 @@ import { useSearchParams } from "next/navigation";
6
6
  import { useForm } from "react-hook-form";
7
7
  import { zodResolver } from "@hookform/resolvers/zod";
8
8
  import { z } from "zod";
9
- import { useAuth } from "../../../hooks/useAuth.js";
9
+ import { useAuthActions } from "../../../hooks/useAuth.js";
10
+ import { safeCallbackPath } from "../../../lib/auth/callback-url.js";
10
11
  import { useLastAuthMethod } from "../../../hooks/useLastAuthMethod.js";
11
12
  import { Button } from "../../ui/button.js";
12
13
  import { Input } from "../../ui/input.js";
@@ -24,6 +25,7 @@ import { AuthTranslationPreloader } from "../../../lib/i18n/AuthTranslationPrelo
24
25
  import { DevKeyring } from "../DevKeyring.js";
25
26
  import { DEV_CONFIG, PUBLIC_AUTH_CONFIG } from "../../../lib/config/config-sync.js";
26
27
  import { getPrimaryEmailMethod } from "../../../lib/auth/auth-methods.js";
28
+ import { DEFAULT_OTP_CONFIG, formatOtpCountdown, getOtpSecondsRemaining } from "../../../lib/auth/otp-config.js";
27
29
  function getErrorMessageFromCode(error, t, context) {
28
30
  const authError = error;
29
31
  const errorCode = authError.code || getErrorCodeFromMessage(error.message);
@@ -94,13 +96,15 @@ function buildLoginSchema(t) {
94
96
  password: z.string().min(6, t("login.errors.passwordTooShort", { defaultValue: "Password must be at least 6 characters" }))
95
97
  });
96
98
  }
97
- const OTP_CODE_LENGTH = 6;
98
99
  function buildOtpEmailSchema(t) {
99
100
  return z.string().trim().email({ message: t("login.errors.invalidEmail", { defaultValue: "Invalid email" }) });
100
101
  }
101
- function buildOtpCodeSchema(t) {
102
- return z.string().trim().regex(new RegExp(`^\\d{${OTP_CODE_LENGTH}}$`), {
103
- message: t("login.errors.otpInvalidCode", { defaultValue: `Enter the ${OTP_CODE_LENGTH}-digit code` })
102
+ function buildOtpCodeSchema(t, length) {
103
+ return z.string().trim().regex(new RegExp(`^\\d{${length}}$`), {
104
+ message: t("login.errors.otpInvalidCode", {
105
+ length,
106
+ defaultValue: `Enter the ${length}-digit code`
107
+ })
104
108
  });
105
109
  }
106
110
  function LoginForm() {
@@ -109,6 +113,9 @@ function LoginForm() {
109
113
  const googleEnabled = PUBLIC_AUTH_CONFIG.providers.google.enabled;
110
114
  const methods = PUBLIC_AUTH_CONFIG.methods;
111
115
  const otpEnabled = methods.includes("email-otp");
116
+ const otpConfig = PUBLIC_AUTH_CONFIG.otp ?? DEFAULT_OTP_CONFIG;
117
+ const otpLength = otpConfig.otpLength;
118
+ const otpExpiresIn = otpConfig.expiresIn;
112
119
  const devKeyringActive = process.env.NODE_ENV !== "production" && !!((_b = (_a = DEV_CONFIG) == null ? void 0 : _a.devKeyring) == null ? void 0 : _b.enabled);
113
120
  const passwordEnabled = methods.includes("email-password") || devKeyringActive;
114
121
  const signupVisible = (registrationMode === "open" || registrationMode === "domain-open") && methods.includes("email-password");
@@ -129,23 +136,36 @@ function LoginForm() {
129
136
  const [otpCode, setOtpCode] = useState("");
130
137
  const [otpEmailError, setOtpEmailError] = useState(null);
131
138
  const [otpCodeError, setOtpCodeError] = useState(null);
139
+ const [otpSentAt, setOtpSentAt] = useState(null);
140
+ const [otpSecondsLeft, setOtpSecondsLeft] = useState(otpExpiresIn);
132
141
  const isProcessingRef = useRef(false);
133
- const { signIn, googleSignIn, sendOtp, signInWithOtp } = useAuth();
142
+ const { signIn, googleSignIn, sendOtp, signInWithOtp } = useAuthActions();
134
143
  const { lastMethod, isReady } = useLastAuthMethod();
135
144
  const t = useTranslations("auth");
136
145
  const loginSchema = useMemo(() => buildLoginSchema(t), [t]);
137
146
  const otpEmailSchema = useMemo(() => buildOtpEmailSchema(t), [t]);
138
- const otpCodeSchema = useMemo(() => buildOtpCodeSchema(t), [t]);
147
+ const otpCodeSchema = useMemo(() => buildOtpCodeSchema(t, otpLength), [t, otpLength]);
139
148
  const searchParams = useSearchParams();
140
149
  const inviteEmail = searchParams.get("email");
141
150
  const fromInvite = searchParams.get("fromInvite") === "true";
142
- const callbackUrl = searchParams.get("callbackUrl");
151
+ const callbackUrl = safeCallbackPath(searchParams.get("callbackUrl"));
143
152
  useEffect(() => {
144
153
  if (fromInvite && inviteEmail) {
145
154
  setShowEmailForm(true);
146
155
  setOtpEmail(inviteEmail);
147
156
  }
148
157
  }, [fromInvite, inviteEmail]);
158
+ useEffect(() => {
159
+ if (otpSentAt === null) return;
160
+ const tick = () => {
161
+ const remaining = getOtpSecondsRemaining(otpSentAt, otpExpiresIn);
162
+ setOtpSecondsLeft(remaining);
163
+ if (remaining <= 0) clearInterval(intervalId);
164
+ };
165
+ const intervalId = setInterval(tick, 1e3);
166
+ tick();
167
+ return () => clearInterval(intervalId);
168
+ }, [otpSentAt, otpExpiresIn]);
149
169
  const switchEmailMode = useCallback((mode) => {
150
170
  setEmailMode(mode);
151
171
  setError(null);
@@ -153,6 +173,7 @@ function LoginForm() {
153
173
  setOtpCodeError(null);
154
174
  setOtpStep("email");
155
175
  setOtpCode("");
176
+ setOtpSentAt(null);
156
177
  }, []);
157
178
  const handleSendOtp = useCallback(async (event) => {
158
179
  var _a2;
@@ -168,11 +189,14 @@ function LoginForm() {
168
189
  setError(null);
169
190
  setLoadingProvider("email");
170
191
  setStatusMessage(t("login.messages.otpSending"));
192
+ const sentAt = Date.now();
171
193
  try {
172
194
  await sendOtp(parsed.data);
173
195
  setOtpEmail(parsed.data);
174
196
  setOtpCode("");
175
197
  setOtpStep("code");
198
+ setOtpSentAt(sentAt);
199
+ setOtpSecondsLeft(getOtpSecondsRemaining(sentAt, otpExpiresIn));
176
200
  setStatusMessage(t("login.messages.otpSent"));
177
201
  } catch (err) {
178
202
  const error2 = err instanceof Error ? err : new Error(t("login.messages.otpSendFailed"));
@@ -182,7 +206,7 @@ function LoginForm() {
182
206
  } finally {
183
207
  setLoadingProvider(null);
184
208
  }
185
- }, [loadingProvider, otpEmail, otpEmailSchema, sendOtp, t]);
209
+ }, [loadingProvider, otpEmail, otpEmailSchema, otpExpiresIn, sendOtp, t]);
186
210
  const handleVerifyOtp = useCallback(async (event) => {
187
211
  var _a2;
188
212
  event == null ? void 0 : event.preventDefault();
@@ -414,7 +438,20 @@ function LoginForm() {
414
438
  ] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
415
439
  /* @__PURE__ */ jsxs(Alert, { "data-cy": sel("auth.login.otpSentNotice"), children: [
416
440
  /* @__PURE__ */ jsx(Mail, { className: "h-4 w-4", "aria-hidden": "true" }),
417
- /* @__PURE__ */ jsx(AlertDescription, { children: t("login.form.otp.codeSent", { email: otpEmail }) })
441
+ /* @__PURE__ */ jsxs(AlertDescription, { children: [
442
+ t("login.form.otp.codeSent", { email: otpEmail, length: otpLength }),
443
+ " ",
444
+ /* @__PURE__ */ jsx(
445
+ "span",
446
+ {
447
+ "data-cy": sel("auth.login.otpCountdown"),
448
+ "aria-live": otpSecondsLeft > 0 ? "off" : "polite",
449
+ children: otpSecondsLeft > 0 ? t("login.form.otp.expiresIn", {
450
+ time: formatOtpCountdown(otpSecondsLeft)
451
+ }) : t("login.form.otp.expired")
452
+ }
453
+ )
454
+ ] })
418
455
  ] }),
419
456
  /* @__PURE__ */ jsx(Label, { htmlFor: "otp-code", children: t("login.form.otp.codeLabel") }),
420
457
  /* @__PURE__ */ jsxs("div", { className: "relative", children: [
@@ -427,9 +464,9 @@ function LoginForm() {
427
464
  inputMode: "numeric",
428
465
  autoComplete: "one-time-code",
429
466
  pattern: "[0-9]*",
430
- maxLength: OTP_CODE_LENGTH,
467
+ maxLength: otpLength,
431
468
  value: otpCode,
432
- onChange: (e) => setOtpCode(e.target.value.replace(/\D/g, "").slice(0, OTP_CODE_LENGTH)),
469
+ onChange: (e) => setOtpCode(e.target.value.replace(/\D/g, "").slice(0, otpLength)),
433
470
  placeholder: t("login.form.otp.codePlaceholder"),
434
471
  className: "pl-9 tracking-widest",
435
472
  autoFocus: true,
@@ -1 +1 @@
1
- {"version":3,"file":"SignupForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/SignupForm.tsx"],"names":[],"mappings":"AA6BA,wBAAgB,UAAU,4CAmgBzB"}
1
+ {"version":3,"file":"SignupForm.d.ts","sourceRoot":"","sources":["../../../../src/components/auth/forms/SignupForm.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,UAAU,4CAmgBzB"}
@@ -5,7 +5,8 @@ import Link from "next/link";
5
5
  import { useSearchParams, useRouter } from "next/navigation";
6
6
  import { useForm } from "react-hook-form";
7
7
  import { zodResolver } from "@hookform/resolvers/zod";
8
- import { useAuth } from "../../../hooks/useAuth.js";
8
+ import { useAuthActions } from "../../../hooks/useAuth.js";
9
+ import { safeCallbackPath } from "../../../lib/auth/callback-url.js";
9
10
  import { Button } from "../../ui/button.js";
10
11
  import { Input } from "../../ui/input.js";
11
12
  import { Label } from "../../ui/label.js";
@@ -30,12 +31,12 @@ function SignupForm() {
30
31
  const [registeredEmail, setRegisteredEmail] = useState("");
31
32
  const [resendingEmail, setResendingEmail] = useState(false);
32
33
  const [statusMessage, setStatusMessage] = useState("");
33
- const { signUp, googleSignIn, resendVerificationEmail } = useAuth();
34
+ const { signUp, googleSignIn, resendVerificationEmail } = useAuthActions();
34
35
  const t = useTranslations("auth");
35
36
  const searchParams = useSearchParams();
36
37
  const inviteEmail = searchParams.get("email");
37
38
  const fromInvite = searchParams.get("fromInvite") === "true";
38
- const callbackUrl = searchParams.get("callbackUrl");
39
+ const callbackUrl = safeCallbackPath(searchParams.get("callbackUrl"));
39
40
  const inviteToken = searchParams.get("inviteToken");
40
41
  const {
41
42
  register,
@@ -10,7 +10,7 @@ import { cn } from "../../../lib/utils/index.js";
10
10
  import { sel } from "../../../lib/test/index.js";
11
11
  import { DynamicForm } from "./dynamic-form.js";
12
12
  import { isPatternReference } from "../../../types/pattern-reference.js";
13
- import { BLOCK_REGISTRY } from "@nextsparkjs/registries/block-registry";
13
+ import { BLOCK_REGISTRY } from "@nextsparkjs/registries/block-registry.client";
14
14
  function groupFieldsByTab(fields) {
15
15
  const grouped = {
16
16
  content: [],
@@ -5,7 +5,7 @@ import { useTranslations } from "next-intl";
5
5
  import { Button } from "../../ui/button.js";
6
6
  import { cn } from "../../../lib/utils/index.js";
7
7
  import { sel } from "../../../lib/test/index.js";
8
- import { BLOCK_REGISTRY } from "@nextsparkjs/registries/block-registry";
8
+ import { BLOCK_REGISTRY } from "@nextsparkjs/registries/block-registry.client";
9
9
  function FloatingBlockToolbar({
10
10
  blockId,
11
11
  blockSlug,
@@ -7,7 +7,7 @@ import { Button } from "../../ui/button.js";
7
7
  import { Card, CardContent } from "../../ui/card.js";
8
8
  import { Badge } from "../../ui/badge.js";
9
9
  import { GripVertical, Copy, Trash2 } from "lucide-react";
10
- import { BLOCK_REGISTRY } from "@nextsparkjs/registries/block-registry";
10
+ import { BLOCK_REGISTRY } from "@nextsparkjs/registries/block-registry.client";
11
11
  import { cn } from "../../../lib/utils/index.js";
12
12
  import { sel } from "../../../lib/test/index.js";
13
13
  function SortableBlock({
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/layouts/Sidebar.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAA;AAGnF,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,wBAAwB,EAAE,CAAA;CACrC;AAED,wBAAgB,OAAO,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,2CAsG5D"}
1
+ {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../../src/components/dashboard/layouts/Sidebar.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAA;AAGnF,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,wBAAwB,EAAE,CAAA;CACrC;AAED,wBAAgB,OAAO,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,YAAY,2CAuG5D"}