@rebasepro/admin 0.2.1 → 0.2.4

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 (214) hide show
  1. package/dist/{CollectionEditorDialog-BXIh2AXg.js → CollectionEditorDialog-D0VqpLPO.js} +73 -256
  2. package/dist/CollectionEditorDialog-D0VqpLPO.js.map +1 -0
  3. package/dist/{CollectionsStudioView-jR8iz_ja.js → CollectionsStudioView-Bc3Rxxc2.js} +5 -4
  4. package/dist/{CollectionsStudioView-jR8iz_ja.js.map → CollectionsStudioView-Bc3Rxxc2.js.map} +1 -1
  5. package/dist/{ExportCollectionAction-CMdiiv1L.js → ExportCollectionAction-Ckc-09BQ.js} +4 -3
  6. package/dist/ExportCollectionAction-Ckc-09BQ.js.map +1 -0
  7. package/dist/{ImportCollectionAction-C05lE0IW.js → ImportCollectionAction-BqjIrC3Z.js} +3 -2
  8. package/dist/{ImportCollectionAction-C05lE0IW.js.map → ImportCollectionAction-BqjIrC3Z.js.map} +1 -1
  9. package/dist/{PropertyEditView-BB5xjnhZ.js → PropertyEditView-CvRSV-A2.js} +430 -445
  10. package/dist/PropertyEditView-CvRSV-A2.js.map +1 -0
  11. package/dist/collection_editor/ConfigControllerProvider.d.ts +0 -5
  12. package/dist/collection_editor/index.d.ts +0 -1
  13. package/dist/collection_editor/types/collection_editor_controller.d.ts +0 -2
  14. package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +3 -3
  15. package/dist/collection_editor/ui/collection_editor/properties/RelationPropertyField.d.ts +1 -7
  16. package/dist/collection_editor_ui.js +3 -3
  17. package/dist/components/ArrayContainer.d.ts +2 -2
  18. package/dist/components/DefaultAppBar.d.ts +18 -1
  19. package/dist/components/DefaultDrawer.d.ts +51 -3
  20. package/dist/components/EntityCollectionTable/fields/TableStorageUpload.d.ts +2 -2
  21. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
  22. package/dist/components/EntityCollectionTable/table_bindings.d.ts +4 -3
  23. package/dist/components/EntityCollectionView/hooks/useKanbanDragAndDrop.d.ts +4 -3
  24. package/dist/components/EntityEditView.d.ts +2 -1
  25. package/dist/components/HomePage/HomePageDnD.d.ts +3 -3
  26. package/dist/components/PropertyCollectionView.d.ts +1 -1
  27. package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
  28. package/dist/components/SelectableTable/SelectionStore.d.ts +4 -1
  29. package/dist/components/SelectableTable/filters/BooleanFilterField.d.ts +2 -2
  30. package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -2
  31. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -2
  32. package/dist/components/SelectableTable/filters/StringNumberFilterField.d.ts +2 -2
  33. package/dist/components/admin/RolesView.d.ts +3 -3
  34. package/dist/components/admin/UsersView.d.ts +3 -3
  35. package/dist/components/app/Drawer.d.ts +8 -1
  36. package/dist/data_export/export/export.d.ts +3 -3
  37. package/dist/editor/components/editor-bubble.d.ts +5 -1
  38. package/dist/editor/components/image-bubble.d.ts +5 -1
  39. package/dist/editor/components/index.d.ts +3 -3
  40. package/dist/editor/components/table-bubble.d.ts +5 -1
  41. package/dist/editor/nodeViews/ReactNodeView.d.ts +4 -1
  42. package/dist/editor/useProseMirror.d.ts +2 -2
  43. package/dist/editor/utils/remove_classes.d.ts +1 -1
  44. package/dist/editor.js +15 -14
  45. package/dist/editor.js.map +1 -1
  46. package/dist/form/EntityForm.d.ts +2 -2
  47. package/dist/form/components/StorageUploadProgress.d.ts +2 -2
  48. package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +1 -1
  49. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
  50. package/dist/form/validation.d.ts +3 -3
  51. package/dist/hooks/navigation/useResolvedCollections.d.ts +6 -0
  52. package/dist/hooks/navigation/useResolvedViews.d.ts +3 -4
  53. package/dist/{index-BAM9KCmM.js → index-BCcLwgfe.js} +3 -2
  54. package/dist/{index-BAM9KCmM.js.map → index-BCcLwgfe.js.map} +1 -1
  55. package/dist/{index-D5OQhv-T.js → index-DY2k5TtG.js} +3 -3
  56. package/dist/index-DY2k5TtG.js.map +1 -0
  57. package/dist/{index-CoSNm3e3.js → index-UQOMHwt1.js} +3 -3
  58. package/dist/index-UQOMHwt1.js.map +1 -0
  59. package/dist/index.d.ts +1 -1
  60. package/dist/index.js +2813 -372
  61. package/dist/index.js.map +1 -1
  62. package/dist/{markdown-z2Ir7Cgo.js → markdown-DD2JDU1X.js} +2 -2
  63. package/dist/markdown-DD2JDU1X.js.map +1 -0
  64. package/dist/preview/components/UrlComponentPreview.d.ts +1 -0
  65. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  66. package/dist/types/components/EntityFormProps.d.ts +2 -2
  67. package/dist/types/fields.d.ts +1 -1
  68. package/dist/{util-DtbWD7LF.js → util-ZM9gQuCv.js} +2104 -2071
  69. package/dist/util-ZM9gQuCv.js.map +1 -0
  70. package/package.json +10 -9
  71. package/src/collection_editor/ConfigControllerProvider.tsx +3 -13
  72. package/src/collection_editor/index.ts +1 -3
  73. package/src/collection_editor/types/collection_editor_controller.tsx +0 -3
  74. package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -6
  75. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -6
  76. package/src/collection_editor/ui/EditorEntityAction.tsx +1 -6
  77. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +7 -14
  78. package/src/collection_editor/ui/NewCollectionCard.tsx +1 -5
  79. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +3 -8
  80. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +1 -10
  81. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +8 -12
  82. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +21 -21
  83. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +4 -4
  84. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +1 -1
  85. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +3 -3
  86. package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +3 -3
  87. package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +8 -8
  88. package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +5 -5
  89. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +2 -2
  90. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +5 -5
  91. package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +5 -5
  92. package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +2 -2
  93. package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +37 -57
  94. package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +2 -2
  95. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +8 -8
  96. package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +5 -5
  97. package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +3 -2
  98. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +2 -2
  99. package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +2 -2
  100. package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +1 -1
  101. package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +4 -7
  102. package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +4 -4
  103. package/src/collection_editor/validateCollectionJson.ts +88 -1
  104. package/src/components/ArrayContainer.tsx +3 -3
  105. package/src/components/DefaultAppBar.tsx +52 -31
  106. package/src/components/DefaultDrawer.tsx +279 -66
  107. package/src/components/DrawerNavigationItem.tsx +1 -1
  108. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +6 -5
  109. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +9 -7
  110. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -5
  111. package/src/components/EntityCollectionTable/fields/VirtualTableNumberInput.tsx +12 -9
  112. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +2 -2
  113. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +1 -1
  114. package/src/components/EntityCollectionTable/table_bindings.tsx +5 -4
  115. package/src/components/EntityCollectionView/EntityCollectionView.tsx +6 -4
  116. package/src/components/EntityCollectionView/hooks/useCollectionInlineEditor.ts +1 -1
  117. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +7 -6
  118. package/src/components/EntityDetailView.tsx +46 -24
  119. package/src/components/EntityEditView.tsx +51 -28
  120. package/src/components/EntityEditViewFormActions.tsx +4 -4
  121. package/src/components/EntityPreview.tsx +9 -4
  122. package/src/components/HomePage/HomePageDnD.tsx +3 -2
  123. package/src/components/PropertyCollectionView.tsx +1 -1
  124. package/src/components/PropertyIdCopyTooltip.tsx +1 -1
  125. package/src/components/RebaseLayout.tsx +5 -1
  126. package/src/components/RebaseNavigation.tsx +2 -2
  127. package/src/components/RebaseRouteDefs.tsx +4 -7
  128. package/src/components/RebaseShell.tsx +16 -13
  129. package/src/components/SearchIconsView.tsx +1 -8
  130. package/src/components/SelectableTable/SelectableTable.tsx +8 -11
  131. package/src/components/SelectableTable/SelectionStore.ts +1 -1
  132. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +3 -3
  133. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +3 -3
  134. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +5 -5
  135. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +3 -3
  136. package/src/components/SideEntityProvider.tsx +2 -1
  137. package/src/components/admin/RolesView.tsx +7 -2
  138. package/src/components/admin/UsersView.tsx +12 -6
  139. package/src/components/app/Drawer.tsx +9 -1
  140. package/src/components/app/Scaffold.tsx +5 -1
  141. package/src/data_export/export/export.ts +17 -17
  142. package/src/data_import/components/DataNewPropertiesMapping.tsx +1 -1
  143. package/src/editor/components/editor-bubble.tsx +32 -9
  144. package/src/editor/components/image-bubble.tsx +27 -11
  145. package/src/editor/components/index.ts +3 -3
  146. package/src/editor/components/table-bubble.tsx +79 -17
  147. package/src/editor/extensions/HighlightDecorationExtension.ts +3 -2
  148. package/src/editor/nodeViews/ReactNodeView.tsx +1 -1
  149. package/src/editor/nodeViews/TaskItemComponent.tsx +9 -8
  150. package/src/editor/schema.ts +135 -59
  151. package/src/editor/selectors/link-selector.tsx +8 -5
  152. package/src/editor/useProseMirror.ts +2 -2
  153. package/src/editor/utils/remove_classes.ts +6 -5
  154. package/src/form/EntityForm.tsx +15 -15
  155. package/src/form/EntityFormActions.tsx +2 -2
  156. package/src/form/PropertyFieldBinding.tsx +64 -64
  157. package/src/form/components/FieldHelperText.tsx +4 -4
  158. package/src/form/components/StorageUploadProgress.tsx +2 -2
  159. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +1 -1
  160. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -1
  161. package/src/form/field_bindings/BlockFieldBinding.tsx +54 -53
  162. package/src/form/field_bindings/KeyValueFieldBinding.tsx +290 -289
  163. package/src/form/field_bindings/MapFieldBinding.tsx +2 -2
  164. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +2 -2
  165. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -1
  166. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +1 -1
  167. package/src/form/field_bindings/ReferenceFieldBinding.tsx +8 -6
  168. package/src/form/field_bindings/RelationFieldBinding.tsx +4 -4
  169. package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
  170. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -1
  171. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +84 -84
  172. package/src/form/field_bindings/SwitchFieldBinding.tsx +16 -16
  173. package/src/form/field_bindings/TextFieldBinding.tsx +77 -73
  174. package/src/form/field_bindings/UserSelectFieldBinding.tsx +17 -17
  175. package/src/form/validation.ts +43 -43
  176. package/src/hooks/navigation/useBuildNavigationStateController.tsx +3 -5
  177. package/src/hooks/navigation/useResolvedCollections.ts +27 -7
  178. package/src/hooks/navigation/useResolvedViews.tsx +24 -44
  179. package/src/index.ts +2 -0
  180. package/src/preview/PropertyPreview.tsx +2 -2
  181. package/src/preview/components/ImagePreview.tsx +2 -1
  182. package/src/preview/components/UrlComponentPreview.tsx +11 -2
  183. package/src/preview/components/UserPreview.tsx +1 -1
  184. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
  185. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -4
  186. package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +3 -3
  187. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +3 -3
  188. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +3 -2
  189. package/src/preview/property_previews/ArrayOneOfPreview.tsx +6 -8
  190. package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +1 -1
  191. package/src/preview/property_previews/ArrayPropertyPreview.tsx +3 -3
  192. package/src/preview/property_previews/MapPropertyPreview.tsx +4 -3
  193. package/src/preview/property_previews/NumberPropertyPreview.tsx +5 -3
  194. package/src/preview/property_previews/StringPropertyPreview.tsx +10 -8
  195. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  196. package/src/types/components/EntityFormProps.tsx +2 -2
  197. package/src/types/fields.tsx +2 -2
  198. package/dist/CollectionEditorDialog-BXIh2AXg.js.map +0 -1
  199. package/dist/ContentHomePage-BQZWuOFb.js +0 -1784
  200. package/dist/ContentHomePage-BQZWuOFb.js.map +0 -1
  201. package/dist/ExportCollectionAction-CMdiiv1L.js.map +0 -1
  202. package/dist/PropertyEditView-BB5xjnhZ.js.map +0 -1
  203. package/dist/RoleChip-QtUFXeTp.js +0 -67
  204. package/dist/RoleChip-QtUFXeTp.js.map +0 -1
  205. package/dist/RolesView-CULIHWZ9.js +0 -437
  206. package/dist/RolesView-CULIHWZ9.js.map +0 -1
  207. package/dist/UsersView-D7_AtJ44.js +0 -408
  208. package/dist/UsersView-D7_AtJ44.js.map +0 -1
  209. package/dist/collection_editor/types/config_permissions.d.ts +0 -19
  210. package/dist/index-CoSNm3e3.js.map +0 -1
  211. package/dist/index-D5OQhv-T.js.map +0 -1
  212. package/dist/markdown-z2Ir7Cgo.js.map +0 -1
  213. package/dist/util-DtbWD7LF.js.map +0 -1
  214. package/src/collection_editor/types/config_permissions.ts +0 -20
@@ -19,18 +19,18 @@ type UserSelectProps = FieldProps<StringProperty>;
19
19
  * @group Form fields
20
20
  */
21
21
  export function UserSelectFieldBinding({
22
- propertyKey,
23
- value,
24
- setValue,
25
- error,
26
- showError,
27
- disabled,
28
- autoFocus,
29
- touched,
30
- property,
31
- includeDescription,
32
- size = "large"
33
- }: UserSelectProps) {
22
+ propertyKey,
23
+ value,
24
+ setValue,
25
+ error,
26
+ showError,
27
+ disabled,
28
+ autoFocus,
29
+ touched,
30
+ property,
31
+ includeDescription,
32
+ size = "large"
33
+ }: UserSelectProps) {
34
34
 
35
35
  const selectorSize: "small" | "medium" | undefined = size === "large" ? "medium" : size;
36
36
 
@@ -46,7 +46,7 @@ export function UserSelectFieldBinding({
46
46
  </PropertyIdCopyTooltip>
47
47
 
48
48
  <UserSelector
49
- value={value ?? null}
49
+ value={value as string | null | undefined}
50
50
  onValueChange={(userId) => {
51
51
  setValue(userId);
52
52
  }}
@@ -56,10 +56,10 @@ export function UserSelectFieldBinding({
56
56
  />
57
57
 
58
58
  <FieldHelperText includeDescription={includeDescription}
59
- showError={showError}
60
- error={error}
61
- disabled={disabled}
62
- property={property}/>
59
+ showError={showError}
60
+ error={error}
61
+ disabled={disabled}
62
+ property={property}/>
63
63
 
64
64
  </>
65
65
  );
@@ -7,7 +7,7 @@ import { getValueInPath, hydrateRegExp } from "@rebasepro/utils";
7
7
 
8
8
  export type CustomFieldValidator = (props: {
9
9
  name: string,
10
- value: any,
10
+ value: unknown,
11
11
  property: Property,
12
12
  entityId?: string | number,
13
13
  parentProperty?: MapProperty | ArrayProperty,
@@ -18,13 +18,13 @@ interface PropertyContext<P extends Property> {
18
18
  parentProperty?: MapProperty | ArrayProperty,
19
19
  entityId?: string | number,
20
20
  customFieldValidator?: CustomFieldValidator,
21
- name?: any
21
+ name?: string
22
22
  }
23
23
 
24
24
  export function getEntitySchema<M extends Record<string, unknown>>(
25
25
  entityId: string | number | undefined,
26
26
  properties: Properties,
27
- customFieldValidator?: CustomFieldValidator): z.ZodObject<any> {
27
+ customFieldValidator?: CustomFieldValidator): z.ZodObject<Record<string, ZodTypeAny>> {
28
28
  const shape: Record<string, ZodTypeAny> = {};
29
29
  Object.entries(properties as Record<string, Property>)
30
30
  .forEach(([name, property]) => {
@@ -153,14 +153,14 @@ function getZodStringSchema({
153
153
  const allowedValues = (isRequired ? entries : [...entries, null])
154
154
  .map((enumValueConfig) => enumValueConfig?.id ?? null);
155
155
  schema = schema.refine(
156
- (value: any) => allowedValues.includes(value),
156
+ (value: unknown) => allowedValues.includes(value as string | null),
157
157
  { message: `Must be one of: ${allowedValues.filter(Boolean).join(", ")}` }
158
158
  );
159
159
  }
160
160
 
161
161
  if (isRequired && !property.enum) {
162
162
  schema = schema.refine(
163
- (value: any) => value !== undefined && value !== null && value !== "",
163
+ (value: unknown) => value !== undefined && value !== null && value !== "",
164
164
  { message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
165
165
  );
166
166
  }
@@ -168,36 +168,36 @@ function getZodStringSchema({
168
168
  if (validation) {
169
169
 
170
170
  if (validation.min || validation.min === 0) schema = schema.refine(
171
- (value: any) => value == null || value.length >= validation.min!,
171
+ (value: unknown) => value == null || (typeof value === "string" && value.length >= validation.min!),
172
172
  { message: `${property.name} must be min ${validation.min} characters long` }
173
173
  );
174
174
  if (validation.max || validation.max === 0) schema = schema.refine(
175
- (value: any) => value == null || value.length <= validation.max!,
175
+ (value: unknown) => value == null || (typeof value === "string" && value.length <= validation.max!),
176
176
  { message: `${property.name} must be max ${validation.max} characters long` }
177
177
  );
178
178
  if (validation.matches) {
179
179
  const regExp = typeof validation.matches === "string" ? hydrateRegExp(validation.matches) : validation.matches;
180
180
  if (regExp) {
181
181
  schema = schema.refine(
182
- (value: any) => value == null || regExp.test(value),
182
+ (value: unknown) => value == null || (typeof value === "string" && regExp.test(value)),
183
183
  { message: validation.matchesMessage ?? "Invalid format" }
184
184
  );
185
185
  }
186
186
  }
187
- if (validation.trim) schema = z.preprocess((v: any) => typeof v === "string" ? v.trim() : v, schema);
188
- if (validation.lowercase) schema = z.preprocess((v: any) => typeof v === "string" ? v.toLowerCase() : v, schema);
189
- if (validation.uppercase) schema = z.preprocess((v: any) => typeof v === "string" ? v.toUpperCase() : v, schema);
187
+ if (validation.trim) schema = z.preprocess((v: unknown) => typeof v === "string" ? v.trim() : v, schema);
188
+ if (validation.lowercase) schema = z.preprocess((v: unknown) => typeof v === "string" ? v.toLowerCase() : v, schema);
189
+ if (validation.uppercase) schema = z.preprocess((v: unknown) => typeof v === "string" ? v.toUpperCase() : v, schema);
190
190
  if (property.email) schema = schema.refine(
191
- (value: any) => value == null || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
191
+ (value: unknown) => value == null || (typeof value === "string" && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)),
192
192
  { message: `${property.name} must be an email` }
193
193
  );
194
194
  if (property.ui?.url) {
195
195
  if (!property.storage || property.storage?.storeUrl) {
196
196
  schema = schema.refine(
197
- (value: any) => {
197
+ (value: unknown) => {
198
198
  if (value == null) return true;
199
199
  try {
200
- new URL(value);
200
+ new URL(value as string);
201
201
  return true;
202
202
  } catch {
203
203
  return false;
@@ -236,7 +236,7 @@ function getZodNumberSchema({
236
236
 
237
237
  if (isRequired) {
238
238
  schema = schema.refine(
239
- (value: any) => value !== undefined && value !== null,
239
+ (value: unknown) => value !== undefined && value !== null,
240
240
  { message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
241
241
  );
242
242
  }
@@ -244,31 +244,31 @@ function getZodNumberSchema({
244
244
  if (validation) {
245
245
 
246
246
  if (validation.min || validation.min === 0) schema = schema.refine(
247
- (value: any) => value == null || value >= validation.min!,
247
+ (value: unknown) => value == null || (typeof value === "number" && value >= validation.min!),
248
248
  { message: `${property.name} must be higher or equal to ${validation.min}` }
249
249
  );
250
250
  if (validation.max || validation.max === 0) schema = schema.refine(
251
- (value: any) => value == null || value <= validation.max!,
251
+ (value: unknown) => value == null || (typeof value === "number" && value <= validation.max!),
252
252
  { message: `${property.name} must be lower or equal to ${validation.max}` }
253
253
  );
254
254
  if (validation.lessThan || validation.lessThan === 0) schema = schema.refine(
255
- (value: any) => value == null || value < validation.lessThan!,
255
+ (value: unknown) => value == null || (typeof value === "number" && value < validation.lessThan!),
256
256
  { message: `${property.name} must be higher than ${validation.lessThan}` }
257
257
  );
258
258
  if (validation.moreThan || validation.moreThan === 0) schema = schema.refine(
259
- (value: any) => value == null || value > validation.moreThan!,
259
+ (value: unknown) => value == null || (typeof value === "number" && value > validation.moreThan!),
260
260
  { message: `${property.name} must be lower than ${validation.moreThan}` }
261
261
  );
262
262
  if (validation.positive) schema = schema.refine(
263
- (value: any) => value == null || value > 0,
263
+ (value: unknown) => value == null || (typeof value === "number" && value > 0),
264
264
  { message: `${property.name} must be positive` }
265
265
  );
266
266
  if (validation.negative) schema = schema.refine(
267
- (value: any) => value == null || value < 0,
267
+ (value: unknown) => value == null || (typeof value === "number" && value < 0),
268
268
  { message: `${property.name} must be negative` }
269
269
  );
270
270
  if (validation.integer) schema = schema.refine(
271
- (value: any) => value == null || Number.isInteger(value),
271
+ (value: unknown) => value == null || (typeof value === "number" && Number.isInteger(value)),
272
272
  { message: `${property.name} must be an integer` }
273
273
  );
274
274
  }
@@ -288,7 +288,7 @@ function getZodGeoPointSchema({
288
288
 
289
289
  if (validation?.required) {
290
290
  schema = schema.refine(
291
- (value: any) => value !== undefined && value !== null,
291
+ (value: unknown) => value !== undefined && value !== null,
292
292
  { message: validation.requiredMessage ? validation.requiredMessage : "Required" }
293
293
  );
294
294
  }
@@ -315,17 +315,17 @@ function getZodDateSchema({
315
315
  if (validation) {
316
316
  if (validation.required) {
317
317
  schema = schema.refine(
318
- (value: any) => value !== undefined && value !== null,
318
+ (value: unknown) => value !== undefined && value !== null,
319
319
  { message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
320
320
  );
321
321
  }
322
322
 
323
323
  if (validation.min) schema = schema.refine(
324
- (value: any) => value == null || value >= validation.min!,
324
+ (value: unknown) => value == null || (value instanceof Date && value >= validation.min!),
325
325
  { message: `${property.name} must be after ${validation.min}` }
326
326
  );
327
327
  if (validation.max) schema = schema.refine(
328
- (value: any) => value == null || value <= validation.max!,
328
+ (value: unknown) => value == null || (value instanceof Date && value <= validation.max!),
329
329
  { message: `${property.name} must be before ${validation.min}` }
330
330
  );
331
331
  }
@@ -345,7 +345,7 @@ function getZodReferenceSchema({
345
345
  if (validation) {
346
346
  if (validation.required) {
347
347
  schema = schema.refine(
348
- (value: any) => value !== undefined && value !== null,
348
+ (value: unknown) => value !== undefined && value !== null,
349
349
  { message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
350
350
  );
351
351
  }
@@ -370,7 +370,7 @@ function getZodRelationSchema({
370
370
  if (validation) {
371
371
  if (validation.required) {
372
372
  schema = schema.refine(
373
- (value: any) => {
373
+ (value: unknown) => {
374
374
  if (isMany) {
375
375
  return value !== undefined && value !== null && Array.isArray(value) && value.length > 0;
376
376
  }
@@ -397,7 +397,7 @@ function getZodBooleanSchema({
397
397
  if (validation) {
398
398
  if (validation.required) {
399
399
  schema = schema.refine(
400
- (value: any) => value !== undefined && value !== null,
400
+ (value: unknown) => value !== undefined && value !== null,
401
401
  { message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
402
402
  );
403
403
  }
@@ -480,13 +480,13 @@ function getZodArraySchema({
480
480
  if (arrayUniqueFields) {
481
481
  if (typeof arrayUniqueFields === "boolean") {
482
482
  arraySchema = arraySchema.refine(
483
- (values: any) => !values || values.length === new Set(values.map((v: any) => v)).size,
483
+ (values: unknown) => !values || !Array.isArray(values) || values.length === new Set(values).size,
484
484
  { message: `${property.name} should have unique values within the array` }
485
485
  );
486
486
  } else if (Array.isArray(arrayUniqueFields)) {
487
487
  arrayUniqueFields.forEach(([fieldName, childProperty]) => {
488
488
  arraySchema = arraySchema.refine(
489
- (values: any) => !values || values.length === new Set(values.map((v: any) => v && v[fieldName])).size,
489
+ (values: unknown) => !values || !Array.isArray(values) || values.length === new Set(values.map((v: unknown) => v && typeof v === "object" ? (v as Record<string, unknown>)[fieldName] : v)).size,
490
490
  { message: `${property.name} → ${childProperty.name ?? fieldName}: should have unique values within the array` }
491
491
  );
492
492
  });
@@ -499,22 +499,22 @@ function getZodArraySchema({
499
499
  if (validation) {
500
500
  if (validation.required) {
501
501
  arraySchema = arraySchema.refine(
502
- (value: any) => value !== undefined && value !== null && value.length > 0,
502
+ (value: unknown) => value !== undefined && value !== null && Array.isArray(value) && value.length > 0,
503
503
  { message: validation?.requiredMessage ? validation.requiredMessage : "Required" }
504
504
  );
505
505
  }
506
506
  if (validation.min || validation.min === 0) arraySchema = arraySchema.refine(
507
- (value: any) => !value || value.length >= validation.min!,
507
+ (value: unknown) => !value || !Array.isArray(value) || value.length >= validation.min!,
508
508
  { message: `${property.name} should be min ${validation.min} entries long` }
509
509
  );
510
510
  if (validation.max) arraySchema = arraySchema.refine(
511
- (value: any) => !value || value.length <= validation.max!,
511
+ (value: unknown) => !value || !Array.isArray(value) || value.length <= validation.max!,
512
512
  { message: `${property.name} should be max ${validation.max} entries long` }
513
513
  );
514
514
  // Handle uniqueInArray at the array level
515
515
  if (validation.uniqueInArray) {
516
516
  arraySchema = arraySchema.refine(
517
- (values: any) => !values || values.length === new Set(values.map((v: any) => v)).size,
517
+ (values: unknown) => !values || !Array.isArray(values) || values.length === new Set(values).size,
518
518
  { message: `${property.name} should have unique values within the array` }
519
519
  );
520
520
  }
@@ -526,12 +526,12 @@ function getZodVectorSchema({
526
526
  property
527
527
  }: PropertyContext<VectorProperty>): ZodTypeAny {
528
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;
529
+ (val: unknown) => {
530
+ if (val && typeof val === "object" && "__type" in val && (val as Record<string, unknown>).__type === "Vector") {
531
+ return (val as Record<string, unknown>).value;
532
532
  }
533
- if (val && typeof val === "object" && "value" in val && Array.isArray(val.value)) {
534
- return val.value;
533
+ if (val && typeof val === "object" && "value" in val && Array.isArray((val as Record<string, unknown>).value)) {
534
+ return (val as Record<string, unknown>).value;
535
535
  }
536
536
  return val;
537
537
  },
@@ -540,14 +540,14 @@ function getZodVectorSchema({
540
540
 
541
541
  if (property.dimensions) {
542
542
  schema = schema.refine(
543
- (val: any) => val === null || val === undefined || val.length === property.dimensions,
543
+ (val: unknown) => val === null || val === undefined || (Array.isArray(val) && val.length === property.dimensions),
544
544
  { message: `${property.name ?? "Vector"} must have exactly ${property.dimensions} dimensions` }
545
545
  );
546
546
  }
547
547
 
548
548
  if (property.validation?.required) {
549
549
  schema = schema.refine(
550
- (val: any) => val !== null && val !== undefined && val.length > 0,
550
+ (val: unknown) => val !== null && val !== undefined && Array.isArray(val) && val.length > 0,
551
551
  { message: property.validation?.requiredMessage ?? "Required" }
552
552
  );
553
553
  }
@@ -563,7 +563,7 @@ function getZodBinarySchema({
563
563
 
564
564
  if (validation?.required) {
565
565
  schema = schema.nullable().optional().refine(
566
- (value: any) => value !== undefined && value !== null && value !== "",
566
+ (value: unknown) => value !== undefined && value !== null && value !== "",
567
567
  { message: validation.requiredMessage ? validation.requiredMessage : "Required" }
568
568
  );
569
569
  }
@@ -59,7 +59,6 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
59
59
  userManagement
60
60
  } = props;
61
61
 
62
- // Step 1: Resolve collections
63
62
  const {
64
63
  collections,
65
64
  loading: collectionsLoading,
@@ -71,10 +70,10 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
71
70
  data,
72
71
  plugins,
73
72
  disabled,
74
- collectionRegistryController
73
+ collectionRegistryController,
74
+ userManagement
75
75
  });
76
76
 
77
- // Step 2: Resolve views and admin views
78
77
  const {
79
78
  views,
80
79
  adminViews,
@@ -89,8 +88,7 @@ export function useBuildNavigationStateController<EC extends EntityCollection, U
89
88
  plugins,
90
89
  adminMode,
91
90
  effectiveRoleController,
92
- userManagement,
93
- collections
91
+ userManagement
94
92
  });
95
93
 
96
94
  // Step 3: Compute top-level navigation (pure derived state)
@@ -3,7 +3,8 @@ import { useCallback, useEffect, useRef, useState, useMemo } from "react";
3
3
 
4
4
  import { AuthController, CollectionRegistryController, RebaseData, User } from "@rebasepro/types";
5
5
  import type { EntityCollectionsBuilder } from "@rebasepro/types";
6
- import { CollectionRegistry } from "@rebasepro/common";
6
+ import { CollectionRegistry, defaultUsersCollection } from "@rebasepro/common";
7
+ import { UserManagementDelegate } from "@rebasepro/types";
7
8
 
8
9
  import { resolveCollections } from "./useNavigationResolution";
9
10
  import { areCollectionListsEqual } from "./utils";
@@ -15,6 +16,7 @@ export type UseResolvedCollectionsProps<EC extends EntityCollection, USER extend
15
16
  plugins?: RebasePlugin[];
16
17
  disabled?: boolean;
17
18
  collectionRegistryController: CollectionRegistryController<EC> & { collectionRegistryRef: React.MutableRefObject<CollectionRegistry> };
19
+ userManagement?: UserManagementDelegate<USER>;
18
20
  };
19
21
 
20
22
  export type UseResolvedCollectionsResult = {
@@ -28,6 +30,10 @@ export type UseResolvedCollectionsResult = {
28
30
  * Hook that resolves collection props (which may be async builders or arrays)
29
31
  * into concrete EntityCollection[], and registers them with the CollectionRegistry.
30
32
  *
33
+ * When userManagement is provided, the default users collection is always
34
+ * prepended. Developer collections override via generic slug-based dedup
35
+ * (Map keyed by slug, last-write-wins). No hardcoded string checks.
36
+ *
31
37
  * Uses refs for potentially-unstable dependencies (driver, authController,
32
38
  * plugins) to avoid re-triggering effects when their object identity changes.
33
39
  */
@@ -41,7 +47,8 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
41
47
  data,
42
48
  plugins,
43
49
  disabled,
44
- collectionRegistryController
50
+ collectionRegistryController,
51
+ userManagement
45
52
  } = props;
46
53
 
47
54
  const [loading, setLoading] = useState(true);
@@ -63,6 +70,8 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
63
70
  authControllerRef.current = authController;
64
71
  const pluginsRef = useRef(plugins);
65
72
  pluginsRef.current = plugins;
73
+ const userManagementRef = useRef(userManagement);
74
+ userManagementRef.current = userManagement;
66
75
 
67
76
  // Ref for resolved collections change detection
68
77
  const resolvedCollectionsRef = useRef<EntityCollection[]>([]);
@@ -86,17 +95,27 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
86
95
 
87
96
  if (cancelled) return;
88
97
 
98
+ // Prepend system defaults; developer collections override via generic dedup.
99
+ // Map keyed by slug — last-write-wins, so developer collections overwrite defaults.
100
+ const defaults: EntityCollection[] = [];
101
+ if (userManagementRef.current) {
102
+ defaults.push(defaultUsersCollection);
103
+ }
104
+ const deduped = Array.from(
105
+ new Map([...defaults, ...resolved].map(c => [c.slug, c])).values()
106
+ );
107
+
89
108
  // Register with the CollectionRegistry; returns true if changed
90
- const changed = collectionRegistryController.collectionRegistryRef.current.registerMultiple(resolved);
109
+ const changed = collectionRegistryController.collectionRegistryRef.current.registerMultiple(deduped);
91
110
 
92
111
  if (changed) {
93
- console.debug("Collections have changed", resolved);
112
+ console.debug("Collections have changed", deduped);
94
113
  }
95
114
 
96
115
  // Only update state if collections actually changed
97
- if (!areCollectionListsEqual(resolvedCollectionsRef.current, resolved)) {
98
- resolvedCollectionsRef.current = resolved;
99
- setResolvedCollections(resolved);
116
+ if (!areCollectionListsEqual(resolvedCollectionsRef.current, deduped)) {
117
+ resolvedCollectionsRef.current = deduped;
118
+ setResolvedCollections(deduped);
100
119
  }
101
120
 
102
121
  setError(undefined);
@@ -131,3 +150,4 @@ export function useResolvedCollections<EC extends EntityCollection, USER extends
131
150
  refresh
132
151
  }), [resolvedCollections, loading, error, refresh]);
133
152
  }
153
+
@@ -23,9 +23,7 @@ import { UserManagementDelegate } from "@rebasepro/types";
23
23
  import { resolveAppViews } from "./useNavigationResolution";
24
24
 
25
25
 
26
- // Lazy-load admin views only rendered when navigation reaches /users or /roles
27
- const UsersView = lazy(() => import("../../components/admin/UsersView").then(m => ({ default: m.UsersView })));
28
- const RolesView = lazy(() => import("../../components/admin/RolesView").then(m => ({ default: m.RolesView })));
26
+ import { RolesView } from "../../components/admin/RolesView";
29
27
 
30
28
  export type UseResolvedViewsProps<USER extends User> = {
31
29
  authController: AuthController<USER>;
@@ -36,7 +34,6 @@ export type UseResolvedViewsProps<USER extends User> = {
36
34
  adminMode?: "content" | "studio" | "settings";
37
35
  effectiveRoleController?: EffectiveRoleController;
38
36
  userManagement?: UserManagementDelegate<USER>;
39
- collections?: EntityCollection[];
40
37
  };
41
38
 
42
39
  export type UseResolvedViewsResult = {
@@ -49,8 +46,8 @@ export type UseResolvedViewsResult = {
49
46
 
50
47
  /**
51
48
  * Hook that resolves view and admin view props (which may be async builders or arrays)
52
- * into concrete AppView[]. Also injects Users/Roles admin views when userManagement
53
- * is provided.
49
+ * into concrete AppView[]. Also injects the Roles admin view when userManagement
50
+ * is provided with roles.
54
51
  *
55
52
  * Uses refs for potentially-unstable dependencies (driver, authController,
56
53
  * plugins) to avoid re-triggering effects when their object identity changes.
@@ -67,8 +64,7 @@ export function useResolvedViews<USER extends User>(
67
64
  plugins,
68
65
  adminMode = "content",
69
66
  effectiveRoleController,
70
- userManagement,
71
- collections
67
+ userManagement
72
68
  } = props;
73
69
 
74
70
  const [loading, setLoading] = useState(true);
@@ -114,43 +110,27 @@ export function useResolvedViews<USER extends User>(
114
110
  const resolvedAuthControllerRef = useRef(resolvedAuthController);
115
111
  resolvedAuthControllerRef.current = resolvedAuthController;
116
112
 
117
- // Memoize JSX elements for injected admin views to ensure stable references.
118
- const usersViewElement = useMemo(() =>
119
- userManagement ? <Suspense fallback={null}><UsersView userManagement={userManagement as unknown as UserManagementDelegate<User>}/></Suspense> : null,
120
- [userManagement]
121
- );
113
+ // Memoize JSX element for injected Roles admin view to ensure stable reference.
114
+ const hasRoles = !!userManagement?.roles;
122
115
  const rolesViewElement = useMemo(() =>
123
- userManagement?.roles ? <Suspense fallback={null}><RolesView userManagement={userManagement as unknown as UserManagementDelegate<User>}/></Suspense> : null,
124
- [userManagement]
116
+ hasRoles ? <RolesView /> : null,
117
+ [hasRoles]
125
118
  );
126
119
 
127
120
  const injectedAdminViews: AppView[] = useMemo(() => {
128
121
  const views: AppView[] = [];
129
122
  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) {
143
- views.push({
144
- slug: "roles",
145
- name: "Roles",
146
- icon: "Shield",
147
- view: rolesViewElement,
148
- group: "Settings"
149
- });
150
- }
123
+ if (userManagement && isUserAdmin && userManagement.roles && rolesViewElement) {
124
+ views.push({
125
+ slug: "roles",
126
+ name: "Roles",
127
+ icon: "Shield",
128
+ view: rolesViewElement,
129
+ group: "Settings"
130
+ });
151
131
  }
152
132
  return views;
153
- }, [userManagement, usersViewElement, rolesViewElement, collections]);
133
+ }, [userManagement, rolesViewElement]);
154
134
 
155
135
  // Store injectedAdminViews in a ref for effect access
156
136
  const injectedAdminViewsRef = useRef(injectedAdminViews);
@@ -171,12 +151,12 @@ export function useResolvedViews<USER extends User>(
171
151
  resolveAppViews(adminViewsProp, resolvedAuthControllerRef.current, dataRef.current)
172
152
  ]);
173
153
 
174
- const hasCustomUsers = newAdminViewsProp.some(v => v.slug === "users");
175
- const hasCustomRoles = newAdminViewsProp.some(v => v.slug === "roles");
154
+ // Generic dedup: developer-provided admin views override any injected ones with the same slug.
155
+ // No hardcoded slug checks — works for any slug generically.
156
+ const customSlugs = new Set(newAdminViewsProp.flatMap(v => Array.isArray(v.slug) ? v.slug : [v.slug]));
176
157
  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;
158
+ const slugs = Array.isArray(v.slug) ? v.slug : [v.slug];
159
+ return slugs.every(s => !customSlugs.has(s));
180
160
  });
181
161
  const newAdminViews = [...newAdminViewsProp, ...finalInjected];
182
162
 
@@ -215,8 +195,7 @@ export function useResolvedViews<USER extends User>(
215
195
  refreshTrigger,
216
196
  adminMode,
217
197
  initialLoading,
218
- user,
219
- collections
198
+ user
220
199
  ]);
221
200
 
222
201
  return useMemo(() => ({
@@ -227,3 +206,4 @@ export function useResolvedViews<USER extends User>(
227
206
  refresh
228
207
  }), [resolvedViews, resolvedAdminViews, loading, error, refresh]);
229
208
  }
209
+
package/src/index.ts CHANGED
@@ -42,6 +42,8 @@ export {
42
42
  Scaffold,
43
43
  AppBar,
44
44
  Drawer,
45
+ DefaultDrawer,
46
+ DrawerFooterActions,
45
47
  AdminModeSyncer,
46
48
  // ContentHomePage, UsersView, RolesView are lazy-loaded — not re-exported here
47
49
  RebaseCMS,
@@ -57,7 +57,7 @@ export const PropertyPreview = React.memo(function PropertyPreview<P extends Pro
57
57
  if (property === null) {
58
58
  content = <EmptyValue/>;
59
59
  } else if (property.ui?.Preview) {
60
- const ResolvedPreview = resolveComponentRef(property.ui.Preview);
60
+ const ResolvedPreview = resolveComponentRef(property.ui.Preview) as React.ComponentType<PropertyPreviewProps<Property>> | undefined;
61
61
  if (ResolvedPreview) {
62
62
  content = <Suspense fallback={null}>
63
63
  {createElement(ResolvedPreview,
@@ -205,7 +205,7 @@ path: stringProperty.reference.path })}
205
205
  }
206
206
  } else if (property.type === "reference") {
207
207
  if (typeof property.path === "string") {
208
- if (typeof value === "object" && "isEntityReference" in value && value.isEntityReference()) {
208
+ if (typeof value === "object" && value !== null && "isEntityReference" in value && (value as EntityReference).isEntityReference()) {
209
209
  content = <ReferencePreview
210
210
  disabled={!property.path}
211
211
  previewProperties={property.ui?.previewProperties}
@@ -3,6 +3,7 @@ import React, { CSSProperties, useMemo, useState, useEffect } from "react";impor
3
3
  import { PreviewSize } from "../../types/components/PropertyPreviewProps";
4
4
  import { getThumbnailMeasure } from "../util";
5
5
  import { useTranslation } from "@rebasepro/core";
6
+ import { sanitizeUrl } from "./UrlComponentPreview";
6
7
 
7
8
  /**
8
9
  * @group Preview components
@@ -127,7 +128,7 @@ maxHeight: "100%" }}>
127
128
  className="invisible group-hover:visible"
128
129
  variant={"filled"}
129
130
  component={"a" as React.ElementType}
130
- href={url}
131
+ href={sanitizeUrl(url)}
131
132
  rel="noopener noreferrer"
132
133
  target="_blank"
133
134
  size={"smallest"}