@rebasepro/admin 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/LICENSE +21 -6
  2. package/dist/{CollectionEditorDialog-MbvXGzEq.js → CollectionEditorDialog-BXIh2AXg.js} +40 -31
  3. package/dist/CollectionEditorDialog-BXIh2AXg.js.map +1 -0
  4. package/dist/{CollectionsStudioView-D9X6aiAr.js → CollectionsStudioView-jR8iz_ja.js} +6 -8
  5. package/dist/CollectionsStudioView-jR8iz_ja.js.map +1 -0
  6. package/dist/{ContentHomePage-CfVB1eUo.js → ContentHomePage-BQZWuOFb.js} +5 -7
  7. package/dist/ContentHomePage-BQZWuOFb.js.map +1 -0
  8. package/dist/{ExportCollectionAction-CUwJg4F9.js → ExportCollectionAction-CMdiiv1L.js} +36 -38
  9. package/dist/ExportCollectionAction-CMdiiv1L.js.map +1 -0
  10. package/dist/{ImportCollectionAction-DGa_SF_8.js → ImportCollectionAction-C05lE0IW.js} +5 -7
  11. package/dist/ImportCollectionAction-C05lE0IW.js.map +1 -0
  12. package/dist/{PropertyEditView-C4nlYmAc.js → PropertyEditView-BB5xjnhZ.js} +261 -165
  13. package/dist/PropertyEditView-BB5xjnhZ.js.map +1 -0
  14. package/dist/{RolesView-CNWxnR8e.js → RolesView-CULIHWZ9.js} +22 -11
  15. package/dist/RolesView-CULIHWZ9.js.map +1 -0
  16. package/dist/{UsersView-YiTIcXkA.js → UsersView-D7_AtJ44.js} +7 -71
  17. package/dist/UsersView-D7_AtJ44.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/VectorPropertyField.d.ts +3 -0
  20. package/dist/collection_editor_ui.js +5 -5
  21. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
  22. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
  23. package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
  24. package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
  25. package/dist/components/EntityDetailView.d.ts +31 -0
  26. package/dist/components/EntityEditView.d.ts +3 -2
  27. package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
  28. package/dist/components/admin/CreationResultDialog.d.ts +5 -0
  29. package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
  30. package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
  31. package/dist/components/common/default_entity_actions.d.ts +7 -1
  32. package/dist/components/field_configs.d.ts +1 -1
  33. package/dist/components/index.d.ts +1 -0
  34. package/dist/data_import/utils/data.d.ts +1 -1
  35. package/dist/data_import/utils/file_headers.d.ts +6 -1
  36. package/dist/data_import/utils/file_to_json.d.ts +1 -11
  37. package/dist/data_import/utils/transforms.d.ts +11 -0
  38. package/dist/editor.js +2 -4
  39. package/dist/editor.js.map +1 -1
  40. package/dist/form/EntityForm.d.ts +1 -1
  41. package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
  42. package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
  43. package/dist/form/index.d.ts +1 -0
  44. package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
  45. package/dist/{index-CtzpHzMQ.js → index-BAM9KCmM.js} +4 -6
  46. package/dist/index-BAM9KCmM.js.map +1 -0
  47. package/dist/{index-DKlrVD1m.js → index-CoSNm3e3.js} +3 -3
  48. package/dist/index-CoSNm3e3.js.map +1 -0
  49. package/dist/{index-kHJXfLNI.js → index-D5OQhv-T.js} +3 -3
  50. package/dist/index-D5OQhv-T.js.map +1 -0
  51. package/dist/index.d.ts +4 -1
  52. package/dist/index.js +352 -148
  53. package/dist/index.js.map +1 -1
  54. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  55. package/dist/types/components/EntityFormProps.d.ts +2 -1
  56. package/dist/types/fields.d.ts +3 -3
  57. package/dist/util/navigation_utils.d.ts +1 -1
  58. package/dist/{util-CwLmSpGp.js → util-DtbWD7LF.js} +5312 -2580
  59. package/dist/util-DtbWD7LF.js.map +1 -0
  60. package/package.json +45 -39
  61. package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
  62. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
  63. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
  64. package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
  65. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
  66. package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
  67. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
  68. package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
  69. package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
  70. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
  71. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
  72. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
  73. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +22 -7
  74. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
  75. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
  76. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
  77. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
  78. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
  79. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
  80. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
  81. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
  82. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
  83. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
  84. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
  85. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
  86. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
  87. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
  88. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
  89. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
  90. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
  91. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
  92. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
  93. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
  94. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
  95. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
  96. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
  97. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
  98. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
  99. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
  100. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
  101. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
  102. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
  103. package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
  104. package/src/collection_editor/validateCollectionJson.ts +9 -9
  105. package/src/components/AdminModeSyncer.tsx +1 -1
  106. package/src/components/ArrayContainer.tsx +19 -15
  107. package/src/components/ClearFilterSortButton.tsx +1 -2
  108. package/src/components/CollectionEditorDialogs.tsx +1 -1
  109. package/src/components/DefaultAppBar.tsx +15 -3
  110. package/src/components/DefaultDrawer.tsx +3 -3
  111. package/src/components/DrawerNavigationGroup.tsx +1 -2
  112. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +19 -9
  113. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +2 -2
  114. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  115. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
  116. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
  117. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
  118. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
  119. package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
  120. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
  121. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +3 -4
  122. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
  123. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
  124. package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
  125. package/src/components/EntityCollectionView/Board.tsx +1 -2
  126. package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
  127. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
  128. package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
  129. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
  130. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
  131. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +90 -21
  132. package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
  133. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
  134. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
  135. package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
  136. package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
  137. package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
  138. package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
  139. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
  140. package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
  141. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
  142. package/src/components/EntityDetailView.tsx +619 -0
  143. package/src/components/EntityEditView.tsx +29 -10
  144. package/src/components/EntityEditViewFormActions.tsx +20 -7
  145. package/src/components/EntityPreview.tsx +14 -5
  146. package/src/components/EntitySidePanel.tsx +116 -62
  147. package/src/components/EntityView.tsx +1 -2
  148. package/src/components/HomePage/ContentHomePage.tsx +1 -1
  149. package/src/components/HomePage/FavouritesView.tsx +1 -2
  150. package/src/components/HomePage/NavigationCard.tsx +1 -2
  151. package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
  152. package/src/components/HomePage/NavigationGroup.tsx +1 -2
  153. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  154. package/src/components/PropertyIdCopyTooltip.tsx +1 -2
  155. package/src/components/RebaseAuthGate.tsx +2 -2
  156. package/src/components/RebaseNavigation.tsx +9 -7
  157. package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
  158. package/src/components/RelationSelector.tsx +34 -6
  159. package/src/components/SearchIconsView.tsx +10 -2
  160. package/src/components/SelectableTable/SelectableTable.tsx +4 -4
  161. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
  162. package/src/components/SideDialogs.tsx +63 -38
  163. package/src/components/UserSelector.tsx +30 -6
  164. package/src/components/admin/CreationResultDialog.tsx +135 -0
  165. package/src/components/admin/RolesFilterSelect.tsx +45 -0
  166. package/src/components/admin/RolesView.tsx +53 -14
  167. package/src/components/admin/UserRolesSelectField.tsx +50 -0
  168. package/src/components/admin/UsersView.tsx +41 -124
  169. package/src/components/app/Scaffold.tsx +1 -2
  170. package/src/components/common/default_entity_actions.tsx +119 -12
  171. package/src/components/field_configs.tsx +39 -3
  172. package/src/components/history/EntityHistoryEntry.tsx +1 -2
  173. package/src/components/history/EntityHistoryView.tsx +1 -2
  174. package/src/components/index.ts +2 -0
  175. package/src/data_export/export/BasicExportAction.tsx +35 -38
  176. package/src/data_export/export/ExportCollectionAction.tsx +39 -40
  177. package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
  178. package/src/data_import/components/ImportFileUpload.tsx +1 -2
  179. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
  180. package/src/data_import/import/ImportCollectionAction.tsx +21 -8
  181. package/src/data_import/utils/data.ts +23 -5
  182. package/src/data_import/utils/file_headers.ts +13 -89
  183. package/src/data_import/utils/file_to_json.ts +43 -68
  184. package/src/data_import/utils/transforms.ts +47 -0
  185. package/src/editor/components/SlashCommandMenu.tsx +17 -2
  186. package/src/editor/components/editor-bubble-item.tsx +1 -1
  187. package/src/editor/extensions/Image/index.ts +1 -1
  188. package/src/editor/extensions/Image.ts +1 -1
  189. package/src/editor/selectors/color-selector.tsx +1 -2
  190. package/src/editor/selectors/link-selector.tsx +1 -2
  191. package/src/editor/selectors/node-selector.tsx +16 -2
  192. package/src/editor/selectors/text-buttons.tsx +1 -2
  193. package/src/editor/utils/prosemirror-utils.ts +1 -1
  194. package/src/form/EntityForm.tsx +16 -6
  195. package/src/form/EntityFormActions.tsx +11 -3
  196. package/src/form/PropertyFieldBinding.tsx +5 -12
  197. package/src/form/components/FieldHelperText.tsx +1 -2
  198. package/src/form/components/LocalChangesMenu.tsx +17 -2
  199. package/src/form/components/StorageItemPreview.tsx +1 -2
  200. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
  201. package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
  202. package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
  203. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
  204. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
  205. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
  206. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
  207. package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
  208. package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
  209. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
  210. package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
  211. package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
  212. package/src/form/index.tsx +1 -0
  213. package/src/form/validation.ts +54 -2
  214. package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
  215. package/src/hooks/navigation/useResolvedViews.tsx +30 -15
  216. package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
  217. package/src/index.ts +6 -0
  218. package/src/preview/PropertyPreview.tsx +1 -1
  219. package/src/preview/components/ImagePreview.tsx +1 -1
  220. package/src/preview/components/UrlComponentPreview.tsx +1 -2
  221. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
  222. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
  223. package/src/routes/RebaseRoute.tsx +64 -35
  224. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  225. package/src/types/components/EntityFormProps.tsx +3 -1
  226. package/src/types/fields.tsx +4 -3
  227. package/src/util/navigation_utils.ts +4 -3
  228. package/src/util/previews.ts +1 -1
  229. package/src/util/property_utils.tsx +22 -6
  230. package/src/util/resolutions.ts +2 -2
  231. package/dist/CollectionEditorDialog-MbvXGzEq.js.map +0 -1
  232. package/dist/CollectionsStudioView-D9X6aiAr.js.map +0 -1
  233. package/dist/ContentHomePage-CfVB1eUo.js.map +0 -1
  234. package/dist/ExportCollectionAction-CUwJg4F9.js.map +0 -1
  235. package/dist/ImportCollectionAction-DGa_SF_8.js.map +0 -1
  236. package/dist/PropertyEditView-C4nlYmAc.js.map +0 -1
  237. package/dist/RolesView-CNWxnR8e.js.map +0 -1
  238. package/dist/UsersView-YiTIcXkA.js.map +0 -1
  239. package/dist/index-CtzpHzMQ.js.map +0 -1
  240. package/dist/index-DKlrVD1m.js.map +0 -1
  241. package/dist/index-kHJXfLNI.js.map +0 -1
  242. package/dist/util-CwLmSpGp.js.map +0 -1
@@ -15,21 +15,8 @@ import { RelationPreview } from "../../preview";
15
15
  import { RelationSelector } from "../../components/RelationSelector";
16
16
  import { MultipleRelationFieldBinding } from "./MultipleRelationFieldBinding";
17
17
 
18
- export function RelationFieldBinding({
19
- propertyKey,
20
- value,
21
- size,
22
- error,
23
- showError,
24
- disabled,
25
- isSubmitting,
26
- property,
27
- includeDescription,
28
- setValue,
29
- setFieldValue,
30
- context,
31
- customProps
32
- }: FieldProps<RelationProperty>) {
18
+ export function RelationFieldBinding(props: FieldProps<RelationProperty>) {
19
+ const { property, propertyKey, context } = props;
33
20
 
34
21
  if (property.type !== "relation") {
35
22
  throw Error("RelationFieldBinding expected a property containing a relation");
@@ -39,146 +26,162 @@ export function RelationFieldBinding({
39
26
  if (!collection || !capabilities?.supportsRelations || !("relations" in collection) || !collection.relations) {
40
27
  throw Error("RelationFieldBinding expected a collection with relations support");
41
28
  }
42
- const resolvedProperty = resolveRelationProperty(property, collection.relations, propertyKey)
29
+ const resolvedProperty = resolveRelationProperty(property, collection.relations, propertyKey);
43
30
  const relation = resolvedProperty.relation;
44
31
 
45
32
  const manyRelation = relation?.cardinality === "many";
46
-
47
- // Inline selector mode
48
33
  const widget = property.ui?.widget ?? "select";
49
34
 
50
35
  if (widget === "select" && relation) {
51
- const normalizedSingle = (!manyRelation && value && !Array.isArray(value)) ? normalizeToEntityRelation(value) : null;
52
- const singleValue = normalizedSingle ?? null;
53
- const multipleValue = (manyRelation && Array.isArray(value)) ? value : [];
54
-
55
- const selectorSize: "small" | "medium" | undefined = size === "large" ? "medium" : size;
56
-
57
- return (
58
- <div className="">
59
- <LabelWithIconAndTooltip
60
- propertyKey={propertyKey}
61
- icon={getIconForProperty(property, "small")}
62
- required={property.validation?.required}
63
- title={property.name ?? propertyKey}
64
- className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
65
-
66
- <RelationSelector
67
- relation={relation}
68
- value={manyRelation ? multipleValue : singleValue}
69
- onValueChange={(newVal) => {
70
- if (manyRelation) {
71
- setValue(Array.isArray(newVal) ? newVal : []);
72
- } else {
73
- setValue(!Array.isArray(newVal) ? (newVal ?? null) : null);
74
- }
75
- }}
76
- disabled={disabled || isSubmitting}
77
- fixedFilter={property.fixedFilter}
78
- size={selectorSize}
79
- />
80
-
81
- <FieldHelperText includeDescription={includeDescription}
82
- showError={showError}
83
- error={error}
84
- disabled={disabled}
85
- property={property}/>
86
- </div>
87
- );
36
+ return <RelationSelectorBinding {...props} relation={relation} manyRelation={manyRelation} />;
88
37
  }
89
38
 
90
39
  if (manyRelation) {
91
- return <MultipleRelationFieldBinding
92
- propertyKey={propertyKey}
93
- value={Array.isArray(value) ? value : []}
94
- error={error}
95
- showError={showError}
96
- disabled={disabled}
97
- isSubmitting={isSubmitting}
98
- property={property}
99
- includeDescription={includeDescription}
100
- setValue={setValue}
101
- setFieldValue={setFieldValue}
102
- context={context}
103
- customProps={customProps}
104
- />
105
- } else {
106
-
107
- const normalizedValue = value && !Array.isArray(value) ? normalizeToEntityRelation(value) : null;
108
- const validValue = !!normalizedValue;
109
-
110
- const collection = relation?.target();
111
-
112
- if (!collection) {
113
- throw Error(`Couldn't find the corresponding collection for the relation: ${propertyKey}`);
114
- }
115
-
116
- const onSingleEntitySelected = useCallback((e: Entity<any> | null) => {
117
- setValue(e ? getRelationFrom(e) : null);
118
- }, [setValue]);
119
-
120
- const referenceDialogController = useEntitySelectionDialog({
121
- multiselect: false,
122
- path: collection.slug,
123
- collection,
124
- onSingleEntitySelected,
125
- selectedEntityIds: validValue && normalizedValue ? [normalizedValue.id] : undefined,
126
- fixedFilter: property.fixedFilter
127
- }
128
- );
129
-
130
- const onEntryClick = (e: React.SyntheticEvent) => {
131
- e.preventDefault();
132
- referenceDialogController.open();
133
- };
134
-
135
- const usedRelation = Array.isArray(value) ? undefined : normalizedValue ?? undefined;
136
- return (
137
- <>
138
- <LabelWithIconAndTooltip
139
- propertyKey={propertyKey}
140
- icon={getIconForProperty(property, "small")}
141
- required={property.validation?.required}
142
- title={property.name ?? propertyKey}
143
- className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
144
-
145
- {!collection && <ErrorView
146
- error={"The specified collection does not exist. Check console"}/>}
147
-
148
- {collection && <>
149
-
150
- {usedRelation && <RelationPreview
151
- disabled={!usedRelation}
152
- previewProperties={property.ui?.previewProperties}
153
- hover={!disabled}
154
- size={size}
155
- onClick={disabled || isSubmitting ? undefined : onEntryClick}
156
- relation={usedRelation}
157
- includeEntityLink={property.includeEntityLink}
158
- includeId={property.includeId}
159
- />}
160
-
161
- {!value && <div className="justify-center text-left">
162
- <EntityPreviewContainer className={cls("px-6 h-16 text-sm font-medium flex items-center gap-6",
163
- disabled || isSubmitting
164
- ? "text-surface-accent-500"
165
- : "cursor-pointer text-surface-accent-700 dark:text-surface-accent-300 hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800")}
166
- onClick={onEntryClick}
167
- size={"medium"}>
168
- <IconForView collectionOrView={collection}
169
- className={"text-surface-300 dark:text-surface-600"}/>
170
- {`Edit ${property.name}`.toUpperCase()}
171
- </EntityPreviewContainer>
172
- </div>}
173
- </>}
174
-
175
- <FieldHelperText includeDescription={includeDescription}
176
- showError={showError}
177
- error={error}
178
- disabled={disabled}
179
- property={property}/>
180
-
181
- </>
182
- );
40
+ return <MultipleRelationFieldBinding {...props} />;
41
+ }
42
+
43
+ return <SingleRelationFieldBinding {...props} relation={relation} />;
44
+ }
45
+
46
+ function RelationSelectorBinding({
47
+ propertyKey,
48
+ value,
49
+ size,
50
+ error,
51
+ showError,
52
+ disabled,
53
+ isSubmitting,
54
+ property,
55
+ includeDescription,
56
+ setValue,
57
+ relation,
58
+ manyRelation
59
+ }: FieldProps<RelationProperty> & { relation: any; manyRelation: boolean }) {
60
+ const normalizedSingle = (!manyRelation && value && !Array.isArray(value)) ? normalizeToEntityRelation(value) : null;
61
+ const singleValue = normalizedSingle ?? null;
62
+ const multipleValue = (manyRelation && Array.isArray(value)) ? value : [];
63
+
64
+ const selectorSize: "small" | "medium" | undefined = size === "large" ? "medium" : size;
65
+
66
+ return (
67
+ <div className="">
68
+ <LabelWithIconAndTooltip
69
+ propertyKey={propertyKey}
70
+ icon={getIconForProperty(property, "small")}
71
+ required={property.validation?.required}
72
+ title={property.name ?? propertyKey}
73
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
74
+
75
+ <RelationSelector
76
+ relation={relation}
77
+ value={manyRelation ? multipleValue : singleValue}
78
+ onValueChange={(newVal) => {
79
+ if (manyRelation) {
80
+ setValue(Array.isArray(newVal) ? newVal : []);
81
+ } else {
82
+ setValue(!Array.isArray(newVal) ? (newVal ?? null) : null);
83
+ }
84
+ }}
85
+ disabled={disabled || isSubmitting}
86
+ fixedFilter={property.fixedFilter}
87
+ size={selectorSize}
88
+ />
89
+
90
+ <FieldHelperText includeDescription={includeDescription}
91
+ showError={showError}
92
+ error={error}
93
+ disabled={disabled}
94
+ property={property}/>
95
+ </div>
96
+ );
97
+ }
98
+
99
+ function SingleRelationFieldBinding({
100
+ propertyKey,
101
+ value,
102
+ size,
103
+ error,
104
+ showError,
105
+ disabled,
106
+ isSubmitting,
107
+ property,
108
+ includeDescription,
109
+ setValue,
110
+ relation
111
+ }: FieldProps<RelationProperty> & { relation: any }) {
112
+ const normalizedValue = value && !Array.isArray(value) ? normalizeToEntityRelation(value) : null;
113
+ const validValue = !!normalizedValue;
114
+
115
+ const collection = relation?.target();
116
+
117
+ if (!collection) {
118
+ throw Error(`Couldn't find the corresponding collection for the relation: ${propertyKey}`);
183
119
  }
120
+
121
+ const onSingleEntitySelected = useCallback((e: Entity<any> | null) => {
122
+ setValue(e ? getRelationFrom(e) : null);
123
+ }, [setValue]);
124
+
125
+ const referenceDialogController = useEntitySelectionDialog({
126
+ multiselect: false,
127
+ path: collection.slug,
128
+ collection,
129
+ onSingleEntitySelected,
130
+ selectedEntityIds: validValue && normalizedValue ? [normalizedValue.id] : undefined,
131
+ fixedFilter: property.fixedFilter
132
+ });
133
+
134
+ const onEntryClick = (e: React.SyntheticEvent) => {
135
+ e.preventDefault();
136
+ referenceDialogController.open();
137
+ };
138
+
139
+ const usedRelation = Array.isArray(value) ? undefined : normalizedValue ?? undefined;
140
+
141
+ return (
142
+ <>
143
+ <LabelWithIconAndTooltip
144
+ propertyKey={propertyKey}
145
+ icon={getIconForProperty(property, "small")}
146
+ required={property.validation?.required}
147
+ title={property.name ?? propertyKey}
148
+ className={"h-8 text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
149
+
150
+ {!collection && <ErrorView
151
+ error={"The specified collection does not exist. Check console"}/>}
152
+
153
+ {collection && <>
154
+
155
+ {usedRelation && <RelationPreview
156
+ disabled={!usedRelation}
157
+ previewProperties={property.ui?.previewProperties}
158
+ hover={!disabled}
159
+ size={size}
160
+ onClick={disabled || isSubmitting ? undefined : onEntryClick}
161
+ relation={usedRelation}
162
+ includeEntityLink={property.includeEntityLink}
163
+ includeId={property.includeId}
164
+ />}
165
+
166
+ {!value && <div className="justify-center text-left">
167
+ <EntityPreviewContainer className={cls("px-6 h-16 text-sm font-medium flex items-center gap-6",
168
+ disabled || isSubmitting
169
+ ? "text-surface-accent-500"
170
+ : "cursor-pointer text-surface-accent-700 dark:text-surface-accent-300 hover:bg-surface-accent-50 dark:hover:bg-surface-800 group-hover:bg-surface-accent-50 dark:group-hover:bg-surface-800")}
171
+ onClick={onEntryClick}
172
+ size={"medium"}>
173
+ <IconForView collectionOrView={collection}
174
+ className={"text-surface-300 dark:text-surface-600"}/>
175
+ {`Edit ${property.name}`.toUpperCase()}
176
+ </EntityPreviewContainer>
177
+ </div>}
178
+ </>}
179
+
180
+ <FieldHelperText includeDescription={includeDescription}
181
+ showError={showError}
182
+ error={error}
183
+ disabled={disabled}
184
+ property={property}/>
185
+ </>
186
+ );
184
187
  }
@@ -130,7 +130,7 @@ export function RepeatFieldBinding({
130
130
 
131
131
  <FieldHelperText includeDescription={includeDescription}
132
132
  showError={showError}
133
- error={error as any}
133
+ error={error}
134
134
  disabled={disabled}
135
135
  property={property}/>
136
136
 
@@ -6,8 +6,7 @@ import React, { useCallback } from "react";
6
6
  import { FieldHelperText, LabelWithIcon } from "../components";
7
7
  import { EnumValuesChip } from "../../preview";
8
8
  import { getIconForProperty } from "../../util/property_utils";
9
- import { cls, IconButton, Select, SelectItem } from "@rebasepro/ui";
10
- import { XIcon } from "lucide-react";
9
+ import { cls, IconButton, Select, SelectItem, XIcon } from "@rebasepro/ui";
11
10
  import { useClearRestoreValue } from "../useClearRestoreValue";
12
11
  import { PropertyIdCopyTooltip } from "../../components/PropertyIdCopyTooltip";
13
12
  import { resolveEnumValues } from "@rebasepro/common";
@@ -2,8 +2,16 @@ import type { FieldProps } from "../../types/fields";
2
2
  import type { NumberProperty, StringProperty } from "@rebasepro/types";
3
3
  import React, { useCallback } from "react";
4
4
 
5
- import { Collapse, IconButton, TextField, TextareaAutosize, fieldBackgroundHoverMixin, fieldBackgroundMixin, cls } from "@rebasepro/ui";
6
- import { XIcon } from "lucide-react";
5
+ import {
6
+ cls,
7
+ Collapse,
8
+ fieldBackgroundHoverMixin,
9
+ fieldBackgroundMixin,
10
+ IconButton,
11
+ TextareaAutosize,
12
+ TextField,
13
+ XIcon
14
+ } from "@rebasepro/ui";
7
15
  import { PreviewType } from "@rebasepro/types";
8
16
  import { FieldHelperText, LabelWithIcon } from "../components";
9
17
  import { PropertyPreview } from "../../preview";
@@ -0,0 +1,202 @@
1
+ import type { FieldProps } from "../../types/fields";
2
+ import type { VectorProperty } from "@rebasepro/types";
3
+ import React, { useState, useEffect, useCallback } from "react";
4
+ import {
5
+ Button,
6
+ CheckIcon,
7
+ EyeIcon,
8
+ EyeOffIcon,
9
+ IconButton,
10
+ PencilIcon,
11
+ TextField,
12
+ Trash2Icon
13
+ } from "@rebasepro/ui";
14
+ import { FieldHelperText, LabelWithIcon } from "../components";
15
+ import { useClearRestoreValue } from "../useClearRestoreValue";
16
+ import { PropertyIdCopyTooltip } from "../../components/PropertyIdCopyTooltip";
17
+ import { getIconForProperty } from "../../util/property_utils";
18
+
19
+ /**
20
+ * Custom field binding to render vector fields (e.g. for high-dimensional embeddings).
21
+ * Shows a compact metadata card by default, and lets users expand values or edit them.
22
+ *
23
+ * Automatically parses inputs to number arrays and packages them into the canonical
24
+ * Vector object structure expected by Rebase driver.
25
+ * @group Form fields
26
+ */
27
+ export function VectorFieldBinding({
28
+ propertyKey,
29
+ value,
30
+ setValue,
31
+ error,
32
+ showError,
33
+ disabled,
34
+ autoFocus,
35
+ property,
36
+ includeDescription,
37
+ size = "large"
38
+ }: FieldProps<VectorProperty>) {
39
+ const isVectorObject = (val: unknown): val is { value: number[] } => {
40
+ return typeof val === "object" && val !== null && "value" in val;
41
+ };
42
+
43
+ // Extract array value from the custom { __type: "Vector", value: number[] } wrapper
44
+ const arrayValue = isVectorObject(value)
45
+ ? value.value
46
+ : (Array.isArray(value) ? value : []);
47
+
48
+ const [textValue, setTextValue] = useState(() => arrayValue.join(", "));
49
+ const [isEditing, setIsEditing] = useState(false);
50
+ const [showValues, setShowValues] = useState(false);
51
+
52
+ useEffect(() => {
53
+ setTextValue(arrayValue.join(", "));
54
+ }, [JSON.stringify(arrayValue)]);
55
+
56
+ useClearRestoreValue({
57
+ property,
58
+ value,
59
+ setValue
60
+ });
61
+
62
+ const handleClearClick = useCallback((e: React.MouseEvent) => {
63
+ e.stopPropagation();
64
+ e.preventDefault();
65
+ setValue(null);
66
+ setTextValue("");
67
+ }, [setValue]);
68
+
69
+ const onChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
70
+ const raw = event.target.value;
71
+ setTextValue(raw);
72
+
73
+ // Parse comma-separated string to number array
74
+ const numbers = raw
75
+ .split(",")
76
+ .map(str => str.trim())
77
+ .filter(str => str !== "")
78
+ .map(Number);
79
+
80
+ setValue({
81
+ __type: "Vector",
82
+ value: numbers
83
+ });
84
+ };
85
+
86
+ const label = (
87
+ <LabelWithIcon
88
+ icon={getIconForProperty(property, "small")}
89
+ required={property.validation?.required}
90
+ title={property.name ?? propertyKey}
91
+ />
92
+ );
93
+
94
+ const isPopulated = arrayValue.length > 0;
95
+
96
+ return (
97
+ <div className="flex flex-col gap-2 w-full mt-2">
98
+ {/* Field Label */}
99
+ <div className="flex items-center justify-between mb-1">
100
+ {label}
101
+ </div>
102
+
103
+ <PropertyIdCopyTooltip propertyKey={propertyKey}>
104
+ <div className="w-full">
105
+ {!isEditing ? (
106
+ /* Compact Preview Card */
107
+ <div className="flex flex-col gap-3 p-4 rounded-xl border border-surface-200 dark:border-surface-700 bg-surface-50/50 dark:bg-surface-800/20 backdrop-blur-sm transition-all duration-200 hover:border-surface-300 dark:hover:border-surface-600">
108
+ <div className="flex items-center justify-between flex-wrap gap-2">
109
+ <div className="flex items-center gap-2.5">
110
+ {/* Status Dot */}
111
+ <div className={`w-2.5 h-2.5 rounded-full ${isPopulated ? 'bg-emerald-500 animate-pulse' : 'bg-surface-300 dark:bg-surface-600'}`} />
112
+ <span className="text-sm font-semibold text-text-primary dark:text-text-primary-dark">
113
+ {isPopulated ? `${arrayValue.length} Dimensions` : "Empty Vector"}
114
+ </span>
115
+ {isPopulated && (
116
+ <span className="text-xs text-text-secondary dark:text-text-secondary-dark px-2 py-0.5 rounded-full bg-surface-100 dark:bg-surface-800 font-medium">
117
+ Embedding
118
+ </span>
119
+ )}
120
+ </div>
121
+
122
+ <div className="flex items-center gap-2">
123
+ {isPopulated && (
124
+ <Button
125
+ variant="text"
126
+ size="small"
127
+ onClick={() => setShowValues(!showValues)}
128
+ startIcon={showValues ? <EyeOffIcon size={14} /> : <EyeIcon size={14} />}
129
+ >
130
+ {showValues ? "Hide values" : "Show values"}
131
+ </Button>
132
+ )}
133
+ {!disabled && (
134
+ <Button
135
+ variant="outlined"
136
+ size="small"
137
+ onClick={() => setIsEditing(true)}
138
+ startIcon={<PencilIcon size={14} />}
139
+ >
140
+ {isPopulated ? "Edit values" : "Add values"}
141
+ </Button>
142
+ )}
143
+ {isPopulated && !disabled && (
144
+ <IconButton size="small" onClick={handleClearClick} className="text-text-secondary hover:text-red-500">
145
+ <Trash2Icon size={14} />
146
+ </IconButton>
147
+ )}
148
+ </div>
149
+ </div>
150
+
151
+ {/* Collapsible scrollable numbers list */}
152
+ {showValues && isPopulated && (
153
+ <div className="mt-1 p-3 rounded-lg bg-surface-100/50 dark:bg-surface-900/40 border border-surface-200/50 dark:border-surface-800/50 max-h-36 overflow-y-auto font-mono text-[11px] leading-relaxed text-text-secondary dark:text-text-secondary-dark break-all selection:bg-primary-100 dark:selection:bg-primary-900/40">
154
+ {arrayValue.join(", ")}
155
+ </div>
156
+ )}
157
+ </div>
158
+ ) : (
159
+ /* Editing View: Text Input */
160
+ <div className="flex flex-col gap-2 p-4 rounded-xl border border-primary-500/30 dark:border-primary-400/20 bg-surface-50/20 dark:bg-surface-800/10">
161
+ <TextField
162
+ size={size}
163
+ value={textValue}
164
+ onChange={onChange}
165
+ autoFocus={true}
166
+ placeholder={`e.g., 0.15, -0.42, 0.88 (Requires ${property.dimensions} dimensions)`}
167
+ disabled={disabled}
168
+ error={showError ? !!error : undefined}
169
+ inputClassName={error ? "text-red-500 dark:text-red-600 font-mono text-xs" : "font-mono text-xs"}
170
+ />
171
+ <div className="flex justify-end gap-2 mt-2">
172
+ <Button
173
+ variant="outlined"
174
+ size="small"
175
+ onClick={() => setIsEditing(false)}
176
+ >
177
+ Cancel
178
+ </Button>
179
+ <Button
180
+ variant="filled"
181
+ size="small"
182
+ onClick={() => setIsEditing(false)}
183
+ startIcon={<CheckIcon size={14} />}
184
+ >
185
+ Done
186
+ </Button>
187
+ </div>
188
+ </div>
189
+ )}
190
+ </div>
191
+ </PropertyIdCopyTooltip>
192
+
193
+ <FieldHelperText
194
+ includeDescription={includeDescription}
195
+ showError={showError}
196
+ error={error}
197
+ disabled={disabled}
198
+ property={property}
199
+ />
200
+ </div>
201
+ );
202
+ }
@@ -20,6 +20,7 @@ export { BlockFieldBinding } from "./field_bindings/BlockFieldBinding";
20
20
  export { ReadOnlyFieldBinding } from "./field_bindings/ReadOnlyFieldBinding";
21
21
  export { MarkdownEditorFieldBinding } from "./field_bindings/MarkdownEditorFieldBinding";
22
22
  export { ArrayCustomShapedFieldBinding } from "./field_bindings/ArrayCustomShapedFieldBinding";
23
+ export { VectorFieldBinding } from "./field_bindings/VectorFieldBinding";
23
24
 
24
25
  export * from "./components";
25
26
 
@@ -1,5 +1,5 @@
1
1
  import type { Properties } from "@rebasepro/types";
2
- import type { ArrayProperty, MapProperty, NumberProperty, Property, BooleanProperty, DateProperty, GeopointProperty, ReferenceProperty, RelationProperty, StringProperty } from "@rebasepro/types";
2
+ import type { ArrayProperty, MapProperty, NumberProperty, Property, BooleanProperty, DateProperty, GeopointProperty, ReferenceProperty, RelationProperty, StringProperty, VectorProperty, BinaryProperty } from "@rebasepro/types";
3
3
  ;
4
4
  import { z, ZodTypeAny } from "zod";
5
5
  import { enumToObjectEntries, isPropertyBuilder } from "@rebasepro/common";
@@ -74,11 +74,15 @@ export function mapPropertyToZod(propertyContext: PropertyContext<Property>): Zo
74
74
  return getZodReferenceSchema(propertyContext as PropertyContext<ReferenceProperty>);
75
75
  } else if (property.type === "relation") {
76
76
  return getZodRelationSchema(propertyContext as PropertyContext<RelationProperty>);
77
+ } else if (property.type === "vector") {
78
+ return getZodVectorSchema(propertyContext as PropertyContext<VectorProperty>);
79
+ } else if (property.type === "binary") {
80
+ return getZodBinarySchema(propertyContext as PropertyContext<BinaryProperty>);
77
81
  }
78
82
 
79
83
  // Log the error but don't crash the form
80
84
  console.error("Unsupported data type in zod mapping", property);
81
- const dataType = "dataType" in (property as unknown as Record<string, unknown>) ? String((property as unknown as Record<string, unknown>).dataType) : "unknown";
85
+ const dataType = "dataType" in (property as Record<string, unknown>) ? String((property as Record<string, unknown>).dataType) : "unknown";
82
86
  return z.any().refine(
83
87
  () => false,
84
88
  { message: `Unsupported data type: ${dataType}` }
@@ -517,3 +521,51 @@ function getZodArraySchema({
517
521
  }
518
522
  return arraySchema;
519
523
  }
524
+
525
+ function getZodVectorSchema({
526
+ property
527
+ }: PropertyContext<VectorProperty>): ZodTypeAny {
528
+ let schema: ZodTypeAny = z.preprocess(
529
+ (val: any) => {
530
+ if (val && typeof val === "object" && "__type" in val && val.__type === "Vector") {
531
+ return val.value;
532
+ }
533
+ if (val && typeof val === "object" && "value" in val && Array.isArray(val.value)) {
534
+ return val.value;
535
+ }
536
+ return val;
537
+ },
538
+ z.array(z.number()).nullable().optional()
539
+ );
540
+
541
+ if (property.dimensions) {
542
+ schema = schema.refine(
543
+ (val: any) => val === null || val === undefined || val.length === property.dimensions,
544
+ { message: `${property.name ?? "Vector"} must have exactly ${property.dimensions} dimensions` }
545
+ );
546
+ }
547
+
548
+ if (property.validation?.required) {
549
+ schema = schema.refine(
550
+ (val: any) => val !== null && val !== undefined && val.length > 0,
551
+ { message: property.validation?.requiredMessage ?? "Required" }
552
+ );
553
+ }
554
+
555
+ return schema;
556
+ }
557
+
558
+ function getZodBinarySchema({
559
+ property
560
+ }: PropertyContext<BinaryProperty>): ZodTypeAny {
561
+ let schema: ZodTypeAny = z.string().nullable().optional();
562
+ const validation = property.validation;
563
+
564
+ if (validation?.required) {
565
+ schema = schema.nullable().optional().refine(
566
+ (value: any) => value !== undefined && value !== null && value !== "",
567
+ { message: validation.requiredMessage ? validation.requiredMessage : "Required" }
568
+ );
569
+ }
570
+ return schema;
571
+ }
@@ -89,7 +89,8 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
89
89
  plugins,
90
90
  adminMode,
91
91
  effectiveRoleController,
92
- userManagement
92
+ userManagement,
93
+ collections
93
94
  });
94
95
 
95
96
  // Step 3: Compute top-level navigation (pure derived state)