@rebasepro/cli 0.5.0 → 0.6.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.
- package/dist/commands/init.d.ts +13 -0
- package/dist/commands/skills.d.ts +1 -0
- package/dist/index.es.js +1631 -1308
- package/dist/index.es.js.map +1 -1
- package/dist/utils/package-manager.d.ts +2 -0
- package/package.json +17 -16
- package/skills/rebase-admin/SKILL.md +710 -0
- package/skills/rebase-api/SKILL.md +662 -0
- package/skills/rebase-api/references/.gitkeep +3 -0
- package/skills/rebase-auth/SKILL.md +1143 -0
- package/skills/rebase-auth/references/.gitkeep +3 -0
- package/skills/rebase-backend-postgres/SKILL.md +633 -0
- package/skills/rebase-backend-postgres/references/.gitkeep +3 -0
- package/skills/rebase-basics/SKILL.md +749 -0
- package/skills/rebase-basics/references/.gitkeep +3 -0
- package/skills/rebase-collections/SKILL.md +1328 -0
- package/skills/rebase-collections/references/.gitkeep +3 -0
- package/skills/rebase-cron-jobs/SKILL.md +699 -0
- package/skills/rebase-cron-jobs/references/.gitkeep +1 -0
- package/skills/rebase-custom-functions/SKILL.md +233 -0
- package/skills/rebase-deployment/SKILL.md +885 -0
- package/skills/rebase-deployment/references/.gitkeep +3 -0
- package/skills/rebase-design-language/SKILL.md +692 -0
- package/skills/rebase-email/SKILL.md +701 -0
- package/skills/rebase-email/references/.gitkeep +1 -0
- package/skills/rebase-entity-history/SKILL.md +485 -0
- package/skills/rebase-entity-history/references/.gitkeep +1 -0
- package/skills/rebase-local-env-setup/SKILL.md +189 -0
- package/skills/rebase-local-env-setup/references/.gitkeep +3 -0
- package/skills/rebase-realtime/SKILL.md +755 -0
- package/skills/rebase-realtime/references/.gitkeep +3 -0
- package/skills/rebase-sdk/SKILL.md +594 -0
- package/skills/rebase-sdk/references/.gitkeep +0 -0
- package/skills/rebase-storage/SKILL.md +765 -0
- package/skills/rebase-storage/references/.gitkeep +3 -0
- package/skills/rebase-studio/SKILL.md +746 -0
- package/skills/rebase-studio/references/.gitkeep +3 -0
- package/skills/rebase-ui-components/SKILL.md +1488 -0
- package/skills/rebase-ui-components/references/.gitkeep +3 -0
- package/skills/rebase-webhooks/SKILL.md +623 -0
- package/skills/rebase-webhooks/references/.gitkeep +1 -0
- package/templates/template/AGENTS.md +2 -0
- package/templates/template/CLAUDE.md +2 -0
- package/templates/template/ai-instructions.md +6 -3
- package/templates/template/backend/package.json +1 -1
- package/templates/template/backend/src/env.ts +1 -1
- package/templates/template/backend/src/index.ts +9 -6
- package/templates/template/config/collections/presets/ecommerce/orders.ts +15 -5
- package/templates/template/config/collections/presets/ecommerce/products.ts +9 -3
- package/templates/template/config/collections/users.ts +7 -10
- package/templates/template/frontend/package.json +2 -2
- package/templates/template/frontend/src/App.tsx +1 -7
- package/templates/template/frontend/vite.config.ts +0 -1
- package/templates/template/package.json +1 -0
- package/dist/commands/cli.test.d.ts +0 -1
- package/dist/commands/dev.test.d.ts +0 -1
- package/dist/commands/init.test.d.ts +0 -1
- package/dist/index.cjs +0 -1575
- package/dist/index.cjs.map +0 -1
- package/dist/utils/package-manager.test.d.ts +0 -1
- package/dist/utils/project.test.d.ts +0 -1
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rebase-admin
|
|
3
|
+
description: Guide for navigating the Rebase admin CMS, opening entities in side drawers, building URLs, embedding collection panels, using the collection registry, and programmatic navigation. Use this skill when an agent or user needs to navigate to a collection view, open an entity in the side panel/drawer, build admin URLs, embed a collection inside a custom page, use the entity selection dialog, or access CMS-specific controllers.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rebase Admin (`@rebasepro/admin`)
|
|
7
|
+
|
|
8
|
+
The `@rebasepro/admin` package provides the CMS layer for Rebase. It handles collection views, entity editing, navigation, side panels (drawers), URL routing, breadcrumbs, and the full CMS context. This skill covers the **programmatic APIs** for navigating and interacting with the admin.
|
|
9
|
+
|
|
10
|
+
> **IMPORTANT FOR AGENTS:** All hooks in this skill must be called **inside** the `<RebaseShell>` component tree. They rely on React contexts provided by `<RebaseNavigation>`, `<SideEntityProvider>`, and `<RebaseRouteDefs>`.
|
|
11
|
+
|
|
12
|
+
## Quick Reference — Common Tasks
|
|
13
|
+
|
|
14
|
+
| Task | Hook / Component | Package |
|
|
15
|
+
|------|-----------------|---------|
|
|
16
|
+
| Open entity in side drawer | `useSideEntityController()` | `@rebasepro/admin` |
|
|
17
|
+
| Navigate to a collection view | `useUrlController()` | `@rebasepro/admin` |
|
|
18
|
+
| Look up a collection by slug | `useCollectionRegistryController()` | `@rebasepro/admin` |
|
|
19
|
+
| Embed a collection in a custom page | `<CollectionPanel>` | `@rebasepro/admin` |
|
|
20
|
+
| Open an entity selection dialog | `useEntitySelectionDialog()` | `@rebasepro/admin` |
|
|
21
|
+
| Open a custom side dialog | `useSideDialogsController()` | `@rebasepro/admin` |
|
|
22
|
+
| Set breadcrumbs | `useBreadcrumbsController()` | `@rebasepro/admin` |
|
|
23
|
+
| Access full CMS context | `useCMSContext()` | `@rebasepro/admin` |
|
|
24
|
+
| Access navigation state & views | `useNavigationStateController()` | `@rebasepro/admin` |
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 1. Opening Entities in the Side Drawer
|
|
29
|
+
|
|
30
|
+
Use `useSideEntityController()` to open, replace, or close entity side panels (the sliding drawer that shows entity forms).
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { useSideEntityController } from "@rebasepro/admin";
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### SideEntityController Interface
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
interface SideEntityController {
|
|
40
|
+
/** Close the last (topmost) panel */
|
|
41
|
+
close: () => void;
|
|
42
|
+
|
|
43
|
+
/** Open a new entity side panel */
|
|
44
|
+
open: <M extends Record<string, unknown>>(props: EntitySidePanelProps<M>) => void;
|
|
45
|
+
|
|
46
|
+
/** Replace the last open panel with a new one */
|
|
47
|
+
replace: <M extends Record<string, unknown>>(props: EntitySidePanelProps<M>) => void;
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### EntitySidePanelProps
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
interface EntitySidePanelProps<M extends Record<string, unknown> = Record<string, unknown>> {
|
|
55
|
+
/** Absolute path of the entity's collection (e.g. "products") */
|
|
56
|
+
path: string;
|
|
57
|
+
|
|
58
|
+
/** ID of the entity. Omit to create a new entity. */
|
|
59
|
+
entityId?: string | number;
|
|
60
|
+
|
|
61
|
+
/** Set to true to create a copy of an existing entity */
|
|
62
|
+
copy?: boolean;
|
|
63
|
+
|
|
64
|
+
/** Open with a specific sub-collection tab selected */
|
|
65
|
+
selectedTab?: string;
|
|
66
|
+
|
|
67
|
+
/** Override the width of the form panel (e.g. "600px") */
|
|
68
|
+
width?: number | string;
|
|
69
|
+
|
|
70
|
+
/** Explicit collection config (auto-resolved from navigation if omitted) */
|
|
71
|
+
collection?: EntityCollection<M>;
|
|
72
|
+
|
|
73
|
+
/** Whether to update the browser URL when opening (default: true) */
|
|
74
|
+
updateUrl?: boolean;
|
|
75
|
+
|
|
76
|
+
/** Callback when the entity is saved/updated */
|
|
77
|
+
onUpdate?: (params: { entity: Entity<M> }) => void;
|
|
78
|
+
|
|
79
|
+
/** Callback when the panel is closed */
|
|
80
|
+
onClose?: () => void;
|
|
81
|
+
|
|
82
|
+
/** Close the panel automatically after saving */
|
|
83
|
+
closeOnSave?: boolean;
|
|
84
|
+
|
|
85
|
+
/** Override form properties */
|
|
86
|
+
formProps?: Record<string, unknown>;
|
|
87
|
+
|
|
88
|
+
/** Show a full-screen toggle button */
|
|
89
|
+
allowFullScreen?: boolean;
|
|
90
|
+
|
|
91
|
+
/** Pre-populate form values when creating a new entity (only when entityId is not set) */
|
|
92
|
+
defaultValues?: Partial<M>;
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Examples
|
|
97
|
+
|
|
98
|
+
**Open an existing entity for editing:**
|
|
99
|
+
```tsx
|
|
100
|
+
const sideEntityController = useSideEntityController();
|
|
101
|
+
|
|
102
|
+
// Open the product with ID "abc123" in the side drawer
|
|
103
|
+
sideEntityController.open({
|
|
104
|
+
path: "products",
|
|
105
|
+
entityId: "abc123"
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Create a new entity with pre-filled values:**
|
|
110
|
+
```tsx
|
|
111
|
+
sideEntityController.open({
|
|
112
|
+
path: "products",
|
|
113
|
+
defaultValues: {
|
|
114
|
+
name: "New Product",
|
|
115
|
+
status: "draft"
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Open with a callback on save:**
|
|
121
|
+
```tsx
|
|
122
|
+
sideEntityController.open({
|
|
123
|
+
path: "orders",
|
|
124
|
+
entityId: orderId,
|
|
125
|
+
closeOnSave: true,
|
|
126
|
+
onUpdate: ({ entity }) => {
|
|
127
|
+
console.log("Saved:", entity.id, entity.values);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Replace the current panel (instead of stacking):**
|
|
133
|
+
```tsx
|
|
134
|
+
sideEntityController.replace({
|
|
135
|
+
path: "clients",
|
|
136
|
+
entityId: "xyz789"
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 2. Navigating to Collection Views
|
|
143
|
+
|
|
144
|
+
Use `useUrlController()` to build URLs and navigate programmatically within the admin.
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { useUrlController } from "@rebasepro/admin";
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### UrlController Interface
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
type UrlController = {
|
|
154
|
+
/** Base path for the CMS (default: "/") */
|
|
155
|
+
basePath: string;
|
|
156
|
+
|
|
157
|
+
/** Base path for collection routes (default: "/c") */
|
|
158
|
+
baseCollectionPath: string;
|
|
159
|
+
|
|
160
|
+
/** Convert a URL path to a data path: "/c/products" → "products" */
|
|
161
|
+
urlPathToDataPath: (cmsPath: string) => string;
|
|
162
|
+
|
|
163
|
+
/** Base URL for the home screen */
|
|
164
|
+
homeUrl: string;
|
|
165
|
+
|
|
166
|
+
/** Check if a URL path belongs to a collection */
|
|
167
|
+
isUrlCollectionPath: (urlPath: string) => boolean;
|
|
168
|
+
|
|
169
|
+
/** Build a URL for a collection: "products" → "/c/products" */
|
|
170
|
+
buildUrlCollectionPath: (path: string) => string;
|
|
171
|
+
|
|
172
|
+
/** Build a URL for a custom view or app path */
|
|
173
|
+
buildAppUrlPath: (path: string) => string;
|
|
174
|
+
|
|
175
|
+
/** Resolve collection IDs in a path to database paths */
|
|
176
|
+
resolveDatabasePathsFrom: (path: string) => string;
|
|
177
|
+
|
|
178
|
+
/** Navigate to a route (wraps react-router's navigate) */
|
|
179
|
+
navigate: (to: string, options?: NavigateOptions) => void;
|
|
180
|
+
};
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Examples
|
|
184
|
+
|
|
185
|
+
**Navigate to a collection view:**
|
|
186
|
+
```tsx
|
|
187
|
+
const urlController = useUrlController();
|
|
188
|
+
|
|
189
|
+
// Navigate to the "products" collection
|
|
190
|
+
const url = urlController.buildUrlCollectionPath("products");
|
|
191
|
+
urlController.navigate(url);
|
|
192
|
+
// This navigates to "/c/products"
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Navigate to a specific entity within a collection:**
|
|
196
|
+
```tsx
|
|
197
|
+
const url = urlController.buildUrlCollectionPath("products/abc123");
|
|
198
|
+
urlController.navigate(url);
|
|
199
|
+
// This navigates to "/c/products/abc123"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Navigate to a custom view:**
|
|
203
|
+
```tsx
|
|
204
|
+
const url = urlController.buildAppUrlPath("my-dashboard");
|
|
205
|
+
urlController.navigate(url);
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**Navigate and replace history (no back button):**
|
|
209
|
+
```tsx
|
|
210
|
+
urlController.navigate(
|
|
211
|
+
urlController.buildUrlCollectionPath("orders"),
|
|
212
|
+
{ replace: true }
|
|
213
|
+
);
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Navigate to home:**
|
|
217
|
+
```tsx
|
|
218
|
+
urlController.navigate(urlController.homeUrl);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
> **IMPORTANT FOR AGENTS:** The URL structure is `basePath + baseCollectionPath + "/" + slug`. By default this produces `/c/products`. Use `buildUrlCollectionPath()` instead of manually constructing URLs.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 3. Collection Registry
|
|
226
|
+
|
|
227
|
+
Use `useCollectionRegistryController()` to look up registered collections by slug.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
import { useCollectionRegistryController } from "@rebasepro/admin";
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### CollectionRegistryController Interface
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
type CollectionRegistryController<
|
|
237
|
+
DB = Record<string, unknown>,
|
|
238
|
+
EC extends EntityCollection = EntityCollection
|
|
239
|
+
> = {
|
|
240
|
+
/** All registered collections */
|
|
241
|
+
collections?: EntityCollection[];
|
|
242
|
+
|
|
243
|
+
/** Whether the registry is ready */
|
|
244
|
+
initialised: boolean;
|
|
245
|
+
|
|
246
|
+
/** Get a collection by slug or path */
|
|
247
|
+
getCollection: <K extends keyof DB>(slugOrPath: Extract<K, string>, includeUserOverride?: boolean) => EC | undefined;
|
|
248
|
+
|
|
249
|
+
/** Get the raw (un-normalized) collection config — for the Visual Editor only */
|
|
250
|
+
getRawCollection: (slugOrPath: string) => EC | undefined;
|
|
251
|
+
|
|
252
|
+
/** Get all parent entity references for a path */
|
|
253
|
+
getParentReferencesFromPath: (path: string) => EntityReference[];
|
|
254
|
+
|
|
255
|
+
/** Get parent collection slugs for a path */
|
|
256
|
+
getParentCollectionSlugs: (path: string) => string[];
|
|
257
|
+
|
|
258
|
+
/** Get parent entity IDs for a path */
|
|
259
|
+
getParentEntityIds: (path: string) => string[];
|
|
260
|
+
|
|
261
|
+
/** Resolve IDs to paths */
|
|
262
|
+
convertIdsToPaths: (ids: string[]) => string[];
|
|
263
|
+
};
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Example
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
const registry = useCollectionRegistryController();
|
|
270
|
+
|
|
271
|
+
// Check if a collection exists
|
|
272
|
+
const products = registry.getCollection("products");
|
|
273
|
+
if (products) {
|
|
274
|
+
console.log("Collection name:", products.name);
|
|
275
|
+
console.log("Properties:", Object.keys(products.properties));
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// List all collections
|
|
279
|
+
registry.collections?.forEach(c => {
|
|
280
|
+
console.log(c.slug, c.name);
|
|
281
|
+
});
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## 4. Embedding Collections with CollectionPanel
|
|
287
|
+
|
|
288
|
+
`CollectionPanel` is a high-level wrapper for embedding collection views inside custom pages (dashboards, home pages, entity detail views).
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { CollectionPanel } from "@rebasepro/admin";
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### CollectionPanelProps
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
type CollectionPanelProps = {
|
|
298
|
+
/** Collection slug to display (e.g. "tasks") — required */
|
|
299
|
+
path: string;
|
|
300
|
+
|
|
301
|
+
/** Title above the collection. `false` to hide. Defaults to collection name. */
|
|
302
|
+
title?: string | false;
|
|
303
|
+
|
|
304
|
+
/** Force a view mode (table, card, etc.) */
|
|
305
|
+
viewMode?: ViewMode;
|
|
306
|
+
|
|
307
|
+
/** Override sort: [fieldName, direction] */
|
|
308
|
+
sort?: [string, "asc" | "desc"];
|
|
309
|
+
|
|
310
|
+
/** Max entities to display */
|
|
311
|
+
limit?: number;
|
|
312
|
+
|
|
313
|
+
/** Sync filter/sort with URL params (default: false) */
|
|
314
|
+
updateUrl?: boolean;
|
|
315
|
+
|
|
316
|
+
/** Entity open mode when clicking */
|
|
317
|
+
openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
|
|
318
|
+
|
|
319
|
+
/** Container CSS class */
|
|
320
|
+
className?: string;
|
|
321
|
+
|
|
322
|
+
/** Additional collection-level overrides */
|
|
323
|
+
collectionOverrides?: Partial<EntityCollection>;
|
|
324
|
+
};
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Examples
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
// Simple embedded collection
|
|
331
|
+
<CollectionPanel path="tasks" title="Pending Tasks" />
|
|
332
|
+
|
|
333
|
+
// Table with sorting and limit
|
|
334
|
+
<CollectionPanel
|
|
335
|
+
path="clients"
|
|
336
|
+
viewMode="table"
|
|
337
|
+
limit={10}
|
|
338
|
+
sort={["createdAt", "desc"]}
|
|
339
|
+
/>
|
|
340
|
+
|
|
341
|
+
// With a default filter
|
|
342
|
+
<CollectionPanel
|
|
343
|
+
path="orders"
|
|
344
|
+
title={false}
|
|
345
|
+
openEntityMode="dialog"
|
|
346
|
+
collectionOverrides={{
|
|
347
|
+
defaultFilter: { status: ["!=", "completed"] }
|
|
348
|
+
}}
|
|
349
|
+
/>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
> **IMPORTANT FOR AGENTS:** `CollectionPanel` defaults `updateUrl` to `false` so embedded panels don't hijack the browser URL. Only set `updateUrl={true}` if you explicitly need URL sync.
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 5. Entity Selection Dialog
|
|
357
|
+
|
|
358
|
+
Use `useEntitySelectionDialog()` to open a side dialog for selecting entities (same mechanism used by reference fields).
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
import { useEntitySelectionDialog } from "@rebasepro/admin";
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Usage
|
|
365
|
+
|
|
366
|
+
```tsx
|
|
367
|
+
function MyComponent() {
|
|
368
|
+
const { open, close } = useEntitySelectionDialog<Product>({
|
|
369
|
+
path: "products",
|
|
370
|
+
onSingleEntitySelected: (entity) => {
|
|
371
|
+
console.log("Selected:", entity.id);
|
|
372
|
+
close();
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
return <Button onClick={open}>Select Product</Button>;
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
The hook accepts all `EntitySelectionProps` except `path` (which you pass separately), plus an `onClose` callback.
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## 6. Side Dialogs (Generic)
|
|
385
|
+
|
|
386
|
+
Use `useSideDialogsController()` to open arbitrary side panels with custom React content. This is the lower-level mechanism behind entity side panels.
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
import { useSideDialogsController } from "@rebasepro/admin";
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### SideDialogsController Interface
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
interface SideDialogsController {
|
|
396
|
+
/** Close the last panel */
|
|
397
|
+
close: () => void;
|
|
398
|
+
|
|
399
|
+
/** Currently open panels */
|
|
400
|
+
sidePanels: SideDialogPanelProps[];
|
|
401
|
+
|
|
402
|
+
/** Override all panels */
|
|
403
|
+
setSidePanels: (panels: SideDialogPanelProps[]) => void;
|
|
404
|
+
|
|
405
|
+
/** Open one or multiple side panels */
|
|
406
|
+
open: (panelProps: SideDialogPanelProps | SideDialogPanelProps[]) => void;
|
|
407
|
+
|
|
408
|
+
/** Replace the last panel */
|
|
409
|
+
replace: (panelProps: SideDialogPanelProps | SideDialogPanelProps[]) => void;
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### SideDialogPanelProps
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
interface SideDialogPanelProps {
|
|
417
|
+
/** Unique key identifying this panel */
|
|
418
|
+
key: string;
|
|
419
|
+
|
|
420
|
+
/** React component to render inside the panel */
|
|
421
|
+
component: React.ReactNode;
|
|
422
|
+
|
|
423
|
+
/** Optional panel width (e.g. "90vw", "600px") */
|
|
424
|
+
width?: string;
|
|
425
|
+
|
|
426
|
+
/** When open, update the browser URL to this path */
|
|
427
|
+
urlPath?: string;
|
|
428
|
+
|
|
429
|
+
/** URL to navigate to when the panel is closed and there's no history */
|
|
430
|
+
parentUrlPath?: string;
|
|
431
|
+
|
|
432
|
+
/** Callback when the panel is closed */
|
|
433
|
+
onClose?: () => void;
|
|
434
|
+
|
|
435
|
+
/** Store additional data on the panel */
|
|
436
|
+
additional?: unknown;
|
|
437
|
+
}
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Example
|
|
441
|
+
|
|
442
|
+
```tsx
|
|
443
|
+
const sideDialogs = useSideDialogsController();
|
|
444
|
+
|
|
445
|
+
sideDialogs.open({
|
|
446
|
+
key: "my-custom-panel",
|
|
447
|
+
component: <MyCustomView data={someData} />,
|
|
448
|
+
width: "600px",
|
|
449
|
+
onClose: () => console.log("Panel closed")
|
|
450
|
+
});
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
## 7. Breadcrumbs
|
|
456
|
+
|
|
457
|
+
Use `useBreadcrumbsController()` to read or set the breadcrumb trail.
|
|
458
|
+
|
|
459
|
+
```typescript
|
|
460
|
+
import { useBreadcrumbsController } from "@rebasepro/admin";
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### BreadcrumbsController Interface
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
interface BreadcrumbsController {
|
|
467
|
+
breadcrumbs: BreadcrumbEntry[];
|
|
468
|
+
set: (props: { breadcrumbs: BreadcrumbEntry[] }) => void;
|
|
469
|
+
updateCount: (id: string, count: number | null | undefined) => void;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
interface BreadcrumbEntry {
|
|
473
|
+
title: string;
|
|
474
|
+
url: string;
|
|
475
|
+
count?: number | null; // undefined = N/A, null = loading, number = loaded
|
|
476
|
+
id?: string; // for targeted count updates
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
### Example
|
|
481
|
+
|
|
482
|
+
```tsx
|
|
483
|
+
const breadcrumbs = useBreadcrumbsController();
|
|
484
|
+
|
|
485
|
+
breadcrumbs.set({
|
|
486
|
+
breadcrumbs: [
|
|
487
|
+
{ title: "Dashboard", url: "/" },
|
|
488
|
+
{ title: "Products", url: "/c/products", id: "products", count: null },
|
|
489
|
+
]
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
// Later, update the count without re-setting everything
|
|
493
|
+
breadcrumbs.updateCount("products", 42);
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
---
|
|
497
|
+
|
|
498
|
+
## 8. Navigation State
|
|
499
|
+
|
|
500
|
+
Use `useNavigationStateController()` to access registered views, loading state, and trigger navigation refresh.
|
|
501
|
+
|
|
502
|
+
```typescript
|
|
503
|
+
import { useNavigationStateController } from "@rebasepro/admin";
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### NavigationStateController Interface
|
|
507
|
+
|
|
508
|
+
```typescript
|
|
509
|
+
type NavigationStateController = {
|
|
510
|
+
/** Custom views added to the main navigation */
|
|
511
|
+
views?: AppView[];
|
|
512
|
+
|
|
513
|
+
/** Custom views added to admin navigation */
|
|
514
|
+
adminViews?: AppView[];
|
|
515
|
+
|
|
516
|
+
/** Top-level navigation entries and groups */
|
|
517
|
+
topLevelNavigation?: NavigationResult;
|
|
518
|
+
|
|
519
|
+
/** Whether navigation is still loading */
|
|
520
|
+
loading: boolean;
|
|
521
|
+
|
|
522
|
+
/** Error during navigation loading */
|
|
523
|
+
navigationLoadingError?: unknown;
|
|
524
|
+
|
|
525
|
+
/** Force a navigation recalculation */
|
|
526
|
+
refreshNavigation: () => void;
|
|
527
|
+
|
|
528
|
+
/** Registered plugins */
|
|
529
|
+
plugins?: RebasePlugin[];
|
|
530
|
+
};
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
---
|
|
534
|
+
|
|
535
|
+
## 9. CMS Context (All-in-One)
|
|
536
|
+
|
|
537
|
+
Use `useCMSContext()` to get the full CMS context combining the core `RebaseContext` with all CMS-specific controllers.
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
import { useCMSContext } from "@rebasepro/admin";
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
### CMSContext Type
|
|
544
|
+
|
|
545
|
+
```typescript
|
|
546
|
+
type CMSContext = RebaseContext & {
|
|
547
|
+
sideEntityController: SideEntityController;
|
|
548
|
+
sideDialogsController: SideDialogsController;
|
|
549
|
+
urlController: UrlController;
|
|
550
|
+
navigationStateController: NavigationStateController;
|
|
551
|
+
collectionRegistryController: CollectionRegistryController;
|
|
552
|
+
};
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
### Example
|
|
556
|
+
|
|
557
|
+
```tsx
|
|
558
|
+
const context = useCMSContext();
|
|
559
|
+
|
|
560
|
+
// Access any controller
|
|
561
|
+
context.sideEntityController.open({ path: "products", entityId: "abc" });
|
|
562
|
+
context.urlController.navigate(context.urlController.buildUrlCollectionPath("orders"));
|
|
563
|
+
context.collectionRegistryController.getCollection("products");
|
|
564
|
+
context.authController; // from RebaseContext
|
|
565
|
+
context.data; // DataSource from RebaseContext
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
> **TIP:** Use `useCMSContext()` instead of `useRebaseContext()` when you need CMS controllers (side panels, navigation, URL). Use `useRebaseContext()` from `@rebasepro/core` when you only need core context (auth, data, storage).
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
## 10. Common Patterns
|
|
573
|
+
|
|
574
|
+
### Navigate to a collection and open an entity
|
|
575
|
+
|
|
576
|
+
```tsx
|
|
577
|
+
import { useUrlController, useSideEntityController } from "@rebasepro/admin";
|
|
578
|
+
|
|
579
|
+
function navigateAndOpen() {
|
|
580
|
+
const urlController = useUrlController();
|
|
581
|
+
const sideEntityController = useSideEntityController();
|
|
582
|
+
|
|
583
|
+
// First navigate to the collection
|
|
584
|
+
urlController.navigate(urlController.buildUrlCollectionPath("products"));
|
|
585
|
+
|
|
586
|
+
// Then open the entity in the side drawer
|
|
587
|
+
sideEntityController.open({
|
|
588
|
+
path: "products",
|
|
589
|
+
entityId: "abc123"
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
### Open entity from a custom view without navigating
|
|
595
|
+
|
|
596
|
+
```tsx
|
|
597
|
+
import { useSideEntityController } from "@rebasepro/admin";
|
|
598
|
+
|
|
599
|
+
function MyCustomView() {
|
|
600
|
+
const sideEntityController = useSideEntityController();
|
|
601
|
+
|
|
602
|
+
return (
|
|
603
|
+
<button onClick={() => sideEntityController.open({
|
|
604
|
+
path: "products",
|
|
605
|
+
entityId: "abc123",
|
|
606
|
+
updateUrl: false // don't change the URL
|
|
607
|
+
})}>
|
|
608
|
+
View Product
|
|
609
|
+
</button>
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
### Programmatic entity creation from a custom view
|
|
615
|
+
|
|
616
|
+
```tsx
|
|
617
|
+
import { useSideEntityController } from "@rebasepro/admin";
|
|
618
|
+
|
|
619
|
+
function CreateButton() {
|
|
620
|
+
const sideEntity = useSideEntityController();
|
|
621
|
+
|
|
622
|
+
return (
|
|
623
|
+
<button onClick={() => sideEntity.open({
|
|
624
|
+
path: "orders",
|
|
625
|
+
defaultValues: {
|
|
626
|
+
status: "pending",
|
|
627
|
+
createdAt: new Date()
|
|
628
|
+
},
|
|
629
|
+
closeOnSave: true,
|
|
630
|
+
onUpdate: ({ entity }) => {
|
|
631
|
+
console.log("Created order:", entity.id);
|
|
632
|
+
}
|
|
633
|
+
})}>
|
|
634
|
+
New Order
|
|
635
|
+
</button>
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
## Exported Components
|
|
643
|
+
|
|
644
|
+
The admin package exports the following components (from `@rebasepro/admin`):
|
|
645
|
+
|
|
646
|
+
| Component | Description |
|
|
647
|
+
|-----------|-------------|
|
|
648
|
+
| `RebaseCMS` | Declarative CMS config (collections, views, editor) — renders nothing |
|
|
649
|
+
| `RebaseShell` | App shell (drawer, nav, routes, layout) — renders the actual UI |
|
|
650
|
+
| `CollectionPanel` | Embed a collection view inside custom pages |
|
|
651
|
+
| `EntityCollectionView` | The collection view component |
|
|
652
|
+
| `EntityView` | Entity detail/edit view |
|
|
653
|
+
| `EntityPreview` | Reference/relation preview chip |
|
|
654
|
+
| `EntityCard` | Card representation of an entity |
|
|
655
|
+
| `SideDialogs` | Side dialog container |
|
|
656
|
+
| `SideEntityProvider` | Context provider for side entity controller |
|
|
657
|
+
| `EntitySelectionTable` | Table for selecting entities |
|
|
658
|
+
| `Scaffold` | Layout scaffold component |
|
|
659
|
+
| `AppBar` | Top app bar |
|
|
660
|
+
| `Drawer` / `DefaultDrawer` | Sidebar drawer |
|
|
661
|
+
| `RebaseAuthGate` | Auth-gated wrapper |
|
|
662
|
+
| `RebaseNavigation` | Navigation provider |
|
|
663
|
+
| `RebaseLayout` | Layout wrapper |
|
|
664
|
+
| `RebaseRouteDefs` | Route definitions |
|
|
665
|
+
|
|
666
|
+
## Exported Hooks
|
|
667
|
+
|
|
668
|
+
| Hook | Description |
|
|
669
|
+
|------|-------------|
|
|
670
|
+
| `useSideEntityController()` | Open/close entity side panels |
|
|
671
|
+
| `useSideDialogsController()` | Open/close generic side dialogs |
|
|
672
|
+
| `useUrlController()` | Build URLs and navigate |
|
|
673
|
+
| `useNavigationStateController()` | Access navigation state |
|
|
674
|
+
| `useCollectionRegistryController()` | Look up collections by slug |
|
|
675
|
+
| `useBreadcrumbsController()` | Read/set breadcrumbs |
|
|
676
|
+
| `useCMSContext()` | Full CMS context (core + CMS controllers) |
|
|
677
|
+
| `useEntitySelectionDialog()` | Open entity selection dialog |
|
|
678
|
+
| `useSelectionController()` | Multi-select controller |
|
|
679
|
+
| `useEntityHistory()` | Entity version history |
|
|
680
|
+
| `useApp()` | App-level utilities |
|
|
681
|
+
|
|
682
|
+
## Exported Utilities
|
|
683
|
+
|
|
684
|
+
| Utility | Description |
|
|
685
|
+
|---------|-------------|
|
|
686
|
+
| `addInitialSlash(path)` | Ensure path starts with `/` |
|
|
687
|
+
| `removeInitialSlash(path)` | Strip leading `/` |
|
|
688
|
+
| `removeTrailingSlash(path)` | Strip trailing `/` |
|
|
689
|
+
| `removeInitialAndTrailingSlashes(path)` | Strip both |
|
|
690
|
+
| `getLastSegment(path)` | Get last path segment |
|
|
691
|
+
| `getCollectionBySlugWithin(collections, slug)` | Find collection in array |
|
|
692
|
+
| `mergeEntityActions(...)` | Merge entity action arrays |
|
|
693
|
+
| `resolveEntityAction(...)` | Resolve an entity action |
|
|
694
|
+
| `resolveEntityView(...)` | Resolve an entity view |
|
|
695
|
+
| `isReferenceProperty(prop)` | Check if property is a reference |
|
|
696
|
+
| `isRelationProperty(prop)` | Check if property is a relation |
|
|
697
|
+
| `getIconForProperty(prop)` | Get icon for a property type |
|
|
698
|
+
|
|
699
|
+
## Built-in Entity Actions
|
|
700
|
+
|
|
701
|
+
```typescript
|
|
702
|
+
import {
|
|
703
|
+
editEntityAction,
|
|
704
|
+
copyEntityAction,
|
|
705
|
+
deleteEntityAction,
|
|
706
|
+
resetPasswordAction
|
|
707
|
+
} from "@rebasepro/admin";
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
These are pre-built `EntityAction` objects that can be added to a collection's `entityActions` array.
|