@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,11 +0,0 @@
1
- import { StorageSource } from "@rebasepro/types";
2
- import { StorageSourceContext } from "../contexts/StorageSourceContext";
3
- import { useContext } from "react";
4
-
5
- /**
6
- * Use this hook to get the storage source being used
7
- * @group Hooks and utilities
8
- */
9
- export const useStorageSource = (): StorageSource => {
10
- return useContext(StorageSourceContext);
11
- };
@@ -1,258 +0,0 @@
1
- import React, { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
2
- import type {
3
- CollectionRegistryController
4
- } from "@rebasepro/types";
5
- import type {
6
- SidePanelController,
7
- UrlController,
8
- NavigationStateController,
9
- BreadcrumbEntry,
10
- BreadcrumbsController
11
- } from "@rebasepro/cms-types";
12
-
13
- export type { BreadcrumbEntry, BreadcrumbsController };
14
-
15
- // ─── Breadcrumbs ──────────────────────────────────────────────────
16
-
17
-
18
- // ─── Bridge interface ───────────────────────────────────────────────
19
-
20
- /**
21
- * StudioBridge provides optional admin capabilities to Studio components.
22
- * When the admin is present, a bridge provider injects real implementations.
23
- * When the admin is absent, noop defaults ensure Studio works standalone.
24
- */
25
- export interface StudioBridge {
26
- collectionRegistry: CollectionRegistryController;
27
- sidePanelController: SidePanelController;
28
- urlController: UrlController;
29
- navigationState: NavigationStateController;
30
- breadcrumbs: BreadcrumbsController;
31
- capabilities: StudioCapabilities;
32
- }
33
-
34
- /**
35
- * What the *host* of these tools can do, as opposed to what the backend can.
36
- *
37
- * Studio is mounted in two very different places. In a project's own admin
38
- * panel it runs next to the collection source files and can edit them through
39
- * the schema-editor routes. In the hosted console it runs against somebody
40
- * else's deployed container: there is no source to edit — the container is
41
- * rebuilt from the customer's repository on every deploy — and the routes that
42
- * would edit it are not mounted at all, because the framework switches the
43
- * schema editor off under `NODE_ENV=production`.
44
- *
45
- * Tools that would otherwise offer a write into the codebase read this to
46
- * decide whether that write is even meaningful.
47
- */
48
- export interface StudioCapabilities {
49
- /**
50
- * Whether the host has the project's collection source at hand and can
51
- * write to it.
52
- *
53
- * Defaults to `true`, which is what an admin panel running beside its own
54
- * `collectionsDir` has always assumed.
55
- */
56
- codebase: boolean;
57
- }
58
-
59
- // ─── Noop defaults ──────────────────────────────────────────────────
60
-
61
- const NOOP_COLLECTION_REGISTRY: CollectionRegistryController = {
62
- getCollection: () => undefined,
63
- getRawCollection: () => undefined,
64
- getParentReferencesFromPath: () => [],
65
- getParentCollectionSlugs: () => [],
66
- getParentEntityIds: () => [],
67
- convertIdsToPaths: () => [],
68
- initialised: false
69
- };
70
-
71
- const NOOP_SIDE_PANEL: SidePanelController = {
72
- open: () => {},
73
- replace: () => {},
74
- close: () => {}
75
- };
76
-
77
- const NOOP_URL_CONTROLLER: UrlController = {
78
- basePath: "/",
79
- baseCollectionPath: "/c",
80
- urlPathToDataPath: () => "",
81
- homeUrl: "/",
82
- isUrlCollectionPath: () => false,
83
- buildUrlCollectionPath: () => "",
84
- buildAppUrlPath: () => "",
85
- resolveDatabasePathsFrom: () => "",
86
- navigate: () => {}
87
- };
88
-
89
- const NOOP_NAVIGATION_STATE: NavigationStateController = {
90
- loading: false,
91
- refreshNavigation: () => {}
92
- };
93
-
94
- const NOOP_BREADCRUMBS: BreadcrumbsController = {
95
- breadcrumbs: [],
96
- set: () => {}
97
- };
98
-
99
- const DEFAULT_CAPABILITIES: StudioCapabilities = {
100
- codebase: true
101
- };
102
-
103
- const NOOP_BRIDGE: StudioBridge = {
104
- collectionRegistry: NOOP_COLLECTION_REGISTRY,
105
- sidePanelController: NOOP_SIDE_PANEL,
106
- urlController: NOOP_URL_CONTROLLER,
107
- navigationState: NOOP_NAVIGATION_STATE,
108
- breadcrumbs: NOOP_BREADCRUMBS,
109
- capabilities: DEFAULT_CAPABILITIES
110
- };
111
-
112
- // ─── Context & Provider ─────────────────────────────────────────────
113
-
114
- export const StudioBridgeContext = createContext<StudioBridge>(NOOP_BRIDGE);
115
-
116
- /**
117
- * Provider that injects admin capabilities into Studio.
118
- * Accepts partial overrides — any field not provided falls back to noop.
119
- *
120
- * Usage (in app wiring, when the admin is present):
121
- * ```tsx
122
- * <StudioBridgeProvider value={{
123
- * collectionRegistry: useCollectionRegistryController(),
124
- * sidePanelController: useSidePanel(),
125
- * urlController: useUrlController(),
126
- * navigationState: useNavigationStateController(),
127
- * breadcrumbs: useBreadcrumbsController(),
128
- * }}>
129
- * <RebaseStudio ... />
130
- * </StudioBridgeProvider>
131
- * ```
132
- */
133
- export function StudioBridgeProvider({
134
- value,
135
- children
136
- }: {
137
- value: Partial<StudioBridge>;
138
- children: React.ReactNode;
139
- }) {
140
- // Keyed on the slices rather than on `value`: callers write the object
141
- // inline (`value={{ collectionRegistry }}`), so a `[value]` dependency
142
- // rebuilt the context on every render of the host and re-rendered every
143
- // Studio consumer with it.
144
- const merged = React.useMemo(
145
- () => ({ ...NOOP_BRIDGE,
146
- ...value }),
147
- // eslint-disable-next-line react-hooks/exhaustive-deps
148
- [
149
- value.collectionRegistry,
150
- value.sidePanelController,
151
- value.urlController,
152
- value.navigationState,
153
- value.breadcrumbs,
154
- value.capabilities
155
- ]
156
- );
157
- return (
158
- <StudioBridgeContext.Provider value={merged}>
159
- {children}
160
- </StudioBridgeContext.Provider>
161
- );
162
- }
163
-
164
- // ─── Convenience hooks ──────────────────────────────────────────────
165
-
166
- /** Collection registry — returns noop if the admin is not present. */
167
- export function useStudioCollectionRegistry(): CollectionRegistryController {
168
- return useContext(StudioBridgeContext).collectionRegistry;
169
- }
170
-
171
- /** Side panel controller — returns noop if the admin is not present. */
172
- export function useStudioSidePanelController(): SidePanelController {
173
- return useContext(StudioBridgeContext).sidePanelController;
174
- }
175
-
176
- /** URL controller — returns noop if the admin is not present. */
177
- export function useStudioUrlController(): UrlController {
178
- return useContext(StudioBridgeContext).urlController;
179
- }
180
-
181
- /** Navigation state — returns noop if the admin is not present. */
182
- export function useStudioNavigationState(): NavigationStateController {
183
- return useContext(StudioBridgeContext).navigationState;
184
- }
185
-
186
- /** Breadcrumbs controller — returns noop if the admin is not present. */
187
- export function useStudioBreadcrumbs(): BreadcrumbsController {
188
- return useContext(StudioBridgeContext).breadcrumbs;
189
- }
190
-
191
- /** What the host can do — see {@link StudioCapabilities}. */
192
- export function useStudioCapabilities(): StudioCapabilities {
193
- return useContext(StudioBridgeContext).capabilities;
194
- }
195
-
196
- // ─── Self-Assembling Bridge Registry ────────────────────────────────
197
-
198
- /**
199
- * Registry that controllers use to self-register their implementations
200
- * into the Studio bridge. Each controller calls `register(key, value)`
201
- * on mount and `unregister(key)` on unmount.
202
- */
203
- export interface StudioBridgeRegistry {
204
- register: <K extends keyof StudioBridge>(key: K, value: StudioBridge[K]) => void;
205
- unregister: (key: keyof StudioBridge) => void;
206
- }
207
-
208
- export const StudioBridgeRegistryContext = createContext<StudioBridgeRegistry | null>(null);
209
-
210
- /**
211
- * Provider that creates a self-assembling bridge.
212
- *
213
- * Mount this above the controller providers. Each controller calls
214
- * `useBridgeRegistration(key, value)` to inject its implementation.
215
- * The bridge context value is automatically kept in sync.
216
- *
217
- * ```tsx
218
- * <StudioBridgeRegistryProvider>
219
- * <CollectionRegistryProvider> // auto-registers
220
- * <SidePanelProvider> // auto-registers
221
- * <UrlProvider> // auto-registers
222
- * <RebaseStudio /> // consumes bridge
223
- * </UrlProvider>
224
- * </SidePanelProvider>
225
- * </CollectionRegistryProvider>
226
- * </StudioBridgeRegistryProvider>
227
- * ```
228
- */
229
- export function StudioBridgeRegistryProvider({ children }: { children: React.ReactNode }) {
230
- const [version, setVersion] = useState(0);
231
- const slicesRef = useRef<Partial<StudioBridge>>({});
232
-
233
- const register = useCallback(<K extends keyof StudioBridge>(key: K, value: StudioBridge[K]) => {
234
- slicesRef.current[key] = value;
235
- setVersion(v => v + 1);
236
- }, []);
237
-
238
- const unregister = useCallback((key: keyof StudioBridge) => {
239
- delete slicesRef.current[key];
240
- setVersion(v => v + 1);
241
- }, []);
242
-
243
- const registry = useMemo<StudioBridgeRegistry>(() => ({ register,
244
- unregister }), [register, unregister]);
245
-
246
- const bridgeValue = useMemo<StudioBridge>(() => ({
247
- ...NOOP_BRIDGE,
248
- ...slicesRef.current
249
- }), [version]);
250
-
251
- return (
252
- <StudioBridgeRegistryContext.Provider value={registry}>
253
- <StudioBridgeContext.Provider value={bridgeValue}>
254
- {children}
255
- </StudioBridgeContext.Provider>
256
- </StudioBridgeRegistryContext.Provider>
257
- );
258
- }
@@ -1,38 +0,0 @@
1
- import { useTranslation as useI18nTranslation } from "react-i18next";
2
- import { useCallback, useMemo } from "react";
3
-
4
- const REBASE_NS = "rebase_core";
5
-
6
- /**
7
- * Internal hook for translating Rebase UI strings.
8
- *
9
- * Uses the `rebase_core` i18next namespace that is initialised by
10
- * `RebaseI18nProvider`. Do NOT use `react-i18next` directly in internal
11
- * components — always go through this hook so the namespace is consistent.
12
- *
13
- * @example
14
- * const { t } = useTranslation();
15
- * <Button>{t("save")}</Button>
16
- *
17
- * @internal
18
- */
19
- export function useTranslation() {
20
- const { t, i18n } = useI18nTranslation(REBASE_NS);
21
-
22
- /**
23
- * Typed translation function scoped to RebaseTranslations keys.
24
- * Also supports i18next interpolation variables, e.g.
25
- * t("add_to_field", { fieldName: "Tags" })
26
- * t("error_deleting", { message: err.message })
27
- * t("sort_key_position", { position: 2 })
28
- *
29
- * Numbers are accepted as well as strings: i18next interpolates them
30
- * either way, and a signature that took only strings pushed a `String()`
31
- * onto every call site with a count in it — `{{count}}`, `{{position}}`.
32
- */
33
- const typedT = useCallback((key: string, vars?: Record<string, string | number>): string =>
34
- t(key, vars) as string, [t]);
35
-
36
- return useMemo(() => ({ t: typedT,
37
- i18n }), [typedT, i18n]);
38
- }
@@ -1,67 +0,0 @@
1
- import { useCallback, useEffect, useState, useMemo } from "react";
2
- import { UnsavedChangesDialogProps } from "../components/UnsavedChangesDialog";
3
- import { useNavigationBlocker } from "./useNavigationBlocker";
4
-
5
- /**
6
- * A single, unified hook to prevent navigation when there are unsaved changes.
7
- *
8
- * It automatically handles:
9
- * 1. Internal React Router navigation using `useBlocker`.
10
- * 2. External browser navigation (page refresh, tab close) using `beforeunload`.
11
- */
12
- export function useUnsavedChangesDialog(
13
- when: boolean,
14
- onOk: () => void
15
- ): {
16
- dialogProps: UnsavedChangesDialogProps;
17
- triggerDialog: () => void;
18
- } {
19
- const [manualDialogOpen, setManualDialogOpen] = useState(false);
20
-
21
- const blocker = useNavigationBlocker(
22
- useCallback(
23
- ({ currentLocation, nextLocation }) =>
24
- when && currentLocation.pathname !== nextLocation.pathname,
25
- [when]
26
- )
27
- );
28
-
29
- useEffect(() => {
30
- if (!when) return;
31
-
32
- const handleBeforeUnload = (e: BeforeUnloadEvent) => {
33
- e.preventDefault();
34
- e.returnValue = "";
35
- };
36
-
37
- window.addEventListener("beforeunload", handleBeforeUnload);
38
- return () => window.removeEventListener("beforeunload", handleBeforeUnload);
39
- }, [when]);
40
-
41
- const handleOk = useCallback(() => {
42
- onOk();
43
- if (blocker.state === "blocked") {
44
- blocker.proceed();
45
- }
46
- setManualDialogOpen(false);
47
- }, [blocker, onOk]);
48
-
49
- const handleCancel = useCallback(() => {
50
- if (blocker.state === "blocked") {
51
- blocker.reset();
52
- }
53
- setManualDialogOpen(false);
54
- }, [blocker]);
55
-
56
- const triggerDialog = useCallback(() => setManualDialogOpen(true), []);
57
-
58
- return useMemo(() => ({
59
- dialogProps: {
60
- open: manualDialogOpen || blocker.state === "blocked",
61
- handleOk,
62
- handleCancel,
63
- body: "There are unsaved changes in this collection"
64
- },
65
- triggerDialog
66
- }), [manualDialogOpen, blocker.state, handleOk, handleCancel, triggerDialog]);
67
- }
@@ -1,11 +0,0 @@
1
- import { UserConfigurationPersistence } from "@rebasepro/cms-types";
2
- import { useContext } from "react";
3
- import { UserConfigurationPersistenceContext } from "../contexts/UserConfigurationPersistenceContext";
4
-
5
- /**
6
- * Use this controller to access the configuration that is stored externally,
7
- * and not defined in code
8
- *
9
- * @group Hooks and utilities
10
- */
11
- export const useUserConfigurationPersistence = (): UserConfigurationPersistence | undefined => useContext(UserConfigurationPersistenceContext);
@@ -1,159 +0,0 @@
1
- import React, { PropsWithChildren, useEffect, useRef } from "react";
2
- import i18next, { i18n } from "i18next";
3
- import { I18nextProvider, initReactI18next } from "react-i18next";
4
- import { en } from "../locales/en";
5
- import { es } from "../locales/es";
6
- import { de } from "../locales/de";
7
- import { fr } from "../locales/fr";
8
- import { it } from "../locales/it";
9
- import { hi } from "../locales/hi";
10
- import { pt } from "../locales/pt";
11
- import { RebaseTranslations } from "@rebasepro/cms-types";
12
- import { readStoredString, writeStoredString } from "../util/local_storage";
13
-
14
- const REBASE_NS = "rebase_core";
15
-
16
- export const REBASE_LOCALE_STORAGE_KEY = "rebase_locale";
17
-
18
- /** DeepPartial helper — allows partial overrides at any nesting level */
19
- type DeepPartial<T> = T extends object
20
- ? { [K in keyof T]?: DeepPartial<T[K]> }
21
- : T;
22
-
23
- export interface RebaseI18nProviderProps {
24
- /** BCP-47 locale tag, e.g. "en", "es", "fr". Defaults to "en". */
25
- locale?: string;
26
- /**
27
- * Override or extend any Rebase UI string, keyed by locale.
28
- *
29
- * @example
30
- * translations={{
31
- * en: { save: "Publish" },
32
- * es: { save: "Publicar", discard: "Descartar" }
33
- * }}
34
- */
35
- translations?: {
36
- [locale: string]: DeepPartial<RebaseTranslations>;
37
- };
38
- }
39
-
40
- /**
41
- * Initialises a dedicated i18next instance for Rebase's internal UI strings.
42
- *
43
- * This instance is isolated from any app-level i18next configuration the
44
- * consumer may have. Mount this at the top of the Rebase component tree.
45
- *
46
- * @internal
47
- */
48
- export function RebaseI18nProvider({
49
- locale = "en",
50
- translations,
51
- children
52
- }: PropsWithChildren<RebaseI18nProviderProps>) {
53
- const i18nRef = useRef<i18n | null>(null);
54
- const [ready, setReady] = React.useState(false);
55
-
56
- if (!i18nRef.current) {
57
- const instance = i18next.createInstance();
58
-
59
- // Build the initial resources: English baseline + any consumer overrides
60
- const resources = buildResources(translations);
61
-
62
- let initialLocale = locale;
63
- const stored = readStoredString(REBASE_LOCALE_STORAGE_KEY);
64
- if (stored) initialLocale = stored;
65
-
66
- instance
67
- .use(initReactI18next)
68
- .init({
69
- lng: initialLocale,
70
- fallbackLng: "en",
71
- ns: [REBASE_NS],
72
- defaultNS: REBASE_NS,
73
- resources,
74
- interpolation: {
75
- // React already escapes — don't double-escape
76
- escapeValue: false
77
- }
78
- }, () => {
79
- setReady(true);
80
- });
81
-
82
- instance.on("languageChanged", (lng) => {
83
- if (typeof window !== "undefined") {
84
- writeStoredString(REBASE_LOCALE_STORAGE_KEY, lng);
85
- }
86
- });
87
-
88
- i18nRef.current = instance;
89
- }
90
-
91
- // When `locale` prop changes, switch language on the existing instance
92
- // ONLY if the user hasn't explicitly set a preference
93
- useEffect(() => {
94
- if (i18nRef.current && i18nRef.current.language !== locale) {
95
- const hasUserPreference = Boolean(readStoredString(REBASE_LOCALE_STORAGE_KEY));
96
- if (!hasUserPreference) {
97
- i18nRef.current.changeLanguage(locale);
98
- }
99
- }
100
- }, [locale]);
101
-
102
- // When consumer translations prop changes, update the resource bundles
103
- useEffect(() => {
104
- if (!i18nRef.current) return;
105
- const resources = buildResources(translations);
106
- for (const [lang, bundle] of Object.entries(resources)) {
107
- i18nRef.current.addResourceBundle(
108
- lang,
109
- REBASE_NS,
110
- bundle[REBASE_NS],
111
- true, // deep merge
112
- true // overwrite existing keys
113
- );
114
- }
115
- }, [translations]);
116
-
117
- if (!ready || !i18nRef.current) return null;
118
-
119
- return (
120
- <I18nextProvider i18n={i18nRef.current}>
121
- {children}
122
- </I18nextProvider>
123
- );
124
- }
125
-
126
- /**
127
- * Build an i18next resources object from the English baseline plus any
128
- * consumer-provided overrides.
129
- */
130
- function buildResources(
131
- translations?: { [locale: string]: DeepPartial<RebaseTranslations> }
132
- ): Record<string, Record<string, object>> {
133
- const resources: Record<string, Record<string, object>> = {
134
- en: { [REBASE_NS]: { ...en } },
135
- es: { [REBASE_NS]: { ...es } },
136
- de: { [REBASE_NS]: { ...de } },
137
- fr: { [REBASE_NS]: { ...fr } },
138
- it: { [REBASE_NS]: { ...it } },
139
- hi: { [REBASE_NS]: { ...hi } },
140
- pt: { [REBASE_NS]: { ...pt } }
141
- };
142
-
143
- if (!translations) return resources;
144
-
145
- for (const [lang, overrides] of Object.entries(translations)) {
146
- if (!resources[lang]) {
147
- // For non-English/Spanish locales, start from English as the fallback base
148
- resources[lang] = { [REBASE_NS]: { ...en } };
149
- }
150
- // Merge consumer overrides (shallow merge is enough since translations
151
- // is a flat record — deepMerge option in addResourceBundle handles deeper)
152
- resources[lang][REBASE_NS] = {
153
- ...resources[lang][REBASE_NS],
154
- ...overrides
155
- };
156
- }
157
-
158
- return resources;
159
- }
package/src/index.ts DELETED
@@ -1,32 +0,0 @@
1
- export * from "./core";
2
- export * from "./hooks";
3
- export * from "./auth";
4
- export * from "./components";
5
- export * from "./util";
6
- export * from "./contexts";
7
-
8
- // @internal — framework implementation details, exported only because
9
- // @rebasepro/cms and @rebasepro/studio consume them. Named explicitly
10
- // (not `export *`) so this file is the single place that grows or shrinks
11
- // the internal surface — see the JSDoc on each symbol for details.
12
- export { CONTAINER_FULL_WIDTH, FORM_CONTAINER_WIDTH, SIDE_PANEL_DEFAULT_WIDTH } from "./internal/common";
13
- export { useRestoreScroll } from "./internal/useRestoreScroll";
14
- export { useUnsavedChangesDialog } from "./hooks/useUnsavedChangesDialog";
15
- export { NavigationBlockerProvider, useNavigationBlocker } from "./hooks/useNavigationBlocker";
16
- export type { UnsavedChangesDialogProps } from "./components/UnsavedChangesDialog";
17
- // The element type of the `storageSources` prop on `<Rebase>`. Anyone registering a
18
- // direct-transport backend writes this shape by hand, and the docs have always told
19
- // them to import it from here — it was simply never exported. Type-only, so it adds
20
- // nothing to the bundle.
21
- export type { RebaseStorageSource } from "./core/RebaseProps";
22
- export { UnsavedChangesDialog } from "./components/UnsavedChangesDialog";
23
- export * from "./i18n/RebaseI18nProvider";
24
- export * from "./locales/en";
25
- export * from "./locales/es";
26
-
27
- // Studio Bridge — shared context for optional admin↔Studio integration
28
- export * from "./hooks/useStudioBridge";
29
-
30
- // Self-assembling bridge registration hook
31
- export { useBridgeRegistration } from "./hooks/useBridgeRegistration";
32
- export * from "./collections";
@@ -1,28 +0,0 @@
1
- /**
2
- * Layout width primitives used by the framework's own side-panel and form
3
- * dialog sizing logic.
4
- *
5
- * @internal Not part of the stable public API — exported only because
6
- * `@rebasepro/cms` and `@rebasepro/studio` need them to compute the same
7
- * dialog widths as the framework. Do not depend on these for app code; they
8
- * may change shape or be removed without a major version bump.
9
- */
10
- export const CONTAINER_FULL_WIDTH = "100vw";
11
-
12
- /** @internal See {@link CONTAINER_FULL_WIDTH}. */
13
- export const FORM_CONTAINER_WIDTH = "768px";
14
-
15
- /**
16
- * How wide the side panel opens when neither the caller nor the collection
17
- * says otherwise.
18
- *
19
- * Sized from what it has to hold rather than from a round number: the form's
20
- * content column plus its metadata rail plus gutters, which is also the width
21
- * at which the form stops being a single stack and picks up the same
22
- * two-column layout it has in full screen. Capped against the viewport so a
23
- * panel never becomes the whole window on a laptop — at that point you want
24
- * full screen, and there is a button for it.
25
- *
26
- * @internal See {@link CONTAINER_FULL_WIDTH}.
27
- */
28
- export const SIDE_PANEL_DEFAULT_WIDTH = "min(1160px, 88vw)";
@@ -1,69 +0,0 @@
1
- import React, { useCallback, useEffect, useRef } from "react";
2
- import { useLocation } from "react-router";
3
-
4
- const scrollsMap: Record<string, number> = {};
5
-
6
- /**
7
- * Restores per-route scroll position on a scrollable container, keyed by
8
- * router location. Used by the framework's own home page implementations.
9
- *
10
- * @internal Not part of the stable public API — exported only because
11
- * `@rebasepro/cms` and `@rebasepro/studio` reuse it in their home page
12
- * components. Its behavior (module-level scroll cache, router coupling) is
13
- * an implementation detail and may change without a major version bump.
14
- */
15
- export function useRestoreScroll() {
16
-
17
- const location = useLocation();
18
-
19
- const containerRef = useRef<HTMLDivElement>(null);
20
- const [scroll, setScroll] = React.useState(0);
21
- const [direction, setDirection] = React.useState<"up" | "down">("down");
22
-
23
- // Use ref to track previous scroll for direction calculation
24
- // This avoids recreating handleScroll on every scroll
25
- const prevScrollRef = useRef(0);
26
-
27
- const handleScroll = useCallback(() => {
28
- if (!containerRef.current || !location.key) return;
29
- const scrollTop = containerRef.current.scrollTop;
30
- scrollsMap[location.key] = scrollTop;
31
- setScroll(scrollTop);
32
- setDirection(scrollTop > prevScrollRef.current ? "down" : "up");
33
- prevScrollRef.current = scrollTop;
34
- }, [location.key]);
35
-
36
- useEffect(() => {
37
- const container = containerRef.current;
38
- if (!container) return;
39
- container.addEventListener("scroll", handleScroll, { passive: true });
40
-
41
- return () => {
42
- if (container)
43
- container.removeEventListener("scroll", handleScroll);
44
- };
45
- }, [handleScroll]);
46
-
47
- // Defer scroll restoration to next tick to allow async content to render
48
- // This is necessary because DefaultHomePage content loads asynchronously
49
- useEffect(() => {
50
- const savedScroll = scrollsMap[location.key];
51
- if (!containerRef.current || !savedScroll) return;
52
-
53
- const timeoutId = setTimeout(() => {
54
- if (!containerRef.current) return;
55
- containerRef.current.scrollTo({
56
- top: savedScroll,
57
- behavior: "auto"
58
- });
59
- }, 0);
60
-
61
- return () => clearTimeout(timeoutId);
62
- }, [location.key]);
63
-
64
- return {
65
- containerRef,
66
- scroll,
67
- direction
68
- };
69
- }