@rebasepro/admin 0.0.1-canary.eae7889 → 0.1.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 (197) hide show
  1. package/dist/{CollectionEditorDialog-B2M9lCyL.js → CollectionEditorDialog-MbvXGzEq.js} +42 -31
  2. package/dist/CollectionEditorDialog-MbvXGzEq.js.map +1 -0
  3. package/dist/{CollectionsStudioView-WG6soyfs.js → CollectionsStudioView-D9X6aiAr.js} +12 -12
  4. package/dist/CollectionsStudioView-D9X6aiAr.js.map +1 -0
  5. package/dist/{ContentHomePage-CDF_a6Lp.js → ContentHomePage-CfVB1eUo.js} +26 -26
  6. package/dist/ContentHomePage-CfVB1eUo.js.map +1 -0
  7. package/dist/{ExportCollectionAction-Dc0VOWMN.js → ExportCollectionAction-CUwJg4F9.js} +2 -2
  8. package/dist/{ExportCollectionAction-Dc0VOWMN.js.map → ExportCollectionAction-CUwJg4F9.js.map} +1 -1
  9. package/dist/{ImportCollectionAction-DpCagAOy.js → ImportCollectionAction-DGa_SF_8.js} +2 -2
  10. package/dist/{ImportCollectionAction-DpCagAOy.js.map → ImportCollectionAction-DGa_SF_8.js.map} +1 -1
  11. package/dist/{PropertyEditView-DS67DxoT.js → PropertyEditView-C4nlYmAc.js} +82 -104
  12. package/dist/PropertyEditView-C4nlYmAc.js.map +1 -0
  13. package/dist/{RolesView-CIuYBimF.js → RolesView-CNWxnR8e.js} +7 -5
  14. package/dist/RolesView-CNWxnR8e.js.map +1 -0
  15. package/dist/{UsersView-B5zelXnH.js → UsersView-YiTIcXkA.js} +14 -35
  16. package/dist/UsersView-YiTIcXkA.js.map +1 -0
  17. package/dist/collection_editor/ConfigControllerProvider.d.ts +0 -4
  18. package/dist/collection_editor/types/collection_editor_controller.d.ts +6 -3
  19. package/dist/collection_editor/types/config_controller.d.ts +14 -7
  20. package/dist/collection_editor/ui/AddKanbanColumnAction.d.ts +3 -2
  21. package/dist/collection_editor/ui/CollectionViewHeaderAction.d.ts +3 -2
  22. package/dist/collection_editor/ui/EditorCollectionAction.d.ts +1 -1
  23. package/dist/collection_editor/ui/EditorCollectionActionStart.d.ts +1 -1
  24. package/dist/collection_editor/ui/EditorEntityAction.d.ts +1 -1
  25. package/dist/collection_editor/ui/KanbanSetupAction.d.ts +3 -2
  26. package/dist/collection_editor/ui/PropertyAddColumnComponent.d.ts +3 -2
  27. package/dist/collection_editor/ui/collection_editor/CollectionDetailsForm.d.ts +3 -4
  28. package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +2 -3
  29. package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -2
  30. package/dist/collection_editor/ui/collection_editor/SubcollectionsEditTab.d.ts +3 -2
  31. package/dist/collection_editor_ui.js +3 -3
  32. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  33. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
  34. package/dist/components/EntityCollectionTable/column_utils.d.ts +2 -2
  35. package/dist/components/EntityCollectionTable/fields/TableMultipleRelationField.d.ts +1 -1
  36. package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +1 -1
  37. package/dist/components/EntityCollectionTable/fields/TableRelationField.d.ts +1 -1
  38. package/dist/components/EntityCollectionTable/fields/TableRelationSelectorField.d.ts +2 -2
  39. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -1
  40. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +3 -2
  41. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +2 -1
  42. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +4 -2
  43. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +4 -2
  44. package/dist/components/EntityCollectionView/FiltersDialog.d.ts +2 -2
  45. package/dist/components/EntityCollectionView/SplitListView.d.ts +3 -2
  46. package/dist/components/EntityEditView.d.ts +9 -2
  47. package/dist/components/RebaseCMS.d.ts +1 -1
  48. package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +2 -2
  49. package/dist/components/ReferenceWidget.d.ts +2 -2
  50. package/dist/components/RelationSelector.d.ts +1 -1
  51. package/dist/components/SelectableTable/SelectableTable.d.ts +2 -2
  52. package/dist/editor.js +2 -2
  53. package/dist/editor.js.map +1 -1
  54. package/dist/hooks/navigation/useNavigationRegistry.d.ts +2 -1
  55. package/dist/hooks/useEntityHistory.d.ts +1 -1
  56. package/dist/{index-CHxgwt6E.js → index-CtzpHzMQ.js} +11 -4
  57. package/dist/index-CtzpHzMQ.js.map +1 -0
  58. package/dist/{index-Dey5WJpO.js → index-DKlrVD1m.js} +3 -3
  59. package/dist/index-DKlrVD1m.js.map +1 -0
  60. package/dist/{index-CBhrgpR7.js → index-kHJXfLNI.js} +3 -3
  61. package/dist/index-kHJXfLNI.js.map +1 -0
  62. package/dist/index.js +79 -63
  63. package/dist/index.js.map +1 -1
  64. package/dist/{useEntityHistory-Dcj4zhGj.js → useEntityHistory-UVsSclfZ.js} +3 -1
  65. package/dist/useEntityHistory-UVsSclfZ.js.map +1 -0
  66. package/dist/util/navigation_utils.d.ts +10 -1
  67. package/dist/{util-BQ82ySL3.js → util-CwLmSpGp.js} +1653 -1257
  68. package/dist/util-CwLmSpGp.js.map +1 -0
  69. package/package.json +9 -17
  70. package/src/collection_editor/ConfigControllerProvider.tsx +19 -28
  71. package/src/collection_editor/types/collection_editor_controller.tsx +3 -3
  72. package/src/collection_editor/types/config_controller.tsx +7 -7
  73. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +4 -4
  74. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +3 -3
  75. package/src/collection_editor/ui/EditorCollectionAction.tsx +3 -3
  76. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +7 -7
  77. package/src/collection_editor/ui/EditorEntityAction.tsx +3 -3
  78. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +4 -2
  79. package/src/collection_editor/ui/KanbanSetupAction.tsx +4 -3
  80. package/src/collection_editor/ui/MissingReferenceWidget.tsx +3 -2
  81. package/src/collection_editor/ui/NewCollectionButton.tsx +2 -1
  82. package/src/collection_editor/ui/NewCollectionCard.tsx +2 -1
  83. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +3 -3
  84. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +5 -50
  85. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +12 -20
  86. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +1 -3
  87. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +17 -2
  88. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +3 -3
  89. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +2 -1
  90. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +18 -12
  91. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +1 -2
  92. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
  93. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +6 -6
  94. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +4 -4
  95. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +2 -2
  96. package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +15 -49
  97. package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +4 -5
  98. package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +1 -1
  99. package/src/collection_editor/ui/collection_editor/templates/products_template.ts +2 -2
  100. package/src/components/DefaultAppBar.tsx +2 -2
  101. package/src/components/DefaultDrawer.tsx +25 -17
  102. package/src/components/DrawerNavigationGroup.tsx +4 -4
  103. package/src/components/DrawerNavigationItem.tsx +6 -6
  104. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +4 -4
  105. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  106. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +4 -4
  107. package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
  108. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +3 -3
  109. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +3 -3
  110. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +4 -4
  111. package/src/components/EntityCollectionTable/fields/TableRelationSelectorField.tsx +3 -3
  112. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +8 -2
  113. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +1 -1
  114. package/src/components/EntityCollectionTable/internal/common.tsx +5 -5
  115. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +1 -1
  116. package/src/components/EntityCollectionTable/table_bindings.tsx +45 -35
  117. package/src/components/EntityCollectionView/EntityBoardCard.tsx +18 -19
  118. package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
  119. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +42 -14
  120. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +4 -3
  121. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +157 -54
  122. package/src/components/EntityCollectionView/EntityCollectionView.tsx +169 -75
  123. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +23 -13
  124. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +21 -12
  125. package/src/components/EntityCollectionView/FiltersDialog.tsx +7 -7
  126. package/src/components/EntityCollectionView/SplitListView.tsx +24 -8
  127. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +33 -5
  128. package/src/components/EntityEditView.tsx +85 -85
  129. package/src/components/EntitySidePanel.tsx +18 -10
  130. package/src/components/HomePage/ContentHomePage.tsx +24 -15
  131. package/src/components/HomePage/NavigationCard.tsx +4 -4
  132. package/src/components/HomePage/NavigationGroup.tsx +2 -2
  133. package/src/components/RebaseAuthGate.tsx +2 -0
  134. package/src/components/RebaseCMS.tsx +4 -3
  135. package/src/components/RebaseNavigation.tsx +8 -5
  136. package/src/components/ReferenceTable/EntitySelectionTable.tsx +4 -4
  137. package/src/components/ReferenceWidget.tsx +3 -3
  138. package/src/components/RelationSelector.tsx +33 -5
  139. package/src/components/SelectableTable/SelectableTable.tsx +6 -6
  140. package/src/components/UserSelector.tsx +1 -1
  141. package/src/components/admin/RolesView.tsx +10 -3
  142. package/src/components/admin/UsersView.tsx +13 -25
  143. package/src/components/app/Scaffold.tsx +4 -4
  144. package/src/components/field_configs.tsx +29 -32
  145. package/src/components/history/EntityHistoryView.tsx +12 -1
  146. package/src/editor/editor.tsx +2 -2
  147. package/src/form/EntityForm.tsx +5 -4
  148. package/src/form/PropertyFieldBinding.tsx +14 -10
  149. package/src/form/components/FieldHelperText.tsx +1 -1
  150. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +3 -3
  151. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -5
  152. package/src/form/field_bindings/BlockFieldBinding.tsx +4 -4
  153. package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
  154. package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
  155. package/src/form/field_bindings/MapFieldBinding.tsx +7 -7
  156. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +1 -1
  157. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +3 -3
  158. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
  159. package/src/form/field_bindings/ReferenceFieldBinding.tsx +2 -2
  160. package/src/form/field_bindings/RelationFieldBinding.tsx +4 -4
  161. package/src/form/field_bindings/RepeatFieldBinding.tsx +5 -5
  162. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -1
  163. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +1 -1
  164. package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -1
  165. package/src/form/field_bindings/TextFieldBinding.tsx +7 -7
  166. package/src/form/field_bindings/UserSelectFieldBinding.tsx +1 -1
  167. package/src/form/useClearRestoreValue.tsx +1 -1
  168. package/src/form/validation.ts +1 -1
  169. package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +2 -1
  170. package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +15 -3
  171. package/src/hooks/navigation/useNavigationRegistry.ts +14 -3
  172. package/src/hooks/navigation/useResolvedViews.tsx +1 -3
  173. package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
  174. package/src/hooks/navigation/utils.ts +1 -1
  175. package/src/hooks/useEntityHistory.ts +7 -2
  176. package/src/preview/PropertyPreview.tsx +27 -23
  177. package/src/preview/components/StorageThumbnail.tsx +4 -1
  178. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
  179. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +1 -1
  180. package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +1 -1
  181. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +3 -3
  182. package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
  183. package/src/routes/RebaseRoute.tsx +57 -11
  184. package/src/util/navigation_utils.ts +21 -2
  185. package/src/util/previews.ts +15 -6
  186. package/src/util/property_utils.tsx +3 -3
  187. package/dist/CollectionEditorDialog-B2M9lCyL.js.map +0 -1
  188. package/dist/CollectionsStudioView-WG6soyfs.js.map +0 -1
  189. package/dist/ContentHomePage-CDF_a6Lp.js.map +0 -1
  190. package/dist/PropertyEditView-DS67DxoT.js.map +0 -1
  191. package/dist/RolesView-CIuYBimF.js.map +0 -1
  192. package/dist/UsersView-B5zelXnH.js.map +0 -1
  193. package/dist/index-CBhrgpR7.js.map +0 -1
  194. package/dist/index-CHxgwt6E.js.map +0 -1
  195. package/dist/index-Dey5WJpO.js.map +0 -1
  196. package/dist/useEntityHistory-Dcj4zhGj.js.map +0 -1
  197. package/dist/util-BQ82ySL3.js.map +0 -1
@@ -7,9 +7,8 @@ export function AdvancedPropertyValidation({ disabled }: {
7
7
  disabled: boolean
8
8
  }) {
9
9
 
10
- const columnWidth = "columnWidth";
11
- const hideFromCollection = "hideFromCollection";
12
- const readOnly = "readOnly";
10
+ const hideFromCollection = "ui.hideFromCollection";
11
+ const readOnly = "ui.readOnly";
13
12
 
14
13
  return (
15
14
 
@@ -19,7 +18,7 @@ export function AdvancedPropertyValidation({ disabled }: {
19
18
  {({ field, form }: FormexFieldProps) => {
20
19
  return <SwitchControl
21
20
  label={"Hide from collection"}
22
- size={"medium"}
21
+ size={"small"}
23
22
  disabled={disabled}
24
23
  form={form}
25
24
  tooltip={"Hide this field from the collection view. It will still be visible in the form view"}
@@ -34,7 +33,7 @@ export function AdvancedPropertyValidation({ disabled }: {
34
33
  {({ field, form }: FormexFieldProps) => {
35
34
  return <SwitchControl
36
35
  label={"Read only"}
37
- size={"medium"}
36
+ size={"small"}
38
37
  disabled={disabled}
39
38
  tooltip={"Is this a read only field. Display only as a preview"}
40
39
  form={form}
@@ -176,7 +176,7 @@ export const pagesCollectionTemplate = {
176
176
  is_published: {
177
177
  type: "boolean",
178
178
  name: "Is Published",
179
- columnWidth: 100,
179
+ ui: { columnWidth: 100 },
180
180
  description: "Should this page be live on the site?"
181
181
  }
182
182
  }
@@ -41,7 +41,7 @@ export const productsCollectionTemplate = {
41
41
  available: {
42
42
  type: "boolean",
43
43
  name: "Available",
44
- columnWidth: 100,
44
+ ui: { columnWidth: 100 },
45
45
  description: "Is this product available in the website"
46
46
  },
47
47
  price: {
@@ -55,7 +55,7 @@ export const productsCollectionTemplate = {
55
55
  images: {
56
56
  type: "array",
57
57
  name: "Images",
58
- hideFromCollection: true,
58
+ ui: { hideFromCollection: true },
59
59
  of: {
60
60
  type: "string",
61
61
  storage: {
@@ -110,9 +110,9 @@ export const DefaultAppBar = function DefaultAppBar({
110
110
  <div
111
111
  style={style}
112
112
  role="banner"
113
- className={cls("w-full h-16 transition-all ease-in duration-75 absolute top-0 max-w-full overflow-x-auto no-scrollbar",
113
+ className={cls("w-full h-14 transition-all ease-in duration-75 absolute top-0 max-w-full overflow-x-auto no-scrollbar",
114
114
  "flex flex-row gap-2 px-4 items-center",
115
- "backdrop-blur-md bg-surface-50/80 dark:bg-surface-900/80",
115
+ "backdrop-blur-sm bg-surface-50/95 dark:bg-surface-900/80",
116
116
  {
117
117
  "pl-[19rem]": drawerOpen && largeLayout,
118
118
  "pl-24": hasDrawer && !(drawerOpen && largeLayout),
@@ -1,9 +1,10 @@
1
1
  import type { NavigationEntry, NavigationResult } from "@rebasepro/types";
2
- import React from "react";
2
+ import React, { useMemo } from "react";
3
3
 
4
- import { useCollapsedGroups, useLargeLayout, useAdminModeController, useEffectiveRoleController, useTranslation, useSlot, useRebaseContext, useAnalyticsController, useRebaseRegistry, STUDIO_NAVIGATION_GROUPS } from "@rebasepro/core";
4
+ import { useCollapsedGroups, buildCollapsedDefaults, useLargeLayout, useAdminModeController, useTranslation, useSlot, useRebaseContext, useAnalyticsController, useRebaseRegistry } from "@rebasepro/core";
5
5
  import { useNavigationStateController, useUrlController } from "../hooks";
6
6
 
7
+
7
8
  import { Link, useNavigate } from "react-router-dom";
8
9
  import { AnalyticsEvent } from "@rebasepro/types";
9
10
  import { cls, Tooltip, Typography , iconSize } from "@rebasepro/ui";
@@ -57,22 +58,31 @@ export function DefaultDrawer({
57
58
 
58
59
  const tooltipsOpen = drawerHovered && !drawerOpen && !adminMenuOpen;
59
60
  const largeLayout = useLargeLayout();
60
- const navigate = useNavigate();
61
61
  const adminModeController = useAdminModeController();
62
- const effectiveRoleController = useEffectiveRoleController();
63
62
  const registry = useRebaseRegistry();
64
63
 
65
- const adminViews = navigationState.topLevelNavigation?.navigationEntries.filter(e => e.type === "admin") ?? [];
64
+ const allNavigationEntries = navigationState.topLevelNavigation?.navigationEntries ?? [];
66
65
 
67
- let groupsToRender = navigationState.topLevelNavigation?.groups ?? [];
68
- if (adminModeController.mode === "studio") {
69
- groupsToRender = groupsToRender.filter(g => STUDIO_NAVIGATION_GROUPS.includes(g));
70
- } else {
71
- groupsToRender = groupsToRender.filter(g => !STUDIO_NAVIGATION_GROUPS.includes(g));
72
- }
66
+ // Studio mode shows view-type entries (devViews) + admin entries (Users/Roles).
67
+ // Content mode shows collections and custom entries + admin entries (Users/Roles), but not studio views.
68
+ const filteredEntries = adminModeController.mode === "studio"
69
+ ? allNavigationEntries.filter(e => e.type === "view" || e.type === "admin")
70
+ : allNavigationEntries.filter(e => e.type !== "view");
71
+
72
+ // Derive groups from the filtered entries, preserving the order from topLevelNavigation.groups
73
+ const entryGroups = new Set(filteredEntries.map(e => e.group).filter(Boolean));
74
+ const orderedGroups = navigationState.topLevelNavigation?.groups ?? [];
75
+ const groupsToRender = [
76
+ ...orderedGroups.filter(g => entryGroups.has(g)),
77
+ ...[...entryGroups].filter(g => !orderedGroups.includes(g))
78
+ ];
73
79
 
74
80
  // Collapsible groups state - using "drawer" namespace for independent state from home page
75
- const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupsToRender, "drawer");
81
+ const collapsedDefaults = useMemo(
82
+ () => buildCollapsedDefaults(registry.cmsConfig?.navigationGroupMappings, "drawer"),
83
+ [registry.cmsConfig?.navigationGroupMappings]
84
+ );
85
+ const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupsToRender, "drawer", collapsedDefaults);
76
86
 
77
87
  const headerSlot = useSlot("navigation.header", { drawerOpen,
78
88
  drawerHovered,
@@ -84,7 +94,6 @@ context });
84
94
  if (!navigationState.topLevelNavigation)
85
95
  return null;
86
96
 
87
- const navigationEntries = navigationState.topLevelNavigation.navigationEntries;
88
97
  const groups = navigationState.topLevelNavigation.groups;
89
98
 
90
99
  const onItemClick = (view: NavigationEntry) => {
@@ -126,7 +135,7 @@ context });
126
135
  <div
127
136
  ref={scrollRef}
128
137
  onScroll={handleScroll}
129
- className={"flex-grow overflow-y-auto overflow-x-visible no-scrollbar"}
138
+ className={"flex-grow min-h-0 overflow-y-auto overflow-x-hidden no-scrollbar"}
130
139
  style={{
131
140
  maskImage: scrolled
132
141
  ? "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)"
@@ -134,7 +143,7 @@ context });
134
143
  }}>
135
144
 
136
145
  {groupsToRender.map((group) => {
137
- const entriesInGroup = Object.values(navigationEntries).filter(e => e.group === group);
146
+ const entriesInGroup = filteredEntries.filter(e => e.group === group);
138
147
  return (
139
148
  <DrawerNavigationGroup
140
149
  key={`drawer_group_${group}`}
@@ -146,7 +155,6 @@ context });
146
155
  tooltipsOpen={tooltipsOpen}
147
156
  adminMenuOpen={adminMenuOpen}
148
157
  onItemClick={onItemClick}
149
- hideHeader={adminModeController.mode === "studio"}
150
158
  />
151
159
  );
152
160
  })}
@@ -306,7 +314,7 @@ function DrawerModeSwitch({
306
314
  return (
307
315
  <div
308
316
  className={cls(
309
- "overflow-hidden transition-all duration-200 ease-in-out px-3",
317
+ "shrink-0 overflow-hidden transition-all duration-200 ease-in-out px-3",
310
318
  showSwitch ? "opacity-100 h-7 mt-2 mb-0" : "opacity-0 pointer-events-none h-7 mt-2 mb-0"
311
319
  )}
312
320
  >
@@ -75,7 +75,7 @@ export function DrawerNavigationGroup({
75
75
  {/* Group Header */}
76
76
  {!hideHeader && (
77
77
  <div
78
- className={cls("pl-4 pr-2 py-0.5 flex flex-row items-center transition-colors",
78
+ className={cls("pl-3 pr-2 py-0.5 flex flex-row items-center transition-colors",
79
79
  drawerOpen ? "cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-800/40 rounded-lg" : "opacity-0 invisible pointer-events-none"
80
80
  )}
81
81
  onClick={drawerOpen ? onToggleCollapsed : undefined}
@@ -83,14 +83,14 @@ export function DrawerNavigationGroup({
83
83
  <ChevronDownIcon
84
84
  size={iconSize.small}
85
85
  className={cls(
86
- "text-surface-500 dark:text-surface-400 transition-transform duration-200 mr-1",
86
+ "text-surface-400 dark:text-surface-400 transition-transform duration-200 mr-1",
87
87
  collapsed ? "-rotate-90" : "rotate-0"
88
88
  )}
89
89
  />
90
90
  <Typography
91
91
  variant={"caption"}
92
92
  color={"secondary"}
93
- className="font-medium flex-grow line-clamp-1"
93
+ className="font-semibold text-[11px] uppercase tracking-wider flex-grow line-clamp-1 text-surface-400 dark:text-surface-400"
94
94
  >
95
95
  {(group || t("views_group"))}
96
96
  </Typography>
@@ -106,7 +106,7 @@ export function DrawerNavigationGroup({
106
106
  <div
107
107
  className={cls(
108
108
  "transition-all duration-200 ease-in-out",
109
- (!hideHeader && collapsed) ? "overflow-hidden" : "overflow-visible",
109
+ "overflow-hidden",
110
110
  !hideHeader && "dark:bg-transparent",
111
111
  !hideHeader ? (drawerOpen ? "rounded-lg" : "rounded-lg") : "rounded-lg",
112
112
  (!hideHeader && collapsed) ? "max-h-0 opacity-0" : "max-h-[2000px] opacity-100"
@@ -22,7 +22,7 @@ export function DrawerNavigationItem({
22
22
  }) {
23
23
 
24
24
  const iconWrap = <div
25
- className={"shrink-0 flex items-center justify-center w-[56px] h-[40px] text-text-secondary dark:text-text-secondary-dark"}>
25
+ className={"shrink-0 flex items-center justify-center w-[44px] h-[30px] text-surface-500 dark:text-text-secondary-dark [&>svg]:size-4"}>
26
26
  {icon}
27
27
  </div>;
28
28
 
@@ -33,12 +33,12 @@ export function DrawerNavigationItem({
33
33
  width: "100%",
34
34
  transition: drawerOpen ? "width 150ms ease-in" : undefined
35
35
  }}
36
- className={({ isActive }: any) => cls("rounded-lg truncate",
37
- "hover:bg-surface-100 dark:hover:bg-surface-800/60 text-text-primary dark:text-surface-300 hover:text-surface-900 dark:hover:text-white",
36
+ className={({ isActive }: any) => cls("rounded-md truncate",
37
+ "hover:bg-surface-100 dark:hover:bg-surface-800/60 text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white",
38
38
  "flex flex-row items-center",
39
- drawerOpen ? "pr-4 h-10" : "h-10",
40
- "font-semibold text-xs",
41
- isActive ? "bg-surface-100 dark:bg-surface-800/50 text-surface-900 dark:text-white" : ""
39
+ drawerOpen ? "pr-4 h-[30px]" : "h-[30px]",
40
+ "font-medium text-[13px]",
41
+ isActive ? "bg-surface-900/[0.06] dark:bg-surface-800/50 text-surface-900 dark:text-white" : ""
42
42
  )}
43
43
  to={url}
44
44
  >
@@ -46,7 +46,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
46
46
  ({
47
47
  className,
48
48
  style,
49
- forceFilter,
49
+ fixedFilter,
50
50
  actionsStart,
51
51
  actions,
52
52
  viewModeToggle,
@@ -143,7 +143,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
143
143
  propertyKey,
144
144
  entity
145
145
  }) ?? column.custom.resolvedProperty;
146
- if (!property?.disabled) {
146
+ if (!property?.ui?.disabled) {
147
147
  disabled = false;
148
148
  }
149
149
 
@@ -248,7 +248,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
248
248
  const columnsResult: VirtualTableColumn[] = propertiesToColumns({
249
249
  properties,
250
250
  sortable,
251
- forceFilter,
251
+ fixedFilter,
252
252
  AdditionalHeaderWidget
253
253
  });
254
254
 
@@ -269,7 +269,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
269
269
  }))
270
270
  : [];
271
271
  return [...columnsResult, ...additionalTableColumns];
272
- }, [properties, sortable, forceFilter, AdditionalHeaderWidget, additionalFields]);
272
+ }, [properties, sortable, fixedFilter, AdditionalHeaderWidget, additionalFields]);
273
273
 
274
274
  const idColumn: VirtualTableColumn = useMemo(() => ({
275
275
  key: "id_ewcfedcswdf3",
@@ -111,7 +111,7 @@ export type EntityCollectionTableProps<M extends Record<string, unknown>,
111
111
 
112
112
  displayedColumnIds?: PropertyColumnConfig[];
113
113
 
114
- forceFilter?: FilterValues<Extract<keyof M, string>>;
114
+ fixedFilter?: FilterValues<Extract<keyof M, string>>;
115
115
 
116
116
  inlineEditing?: boolean;
117
117
 
@@ -89,11 +89,11 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
89
89
  setSavedTimestamp(Date.now());
90
90
  }, []);
91
91
 
92
- const customField = Boolean(property.Field);
93
- const customPreview = Boolean(property.Preview);
92
+ const customField = Boolean(property.ui?.Field);
93
+ const customPreview = Boolean(property.ui?.Preview);
94
94
  const readOnlyProperty = isReadOnly(property);
95
- const disabledTooltip: string | undefined = typeof property.disabled === "object" ? property.disabled.disabledMessage : undefined;
96
- const disabled = readonly || disabledProp || Boolean(property.disabled);
95
+ const disabledTooltip: string | undefined = typeof property.ui?.disabled === "object" ? property.ui?.disabled.disabledMessage : undefined;
96
+ const disabled = readonly || disabledProp || Boolean(property.ui?.disabled);
97
97
 
98
98
  const validation = useMemo(() => mapPropertyToZod({
99
99
  property,
@@ -21,7 +21,7 @@ export function buildIdColumn(largeLayout?: boolean): VirtualTableColumn {
21
21
  export interface PropertiesToColumnsParams<M extends Record<string, unknown>> {
22
22
  properties: Properties;
23
23
  sortable?: boolean;
24
- forceFilter?: FilterValues<keyof M extends string ? keyof M : never>;
24
+ fixedFilter?: FilterValues<keyof M extends string ? keyof M : never>;
25
25
  AdditionalHeaderWidget?: React.ComponentType<{
26
26
  property: Property,
27
27
  propertyKey: string,
@@ -29,8 +29,8 @@ export interface PropertiesToColumnsParams<M extends Record<string, unknown>> {
29
29
  }>;
30
30
  }
31
31
 
32
- export function propertiesToColumns<M extends Record<string, unknown>>({ properties, sortable, forceFilter, AdditionalHeaderWidget }: PropertiesToColumnsParams<M>): VirtualTableColumn[] {
33
- const disabledFilter = Boolean(forceFilter);
32
+ export function propertiesToColumns<M extends Record<string, unknown>>({ properties, sortable, fixedFilter, AdditionalHeaderWidget }: PropertiesToColumnsParams<M>): VirtualTableColumn[] {
33
+ const disabledFilter = Boolean(fixedFilter);
34
34
  return Object.entries<Property>(properties)
35
35
  .flatMap(([key, property]) => getColumnKeysForProperty(property, key))
36
36
  .map(({
@@ -22,7 +22,7 @@ type TableMultipleRelationFieldProps = {
22
22
  previewProperties?: string[];
23
23
  title?: string;
24
24
  relation: Relation;
25
- forceFilter?: FilterValues<string>;
25
+ fixedFilter?: FilterValues<string>;
26
26
  includeId?: boolean;
27
27
  includeEntityLink?: boolean;
28
28
  };
@@ -43,7 +43,7 @@ export const TableMultipleRelationFieldInternal = React.memo(
43
43
  previewProperties,
44
44
  title,
45
45
  disabled,
46
- forceFilter,
46
+ fixedFilter,
47
47
  collection,
48
48
  includeId,
49
49
  includeEntityLink
@@ -63,7 +63,7 @@ export const TableMultipleRelationFieldInternal = React.memo(
63
63
  collection,
64
64
  onMultipleEntitiesSelected,
65
65
  selectedEntityIds,
66
- forceFilter
66
+ fixedFilter
67
67
  }
68
68
  );
69
69
 
@@ -25,7 +25,7 @@ type TableReferenceFieldProps = {
25
25
  previewProperties?: string[];
26
26
  title?: string;
27
27
  path: string;
28
- forceFilter?: FilterValues<string>;
28
+ fixedFilter?: FilterValues<string>;
29
29
  includeId?: boolean;
30
30
  includeEntityLink?: boolean;
31
31
  };
@@ -60,7 +60,7 @@ export const TableReferenceFieldInternal = React.memo(
60
60
  previewProperties,
61
61
  title,
62
62
  disabled,
63
- forceFilter,
63
+ fixedFilter,
64
64
  collection,
65
65
  includeId,
66
66
  includeEntityLink
@@ -87,7 +87,7 @@ export const TableReferenceFieldInternal = React.memo(
87
87
  onMultipleEntitiesSelected,
88
88
  onSingleEntitySelected,
89
89
  selectedEntityIds,
90
- forceFilter
90
+ fixedFilter
91
91
  }
92
92
  );
93
93
 
@@ -25,7 +25,7 @@ type TableRelationFieldProps = {
25
25
  previewProperties?: string[];
26
26
  title?: string;
27
27
  relation: Relation;
28
- forceFilter?: FilterValues<string>;
28
+ fixedFilter?: FilterValues<string>;
29
29
  includeId?: boolean;
30
30
  includeEntityLink?: boolean;
31
31
  };
@@ -46,7 +46,7 @@ export function TableRelationField(props: TableRelationFieldProps) {
46
46
  previewProperties={props.previewProperties}
47
47
  title={props.title}
48
48
  relation={props.relation}
49
- forceFilter={props.forceFilter}
49
+ fixedFilter={props.fixedFilter}
50
50
  includeId={props.includeId}
51
51
  includeEntityLink={props.includeEntityLink}
52
52
  />;
@@ -69,7 +69,7 @@ export const TableRelationFieldInternal = React.memo(
69
69
  previewProperties,
70
70
  title,
71
71
  disabled,
72
- forceFilter,
72
+ fixedFilter,
73
73
  collection,
74
74
  includeId,
75
75
  includeEntityLink
@@ -96,7 +96,7 @@ export const TableRelationFieldInternal = React.memo(
96
96
  onMultipleEntitiesSelected,
97
97
  onSingleEntitySelected,
98
98
  selectedEntityIds,
99
- forceFilter
99
+ fixedFilter
100
100
  }
101
101
  );
102
102
 
@@ -14,7 +14,7 @@ interface RelationSelectorFieldProps {
14
14
  /** The relation configuration */
15
15
  relation: Relation;
16
16
  /** Force filter to be applied to the relation search */
17
- forceFilter?: FilterValues<string>;
17
+ fixedFilter?: FilterValues<string>;
18
18
  /** Collection size for display */
19
19
  size?: "small" | "medium";
20
20
  }
@@ -25,7 +25,7 @@ export function TableRelationSelectorField({
25
25
  internalValue,
26
26
  updateValue,
27
27
  relation,
28
- forceFilter,
28
+ fixedFilter,
29
29
  size = "medium"
30
30
  }: RelationSelectorFieldProps) {
31
31
 
@@ -36,7 +36,7 @@ export function TableRelationSelectorField({
36
36
  value={internalValue || null}
37
37
  onValueChange={(newVal) => updateValue(newVal ?? null)}
38
38
  relation={relation}
39
- forceFilter={forceFilter}
39
+ fixedFilter={fixedFilter}
40
40
  />
41
41
  );
42
42
  }
@@ -13,6 +13,10 @@ interface CollectionTableToolbarProps {
13
13
  viewModeToggle?: React.ReactNode;
14
14
  title?: React.ReactNode,
15
15
  onTextSearch?: (searchString?: string) => void;
16
+ /**
17
+ * Initial search string to pre-populate the search bar (e.g. from URL params).
18
+ */
19
+ initialSearchText?: string;
16
20
  /**
17
21
  * When true the toolbar is in "compact" mode for the split-view left panel.
18
22
  * - Search bar, loading spinner, and view-mode toggle are hidden.
@@ -29,6 +33,7 @@ export function CollectionTableToolbar({
29
33
  onTextSearch,
30
34
  title,
31
35
  viewModeToggle,
36
+ initialSearchText,
32
37
  compact = false
33
38
  }: CollectionTableToolbarProps) {
34
39
 
@@ -54,7 +59,7 @@ export function CollectionTableToolbar({
54
59
  {viewModeToggle}
55
60
  </div>
56
61
 
57
- {title && <div className={"hidden lg:block"}>
62
+ {title && <div className={"flex items-center"}>
58
63
  {title}
59
64
  </div>}
60
65
 
@@ -84,7 +89,8 @@ export function CollectionTableToolbar({
84
89
  size={"small"}
85
90
  placeholder={t("search")}
86
91
  onTextSearch={onTextSearch}
87
- expandable={true}/>}
92
+ expandable={true}
93
+ initialValue={initialSearchText}/>}
88
94
  </div>
89
95
 
90
96
  {/* Secondary actions — always inline */}
@@ -204,7 +204,7 @@ export const EntityTableCell = React.memo<EntityTableCellProps>(
204
204
  `flex relative h-full rounded-md p-${p} border-4`,
205
205
  showSaved ? "bg-primary/20 dark:bg-primary/20" : (onHover && !disabled ? "bg-surface-50 dark:bg-surface-900" : ""),
206
206
  hideOverflow ? "overflow-hidden" : "",
207
- isSelected && !showSaved ? "bg-surface-50 dark:bg-surface-900" : "",
207
+ isSelected && !showSaved ? "bg-surface-accent-50 dark:bg-surface-accent-950" : "",
208
208
  borderClass
209
209
  )}
210
210
  ref={ref}
@@ -17,20 +17,20 @@ export function getTableCellAlignment(property: Property): "right" | "left" | "c
17
17
 
18
18
  export function getTablePropertyColumnWidth(property: Property): number {
19
19
 
20
- if (property.columnWidth) {
21
- return property.columnWidth;
20
+ if (property.ui?.columnWidth) {
21
+ return property.ui?.columnWidth;
22
22
  }
23
23
 
24
24
  if (property.type === "string") {
25
- if (property.url) {
25
+ if (property.ui?.url) {
26
26
  return 280;
27
27
  } else if (property.storage) {
28
28
  return 160;
29
29
  } else if (property.enum) {
30
30
  return 200;
31
- } else if (property.multiline) {
31
+ } else if (property.ui?.multiline) {
32
32
  return 300;
33
- } else if (property.markdown) {
33
+ } else if (property.ui?.markdown) {
34
34
  return 300;
35
35
  } else if (property.email) {
36
36
  return 200;
@@ -291,7 +291,7 @@ export function PopupFormFieldInternal<M extends Record<string, unknown>>({
291
291
  const fieldProps: PropertyFieldBindingProps<M> | undefined = propertyKey && property
292
292
  ? {
293
293
  propertyKey: propertyKey as string,
294
- disabled: isSubmitting || isReadOnly(property) || !!property.disabled,
294
+ disabled: isSubmitting || isReadOnly(property) || !!property.ui?.disabled,
295
295
  property,
296
296
  includeDescription: false,
297
297
  underlyingValueHasChanged: false,
@@ -41,7 +41,7 @@ export interface TableFieldConfig {
41
41
  }
42
42
 
43
43
  export function isStorageProperty(property: Property) {
44
- if (property.type === "string" && property.markdown)
44
+ if (property.type === "string" && property.ui?.markdown)
45
45
  return false;
46
46
  if (property.type === "string" && (property as StringProperty).storage)
47
47
  return true;
@@ -81,7 +81,7 @@ path: referenceProperty.path as string }) : undefined;
81
81
  includeId={referenceProperty.includeId}
82
82
  includeEntityLink={referenceProperty.includeEntityLink}
83
83
  title={property.name}
84
- forceFilter={referenceProperty.forceFilter}
84
+ fixedFilter={referenceProperty.fixedFilter}
85
85
  />
86
86
  );
87
87
  },
@@ -181,8 +181,8 @@ path: referenceProperty.path as string }) : undefined;
181
181
  ),
182
182
  fullHeight: true
183
183
  };
184
- } else if (stringProperty.markdown || !stringProperty.storage || !stringProperty.reference) {
185
- const multiline = Boolean(stringProperty.multiline) || Boolean(stringProperty.markdown);
184
+ } else if (stringProperty.ui?.markdown || !stringProperty.storage || !stringProperty.reference) {
185
+ const multiline = Boolean(stringProperty.ui?.multiline) || Boolean(stringProperty.ui?.markdown);
186
186
  return {
187
187
  Component: ({ error, validationError, disabled, selected, internalValue, updateValue }: any) => (
188
188
  <VirtualTableInput
@@ -238,11 +238,11 @@ path: referenceProperty.path as string }) : undefined;
238
238
  size={size}
239
239
  path={property.path}
240
240
  multiselect={false}
241
- previewProperties={property.previewProperties}
241
+ previewProperties={property.ui?.previewProperties}
242
242
  includeId={property.includeId}
243
243
  includeEntityLink={property.includeEntityLink}
244
244
  title={property.name ?? propertyKey}
245
- forceFilter={property.forceFilter}
245
+ fixedFilter={property.fixedFilter}
246
246
  />
247
247
  ),
248
248
  allowScroll: false
@@ -250,39 +250,14 @@ path: referenceProperty.path as string }) : undefined;
250
250
  }
251
251
  } else if (property.type === "relation") {
252
252
  if (property.relation) {
253
- if (property.widget === "dialog") {
253
+ if (property.ui?.widget === "dialog") {
254
254
  return {
255
- Component: ({ propertyKey, internalValue, updateValue, disabled, size, property }: any) => (
256
- <TableRelationField
257
- name={propertyKey}
258
- internalValue={internalValue as EntityRelation}
259
- updateValue={updateValue}
260
- disabled={disabled}
261
- size={size}
262
- multiselect={false}
263
- relation={property.relation}
264
- previewProperties={property.previewProperties}
265
- includeId={property.includeId}
266
- includeEntityLink={property.includeEntityLink}
267
- title={property.name ?? propertyKey}
268
- forceFilter={property.forceFilter}
269
- />
270
- ),
255
+ Component: RelationDialogBindingComponent,
271
256
  allowScroll: false
272
257
  };
273
258
  } else {
274
259
  return {
275
- Component: ({ propertyKey, internalValue, updateValue, disabled, property }: any) => (
276
- <TableRelationSelectorField
277
- name={propertyKey}
278
- internalValue={internalValue as EntityRelation}
279
- updateValue={updateValue}
280
- disabled={disabled}
281
- size={"small"}
282
- relation={property.relation!}
283
- forceFilter={property.forceFilter}
284
- />
285
- ),
260
+ Component: RelationSelectorBindingComponent,
286
261
  allowScroll: false
287
262
  };
288
263
  }
@@ -330,7 +305,7 @@ path: referenceProperty.path as string }) : undefined;
330
305
  path={ofProp.path}
331
306
  previewProperties={ofProp.previewProperties}
332
307
  title={arrayProperty.name}
333
- forceFilter={ofProp.forceFilter}
308
+ fixedFilter={ofProp.fixedFilter}
334
309
  includeId={ofProp.includeId}
335
310
  includeEntityLink={ofProp.includeEntityLink}
336
311
  />
@@ -344,3 +319,38 @@ path: referenceProperty.path as string }) : undefined;
344
319
 
345
320
  return undefined;
346
321
  }
322
+
323
+ /** Stable component for relation fields rendered with the dialog widget */
324
+ function RelationDialogBindingComponent({ propertyKey, internalValue, updateValue, disabled, size, property }: any) {
325
+ return (
326
+ <TableRelationField
327
+ name={propertyKey}
328
+ internalValue={internalValue as EntityRelation}
329
+ updateValue={updateValue}
330
+ disabled={disabled}
331
+ size={size}
332
+ multiselect={false}
333
+ relation={property.relation}
334
+ previewProperties={property.ui?.previewProperties}
335
+ includeId={property.includeId}
336
+ includeEntityLink={property.includeEntityLink}
337
+ title={property.name ?? propertyKey}
338
+ fixedFilter={property.fixedFilter}
339
+ />
340
+ );
341
+ }
342
+
343
+ /** Stable component for relation fields rendered with the inline selector */
344
+ function RelationSelectorBindingComponent({ propertyKey, internalValue, updateValue, disabled, property }: any) {
345
+ return (
346
+ <TableRelationSelectorField
347
+ name={propertyKey}
348
+ internalValue={internalValue as EntityRelation}
349
+ updateValue={updateValue}
350
+ disabled={disabled}
351
+ size={"small"}
352
+ relation={property.relation!}
353
+ fixedFilter={property.fixedFilter}
354
+ />
355
+ );
356
+ }