@rebasepro/admin 0.11.0 → 0.11.1-canary.g8caabf3
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.
- package/README.md +1 -1
- package/dist/{CollectionEditorDialog-o7F_zbGY.js → CollectionEditorDialog-id__fOqM.js} +4 -4
- package/dist/CollectionEditorDialog-id__fOqM.js.map +1 -0
- package/dist/{PropertyEditView-DgB2b22q.js → PropertyEditView-BLPT_e-N.js} +2 -2
- package/dist/{PropertyEditView-DgB2b22q.js.map → PropertyEditView-BLPT_e-N.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-DaLRgPkj.js → RouterCollectionsStudioView-DwkGdgyN.js} +4 -4
- package/dist/{RouterCollectionsStudioView-DaLRgPkj.js.map → RouterCollectionsStudioView-DwkGdgyN.js.map} +1 -1
- package/dist/collection_editor/CollectionEditorDialogsContext.d.ts +1 -1
- package/dist/collection_editor/_cms_internals.d.ts +1 -1
- package/dist/collection_editor/extensibility_types.d.ts +1 -1
- package/dist/collection_editor_ui.js +4 -4
- package/dist/components/CollectionEditorDialogs.d.ts +2 -2
- package/dist/components/CollectionViewBinding/CollectionListViewBinding.d.ts +2 -2
- package/dist/components/DefaultDrawer.d.ts +3 -3
- package/dist/components/DrawerNavigationGroup.d.ts +8 -1
- package/dist/components/DrawerNavigationItem.d.ts +7 -1
- package/dist/components/EditViewBinding.d.ts +1 -1
- package/dist/components/RebaseAdmin.d.ts +1 -1
- package/dist/components/RebaseAuthGate.d.ts +1 -1
- package/dist/components/RebaseLayout.d.ts +5 -1
- package/dist/components/RebaseNavigation.d.ts +2 -2
- package/dist/components/RebaseRouteDefs.d.ts +1 -1
- package/dist/components/RebaseShell.d.ts +6 -1
- package/dist/components/SidePanelProvider.d.ts +2 -2
- package/dist/components/app/Scaffold.d.ts +11 -0
- package/dist/{export-BvqhjdEb.js → export-lZhpezjk.js} +3 -3
- package/dist/export-lZhpezjk.js.map +1 -0
- package/dist/form/EntityForm.d.ts +2 -2
- package/dist/form/EntityFormBinding.d.ts +5 -5
- package/dist/{history-Dz20hH38.js → history-DkP1tce0.js} +2 -2
- package/dist/{history-Dz20hH38.js.map → history-DkP1tce0.js.map} +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/useAdminContext.d.ts +29 -0
- package/dist/{import-DINSB-Vu.js → import-DQPGsiIw.js} +2 -2
- package/dist/{import-DINSB-Vu.js.map → import-DQPGsiIw.js.map} +1 -1
- package/dist/index.js +60 -38
- package/dist/index.js.map +1 -1
- package/dist/types/components/EntityFormProps.d.ts +1 -1
- package/dist/types/fields.d.ts +1 -1
- package/dist/{util-BhhfHY1M.js → util-DBxSfWpl.js} +45 -35
- package/dist/util-DBxSfWpl.js.map +1 -0
- package/package.json +9 -9
- package/src/collection_editor/CollectionEditorDialogsContext.tsx +1 -1
- package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
- package/src/collection_editor/_cms_internals.ts +1 -1
- package/src/collection_editor/extensibility_types.ts +1 -1
- package/src/collection_editor/index.ts +2 -2
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +2 -2
- package/src/components/CollectionEditorDialogs.tsx +2 -2
- package/src/components/CollectionTableBinding/CollectionRowActions.tsx +5 -4
- package/src/components/CollectionViewBinding/CollectionListViewBinding.tsx +8 -7
- package/src/components/CollectionViewBinding/CollectionViewActions.tsx +2 -2
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +2 -2
- package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +2 -2
- package/src/components/DefaultDrawer.tsx +19 -8
- package/src/components/DeleteEntityDialog.tsx +2 -2
- package/src/components/DetailViewBinding.tsx +21 -1
- package/src/components/DrawerNavigationGroup.tsx +28 -4
- package/src/components/DrawerNavigationItem.tsx +19 -5
- package/src/components/EditFormActions.tsx +4 -3
- package/src/components/EditViewBinding.tsx +1 -1
- package/src/components/HomePage/ContentHomePage.tsx +4 -4
- package/src/components/RebaseAdmin.tsx +3 -3
- package/src/components/RebaseAuthGate.tsx +1 -1
- package/src/components/RebaseLayout.tsx +8 -2
- package/src/components/RebaseNavigation.tsx +9 -9
- package/src/components/RebaseRouteDefs.tsx +2 -2
- package/src/components/RebaseShell.tsx +10 -1
- package/src/components/RelationSelector.tsx +2 -2
- package/src/components/SidePanelProvider.tsx +2 -2
- package/src/components/app/Scaffold.tsx +16 -1
- package/src/data_export/export/ExportCollectionAction.tsx +2 -2
- package/src/form/EntityForm.tsx +2 -2
- package/src/form/EntityFormActions.tsx +2 -1
- package/src/form/EntityFormBinding.tsx +7 -7
- package/src/hooks/index.ts +1 -1
- package/src/hooks/navigation/useNavigationResolution.ts +2 -2
- package/src/hooks/{useCMSContext.tsx → useAdminContext.tsx} +10 -10
- package/src/hooks/useResolvedNavigationFrom.tsx +2 -2
- package/src/index.ts +4 -4
- package/src/preview/components/RelationPreview.tsx +1 -1
- package/src/types/components/EntityFormProps.tsx +2 -2
- package/src/types/fields.tsx +1 -1
- package/dist/CollectionEditorDialog-o7F_zbGY.js.map +0 -1
- package/dist/export-BvqhjdEb.js.map +0 -1
- package/dist/hooks/useCMSContext.d.ts +0 -29
- package/dist/util-BhhfHY1M.js.map +0 -1
|
@@ -3,7 +3,7 @@ import { useRebaseRegistryDispatch } from "@rebasepro/app";
|
|
|
3
3
|
import type { RebaseAdminConfig } from "@rebasepro/admin-types";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Declarative component to configure the
|
|
6
|
+
* Declarative component to configure the admin in Rebase.
|
|
7
7
|
* Renders nothing — purely registers config into the RebaseRegistry.
|
|
8
8
|
*
|
|
9
9
|
* When `collectionEditor` is provided, the built-in visual schema editor
|
|
@@ -14,7 +14,7 @@ export function RebaseAdmin({ collections, views, homePage, entityViews, entityA
|
|
|
14
14
|
const dispatch = useRebaseRegistryDispatch();
|
|
15
15
|
|
|
16
16
|
useLayoutEffect(() => {
|
|
17
|
-
dispatch.
|
|
17
|
+
dispatch.registerAdmin({ collections,
|
|
18
18
|
views,
|
|
19
19
|
homePage,
|
|
20
20
|
entityViews,
|
|
@@ -22,7 +22,7 @@ entityActions,
|
|
|
22
22
|
collectionEditor,
|
|
23
23
|
navigationGroupMappings,
|
|
24
24
|
basePath });
|
|
25
|
-
return () => dispatch.
|
|
25
|
+
return () => dispatch.unregisterAdmin();
|
|
26
26
|
}, [dispatch, collections, views, homePage, entityViews, entityActions, collectionEditor, navigationGroupMappings, basePath]);
|
|
27
27
|
|
|
28
28
|
return null;
|
|
@@ -15,7 +15,7 @@ import type { AuthControllerExtended } from "@rebasepro/admin-types";
|
|
|
15
15
|
* - Renders `children` when a user is authenticated.
|
|
16
16
|
*
|
|
17
17
|
* **Independently usable**: Use this alone when you want auth gating
|
|
18
|
-
* without the full
|
|
18
|
+
* without the full admin layout or navigation.
|
|
19
19
|
*
|
|
20
20
|
* @example
|
|
21
21
|
* ```tsx
|
|
@@ -19,8 +19,12 @@ export interface RebaseLayoutProps {
|
|
|
19
19
|
appBar?: React.ReactNode;
|
|
20
20
|
/** Custom Drawer to override the default. */
|
|
21
21
|
drawer?: React.ReactNode;
|
|
22
|
-
/**
|
|
22
|
+
/** Expand the drawer while the pointer is over it. Not a load-time default — that is `defaultDrawerOpen`. */
|
|
23
23
|
autoOpenDrawer?: boolean;
|
|
24
|
+
/** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */
|
|
25
|
+
defaultDrawerOpen?: boolean;
|
|
26
|
+
/** Path to the logo shown in the drawer and top bar. Falls back to the Rebase mark. */
|
|
27
|
+
logo?: string;
|
|
24
28
|
/** Dev views passed to AdminModeSyncer (resolved from RebaseNavigation). */
|
|
25
29
|
devViews?: AppView[];
|
|
26
30
|
}
|
|
@@ -49,6 +53,8 @@ export function RebaseLayout(props: RebaseLayoutProps) {
|
|
|
49
53
|
appBar,
|
|
50
54
|
drawer,
|
|
51
55
|
autoOpenDrawer = false,
|
|
56
|
+
defaultDrawerOpen = false,
|
|
57
|
+
logo,
|
|
52
58
|
devViews = []
|
|
53
59
|
} = props;
|
|
54
60
|
|
|
@@ -63,7 +69,7 @@ export function RebaseLayout(props: RebaseLayoutProps) {
|
|
|
63
69
|
);
|
|
64
70
|
|
|
65
71
|
return (
|
|
66
|
-
<Scaffold autoOpenDrawer={autoOpenDrawer}>
|
|
72
|
+
<Scaffold autoOpenDrawer={autoOpenDrawer} defaultDrawerOpen={defaultDrawerOpen} logo={logo}>
|
|
67
73
|
<AdminModeSyncer devViews={devViews}/>
|
|
68
74
|
{appBar}
|
|
69
75
|
{ActiveDrawer}
|
|
@@ -50,13 +50,13 @@ export interface RebaseNavigationProps {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* Navigation layer — builds and provides all
|
|
53
|
+
* Navigation layer — builds and provides all admin navigation controllers:
|
|
54
54
|
* collection registry, URL controller, navigation state, side entity,
|
|
55
55
|
* and the self-assembling Studio bridge.
|
|
56
56
|
*
|
|
57
57
|
* Also handles the collection editor config controller when enabled.
|
|
58
58
|
*
|
|
59
|
-
* **Independently usable**: Use this when you need
|
|
59
|
+
* **Independently usable**: Use this when you need admin navigation
|
|
60
60
|
* (entity tables, side panels) in a custom layout.
|
|
61
61
|
*
|
|
62
62
|
* @example
|
|
@@ -76,7 +76,7 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
76
76
|
|
|
77
77
|
// ── Collection Editor resolution ──────────────────────────────────
|
|
78
78
|
// The collection editor is ALWAYS enabled when Studio is registered.
|
|
79
|
-
// The `collectionEditor`
|
|
79
|
+
// The `collectionEditor` admin config is for fine-tuning (readOnly, auth, etc.),
|
|
80
80
|
// not for opting-in. When omitted, the editor defaults to enabled
|
|
81
81
|
// (read-only in production).
|
|
82
82
|
const collectionEditorConfig = registry.cmsConfig?.collectionEditor;
|
|
@@ -86,7 +86,7 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
86
86
|
return collectionEditorConfig;
|
|
87
87
|
}, [collectionEditorConfig]);
|
|
88
88
|
|
|
89
|
-
// ── Combine
|
|
89
|
+
// ── Combine admin and Studio Configs ────────────────────────────────
|
|
90
90
|
const cmsCollections = registry.cmsConfig?.collections ?? EMPTY_COLLECTIONS;
|
|
91
91
|
|
|
92
92
|
// ── Build the navigation controllers ──────────────────────────────
|
|
@@ -203,8 +203,8 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
203
203
|
return base;
|
|
204
204
|
}, [registry.studioConfig?.devViews, schemaView]);
|
|
205
205
|
|
|
206
|
-
// Merge
|
|
207
|
-
// Order:
|
|
206
|
+
// Merge admin-registered views with Studio dev views.
|
|
207
|
+
// Order: admin views (developer's primary content) → Studio dev views (tooling).
|
|
208
208
|
// Plugin views are merged later inside resolveAppViews.
|
|
209
209
|
const cmsViews = registry.cmsConfig?.views;
|
|
210
210
|
const mergedViews = useMemo(() => {
|
|
@@ -234,7 +234,7 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
234
234
|
adminMode: adminModeController?.mode
|
|
235
235
|
});
|
|
236
236
|
|
|
237
|
-
// ── Merge
|
|
237
|
+
// ── Merge admin-registered entityViews/entityActions into the customization controller ──
|
|
238
238
|
// The <Rebase> component builds the customizationController from its own props,
|
|
239
239
|
// but entity views passed to <RebaseAdmin> are stored in the registry and not
|
|
240
240
|
// automatically merged. We re-provide an enriched controller here so that
|
|
@@ -260,7 +260,7 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
260
260
|
}, [parentCustomizationController, registry.cmsConfig?.entityViews, registry.cmsConfig?.entityActions]);
|
|
261
261
|
|
|
262
262
|
// ── Inner content with all context providers ──────────────────────
|
|
263
|
-
// Re-provide RebaseDataContext with the routed data so that every
|
|
263
|
+
// Re-provide RebaseDataContext with the routed data so that every admin
|
|
264
264
|
// consumer (list/entity views, references, board, import/export, and
|
|
265
265
|
// `context.data`) is routed to the correct driver by collection path.
|
|
266
266
|
const navigationContent = (
|
|
@@ -302,7 +302,7 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
/**
|
|
305
|
-
* Internal component that auto-registers
|
|
305
|
+
* Internal component that auto-registers admin controllers into the
|
|
306
306
|
* self-assembling Studio bridge. Must be rendered inside both the
|
|
307
307
|
* navigation contexts and the StudioBridgeRegistryProvider.
|
|
308
308
|
*/
|
|
@@ -45,7 +45,7 @@ export interface RebaseRouteDefsProps {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* Route definitions for the
|
|
48
|
+
* Route definitions for the admin.
|
|
49
49
|
*
|
|
50
50
|
* Defines all standard routes: home, studio home, collection view,
|
|
51
51
|
* settings, debug, custom views, and a catch-all 404.
|
|
@@ -77,7 +77,7 @@ export function RebaseRouteDefs({ children, layout }: RebaseRouteDefsProps) {
|
|
|
77
77
|
|
|
78
78
|
const routeContents = (
|
|
79
79
|
<>
|
|
80
|
-
{/* Core
|
|
80
|
+
{/* Core admin Routes */}
|
|
81
81
|
<Route path={"/"} element={cmsHomePage}/>
|
|
82
82
|
{registry.studioConfig && (
|
|
83
83
|
<Route path={"/s"} element={studioHomePage}/>
|
|
@@ -14,12 +14,17 @@ export interface RebaseShellProps {
|
|
|
14
14
|
/** Top bar. Only rendered if provided — pass `<AppBar/>` for the default one. */
|
|
15
15
|
appBar?: React.ReactNode;
|
|
16
16
|
drawer?: React.ReactNode;
|
|
17
|
+
/** Expand the drawer while the pointer is over it. Not a load-time default — that is `defaultDrawerOpen`. */
|
|
17
18
|
autoOpenDrawer?: boolean;
|
|
19
|
+
/** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */
|
|
20
|
+
defaultDrawerOpen?: boolean;
|
|
21
|
+
/** Path to the logo shown in the drawer and top bar. Falls back to the Rebase mark. */
|
|
22
|
+
logo?: string;
|
|
18
23
|
children?: React.ReactNode;
|
|
19
24
|
}
|
|
20
25
|
|
|
21
26
|
/**
|
|
22
|
-
* Convenience component that composes all four
|
|
27
|
+
* Convenience component that composes all four admin layers:
|
|
23
28
|
*
|
|
24
29
|
* ```
|
|
25
30
|
* <RebaseAuthGate>
|
|
@@ -40,6 +45,8 @@ export function RebaseShell(props: RebaseShellProps) {
|
|
|
40
45
|
appBar,
|
|
41
46
|
drawer,
|
|
42
47
|
autoOpenDrawer = false,
|
|
48
|
+
defaultDrawerOpen = false,
|
|
49
|
+
logo,
|
|
43
50
|
children
|
|
44
51
|
} = props;
|
|
45
52
|
|
|
@@ -61,6 +68,8 @@ export function RebaseShell(props: RebaseShellProps) {
|
|
|
61
68
|
appBar={appBar}
|
|
62
69
|
drawer={drawer}
|
|
63
70
|
autoOpenDrawer={autoOpenDrawer}
|
|
71
|
+
defaultDrawerOpen={defaultDrawerOpen}
|
|
72
|
+
logo={logo}
|
|
64
73
|
devViews={devViews}
|
|
65
74
|
/>
|
|
66
75
|
}
|
|
@@ -223,7 +223,7 @@ export const RelationSelector = React.forwardRef<
|
|
|
223
223
|
|
|
224
224
|
if (hasEmbeddedData) {
|
|
225
225
|
const r = rel as EntityRelation;
|
|
226
|
-
//
|
|
226
|
+
// admin wire format embeds relation data as { id, path, values }
|
|
227
227
|
newResolvedItems.push(toRelationItem(r.data as unknown as Entity, r));
|
|
228
228
|
} else if (currentSelectedMap.has(relId)) {
|
|
229
229
|
// We already have it in currentSelected
|
|
@@ -259,7 +259,7 @@ export const RelationSelector = React.forwardRef<
|
|
|
259
259
|
const relation = isPrimitive ? new EntityRelation(relId, path) : rel as EntityRelation;
|
|
260
260
|
|
|
261
261
|
if (!isPrimitive && (rel as EntityRelation).data) {
|
|
262
|
-
//
|
|
262
|
+
// admin wire format embeds relation data as { id, path, values }
|
|
263
263
|
return toRelationItem((rel as EntityRelation).data as unknown as Entity, relation);
|
|
264
264
|
}
|
|
265
265
|
if (currentSelectedMap.has(String(relId))) {
|
|
@@ -15,8 +15,8 @@ import { useAuthController, useBridgeRegistration, NavigationBlockerProvider } f
|
|
|
15
15
|
* Provider that builds the SidePanelController and makes it available
|
|
16
16
|
* via the SidePanelControllerContext from @rebasepro/app.
|
|
17
17
|
*
|
|
18
|
-
* After the
|
|
19
|
-
* in the
|
|
18
|
+
* After the admin extraction refactor, `useBuildSidePanel` lives
|
|
19
|
+
* in the admin package while the context it feeds into lives in core.
|
|
20
20
|
* This provider bridges the two: place it inside the `<Rebase>` tree and
|
|
21
21
|
* above any component that calls `useSidePanel()`.
|
|
22
22
|
*
|
|
@@ -18,6 +18,18 @@ export interface ScaffoldProps {
|
|
|
18
18
|
*/
|
|
19
19
|
autoOpenDrawer?: boolean;
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Start with the drawer expanded rather than collapsed to icons.
|
|
23
|
+
*
|
|
24
|
+
* Distinct from {@link autoOpenDrawer}, which is a hover behaviour: this one
|
|
25
|
+
* only seeds the initial state, so the user's own toggle still wins for the
|
|
26
|
+
* rest of the session.
|
|
27
|
+
*
|
|
28
|
+
* Ignored on small layouts, where an expanded drawer covers the content it is
|
|
29
|
+
* meant to navigate.
|
|
30
|
+
*/
|
|
31
|
+
defaultDrawerOpen?: boolean;
|
|
32
|
+
|
|
21
33
|
/**
|
|
22
34
|
* Logo to be displayed in the top bar and drawer.
|
|
23
35
|
* Note that this has no effect if you are using a custom AppBar or Drawer.
|
|
@@ -51,6 +63,7 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
51
63
|
const {
|
|
52
64
|
children,
|
|
53
65
|
autoOpenDrawer,
|
|
66
|
+
defaultDrawerOpen = false,
|
|
54
67
|
logo,
|
|
55
68
|
className,
|
|
56
69
|
style,
|
|
@@ -70,7 +83,9 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
70
83
|
const includeDrawer = drawerChildren.length > 0;
|
|
71
84
|
const largeLayout = useLargeLayout();
|
|
72
85
|
|
|
73
|
-
|
|
86
|
+
// Seeded once, deliberately: a `useEffect` syncing this to the prop would
|
|
87
|
+
// re-expand the drawer under a user who had just collapsed it.
|
|
88
|
+
const [drawerOpen, setDrawerOpen] = React.useState(defaultDrawerOpen && largeLayout);
|
|
74
89
|
const [onHover, setOnHover] = React.useState(false);
|
|
75
90
|
|
|
76
91
|
const setOnHoverTrue = useCallback(() => setOnHover(true), []);
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
useData,
|
|
8
8
|
useTranslation
|
|
9
9
|
} from "@rebasepro/app";
|
|
10
|
-
import {
|
|
10
|
+
import { useAdminContext } from "../../hooks";
|
|
11
11
|
import { Entity, User } from "@rebasepro/types";
|
|
12
12
|
import { CollectionActionsProps, ExportConfig, RebaseContext, AdminCollection } from "@rebasepro/admin-types";
|
|
13
13
|
import { getDefaultValuesFor } from "@rebasepro/common";
|
|
@@ -56,7 +56,7 @@ export function ExportCollectionAction<M extends Record<string, unknown>, USER e
|
|
|
56
56
|
const [exportType, setExportType] = React.useState<"csv" | "json">("csv");
|
|
57
57
|
const [dateExportType, setDateExportType] = React.useState<"timestamp" | "string">("string");
|
|
58
58
|
|
|
59
|
-
const context =
|
|
59
|
+
const context = useAdminContext<USER>();
|
|
60
60
|
const dataClient = useData();
|
|
61
61
|
|
|
62
62
|
const canExport = !exportAllowed || exportAllowed({
|
package/src/form/EntityForm.tsx
CHANGED
|
@@ -39,9 +39,9 @@ import {
|
|
|
39
39
|
/**
|
|
40
40
|
* Headless entity form component.
|
|
41
41
|
*
|
|
42
|
-
* Renders a form for a entity collection without any
|
|
42
|
+
* Renders a form for a entity collection without any admin or backend dependencies.
|
|
43
43
|
* All backend concerns (save, caching, analytics, plugin slots) are provided via
|
|
44
|
-
* callback props. For
|
|
44
|
+
* callback props. For admin-connected usage, use {@link EntityFormBinding} instead.
|
|
45
45
|
*
|
|
46
46
|
* @group Components
|
|
47
47
|
*/
|
|
@@ -5,6 +5,7 @@ import type { EntityAction, AdminCollection } from "@rebasepro/admin-types";
|
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { Entity } from "@rebasepro/types";
|
|
7
7
|
import type { EntityFormActionsProps } from "../types/components/EntityFormActionsProps";
|
|
8
|
+
import { getIcon } from "@rebasepro/app";
|
|
8
9
|
import {
|
|
9
10
|
AlertCircleIcon,
|
|
10
11
|
Button,
|
|
@@ -136,7 +137,7 @@ function buildBottomActions<M extends Record<string, unknown>>({
|
|
|
136
137
|
formContext
|
|
137
138
|
});
|
|
138
139
|
}}>
|
|
139
|
-
{action.icon}
|
|
140
|
+
{getIcon(action.icon, undefined, undefined, "smallest")}
|
|
140
141
|
</IconButton>
|
|
141
142
|
))}
|
|
142
143
|
</div>}
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
|
|
31
31
|
import { useCollectionRegistryController } from "../hooks/navigation/contexts/CollectionRegistryContext";
|
|
32
32
|
import { useSidePanel } from "../hooks/useSidePanel";
|
|
33
|
-
import {
|
|
33
|
+
import { useAdminContext } from "../hooks/useAdminContext";
|
|
34
34
|
import { EntityForm } from "./EntityForm";
|
|
35
35
|
import {
|
|
36
36
|
extractTouchedValues,
|
|
@@ -41,9 +41,9 @@ import {
|
|
|
41
41
|
import { mergeDeep } from "@rebasepro/utils";
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Props for the
|
|
44
|
+
* Props for the admin-connected EntityFormBinding wrapper.
|
|
45
45
|
* Extends EntityFormProps — you can pass all the same props as EntityForm,
|
|
46
|
-
* but the binding provides
|
|
46
|
+
* but the binding provides admin context (save, caching, analytics, plugin slots)
|
|
47
47
|
* automatically.
|
|
48
48
|
*/
|
|
49
49
|
export type EntityFormBindingProps<M extends Record<string, unknown>> = Omit<EntityFormProps<M>,
|
|
@@ -63,7 +63,7 @@ export type EntityFormBindingProps<M extends Record<string, unknown>> = Omit<Ent
|
|
|
63
63
|
>;
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
66
|
+
* admin-connected wrapper around EntityForm.
|
|
67
67
|
*
|
|
68
68
|
* Provides all backend concerns that the headless EntityForm delegates via callbacks:
|
|
69
69
|
* - Save via the data layer (`saveEntityWithCallbacks`)
|
|
@@ -74,8 +74,8 @@ export type EntityFormBindingProps<M extends Record<string, unknown>> = Omit<Ent
|
|
|
74
74
|
* - Analytics events
|
|
75
75
|
* - Navigation via side entity controller
|
|
76
76
|
*
|
|
77
|
-
* Use this component inside the
|
|
78
|
-
* For headless usage outside the
|
|
77
|
+
* Use this component inside the admin (`<RebaseShell>`).
|
|
78
|
+
* For headless usage outside the admin, use `EntityForm` directly.
|
|
79
79
|
*
|
|
80
80
|
* @group Components
|
|
81
81
|
*/
|
|
@@ -102,7 +102,7 @@ export function EntityFormBinding<M extends Record<string, unknown>>({
|
|
|
102
102
|
const dataClient = useData();
|
|
103
103
|
const snackbarController = useSnackbarController();
|
|
104
104
|
const customizationController = useCustomizationController();
|
|
105
|
-
const context =
|
|
105
|
+
const context = useAdminContext();
|
|
106
106
|
const analyticsController = useAnalyticsController();
|
|
107
107
|
|
|
108
108
|
const [status, setStatus] = useState<EntityStatus>(initialStatus);
|
package/src/hooks/index.ts
CHANGED
|
@@ -13,4 +13,4 @@ export * from "./navigation/useResolvedViews";
|
|
|
13
13
|
export * from "./navigation/useTopLevelNavigation";
|
|
14
14
|
export * from "./useSideDialogsController";
|
|
15
15
|
export * from "./useBreadcrumbsController";
|
|
16
|
-
export * from "./
|
|
16
|
+
export * from "./useAdminContext";
|
|
@@ -238,13 +238,13 @@ export async function resolveAppViews(
|
|
|
238
238
|
if (count > 1) {
|
|
239
239
|
console.warn(
|
|
240
240
|
`[Rebase] Duplicate view slug "${slug}" detected (${count} views). ` +
|
|
241
|
-
`Last-write-wins. Ensure unique slugs across
|
|
241
|
+
`Last-write-wins. Ensure unique slugs across admin views and plugins.`
|
|
242
242
|
);
|
|
243
243
|
}
|
|
244
244
|
});
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
// Filter by roles — applies to
|
|
247
|
+
// Filter by roles — applies to admin, plugin, and builder-returned views
|
|
248
248
|
resolvedViews = filterViewsByRole(resolvedViews, authController);
|
|
249
249
|
|
|
250
250
|
return resolvedViews;
|
|
@@ -25,13 +25,13 @@ import {
|
|
|
25
25
|
} from "./navigation/contexts";
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* The
|
|
29
|
-
* controllers that are only available inside the
|
|
28
|
+
* The admin context extends the core RebaseContext with admin-specific
|
|
29
|
+
* controllers that are only available inside the admin routing tree.
|
|
30
30
|
*
|
|
31
|
-
* Use {@link
|
|
31
|
+
* Use {@link useAdminContext} to obtain an instance.
|
|
32
32
|
* @group Hooks and utilities
|
|
33
33
|
*/
|
|
34
|
-
export type
|
|
34
|
+
export type AdminContext<
|
|
35
35
|
DB = Record<string, unknown>,
|
|
36
36
|
USER extends User = User,
|
|
37
37
|
AuthControllerType extends AuthController<USER> = AuthController<USER>
|
|
@@ -44,20 +44,20 @@ export type CMSContext<
|
|
|
44
44
|
};
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* Hook that builds a fully-populated
|
|
48
|
-
* core {@link RebaseContext} with
|
|
47
|
+
* Hook that builds a fully-populated admin context by combining the
|
|
48
|
+
* core {@link RebaseContext} with admin-specific controllers.
|
|
49
49
|
*
|
|
50
|
-
* Use this instead of `useRebaseContext()` in
|
|
50
|
+
* Use this instead of `useRebaseContext()` in admin components that
|
|
51
51
|
* need to pass context to entity action callbacks, plugin slots,
|
|
52
|
-
* or any consumer that expects
|
|
52
|
+
* or any consumer that expects admin controllers on the context object.
|
|
53
53
|
*
|
|
54
54
|
* @group Hooks and utilities
|
|
55
55
|
*/
|
|
56
|
-
export function
|
|
56
|
+
export function useAdminContext<
|
|
57
57
|
DB = Record<string, unknown>,
|
|
58
58
|
USER extends User = User,
|
|
59
59
|
AuthControllerType extends AuthController<USER> = AuthController<USER>
|
|
60
|
-
>():
|
|
60
|
+
>(): AdminContext<DB, USER, AuthControllerType> {
|
|
61
61
|
const baseContext = useRebaseContext<USER, AuthControllerType>();
|
|
62
62
|
const sidePanelController = useSidePanel();
|
|
63
63
|
const sideDialogsController = useSideDialogsController();
|
|
@@ -4,7 +4,7 @@ import { Entity, User } from "@rebasepro/types";
|
|
|
4
4
|
import { RebaseContext } from "@rebasepro/admin-types";
|
|
5
5
|
import { useEffect, useState, useMemo } from "react";
|
|
6
6
|
import { getNavigationEntriesFromPath } from "@rebasepro/app";
|
|
7
|
-
import {
|
|
7
|
+
import { useAdminContext } from "./useAdminContext";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @see resolveNavigationFrom
|
|
@@ -136,7 +136,7 @@ export function useResolvedNavigationFrom<M extends Record<string, unknown>>(
|
|
|
136
136
|
path
|
|
137
137
|
}: NavigationFromProps): NavigationFrom<M> {
|
|
138
138
|
|
|
139
|
-
const context =
|
|
139
|
+
const context = useAdminContext();
|
|
140
140
|
const { navigationStateController, collectionRegistryController } = context;
|
|
141
141
|
|
|
142
142
|
const [data, setData] = useState<ResolvedNavigationEntry<M>[] | undefined>();
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// admin-specific types take priority over base types when names conflict
|
|
2
2
|
export * from "./types";
|
|
3
3
|
// Editor types only — the full ProseMirror editor (RichTextEditor) is a heavy import (~300 KB)
|
|
4
4
|
// and is available as a separate entry point: @rebasepro/admin/editor
|
|
@@ -77,7 +77,7 @@ export {
|
|
|
77
77
|
mergeEntityActions,
|
|
78
78
|
resolveEntityAction,
|
|
79
79
|
resolveEntityView,
|
|
80
|
-
// Property utilities (moved from @rebasepro/app — property-aware logic belongs in
|
|
80
|
+
// Property utilities (moved from @rebasepro/app — property-aware logic belongs in admin)
|
|
81
81
|
isReferenceProperty,
|
|
82
82
|
isRelationProperty,
|
|
83
83
|
getIconForWidget,
|
|
@@ -87,7 +87,7 @@ export {
|
|
|
87
87
|
getBracketNotation,
|
|
88
88
|
getPropertiesWithPropertiesOrder,
|
|
89
89
|
getDefaultPropertiesOrder,
|
|
90
|
-
// Preview utilities (moved from @rebasepro/app — property-aware logic belongs in
|
|
90
|
+
// Preview utilities (moved from @rebasepro/app — property-aware logic belongs in admin)
|
|
91
91
|
getEntityPreviewKeys,
|
|
92
92
|
getEntityTitlePropertyKey,
|
|
93
93
|
getEntityTitlePropertyKeyForEntity
|
|
@@ -102,7 +102,7 @@ export { useCollectionDataController, createStaticDataController } from "./util/
|
|
|
102
102
|
export * from "./data_import";
|
|
103
103
|
export * from "./data_export";
|
|
104
104
|
|
|
105
|
-
// Collection editor — moved from @rebasepro/studio (
|
|
105
|
+
// Collection editor — moved from @rebasepro/studio (admin-dependent visual schema editor)
|
|
106
106
|
export * from "./collection_editor";
|
|
107
107
|
|
|
108
108
|
|
|
@@ -158,7 +158,7 @@ function RelationPreviewExisting<M extends Record<string, unknown> = Record<stri
|
|
|
158
158
|
collection: AdminCollection<M>
|
|
159
159
|
}) {
|
|
160
160
|
|
|
161
|
-
//
|
|
161
|
+
// admin wire format embeds relation data as { id, path, values }
|
|
162
162
|
const passedEntity = relation.data as Entity<M> | undefined;
|
|
163
163
|
const ResolvedEntityPreview = useComponentOverride("EntityPreview", EntityPreviewBinding);
|
|
164
164
|
const customizationController = useCustomizationController();
|
|
@@ -7,7 +7,7 @@ import { EntityFormActionsProps } from "./EntityFormActionsProps";
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Props for the headless EntityForm component.
|
|
10
|
-
* This form can be used without
|
|
10
|
+
* This form can be used without admin context — all backend concerns
|
|
11
11
|
* (save, caching, analytics, plugin slots) are provided via callbacks.
|
|
12
12
|
*/
|
|
13
13
|
export type EntityFormProps<M extends Record<string, unknown>> = {
|
|
@@ -51,7 +51,7 @@ export type EntityFormProps<M extends Record<string, unknown>> = {
|
|
|
51
51
|
|
|
52
52
|
children?: React.ReactNode;
|
|
53
53
|
|
|
54
|
-
// --- Headless callbacks (replace internal
|
|
54
|
+
// --- Headless callbacks (replace internal admin hooks) ---
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* Called on form submit with the values to save.
|
package/src/types/fields.tsx
CHANGED
|
@@ -243,7 +243,7 @@ export interface PropertyFieldBindingProps<M extends Record<string, unknown> = R
|
|
|
243
243
|
propertyKey: string;
|
|
244
244
|
|
|
245
245
|
/**
|
|
246
|
-
* The
|
|
246
|
+
* The admin property you are binding this field to
|
|
247
247
|
*/
|
|
248
248
|
property: Property;
|
|
249
249
|
|