@firecms/collection_editor 3.0.1 → 3.1.0-canary.24c8270

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 (90) hide show
  1. package/dist/ConfigControllerProvider.d.ts +6 -0
  2. package/dist/api/generateCollectionApi.d.ts +71 -0
  3. package/dist/api/index.d.ts +1 -0
  4. package/dist/index.d.ts +5 -1
  5. package/dist/index.es.js +9466 -5588
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +9461 -5583
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/types/collection_editor_controller.d.ts +14 -0
  10. package/dist/types/collection_inference.d.ts +8 -2
  11. package/dist/types/config_controller.d.ts +23 -2
  12. package/dist/ui/AddKanbanColumnAction.d.ts +11 -0
  13. package/dist/ui/KanbanSetupAction.d.ts +10 -0
  14. package/dist/ui/collection_editor/AICollectionGeneratorPopover.d.ts +37 -0
  15. package/dist/ui/collection_editor/AIModifiedPathsContext.d.ts +20 -0
  16. package/dist/ui/collection_editor/CollectionDetailsForm.d.ts +2 -3
  17. package/dist/ui/collection_editor/CollectionEditorDialog.d.ts +24 -0
  18. package/dist/ui/collection_editor/CollectionEditorWelcomeView.d.ts +4 -1
  19. package/dist/ui/collection_editor/CollectionJsonImportDialog.d.ts +7 -0
  20. package/dist/ui/collection_editor/CollectionYupValidation.d.ts +9 -13
  21. package/dist/ui/collection_editor/DisplaySettingsForm.d.ts +3 -0
  22. package/dist/ui/collection_editor/EntityActionsEditTab.d.ts +2 -1
  23. package/dist/ui/collection_editor/ExtendSettingsForm.d.ts +14 -0
  24. package/dist/ui/collection_editor/GeneralSettingsForm.d.ts +7 -0
  25. package/dist/ui/collection_editor/KanbanConfigSection.d.ts +4 -0
  26. package/dist/ui/collection_editor/PropertyEditView.d.ts +6 -1
  27. package/dist/ui/collection_editor/PropertyTree.d.ts +2 -1
  28. package/dist/ui/collection_editor/SubcollectionsEditTab.d.ts +2 -1
  29. package/dist/ui/collection_editor/ViewModeSwitch.d.ts +6 -0
  30. package/dist/ui/collection_editor/properties/EnumPropertyField.d.ts +2 -1
  31. package/dist/ui/collection_editor/properties/conditions/ConditionsEditor.d.ts +10 -0
  32. package/dist/ui/collection_editor/properties/conditions/ConditionsPanel.d.ts +2 -0
  33. package/dist/ui/collection_editor/properties/conditions/EnumConditionsEditor.d.ts +6 -0
  34. package/dist/ui/collection_editor/properties/conditions/index.d.ts +6 -0
  35. package/dist/ui/collection_editor/properties/conditions/property_paths.d.ts +19 -0
  36. package/dist/useCollectionEditorPlugin.d.ts +7 -1
  37. package/dist/utils/validateCollectionJson.d.ts +22 -0
  38. package/package.json +15 -15
  39. package/src/ConfigControllerProvider.tsx +82 -47
  40. package/src/api/generateCollectionApi.ts +119 -0
  41. package/src/api/index.ts +1 -0
  42. package/src/index.ts +28 -1
  43. package/src/types/collection_editor_controller.tsx +16 -3
  44. package/src/types/collection_inference.ts +15 -2
  45. package/src/types/config_controller.tsx +27 -2
  46. package/src/ui/AddKanbanColumnAction.tsx +203 -0
  47. package/src/ui/EditorCollectionActionStart.tsx +1 -2
  48. package/src/ui/HomePageEditorCollectionAction.tsx +41 -13
  49. package/src/ui/KanbanSetupAction.tsx +38 -0
  50. package/src/ui/MissingReferenceWidget.tsx +1 -1
  51. package/src/ui/NewCollectionButton.tsx +1 -1
  52. package/src/ui/PropertyAddColumnComponent.tsx +1 -1
  53. package/src/ui/collection_editor/AICollectionGeneratorPopover.tsx +242 -0
  54. package/src/ui/collection_editor/AIModifiedPathsContext.tsx +88 -0
  55. package/src/ui/collection_editor/CollectionDetailsForm.tsx +212 -259
  56. package/src/ui/collection_editor/CollectionEditorDialog.tsx +237 -169
  57. package/src/ui/collection_editor/CollectionEditorWelcomeView.tsx +133 -67
  58. package/src/ui/collection_editor/CollectionJsonImportDialog.tsx +171 -0
  59. package/src/ui/collection_editor/CollectionPropertiesEditorForm.tsx +190 -91
  60. package/src/ui/collection_editor/DisplaySettingsForm.tsx +333 -0
  61. package/src/ui/collection_editor/EntityActionsEditTab.tsx +106 -96
  62. package/src/ui/collection_editor/EntityActionsSelectDialog.tsx +6 -7
  63. package/src/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +1 -3
  64. package/src/ui/collection_editor/EnumForm.tsx +147 -100
  65. package/src/ui/collection_editor/ExtendSettingsForm.tsx +93 -0
  66. package/src/ui/collection_editor/GeneralSettingsForm.tsx +337 -0
  67. package/src/ui/collection_editor/GetCodeDialog.tsx +57 -36
  68. package/src/ui/collection_editor/KanbanConfigSection.tsx +207 -0
  69. package/src/ui/collection_editor/LayoutModeSwitch.tsx +22 -41
  70. package/src/ui/collection_editor/PropertyEditView.tsx +206 -142
  71. package/src/ui/collection_editor/PropertyFieldPreview.tsx +1 -1
  72. package/src/ui/collection_editor/PropertyTree.tsx +130 -58
  73. package/src/ui/collection_editor/SubcollectionsEditTab.tsx +171 -162
  74. package/src/ui/collection_editor/UnsavedChangesDialog.tsx +0 -2
  75. package/src/ui/collection_editor/ViewModeSwitch.tsx +41 -0
  76. package/src/ui/collection_editor/properties/BlockPropertyField.tsx +0 -2
  77. package/src/ui/collection_editor/properties/BooleanPropertyField.tsx +1 -0
  78. package/src/ui/collection_editor/properties/DateTimePropertyField.tsx +117 -35
  79. package/src/ui/collection_editor/properties/EnumPropertyField.tsx +28 -21
  80. package/src/ui/collection_editor/properties/MapPropertyField.tsx +0 -2
  81. package/src/ui/collection_editor/properties/MarkdownPropertyField.tsx +115 -39
  82. package/src/ui/collection_editor/properties/StoragePropertyField.tsx +1 -1
  83. package/src/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +861 -0
  84. package/src/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +28 -0
  85. package/src/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +599 -0
  86. package/src/ui/collection_editor/properties/conditions/index.ts +6 -0
  87. package/src/ui/collection_editor/properties/conditions/property_paths.ts +92 -0
  88. package/src/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -1
  89. package/src/useCollectionEditorPlugin.tsx +32 -17
  90. package/src/utils/validateCollectionJson.ts +380 -0
@@ -3,12 +3,24 @@ import equal from "react-fast-compare"
3
3
 
4
4
  import {
5
5
  AdditionalFieldDelegate,
6
+ AIModifiedIndicator,
6
7
  CMSType,
7
8
  isPropertyBuilder,
8
9
  PropertiesOrBuilders,
9
10
  PropertyOrBuilder
10
11
  } from "@firecms/core";
11
- import { AutorenewIcon, defaultBorderMixin, DragHandleIcon, IconButton, RemoveIcon, Tooltip } from "@firecms/ui";
12
+ import {
13
+ FindInPageIcon,
14
+ defaultBorderMixin,
15
+ DeleteIcon,
16
+ IconButton,
17
+ Menu,
18
+ MenuItem,
19
+ MoreVertIcon,
20
+ Tooltip,
21
+ VerticalAlignBottomIcon,
22
+ VerticalAlignTopIcon
23
+ } from "@firecms/ui";
12
24
  import { NonEditablePropertyPreview, PropertyFieldPreview } from "./PropertyFieldPreview";
13
25
  import {
14
26
  closestCenter,
@@ -30,24 +42,25 @@ import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
30
42
  import { CSS } from "@dnd-kit/utilities";
31
43
  import { getFullId, getFullIdPath } from "./util";
32
44
  import { editableProperty } from "../../utils/entities";
45
+ import { useAIModifiedPaths } from "./AIModifiedPathsContext";
33
46
 
34
47
  export const PropertyTree = React.memo(
35
48
  function PropertyTree<M extends {
36
49
  [Key: string]: CMSType
37
50
  }>({
38
- namespace,
39
- selectedPropertyKey,
40
- onPropertyClick,
41
- properties,
42
- propertiesOrder: propertiesOrderProp,
43
- additionalFields,
44
- errors,
45
- onPropertyMove,
46
- onPropertyRemove,
47
- className,
48
- inferredPropertyKeys,
49
- collectionEditable
50
- }: {
51
+ namespace,
52
+ selectedPropertyKey,
53
+ onPropertyClick,
54
+ properties,
55
+ propertiesOrder: propertiesOrderProp,
56
+ additionalFields,
57
+ errors,
58
+ onPropertyMove,
59
+ onPropertyRemove,
60
+ className,
61
+ inferredPropertyKeys,
62
+ collectionEditable
63
+ }: {
51
64
  namespace?: string;
52
65
  selectedPropertyKey?: string;
53
66
  onPropertyClick?: (propertyKey: string, namespace?: string) => void;
@@ -62,7 +75,15 @@ export const PropertyTree = React.memo(
62
75
  collectionEditable: boolean;
63
76
  }) {
64
77
 
65
- const propertiesOrder = propertiesOrderProp ?? Object.keys(properties);
78
+ // Filter propertiesOrder to only include top-level keys (no dots) that exist in properties
79
+ // Nested keys like "data.mode" are for column ordering in the table, not for the property editor
80
+ const propertyKeys = Object.keys(properties);
81
+ const filteredOrder = (propertiesOrderProp ?? propertyKeys)
82
+ .filter(key => !key.includes(".") && properties[key as keyof typeof properties]);
83
+
84
+ // Ensure all properties are included (append any missing ones)
85
+ const missingKeys = propertyKeys.filter(key => !filteredOrder.includes(key));
86
+ const propertiesOrder = [...filteredOrder, ...missingKeys];
66
87
 
67
88
  const sensors = useSensors(
68
89
  useSensor(PointerSensor, {
@@ -144,6 +165,7 @@ export const PropertyTree = React.memo(
144
165
  additionalField={additionalField}
145
166
  errors={errors}
146
167
  namespace={namespace}
168
+ propertiesOrder={propertiesOrder}
147
169
  inferredPropertyKeys={inferredPropertyKeys}
148
170
  onPropertyMove={onPropertyMove}
149
171
  onPropertyRemove={onPropertyRemove}
@@ -162,19 +184,20 @@ export const PropertyTree = React.memo(
162
184
  );
163
185
 
164
186
  export function PropertyTreeEntry({
165
- id,
166
- propertyKey,
167
- namespace,
168
- propertyOrBuilder,
169
- additionalField,
170
- selectedPropertyKey,
171
- errors,
172
- onPropertyClick,
173
- onPropertyMove,
174
- onPropertyRemove,
175
- inferredPropertyKeys,
176
- collectionEditable
177
- }: {
187
+ id,
188
+ propertyKey,
189
+ namespace,
190
+ propertyOrBuilder,
191
+ additionalField,
192
+ selectedPropertyKey,
193
+ errors,
194
+ propertiesOrder,
195
+ onPropertyClick,
196
+ onPropertyMove,
197
+ onPropertyRemove,
198
+ inferredPropertyKeys,
199
+ collectionEditable
200
+ }: {
178
201
  id: string;
179
202
  propertyKey: string;
180
203
  namespace?: string;
@@ -182,6 +205,7 @@ export function PropertyTreeEntry({
182
205
  additionalField?: AdditionalFieldDelegate<any>;
183
206
  selectedPropertyKey?: string;
184
207
  errors: Record<string, any>;
208
+ propertiesOrder: string[];
185
209
  onPropertyClick?: (propertyKey: string, namespace?: string) => void;
186
210
  onPropertyMove?: (propertiesOrder: string[], namespace?: string) => void;
187
211
  onPropertyRemove?: (propertyKey: string, namespace?: string) => void;
@@ -226,6 +250,7 @@ export function PropertyTreeEntry({
226
250
  onPropertyClick={onPropertyClick}
227
251
  onPropertyMove={onPropertyMove}
228
252
  onPropertyRemove={onPropertyRemove}
253
+ inferredPropertyKeys={inferredPropertyKeys}
229
254
  collectionEditable={collectionEditable}
230
255
  />
231
256
  }
@@ -234,11 +259,17 @@ export function PropertyTreeEntry({
234
259
  const selected = selectedPropertyKey === fullId;
235
260
  const editable = propertyOrBuilder && ((collectionEditable && !isPropertyBuilder(propertyOrBuilder)) || editableProperty(propertyOrBuilder));
236
261
 
262
+ // Check if this property was AI-modified
263
+ const aiModifiedPaths = useAIModifiedPaths();
264
+ const isAIModified = aiModifiedPaths?.isPathModified(`properties.${propertyKey}`) ?? false;
265
+
237
266
  return (
238
267
  <div
239
268
  ref={setNodeRef}
240
269
  style={style}
241
- className="relative -ml-8"
270
+ className="relative -ml-8 cursor-grab"
271
+ {...attributes}
272
+ {...listeners}
242
273
  >
243
274
  <div className="relative">
244
275
  {subtree && <div
@@ -247,7 +278,7 @@ export function PropertyTreeEntry({
247
278
  left: "32px",
248
279
  top: "64px",
249
280
  bottom: "16px"
250
- }}/>}
281
+ }} />}
251
282
 
252
283
  <div>
253
284
  {!isPropertyBuilder(propertyOrBuilder) && !additionalField && editable
@@ -256,38 +287,79 @@ export function PropertyTreeEntry({
256
287
  onClick={onPropertyClick ? () => onPropertyClick(propertyKey, namespace) : undefined}
257
288
  includeName={true}
258
289
  selected={selected}
259
- hasError={hasError}/>
290
+ hasError={hasError} />
260
291
  : <NonEditablePropertyPreview name={propertyKey}
261
- property={propertyOrBuilder}
262
- onClick={onPropertyClick ? () => onPropertyClick(propertyKey, namespace) : undefined}
263
- selected={selected}/>}
292
+ property={propertyOrBuilder}
293
+ onClick={onPropertyClick ? () => onPropertyClick(propertyKey, namespace) : undefined}
294
+ selected={selected} />}
264
295
  </div>
265
296
 
266
- <div className="absolute top-2 right-2 flex flex-row">
267
- {isPropertyInferred && <Tooltip title={"Inferred property"}>
268
- <AutorenewIcon size="small" className={"p-2"}/>
269
- </Tooltip>}
270
-
271
- {onPropertyRemove && !isPropertyInferred && <Tooltip title={"Remove"}
272
- asChild={true}>
273
- <IconButton size="small"
274
- color="inherit"
275
- onClick={() => onPropertyRemove(propertyKey, namespace)}>
276
- <RemoveIcon size={"small"}/>
277
- </IconButton>
278
- </Tooltip>}
279
-
280
- {onPropertyMove && <Tooltip title={"Move"}
281
- asChild={true}>
282
- <IconButton
283
- component={"span"}
284
- size="small"
285
- {...attributes}
286
- {...listeners}
297
+ <div className="absolute top-3 right-3 flex flex-row items-center gap-1">
298
+ {isAIModified && <AIModifiedIndicator />}
299
+ {isPropertyInferred && <>
300
+ <Tooltip title={"Inferred property"} asChild={true}>
301
+ <IconButton size="smallest" disabled>
302
+ <FindInPageIcon size="smallest" />
303
+ </IconButton>
304
+ </Tooltip>
305
+ {onPropertyRemove && <Tooltip title={"Remove inferred property"}
306
+ asChild={true}>
307
+ <IconButton size="smallest"
308
+ color="inherit"
309
+ onClick={(e) => {
310
+ e.stopPropagation();
311
+ onPropertyRemove(propertyKey, namespace);
312
+ }}>
313
+ <DeleteIcon size={"smallest"} />
314
+ </IconButton>
315
+ </Tooltip>}
316
+ </>}
317
+
318
+ <Menu
319
+ trigger={
320
+ <IconButton
321
+ size="smallest"
322
+ >
323
+ <MoreVertIcon size={"smallest"} />
324
+ </IconButton>
325
+ }
326
+ >
327
+ <MenuItem
328
+ dense
329
+ onClick={() => {
330
+ const currentIndex = propertiesOrder.indexOf(propertyKey);
331
+ if (currentIndex > 0) {
332
+ const newOrder = propertiesOrder.filter(k => k !== propertyKey);
333
+ newOrder.unshift(propertyKey);
334
+ onPropertyMove?.(newOrder, namespace);
335
+ }
336
+ }}
337
+ >
338
+ <VerticalAlignTopIcon size="smallest" />
339
+ Move to top
340
+ </MenuItem>
341
+ <MenuItem
342
+ dense
343
+ onClick={() => {
344
+ const currentIndex = propertiesOrder.indexOf(propertyKey);
345
+ if (currentIndex < propertiesOrder.length - 1) {
346
+ const newOrder = propertiesOrder.filter(k => k !== propertyKey);
347
+ newOrder.push(propertyKey);
348
+ onPropertyMove?.(newOrder, namespace);
349
+ }
350
+ }}
351
+ >
352
+ <VerticalAlignBottomIcon size="smallest" />
353
+ Move to bottom
354
+ </MenuItem>
355
+ <MenuItem
356
+ dense
357
+ onClick={() => onPropertyRemove?.(propertyKey, namespace)}
287
358
  >
288
- <DragHandleIcon size={"small"}/>
289
- </IconButton>
290
- </Tooltip>}
359
+ <DeleteIcon size="smallest" />
360
+ Delete
361
+ </MenuItem>
362
+ </Menu>
291
363
 
292
364
  </div>
293
365