@firecms/core 3.0.0-canary.140 → 3.0.0-canary.142

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 (34) hide show
  1. package/dist/components/ArrayContainer.d.ts +13 -3
  2. package/dist/components/EntityCollectionTable/internal/popup_field/PopupFormField.d.ts +6 -3
  3. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  4. package/dist/form/components/index.d.ts +0 -1
  5. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  6. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -2
  7. package/dist/index.es.js +9433 -9358
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/index.umd.js +9432 -9357
  10. package/dist/index.umd.js.map +1 -1
  11. package/dist/types/collections.d.ts +2 -1
  12. package/dist/types/fields.d.ts +16 -0
  13. package/dist/util/objects.d.ts +1 -0
  14. package/dist/util/property_utils.d.ts +2 -2
  15. package/package.json +14 -14
  16. package/src/components/ArrayContainer.tsx +36 -13
  17. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +6 -4
  18. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +66 -58
  19. package/src/components/EntityCollectionView/EntityCollectionView.tsx +2 -3
  20. package/src/form/PropertyFieldBinding.tsx +22 -17
  21. package/src/form/components/index.tsx +0 -1
  22. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +16 -10
  23. package/src/form/field_bindings/BlockFieldBinding.tsx +24 -8
  24. package/src/form/field_bindings/KeyValueFieldBinding.tsx +4 -1
  25. package/src/form/field_bindings/MapFieldBinding.tsx +55 -39
  26. package/src/form/field_bindings/ReferenceFieldBinding.tsx +1 -1
  27. package/src/form/field_bindings/RepeatFieldBinding.tsx +25 -20
  28. package/src/hooks/data/save.ts +0 -1
  29. package/src/types/collections.ts +2 -1
  30. package/src/types/fields.tsx +18 -0
  31. package/src/util/objects.ts +20 -0
  32. package/src/util/property_utils.tsx +9 -2
  33. package/dist/form/components/FormikArrayContainer.d.ts +0 -19
  34. package/src/form/components/FormikArrayContainer.tsx +0 -47
@@ -497,5 +497,6 @@ export type SelectedCellProps<M extends Record<string, any>> = {
497
497
  cellRect: DOMRect;
498
498
  width: number;
499
499
  height: number;
500
- entity: Entity<M>;
500
+ entityPath: string;
501
+ entityId: string;
501
502
  };
@@ -90,6 +90,14 @@ export interface FieldProps<T extends CMSType = any, CustomProps = any, M extend
90
90
  * Size of the field
91
91
  */
92
92
  size?: "smallest" | "small" | "medium";
93
+ /**
94
+ * Some properties might change internal state (like expanding a panel).
95
+ * This function should be called when the internal state changes.
96
+ * This is used to preserve state in array containers.
97
+ *
98
+ * @param property
99
+ */
100
+ onPropertyChange?: (property: Partial<Property<any>>) => void;
93
101
  }
94
102
  /**
95
103
  * Context passed to custom fields
@@ -183,4 +191,12 @@ export interface PropertyFieldBindingProps<T extends CMSType, M extends Record<s
183
191
  * The size of the field
184
192
  */
185
193
  size?: "smallest" | "small" | "medium";
194
+ /**
195
+ * Some properties might change internal state (like expanding a panel).
196
+ * This function should be called when the internal state changes.
197
+ * This is used to preserve state in array containers.
198
+ *
199
+ * @param property
200
+ */
201
+ onPropertyChange?: (property: Partial<Property<any>>) => void;
186
202
  }
@@ -6,5 +6,6 @@ export declare function removeInPath(o: object, path: string): object | undefine
6
6
  export declare function removeFunctions(o: object | undefined): any;
7
7
  export declare function getHashValue<T>(v: T): any;
8
8
  export declare function removeUndefined(value: any, removeEmptyStrings?: boolean): any;
9
+ export declare function removeNulls(value: any): any;
9
10
  export declare function isEmptyObject(obj: object): boolean;
10
11
  export declare function removePropsIfExisting(source: any, comparison: any): any;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { EntityCollection, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedProperty } from "../types";
2
+ import { EntityCollection, PropertiesOrBuilders, PropertyConfig, PropertyOrBuilder, ResolvedProperties, ResolvedProperty } from "../types";
3
3
  export declare function isReferenceProperty(propertyOrBuilder: PropertyOrBuilder, fields: Record<string, PropertyConfig>): boolean | null;
4
4
  export declare function getIdIcon(size: "small" | "medium" | "large"): React.ReactNode;
5
5
  export declare function getIconForWidget(widget: PropertyConfig | undefined, size: "small" | "medium" | "large"): import("react/jsx-runtime").JSX.Element;
@@ -11,7 +11,7 @@ export declare function getColorForProperty(property: PropertyOrBuilder, fields:
11
11
  * @param properties
12
12
  * @param path
13
13
  */
14
- export declare function getPropertyInPath<M extends Record<string, any>>(properties: PropertiesOrBuilders<M>, path: string): PropertyOrBuilder<any, M> | undefined;
14
+ export declare function getPropertyInPath<M extends Record<string, any>>(properties: PropertiesOrBuilders<M> | ResolvedProperties, path: string): PropertyOrBuilder<any, M> | undefined;
15
15
  export declare function getResolvedPropertyInPath(properties: Record<string, ResolvedProperty>, path: string): ResolvedProperty | undefined;
16
16
  export declare function getBracketNotation(path: string): string;
17
17
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@firecms/core",
3
3
  "type": "module",
4
- "version": "3.0.0-canary.140",
4
+ "version": "3.0.0-canary.142",
5
5
  "description": "Awesome Firebase/Firestore-based headless open-source CMS",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/firecmsco"
@@ -46,9 +46,9 @@
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "@firecms/editor": "^3.0.0-canary.140",
50
- "@firecms/formex": "^3.0.0-canary.140",
51
- "@firecms/ui": "^3.0.0-canary.140",
49
+ "@firecms/editor": "^3.0.0-canary.142",
50
+ "@firecms/formex": "^3.0.0-canary.142",
51
+ "@firecms/ui": "^3.0.0-canary.142",
52
52
  "@hello-pangea/dnd": "^17.0.0",
53
53
  "@radix-ui/react-portal": "^1.1.2",
54
54
  "clsx": "^2.1.1",
@@ -58,7 +58,7 @@
58
58
  "markdown-it": "^14.1.0",
59
59
  "notistack": "^3.0.1",
60
60
  "object-hash": "^3.0.0",
61
- "react-dropzone": "^14.2.9",
61
+ "react-dropzone": "^14.2.10",
62
62
  "react-fast-compare": "^3.2.2",
63
63
  "react-image-file-resizer": "^0.4.8",
64
64
  "react-transition-group": "^4.4.5",
@@ -77,30 +77,30 @@
77
77
  "@jest/globals": "^29.7.0",
78
78
  "@testing-library/react": "^16.0.1",
79
79
  "@testing-library/user-event": "^14.5.2",
80
- "@types/jest": "^29.5.13",
80
+ "@types/jest": "^29.5.14",
81
81
  "@types/node": "^20.16.11",
82
82
  "@types/object-hash": "^3.0.6",
83
- "@types/react": "^18.3.11",
84
- "@types/react-dom": "^18.3.0",
83
+ "@types/react": "^18.3.12",
84
+ "@types/react-dom": "^18.3.1",
85
85
  "@types/react-measure": "^2.0.12",
86
- "@vitejs/plugin-react": "^4.3.2",
86
+ "@vitejs/plugin-react": "^4.3.3",
87
87
  "cross-env": "^7.0.3",
88
- "firebase": "^10.14.0",
88
+ "firebase": "^10.14.1",
89
89
  "jest": "^29.7.0",
90
90
  "npm-run-all": "^4.1.5",
91
- "react-router": "^6.26.2",
92
- "react-router-dom": "^6.26.2",
91
+ "react-router": "^6.27.0",
92
+ "react-router-dom": "^6.27.0",
93
93
  "ts-jest": "^29.2.5",
94
94
  "ts-node": "^10.9.2",
95
95
  "tsd": "^0.31.2",
96
96
  "typescript": "^5.6.3",
97
- "vite": "^5.4.8"
97
+ "vite": "^5.4.10"
98
98
  },
99
99
  "files": [
100
100
  "dist",
101
101
  "src"
102
102
  ],
103
- "gitHead": "112132e315d1ae63babf9f53500c00bc37a2d8e4",
103
+ "gitHead": "9adfc426dab9b7e197f1080065e08d49366fdadd",
104
104
  "publishConfig": {
105
105
  "access": "public"
106
106
  },
@@ -16,11 +16,21 @@ import {
16
16
  useOutsideAlerter
17
17
  } from "@firecms/ui";
18
18
 
19
+ export type ArrayEntryParams = {
20
+ index: number,
21
+ internalId: number,
22
+ isDragging: boolean,
23
+ storedProps?: object,
24
+ storeProps: (props: object) => void
25
+ };
26
+
27
+ export type ArrayEntryBuilder = (params: ArrayEntryParams) => React.ReactNode;
28
+
19
29
  export interface ArrayContainerProps<T> {
20
30
  droppableId: string;
21
31
  value: T[];
22
32
  addLabel: string;
23
- buildEntry: (index: number, internalId: number, isDragging:boolean) => React.ReactNode;
33
+ buildEntry: ArrayEntryBuilder;
24
34
  disabled?: boolean;
25
35
  size?: "small" | "medium";
26
36
  onInternalIdAdded?: (id: number) => void;
@@ -67,6 +77,12 @@ export function ArrayContainer<T>({
67
77
  ? Object.values(internalIdsRef.current)
68
78
  : []);
69
79
 
80
+ const itemCustomPropsRef = useRef<Record<number, object>>({});
81
+
82
+ const updateItemCustomProps = useCallback((internalId: number, customProps: object) => {
83
+ itemCustomPropsRef.current[internalId] = customProps;
84
+ }, []);
85
+
70
86
  useEffect(() => {
71
87
  if (hasValue && value && value.length !== internalIds.length) {
72
88
  const newInternalIds = value.map((v, index) => {
@@ -149,6 +165,8 @@ export function ArrayContainer<T>({
149
165
  remove={remove}
150
166
  copy={copy}
151
167
  isDragging={snapshot.isDragging}
168
+ storedProps={itemCustomPropsRef.current[internalId]}
169
+ updateItemCustomProps={updateItemCustomProps}
152
170
  />
153
171
  );
154
172
  }}
@@ -176,6 +194,8 @@ export function ArrayContainer<T>({
176
194
  remove={remove}
177
195
  copy={copy}
178
196
  isDragging={snapshot.isDragging}
197
+ storedProps={itemCustomPropsRef.current[internalId]}
198
+ updateItemCustomProps={updateItemCustomProps}
179
199
  />
180
200
  )}
181
201
  </Draggable>
@@ -208,10 +228,12 @@ type ArrayContainerItemProps = {
208
228
  internalId: number,
209
229
  size?: "small" | "medium",
210
230
  disabled: boolean,
211
- buildEntry: (index: number, internalId: number, isDragging: boolean) => React.ReactNode,
231
+ buildEntry: ArrayEntryBuilder,
212
232
  remove: (index: number) => void,
213
233
  copy: (index: number) => void,
214
234
  isDragging: boolean,
235
+ storedProps?: object,
236
+ updateItemCustomProps: (internalId: number, props: object) => void
215
237
  };
216
238
 
217
239
  export function ArrayContainerItem({
@@ -223,29 +245,30 @@ export function ArrayContainerItem({
223
245
  buildEntry,
224
246
  remove,
225
247
  copy,
226
- isDragging
248
+ isDragging,
249
+ storedProps,
250
+ updateItemCustomProps
227
251
  }: ArrayContainerItemProps) {
228
252
 
229
- const [onHover, setOnHover] = React.useState(false);
230
- const setOnHoverTrue = useCallback(() => setOnHover(true), []);
231
- const setOnHoverFalse = useCallback(() => setOnHover(false), []);
232
-
233
253
  return <div
234
- onMouseEnter={setOnHoverTrue}
235
- onMouseMove={setOnHoverTrue}
236
- onMouseLeave={setOnHoverFalse}
237
254
  ref={provided.innerRef}
238
255
  {...provided.draggableProps}
239
256
  style={provided.draggableProps.style}
240
257
  className={`${
241
- (isDragging || onHover) ? "hover:bg-slate-50 dark:hover:bg-gray-800 dark:hover:bg-opacity-20" : ""
242
- } mb-1 rounded-md opacity-100`}
258
+ !isDragging ? "hover:bg-slate-50 dark:hover:bg-gray-800 dark:hover:bg-opacity-20" : ""
259
+ } rounded-md opacity-100`}
243
260
  >
244
261
  <div
245
262
  className="flex items-start">
246
263
  <div
247
264
  className="flex-grow w-[calc(100%-48px)] text-text-primary dark:text-text-primary-dark">
248
- {buildEntry(index, internalId, isDragging)}
265
+ {buildEntry({
266
+ index,
267
+ internalId,
268
+ isDragging,
269
+ storedProps,
270
+ storeProps: (props: object) => updateItemCustomProps(internalId, props)
271
+ })}
249
272
  </div>
250
273
  <ArrayItemOptions direction={size === "small" ? "row" : "column"}
251
274
  disabled={disabled}
@@ -89,8 +89,8 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
89
89
  } = useSelectableTableController();
90
90
 
91
91
  const selected = selectedCell?.propertyKey === propertyKey &&
92
- selectedCell?.entity.path === entity.path &&
93
- selectedCell?.entity.id === entity.id;
92
+ selectedCell?.entityPath === entity.path &&
93
+ selectedCell?.entityId === entity.id;
94
94
 
95
95
  const [internalValue, setInternalValue] = useState<any | null>(value);
96
96
  const internalValueRef = useRef(value);
@@ -193,7 +193,8 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
193
193
  select({
194
194
  width,
195
195
  height,
196
- entity,
196
+ entityPath: entity.path,
197
+ entityId: entity.id,
197
198
  cellRect,
198
199
  propertyKey: propertyKey as Extract<keyof M, string>
199
200
  });
@@ -209,7 +210,8 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
209
210
  setPopupCell({
210
211
  width,
211
212
  height,
212
- entity,
213
+ entityPath: entity.path,
214
+ entityId: entity.id,
213
215
  cellRect,
214
216
  propertyKey: propertyKey as Extract<keyof M, string>
215
217
  });
@@ -1,5 +1,4 @@
1
1
  import React, { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react";
2
- import equal from "react-fast-compare"
3
2
 
4
3
  import * as Portal from "@radix-ui/react-portal";
5
4
 
@@ -19,20 +18,19 @@ import { useDraggable } from "./useDraggable";
19
18
  import { CustomFieldValidator, getYupEntitySchema } from "../../../../form/validation";
20
19
  import { useWindowSize } from "./useWindowSize";
21
20
  import { ElementResizeListener } from "./ElementResizeListener";
22
- import { ErrorView } from "../../../ErrorView";
23
21
  import { getPropertyInPath, isReadOnly, resolveCollection } from "../../../../util";
24
22
  import { Button, ClearIcon, DialogActions, IconButton, Typography } from "@firecms/ui";
25
23
  import { PropertyFieldBinding } from "../../../../form";
26
- import { useCustomizationController, useFireCMSContext } from "../../../../hooks";
24
+ import { useCustomizationController, useDataSource, useFireCMSContext } from "../../../../hooks";
27
25
  import { OnCellValueChangeParams } from "../../../common";
28
26
 
29
27
  interface PopupFormFieldProps<M extends Record<string, any>> {
30
- entity: Entity<M>;
31
28
  customFieldValidator?: CustomFieldValidator;
32
29
  path: string;
30
+ entityId: string;
33
31
  tableKey: string;
34
32
  propertyKey?: Extract<keyof M, string>;
35
- collection?: EntityCollection<M>;
33
+ collection?: EntityCollection<any>;
36
34
  cellRect?: DOMRect;
37
35
  open: boolean;
38
36
  onClose: () => void;
@@ -46,13 +44,54 @@ interface PopupFormFieldProps<M extends Record<string, any>> {
46
44
 
47
45
  export function PopupFormField<M extends Record<string, any>>(props: PopupFormFieldProps<M>) {
48
46
  if (!props.open) return null;
49
- return <PopupFormFieldInternal {...props} />;
47
+ return <PopupFormFieldLoading {...props} />;
50
48
 
51
49
  }
52
50
 
51
+ export function PopupFormFieldLoading<M extends Record<string, any>>({
52
+ tableKey,
53
+ entityId,
54
+ customFieldValidator,
55
+ propertyKey,
56
+ collection: inputCollection,
57
+ path,
58
+ cellRect,
59
+ open,
60
+ onClose,
61
+ onCellValueChange,
62
+ container
63
+ }: PopupFormFieldProps<M>) {
64
+ const dataSource = useDataSource();
65
+ const [entity, setEntity] = useState<Entity<M> | undefined>(undefined);
66
+ useEffect(() => {
67
+ if (entityId && inputCollection) {
68
+ dataSource.fetchEntity({
69
+ path,
70
+ entityId,
71
+ collection: inputCollection
72
+ }).then(setEntity);
73
+ }
74
+ }, [entityId, inputCollection]);
75
+
76
+ if (!entity) return null;
77
+ return <PopupFormFieldInternal {...{
78
+ tableKey,
79
+ entityId,
80
+ customFieldValidator,
81
+ propertyKey,
82
+ collection: inputCollection,
83
+ path,
84
+ cellRect,
85
+ open,
86
+ onClose,
87
+ onCellValueChange,
88
+ container
89
+ }} entity={entity}/>;
90
+ }
91
+
53
92
  export function PopupFormFieldInternal<M extends Record<string, any>>({
54
93
  tableKey,
55
- entity: entityProp,
94
+ entityId,
56
95
  customFieldValidator,
57
96
  propertyKey,
58
97
  collection: inputCollection,
@@ -61,10 +100,12 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
61
100
  open,
62
101
  onClose,
63
102
  onCellValueChange,
64
- container
65
- }: PopupFormFieldProps<M>) {
103
+ container,
104
+ entity
105
+ }: PopupFormFieldProps<M> & {
106
+ entity?: Entity<M>
107
+ }) {
66
108
 
67
- // const dataSource = useDataSource();
68
109
  const fireCMSContext = useFireCMSContext();
69
110
  const customizationController = useCustomizationController();
70
111
 
@@ -74,32 +115,11 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
74
115
  y: number
75
116
  }>();
76
117
 
77
- const entityId = entityProp.id;
78
- const [entity, setEntity] = useState<Entity<M> | undefined>(entityProp);
79
- // useEffect(() => {
80
- // if (entityId && inputCollection) {
81
- // return dataSource.listenEntity?.({
82
- // path,
83
- // entityId,
84
- // collection: inputCollection,
85
- // onUpdate: (e) => {
86
- // setEntity(e);
87
- // setInternalValue(e?.values);
88
- // }
89
- // });
90
- // } else {
91
- // return () => {
92
- // };
93
- // }
94
- // }, [dataSource, entityId, inputCollection, path, open]);
95
-
96
- const [internalValue, setInternalValue] = useState<EntityValues<M> | undefined>(entity?.values);
97
-
98
118
  const collection: ResolvedEntityCollection<M> | undefined = inputCollection
99
119
  ? resolveCollection<M>({
100
120
  collection: inputCollection,
101
121
  path,
102
- values: internalValue,
122
+ values: entity?.values,
103
123
  entityId,
104
124
  propertyConfigs: customizationController.propertyConfigs
105
125
  })
@@ -214,10 +234,6 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
214
234
  return Promise.resolve();
215
235
  };
216
236
 
217
- if (!entity)
218
- return <></>;
219
-
220
- // eslint-disable-next-line react-hooks/rules-of-hooks
221
237
  const formex = useCreateFormex<M>({
222
238
  initialValues: (entity?.values ?? {}) as EntityValues<M>,
223
239
  validation: (values) => {
@@ -234,26 +250,22 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
234
250
  validateOnInitialRender: true,
235
251
  onSubmit: (values, actions) => {
236
252
  saveValue(values)
237
- .then(() => onClose())
253
+ .then(() => {
254
+ formex.resetForm({
255
+ values: values
256
+ })
257
+ onClose();
258
+ })
238
259
  .finally(() => actions.setSubmitting(false));
239
260
  }
240
261
  });
241
262
 
242
- const { values, isSubmitting, setFieldValue, handleSubmit } = formex;
243
-
244
- // eslint-disable-next-line react-hooks/rules-of-hooks
245
- useEffect(() => {
246
- if (!equal(values, internalValue)) {
247
- setInternalValue(values);
248
- }
249
- }, [values]);
250
-
251
- if (!entity)
252
- return <ErrorView
253
- error={"PopupFormField misconfiguration"}/>;
254
-
255
- if (!collection)
256
- return <></>;
263
+ const {
264
+ values,
265
+ isSubmitting,
266
+ setFieldValue,
267
+ handleSubmit
268
+ } = formex;
257
269
 
258
270
  const disabled = isSubmitting;
259
271
 
@@ -267,7 +279,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
267
279
  formex
268
280
  };
269
281
 
270
- const property: ResolvedProperty<any> | undefined = propertyKey && getPropertyInPath(collection.properties, propertyKey as string);
282
+ const property: ResolvedProperty<any> | undefined = propertyKey && getPropertyInPath(collection?.properties ?? {} as ResolvedProperties, propertyKey as string);
271
283
  const fieldProps: PropertyFieldBindingProps<any, M> | undefined = propertyKey && property
272
284
  ? {
273
285
  propertyKey: propertyKey as string,
@@ -285,7 +297,7 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
285
297
  let internalForm = <>
286
298
  <div
287
299
  key={`popup_form_${tableKey}_${entityId}_${propertyKey}`}
288
- className="w-[560px] max-w-full max-h-[85vh]">
300
+ className="w-[700px] max-w-full max-h-[85vh]">
289
301
  <form
290
302
  onSubmit={handleSubmit}
291
303
  noValidate>
@@ -320,10 +332,6 @@ export function PopupFormFieldInternal<M extends Record<string, any>>({
320
332
 
321
333
  const plugins = customizationController.plugins;
322
334
  if (plugins) {
323
- // const formController: FormContext<M> = {
324
- // values,
325
- // setFieldValue
326
- // }
327
335
  plugins.forEach((plugin: FireCMSPlugin) => {
328
336
  if (plugin.form?.provider) {
329
337
  internalForm = (
@@ -665,13 +665,13 @@ export const EntityCollectionView = React.memo(
665
665
  />
666
666
 
667
667
  {popupCell && <PopupFormField
668
- key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entity?.id}`}
668
+ key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entityId}`}
669
669
  open={Boolean(popupCell)}
670
670
  onClose={onPopupClose}
671
671
  cellRect={popupCell?.cellRect}
672
672
  propertyKey={popupCell?.propertyKey}
673
673
  collection={collection}
674
- entity={popupCell.entity}
674
+ entityId={popupCell.entityId}
675
675
  tableKey={tableKey.current}
676
676
  customFieldValidator={uniqueFieldValidator}
677
677
  path={resolvedFullPath}
@@ -785,7 +785,6 @@ function EntityIdHeaderWidget({
785
785
  const [recentIds, setRecentIds] = React.useState<string[]>(getRecentIds(collection.id));
786
786
  const sideEntityController = useSideEntityController();
787
787
 
788
-
789
788
  return (
790
789
  <Tooltip title={!openPopup ? "Find by ID" : undefined} asChild={false}>
791
790
  <Popover
@@ -86,7 +86,8 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
86
86
  minimalistView,
87
87
  autoFocus,
88
88
  index,
89
- size
89
+ size,
90
+ onPropertyChange
90
91
  }: PropertyFieldBindingProps<T, M>): ReactElement<PropertyFieldBindingProps<T, M>> {
91
92
 
92
93
  const customizationController = useCustomizationController();
@@ -124,6 +125,7 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
124
125
  if (!propertyConfig) {
125
126
  console.log("INTERNAL: Could not find field config for property", {
126
127
  propertyKey,
128
+ property,
127
129
  resolvedProperty,
128
130
  fields: customizationController.propertyConfigs,
129
131
  propertyConfig
@@ -159,13 +161,14 @@ function PropertyFieldBindingInternal<T extends CMSType = CMSType, M extends Rec
159
161
  partOfArray,
160
162
  minimalistView,
161
163
  autoFocus,
162
- size
164
+ size,
165
+ onPropertyChange
163
166
  };
164
167
 
165
168
  return <FieldInternal
166
169
  Component={Component as ComponentType<FieldProps>}
167
170
  componentProps={componentProps}
168
- fieldProps={fieldProps}/>;
171
+ formexFieldProps={fieldProps}/>;
169
172
  }}
170
173
  </Field>
171
174
  );
@@ -191,26 +194,27 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
191
194
  autoFocus,
192
195
  context,
193
196
  disabled,
194
- size
197
+ size,
198
+ onPropertyChange
195
199
  },
196
- fieldProps
200
+ formexFieldProps
197
201
  }:
198
202
  {
199
203
  Component: ComponentType<FieldProps<T, any, M>>,
200
204
  componentProps: ResolvedPropertyFieldBindingProps<T, M>,
201
- fieldProps: FormexFieldProps<T, any>
205
+ formexFieldProps: FormexFieldProps<T, any>
202
206
  }) {
203
207
 
204
208
  const { plugins } = useCustomizationController();
205
209
 
206
210
  const customFieldProps: any = property.customProps;
207
- const value = fieldProps.field.value;
208
- // const initialValue = fieldProps.meta.initialValue;
209
- const error = getIn(fieldProps.form.errors, propertyKey);
210
- const touched = getIn(fieldProps.form.touched, propertyKey);
211
+ const value = formexFieldProps.field.value;
212
+ // const initialValue = formexFieldProps.meta.initialValue;
213
+ const error = getIn(formexFieldProps.form.errors, propertyKey);
214
+ const touched = getIn(formexFieldProps.form.touched, propertyKey);
211
215
 
212
216
  const showError: boolean = error &&
213
- (fieldProps.form.submitCount > 0 || property.validation?.unique) &&
217
+ (formexFieldProps.form.submitCount > 0 || property.validation?.unique) &&
214
218
  (!Array.isArray(error) || !!error.filter((e: any) => !!e).length);
215
219
 
216
220
  const WrappedComponent: ComponentType<FieldProps<T, any, M>> | null = useWrappedComponent({
@@ -223,16 +227,16 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
223
227
  });
224
228
  const UsedComponent: ComponentType<FieldProps<T>> = WrappedComponent ?? Component;
225
229
 
226
- const isSubmitting = fieldProps.form.isSubmitting;
230
+ const isSubmitting = formexFieldProps.form.isSubmitting;
227
231
 
228
232
  const setValue = useCallback((value: T | null, shouldValidate?: boolean) => {
229
- fieldProps.form.setFieldTouched(propertyKey, true, false);
230
- fieldProps.form.setFieldValue(propertyKey, value, shouldValidate);
233
+ formexFieldProps.form.setFieldTouched(propertyKey, true, false);
234
+ formexFieldProps.form.setFieldValue(propertyKey, value, shouldValidate);
231
235
  }, []);
232
236
 
233
237
  const setFieldValue = useCallback((otherPropertyKey: string, value: CMSType | null, shouldValidate?: boolean) => {
234
- fieldProps.form.setFieldTouched(propertyKey, true, false);
235
- fieldProps.form.setFieldValue(otherPropertyKey, value, shouldValidate);
238
+ formexFieldProps.form.setFieldTouched(propertyKey, true, false);
239
+ formexFieldProps.form.setFieldValue(otherPropertyKey, value, shouldValidate);
236
240
  }, []);
237
241
 
238
242
  const cmsFieldProps: FieldProps<T, CustomProps, M> = {
@@ -253,7 +257,8 @@ function FieldInternal<T extends CMSType, CustomProps, M extends Record<string,
253
257
  autoFocus: autoFocus ?? false,
254
258
  customProps: customFieldProps,
255
259
  context,
256
- size
260
+ size,
261
+ onPropertyChange
257
262
  };
258
263
 
259
264
  return (
@@ -1,4 +1,3 @@
1
- export * from "./FormikArrayContainer";
2
1
  export * from "./FieldHelperText";
3
2
  export * from "./LabelWithIcon";
4
3
  export * from "./LabelWithIconAndTooltip";