@rebasepro/cms-types 0.17.0-canary.0
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/LICENSE +21 -0
- package/dist/admin_collection.d.ts +650 -0
- package/dist/augment.d.ts +81 -0
- package/dist/collections.d.ts +282 -0
- package/dist/controllers/analytics_controller.d.ts +7 -0
- package/dist/controllers/auth.d.ts +111 -0
- package/dist/controllers/customization_controller.d.ts +69 -0
- package/dist/controllers/dialogs_controller.d.ts +36 -0
- package/dist/controllers/index.d.ts +10 -0
- package/dist/controllers/local_config_persistence.d.ts +20 -0
- package/dist/controllers/navigation.d.ts +248 -0
- package/dist/controllers/registry.d.ts +96 -0
- package/dist/controllers/side_dialogs_controller.d.ts +67 -0
- package/dist/controllers/side_panel_controller.d.ts +97 -0
- package/dist/controllers/snackbar.d.ts +45 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.es.js +154 -0
- package/dist/index.es.js.map +1 -0
- package/dist/react_component_ref.d.ts +43 -0
- package/dist/rebase_context.d.ts +68 -0
- package/dist/types/breadcrumbs.d.ts +15 -0
- package/dist/types/builders.d.ts +15 -0
- package/dist/types/collection_views.d.ts +105 -0
- package/dist/types/component_overrides.d.ts +196 -0
- package/dist/types/entity_actions.d.ts +112 -0
- package/dist/types/entity_display.d.ts +148 -0
- package/dist/types/entity_link_builder.d.ts +7 -0
- package/dist/types/entity_views.d.ts +115 -0
- package/dist/types/export_import.d.ts +21 -0
- package/dist/types/form_layout.d.ts +126 -0
- package/dist/types/formex.d.ts +40 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/locales.d.ts +4 -0
- package/dist/types/modify_collections.d.ts +5 -0
- package/dist/types/plugins.d.ts +277 -0
- package/dist/types/property_config.d.ts +74 -0
- package/dist/types/property_options.d.ts +255 -0
- package/dist/types/slots.d.ts +279 -0
- package/dist/types/translations.d.ts +989 -0
- package/dist/types/user_management_delegate.d.ts +22 -0
- package/package.json +103 -0
- package/src/admin_collection.ts +775 -0
- package/src/augment.ts +79 -0
- package/src/collections.ts +312 -0
- package/src/controllers/analytics_controller.tsx +57 -0
- package/src/controllers/auth.ts +122 -0
- package/src/controllers/customization_controller.tsx +81 -0
- package/src/controllers/dialogs_controller.tsx +37 -0
- package/src/controllers/index.ts +10 -0
- package/src/controllers/local_config_persistence.tsx +22 -0
- package/src/controllers/navigation.ts +288 -0
- package/src/controllers/registry.ts +114 -0
- package/src/controllers/side_dialogs_controller.tsx +82 -0
- package/src/controllers/side_panel_controller.tsx +112 -0
- package/src/controllers/snackbar.ts +51 -0
- package/src/index.ts +20 -0
- package/src/react_component_ref.ts +52 -0
- package/src/rebase_context.ts +81 -0
- package/src/types/breadcrumbs.ts +16 -0
- package/src/types/builders.ts +18 -0
- package/src/types/collection_views.tsx +125 -0
- package/src/types/component_overrides.ts +244 -0
- package/src/types/entity_actions.tsx +134 -0
- package/src/types/entity_display.ts +182 -0
- package/src/types/entity_link_builder.ts +8 -0
- package/src/types/entity_views.tsx +135 -0
- package/src/types/export_import.ts +26 -0
- package/src/types/form_layout.ts +137 -0
- package/src/types/formex.ts +45 -0
- package/src/types/index.ts +18 -0
- package/src/types/locales.ts +81 -0
- package/src/types/modify_collections.tsx +6 -0
- package/src/types/plugins.tsx +346 -0
- package/src/types/property_config.tsx +97 -0
- package/src/types/property_options.ts +300 -0
- package/src/types/slots.tsx +334 -0
- package/src/types/translations.ts +1104 -0
- package/src/types/user_management_delegate.ts +23 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-property presentation options.
|
|
3
|
+
*
|
|
4
|
+
* These lived in `@rebasepro/types` next to the property types they belong to, which
|
|
5
|
+
* meant a BaaS install shipped `Field`, `Preview`, `columnWidth` and `hideFromCollection`
|
|
6
|
+
* in its type surface with nothing to render them. They are attached to the property
|
|
7
|
+
* types by `augment.ts` instead.
|
|
8
|
+
*/
|
|
9
|
+
import type { ComponentRef, FilterValues, WhereFilterOp } from "@rebasepro/types";
|
|
10
|
+
import { ADMIN_PROPERTY_KEYS as CORE_ADMIN_PROPERTY_KEYS } from "@rebasepro/types";
|
|
11
|
+
import type { PropertySpan } from "./form_layout";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Interface including all common properties of an admin property.
|
|
15
|
+
* @group Entity properties
|
|
16
|
+
*/
|
|
17
|
+
export interface AdminPropertyOptions<CustomProps = unknown> {
|
|
18
|
+
columnWidth?: number;
|
|
19
|
+
hideFromCollection?: boolean;
|
|
20
|
+
readOnly?: boolean;
|
|
21
|
+
disabled?: boolean | PropertyDisabledConfig;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* How many of the form grid's {@link FORM_GRID_COLUMNS} columns this field
|
|
25
|
+
* occupies. Omit to let the layout derive one from the property type.
|
|
26
|
+
*
|
|
27
|
+
* Spans snap to a shared grid, so two fields line up whatever order they
|
|
28
|
+
* are declared in.
|
|
29
|
+
*/
|
|
30
|
+
span?: PropertySpan;
|
|
31
|
+
customProps?: CustomProps;
|
|
32
|
+
Field?: ComponentRef<any>;
|
|
33
|
+
Preview?: ComponentRef<any>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Narrow the filter operators offered for this property in collection
|
|
37
|
+
* filter UIs (table header filters and the Filters dialog).
|
|
38
|
+
*
|
|
39
|
+
* The final offered set is the **intersection** of the engine's
|
|
40
|
+
* capabilities, the property-type defaults, and this list — you can only
|
|
41
|
+
* *restrict*, never enable an operator the underlying engine cannot run.
|
|
42
|
+
*
|
|
43
|
+
* Pass an empty array to disable filtering on this property entirely.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // Email column: exact match, contains, and null check only
|
|
47
|
+
* admin: { filterOperators: ["==", "ilike", "is-null"] }
|
|
48
|
+
*/
|
|
49
|
+
filterOperators?: readonly WhereFilterOp[];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Replace the filter field rendered for this property in collection
|
|
53
|
+
* filter UIs. The component receives `FilterFieldBindingProps`
|
|
54
|
+
* (property, resolved `operators`, `value`, `setValue`, …).
|
|
55
|
+
*
|
|
56
|
+
* Takes precedence over the collection-level
|
|
57
|
+
* `components["Collection.FilterField"]` override and the built-in
|
|
58
|
+
* per-type filter fields.
|
|
59
|
+
*/
|
|
60
|
+
Filter?: ComponentRef<any>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @group Entity properties
|
|
65
|
+
*/
|
|
66
|
+
export interface AdminStringOptions extends AdminPropertyOptions {
|
|
67
|
+
/**
|
|
68
|
+
* Is this string property long enough so it should be displayed in
|
|
69
|
+
* a multiple line field. Defaults to false. If set to true,
|
|
70
|
+
* the number of lines adapts to the content
|
|
71
|
+
*/
|
|
72
|
+
multiline?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Should this string property be displayed as a markdown field. If true,
|
|
75
|
+
* the field is rendered as a text editor that supports markdown highlight
|
|
76
|
+
* syntax. It also includes a preview of the result.
|
|
77
|
+
*/
|
|
78
|
+
markdown?: boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Should this string be rendered as a tag instead of just text.
|
|
81
|
+
*/
|
|
82
|
+
previewAsTag?: boolean;
|
|
83
|
+
clearable?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* How to render a string that holds a URL: a link, or one of the supported
|
|
86
|
+
* media types for an inline preview.
|
|
87
|
+
*
|
|
88
|
+
* Only presentation. Whether the string *is* a URL is `url` on the property
|
|
89
|
+
* itself, which is what the OpenAPI contract is generated from.
|
|
90
|
+
*/
|
|
91
|
+
urlPreview?: PreviewType;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* How a number is written out for reading.
|
|
96
|
+
*
|
|
97
|
+
* A thin, explicit subset of `Intl.NumberFormatOptions`. Explicit is the whole
|
|
98
|
+
* point: nothing here is inferred. A collection that happens to carry a
|
|
99
|
+
* `currency` column alongside a `total` column has not told us that one formats
|
|
100
|
+
* the other — that is a relationship only the author knows, and guessing it
|
|
101
|
+
* would put a euro sign on the one number that was never money.
|
|
102
|
+
*
|
|
103
|
+
* Presentation only. It changes what {@link PropertyPreview} renders — the
|
|
104
|
+
* detail view, the table cell, a reference card — and never what the number
|
|
105
|
+
* input holds, because a formatted string is not a number you can type into.
|
|
106
|
+
*/
|
|
107
|
+
export interface NumberFormatOptions {
|
|
108
|
+
/** Defaults to `"decimal"`. `"currency"` requires {@link currency}. */
|
|
109
|
+
style?: "decimal" | "currency" | "percent";
|
|
110
|
+
/**
|
|
111
|
+
* ISO 4217 code — `"EUR"`, `"USD"`. Setting it implies `style: "currency"`,
|
|
112
|
+
* so the common case is one key.
|
|
113
|
+
*/
|
|
114
|
+
currency?: string;
|
|
115
|
+
/**
|
|
116
|
+
* BCP 47 tag. Defaults to the panel's locale, which is what makes the same
|
|
117
|
+
* amount read `1,234.50` for one user and `1.234,50` for another.
|
|
118
|
+
*/
|
|
119
|
+
locale?: string;
|
|
120
|
+
minimumFractionDigits?: number;
|
|
121
|
+
maximumFractionDigits?: number;
|
|
122
|
+
/** `"compact"` renders `12000` as `12K`. Useful in narrow table columns. */
|
|
123
|
+
notation?: "standard" | "compact";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @group Entity properties
|
|
128
|
+
*/
|
|
129
|
+
export interface AdminNumberOptions extends AdminPropertyOptions {
|
|
130
|
+
clearable?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Write this number out as currency, a percentage, or with fixed decimals.
|
|
133
|
+
* Omit and the raw value renders, which stays the default: a number in the
|
|
134
|
+
* database is shown as the number in the database.
|
|
135
|
+
*/
|
|
136
|
+
format?: NumberFormatOptions;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @group Entity properties
|
|
141
|
+
*/
|
|
142
|
+
export interface AdminVectorOptions extends AdminPropertyOptions {
|
|
143
|
+
clearable?: boolean;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @group Entity properties
|
|
148
|
+
*/
|
|
149
|
+
export interface AdminDateOptions extends AdminPropertyOptions {
|
|
150
|
+
/**
|
|
151
|
+
* Add an icon to clear the value and set it to `null`. Defaults to `false`
|
|
152
|
+
*/
|
|
153
|
+
clearable?: boolean;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @group Entity properties
|
|
158
|
+
*/
|
|
159
|
+
export interface AdminReferenceOptions extends AdminPropertyOptions {
|
|
160
|
+
previewProperties?: string[];
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Offer only entities that pass this filter in the selection dialog.
|
|
164
|
+
* e.g. `fixedFilter: { age: [">=", 18] }`
|
|
165
|
+
*/
|
|
166
|
+
fixedFilter?: FilterValues<string>;
|
|
167
|
+
|
|
168
|
+
/** Show the referenced entity's id in previews. Defaults to `true`. */
|
|
169
|
+
includeId?: boolean;
|
|
170
|
+
|
|
171
|
+
/** Show a link that opens the referenced entity. Defaults to `true`. */
|
|
172
|
+
includeEntityLink?: boolean;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @group Entity properties
|
|
177
|
+
*/
|
|
178
|
+
export interface AdminRelationOptions extends AdminPropertyOptions {
|
|
179
|
+
previewProperties?: string[];
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Which widget selects the related entity. Defaults to `select`.
|
|
183
|
+
*/
|
|
184
|
+
widget?: "select" | "dialog";
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Offer only entities that pass this filter in the selection widget.
|
|
188
|
+
* e.g. `fixedFilter: { age: [">=", 18] }`
|
|
189
|
+
*/
|
|
190
|
+
fixedFilter?: FilterValues<string>;
|
|
191
|
+
|
|
192
|
+
/** Show the related entity's id in previews. Defaults to `true`. */
|
|
193
|
+
includeId?: boolean;
|
|
194
|
+
|
|
195
|
+
/** Show a link that opens the related entity. Defaults to `true`. */
|
|
196
|
+
includeEntityLink?: boolean;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Render a **many**-relation as a picker inside the entity form as well as
|
|
200
|
+
* the tab it already gets. Defaults to `false`.
|
|
201
|
+
*
|
|
202
|
+
* The entity view lists a many-relation's rows as a tab, which is the whole
|
|
203
|
+
* treatment: the child rows are a list, not a value the form holds. This
|
|
204
|
+
* flag exists for the project that wants the inline picker anyway — it is
|
|
205
|
+
* off by default because the two surfaces are redundant by construction.
|
|
206
|
+
*
|
|
207
|
+
* No effect on a to-one relation: a foreign key gets no tab, so its picker
|
|
208
|
+
* is always rendered.
|
|
209
|
+
*/
|
|
210
|
+
renderInForm?: boolean;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* @group Entity properties
|
|
215
|
+
*/
|
|
216
|
+
export interface AdminArrayOptions extends AdminPropertyOptions {
|
|
217
|
+
expanded?: boolean;
|
|
218
|
+
minimalistView?: boolean;
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Can the elements in this array be reordered by dragging. Defaults to
|
|
222
|
+
* `true`. No effect when the property is disabled.
|
|
223
|
+
*/
|
|
224
|
+
sortable?: boolean;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Can elements be added to this array. Defaults to `true`. No effect when
|
|
228
|
+
* the property is disabled.
|
|
229
|
+
*/
|
|
230
|
+
canAddElements?: boolean;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @group Entity properties
|
|
235
|
+
*/
|
|
236
|
+
export interface AdminMapOptions extends AdminPropertyOptions {
|
|
237
|
+
expanded?: boolean;
|
|
238
|
+
minimalistView?: boolean;
|
|
239
|
+
spreadChildren?: boolean;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Which of the map's own properties are shown when it is rendered as a
|
|
243
|
+
* preview. Defaults to all of them, in `propertiesOrder`.
|
|
244
|
+
*/
|
|
245
|
+
previewProperties?: string[];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @group Entity properties
|
|
250
|
+
*/
|
|
251
|
+
export interface PropertyDisabledConfig {
|
|
252
|
+
/**
|
|
253
|
+
* Enable this flag if you would like to clear the value of the field
|
|
254
|
+
* when the corresponding property gets disabled.
|
|
255
|
+
*
|
|
256
|
+
* This is useful for keeping data consistency when you have conditional
|
|
257
|
+
* properties.
|
|
258
|
+
*/
|
|
259
|
+
clearOnDisabled?: boolean;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Explanation of why this property is disabled (e.g. a different field
|
|
263
|
+
* needs to be enabled)
|
|
264
|
+
*/
|
|
265
|
+
disabledMessage?: string;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Set this flag to true if you want to hide this field when disabled
|
|
269
|
+
*/
|
|
270
|
+
hidden?: boolean;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Used for previewing urls if the download file is known
|
|
275
|
+
* @group Entity properties
|
|
276
|
+
*/
|
|
277
|
+
export type PreviewType = "image" | "video" | "audio" | "file";
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Every key any property `admin` block accepts, across the base options and the
|
|
281
|
+
* per-type extensions.
|
|
282
|
+
*/
|
|
283
|
+
type AnyAdminPropertyOptionKey =
|
|
284
|
+
| keyof AdminPropertyOptions
|
|
285
|
+
| keyof AdminStringOptions
|
|
286
|
+
| keyof AdminNumberOptions
|
|
287
|
+
| keyof AdminVectorOptions
|
|
288
|
+
| keyof AdminDateOptions
|
|
289
|
+
| keyof AdminReferenceOptions
|
|
290
|
+
| keyof AdminRelationOptions
|
|
291
|
+
| keyof AdminArrayOptions
|
|
292
|
+
| keyof AdminMapOptions;
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Core's list, re-exported through the same `satisfies` agreement check that
|
|
296
|
+
* {@link ADMIN_COLLECTION_KEYS} gets: core owns the data because the boot-time
|
|
297
|
+
* collection validator in `@rebasepro/server` needs it and may not import this
|
|
298
|
+
* package, and this clause is what stops the data from drifting off the types.
|
|
299
|
+
*/
|
|
300
|
+
export const ADMIN_PROPERTY_KEYS = CORE_ADMIN_PROPERTY_KEYS satisfies readonly AnyAdminPropertyOptionKey[];
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
import type { CollectionActionsProps, EntityTableController, SelectionController } from "../collections";
|
|
4
|
+
import type { Entity } from "@rebasepro/types";
|
|
5
|
+
import type { PluginFormActionProps, PluginGenericProps, PluginHomePageActionsProps, PluginHomePageAdditionalCardsProps } from "./plugins";
|
|
6
|
+
import type { Property } from "@rebasepro/types";
|
|
7
|
+
import type { RebaseContext } from "../rebase_context";
|
|
8
|
+
import type { AdminCollection } from "@rebasepro/cms-types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Registry mapping slot names to their component prop types.
|
|
12
|
+
* Each key represents a UI extension point in the admin.
|
|
13
|
+
* @group Plugins
|
|
14
|
+
*/
|
|
15
|
+
export interface SlotRegistry {
|
|
16
|
+
// ── Home page ─────────────────────────────────────────────────────
|
|
17
|
+
"home.actions": PluginGenericProps;
|
|
18
|
+
"home.cards": PluginHomePageAdditionalCardsProps;
|
|
19
|
+
"home.children.start": PluginGenericProps;
|
|
20
|
+
"home.children.end": PluginGenericProps;
|
|
21
|
+
/** Compact widget rendered inline in a home page collection card. */
|
|
22
|
+
"home.card.widget": HomeCardWidgetSlotProps;
|
|
23
|
+
"home.collection.actions": PluginHomePageActionsProps;
|
|
24
|
+
|
|
25
|
+
// ── Navigation / Drawer ───────────────────────────────────────────
|
|
26
|
+
/** Rendered below the logo in the sidebar drawer. */
|
|
27
|
+
"navigation.header": NavigationSlotProps;
|
|
28
|
+
/** Rendered above the collapse toggle at the bottom of the drawer. */
|
|
29
|
+
"navigation.footer": NavigationSlotProps;
|
|
30
|
+
|
|
31
|
+
// ── Collection view ───────────────────────────────────────────────
|
|
32
|
+
"collection.actions": CollectionActionsProps;
|
|
33
|
+
"collection.actions.start": CollectionActionsProps;
|
|
34
|
+
"collection.header.action": CollectionHeaderActionProps;
|
|
35
|
+
"collection.add-column": CollectionAddColumnProps;
|
|
36
|
+
"collection.error": CollectionErrorProps;
|
|
37
|
+
/** Extra widgets rendered inside the collection toolbar row. */
|
|
38
|
+
"collection.toolbar": CollectionToolbarProps;
|
|
39
|
+
/** Custom empty-state component when a collection has no data. */
|
|
40
|
+
"collection.empty-state": CollectionEmptyStateProps;
|
|
41
|
+
/** Widgets rendered above the collection table. */
|
|
42
|
+
"collection.widgets": CollectionWidgetsSlotProps;
|
|
43
|
+
|
|
44
|
+
// ── Entity / Form ─────────────────────────────────────────────────
|
|
45
|
+
"form.actions": PluginFormActionProps;
|
|
46
|
+
"form.actions.top": PluginFormActionProps;
|
|
47
|
+
/** Rendered before the form title / field list. */
|
|
48
|
+
"form.before": PluginFormActionProps;
|
|
49
|
+
/** Rendered after the form field list. */
|
|
50
|
+
"form.after": PluginFormActionProps;
|
|
51
|
+
|
|
52
|
+
// ── Entity row actions ────────────────────────────────────────────
|
|
53
|
+
/** Per-row actions in entity tables (e.g. bulk actions, row context menus). */
|
|
54
|
+
"entity.row.actions": EntityRowActionsProps;
|
|
55
|
+
|
|
56
|
+
// ── Entity field decoration ───────────────────────────────────────
|
|
57
|
+
/** Inject UI before an individual form field. */
|
|
58
|
+
"entity.field.before": EntityFieldSlotProps;
|
|
59
|
+
/** Inject UI after an individual form field. */
|
|
60
|
+
"entity.field.after": EntityFieldSlotProps;
|
|
61
|
+
|
|
62
|
+
// ── Collection filter panel ───────────────────────────────────────
|
|
63
|
+
/** Custom filter sidebar for a collection. */
|
|
64
|
+
"collection.filter-panel": CollectionFilterPanelProps;
|
|
65
|
+
|
|
66
|
+
// ── Dashboard ─────────────────────────────────────────────────────
|
|
67
|
+
/** Widget rendered on the dashboard / home page. */
|
|
68
|
+
"dashboard.widget": DashboardWidgetProps;
|
|
69
|
+
|
|
70
|
+
// ── Global ────────────────────────────────────────────────────────
|
|
71
|
+
/** Cross-collection search bar component. */
|
|
72
|
+
"global.search": GlobalSearchProps;
|
|
73
|
+
/** Top-level toolbar actions rendered in the shell toolbar area. */
|
|
74
|
+
"shell.toolbar": ShellToolbarProps;
|
|
75
|
+
|
|
76
|
+
// ── Kanban ────────────────────────────────────────────────────────
|
|
77
|
+
"kanban.setup": KanbanSetupProps;
|
|
78
|
+
"kanban.add-column": KanbanAddColumnProps;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Valid slot names for UI extension points.
|
|
83
|
+
* @group Plugins
|
|
84
|
+
*/
|
|
85
|
+
/**
|
|
86
|
+
* Slots this build declares but renders nowhere.
|
|
87
|
+
*
|
|
88
|
+
* Every name here appears in {@link SlotRegistry}, has a props interface, and
|
|
89
|
+
* is listed in the public slot reference alongside the ones that work — so a
|
|
90
|
+
* plugin author picks one off the table, registers a component, sees nothing,
|
|
91
|
+
* and has no way to tell whether the fault is theirs. Seven of twenty-nine were
|
|
92
|
+
* in that state.
|
|
93
|
+
*
|
|
94
|
+
* This is a statement of fact, not a wish list: `slot-render-sites.test.ts`
|
|
95
|
+
* derives the same set by scanning for render sites and fails when the two
|
|
96
|
+
* disagree. Implementing a slot therefore forces its removal from here, and
|
|
97
|
+
* declaring one without rendering it forces its addition — at which point
|
|
98
|
+
* `Rebase` warns anyone who registers for it, which is the whole point.
|
|
99
|
+
*/
|
|
100
|
+
export const UNRENDERED_SLOTS = [
|
|
101
|
+
"collection.filter-panel",
|
|
102
|
+
"dashboard.widget",
|
|
103
|
+
"entity.field.after",
|
|
104
|
+
"entity.field.before",
|
|
105
|
+
"entity.row.actions",
|
|
106
|
+
"global.search",
|
|
107
|
+
"shell.toolbar"
|
|
108
|
+
] as const satisfies readonly (keyof SlotRegistry)[];
|
|
109
|
+
|
|
110
|
+
export type SlotName = keyof SlotRegistry;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* A single UI component contribution to a named slot.
|
|
114
|
+
* @group Plugins
|
|
115
|
+
*/
|
|
116
|
+
export interface SlotContribution<K extends SlotName = SlotName> {
|
|
117
|
+
/**
|
|
118
|
+
* Which slot to contribute to.
|
|
119
|
+
*/
|
|
120
|
+
slot: K;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The component to render in the slot.
|
|
124
|
+
* Typed loosely so mixed-slot arrays work.
|
|
125
|
+
* Type safety is provided at the `useSlot` call site.
|
|
126
|
+
*/
|
|
127
|
+
Component: React.ComponentType<any>;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Additional props to merge into the slot props before rendering.
|
|
131
|
+
*/
|
|
132
|
+
props?: Record<string, unknown>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Ordering hint. Lower values render first. Defaults to 50.
|
|
136
|
+
*/
|
|
137
|
+
order?: number;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// ── Prop interfaces for slots ─────────────────────────────────────────
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Props for `navigation.header` and `navigation.footer` slots.
|
|
144
|
+
* @group Plugins
|
|
145
|
+
*/
|
|
146
|
+
export interface NavigationSlotProps {
|
|
147
|
+
drawerOpen: boolean;
|
|
148
|
+
drawerHovered: boolean;
|
|
149
|
+
context: RebaseContext;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Props for the `collection.toolbar` slot.
|
|
154
|
+
* @group Plugins
|
|
155
|
+
*/
|
|
156
|
+
export interface CollectionToolbarProps {
|
|
157
|
+
path: string;
|
|
158
|
+
collection: AdminCollection;
|
|
159
|
+
parentCollectionSlugs: string[];
|
|
160
|
+
parentEntityIds: string[];
|
|
161
|
+
tableController: EntityTableController;
|
|
162
|
+
selectionController: SelectionController;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Props for the `collection.empty-state` slot.
|
|
167
|
+
* @group Plugins
|
|
168
|
+
*/
|
|
169
|
+
export interface CollectionEmptyStateProps {
|
|
170
|
+
path: string;
|
|
171
|
+
collection: AdminCollection;
|
|
172
|
+
parentCollectionSlugs: string[];
|
|
173
|
+
parentEntityIds: string[];
|
|
174
|
+
canCreate: boolean;
|
|
175
|
+
onNewClick?: () => void;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Props for the `collection.header.action` slot.
|
|
180
|
+
* @group Plugins
|
|
181
|
+
*/
|
|
182
|
+
export interface CollectionHeaderActionProps {
|
|
183
|
+
property: Property;
|
|
184
|
+
propertyKey: string;
|
|
185
|
+
path: string;
|
|
186
|
+
parentCollectionSlugs: string[];
|
|
187
|
+
parentEntityIds: string[];
|
|
188
|
+
onHover: boolean;
|
|
189
|
+
collection: AdminCollection;
|
|
190
|
+
tableController: EntityTableController;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Props for the `collection.add-column` slot.
|
|
195
|
+
* @group Plugins
|
|
196
|
+
*/
|
|
197
|
+
export interface CollectionAddColumnProps {
|
|
198
|
+
path: string;
|
|
199
|
+
parentCollectionSlugs: string[];
|
|
200
|
+
parentEntityIds: string[];
|
|
201
|
+
collection: AdminCollection;
|
|
202
|
+
tableController: EntityTableController;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Props for the `collection.error` slot.
|
|
207
|
+
* @group Plugins
|
|
208
|
+
*/
|
|
209
|
+
export interface CollectionErrorProps {
|
|
210
|
+
path: string;
|
|
211
|
+
collection: AdminCollection;
|
|
212
|
+
parentCollectionSlugs?: string[];
|
|
213
|
+
parentEntityIds?: string[];
|
|
214
|
+
error: Error;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Props for the `kanban.setup` slot.
|
|
219
|
+
* @group Plugins
|
|
220
|
+
*/
|
|
221
|
+
export interface KanbanSetupProps {
|
|
222
|
+
collection: AdminCollection;
|
|
223
|
+
fullPath: string;
|
|
224
|
+
parentCollectionSlugs: string[];
|
|
225
|
+
parentEntityIds: string[];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Props for the `kanban.add-column` slot.
|
|
230
|
+
* @group Plugins
|
|
231
|
+
*/
|
|
232
|
+
export interface KanbanAddColumnProps {
|
|
233
|
+
collection: AdminCollection;
|
|
234
|
+
fullPath: string;
|
|
235
|
+
parentCollectionSlugs: string[];
|
|
236
|
+
parentEntityIds: string[];
|
|
237
|
+
columnProperty: string;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ── New slot prop interfaces ──────────────────────────────────────────
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Props for `entity.row.actions` slot.
|
|
244
|
+
* Rendered for each row in a entity collection table.
|
|
245
|
+
* @group Plugins
|
|
246
|
+
*/
|
|
247
|
+
export interface EntityRowActionsProps {
|
|
248
|
+
entity: Entity;
|
|
249
|
+
entityId: string;
|
|
250
|
+
path: string;
|
|
251
|
+
collection: AdminCollection;
|
|
252
|
+
parentCollectionSlugs: string[];
|
|
253
|
+
parentEntityIds: string[];
|
|
254
|
+
selectionController: SelectionController;
|
|
255
|
+
context: RebaseContext;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Props for `entity.field.before` and `entity.field.after` slots.
|
|
260
|
+
* Rendered around individual form fields in the entity edit view.
|
|
261
|
+
* @group Plugins
|
|
262
|
+
*/
|
|
263
|
+
export interface EntityFieldSlotProps {
|
|
264
|
+
propertyKey: string;
|
|
265
|
+
property: Property;
|
|
266
|
+
path: string;
|
|
267
|
+
entityId?: string | number;
|
|
268
|
+
collection: AdminCollection;
|
|
269
|
+
context: RebaseContext;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Props for `collection.filter-panel` slot.
|
|
274
|
+
* Custom filter sidebar rendered alongside the collection table.
|
|
275
|
+
* @group Plugins
|
|
276
|
+
*/
|
|
277
|
+
export interface CollectionFilterPanelProps {
|
|
278
|
+
path: string;
|
|
279
|
+
collection: AdminCollection;
|
|
280
|
+
parentCollectionSlugs: string[];
|
|
281
|
+
parentEntityIds: string[];
|
|
282
|
+
tableController: EntityTableController;
|
|
283
|
+
context: RebaseContext;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Props for `dashboard.widget` slot.
|
|
288
|
+
* Widgets rendered on the home / dashboard page.
|
|
289
|
+
* @group Plugins
|
|
290
|
+
*/
|
|
291
|
+
export interface DashboardWidgetProps {
|
|
292
|
+
context: RebaseContext;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Props for `global.search` slot.
|
|
297
|
+
* Cross-collection search bar rendered in the app shell.
|
|
298
|
+
* @group Plugins
|
|
299
|
+
*/
|
|
300
|
+
export interface GlobalSearchProps {
|
|
301
|
+
context: RebaseContext;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Props for `shell.toolbar` slot.
|
|
306
|
+
* Actions rendered in the top-level toolbar / app bar area.
|
|
307
|
+
* @group Plugins
|
|
308
|
+
*/
|
|
309
|
+
export interface ShellToolbarProps {
|
|
310
|
+
context: RebaseContext;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Props for `collection.widgets` slot.
|
|
315
|
+
* Widgets rendered above the collection table.
|
|
316
|
+
* @group Plugins
|
|
317
|
+
*/
|
|
318
|
+
export interface CollectionWidgetsSlotProps {
|
|
319
|
+
path: string;
|
|
320
|
+
collection: AdminCollection;
|
|
321
|
+
parentCollectionSlugs: string[];
|
|
322
|
+
parentEntityIds: string[];
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Props for `home.card.widget` slot.
|
|
327
|
+
* Compact widget rendered inline in a home page collection card.
|
|
328
|
+
* @group Plugins
|
|
329
|
+
*/
|
|
330
|
+
export interface HomeCardWidgetSlotProps {
|
|
331
|
+
slug: string;
|
|
332
|
+
collection: AdminCollection;
|
|
333
|
+
context: RebaseContext;
|
|
334
|
+
}
|