@rebasepro/admin 0.1.2 → 0.2.3

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 (243) hide show
  1. package/LICENSE +21 -6
  2. package/dist/{CollectionEditorDialog-ywdxhs1L.js → CollectionEditorDialog-CmGXXSY9.js} +42 -209
  3. package/dist/CollectionEditorDialog-CmGXXSY9.js.map +1 -0
  4. package/dist/{CollectionsStudioView-BDzMFzqH.js → CollectionsStudioView-DcLHT5bU.js} +6 -8
  5. package/dist/CollectionsStudioView-DcLHT5bU.js.map +1 -0
  6. package/dist/{ContentHomePage-0tHuEIm_.js → ContentHomePage-C7vFqKSe.js} +5 -7
  7. package/dist/ContentHomePage-C7vFqKSe.js.map +1 -0
  8. package/dist/{ExportCollectionAction-BIrq92To.js → ExportCollectionAction-BfN34eWX.js} +36 -38
  9. package/dist/ExportCollectionAction-BfN34eWX.js.map +1 -0
  10. package/dist/{ImportCollectionAction-h8yg_To8.js → ImportCollectionAction-SZrInjhx.js} +5 -7
  11. package/dist/ImportCollectionAction-SZrInjhx.js.map +1 -0
  12. package/dist/{PropertyEditView-BuZrNnBN.js → PropertyEditView-Cvryrb3B.js} +563 -489
  13. package/dist/PropertyEditView-Cvryrb3B.js.map +1 -0
  14. package/dist/{RolesView-CMPsaIXo.js → RolesView-BCb7qwWs.js} +22 -11
  15. package/dist/RolesView-BCb7qwWs.js.map +1 -0
  16. package/dist/{UsersView-BkeblMVT.js → UsersView-Cex24r8H.js} +7 -71
  17. package/dist/UsersView-Cex24r8H.js.map +1 -0
  18. package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +2 -2
  19. package/dist/collection_editor/ui/collection_editor/properties/RelationPropertyField.d.ts +1 -7
  20. package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +3 -0
  21. package/dist/collection_editor_ui.js +5 -5
  22. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
  23. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
  24. package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
  25. package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
  26. package/dist/components/EntityDetailView.d.ts +31 -0
  27. package/dist/components/EntityEditView.d.ts +3 -2
  28. package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
  29. package/dist/components/admin/CreationResultDialog.d.ts +5 -0
  30. package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
  31. package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
  32. package/dist/components/common/default_entity_actions.d.ts +7 -1
  33. package/dist/components/field_configs.d.ts +1 -1
  34. package/dist/components/index.d.ts +1 -0
  35. package/dist/data_import/utils/data.d.ts +1 -1
  36. package/dist/data_import/utils/file_headers.d.ts +6 -1
  37. package/dist/data_import/utils/file_to_json.d.ts +1 -11
  38. package/dist/data_import/utils/transforms.d.ts +11 -0
  39. package/dist/editor.js +2 -4
  40. package/dist/editor.js.map +1 -1
  41. package/dist/form/EntityForm.d.ts +1 -1
  42. package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
  43. package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
  44. package/dist/form/index.d.ts +1 -0
  45. package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
  46. package/dist/{index-eRJbMvHi.js → index-DjduZG1T.js} +3 -3
  47. package/dist/index-DjduZG1T.js.map +1 -0
  48. package/dist/{index-BuZaHcyc.js → index-MKPc70-v.js} +3 -3
  49. package/dist/index-MKPc70-v.js.map +1 -0
  50. package/dist/{index-CS6uJ7oW.js → index-PLIQXpTt.js} +4 -6
  51. package/dist/index-PLIQXpTt.js.map +1 -0
  52. package/dist/index.d.ts +4 -1
  53. package/dist/index.js +352 -148
  54. package/dist/index.js.map +1 -1
  55. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  56. package/dist/types/components/EntityFormProps.d.ts +2 -1
  57. package/dist/types/fields.d.ts +3 -3
  58. package/dist/util/navigation_utils.d.ts +1 -1
  59. package/dist/{util-zfU1zOCX.js → util-DbWax_sV.js} +5453 -2641
  60. package/dist/util-DbWax_sV.js.map +1 -0
  61. package/package.json +46 -39
  62. package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
  63. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
  64. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
  65. package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
  66. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
  67. package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
  68. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
  69. package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
  70. package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
  71. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
  72. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
  73. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
  74. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +23 -17
  75. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
  76. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
  77. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
  78. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
  79. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
  80. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
  81. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
  82. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
  83. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
  84. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
  85. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
  86. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
  87. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
  88. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
  89. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
  90. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
  91. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
  92. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
  93. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
  94. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
  95. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
  96. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
  97. package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +37 -57
  98. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
  99. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
  100. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
  101. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
  102. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
  103. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
  104. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
  105. package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
  106. package/src/collection_editor/validateCollectionJson.ts +97 -10
  107. package/src/components/AdminModeSyncer.tsx +1 -1
  108. package/src/components/ArrayContainer.tsx +19 -15
  109. package/src/components/ClearFilterSortButton.tsx +1 -2
  110. package/src/components/CollectionEditorDialogs.tsx +1 -1
  111. package/src/components/DefaultAppBar.tsx +15 -3
  112. package/src/components/DefaultDrawer.tsx +3 -3
  113. package/src/components/DrawerNavigationGroup.tsx +1 -2
  114. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +14 -6
  115. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +1 -1
  116. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  117. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
  118. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
  119. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
  120. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
  121. package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
  122. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
  123. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +1 -2
  124. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
  125. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
  126. package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
  127. package/src/components/EntityCollectionView/Board.tsx +1 -2
  128. package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
  129. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
  130. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
  131. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
  132. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +87 -18
  133. package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
  134. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
  135. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
  136. package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
  137. package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
  138. package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
  139. package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
  140. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
  141. package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
  142. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
  143. package/src/components/EntityDetailView.tsx +619 -0
  144. package/src/components/EntityEditView.tsx +29 -10
  145. package/src/components/EntityEditViewFormActions.tsx +20 -7
  146. package/src/components/EntityPreview.tsx +14 -5
  147. package/src/components/EntitySidePanel.tsx +116 -62
  148. package/src/components/EntityView.tsx +1 -2
  149. package/src/components/HomePage/ContentHomePage.tsx +1 -1
  150. package/src/components/HomePage/FavouritesView.tsx +1 -2
  151. package/src/components/HomePage/NavigationCard.tsx +1 -2
  152. package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
  153. package/src/components/HomePage/NavigationGroup.tsx +1 -2
  154. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  155. package/src/components/PropertyIdCopyTooltip.tsx +1 -2
  156. package/src/components/RebaseAuthGate.tsx +2 -2
  157. package/src/components/RebaseNavigation.tsx +9 -7
  158. package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
  159. package/src/components/RelationSelector.tsx +34 -6
  160. package/src/components/SearchIconsView.tsx +10 -2
  161. package/src/components/SelectableTable/SelectableTable.tsx +2 -2
  162. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
  163. package/src/components/SideDialogs.tsx +63 -38
  164. package/src/components/UserSelector.tsx +30 -6
  165. package/src/components/admin/CreationResultDialog.tsx +135 -0
  166. package/src/components/admin/RolesFilterSelect.tsx +45 -0
  167. package/src/components/admin/RolesView.tsx +53 -14
  168. package/src/components/admin/UserRolesSelectField.tsx +50 -0
  169. package/src/components/admin/UsersView.tsx +41 -124
  170. package/src/components/app/Scaffold.tsx +1 -2
  171. package/src/components/common/default_entity_actions.tsx +119 -12
  172. package/src/components/field_configs.tsx +39 -3
  173. package/src/components/history/EntityHistoryEntry.tsx +1 -2
  174. package/src/components/history/EntityHistoryView.tsx +1 -2
  175. package/src/components/index.ts +2 -0
  176. package/src/data_export/export/BasicExportAction.tsx +35 -38
  177. package/src/data_export/export/ExportCollectionAction.tsx +39 -40
  178. package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
  179. package/src/data_import/components/ImportFileUpload.tsx +1 -2
  180. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
  181. package/src/data_import/import/ImportCollectionAction.tsx +21 -8
  182. package/src/data_import/utils/data.ts +23 -5
  183. package/src/data_import/utils/file_headers.ts +13 -89
  184. package/src/data_import/utils/file_to_json.ts +43 -68
  185. package/src/data_import/utils/transforms.ts +47 -0
  186. package/src/editor/components/SlashCommandMenu.tsx +17 -2
  187. package/src/editor/components/editor-bubble-item.tsx +1 -1
  188. package/src/editor/extensions/Image/index.ts +1 -1
  189. package/src/editor/extensions/Image.ts +1 -1
  190. package/src/editor/selectors/color-selector.tsx +1 -2
  191. package/src/editor/selectors/link-selector.tsx +1 -2
  192. package/src/editor/selectors/node-selector.tsx +16 -2
  193. package/src/editor/selectors/text-buttons.tsx +1 -2
  194. package/src/editor/utils/prosemirror-utils.ts +1 -1
  195. package/src/form/EntityForm.tsx +16 -6
  196. package/src/form/EntityFormActions.tsx +11 -3
  197. package/src/form/PropertyFieldBinding.tsx +5 -12
  198. package/src/form/components/FieldHelperText.tsx +1 -2
  199. package/src/form/components/LocalChangesMenu.tsx +17 -2
  200. package/src/form/components/StorageItemPreview.tsx +1 -2
  201. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
  202. package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
  203. package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
  204. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
  205. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
  206. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
  207. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
  208. package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
  209. package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
  210. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
  211. package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
  212. package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
  213. package/src/form/index.tsx +1 -0
  214. package/src/form/validation.ts +54 -2
  215. package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
  216. package/src/hooks/navigation/useResolvedViews.tsx +30 -15
  217. package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
  218. package/src/index.ts +6 -0
  219. package/src/preview/PropertyPreview.tsx +1 -1
  220. package/src/preview/components/ImagePreview.tsx +1 -1
  221. package/src/preview/components/UrlComponentPreview.tsx +1 -2
  222. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
  223. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
  224. package/src/routes/RebaseRoute.tsx +64 -35
  225. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  226. package/src/types/components/EntityFormProps.tsx +3 -1
  227. package/src/types/fields.tsx +4 -3
  228. package/src/util/navigation_utils.ts +4 -3
  229. package/src/util/previews.ts +1 -1
  230. package/src/util/property_utils.tsx +22 -6
  231. package/src/util/resolutions.ts +2 -2
  232. package/dist/CollectionEditorDialog-ywdxhs1L.js.map +0 -1
  233. package/dist/CollectionsStudioView-BDzMFzqH.js.map +0 -1
  234. package/dist/ContentHomePage-0tHuEIm_.js.map +0 -1
  235. package/dist/ExportCollectionAction-BIrq92To.js.map +0 -1
  236. package/dist/ImportCollectionAction-h8yg_To8.js.map +0 -1
  237. package/dist/PropertyEditView-BuZrNnBN.js.map +0 -1
  238. package/dist/RolesView-CMPsaIXo.js.map +0 -1
  239. package/dist/UsersView-BkeblMVT.js.map +0 -1
  240. package/dist/index-BuZaHcyc.js.map +0 -1
  241. package/dist/index-CS6uJ7oW.js.map +0 -1
  242. package/dist/index-eRJbMvHi.js.map +0 -1
  243. package/dist/util-zfU1zOCX.js.map +0 -1
@@ -36,6 +36,7 @@ export type UseResolvedViewsProps<USER extends User> = {
36
36
  adminMode?: "content" | "studio" | "settings";
37
37
  effectiveRoleController?: EffectiveRoleController;
38
38
  userManagement?: UserManagementDelegate<USER>;
39
+ collections?: EntityCollection[];
39
40
  };
40
41
 
41
42
  export type UseResolvedViewsResult = {
@@ -66,7 +67,8 @@ export function useResolvedViews<USER extends User>(
66
67
  plugins,
67
68
  adminMode = "content",
68
69
  effectiveRoleController,
69
- userManagement
70
+ userManagement,
71
+ collections
70
72
  } = props;
71
73
 
72
74
  const [loading, setLoading] = useState(true);
@@ -124,24 +126,31 @@ export function useResolvedViews<USER extends User>(
124
126
 
125
127
  const injectedAdminViews: AppView[] = useMemo(() => {
126
128
  const views: AppView[] = [];
127
- if (userManagement && usersViewElement) {
128
- views.push({
129
- slug: "users",
130
- name: "Users",
131
- icon: "Headset",
132
- view: usersViewElement
133
- });
134
- if (userManagement.roles && rolesViewElement) {
129
+ const isUserAdmin = userManagement?.isAdmin !== false;
130
+ if (userManagement && isUserAdmin && usersViewElement) {
131
+ const hasUsersCollection = collections?.some(c => c.slug === "users");
132
+ if (!hasUsersCollection) {
133
+ views.push({
134
+ slug: "users",
135
+ name: "Users",
136
+ icon: "Headset",
137
+ view: usersViewElement,
138
+ group: "Settings"
139
+ });
140
+ }
141
+ const hasRolesCollection = collections?.some(c => c.slug === "roles");
142
+ if (userManagement.roles && rolesViewElement && !hasRolesCollection) {
135
143
  views.push({
136
144
  slug: "roles",
137
145
  name: "Roles",
138
146
  icon: "Shield",
139
- view: rolesViewElement
147
+ view: rolesViewElement,
148
+ group: "Settings"
140
149
  });
141
150
  }
142
151
  }
143
152
  return views;
144
- }, [userManagement, usersViewElement, rolesViewElement]);
153
+ }, [userManagement, usersViewElement, rolesViewElement, collections]);
145
154
 
146
155
  // Store injectedAdminViews in a ref for effect access
147
156
  const injectedAdminViewsRef = useRef(injectedAdminViews);
@@ -162,9 +171,14 @@ export function useResolvedViews<USER extends User>(
162
171
  resolveAppViews(adminViewsProp, resolvedAuthControllerRef.current, dataRef.current)
163
172
  ]);
164
173
 
165
- if (cancelled) return;
166
-
167
- const newAdminViews = [...newAdminViewsProp, ...injectedAdminViewsRef.current];
174
+ const hasCustomUsers = newAdminViewsProp.some(v => v.slug === "users");
175
+ const hasCustomRoles = newAdminViewsProp.some(v => v.slug === "roles");
176
+ const finalInjected = injectedAdminViewsRef.current.filter(v => {
177
+ if (v.slug === "users" && hasCustomUsers) return false;
178
+ if (v.slug === "roles" && hasCustomRoles) return false;
179
+ return true;
180
+ });
181
+ const newAdminViews = [...newAdminViewsProp, ...finalInjected];
168
182
 
169
183
  // Compare views by slug identity rather than deepEqual.
170
184
  // Views contain React elements (JSX) whose internal properties
@@ -201,7 +215,8 @@ export function useResolvedViews<USER extends User>(
201
215
  refreshTrigger,
202
216
  adminMode,
203
217
  initialLoading,
204
- user
218
+ user,
219
+ collections
205
220
  ]);
206
221
 
207
222
  return useMemo(() => ({
@@ -152,7 +152,7 @@ export function useTopLevelNavigation(
152
152
  if (adminView.hideFromNavigation) return acc;
153
153
 
154
154
  const pathKey = adminView.slug;
155
- let groupName = NAVIGATION_ADMIN_GROUP_NAME;
155
+ let groupName = adminView.group?.trim() || NAVIGATION_ADMIN_GROUP_NAME;
156
156
 
157
157
  if (finalNavigationGroupMappings) {
158
158
  for (const pluginGroupDef of finalNavigationGroupMappings) {
package/src/index.ts CHANGED
@@ -37,6 +37,7 @@ export {
37
37
  editEntityAction,
38
38
  copyEntityAction,
39
39
  deleteEntityAction,
40
+ resetPasswordAction,
40
41
  SideEntityProvider,
41
42
  Scaffold,
42
43
  AppBar,
@@ -93,3 +94,8 @@ export * from "./data_export";
93
94
 
94
95
  // Collection editor — moved from @rebasepro/studio (CMS-dependent visual schema editor)
95
96
  export * from "./collection_editor";
97
+
98
+ export { RolesFilterSelect } from "./components/admin/RolesFilterSelect";
99
+ export { UserRolesSelectField } from "./components/admin/UserRolesSelectField";
100
+ export { CreationResultDialog } from "./components/admin/CreationResultDialog";
101
+
@@ -111,7 +111,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<P extends Pro
111
111
  if (typeof stringProperty.reference.path === "string") {
112
112
  content = <ReferencePreview
113
113
  disabled={!stringProperty.reference.path}
114
- previewProperties={(stringProperty as any).reference?.previewProperties}
114
+ previewProperties={stringProperty.reference?.ui?.previewProperties}
115
115
  includeId={stringProperty.reference.includeId}
116
116
  includeEntityLink={stringProperty.reference.includeEntityLink}
117
117
  size={props.size}
@@ -1,4 +1,4 @@
1
- import { CopyIcon, ExternalLinkIcon, ImageOffIcon } from "lucide-react";
1
+ import { CopyIcon, ExternalLinkIcon, ImageOffIcon } from "@rebasepro/ui";
2
2
  import React, { CSSProperties, useMemo, useState, useEffect } from "react";import { IconButton, Tooltip } from "@rebasepro/ui";
3
3
  import { PreviewSize } from "../../types/components/PropertyPreviewProps";
4
4
  import { getThumbnailMeasure } from "../util";
@@ -3,8 +3,7 @@ import React, { useMemo } from "react";
3
3
  import { ImagePreview } from "./ImagePreview";
4
4
  import { PreviewType } from "@rebasepro/types";
5
5
  import type { PreviewSize } from "../../types/components/PropertyPreviewProps";
6
- import { cls, Tooltip, Typography } from "@rebasepro/ui";
7
- import { ExternalLinkIcon, FileTextIcon } from "lucide-react";
6
+ import { cls, ExternalLinkIcon, FileTextIcon, Tooltip, Typography } from "@rebasepro/ui";
8
7
  import { EmptyValue } from "./EmptyValue";
9
8
  import { getThumbnailMeasure } from "../util";
10
9
 
@@ -1,4 +1,4 @@
1
- import type { ArrayProperty, Property } from "@rebasepro/types";
1
+ import type { ArrayProperty, MapProperty, Property } from "@rebasepro/types";
2
2
  import React from "react";
3
3
  import { ErrorBoundary } from "@rebasepro/ui";
4
4
  import type { PropertyPreviewProps } from "../../types/components/PropertyPreviewProps";
@@ -28,7 +28,7 @@ export function ArrayOfMapsPreview({
28
28
  throw Error(`You need to specify a 'properties' prop (or specify a custom field) in your map property ${propertyKey}`);
29
29
  }
30
30
  const values = value;
31
- const previewProperties: string[] | undefined = (mapProperty.ui as any)?.previewProperties;
31
+ const previewProperties: string[] | undefined = (mapProperty as MapProperty).previewProperties;
32
32
 
33
33
  if (!values) return null;
34
34
 
@@ -2,7 +2,7 @@ import type { Properties } from "@rebasepro/types";
2
2
  import type { ArrayProperty, MapProperty, Property, StringProperty } from "@rebasepro/types";
3
3
  import { PreviewSize } from "../../types/components/PropertyPreviewProps";
4
4
  import React from "react";
5
- import { Skeleton } from "@rebasepro/ui";
5
+ import { Skeleton, Table, TableBody, TableRow, TableCell, Typography } from "@rebasepro/ui";
6
6
  import { getThumbnailMeasure } from "../util";
7
7
 
8
8
  export interface SkeletonPropertyComponentProps {
@@ -79,7 +79,7 @@ function renderMap<T extends Record<string, any>>(property: MapProperty, size: P
79
79
  if (size === "large") {
80
80
  mapPropertyKeys = Object.keys(property.properties);
81
81
  } else {
82
- mapPropertyKeys = ((property.ui as any)?.previewProperties || Object.keys(property.properties)) as string[];
82
+ mapPropertyKeys = (property.previewProperties || Object.keys(property.properties)) as string[];
83
83
  if (size === "medium")
84
84
  mapPropertyKeys = mapPropertyKeys.slice(0, 3);
85
85
  else if (size === "small")
@@ -103,33 +103,32 @@ function renderMap<T extends Record<string, any>>(property: MapProperty, size: P
103
103
  );
104
104
 
105
105
  return (
106
- <table className="table-auto">
107
- <tbody>
106
+ <Table className="table-auto">
107
+ <TableBody>
108
108
  {mapPropertyKeys &&
109
109
  mapPropertyKeys.map((key, index) => {
110
110
  return (
111
- <tr
112
- key={`map_preview_table__${index}`}
113
- className="border-b last:border-b-0">
114
- <th key={`table-cell-title--${key}`}
111
+ <TableRow
112
+ key={`map_preview_table__${index}`}>
113
+ <TableCell key={`table-cell-title--${key}`}
115
114
  className="align-top"
116
115
  style={{ width: "30%" }}>
117
- <p className="text-xs text-secondary">
116
+ <Typography variant="caption" color="secondary">
118
117
  {property.properties![key].name}
119
- </p>
120
- </th>
121
- <th key={`table-cell-${key}`}
118
+ </Typography>
119
+ </TableCell>
120
+ <TableCell key={`table-cell-${key}`}
122
121
  style={{ width: "70%" }}>
123
122
  {property.properties && property.properties[key] &&
124
123
  <SkeletonPropertyComponent
125
124
  property={property.properties[key]}
126
125
  size={"medium"}/>}
127
- </th>
128
- </tr>
126
+ </TableCell>
127
+ </TableRow>
129
128
  );
130
129
  })}
131
- </tbody>
132
- </table>
130
+ </TableBody>
131
+ </Table>
133
132
  );
134
133
  }
135
134
 
@@ -142,28 +141,28 @@ function renderArrayOfMaps(properties: Properties, size: PreviewSize, previewPro
142
141
  }
143
142
 
144
143
  return (
145
- <table className="table-auto">
146
- <tbody>
144
+ <Table className="table-auto">
145
+ <TableBody>
147
146
  {
148
147
  [0, 1, 2].map((value, index) => {
149
148
  return (
150
- <tr key={`table_${value}_${index}`}>
149
+ <TableRow key={`table_${value}_${index}`}>
151
150
  {tableProperties && tableProperties.map(
152
151
  (key) => (
153
- <th
152
+ <TableCell
154
153
  key={`table-cell-${key}`}
155
154
  >
156
155
  <SkeletonPropertyComponent
157
156
  property={(properties)[key]}
158
157
  size={"medium"}/>
159
- </th>
158
+ </TableCell>
160
159
  )
161
160
  )}
162
- </tr>
161
+ </TableRow>
163
162
  );
164
163
  })}
165
- </tbody>
166
- </table>
164
+ </TableBody>
165
+ </Table>
167
166
  );
168
167
  }
169
168
 
@@ -1,6 +1,7 @@
1
1
  import type { EntityCollection, ViewMode } from "@rebasepro/types";
2
- import { Blocker, useBlocker, useLocation } from "react-router";
2
+ import { Blocker, useBlocker, useLocation } from "react-router-dom";
3
3
  import { EntityEditView } from "../components/EntityEditView";
4
+ import { EntityDetailView } from "../components/EntityDetailView";
4
5
  import { useEffect, useRef, useState } from "react";
5
6
  import { useNavigate } from "react-router-dom";
6
7
  import { EntityCollectionView } from "../components";
@@ -146,7 +147,7 @@ export function RebaseRoute() {
146
147
  // Resolve the effective openEntityMode based on the current view mode.
147
148
  // Priority: collection.openEntityMode (explicit) > view-mode-based default.
148
149
  // View mode priority: URL __view param > saved user config > collection default.
149
- let effectiveOpenMode: "side_panel" | "full_screen" | "split" | undefined = collection?.openEntityMode;
150
+ let effectiveOpenMode: "side_panel" | "full_screen" | "split" | "dialog" | undefined = collection?.openEntityMode;
150
151
  if (!effectiveOpenMode && collection) {
151
152
  const urlViewParam = new URLSearchParams(location.search).get("__view");
152
153
  let currentViewMode: ViewMode = collection.defaultViewMode ?? "list";
@@ -268,7 +269,7 @@ function EntityFullScreenRoute({
268
269
  if (entityIdIdx >= 0) {
269
270
  const afterEntity = pathname.substring(entityIdIdx + 1 + entityIdStr.length);
270
271
  const trailingSegment = afterEntity.startsWith("/") ? afterEntity.substring(1) : afterEntity;
271
- if (trailingSegment.length > 0) {
272
+ if (trailingSegment.length > 0 && trailingSegment !== "edit") {
272
273
  urlTab = trailingSegment;
273
274
  }
274
275
  }
@@ -290,35 +291,30 @@ function EntityFullScreenRoute({
290
291
 
291
292
  const entityPath = basePath + `/${entityId}`;
292
293
 
293
- let blocker: Blocker | undefined = undefined;
294
- try {
295
- blocker = useBlocker(({
296
- currentLocation,
297
- nextLocation
298
- }) => {
299
- if (nextLocation.pathname.startsWith(entityPath))
300
- return false;
301
-
302
- // Side panel overlay navigations preserve the underlying form via
303
- // base_location in router state no data is lost in either direction.
304
-
305
- // Opening a side panel (e.g. clicking a relation arrow)
306
- const nextHash = nextLocation.hash;
307
- if (nextHash === "#side" || nextHash === "#new_side")
308
- return false;
309
-
310
- // Closing a side panel (navigate(-1) back to the form's own path)
311
- const currentHash = currentLocation.hash;
312
- if ((currentHash === "#side" || currentHash === "#new_side") &&
313
- (nextLocation.pathname === basePath ||
314
- nextLocation.pathname.startsWith(entityPath)))
315
- return false;
316
-
317
- return blocked.current;
318
- });
319
- } catch (e) {
320
- // console.warn("Blocker not available, navigation will not be blocked");
321
- }
294
+ const blocker = useBlocker(({
295
+ currentLocation,
296
+ nextLocation
297
+ }) => {
298
+ if (nextLocation.pathname.startsWith(entityPath))
299
+ return false;
300
+
301
+ // Side panel overlay navigations preserve the underlying form via
302
+ // base_location in router state — no data is lost in either direction.
303
+
304
+ // Opening a side panel (e.g. clicking a relation arrow)
305
+ const nextHash = nextLocation.hash;
306
+ if (nextHash === "#side" || nextHash === "#new_side")
307
+ return false;
308
+
309
+ // Closing a side panel (navigate(-1) back to the form's own path)
310
+ const currentHash = currentLocation.hash;
311
+ if ((currentHash === "#side" || currentHash === "#new_side") &&
312
+ (nextLocation.pathname === basePath ||
313
+ nextLocation.pathname.startsWith(entityPath)))
314
+ return false;
315
+
316
+ return blocked.current;
317
+ });
322
318
 
323
319
  const lastCollectionEntry = [...navigationEntries].reverse().find((entry) => entry.type === "collection");
324
320
 
@@ -342,6 +338,38 @@ function EntityFullScreenRoute({
342
338
  const collection = collectionRegistry.getCollection(rawCollection.slug) || rawCollection;
343
339
  const fullIdPath = isNew ? lastCollectionEntry!.slug : lastEntityEntry!.slug;
344
340
  const collectionPath = urlController.resolveDatabasePathsFrom(fullIdPath);
341
+ const isEditRoute = pathname.endsWith("/edit") || pathname.split("/").pop() === "edit";
342
+ // Determine if this is a detail-view-first collection showing the view page
343
+ const isDetailMode = collection.defaultEntityAction === "view" && !isNew && !isCopy && entityId && !isEditRoute;
344
+
345
+ if (isDetailMode) {
346
+ return <>
347
+ <EntityDetailView
348
+ key={collection.slug + "_view_" + entityId}
349
+ entityId={entityId}
350
+ collection={collection}
351
+ layout={"full_screen"}
352
+ path={collectionPath}
353
+ selectedTab={selectedTab ?? undefined}
354
+ onEditClick={() => {
355
+ const editUrl = urlController.buildUrlCollectionPath(`${collectionPath}/${entityId}`) + "/edit";
356
+ navigate(editUrl + hash);
357
+ }}
358
+ onTabChange={(params) => {
359
+ setSelectedTab(params.selectedTab);
360
+ const newSelectedTab = params.selectedTab;
361
+ if (newSelectedTab) {
362
+ navigate(`${basePath}/${entityId}/${newSelectedTab}${hash}`, { replace: true });
363
+ } else {
364
+ navigate(`${basePath}/${entityId}${hash}`, { replace: true });
365
+ }
366
+ }}
367
+ parentCollectionSlugs={parentCollectionSlugs}
368
+ parentEntityIds={parentEntityIds}
369
+ />
370
+ </>;
371
+ }
372
+
345
373
  return <>
346
374
  <EntityEditView
347
375
  key={collection.slug + "_" + (isNew ? "new" : (isCopy ? entityId + "_copy" : entityId))}
@@ -353,11 +381,13 @@ function EntityFullScreenRoute({
353
381
  selectedTab={selectedTab ?? undefined}
354
382
  defaultValues={isNew ? defaultValues : undefined}
355
383
  onValuesModified={(modified) => blocked.current = modified}
384
+ navigateBack={() => {
385
+ const detailUrl = urlController.buildUrlCollectionPath(`${collectionPath}/${entityId}`);
386
+ navigate(detailUrl + hash);
387
+ }}
356
388
  onSaved={(params) => {
357
389
  const newSelectedTab = params.selectedTab;
358
390
  const newEntityId = params.entityId;
359
- // Clear the hash after saving a new entity — preserving #new
360
- // would cause the route to re-parse as "new" and show "not found".
361
391
  const savedHash = isNew ? "" : hash;
362
392
  if (newSelectedTab) {
363
393
  navigate(`${basePath}/${newEntityId}/${newSelectedTab}${savedHash}`, { replace: true });
@@ -385,6 +415,5 @@ function EntityFullScreenRoute({
385
415
  handleOk={() => blocker?.proceed?.()}
386
416
  handleCancel={() => blocker?.reset?.()}
387
417
  body={"You have unsaved changes in this entity."}/>
388
-
389
418
  </>;
390
419
  }
@@ -13,7 +13,7 @@ export interface EntityFormActionsProps {
13
13
  disabled: boolean;
14
14
  status: "new" | "existing" | "copy";
15
15
  pluginActions: React.ReactNode[];
16
- openEntityMode: "side_panel" | "full_screen" | "split";
16
+ openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
17
17
  showDefaultActions?: boolean;
18
18
  navigateBack: () => void;
19
19
  formContext: FormContext
@@ -22,7 +22,7 @@ export type EntityFormProps<M extends Record<string, unknown>> = {
22
22
  onStatusChange?: (status: EntityStatus) => void;
23
23
  onEntityChange?: (entity: Entity<M>) => void;
24
24
  formex?: FormexController<M>;
25
- openEntityMode?: "side_panel" | "full_screen" | "split";
25
+ openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
26
26
  /**
27
27
  * If true, the form will be disabled and no actions will be available
28
28
  */
@@ -39,6 +39,8 @@ export type EntityFormProps<M extends Record<string, unknown>> = {
39
39
 
40
40
  EntityFormActionsComponent?: React.FC<EntityFormActionsProps>;
41
41
 
42
+ navigateBack?: () => void;
43
+
42
44
  Builder?: React.ComponentType<EntityCustomViewParams<M>>;
43
45
 
44
46
  children?: React.ReactNode;
@@ -28,7 +28,8 @@ export type DefaultFieldConfig =
28
28
  | "key_value"
29
29
  | "repeat"
30
30
  | "custom_array"
31
- | "block";
31
+ | "block"
32
+ | "vector_input";
32
33
 
33
34
  /**
34
35
  * When building a custom field you need to create a React component that takes
@@ -130,7 +131,7 @@ export interface FieldProps<
130
131
  /**
131
132
  * Additional properties set by the developer
132
133
  */
133
- customProps: CustomProps
134
+ customProps?: CustomProps;
134
135
 
135
136
  /**
136
137
  * Additional values related to the state of the form or the entity
@@ -203,7 +204,7 @@ export interface FormContext<M extends Record<string, unknown> = Record<string,
203
204
 
204
205
  savingError?: Error;
205
206
 
206
- openEntityMode: "side_panel" | "full_screen" | "split";
207
+ openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
207
208
 
208
209
  /**
209
210
  * This is the underlying formex controller that powers the form.
@@ -30,7 +30,7 @@ export function navigateToEntity({
30
30
  }:
31
31
 
32
32
  {
33
- openEntityMode: "side_panel" | "full_screen" | "split";
33
+ openEntityMode: "side_panel" | "full_screen" | "split" | "dialog";
34
34
  collection?: EntityCollection;
35
35
  entityId?: string | number;
36
36
  selectedTab?: string;
@@ -50,7 +50,8 @@ export function navigateToEntity({
50
50
  navigation: UrlController
51
51
  }) {
52
52
 
53
- if (openEntityMode === "side_panel") {
53
+ if (openEntityMode === "side_panel" || openEntityMode === "dialog") {
54
+
54
55
 
55
56
  sideEntityController.open({
56
57
  entityId,
@@ -58,7 +59,7 @@ export function navigateToEntity({
58
59
  copy,
59
60
  selectedTab,
60
61
  collection,
61
- updateUrl: true,
62
+ updateUrl: openEntityMode !== "dialog",
62
63
  onClose,
63
64
  defaultValues
64
65
  });
@@ -21,7 +21,7 @@ export function getEntityPreviewKeys(
21
21
  return listProperties
22
22
  .filter(key => {
23
23
  const prop = targetCollection.properties[key];
24
- const isIdProp = prop && typeof prop === "object" && "isId" in prop && Boolean((prop as unknown as { isId?: boolean }).isId);
24
+ const isIdProp = prop && typeof prop === "object" && "isId" in prop && Boolean((prop as { isId?: boolean }).isId);
25
25
  return !isIdProp;
26
26
  })
27
27
  .filter(key => {
@@ -1,13 +1,27 @@
1
1
 
2
2
  import type { Properties } from "@rebasepro/types";
3
- import type { EntityCollection, MapProperty, Property, PropertyConfig } from "@rebasepro/types";
3
+ import type { EntityCollection, MapProperty, Property, PropertyConfig, StringProperty } from "@rebasepro/types";
4
4
  import React from "react";
5
5
 
6
6
  import { isPropertyBuilder } from "@rebasepro/common";
7
- import { iconSize } from "@rebasepro/ui";
8
- import type { IconSize } from "@rebasepro/ui";
9
- import { CircleIcon, FlagIcon, FunctionSquareIcon, GlobeIcon, TextIcon, Rows3Icon, LinkIcon, VoteIcon, MailIcon, HashIcon, RepeatIcon, CalendarIcon, AlignLeftIcon, UploadIcon } from "lucide-react";
10
- import type { LucideIcon } from "lucide-react";
7
+ import {
8
+ AlignLeftIcon,
9
+ CalendarIcon,
10
+ CircleIcon,
11
+ FlagIcon,
12
+ FunctionSquareIcon,
13
+ GlobeIcon,
14
+ HashIcon,
15
+ iconSize,
16
+ LinkIcon,
17
+ MailIcon,
18
+ RepeatIcon,
19
+ Rows3Icon,
20
+ TextIcon,
21
+ UploadIcon,
22
+ VoteIcon
23
+ } from "@rebasepro/ui";
24
+ import type { IconSize, LucideIcon } from "@rebasepro/ui";
11
25
 
12
26
  /**
13
27
  * Resolve a size value (string token or number) to a numeric pixel value
@@ -61,7 +75,7 @@ function getDefaultIconForProperty(property: Property): LucideIcon {
61
75
  if (property.ui?.url) return GlobeIcon;
62
76
  if (property.email) return MailIcon;
63
77
  if (property.ui?.multiline || property.ui?.markdown) return AlignLeftIcon;
64
- if ((property as any).reference) return LinkIcon;
78
+ if ((property as StringProperty).reference) return LinkIcon;
65
79
  return TextIcon;
66
80
  }
67
81
  case "number":
@@ -86,6 +100,8 @@ function getDefaultIconForProperty(property: Property): LucideIcon {
86
100
  return LinkIcon;
87
101
  case "relation":
88
102
  return LinkIcon;
103
+ case "vector":
104
+ return HashIcon;
89
105
  default:
90
106
  return CircleIcon;
91
107
  }
@@ -1,4 +1,4 @@
1
- import { HistoryIcon } from "lucide-react";
1
+ import { HistoryIcon } from "@rebasepro/ui";
2
2
  import React, { lazy } from "react";
3
3
  import type { EntityCustomView, EntityCollection } from "@rebasepro/types";
4
4
  import type { CustomizationController, EntityAction } from "@rebasepro/types";
@@ -52,7 +52,7 @@ export function resolvedSelectedEntityView<M extends Record<string, unknown>>(
52
52
  ) {
53
53
  const resolvedEntityViews = customViews
54
54
  ? customViews
55
- .map((e) => resolveEntityView(e, (customizationController as unknown as { entityViews?: EntityCustomView[] }).entityViews))
55
+ .map((e) => resolveEntityView(e, (customizationController as { entityViews?: EntityCustomView[] }).entityViews))
56
56
  .filter(Boolean)
57
57
  .filter((e) => (e as EntityCustomView).key !== "__rebase_history") as EntityCustomView[]
58
58
  : [];