@rebasepro/app 0.17.3 → 0.18.1

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 (185) hide show
  1. package/README.md +4 -1
  2. package/dist/components/index.d.ts +0 -3
  3. package/dist/contexts/AuthControllerContext.d.ts +2 -1
  4. package/dist/contexts/CustomizationControllerContext.d.ts +2 -1
  5. package/dist/contexts/DialogsProvider.d.ts +2 -1
  6. package/dist/contexts/RebaseDataContext.d.ts +10 -1
  7. package/dist/contexts/StorageSourceContext.d.ts +11 -1
  8. package/dist/core/RebaseProps.d.ts +2 -12
  9. package/dist/debug/index.d.ts +19 -0
  10. package/dist/debug.js +3631 -0
  11. package/dist/hooks/data/delete.d.ts +16 -7
  12. package/dist/hooks/data/save.d.ts +18 -4
  13. package/dist/hooks/index.d.ts +1 -0
  14. package/dist/hooks/useAdminModeController.d.ts +5 -4
  15. package/dist/hooks/useNavigationGroupLabel.d.ts +17 -0
  16. package/dist/hooks/useStudioBridge.d.ts +33 -0
  17. package/dist/index.es.js +2599 -6980
  18. package/dist/index.es.js.map +1 -1
  19. package/dist/vitePlugin.d.ts +22 -0
  20. package/dist/vitePlugin.js +40 -1
  21. package/package.json +42 -31
  22. package/src/auth/api.ts +0 -134
  23. package/src/auth/index.ts +0 -26
  24. package/src/auth/types.ts +0 -115
  25. package/src/auth/useRebaseAuthController.ts +0 -345
  26. package/src/collections/collection_view_config.ts +0 -76
  27. package/src/collections/entity-display-cache.ts +0 -195
  28. package/src/collections/entity-display.ts +0 -77
  29. package/src/collections/entity_image_preview.ts +0 -61
  30. package/src/collections/filter-operator-resolution.ts +0 -119
  31. package/src/collections/form-layout.ts +0 -394
  32. package/src/collections/index.ts +0 -13
  33. package/src/collections/navigation_from_path.ts +0 -123
  34. package/src/collections/navigation_utils.ts +0 -171
  35. package/src/collections/parent_references_from_path.ts +0 -59
  36. package/src/collections/property-path.ts +0 -30
  37. package/src/collections/property_presentation.ts +0 -264
  38. package/src/collections/summary-property.ts +0 -114
  39. package/src/collections/title-property.ts +0 -312
  40. package/src/components/AIIcon.tsx +0 -47
  41. package/src/components/AuthSimulationMenu.tsx +0 -0
  42. package/src/components/ConfirmationDialog.tsx +0 -48
  43. package/src/components/Debug/UIReferenceView.tsx +0 -1053
  44. package/src/components/Debug/UIStyleGuide.tsx +0 -159
  45. package/src/components/Debug/collection-views/CardViewDemo.tsx +0 -87
  46. package/src/components/Debug/collection-views/CollectionTableDemo.tsx +0 -107
  47. package/src/components/Debug/collection-views/KanbanBoardDemo.tsx +0 -89
  48. package/src/components/Debug/collection-views/index.ts +0 -3
  49. package/src/components/Debug/collection-views/sample_data.ts +0 -44
  50. package/src/components/Debug/crm-dashboard/CalendarWidget.tsx +0 -387
  51. package/src/components/Debug/crm-dashboard/CrmDashboardDemo.tsx +0 -1100
  52. package/src/components/Debug/crm-dashboard/DashboardMetrics.tsx +0 -131
  53. package/src/components/Debug/crm-dashboard/PipelineOverview.tsx +0 -288
  54. package/src/components/Debug/crm-dashboard/RecentActivity.tsx +0 -213
  55. package/src/components/Debug/crm-dashboard/TaskFilters.tsx +0 -182
  56. package/src/components/Debug/crm-dashboard/TaskTable.tsx +0 -425
  57. package/src/components/Debug/crm-dashboard/TasksView.tsx +0 -234
  58. package/src/components/ErrorTooltip.tsx +0 -12
  59. package/src/components/ErrorView.tsx +0 -94
  60. package/src/components/LanguageToggle.tsx +0 -59
  61. package/src/components/LoginView/LoginView.tsx +0 -1235
  62. package/src/components/LoginView/index.ts +0 -2
  63. package/src/components/LoginView/oauth-redirect-flow.ts +0 -184
  64. package/src/components/NotFoundPage.tsx +0 -27
  65. package/src/components/RebaseAuth.tsx +0 -27
  66. package/src/components/RebaseLogo.tsx +0 -88
  67. package/src/components/SchemaDriftBanner.tsx +0 -102
  68. package/src/components/UnsavedChangesDialog.tsx +0 -46
  69. package/src/components/UserDisplay.tsx +0 -54
  70. package/src/components/UserSelectPopover.tsx +0 -399
  71. package/src/components/UserSettingsView.tsx +0 -318
  72. package/src/components/common/index.ts +0 -6
  73. package/src/components/common/table_height.tsx +0 -21
  74. package/src/components/common/types.tsx +0 -66
  75. package/src/components/common/useColumnsIds.tsx +0 -261
  76. package/src/components/common/useDataTableController.tsx +0 -571
  77. package/src/components/common/useDebouncedData.ts +0 -49
  78. package/src/components/common/useScrollRestoration.tsx +0 -68
  79. package/src/components/index.tsx +0 -26
  80. package/src/contexts/AdminModeController.tsx +0 -11
  81. package/src/contexts/AnalyticsContext.tsx +0 -4
  82. package/src/contexts/AuthControllerContext.tsx +0 -4
  83. package/src/contexts/CollectionResolverContext.tsx +0 -24
  84. package/src/contexts/CollectionScopeContext.tsx +0 -68
  85. package/src/contexts/ComponentOverrideContext.tsx +0 -81
  86. package/src/contexts/CustomizationControllerContext.tsx +0 -4
  87. package/src/contexts/DataDriverContext.tsx +0 -4
  88. package/src/contexts/DataSourcesContext.tsx +0 -36
  89. package/src/contexts/DatabaseAdminContext.tsx +0 -4
  90. package/src/contexts/DialogsProvider.tsx +0 -56
  91. package/src/contexts/EffectiveRoleController.tsx +0 -12
  92. package/src/contexts/ModeController.tsx +0 -11
  93. package/src/contexts/RebaseClientInstanceContext.tsx +0 -7
  94. package/src/contexts/RebaseDataContext.tsx +0 -4
  95. package/src/contexts/SnackbarProvider.tsx +0 -15
  96. package/src/contexts/StorageSourceContext.tsx +0 -4
  97. package/src/contexts/StorageSourcesContext.tsx +0 -30
  98. package/src/contexts/UserConfigurationPersistenceContext.tsx +0 -4
  99. package/src/contexts/index.ts +0 -18
  100. package/src/core/PluginLifecycleManager.tsx +0 -96
  101. package/src/core/PluginProviderStack.tsx +0 -40
  102. package/src/core/Rebase.tsx +0 -488
  103. package/src/core/RebaseProps.tsx +0 -333
  104. package/src/core/RebaseRouter.tsx +0 -18
  105. package/src/core/RebaseRoutes.tsx +0 -24
  106. package/src/core/index.tsx +0 -5
  107. package/src/hooks/ApiConfigContext.tsx +0 -83
  108. package/src/hooks/data/collectionQuery.ts +0 -55
  109. package/src/hooks/data/delete.ts +0 -56
  110. package/src/hooks/data/save.ts +0 -78
  111. package/src/hooks/data/useCollection.tsx +0 -183
  112. package/src/hooks/data/useData.tsx +0 -18
  113. package/src/hooks/data/useDataOrder.ts +0 -26
  114. package/src/hooks/data/useFetch.tsx +0 -156
  115. package/src/hooks/data/useRelationSelector.tsx +0 -280
  116. package/src/hooks/index.tsx +0 -45
  117. package/src/hooks/useAdminModeController.tsx +0 -23
  118. package/src/hooks/useAnalyticsController.tsx +0 -8
  119. package/src/hooks/useAuthController.tsx +0 -15
  120. package/src/hooks/useAuthSubscription.ts +0 -130
  121. package/src/hooks/useBackendStorageSource.ts +0 -295
  122. package/src/hooks/useBridgeRegistration.tsx +0 -32
  123. package/src/hooks/useBrowserTitleAndIcon.tsx +0 -23
  124. package/src/hooks/useBuildAdminModeController.tsx +0 -29
  125. package/src/hooks/useBuildEffectiveRoleController.tsx +0 -30
  126. package/src/hooks/useBuildLocalConfigurationPersistence.tsx +0 -83
  127. package/src/hooks/useBuildModeController.tsx +0 -73
  128. package/src/hooks/useClipboard.tsx +0 -158
  129. package/src/hooks/useCollapsedGroups.ts +0 -116
  130. package/src/hooks/useComponentOverride.tsx +0 -59
  131. package/src/hooks/useCustomizationController.tsx +0 -14
  132. package/src/hooks/useDialogsController.tsx +0 -15
  133. package/src/hooks/useEffectiveRoleController.tsx +0 -10
  134. package/src/hooks/useLargeLayout.tsx +0 -65
  135. package/src/hooks/useModeController.tsx +0 -23
  136. package/src/hooks/useNavigationBlocker.tsx +0 -108
  137. package/src/hooks/usePermissions.ts +0 -45
  138. package/src/hooks/useRebaseClient.tsx +0 -10
  139. package/src/hooks/useRebaseContext.tsx +0 -84
  140. package/src/hooks/useRebaseRegistry.tsx +0 -91
  141. package/src/hooks/useResolvedComponent.tsx +0 -195
  142. package/src/hooks/useSlot.tsx +0 -64
  143. package/src/hooks/useSnackbarController.tsx +0 -80
  144. package/src/hooks/useStorageSource.tsx +0 -11
  145. package/src/hooks/useStudioBridge.tsx +0 -258
  146. package/src/hooks/useTranslation.ts +0 -38
  147. package/src/hooks/useUnsavedChangesDialog.tsx +0 -67
  148. package/src/hooks/useUserConfigurationPersistence.tsx +0 -11
  149. package/src/i18n/RebaseI18nProvider.tsx +0 -159
  150. package/src/index.ts +0 -32
  151. package/src/internal/common.tsx +0 -28
  152. package/src/internal/useRestoreScroll.tsx +0 -69
  153. package/src/locales/de.ts +0 -941
  154. package/src/locales/en.ts +0 -1021
  155. package/src/locales/es.ts +0 -962
  156. package/src/locales/fr.ts +0 -941
  157. package/src/locales/hi.ts +0 -941
  158. package/src/locales/it.ts +0 -941
  159. package/src/locales/pt.ts +0 -949
  160. package/src/util/constants.ts +0 -7
  161. package/src/util/createFormexStub.tsx +0 -66
  162. package/src/util/entity_cache.ts +0 -242
  163. package/src/util/enums.ts +0 -34
  164. package/src/util/icon_list.ts +0 -22
  165. package/src/util/icons.tsx +0 -129
  166. package/src/util/index.ts +0 -13
  167. package/src/util/local_storage.ts +0 -66
  168. package/src/util/previews.ts +0 -127
  169. package/src/util/useStorageUploadController.tsx +0 -354
  170. package/src/vitePlugin.ts +0 -215
  171. /package/dist/{components/Debug → debug}/UIReferenceView.d.ts +0 -0
  172. /package/dist/{components/Debug → debug}/UIStyleGuide.d.ts +0 -0
  173. /package/dist/{components/Debug → debug}/collection-views/CardViewDemo.d.ts +0 -0
  174. /package/dist/{components/Debug → debug}/collection-views/CollectionTableDemo.d.ts +0 -0
  175. /package/dist/{components/Debug → debug}/collection-views/KanbanBoardDemo.d.ts +0 -0
  176. /package/dist/{components/Debug → debug}/collection-views/index.d.ts +0 -0
  177. /package/dist/{components/Debug → debug}/collection-views/sample_data.d.ts +0 -0
  178. /package/dist/{components/Debug → debug}/crm-dashboard/CalendarWidget.d.ts +0 -0
  179. /package/dist/{components/Debug → debug}/crm-dashboard/CrmDashboardDemo.d.ts +0 -0
  180. /package/dist/{components/Debug → debug}/crm-dashboard/DashboardMetrics.d.ts +0 -0
  181. /package/dist/{components/Debug → debug}/crm-dashboard/PipelineOverview.d.ts +0 -0
  182. /package/dist/{components/Debug → debug}/crm-dashboard/RecentActivity.d.ts +0 -0
  183. /package/dist/{components/Debug → debug}/crm-dashboard/TaskFilters.d.ts +0 -0
  184. /package/dist/{components/Debug → debug}/crm-dashboard/TaskTable.d.ts +0 -0
  185. /package/dist/{components/Debug → debug}/crm-dashboard/TasksView.d.ts +0 -0
@@ -1,2 +0,0 @@
1
- export { LoginView } from "./LoginView";
2
- export type { LoginViewProps } from "./LoginView";
@@ -1,184 +0,0 @@
1
- /**
2
- * The browser half of the OAuth authorization-code flow.
3
- *
4
- * The server only ever sees a `code` and a `redirectUri` taken from the
5
- * request body, so `state`, PKCE and the binding between "this browser started
6
- * a login" and "this code came back" are, by construction, the client's job.
7
- * In the admin login they had been nobody's job: the authorize URL carried no
8
- * `state`, and the return leg accepted any `?code=` as long as a localStorage
9
- * marker naming the *provider* was set — a marker written on button click and
10
- * removed only on a callback that carried a code, so abandoning the flow left
11
- * it set indefinitely.
12
- *
13
- * Everything here is provider-agnostic on purpose. A button that wants a new
14
- * provider calls {@link startOAuthRedirect} and gets state, expiry and PKCE
15
- * without deciding anything, which is what stops the next provider shipping
16
- * without them.
17
- */
18
-
19
- /** sessionStorage, not localStorage: a login attempt belongs to one tab. */
20
- const STORAGE_KEY = "rebase_oauth_redirect";
21
-
22
- /** How long a started authorization stays valid. */
23
- const PENDING_TTL_MS = 10 * 60 * 1000;
24
-
25
- export interface OAuthRedirectRequest {
26
- /** Provider id, as mounted at `POST /auth/<id>`. */
27
- provider: string;
28
- /** The provider's authorization endpoint. */
29
- authorizeUrl: string;
30
- clientId: string;
31
- scope: string;
32
- /** Where the provider sends the browser back. Echoed to the token exchange. */
33
- redirectUri: string;
34
- /** Set when the provider implements PKCE. */
35
- pkce?: boolean;
36
- /** Extra authorize-endpoint parameters (`response_type`, and so on). */
37
- params?: Record<string, string>;
38
- }
39
-
40
- /** What the browser remembers between leaving for the provider and coming back. */
41
- export interface PendingOAuthRedirect {
42
- provider: string;
43
- state: string;
44
- codeVerifier?: string;
45
- redirectUri: string;
46
- startedAt: number;
47
- }
48
-
49
- export type OAuthCallbackResult =
50
- /** No OAuth callback in this URL. */
51
- | { status: "none" }
52
- /** The provider reported a failure, or the user declined. */
53
- | { status: "error"; error: string }
54
- /**
55
- * A code arrived that this browser cannot account for: no pending
56
- * authorization, an expired one, or a `state` that does not match. This is
57
- * what a login-CSRF / code-injection attempt looks like.
58
- */
59
- | { status: "mismatch" }
60
- | { status: "ok"; provider: string; code: string; codeVerifier?: string; redirectUri: string };
61
-
62
- type Storage = Pick<globalThis.Storage, "getItem" | "setItem" | "removeItem">;
63
-
64
- function defaultStorage(): Storage | null {
65
- try {
66
- return window.sessionStorage;
67
- } catch {
68
- return null;
69
- }
70
- }
71
-
72
- function base64Url(bytes: Uint8Array): string {
73
- let binary = "";
74
- for (const byte of bytes) binary += String.fromCharCode(byte);
75
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
76
- }
77
-
78
- function randomToken(byteLength = 32): string {
79
- const bytes = new Uint8Array(byteLength);
80
- crypto.getRandomValues(bytes);
81
- return base64Url(bytes);
82
- }
83
-
84
- async function pkceChallenge(verifier: string): Promise<string> {
85
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
86
- return base64Url(new Uint8Array(digest));
87
- }
88
-
89
- export function readPendingOAuthRedirect(storage: Storage | null = defaultStorage()): PendingOAuthRedirect | null {
90
- if (!storage) return null;
91
- const raw = storage.getItem(STORAGE_KEY);
92
- if (!raw) return null;
93
- try {
94
- const parsed = JSON.parse(raw) as PendingOAuthRedirect;
95
- if (!parsed?.provider || !parsed?.state) return null;
96
- return parsed;
97
- } catch {
98
- return null;
99
- }
100
- }
101
-
102
- export function clearPendingOAuthRedirect(storage: Storage | null = defaultStorage()): void {
103
- storage?.removeItem(STORAGE_KEY);
104
- }
105
-
106
- /**
107
- * Build the authorize URL and the pending record that will validate its
108
- * callback. Split out from {@link startOAuthRedirect} so it can be tested
109
- * without navigating.
110
- */
111
- export async function buildOAuthAuthorization(
112
- request: OAuthRedirectRequest,
113
- now: number = Date.now()
114
- ): Promise<{ url: string; pending: PendingOAuthRedirect }> {
115
- const state = randomToken();
116
- const url = new URL(request.authorizeUrl);
117
- url.searchParams.set("response_type", "code");
118
- url.searchParams.set("client_id", request.clientId);
119
- url.searchParams.set("redirect_uri", request.redirectUri);
120
- url.searchParams.set("scope", request.scope);
121
- url.searchParams.set("state", state);
122
- for (const [key, value] of Object.entries(request.params ?? {})) {
123
- url.searchParams.set(key, value);
124
- }
125
-
126
- let codeVerifier: string | undefined;
127
- if (request.pkce) {
128
- codeVerifier = randomToken(32);
129
- url.searchParams.set("code_challenge", await pkceChallenge(codeVerifier));
130
- url.searchParams.set("code_challenge_method", "S256");
131
- }
132
-
133
- return {
134
- url: url.toString(),
135
- pending: { provider: request.provider, state, codeVerifier, redirectUri: request.redirectUri, startedAt: now }
136
- };
137
- }
138
-
139
- /** Remember the authorization and send the browser to the provider. */
140
- export async function startOAuthRedirect(
141
- request: OAuthRedirectRequest,
142
- storage: Storage | null = defaultStorage()
143
- ): Promise<void> {
144
- const { url, pending } = await buildOAuthAuthorization(request);
145
- storage?.setItem(STORAGE_KEY, JSON.stringify(pending));
146
- window.location.href = url;
147
- }
148
-
149
- /**
150
- * Interpret a return from the provider.
151
- *
152
- * Clears the pending record on **every** path that saw a callback — including
153
- * `?error=` and a state mismatch — so a declined or abandoned consent screen
154
- * cannot leave the browser primed to accept somebody else's code later.
155
- */
156
- export function consumeOAuthCallback(
157
- search: string,
158
- storage: Storage | null = defaultStorage(),
159
- now: number = Date.now()
160
- ): OAuthCallbackResult {
161
- const params = new URLSearchParams(search);
162
- const code = params.get("code");
163
- const state = params.get("state");
164
- const error = params.get("error");
165
-
166
- if (!code && !error && !state) return { status: "none" };
167
-
168
- const pending = readPendingOAuthRedirect(storage);
169
- clearPendingOAuthRedirect(storage);
170
-
171
- if (error) return { status: "error", error };
172
- if (!code) return { status: "mismatch" };
173
- if (!pending) return { status: "mismatch" };
174
- if (now - pending.startedAt > PENDING_TTL_MS) return { status: "mismatch" };
175
- if (!state || state !== pending.state) return { status: "mismatch" };
176
-
177
- return {
178
- status: "ok",
179
- provider: pending.provider,
180
- code,
181
- codeVerifier: pending.codeVerifier,
182
- redirectUri: pending.redirectUri
183
- };
184
- }
@@ -1,27 +0,0 @@
1
- import React from "react";
2
- import { Link } from "react-router";
3
- import { Button, Typography } from "@rebasepro/ui";
4
- import { useTranslation } from "../hooks";
5
-
6
- export function NotFoundPage() {
7
- const { t } = useTranslation();
8
-
9
- return (
10
- <div className="flex w-full h-full">
11
- <div className="m-auto flex items-center flex-col"
12
- >
13
- <Typography variant={"h4"} align={"center"}
14
- gutterBottom={true}>
15
- {t("page_not_found")}
16
- </Typography>
17
- <Typography align={"center"} gutterBottom={true}>
18
- {t("page_not_found_body")}
19
- </Typography>
20
- <Button
21
- variant={"text"}
22
- component={Link}
23
- to={"/"}>{t("back_to_home")}</Button>
24
- </div>
25
- </div>
26
- );
27
- }
@@ -1,27 +0,0 @@
1
- import React, { useLayoutEffect, useRef } from "react";
2
- import { useRebaseRegistryDispatch } from "../hooks";
3
- import type { RebaseAuthViewConfig } from "@rebasepro/cms-types";
4
-
5
- /**
6
- * Declarative component to configure authentication in Rebase.
7
- * Renders nothing — purely registers config into the RebaseRegistry.
8
- *
9
- * This is a framework-level component that lives in core since
10
- * authentication is cross-cutting (admin, Studio, any app area).
11
- * @group Core
12
- */
13
- export function RebaseAuth({ loginView }: RebaseAuthViewConfig) {
14
- const dispatch = useRebaseRegistryDispatch();
15
- const registeredRef = useRef(false);
16
-
17
- useLayoutEffect(() => {
18
- dispatch.registerAuth({ loginView });
19
- registeredRef.current = true;
20
- return () => {
21
- registeredRef.current = false;
22
- dispatch.unregisterAuth();
23
- };
24
- }, [dispatch, loginView]);
25
-
26
- return null;
27
- }
@@ -1,88 +0,0 @@
1
- import React from "react";
2
-
3
- export function RebaseLogo({
4
- width,
5
- height,
6
- className,
7
- style
8
- }: {
9
- width?: string,
10
- height?: string,
11
- className?: string,
12
- style?: React.CSSProperties
13
- }) {
14
- return (
15
- <svg
16
- width={width ?? "100%"} height={height ?? "100%"}
17
- version="1.1"
18
- style={style}
19
- className={className}
20
- viewBox="112.1405 1079.711 306.058 306.058" fill="none" xmlns="http://www.w3.org/2000/svg">
21
- <path fill="#34b6d9" d="M237.01 1087.234a56 56 0 0 1 56.07 0l83.819 48.473a56 56 0 0 1 27.965 48.477v97.108a56 56 0 0 1-27.965 48.477l-83.819 48.473a56 56 0 0 1-56.07 0l-83.818-48.473a56 56 0 0 1-27.965-48.477v-97.108a56 56 0 0 1 27.965-48.477Z"/>
22
- <path fill="#358fd8" d="M264.64 1286.718c27.352 0 49.525 22.173 49.525 49.526 0 27.352-22.173 49.525-49.525 49.525-27.353 0-49.526-22.173-49.526-49.525Z"/>
23
- <path fill="#ff9197" d="M174.941 1131.547c27.352 0 49.526 22.174 49.526 49.526s-22.174 49.526-49.526 49.526-49.526-22.174-49.526-49.526Z"/>
24
- <path fill="#358fd8" d="M355.338 1131.547c27.352 0 49.526 22.174 49.526 49.526s-22.174 49.526-49.526 49.526-49.526-22.174-49.526-49.526Z"/>
25
- <path fill="#fe9197" d="M125.227 1196.44v-14.661c0-13.35 7.55-20.303 17.99-18.168l56.424 31.13 2.72 1.572 27.643 31.545 35.193 30.52q.173 1.522.229 3.013l-54.046-11.395-28.464-26.045Z"/>
26
- <path fill="#013afd" d="M151.207 1328.696c-14.348-8.285-25.98-28.432-25.98-45v-35.214l11.299-.401c.614.866 34.062 48.973 34.606 49.656.394.495 22.156 40.224 34.409 62.328Z"/>
27
- <path fill="#2c09d1" d="m211.38 1249.996 30.436 6.417 9.53 9.1-2.926 15.797 16.939 30.08-14.049 6.672-35.072-10.288-33.83-61.32 9.09-.323Z"/>
28
- <path fill="#2ac1cf" d="M240.774 1380.37a34 34 0 0 1-1.304-.716l-16.141-9.319-49.383-74.238 29.211 7.839Z"/>
29
- <path fill="#2c42d0" d="m173.359 1219.393 9.557 4.558 28.464 26.045-19.883-3.865-12.782.453-31.643-13.936-15.11-11.819Z"/>
30
- <path fill="#8b66ed" d="M257.113 1381.863c-4.336 2.13-10.043 1.783-16.34-1.493l-37.616-76.434 13.081 3.838Z"/>
31
- <path fill="#2c09d1" d="m145.888 1247.749 7.224-.257 23.615 41.804 11.98 1.728-24.421-43.544-.014-.383 10.725-.38 28.16 57.219-29.211-7.839-7.37-11.08Z"/>
32
- <path fill="#2ac1cf" d="M265.451 1311.554v53.1q0 .255-.004.505l-.25-.26-29.148-38.794-6.308-14.37 21.57 6.328 14.048-6.672Z"/>
33
- <path fill="#fd485f" d="m223.329 1370.335-17.788-10.27c-12.253-22.104-34.015-61.833-34.41-62.328-.543-.683-33.991-48.79-34.605-49.656l9.362-.332 20.688 37.269Z"/>
34
- <path fill="#2d42d0" d="m202.362 1196.313 37.108 21.424c13.11 7.57 23.953 25.043 25.727 40.641l-35.193-30.52Z"/>
35
- <path fill="#2b0ad1" d="M265.447 1365.16c-.095 6.58-2.056 11.56-5.304 14.604l-39.936-70.826 9.534 2.797 6.308 14.37 29.148 38.794Z"/>
36
- <path fill="#fe9196" d="M125.227 1240.59v-16.4l21.845 8.458 31.643 13.936-35.367 1.255Z"/>
37
- <path fill="#8b66ed" d="m174.997 1246.716 7.411-.263 33.83 61.32-13.08-3.837Z"/>
38
- <path fill="#2cc5d2" d="m153.112 1247.492 11.16-.395.014.383 24.421 43.544-11.98-1.728Z"/>
39
- <path fill="#fc4962" d="M125.227 1224.19v-8.878l30.211-4.464 17.92 8.545-41.396 1.436 15.11 11.82Z"/>
40
- <path fill="#fe475f" d="M265.451 1292.508v18.84l-.092.043-16.939-30.08 2.927-15.799.214.206Z"/>
41
- <path fill="#2d43cd" d="M125.227 1215.312v-18.871l30.211 14.407Z"/>
42
- <path fill="#2ac4d1" d="M260.143 1379.764a12.5 12.5 0 0 1-3.03 2.099l-40.875-74.09 3.969 1.165Z"/>
43
- <path fill="#fe475f" d="M265.426 1261.391q.025.677.025 1.346v16.241l-13.89-13.26-.186-.36-.028.154-9.53-9.099Z"/>
44
- <path fill="#40b6d9" d="M265.451 1278.978v13.53c-4.95-9.535-12.604-24.31-13.89-26.79Z"/>
45
- <path fill="#013afd" d="M125.227 1248.482v-7.892l18.12 7.249Z"/>
46
- <path fill="#fe9197" d="M143.217 1163.611c2.517.515 5.203 1.558 7.99 3.168l48.434 27.963Z"/>
47
- <path fill="#fec404" d="m251.347 1265.512.028-.154.186.36Z"/>
48
- <path fill="#ccc" d="M265.451 1311.347v.207l-.092-.163Z"/>
49
- <path fill="#2fc7d5" d="M383.274 1164.17a31 31 0 0 1-3.887 2.64l-2.59 1.495-95.242 18.988-50.727-18.022 25.55-32.892 63.642 26.919-61.075-31.394Z"/>
50
- <path fill="#320fdd" d="m215.866 1112.967 18.535-16.15 5.766 32.704 16.212 6.858-25.551 32.892-57.218-19.484Z"/>
51
- <path fill="#fd4a61" d="m305.806 1094.328 73.58 42.482c7.16 4.134 10.748 9.55 10.757 14.968l-40.264-5.624-25.491-7.867-33.1-30.491-18.842-4.065Z"/>
52
- <path fill="#fec504" d="M388.516 1158.077c-1.145 2.145-2.892 4.205-5.242 6.093l-124.33-32.266 6.47-29.689 25.874 5.58 33.1 30.492Z"/>
53
- <path fill="#320fdd" d="m179.744 1183.464-26.935-15.551 18.147-15.813 55.184 23.206-15.732 20.252Z"/>
54
- <path fill="#33b6d9" d="m358.403 1178.925-52.998 30.599-44.794-17.995 89.572-18.117Z"/>
55
- <path fill="#fd4a63" d="m234.401 1096.817 12.723-11.087 19.395 11.42-7.574 34.754 61.075 31.394-79.853-33.777Z"/>
56
- <path fill="#fe9197" d="m152.809 1167.913-1.91-1.103c-10.42-6.016-13.273-14.747-8.558-22.25l56.907-27.791 15.854-3.136Z"/>
57
- <path fill="#8b69f1" d="m305.405 1209.524-14.281 8.245c-5.252 3.032-11.697 4.954-18.462 5.767l-43.574-25.631 31.523-6.376Z"/>
58
- <path fill="#3015d8" d="M252.294 1080.973c13.06-2.81 28.331-1.183 38.83 4.879l14.682 8.476-33.36 9.403-7.031-1.516 1.104-5.064-19.395-11.42Z"/>
59
- <path fill="#2c0ace" d="M239.162 1085.852c3.85-2.223 8.342-3.85 13.132-4.88l-37.192 32.66-15.854 3.137-56.907 27.791c1.777-2.828 4.63-5.482 8.559-7.75Z"/>
60
- <path fill="#2fc7d5" d="m229.088 1197.905-8.773 1.774-9.907-4.121 15.732-20.252 37.462 15.618Z"/>
61
- <path fill="#33b6d9" d="M272.662 1223.536c-11.721 1.407-24.402-.515-33.5-5.767l-28.093-16.22 18.019-3.644Z"/>
62
- <path fill="#fe9197" d="m264.078 1190.828-.476.096-37.462-15.618 4.688-6.035 50.727 18.022ZM170.956 1152.1l2.654-2.313 57.218 19.484-4.688 6.035Z"/>
63
- <path fill="#30c3d9" d="M390.143 1151.778c.01 2.125-.533 4.25-1.627 6.3l-38.637-11.924Z"/>
64
- <path fill="#ff4c60" d="m211.07 1201.55-31.326-18.086 40.57 16.215Z"/>
65
- <path fill="#2d08d0" d="m376.798 1168.305-18.395 10.62-8.22-5.513Z"/>
66
- <path fill="#2fc7d5" d="M264.887 1262.737c0-16.568 11.632-36.715 25.98-45l40.425-23.339 11.932 35.4-25.718 46.274-26.284-2.855-1.382.145-1.411-.146-23.542.675Z"/>
67
- <path fill="#32abd6" d="M383.486 1164.684c2.376-.909 4.642-1.382 6.752-1.446l-7.859 43.045-.292 5.18 8.911 13.519 5.344-41.78 4.102-15.889c2.942 3.164 4.667 8.084 4.667 14.466v91.585h-1.324c-1.104 3.308-34.555 60.887-34.486 61.007l-21.13 12.2 8.305-32.902-10.115 14.693 10.115-20.342 47.315-78.499-7.45 6.694-15.674 18.243 2.62-89.698.155-.059Z"/>
68
- <path fill="#2eabd6" d="m324.54 1360.214-33.672 19.44c-13.695 7.907-24.915 2.15-25.91-12.796l8.385-12.077 47.855-71.354 7.12-26.81 5.119-9.209.57 31.212-13.987 50.442 6.42-5.847-2.408 22.126.459 8.254Z"/>
69
- <path fill="#8b65f0" d="M264.959 1366.858a33 33 0 0 1-.072-2.204v-88.582l24.953-2.71 26.235 2.554 1.43.156 10.813-19.454-7.12 26.81-47.855 71.353Z"/>
70
- <path fill="#fd4861" d="m378.764 1192.394 3.89-5.923c-1.987-.058-4.42 64.146-4.402 65.055.019.91-5.901 22.365-5.901 22.365l-17.658 29.778-14.983 14.696 9.72-45.149.036-1.115 6.455-7.894Z"/>
71
- <path fill="#32abd6" d="m377.832 1167.529.229-.133.703 24.998-22.843 71.813-6.455 7.894.572-17.63-3.443-30.74Z"/>
72
- <path fill="#8c66ef" d="m328.775 1297.488.034-.126 20.657-25.261-.036 1.115-9.72 45.15 14.983-14.697-13.8 22.045-16.86 19.627 2.407-22.126-6.42 5.847Z"/>
73
- <path fill="#2c08d3" d="m331.292 1194.398 27.203-15.705 5.51 13.714-20.781 37.391Z"/>
74
- <path fill="#300bd2" d="m324.491 1353.595-.459-8.254 16.861-19.627 13.8-22.045 17.658-29.778 20.08-31.948 3.91-5.728 7.45-6.694-47.315 78.5-10.115 20.341-21.821 31.852Z"/>
75
- <path fill="#2c08d3" d="m333.437 1247.408 13.158-23.676 3.443 30.738-4.056 14.678-14.316 17.914 2.34-8.442Z"/>
76
- <path fill="#8b68ef" d="M405.111 1273.364v10.332c0 16.568-11.632 36.715-25.98 45l-9.83 5.675c-.07-.12 33.382-57.7 34.486-61.007Z"/>
77
- <path fill="#fec504" d="M390.238 1163.238c4.109-.125 7.625 1.3 10.206 4.075l-4.102 15.89-5.344 41.779-8.91-13.518.291-5.18Z"/>
78
- <path fill="#300bd2" d="m348.171 1346.57-23.631 13.644 31.936-46.545Z"/>
79
- <path fill="#348fd8" d="M372.35 1273.891s5.921-21.455 5.902-22.365 2.415-65.113 4.402-65.055l-1.987 67.987 15.675-18.243-3.91 5.728Z"/>
80
- <path fill="#32abd6" d="m358.495 1178.693 19.337-11.164-13.827 24.878Z"/>
81
- <path fill="#fd4861" d="m331.391 1288.05.275-.988 14.316-17.914 4.056-14.678-.572 17.63-20.657 25.262Z"/>
82
- <path fill="#ccc" fillOpacity=".579" d="m378.06 1167.396 1.07-.617a31 31 0 0 1 4.158-2.019l-.634 21.71-3.89 5.924Z"/>
83
- <path fill="#2fc7d5" d="M264.887 1276.072v-2.18l23.542-.676 1.411.146Z"/>
84
- <path fill="#8b65f0" d="m291.193 1273.502-1.353-.14 1.382-.145 24.853 2.7Z"/>
85
- </svg>
86
- );
87
-
88
- }
@@ -1,102 +0,0 @@
1
- import React, { createContext, useCallback, useContext, useMemo, useState } from "react";
2
- import { Alert, Typography } from "@rebasepro/ui";
3
-
4
- // ── Schema Drift Context ────────────────────────────────────────────────
5
-
6
- interface SchemaDriftContextValue {
7
- /** Report a schema drift error (call from any data-loading hook). */
8
- reportSchemaDrift: (message: string) => void;
9
- /** The most recent schema drift message, or null. */
10
- schemaDriftMessage: string | null;
11
- /** Dismiss the banner for this session. */
12
- dismiss: () => void;
13
- }
14
-
15
- const SchemaDriftContext = createContext<SchemaDriftContextValue>({
16
- reportSchemaDrift: () => {},
17
- schemaDriftMessage: null,
18
- dismiss: () => {}
19
- });
20
-
21
- export function useSchemaDriftContext(): SchemaDriftContextValue {
22
- return useContext(SchemaDriftContext);
23
- }
24
-
25
- /**
26
- * Detects schema drift from an error object.
27
- * Checks both the error code (from `RebaseApiError`) and the message
28
- * for schema drift indicators.
29
- */
30
- export function isSchemaDriftError(error: unknown): boolean {
31
- if (!error || typeof error !== "object") return false;
32
- // RebaseApiError from the SDK has a `code` property
33
- if ("code" in error && (error as { code?: string }).code === "SCHEMA_DRIFT") {
34
- return true;
35
- }
36
- // Fallback: check the message for the telltale phrase
37
- if (error instanceof Error && error.message.includes("Schema drift:")) {
38
- return true;
39
- }
40
- return false;
41
- }
42
-
43
- // ── Provider ─────────────────────────────────────────────────────────────
44
-
45
- export function SchemaDriftProvider({ children }: { children: React.ReactNode }) {
46
- const [schemaDriftMessage, setSchemaDriftMessage] = useState<string | null>(null);
47
- const [dismissed, setDismissed] = useState(false);
48
-
49
- const reportSchemaDrift = useCallback((message: string) => {
50
- setSchemaDriftMessage(prev => prev ?? message);
51
- }, []);
52
-
53
- const dismiss = useCallback(() => {
54
- setDismissed(true);
55
- }, []);
56
-
57
- const value = useMemo<SchemaDriftContextValue>(() => ({
58
- reportSchemaDrift,
59
- schemaDriftMessage: dismissed ? null : schemaDriftMessage,
60
- dismiss
61
- }), [reportSchemaDrift, schemaDriftMessage, dismissed, dismiss]);
62
-
63
- return (
64
- <SchemaDriftContext.Provider value={value}>
65
- {children}
66
- </SchemaDriftContext.Provider>
67
- );
68
- }
69
-
70
- // ── Banner Component ─────────────────────────────────────────────────────
71
-
72
- export interface SchemaDriftBannerProps {
73
- className?: string;
74
- }
75
-
76
- /**
77
- * Persistent banner shown when a schema drift error is detected.
78
- */
79
- export function SchemaDriftBanner({ className }: SchemaDriftBannerProps) {
80
- const { schemaDriftMessage, dismiss } = useSchemaDriftContext();
81
-
82
- if (!schemaDriftMessage) return null;
83
-
84
- return (
85
- <Alert
86
- color="warning"
87
- size="small"
88
- onDismiss={dismiss}
89
- className={className}
90
- >
91
- <div className="flex flex-col gap-1">
92
- <Typography variant="label" className="text-amber-800 dark:text-amber-200">
93
- Schema drift detected
94
- </Typography>
95
- <Typography variant="body2" className="text-amber-700 dark:text-amber-300">
96
- {schemaDriftMessage}{" "}
97
- Run <code className="bg-amber-200 dark:bg-amber-800 px-1 rounded text-xs">pnpm db:push</code> in your backend terminal to sync.
98
- </Typography>
99
- </div>
100
- </Alert>
101
- );
102
- }
@@ -1,46 +0,0 @@
1
- import React from "react";
2
- import { Button, Dialog, DialogActions, DialogContent, DialogTitle, Typography } from "@rebasepro/ui";
3
- import { useTranslation } from "../hooks/useTranslation";
4
-
5
- export interface UnsavedChangesDialogProps {
6
- open: boolean;
7
- body?: React.ReactNode;
8
- title?: string;
9
- handleOk: () => void;
10
- handleCancel: () => void;
11
- }
12
-
13
- export function UnsavedChangesDialog({
14
- open,
15
- handleOk,
16
- handleCancel,
17
- body,
18
- title
19
- }: UnsavedChangesDialogProps) {
20
-
21
- const { t } = useTranslation();
22
-
23
- return (
24
- <Dialog
25
- onEscapeKeyDown={() => {
26
- handleCancel();
27
- }}
28
- open={open}
29
- >
30
- <DialogTitle variant={"h6"}>{title}</DialogTitle>
31
- <DialogContent>
32
-
33
- <Typography>
34
- {body ?? t("unsaved_changes")}
35
- </Typography>
36
-
37
- </DialogContent>
38
- <DialogActions>
39
- <Button variant="text"
40
- onClick={handleCancel} autoFocus> {t("cancel")} </Button>
41
- <Button
42
- onClick={handleOk}> {t("ok")} </Button>
43
- </DialogActions>
44
- </Dialog>
45
- );
46
- }
@@ -1,54 +0,0 @@
1
- import { CircleUserIcon, cls, defaultBorderMixin } from "@rebasepro/ui";
2
- import { User } from "@rebasepro/types";
3
-
4
- /**
5
- * Component to render a single user with name and email
6
- */
7
- export function UserDisplay({
8
- user
9
- }: { user: User | null }) {
10
- if (!user) {
11
- return <span className={cls("italic", "text-text-disabled dark:text-text-disabled-dark", "text-sm")}>Not set</span>;
12
- }
13
-
14
- const avatarSizeClass = "w-6 h-6";
15
-
16
- return (
17
- <div className={cls(
18
- "inline-flex items-center gap-4 px-2 py-1 rounded-xl text-left max-w-full overflow-hidden",
19
- "bg-surface-accent-100 dark:bg-surface-accent-800",
20
- "border",
21
- defaultBorderMixin
22
- )}>
23
- {user.photoURL ? (
24
- <img
25
- src={user.photoURL}
26
- alt={user.displayName || user.email || "User"}
27
- className={cls(
28
- "rounded-full object-cover",
29
- avatarSizeClass
30
- )}
31
- />
32
- ) : (
33
- <CircleUserIcon
34
- className={cls(
35
- "text-text-secondary dark:text-text-secondary-dark",
36
- avatarSizeClass
37
- )}
38
- />
39
- )}
40
- <div className="flex flex-col min-w-0">
41
- <span className={cls("font-regular truncate", "text-sm")}>
42
- {user.displayName || user.email || "-"}
43
- </span>
44
- {user.displayName && user.email && (
45
- <span className={cls("text-text-secondary dark:text-text-secondary-dark truncate",
46
- "text-xs"
47
- )}>
48
- {user.email}
49
- </span>
50
- )}
51
- </div>
52
- </div>
53
- );
54
- }