@firecms/core 3.0.1 → 3.1.0-canary.1df3b2c

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 (170) hide show
  1. package/README.md +1 -1
  2. package/dist/components/AIIcon.d.ts +16 -0
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
  6. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
  7. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
  8. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
  9. package/dist/components/EntityCollectionView/Board.d.ts +2 -0
  10. package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
  11. package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
  12. package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
  13. package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
  14. package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
  15. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
  16. package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
  17. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
  18. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
  19. package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
  20. package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +49 -0
  21. package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
  22. package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
  23. package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
  24. package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
  25. package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
  26. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +2 -0
  27. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  28. package/dist/components/VirtualTable/VirtualTableProps.d.ts +11 -0
  29. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
  30. package/dist/components/VirtualTable/types.d.ts +2 -0
  31. package/dist/components/index.d.ts +3 -0
  32. package/dist/contexts/index.d.ts +10 -0
  33. package/dist/core/DrawerNavigationGroup.d.ts +45 -0
  34. package/dist/core/index.d.ts +1 -0
  35. package/dist/form/validation.d.ts +3 -2
  36. package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
  37. package/dist/hooks/useCollapsedGroups.d.ts +4 -1
  38. package/dist/index.es.js +5239 -1590
  39. package/dist/index.es.js.map +1 -1
  40. package/dist/index.umd.js +5233 -1585
  41. package/dist/index.umd.js.map +1 -1
  42. package/dist/preview/PropertyPreviewProps.d.ts +5 -0
  43. package/dist/preview/components/DatePreview.d.ts +13 -3
  44. package/dist/preview/components/ImagePreview.d.ts +5 -1
  45. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  46. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  47. package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
  48. package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
  49. package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
  50. package/dist/types/collections.d.ts +42 -2
  51. package/dist/types/datasource.d.ts +0 -1
  52. package/dist/types/plugins.d.ts +46 -1
  53. package/dist/types/properties.d.ts +259 -4
  54. package/dist/util/__tests__/conditions.test.d.ts +1 -0
  55. package/dist/util/__tests__/objects.test.d.ts +1 -0
  56. package/dist/util/conditions.d.ts +26 -0
  57. package/dist/util/entities.d.ts +1 -2
  58. package/dist/util/index.d.ts +2 -1
  59. package/dist/util/property_utils.d.ts +2 -1
  60. package/dist/util/resolutions.d.ts +1 -1
  61. package/package.json +10 -7
  62. package/src/app/Scaffold.tsx +14 -15
  63. package/src/components/AIIcon.tsx +39 -0
  64. package/src/components/ArrayContainer.tsx +1 -4
  65. package/src/components/ClearFilterSortButton.tsx +19 -16
  66. package/src/components/ConfirmationDialog.tsx +0 -2
  67. package/src/components/DeleteEntityDialog.tsx +2 -4
  68. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +74 -41
  69. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
  70. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
  71. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
  72. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +20 -42
  73. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
  74. package/src/components/EntityCollectionView/Board.tsx +324 -0
  75. package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
  76. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
  77. package/src/components/EntityCollectionView/BoardSortableList.tsx +172 -0
  78. package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
  79. package/src/components/EntityCollectionView/EntityCard.tsx +231 -0
  80. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +713 -0
  81. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +244 -0
  82. package/src/components/EntityCollectionView/EntityCollectionView.tsx +485 -203
  83. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +31 -19
  84. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +84 -15
  85. package/src/components/EntityCollectionView/FiltersDialog.tsx +249 -0
  86. package/src/components/EntityCollectionView/ViewModeToggle.tsx +202 -0
  87. package/src/components/EntityCollectionView/board_types.ts +113 -0
  88. package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
  89. package/src/components/ErrorTooltip.tsx +2 -1
  90. package/src/components/HomePage/DefaultHomePage.tsx +47 -10
  91. package/src/components/HomePage/HomePageDnD.tsx +56 -41
  92. package/src/components/HomePage/NavigationCard.tsx +20 -18
  93. package/src/components/HomePage/NavigationGroup.tsx +17 -16
  94. package/src/components/HomePage/RenameGroupDialog.tsx +0 -2
  95. package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
  96. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +3 -10
  97. package/src/components/ReferenceWidget.tsx +2 -4
  98. package/src/components/SelectableTable/SelectableTable.tsx +75 -67
  99. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
  100. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +39 -40
  101. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +38 -38
  102. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +49 -58
  103. package/src/components/UnsavedChangesDialog.tsx +0 -2
  104. package/src/components/UserDisplay.tsx +4 -4
  105. package/src/components/VirtualTable/VirtualTable.tsx +170 -19
  106. package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
  107. package/src/components/VirtualTable/VirtualTableHeader.tsx +20 -11
  108. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +158 -42
  109. package/src/components/VirtualTable/VirtualTableProps.tsx +14 -1
  110. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  111. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
  112. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +17 -4
  113. package/src/components/VirtualTable/types.tsx +2 -0
  114. package/src/components/common/useColumnsIds.tsx +95 -3
  115. package/src/components/index.tsx +4 -0
  116. package/src/contexts/BreacrumbsContext.tsx +15 -8
  117. package/src/contexts/index.ts +10 -0
  118. package/src/core/DefaultAppBar.tsx +39 -26
  119. package/src/core/DefaultDrawer.tsx +42 -56
  120. package/src/core/DrawerNavigationGroup.tsx +118 -0
  121. package/src/core/DrawerNavigationItem.tsx +4 -3
  122. package/src/core/EntityEditView.tsx +41 -43
  123. package/src/core/SideDialogs.tsx +4 -2
  124. package/src/core/index.tsx +1 -0
  125. package/src/form/PropertyFieldBinding.tsx +58 -43
  126. package/src/form/components/StorageItemPreview.tsx +2 -1
  127. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -1
  128. package/src/form/field_bindings/DateTimeFieldBinding.tsx +17 -16
  129. package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -1
  130. package/src/form/field_bindings/MapFieldBinding.tsx +69 -67
  131. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +21 -17
  132. package/src/form/field_bindings/TextFieldBinding.tsx +71 -35
  133. package/src/form/validation.ts +245 -160
  134. package/src/hooks/useBreadcrumbsController.tsx +18 -0
  135. package/src/hooks/useBuildNavigationController.tsx +42 -19
  136. package/src/hooks/useCollapsedGroups.ts +12 -4
  137. package/src/internal/useBuildDataSource.ts +69 -34
  138. package/src/internal/useBuildSideDialogsController.tsx +11 -8
  139. package/src/internal/useBuildSideEntityController.tsx +2 -4
  140. package/src/internal/useRestoreScroll.tsx +26 -14
  141. package/src/preview/PropertyPreview.tsx +40 -32
  142. package/src/preview/PropertyPreviewProps.tsx +6 -0
  143. package/src/preview/components/DatePreview.tsx +72 -4
  144. package/src/preview/components/EmptyValue.tsx +1 -1
  145. package/src/preview/components/ImagePreview.tsx +37 -21
  146. package/src/preview/components/StorageThumbnail.tsx +16 -12
  147. package/src/preview/components/UrlComponentPreview.tsx +28 -25
  148. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
  149. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
  150. package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
  151. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
  152. package/src/routes/CustomCMSRoute.tsx +1 -0
  153. package/src/routes/FireCMSRoute.tsx +26 -13
  154. package/src/types/collections.ts +48 -3
  155. package/src/types/datasource.ts +54 -56
  156. package/src/types/plugins.tsx +51 -1
  157. package/src/types/properties.ts +347 -27
  158. package/src/util/__tests__/conditions.test.ts +506 -0
  159. package/src/util/__tests__/objects.test.ts +196 -0
  160. package/src/util/callbacks.ts +6 -3
  161. package/src/util/collections.ts +51 -6
  162. package/src/util/conditions.ts +339 -0
  163. package/src/util/entities.ts +28 -29
  164. package/src/util/entity_cache.ts +2 -1
  165. package/src/util/index.ts +2 -1
  166. package/src/util/objects.ts +31 -13
  167. package/src/util/{references.ts → previews.ts} +14 -0
  168. package/src/util/property_utils.tsx +36 -10
  169. package/src/util/resolutions.ts +57 -55
  170. /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
@@ -12,10 +12,9 @@ export function isObject(item: any) {
12
12
  return item && typeof item === "object" && !Array.isArray(item);
13
13
  }
14
14
 
15
-
16
- export function isPlainObject(obj:any) {
15
+ export function isPlainObject(obj: any) {
17
16
  // 1. Rule out non-objects, null, and arrays
18
- if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {
17
+ if (typeof obj !== "object" || obj === null || Array.isArray(obj)) {
19
18
  return false;
20
19
  }
21
20
 
@@ -26,7 +25,6 @@ export function isPlainObject(obj:any) {
26
25
  return proto === Object.prototype;
27
26
  }
28
27
 
29
-
30
28
  export function mergeDeep<T extends Record<any, any>, U extends Record<any, any>>(
31
29
  target: T,
32
30
  source: U,
@@ -75,9 +73,11 @@ export function mergeDeep<T extends Record<any, any>, U extends Record<any, any>
75
73
  newArray[i] = sourceItem;
76
74
  } else if (sourceItem === null) {
77
75
  newArray[i] = targetItem;
78
- } else if (isObject(sourceItem) && isObject(targetItem)) {
76
+ } else if (isPlainObject(sourceItem) && isPlainObject(targetItem)) {
77
+ // Only recursively merge plain objects, preserve class instances
79
78
  newArray[i] = mergeDeep(targetItem, sourceItem, ignoreUndefined);
80
79
  } else {
80
+ // For class instances and primitives, use source directly
81
81
  newArray[i] = sourceItem;
82
82
  }
83
83
  }
@@ -87,17 +87,20 @@ export function mergeDeep<T extends Record<any, any>, U extends Record<any, any>
87
87
  // overwrite with a shallow copy of the source array.
88
88
  (output as any)[key] = [...sourceValue];
89
89
  }
90
- } else if (isObject(sourceValue)) {
91
- // If source value is an object:
92
- if (isObject(outputValue)) {
93
- // If the corresponding value in output (from target) is also an object, recurse.
90
+ } else if (isPlainObject(sourceValue)) {
91
+ // If source value is a plain object (not a class instance like EntityReference, GeoPoint, etc.):
92
+ if (isPlainObject(outputValue)) {
93
+ // If the corresponding value in output (from target) is also a plain object, recurse.
94
94
  // Ensure the ignoreUndefined flag is passed down.
95
95
  (output as any)[key] = mergeDeep(outputValue, sourceValue, ignoreUndefined);
96
96
  } else {
97
- // If output's value (from target) is not an object (e.g., null, primitive, or key didn't exist in original target),
97
+ // If output's value (from target) is not a plain object (e.g., null, primitive, class instance, or key didn't exist in original target),
98
98
  // overwrite with the source object.
99
99
  (output as any)[key] = sourceValue;
100
100
  }
101
+ } else if (isObject(sourceValue)) {
102
+ // If source value is a class instance (not a plain object), use it directly to preserve prototype
103
+ (output as any)[key] = sourceValue;
101
104
  } else {
102
105
  // If source value is a primitive, null, or undefined (and not ignored).
103
106
  (output as any)[key] = sourceValue;
@@ -108,7 +111,6 @@ export function mergeDeep<T extends Record<any, any>, U extends Record<any, any>
108
111
  return output as T & U;
109
112
  }
110
113
 
111
-
112
114
  export function getValueInPath(o: object | undefined, path: string): any {
113
115
  if (!o) return undefined;
114
116
  if (typeof o === "object") {
@@ -151,6 +153,14 @@ export function removeFunctions(o: object | undefined): any {
151
153
  if (o === undefined) return undefined;
152
154
  if (o === null) return null;
153
155
  if (typeof o === "object") {
156
+ // Handle arrays first - map over them recursively
157
+ if (Array.isArray(o)) {
158
+ return o.map(v => removeFunctions(v));
159
+ }
160
+ // Preserve class instances (EntityReference, GeoPoint, etc.) - don't recurse into them
161
+ if (!isPlainObject(o)) {
162
+ return o;
163
+ }
154
164
  return Object.entries(o)
155
165
  .filter(([_, value]) => typeof value !== "function")
156
166
  .map(([key, value]) => {
@@ -186,9 +196,13 @@ export function removeUndefined(value: any, removeEmptyStrings?: boolean): any {
186
196
  return value.map((v: any) => removeUndefined(v, removeEmptyStrings));
187
197
  }
188
198
  if (typeof value === "object") {
189
- const res: object = {};
190
199
  if (value === null)
191
200
  return value;
201
+ // Preserve class instances (EntityReference, GeoPoint, etc.) - don't recurse into them
202
+ if (!isPlainObject(value)) {
203
+ return value;
204
+ }
205
+ const res: object = {};
192
206
  Object.keys(value).forEach((key) => {
193
207
  if (!isEmptyObject(value)) {
194
208
  const childRes = removeUndefined(value[key], removeEmptyStrings);
@@ -211,9 +225,13 @@ export function removeNulls(value: any): any {
211
225
  return value.map((v: any) => removeNulls(v));
212
226
  }
213
227
  if (typeof value === "object") {
214
- const res: object = {};
215
228
  if (value === null)
216
229
  return value;
230
+ // Preserve class instances (EntityReference, GeoPoint, etc.) - don't recurse into them
231
+ if (!isPlainObject(value)) {
232
+ return value;
233
+ }
234
+ const res: object = {};
217
235
  Object.keys(value).forEach((key) => {
218
236
  if (value[key] !== null)
219
237
  (res as any)[key] = removeNulls(value[key]);
@@ -58,5 +58,19 @@ export function getEntityImagePreviewPropertyKey<M extends object>(collection: R
58
58
  return key;
59
59
  }
60
60
  }
61
+ // also check for URL properties with image preview type
62
+ for (const key in collection.properties) {
63
+ const property = collection.properties[key];
64
+ if (property.dataType === "string" && property.url === "image") {
65
+ return key;
66
+ }
67
+ }
68
+ // and arrays of URL properties with image preview type
69
+ for (const key in collection.properties) {
70
+ const property = collection.properties[key];
71
+ if (property.dataType === "array" && property.of?.dataType === "string" && property.of.url === "image") {
72
+ return key;
73
+ }
74
+ }
61
75
  return undefined;
62
76
  }
@@ -36,13 +36,13 @@ export function isReferenceProperty(
36
36
  }
37
37
 
38
38
  export function getIdIcon(size: "small" | "medium" | "large"): React.ReactNode {
39
- return <CircleIcon size={size}/>;
39
+ return <CircleIcon size={size} />;
40
40
  }
41
41
 
42
42
  export function getIconForWidget(widget: PropertyConfig | undefined,
43
- size: "small" | "medium" | "large") {
43
+ size: "small" | "medium" | "large") {
44
44
  const Icon = widget?.Icon ?? CircleIcon;
45
- return <Icon size={size}/>;
45
+ return <Icon size={size} />;
46
46
  }
47
47
 
48
48
  export function getIconForProperty(
@@ -52,7 +52,7 @@ export function getIconForProperty(
52
52
  ): React.ReactNode {
53
53
 
54
54
  if (isPropertyBuilder(property)) {
55
- return <FunctionsIcon size={size}/>;
55
+ return <FunctionsIcon size={size} />;
56
56
  } else {
57
57
  const widget = getFieldConfig(property, fields);
58
58
  return getIconForWidget(widget, size);
@@ -113,25 +113,51 @@ export function getBracketNotation(path: string): string {
113
113
  }
114
114
 
115
115
  /**
116
- * Get properties exclusively indexed by their order
116
+ * Get properties sorted by their order, but include ALL properties.
117
+ * Nested keys (like "data.mode") in propertiesOrder are ignored - they're for column ordering.
117
118
  * @param properties
118
119
  * @param propertiesOrder
119
120
  */
120
121
  export function getPropertiesWithPropertiesOrder<M extends Record<string, any>>(properties: PropertiesOrBuilders<M>, propertiesOrder?: Extract<keyof M, string>[]): PropertiesOrBuilders<M> {
121
122
  if (!propertiesOrder) return properties;
123
+
124
+ const propertyKeys = Object.keys(properties);
125
+
126
+ // Filter propertiesOrder to only include top-level keys (no dots) that exist
127
+ const validOrderKeys = (propertiesOrder as string[]).filter(
128
+ key => !key.includes(".") && properties[key as keyof M]
129
+ );
130
+
122
131
  const result: PropertiesOrBuilders<any> = {};
123
- propertiesOrder.filter(Boolean).forEach(path => {
124
- const property = getPropertyInPath(properties, path);
132
+
133
+ // First add properties in the specified order
134
+ validOrderKeys.forEach(key => {
135
+ const property = properties[key];
125
136
  if (typeof property === "object" && property.dataType === "map" && property.properties) {
126
- result[path] = {
137
+ result[key] = {
127
138
  ...property,
128
139
  properties: getPropertiesWithPropertiesOrder(property.properties, property.propertiesOrder ?? [])
129
140
  }
141
+ } else if (property) {
142
+ result[key] = property;
130
143
  }
131
- if (property) {
132
- result[path] = property;
144
+ });
145
+
146
+ // Then add any missing properties (so they don't disappear!)
147
+ propertyKeys.forEach(key => {
148
+ if (!result[key]) {
149
+ const property = properties[key];
150
+ if (typeof property === "object" && property.dataType === "map" && property.properties) {
151
+ result[key] = {
152
+ ...property,
153
+ properties: getPropertiesWithPropertiesOrder(property.properties, property.propertiesOrder ?? [])
154
+ }
155
+ } else if (property) {
156
+ result[key] = property;
157
+ }
133
158
  }
134
159
  });
160
+
135
161
  return result;
136
162
  }
137
163
 
@@ -31,28 +31,28 @@ import { getIn } from "@firecms/formex";
31
31
  import { enumToObjectEntries } from "./enums";
32
32
  import { isDefaultFieldConfigId } from "../core";
33
33
 
34
- export const resolveCollection = <M extends Record<string, any>, >
35
- ({
36
- collection,
37
- path,
38
- entityId,
39
- values,
40
- previousValues,
41
- userConfigPersistence,
42
- propertyConfigs,
43
- ignoreMissingFields = false,
44
- authController
45
- }: {
46
- collection: EntityCollection<M> | ResolvedEntityCollection<M>;
47
- path: string,
48
- entityId?: string,
49
- values?: Partial<EntityValues<M>>,
50
- previousValues?: Partial<EntityValues<M>>,
51
- userConfigPersistence?: UserConfigurationPersistence;
52
- propertyConfigs?: Record<string, PropertyConfig>;
53
- ignoreMissingFields?: boolean;
54
- authController: AuthController;
55
- }): ResolvedEntityCollection<M> => {
34
+ export const resolveCollection = <M extends Record<string, any>,>
35
+ ({
36
+ collection,
37
+ path,
38
+ entityId,
39
+ values,
40
+ previousValues,
41
+ userConfigPersistence,
42
+ propertyConfigs,
43
+ ignoreMissingFields = false,
44
+ authController
45
+ }: {
46
+ collection: EntityCollection<M> | ResolvedEntityCollection<M>;
47
+ path: string,
48
+ entityId?: string,
49
+ values?: Partial<EntityValues<M>>,
50
+ previousValues?: Partial<EntityValues<M>>,
51
+ userConfigPersistence?: UserConfigurationPersistence;
52
+ propertyConfigs?: Record<string, PropertyConfig>;
53
+ ignoreMissingFields?: boolean;
54
+ authController: AuthController;
55
+ }): ResolvedEntityCollection<M> => {
56
56
 
57
57
  const collectionOverride = userConfigPersistence?.getCollectionConfig<M>(path);
58
58
  const storedProperties = getValueInPath(collectionOverride, "properties");
@@ -102,11 +102,11 @@ export const resolveCollection = <M extends Record<string, any>, >
102
102
  * @param propertyValue
103
103
  */
104
104
  export function resolveProperty<T extends CMSType = CMSType, M extends Record<string, any> = any>({
105
- propertyOrBuilder,
106
- fromBuilder = false,
107
- ignoreMissingFields = false,
108
- ...props
109
- }: {
105
+ propertyOrBuilder,
106
+ fromBuilder = false,
107
+ ignoreMissingFields = false,
108
+ ...props
109
+ }: {
110
110
  propertyKey?: string,
111
111
  propertyOrBuilder: PropertyOrBuilder<T, M> | ResolvedProperty<T>,
112
112
  values?: Partial<M>,
@@ -223,11 +223,11 @@ export function resolveProperty<T extends CMSType = CMSType, M extends Record<st
223
223
  }
224
224
 
225
225
  export function getArrayResolvedProperties<M>({
226
- propertyKey,
227
- propertyValue,
228
- property,
229
- ...props
230
- }: {
226
+ propertyKey,
227
+ propertyValue,
228
+ property,
229
+ ...props
230
+ }: {
231
231
  propertyValue: any,
232
232
  propertyKey?: string,
233
233
  property: ArrayProperty<any> | ResolvedArrayProperty<any>,
@@ -256,11 +256,11 @@ export function getArrayResolvedProperties<M>({
256
256
  }
257
257
 
258
258
  export function resolveArrayProperty<T extends any[], M>({
259
- propertyKey,
260
- property,
261
- ignoreMissingFields = false,
262
- ...props
263
- }: {
259
+ propertyKey,
260
+ property,
261
+ ignoreMissingFields = false,
262
+ ...props
263
+ }: {
264
264
  propertyKey?: string,
265
265
  property: ArrayProperty<T> | ResolvedArrayProperty<T>,
266
266
  values?: Partial<M>,
@@ -272,7 +272,7 @@ export function resolveArrayProperty<T extends any[], M>({
272
272
  propertyConfigs?: Record<string, PropertyConfig>;
273
273
  ignoreMissingFields?: boolean;
274
274
  authController: AuthController;
275
- }): ResolvedArrayProperty {
275
+ }): ResolvedArrayProperty | null {
276
276
  const propertyValue = propertyKey ? getIn(props.values, propertyKey) : undefined;
277
277
 
278
278
  if (property.of) {
@@ -347,7 +347,8 @@ export function resolveArrayProperty<T extends any[], M>({
347
347
  resolvedProperties
348
348
  } as ResolvedArrayProperty;
349
349
  } else if (!property.Field) {
350
- throw Error("The array property needs to declare an 'of' or a 'oneOf' property, or provide a custom `Field`")
350
+ console.error("The array property needs to declare an 'of' or a 'oneOf' property, or provide a custom `Field`", property);
351
+ return null;
351
352
  } else {
352
353
  return {
353
354
  ...property,
@@ -364,11 +365,11 @@ export function resolveArrayProperty<T extends any[], M>({
364
365
  * @param value
365
366
  */
366
367
  export function resolveProperties<M extends Record<string, any>>({
367
- propertyKey,
368
- properties,
369
- ignoreMissingFields,
370
- ...props
371
- }: {
368
+ propertyKey,
369
+ properties,
370
+ ignoreMissingFields,
371
+ ...props
372
+ }: {
372
373
  propertyKey?: string,
373
374
  properties: PropertiesOrBuilders<M>,
374
375
  values?: Partial<M>,
@@ -416,16 +417,17 @@ export function resolvePropertyEnum(property: StringProperty | NumberProperty, f
416
417
  }
417
418
 
418
419
  export function resolveEnumValues(input: EnumValues): EnumValueConfig[] | undefined {
419
- if (typeof input === "object") {
420
- return Object.entries(input).map(([id, value]) =>
421
- (typeof value === "string"
422
- ? {
423
- id,
424
- label: value
425
- }
426
- : value));
427
- } else if (Array.isArray(input)) {
420
+ // Check Array.isArray first since typeof [] === "object" is true in JavaScript
421
+ if (Array.isArray(input)) {
428
422
  return input as EnumValueConfig[];
423
+ } else if (typeof input === "object" && input !== null) {
424
+ return Object.entries(input).map(([id, value]) =>
425
+ (typeof value === "string"
426
+ ? {
427
+ id,
428
+ label: value
429
+ }
430
+ : value));
429
431
  } else {
430
432
  return undefined;
431
433
  }
@@ -457,8 +459,8 @@ export function resolvedSelectedEntityView<M extends Record<string, any>>(
457
459
  canEdit?: boolean,
458
460
  ) {
459
461
  const resolvedEntityViews = customViews ? customViews
460
- .map(e => resolveEntityView(e, customizationController.entityViews))
461
- .filter((e): e is EntityCustomView<M> => Boolean(e))
462
+ .map(e => resolveEntityView(e, customizationController.entityViews))
463
+ .filter((e): e is EntityCustomView<M> => Boolean(e))
462
464
  // .filter((e) => canEdit || !e.includeActions)
463
465
  : [];
464
466
 
File without changes