@rebasepro/admin 0.6.1 → 0.7.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.
Files changed (134) hide show
  1. package/dist/{CollectionEditorDialog-HNXGxXdO.js → CollectionEditorDialog-iGgS4rLX.js} +233 -152
  2. package/dist/CollectionEditorDialog-iGgS4rLX.js.map +1 -0
  3. package/dist/{PropertyEditView-C2wp8kQ9.js → PropertyEditView-C9yhLyja.js} +129 -15
  4. package/dist/PropertyEditView-C9yhLyja.js.map +1 -0
  5. package/dist/{CollectionsStudioView-B1mN33GB.js → RouterCollectionsStudioView-Dqx27GD8.js} +61 -39
  6. package/dist/RouterCollectionsStudioView-Dqx27GD8.js.map +1 -0
  7. package/dist/collection_editor/extensibility_types.d.ts +135 -0
  8. package/dist/collection_editor/index.d.ts +6 -0
  9. package/dist/collection_editor/serializable_types.d.ts +374 -0
  10. package/dist/collection_editor/serializable_utils.d.ts +50 -0
  11. package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +2 -1
  12. package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +12 -1
  13. package/dist/collection_editor/ui/collection_editor/CollectionStudioView.d.ts +13 -1
  14. package/dist/collection_editor/ui/collection_editor/CollectionsStudioView.d.ts +24 -2
  15. package/dist/collection_editor/ui/collection_editor/DisplaySettingsForm.d.ts +2 -1
  16. package/dist/collection_editor/ui/collection_editor/GeneralSettingsForm.d.ts +4 -1
  17. package/dist/collection_editor/ui/collection_editor/PropertyEditView.d.ts +12 -1
  18. package/dist/collection_editor/ui/collection_editor/RouterCollectionStudioView.d.ts +15 -0
  19. package/dist/collection_editor/ui/collection_editor/RouterCollectionsStudioView.d.ts +14 -0
  20. package/dist/collection_editor/useJsonCollectionsConfigController.d.ts +37 -0
  21. package/dist/collection_editor/useSafeSnackbarController.d.ts +2 -0
  22. package/dist/collection_editor_ui.d.ts +4 -0
  23. package/dist/collection_editor_ui.js +33 -4
  24. package/dist/collection_editor_ui.js.map +1 -0
  25. package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +3 -3
  26. package/dist/components/EntityCollectionView/hooks/useKanbanDragAndDrop.d.ts +3 -3
  27. package/dist/components/EntityEditView.d.ts +3 -2
  28. package/dist/components/RebaseCMS.d.ts +1 -1
  29. package/dist/form/EntityForm.d.ts +10 -9
  30. package/dist/form/EntityFormBinding.d.ts +27 -0
  31. package/dist/form/form_utils.d.ts +8 -0
  32. package/dist/form/index.d.ts +5 -1
  33. package/dist/{history-BO6VT85a.js → history-ChHgyyvM.js} +2 -2
  34. package/dist/{history-BO6VT85a.js.map → history-ChHgyyvM.js.map} +1 -1
  35. package/dist/hooks/navigation/contexts/CollectionRegistryContext.d.ts +1 -1
  36. package/dist/hooks/navigation/useAsyncResolver.d.ts +26 -0
  37. package/dist/hooks/navigation/useBuildCollectionRegistryController.d.ts +2 -0
  38. package/dist/hooks/navigation/useTopLevelNavigation.d.ts +1 -1
  39. package/dist/hooks/navigation/utils.d.ts +1 -1
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.js +2 -2
  42. package/dist/routes/CustomViewRoute.d.ts +2 -1
  43. package/dist/{src-BYniefVu.js → src-DOX2nOyh.js} +1586 -1283
  44. package/dist/src-DOX2nOyh.js.map +1 -0
  45. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  46. package/dist/types/components/EntityFormProps.d.ts +59 -0
  47. package/dist/types/fields.d.ts +6 -1
  48. package/dist/util/dataControllerAdapter.d.ts +30 -0
  49. package/dist/util/navigation_utils.d.ts +1 -1
  50. package/dist/util/propertyConfigMapper.d.ts +17 -0
  51. package/package.json +18 -18
  52. package/src/collection_editor/extensibility_types.ts +168 -0
  53. package/src/collection_editor/index.ts +46 -0
  54. package/src/collection_editor/serializable_types.ts +487 -0
  55. package/src/collection_editor/serializable_utils.ts +588 -0
  56. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +4 -4
  57. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +134 -70
  58. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +95 -78
  59. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +23 -20
  60. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +79 -27
  61. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +9 -7
  62. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +22 -5
  63. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +3 -3
  64. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +155 -10
  65. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +6 -6
  66. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +1 -0
  67. package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +44 -0
  68. package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +41 -0
  69. package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +4 -3
  70. package/src/collection_editor/useJsonCollectionsConfigController.tsx +286 -0
  71. package/src/collection_editor/useSafeSnackbarController.ts +9 -0
  72. package/src/collection_editor_ui.ts +6 -0
  73. package/src/components/DefaultDrawer.tsx +13 -3
  74. package/src/components/DrawerNavigationGroup.tsx +2 -2
  75. package/src/components/EntityCollectionView/EntityBoardCard.tsx +6 -6
  76. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +12 -11
  77. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +40 -190
  78. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +54 -183
  79. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +6 -6
  80. package/src/components/EntityEditView.tsx +5 -4
  81. package/src/components/EntityEditViewFormActions.tsx +32 -26
  82. package/src/components/HomePage/ContentHomePage.tsx +13 -4
  83. package/src/components/RebaseCMS.tsx +3 -2
  84. package/src/components/RebaseNavigation.tsx +71 -7
  85. package/src/components/SelectableTable/SelectableTable.tsx +2 -2
  86. package/src/components/SideDialogs.tsx +0 -7
  87. package/src/components/common/default_entity_actions.tsx +9 -9
  88. package/src/contexts/BreacrumbsContext.tsx +15 -6
  89. package/src/editor/selectors/ai-selector.tsx +0 -1
  90. package/src/form/EntityForm.tsx +191 -428
  91. package/src/form/EntityFormActions.tsx +33 -47
  92. package/src/form/EntityFormBinding.tsx +323 -0
  93. package/src/form/components/FormLayout.tsx +1 -1
  94. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +7 -2
  95. package/src/form/form_utils.ts +163 -0
  96. package/src/form/index.tsx +14 -5
  97. package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +2 -2
  98. package/src/hooks/navigation/contexts/NavigationStateContext.tsx +2 -2
  99. package/src/hooks/navigation/contexts/UrlContext.tsx +1 -2
  100. package/src/hooks/navigation/useAsyncResolver.ts +100 -0
  101. package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +15 -8
  102. package/src/hooks/navigation/useBuildNavigationStateController.tsx +12 -8
  103. package/src/hooks/navigation/useNavigationResolution.ts +33 -0
  104. package/src/hooks/navigation/useResolvedCollections.ts +29 -71
  105. package/src/hooks/navigation/useResolvedViews.tsx +40 -70
  106. package/src/hooks/navigation/useTopLevelNavigation.ts +20 -16
  107. package/src/hooks/navigation/utils.ts +7 -4
  108. package/src/index.ts +5 -0
  109. package/src/routes/CustomViewRoute.tsx +14 -6
  110. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  111. package/src/types/components/EntityFormProps.tsx +68 -0
  112. package/src/types/fields.tsx +7 -1
  113. package/src/util/dataControllerAdapter.ts +93 -0
  114. package/src/util/navigation_utils.ts +1 -1
  115. package/src/util/propertyConfigMapper.ts +134 -0
  116. package/LICENSE +0 -21
  117. package/dist/CollectionEditorDialog-HNXGxXdO.js.map +0 -1
  118. package/dist/CollectionsStudioView-B1mN33GB.js.map +0 -1
  119. package/dist/PropertyEditView-C2wp8kQ9.js.map +0 -1
  120. package/dist/components/EntityCollectionView/Board.d.ts +0 -3
  121. package/dist/components/EntityCollectionView/BoardColumn.d.ts +0 -42
  122. package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +0 -9
  123. package/dist/components/EntityCollectionView/BoardSortableList.d.ts +0 -14
  124. package/dist/components/EntityCollectionView/board_types.d.ts +0 -105
  125. package/dist/hooks/navigation/useNavigationRegistry.d.ts +0 -12
  126. package/dist/hooks/navigation/useNavigationURLs.d.ts +0 -11
  127. package/dist/src-BYniefVu.js.map +0 -1
  128. package/src/components/EntityCollectionView/Board.tsx +0 -475
  129. package/src/components/EntityCollectionView/BoardColumn.tsx +0 -165
  130. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +0 -46
  131. package/src/components/EntityCollectionView/BoardSortableList.tsx +0 -177
  132. package/src/components/EntityCollectionView/board_types.ts +0 -113
  133. package/src/hooks/navigation/useNavigationRegistry.ts +0 -164
  134. package/src/hooks/navigation/useNavigationURLs.ts +0 -56
@@ -0,0 +1,374 @@
1
+ /**
2
+ * JSON-serializable versions of Rebase collection and property types.
3
+ *
4
+ * These types strip all non-serializable fields (functions, React nodes,
5
+ * class instances) from the original types in `@rebasepro/types`, making
6
+ * them safe for `JSON.stringify()` / database storage.
7
+ *
8
+ * Use `toSerializableCollection` / `fromSerializableCollection` from
9
+ * `./serializable_utils` to convert between the original and serializable forms.
10
+ *
11
+ * @module
12
+ */
13
+ import type { EnumValues, PropertyValidationSchema, NumberPropertyValidationSchema, ArrayPropertyValidationSchema, PropertyConditions, ImageResize, FileType } from "@rebasepro/types";
14
+ import type { ViewMode, CollectionSize, SecurityRule, FilterValues, FilterPreset, KanbanConfig, NavigationGroupMapping } from "@rebasepro/types";
15
+ import type { OnAction, JoinStep } from "@rebasepro/types";
16
+ /**
17
+ * JSON-serializable version of `BaseUIConfig`.
18
+ * Drops `Field` and `Preview` (ComponentRef — functions/components).
19
+ */
20
+ export interface SerializableBaseUIConfig {
21
+ columnWidth?: number;
22
+ hideFromCollection?: boolean;
23
+ readOnly?: boolean;
24
+ disabled?: boolean | SerializablePropertyDisabledConfig;
25
+ widthPercentage?: number;
26
+ customProps?: unknown;
27
+ }
28
+ /** JSON-serializable version of `PropertyDisabledConfig`. Already serializable. */
29
+ export interface SerializablePropertyDisabledConfig {
30
+ clearOnDisabled?: boolean;
31
+ disabledMessage?: string;
32
+ hidden?: boolean;
33
+ }
34
+ /**
35
+ * JSON-serializable version of `StringPropertyValidationSchema`.
36
+ * `matches` is forced to `string` (no RegExp).
37
+ */
38
+ export interface SerializableStringValidation extends PropertyValidationSchema {
39
+ length?: number;
40
+ min?: number;
41
+ max?: number;
42
+ /** Regex pattern as a string. RegExp objects are converted to their `.source`. */
43
+ matches?: string;
44
+ matchesMessage?: string;
45
+ trim?: boolean;
46
+ lowercase?: boolean;
47
+ uppercase?: boolean;
48
+ }
49
+ /**
50
+ * JSON-serializable version of `DatePropertyValidationSchema`.
51
+ * `min` and `max` are ISO 8601 strings instead of `Date` objects.
52
+ */
53
+ export interface SerializableDateValidation extends PropertyValidationSchema {
54
+ /** Minimum date as ISO 8601 string. */
55
+ min?: string;
56
+ /** Maximum date as ISO 8601 string. */
57
+ max?: string;
58
+ }
59
+ /**
60
+ * JSON-serializable version of `StorageConfig`.
61
+ * Drops all function fields: `processFile`, `postProcess`, `previewUrl`.
62
+ * `storagePath` and `fileName` are string-only (no function variant).
63
+ */
64
+ export interface SerializableStorageConfig {
65
+ acceptedFiles?: FileType[];
66
+ imageResize?: ImageResize;
67
+ metadata?: Record<string, unknown>;
68
+ /** String template only. Function variant is not serializable. */
69
+ fileName?: string;
70
+ /** String template only. Function variant is not serializable. */
71
+ storagePath: string;
72
+ includeBucketUrl?: boolean;
73
+ storeUrl?: boolean;
74
+ maxSize?: number;
75
+ }
76
+ /** JSON-serializable version of `StringUIConfig`. */
77
+ export interface SerializableStringUIConfig extends SerializableBaseUIConfig {
78
+ multiline?: boolean;
79
+ markdown?: boolean;
80
+ previewAsTag?: boolean;
81
+ clearable?: boolean;
82
+ url?: boolean | "image" | "video" | "audio" | "file";
83
+ }
84
+ /** JSON-serializable version of `NumberUIConfig`. */
85
+ export interface SerializableNumberUIConfig extends SerializableBaseUIConfig {
86
+ clearable?: boolean;
87
+ }
88
+ /** JSON-serializable version of `DateUIConfig`. */
89
+ export interface SerializableDateUIConfig extends SerializableBaseUIConfig {
90
+ clearable?: boolean;
91
+ }
92
+ /** JSON-serializable version of `VectorUIConfig`. */
93
+ export interface SerializableVectorUIConfig extends SerializableBaseUIConfig {
94
+ clearable?: boolean;
95
+ }
96
+ /** JSON-serializable version of `ReferenceUIConfig`. */
97
+ export interface SerializableReferenceUIConfig extends SerializableBaseUIConfig {
98
+ previewProperties?: string[];
99
+ }
100
+ /** JSON-serializable version of `RelationUIConfig`. */
101
+ export interface SerializableRelationUIConfig extends SerializableBaseUIConfig {
102
+ previewProperties?: string[];
103
+ widget?: "select" | "dialog";
104
+ }
105
+ /** JSON-serializable version of `ArrayUIConfig`. */
106
+ export interface SerializableArrayUIConfig extends SerializableBaseUIConfig {
107
+ expanded?: boolean;
108
+ minimalistView?: boolean;
109
+ }
110
+ /** JSON-serializable version of `MapUIConfig`. */
111
+ export interface SerializableMapUIConfig extends SerializableBaseUIConfig {
112
+ expanded?: boolean;
113
+ minimalistView?: boolean;
114
+ spreadChildren?: boolean;
115
+ }
116
+ /**
117
+ * JSON-serializable version of `BaseProperty`.
118
+ * Drops: `dynamicProps` (function), `callbacks` (functions).
119
+ * Keeps: `conditions` (JSON Logic — already serializable by design).
120
+ */
121
+ export interface SerializableBaseProperty {
122
+ ui?: SerializableBaseUIConfig;
123
+ name: string;
124
+ description?: string;
125
+ propertyConfig?: string;
126
+ columnName?: string;
127
+ validation?: PropertyValidationSchema;
128
+ defaultValue?: unknown;
129
+ /**
130
+ * JSON Logic conditions — fully serializable by design.
131
+ * These are the declarative alternative to `dynamicProps` functions.
132
+ */
133
+ conditions?: PropertyConditions;
134
+ /**
135
+ * Arbitrary key-value metadata for external consumers.
136
+ * Not interpreted by Rebase — passed through serialization unchanged.
137
+ */
138
+ metadata?: Record<string, unknown>;
139
+ }
140
+ /** JSON-serializable `StringProperty`. */
141
+ export interface SerializableStringProperty extends SerializableBaseProperty {
142
+ ui?: SerializableStringUIConfig;
143
+ type: "string";
144
+ columnType?: "varchar" | "text" | "char" | "uuid";
145
+ validation?: SerializableStringValidation;
146
+ isId?: boolean | "manual" | "uuid" | "cuid" | string;
147
+ enum?: EnumValues;
148
+ multiline?: boolean;
149
+ markdown?: boolean;
150
+ storage?: SerializableStorageConfig;
151
+ userSelect?: boolean;
152
+ url?: boolean | "image" | "video" | "audio" | "file";
153
+ email?: boolean;
154
+ previewAsTag?: boolean;
155
+ reference?: SerializableReferenceProperty;
156
+ }
157
+ /** JSON-serializable `NumberProperty`. */
158
+ export interface SerializableNumberProperty extends SerializableBaseProperty {
159
+ ui?: SerializableNumberUIConfig;
160
+ type: "number";
161
+ columnType?: "integer" | "real" | "double precision" | "numeric" | "bigint" | "serial" | "bigserial";
162
+ validation?: NumberPropertyValidationSchema;
163
+ isId?: boolean | "manual" | "increment" | string;
164
+ enum?: EnumValues;
165
+ }
166
+ /** JSON-serializable `BooleanProperty`. */
167
+ export interface SerializableBooleanProperty extends SerializableBaseProperty {
168
+ ui?: SerializableBaseUIConfig;
169
+ type: "boolean";
170
+ validation?: PropertyValidationSchema;
171
+ }
172
+ /** JSON-serializable `DateProperty`. */
173
+ export interface SerializableDateProperty extends SerializableBaseProperty {
174
+ ui?: SerializableDateUIConfig;
175
+ type: "date";
176
+ columnType?: "timestamp" | "date" | "time";
177
+ validation?: SerializableDateValidation;
178
+ mode?: "date" | "date_time";
179
+ timezone?: string;
180
+ autoValue?: "on_create" | "on_update";
181
+ clearable?: boolean;
182
+ }
183
+ /** JSON-serializable `GeopointProperty`. */
184
+ export interface SerializableGeopointProperty extends SerializableBaseProperty {
185
+ ui?: SerializableBaseUIConfig;
186
+ type: "geopoint";
187
+ validation?: PropertyValidationSchema;
188
+ }
189
+ /** JSON-serializable `VectorProperty`. */
190
+ export interface SerializableVectorProperty extends SerializableBaseProperty {
191
+ ui?: SerializableVectorUIConfig;
192
+ type: "vector";
193
+ dimensions: number;
194
+ validation?: PropertyValidationSchema;
195
+ }
196
+ /** JSON-serializable `BinaryProperty`. */
197
+ export interface SerializableBinaryProperty extends SerializableBaseProperty {
198
+ type: "binary";
199
+ validation?: PropertyValidationSchema;
200
+ }
201
+ /**
202
+ * JSON-serializable `ReferenceProperty`.
203
+ * Already largely serializable; just inherits the serializable base.
204
+ */
205
+ export interface SerializableReferenceProperty extends SerializableBaseProperty {
206
+ ui?: SerializableReferenceUIConfig;
207
+ type: "reference";
208
+ isId?: boolean;
209
+ path?: string;
210
+ fixedFilter?: FilterValues<string>;
211
+ includeId?: boolean;
212
+ includeEntityLink?: boolean;
213
+ }
214
+ /**
215
+ * JSON-serializable `RelationProperty`.
216
+ * `target` is string-only (collection slug). The function variant
217
+ * `() => EntityCollection` is not serializable.
218
+ */
219
+ export interface SerializableRelationProperty extends SerializableBaseProperty {
220
+ ui?: SerializableRelationUIConfig;
221
+ type: "relation";
222
+ isId?: boolean;
223
+ /** Target collection slug. Function variant is not serializable. */
224
+ target?: string;
225
+ cardinality?: "one" | "many";
226
+ direction?: "owning" | "inverse";
227
+ inverseRelationName?: string;
228
+ localKey?: string;
229
+ foreignKeyOnTarget?: string;
230
+ through?: {
231
+ table: string;
232
+ sourceColumn: string;
233
+ targetColumn: string;
234
+ };
235
+ joinPath?: JoinStep[];
236
+ onUpdate?: OnAction;
237
+ onDelete?: OnAction;
238
+ relationName?: string;
239
+ fixedFilter?: FilterValues<string>;
240
+ includeId?: boolean;
241
+ includeEntityLink?: boolean;
242
+ widget?: "select" | "dialog";
243
+ }
244
+ /** JSON-serializable `ArrayProperty`. */
245
+ export interface SerializableArrayProperty extends SerializableBaseProperty {
246
+ ui?: SerializableArrayUIConfig;
247
+ type: "array";
248
+ columnType?: "json" | "jsonb" | "text[]" | "integer[]" | "boolean[]" | "numeric[]";
249
+ of?: SerializableProperty | SerializableProperty[];
250
+ oneOf?: {
251
+ properties: SerializableProperties;
252
+ propertiesOrder?: string[];
253
+ typeField?: string;
254
+ valueField?: string;
255
+ };
256
+ validation?: ArrayPropertyValidationSchema;
257
+ sortable?: boolean;
258
+ canAddElements?: boolean;
259
+ }
260
+ /** JSON-serializable `MapProperty`. */
261
+ export interface SerializableMapProperty extends SerializableBaseProperty {
262
+ ui?: SerializableMapUIConfig;
263
+ type: "map";
264
+ columnType?: "json" | "jsonb";
265
+ properties?: SerializableProperties;
266
+ propertiesOrder?: string[];
267
+ validation?: PropertyValidationSchema;
268
+ previewProperties?: string[];
269
+ keyValue?: boolean;
270
+ }
271
+ /**
272
+ * Union of all JSON-serializable property types.
273
+ * Mirrors `Property` from `@rebasepro/types` but with all non-serializable
274
+ * fields stripped.
275
+ */
276
+ export type SerializableProperty = SerializableStringProperty | SerializableNumberProperty | SerializableBooleanProperty | SerializableDateProperty | SerializableGeopointProperty | SerializableReferenceProperty | SerializableRelationProperty | SerializableArrayProperty | SerializableMapProperty | SerializableVectorProperty | SerializableBinaryProperty;
277
+ /** Record of serializable properties, keyed by property key. */
278
+ export type SerializableProperties = {
279
+ [key: string]: SerializableProperty;
280
+ };
281
+ /**
282
+ * JSON-serializable version of `EntityCollection` / `BaseEntityCollection`.
283
+ *
284
+ * Strips all non-serializable fields:
285
+ * - Functions: `callbacks`, `childCollections`, `additionalFields`, `defaultSelectedView` (fn)
286
+ * - React nodes: `icon` (ReactNode variant), `entityViews`, `formView`
287
+ * - Runtime objects: `selectionController`, `overrides`
288
+ * - Component refs: `Actions`, `components`, `entityActions`
289
+ * - `exportable` when it's an `ExportConfig` (contains functions)
290
+ * - `auth` when it's an `AuthCollectionConfig` (contains functions)
291
+ *
292
+ * Keeps all data-describing fields that the collection editor works with.
293
+ */
294
+ export interface SerializableCollection {
295
+ slug: string;
296
+ name: string;
297
+ singularName?: string;
298
+ description?: string;
299
+ /**
300
+ * Icon name as a string (e.g. Lucide icon key).
301
+ * React.ReactNode variant is not serializable and is stripped.
302
+ */
303
+ icon?: string;
304
+ group?: string;
305
+ driver?: string;
306
+ databaseId?: string;
307
+ properties: SerializableProperties;
308
+ propertiesOrder?: string[];
309
+ previewProperties?: string[];
310
+ listProperties?: string[];
311
+ titleProperty?: string;
312
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
313
+ defaultEntityAction?: "view" | "edit";
314
+ defaultViewMode?: ViewMode;
315
+ enabledViews?: ViewMode[];
316
+ kanban?: KanbanConfig<Record<string, unknown>>;
317
+ defaultSize?: CollectionSize;
318
+ sideDialogWidth?: number | string;
319
+ pagination?: boolean | number;
320
+ selectionEnabled?: boolean;
321
+ inlineEditing?: boolean;
322
+ hideFromNavigation?: boolean;
323
+ hideIdFromForm?: boolean;
324
+ hideIdFromCollection?: boolean;
325
+ formAutoSave?: boolean;
326
+ alwaysApplyDefaultValues?: boolean;
327
+ includeJsonView?: boolean;
328
+ history?: boolean;
329
+ localChangesBackup?: "manual_apply" | "auto_apply" | false;
330
+ exportable?: boolean;
331
+ auth?: boolean;
332
+ /**
333
+ * Default selected view as a string key.
334
+ * The function variant (`DefaultSelectedViewBuilder`) is not serializable.
335
+ */
336
+ defaultSelectedView?: string;
337
+ fixedFilter?: FilterValues<string>;
338
+ defaultFilter?: FilterValues<string>;
339
+ filterPresets?: FilterPreset<string>[];
340
+ sort?: [string, "asc" | "desc"];
341
+ orderProperty?: string;
342
+ disableDefaultActions?: ("edit" | "copy" | "delete")[];
343
+ table?: string;
344
+ schema?: string;
345
+ securityRules?: SecurityRule[];
346
+ ownerId?: string;
347
+ /**
348
+ * Arbitrary key-value metadata for external consumers.
349
+ * Not interpreted by Rebase — passed through serialization unchanged.
350
+ */
351
+ metadata?: Record<string, unknown>;
352
+ }
353
+ /**
354
+ * Adapter interface for persisting serializable collections to a JSON backend.
355
+ * Implement this to store collection configs in a database, API, localStorage, etc.
356
+ */
357
+ export interface JsonCollectionStore {
358
+ /** Load all persisted collections. */
359
+ load(): Promise<SerializableCollection[]>;
360
+ /** Save (create or update) a single collection by its slug. */
361
+ save(slug: string, data: SerializableCollection): Promise<void>;
362
+ /** Delete a collection by its slug. */
363
+ delete(slug: string): Promise<void>;
364
+ /**
365
+ * Optional: save navigation group mappings.
366
+ * If not implemented, navigation entries are not persisted.
367
+ */
368
+ saveNavigationEntries?(entries: NavigationGroupMapping[]): Promise<void>;
369
+ /**
370
+ * Optional: load navigation group mappings.
371
+ * If not implemented, an empty array is used.
372
+ */
373
+ loadNavigationEntries?(): Promise<NavigationGroupMapping[]>;
374
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Conversion utilities between the full Rebase types and their
3
+ * JSON-serializable counterparts.
4
+ *
5
+ * - `toSerializableCollection` / `toSerializableProperty` — strip non-serializable fields
6
+ * - `fromSerializableCollection` / `fromSerializableProperty` — reconstruct original types
7
+ *
8
+ * @module
9
+ */
10
+ import type { EntityCollection, Property, Properties } from "@rebasepro/types";
11
+ import type { SerializableCollection, SerializableProperty, SerializableProperties } from "./serializable_types";
12
+ /**
13
+ * Convert a single `Property` to its JSON-serializable form.
14
+ * Strips functions, converts RegExp to string, Date to ISO string.
15
+ */
16
+ export declare function toSerializableProperty(property: Property): SerializableProperty;
17
+ /**
18
+ * Convert a `Properties` record to its serializable form.
19
+ */
20
+ export declare function toSerializableProperties(properties: Properties): SerializableProperties;
21
+ /**
22
+ * Convert an `EntityCollection` to its JSON-serializable form.
23
+ *
24
+ * Strips all non-serializable fields (functions, React nodes, class instances)
25
+ * while preserving the structural schema that the collection editor works with.
26
+ *
27
+ * The result is safe for `JSON.stringify()` and database storage.
28
+ */
29
+ export declare function toSerializableCollection(collection: EntityCollection): SerializableCollection;
30
+ /**
31
+ * Convert a serializable property back to the original `Property` type.
32
+ *
33
+ * This is a mostly pass-through operation since serializable properties
34
+ * are a subset of the original types. The main conversions are:
35
+ * - `validation.matches` (string) stays as string (compatible with Property)
36
+ * - `validation.min/max` on dates: ISO strings → Date objects
37
+ */
38
+ export declare function fromSerializableProperty(serialized: SerializableProperty): Property;
39
+ /**
40
+ * Convert a `SerializableProperties` record back to `Properties`.
41
+ */
42
+ export declare function fromSerializableProperties(serialized: SerializableProperties): Properties;
43
+ /**
44
+ * Convert a `SerializableCollection` back to an `EntityCollection`.
45
+ *
46
+ * The result will NOT contain any of the non-serializable fields
47
+ * (callbacks, entityActions, etc.) — those must be re-attached by the
48
+ * consumer if needed.
49
+ */
50
+ export declare function fromSerializableCollection(serialized: SerializableCollection): EntityCollection;
@@ -4,7 +4,8 @@ import { CollectionsConfigController } from "../../types/config_controller";
4
4
  import { CollectionInference } from "../../types/collection_inference";
5
5
  import { CollectionGenerationCallback } from "../../api/generateCollectionApi";
6
6
  import { TableMetadata } from "@rebasepro/types";
7
- export interface CollectionEditorDialogProps {
7
+ import type { CollectionEditorExtensionProps } from "../../extensibility_types";
8
+ export interface CollectionEditorDialogProps extends CollectionEditorExtensionProps {
8
9
  open: boolean;
9
10
  isNewCollection: boolean;
10
11
  initialValues?: {
@@ -1,5 +1,7 @@
1
1
  import React from "react";
2
2
  import { EntityCollection, PropertyConfig, User } from "@rebasepro/types";
3
+ import type { PropertyTypePreset, PropertyType } from "../../extensibility_types";
4
+ import type { SerializableProperty, SerializableCollection } from "../../serializable_types";
3
5
  type CollectionEditorFormProps = {
4
6
  showErrors: boolean;
5
7
  isNewCollection: boolean;
@@ -11,6 +13,15 @@ type CollectionEditorFormProps = {
11
13
  getData?: () => Promise<object[]>;
12
14
  doCollectionInference?: (collection: EntityCollection) => Promise<Partial<EntityCollection> | null> | undefined;
13
15
  propertyConfigs: Record<string, PropertyConfig>;
16
+ propertyTypePresets?: PropertyTypePreset[];
17
+ hiddenPropertyTypes?: PropertyType[];
18
+ renderExtraPropertyFields?: (params: {
19
+ metadata: Record<string, unknown>;
20
+ onMetadataChange: (key: string, value: unknown) => void;
21
+ property: SerializableProperty;
22
+ collection: SerializableCollection;
23
+ }) => React.ReactNode;
24
+ standalone?: boolean;
14
25
  };
15
- export declare function CollectionPropertiesEditorForm({ showErrors, isNewCollection, propertyErrorsRef, onPropertyError, setDirty, extraIcon, getUser, getData, doCollectionInference, propertyConfigs }: CollectionEditorFormProps): React.JSX.Element;
26
+ export declare function CollectionPropertiesEditorForm({ showErrors, isNewCollection, propertyErrorsRef, onPropertyError, setDirty, extraIcon, getUser, getData, doCollectionInference, propertyConfigs, propertyTypePresets, hiddenPropertyTypes, renderExtraPropertyFields, standalone, }: CollectionEditorFormProps): React.JSX.Element;
16
27
  export {};
@@ -1,6 +1,18 @@
1
1
  import * as React from "react";
2
2
  import { CollectionEditorDialogProps } from "./CollectionEditorDialog";
3
+ import type { EntityCollection } from "@rebasepro/types";
3
4
  export type CollectionStudioViewProps = Omit<CollectionEditorDialogProps, "open" | "isNewCollection" | "editedCollectionId" | "handleClose" | "handleCancel"> & {
4
5
  collectionId?: string | "new";
6
+ /**
7
+ * Called after a successful save.
8
+ * Receives the saved collection (or undefined if dismissed without saving).
9
+ * When not provided, save completes silently.
10
+ */
11
+ onSave?: (collection?: EntityCollection) => void;
12
+ /**
13
+ * Called when the user cancels editing.
14
+ * When not provided, cancel is a no-op.
15
+ */
16
+ onCancel?: () => void;
5
17
  };
6
- export declare function CollectionStudioView({ collectionId, ...props }: CollectionStudioViewProps): React.JSX.Element;
18
+ export declare function CollectionStudioView({ collectionId, onSave, onCancel, ...props }: CollectionStudioViewProps): React.JSX.Element;
@@ -1,6 +1,28 @@
1
1
  import React from "react";
2
+ import type { EntityCollection } from "@rebasepro/types";
2
3
  import { CollectionsConfigController } from "../../types/config_controller";
3
- export interface CollectionsStudioViewProps {
4
+ import type { CollectionEditorExtensionProps } from "../../extensibility_types";
5
+ export interface CollectionsStudioViewProps extends CollectionEditorExtensionProps {
4
6
  configController: CollectionsConfigController;
7
+ /**
8
+ * Collections to show in the sidebar.
9
+ * When provided, overrides the collections from `configController`.
10
+ * Use this to control exactly which collections the editor displays.
11
+ */
12
+ collections?: EntityCollection[];
13
+ /**
14
+ * Controlled active collection ID.
15
+ * When provided together with `onActiveCollectionChange`,
16
+ * navigation is fully external — no internal state is used.
17
+ */
18
+ activeCollectionId?: string;
19
+ /**
20
+ * Called when the user clicks a collection, "new", or navigates.
21
+ * When provided, the component is fully controlled (no internal state).
22
+ * When not provided, the component manages selection via internal state.
23
+ *
24
+ * Pass `"new"` to create a new collection. Pass `undefined` to deselect.
25
+ */
26
+ onActiveCollectionChange?: (collectionId: string | undefined) => void;
5
27
  }
6
- export declare function CollectionsStudioView({ configController }: CollectionsStudioViewProps): React.JSX.Element;
28
+ export declare function CollectionsStudioView({ configController, collections: collectionsProp, activeCollectionId: controlledActiveId, onActiveCollectionChange, propertyTypePresets, hiddenPropertyTypes, renderExtraPropertyFields, renderExtraCollectionFields, visibleTabs, standalone, }: CollectionsStudioViewProps): React.JSX.Element;
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
- export declare function DisplaySettingsForm({ expandKanban }: {
2
+ export declare function DisplaySettingsForm({ expandKanban, standalone, }: {
3
3
  expandKanban?: boolean;
4
+ standalone?: boolean;
4
5
  }): React.JSX.Element;
@@ -1,8 +1,11 @@
1
1
  import React from "react";
2
2
  import type { EntityCollection } from "@rebasepro/types";
3
- export declare function GeneralSettingsForm({ isNewCollection, existingPaths, existingIds, parentCollection }: {
3
+ import type { ExtraCollectionFieldsParams } from "../../extensibility_types";
4
+ export declare function GeneralSettingsForm({ isNewCollection, existingPaths, existingIds, parentCollection, renderExtraCollectionFields, standalone, }: {
4
5
  isNewCollection: boolean;
5
6
  existingPaths?: string[];
6
7
  existingIds?: string[];
7
8
  parentCollection?: EntityCollection;
9
+ renderExtraCollectionFields?: (params: ExtraCollectionFieldsParams) => React.ReactNode;
10
+ standalone?: boolean;
8
11
  }): React.JSX.Element;
@@ -1,6 +1,8 @@
1
1
  import React from "react";
2
2
  import { FormexController } from "@rebasepro/formex";
3
- import { Property, PropertyConfig } from "@rebasepro/types";
3
+ import { EntityCollection, Property, PropertyConfig } from "@rebasepro/types";
4
+ import type { PropertyTypePreset, PropertyType } from "../../extensibility_types";
5
+ import type { SerializableProperty, SerializableCollection } from "../../serializable_types";
4
6
  export type PropertyWithId = Property & {
5
7
  id?: string;
6
8
  conditions?: import("@rebasepro/types").PropertyConditions;
@@ -32,6 +34,15 @@ export type PropertyFormProps = {
32
34
  getData?: () => Promise<object[]>;
33
35
  getController?: (formex: FormexController<PropertyWithId>) => void;
34
36
  propertyConfigs: Record<string, PropertyConfig>;
37
+ propertyTypePresets?: PropertyTypePreset[];
38
+ hiddenPropertyTypes?: PropertyType[];
39
+ renderExtraPropertyFields?: (params: {
40
+ metadata: Record<string, unknown>;
41
+ onMetadataChange: (key: string, value: unknown) => void;
42
+ property: SerializableProperty;
43
+ collection: SerializableCollection;
44
+ }) => React.ReactNode;
45
+ collectionValues?: EntityCollection;
35
46
  };
36
47
  export declare const PropertyForm: React.MemoExoticComponent<(props: PropertyFormProps) => React.JSX.Element>;
37
48
  export declare function PropertyFormDialog({ open, onCancel, onOkClicked, onPropertyChanged, getData, ...formProps }: PropertyFormProps & {
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Router-aware wrapper around CollectionStudioView.
3
+ *
4
+ * This component provides the react-router-based navigation behavior
5
+ * that Rebase Studio expects: cancel navigates to the root path,
6
+ * save navigates to the saved collection's slug, and a snackbar
7
+ * toast is shown on success.
8
+ *
9
+ * External consumers should use `CollectionStudioView` directly
10
+ * (which has no react-router dependency).
11
+ */
12
+ import React from "react";
13
+ import { CollectionStudioViewProps } from "./CollectionStudioView";
14
+ export type RouterCollectionStudioViewProps = Omit<CollectionStudioViewProps, "onSave" | "onCancel">;
15
+ export declare function RouterCollectionStudioView(props: RouterCollectionStudioViewProps): React.JSX.Element;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Router-aware wrapper around CollectionsStudioView.
3
+ *
4
+ * This component provides the react-router-based navigation behavior
5
+ * that Rebase Studio expects: the active collection is derived from the
6
+ * URL, and clicking a collection navigates via react-router.
7
+ *
8
+ * External consumers should use `CollectionsStudioView` directly
9
+ * (which has no react-router dependency).
10
+ */
11
+ import React from "react";
12
+ import { CollectionsStudioViewProps } from "./CollectionsStudioView";
13
+ export type RouterCollectionsStudioViewProps = Omit<CollectionsStudioViewProps, "activeCollectionId" | "onActiveCollectionChange">;
14
+ export declare function RouterCollectionsStudioView(props: RouterCollectionsStudioViewProps): React.JSX.Element;
@@ -0,0 +1,37 @@
1
+ import type { CollectionsConfigController } from "./types/config_controller";
2
+ import type { JsonCollectionStore } from "./serializable_types";
3
+ export interface UseJsonCollectionsConfigControllerOptions {
4
+ /**
5
+ * The store adapter for persisting/loading collections.
6
+ */
7
+ store: JsonCollectionStore;
8
+ /**
9
+ * If true, the configuration cannot be modified.
10
+ */
11
+ readOnly?: boolean;
12
+ /**
13
+ * If true, collections will be loaded from the store on mount.
14
+ * Defaults to true.
15
+ */
16
+ autoLoad?: boolean;
17
+ }
18
+ /**
19
+ * A `CollectionsConfigController` implementation that persists collection
20
+ * configurations as JSON via a pluggable `JsonCollectionStore` adapter.
21
+ *
22
+ * Use this when you want to store collection schemas in a database, API,
23
+ * localStorage, or any other JSON-compatible backend — as opposed to the
24
+ * default code-based persistence.
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * const store: JsonCollectionStore = {
29
+ * load: async () => { const res = await fetch('/api/schemas'); return res.json(); },
30
+ * save: async (slug, data) => { await fetch(`/api/schemas/${slug}`, { method: 'PUT', body: JSON.stringify(data) }); },
31
+ * delete: async (slug) => { await fetch(`/api/schemas/${slug}`, { method: 'DELETE' }); },
32
+ * };
33
+ *
34
+ * const configController = useJsonCollectionsConfigController({ store });
35
+ * ```
36
+ */
37
+ export declare function useJsonCollectionsConfigController({ store, readOnly, autoLoad, }: UseJsonCollectionsConfigControllerOptions): CollectionsConfigController;
@@ -0,0 +1,2 @@
1
+ import { useSnackbarController } from "@rebasepro/core";
2
+ export declare function useSafeSnackbarController(): ReturnType<typeof useSnackbarController> | undefined;
@@ -6,3 +6,7 @@ export { CollectionStudioView } from "./collection_editor/ui/collection_editor/C
6
6
  export type { CollectionStudioViewProps } from "./collection_editor/ui/collection_editor/CollectionStudioView";
7
7
  export { CollectionsStudioView } from "./collection_editor/ui/collection_editor/CollectionsStudioView";
8
8
  export type { CollectionsStudioViewProps } from "./collection_editor/ui/collection_editor/CollectionsStudioView";
9
+ export { RouterCollectionStudioView } from "./collection_editor/ui/collection_editor/RouterCollectionStudioView";
10
+ export type { RouterCollectionStudioViewProps } from "./collection_editor/ui/collection_editor/RouterCollectionStudioView";
11
+ export { RouterCollectionsStudioView } from "./collection_editor/ui/collection_editor/RouterCollectionsStudioView";
12
+ export type { RouterCollectionsStudioViewProps } from "./collection_editor/ui/collection_editor/RouterCollectionsStudioView";