@webiny/app-headless-cms 6.0.0-rc.2 → 6.0.0-rc.3

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 (169) hide show
  1. package/admin/components/ContentEntries/Header/ButtonRefresh/ButtonRefresh.d.ts +2 -0
  2. package/admin/components/ContentEntries/Header/ButtonRefresh/ButtonRefresh.js +18 -0
  3. package/admin/components/ContentEntries/Header/ButtonRefresh/ButtonRefresh.js.map +1 -0
  4. package/admin/components/ContentEntries/Header/ButtonRefresh/index.d.ts +1 -0
  5. package/admin/components/ContentEntries/Header/ButtonRefresh/index.js +3 -0
  6. package/admin/components/ContentEntries/Header/ButtonRefresh/index.js.map +1 -0
  7. package/admin/components/ContentEntries/Header/Header.js +2 -1
  8. package/admin/components/ContentEntries/Header/Header.js.map +1 -1
  9. package/admin/components/ContentEntries/SidebarContent/SidebarContent.js +1 -1
  10. package/admin/components/ContentEntries/SidebarContent/SidebarContent.js.map +1 -1
  11. package/admin/components/ContentEntries/SidebarHeader/SidebarHeader.js +1 -1
  12. package/admin/components/ContentEntries/SidebarHeader/SidebarHeader.js.map +1 -1
  13. package/admin/components/ContentModelEditor/ContentModelEditor.js +1 -6
  14. package/admin/components/ContentModelEditor/ContentModelEditor.js.map +1 -1
  15. package/admin/components/ContentModelEditor/ContentModelEditorProvider.d.ts +2 -0
  16. package/admin/components/ContentModelEditor/ContentModelEditorProvider.js +14 -2
  17. package/admin/components/ContentModelEditor/ContentModelEditorProvider.js.map +1 -1
  18. package/admin/components/ContentModelEditor/FieldsSidebar.js +51 -2
  19. package/admin/components/ContentModelEditor/FieldsSidebar.js.map +1 -1
  20. package/admin/components/Droppable.d.ts +1 -1
  21. package/admin/components/Droppable.js.map +1 -1
  22. package/admin/components/FieldEditor/EditFieldDialog/AppearanceTab.js +3 -3
  23. package/admin/components/FieldEditor/EditFieldDialog/AppearanceTab.js.map +1 -1
  24. package/admin/components/FieldEditor/EditFieldDialog/FieldSettingsTabs.d.ts +10 -0
  25. package/admin/components/FieldEditor/EditFieldDialog/FieldSettingsTabs.js +69 -0
  26. package/admin/components/FieldEditor/EditFieldDialog/FieldSettingsTabs.js.map +1 -0
  27. package/admin/components/FieldEditor/EditFieldDialog/GeneralTab.js +27 -9
  28. package/admin/components/FieldEditor/EditFieldDialog/GeneralTab.js.map +1 -1
  29. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/CannotUsePermissions.d.ts +2 -0
  30. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/CannotUsePermissions.js +14 -0
  31. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/CannotUsePermissions.js.map +1 -0
  32. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/FieldPermissionsSelection.d.ts +15 -0
  33. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/FieldPermissionsSelection.js +131 -0
  34. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/FieldPermissionsSelection.js.map +1 -0
  35. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/PermissionsTab.d.ts +4 -0
  36. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/PermissionsTab.js +74 -0
  37. package/admin/components/FieldEditor/EditFieldDialog/PermissionsTab/PermissionsTab.js.map +1 -0
  38. package/admin/components/FieldEditor/EditFieldDialog/RulesTab/RulesTab.d.ts +13 -0
  39. package/admin/components/FieldEditor/EditFieldDialog/RulesTab/RulesTab.js +203 -0
  40. package/admin/components/FieldEditor/EditFieldDialog/RulesTab/RulesTab.js.map +1 -0
  41. package/admin/components/FieldEditor/EditFieldDialog/RulesTab/index.d.ts +1 -0
  42. package/admin/components/FieldEditor/EditFieldDialog/RulesTab/index.js +3 -0
  43. package/admin/components/FieldEditor/EditFieldDialog/RulesTab/index.js.map +1 -0
  44. package/admin/components/FieldEditor/EditFieldDialog.js +13 -56
  45. package/admin/components/FieldEditor/EditFieldDialog.js.map +1 -1
  46. package/admin/components/FieldEditor/EditFieldDialogContainer.d.ts +12 -0
  47. package/admin/components/FieldEditor/EditFieldDialogContainer.js +40 -0
  48. package/admin/components/FieldEditor/EditFieldDialogContainer.js.map +1 -0
  49. package/admin/components/FieldEditor/EditFieldDrawerContainer.d.ts +12 -0
  50. package/admin/components/FieldEditor/EditFieldDrawerContainer.js +40 -0
  51. package/admin/components/FieldEditor/EditFieldDrawerContainer.js.map +1 -0
  52. package/admin/components/FieldEditor/FieldEditor.js +148 -88
  53. package/admin/components/FieldEditor/FieldEditor.js.map +1 -1
  54. package/admin/components/FieldEditor/FieldEditorContext.d.ts +33 -3
  55. package/admin/components/FieldEditor/FieldEditorContext.js +225 -6
  56. package/admin/components/FieldEditor/FieldEditorContext.js.map +1 -1
  57. package/admin/components/FieldEditor/LayoutCell.d.ts +9 -0
  58. package/admin/components/FieldEditor/LayoutCell.js +33 -0
  59. package/admin/components/FieldEditor/LayoutCell.js.map +1 -0
  60. package/admin/components/FieldEditor/utils/deleteField.js +12 -4
  61. package/admin/components/FieldEditor/utils/deleteField.js.map +1 -1
  62. package/admin/components/FieldEditor/utils/getFieldPosition.js +6 -1
  63. package/admin/components/FieldEditor/utils/getFieldPosition.js.map +1 -1
  64. package/admin/graphql/contentModels.d.ts +2 -2
  65. package/admin/graphql/contentModels.js +7 -0
  66. package/admin/graphql/contentModels.js.map +1 -1
  67. package/admin/hooks/useModelFieldGraphqlContext.d.ts +1 -0
  68. package/admin/plugins/fieldRenderers/DynamicSection.d.ts +2 -1
  69. package/admin/plugins/fieldRenderers/DynamicSection.js +3 -1
  70. package/admin/plugins/fieldRenderers/DynamicSection.js.map +1 -1
  71. package/admin/plugins/fieldRenderers/boolean/booleanSwitch.js +7 -1
  72. package/admin/plugins/fieldRenderers/boolean/booleanSwitch.js.map +1 -1
  73. package/admin/plugins/fieldRenderers/checkboxes.js +7 -1
  74. package/admin/plugins/fieldRenderers/checkboxes.js.map +1 -1
  75. package/admin/plugins/fieldRenderers/dateTime/Input.js +9 -2
  76. package/admin/plugins/fieldRenderers/dateTime/Input.js.map +1 -1
  77. package/admin/plugins/fieldRenderers/dateTime/Select.js +7 -0
  78. package/admin/plugins/fieldRenderers/dateTime/Select.js.map +1 -1
  79. package/admin/plugins/fieldRenderers/dynamicZone/MultiValueDynamicZone.d.ts +1 -0
  80. package/admin/plugins/fieldRenderers/dynamicZone/MultiValueDynamicZone.js +9 -5
  81. package/admin/plugins/fieldRenderers/dynamicZone/MultiValueDynamicZone.js.map +1 -1
  82. package/admin/plugins/fieldRenderers/dynamicZone/SingleValueDynamicZone.d.ts +2 -1
  83. package/admin/plugins/fieldRenderers/dynamicZone/SingleValueDynamicZone.js +18 -10
  84. package/admin/plugins/fieldRenderers/dynamicZone/SingleValueDynamicZone.js.map +1 -1
  85. package/admin/plugins/fieldRenderers/lexicalText/lexicalTextInput.js +13 -4
  86. package/admin/plugins/fieldRenderers/lexicalText/lexicalTextInput.js.map +1 -1
  87. package/admin/plugins/fieldRenderers/lexicalText/lexicalTextInputs.js +10 -4
  88. package/admin/plugins/fieldRenderers/lexicalText/lexicalTextInputs.js.map +1 -1
  89. package/admin/plugins/fieldRenderers/longText/longText.js +7 -1
  90. package/admin/plugins/fieldRenderers/longText/longText.js.map +1 -1
  91. package/admin/plugins/fieldRenderers/longText/longTexts.js +12 -3
  92. package/admin/plugins/fieldRenderers/longText/longTexts.js.map +1 -1
  93. package/admin/plugins/fieldRenderers/number/numberInput.js +7 -1
  94. package/admin/plugins/fieldRenderers/number/numberInput.js.map +1 -1
  95. package/admin/plugins/fieldRenderers/number/numberInputs.js +11 -3
  96. package/admin/plugins/fieldRenderers/number/numberInputs.js.map +1 -1
  97. package/admin/plugins/fieldRenderers/object/FieldSettings.d.ts +2 -1
  98. package/admin/plugins/fieldRenderers/object/MultiValueContainer.js +5 -0
  99. package/admin/plugins/fieldRenderers/object/MultiValueContainer.js.map +1 -1
  100. package/admin/plugins/fieldRenderers/object/MultiValueItemContainer.d.ts +1 -0
  101. package/admin/plugins/fieldRenderers/object/MultiValueItemContainer.js +3 -2
  102. package/admin/plugins/fieldRenderers/object/MultiValueItemContainer.js.map +1 -1
  103. package/admin/plugins/fieldRenderers/radioButtons.js +7 -1
  104. package/admin/plugins/fieldRenderers/radioButtons.js.map +1 -1
  105. package/admin/plugins/fieldRenderers/ref/advanced/components/AdvancedMultipleReferenceField.js +15 -7
  106. package/admin/plugins/fieldRenderers/ref/advanced/components/AdvancedMultipleReferenceField.js.map +1 -1
  107. package/admin/plugins/fieldRenderers/ref/advanced/components/AdvancedSingleReferenceField.js +14 -7
  108. package/admin/plugins/fieldRenderers/ref/advanced/components/AdvancedSingleReferenceField.js.map +1 -1
  109. package/admin/plugins/fieldRenderers/ref/advanced/components/Entry.d.ts +3 -1
  110. package/admin/plugins/fieldRenderers/ref/advanced/components/Entry.js +7 -6
  111. package/admin/plugins/fieldRenderers/ref/advanced/components/Entry.js.map +1 -1
  112. package/admin/plugins/fieldRenderers/ref/components/ContentEntriesAutocomplete.d.ts +1 -1
  113. package/admin/plugins/fieldRenderers/ref/components/ContentEntriesAutocomplete.js +9 -3
  114. package/admin/plugins/fieldRenderers/ref/components/ContentEntriesAutocomplete.js.map +1 -1
  115. package/admin/plugins/fieldRenderers/ref/components/ContentEntriesMultiAutoComplete.d.ts +1 -1
  116. package/admin/plugins/fieldRenderers/ref/components/ContentEntriesMultiAutoComplete.js +9 -3
  117. package/admin/plugins/fieldRenderers/ref/components/ContentEntriesMultiAutoComplete.js.map +1 -1
  118. package/admin/plugins/fieldRenderers/ref/simple/components/SimpleMultipleRenderer.js +7 -1
  119. package/admin/plugins/fieldRenderers/ref/simple/components/SimpleMultipleRenderer.js.map +1 -1
  120. package/admin/plugins/fieldRenderers/ref/simple/components/SimpleSingleRenderer.js +7 -1
  121. package/admin/plugins/fieldRenderers/ref/simple/components/SimpleSingleRenderer.js.map +1 -1
  122. package/admin/plugins/fieldRenderers/select.js +7 -1
  123. package/admin/plugins/fieldRenderers/select.js.map +1 -1
  124. package/admin/plugins/fieldRenderers/text/tags.js +7 -1
  125. package/admin/plugins/fieldRenderers/text/tags.js.map +1 -1
  126. package/admin/plugins/fieldRenderers/text/textInput.js +7 -1
  127. package/admin/plugins/fieldRenderers/text/textInput.js.map +1 -1
  128. package/admin/plugins/fieldRenderers/text/textInputs.js +12 -3
  129. package/admin/plugins/fieldRenderers/text/textInputs.js.map +1 -1
  130. package/admin/plugins/fields/ui/TabsLayoutEditor.d.ts +9 -0
  131. package/admin/plugins/fields/ui/TabsLayoutEditor.js +470 -0
  132. package/admin/plugins/fields/ui/TabsLayoutEditor.js.map +1 -0
  133. package/admin/plugins/fields/ui/alert.d.ts +2 -2
  134. package/admin/plugins/fields/ui/alert.js +144 -17
  135. package/admin/plugins/fields/ui/alert.js.map +1 -1
  136. package/admin/plugins/fields/ui/index.d.ts +1 -0
  137. package/admin/plugins/fields/ui/index.js +1 -0
  138. package/admin/plugins/fields/ui/index.js.map +1 -1
  139. package/admin/plugins/fields/ui/separator.d.ts +2 -2
  140. package/admin/plugins/fields/ui/separator.js +131 -17
  141. package/admin/plugins/fields/ui/separator.js.map +1 -1
  142. package/admin/plugins/fields/ui/tabs.d.ts +2 -0
  143. package/admin/plugins/fields/ui/tabs.js +89 -0
  144. package/admin/plugins/fields/ui/tabs.js.map +1 -0
  145. package/admin/plugins/index.d.ts +1 -0
  146. package/admin/views/contentEntries/hooks/useContentEntriesList.d.ts +1 -0
  147. package/admin/views/contentEntries/hooks/useContentEntriesList.js +4 -2
  148. package/admin/views/contentEntries/hooks/useContentEntriesList.js.map +1 -1
  149. package/admin/views/contentModels/importing/graphql.d.ts +2 -2
  150. package/admin/views/contentModels/importing/graphql.js.map +1 -1
  151. package/allPlugins.d.ts +2 -1
  152. package/allPlugins.js +2 -3
  153. package/allPlugins.js.map +1 -1
  154. package/exports/admin/cms/model.d.ts +1 -0
  155. package/exports/admin/cms/model.js +3 -0
  156. package/exports/admin/cms/model.js.map +1 -0
  157. package/package.json +23 -23
  158. package/types.d.ts +1 -0
  159. package/types.js +5 -1
  160. package/types.js.map +1 -1
  161. package/admin/plugins/fieldRenderers/ui/alert.d.ts +0 -2
  162. package/admin/plugins/fieldRenderers/ui/alert.js +0 -32
  163. package/admin/plugins/fieldRenderers/ui/alert.js.map +0 -1
  164. package/admin/plugins/fieldRenderers/ui/index.d.ts +0 -2
  165. package/admin/plugins/fieldRenderers/ui/index.js +0 -4
  166. package/admin/plugins/fieldRenderers/ui/index.js.map +0 -1
  167. package/admin/plugins/fieldRenderers/ui/separator.d.ts +0 -2
  168. package/admin/plugins/fieldRenderers/ui/separator.js +0 -31
  169. package/admin/plugins/fieldRenderers/ui/separator.js.map +0 -1
@@ -1,6 +1,7 @@
1
1
  import React, { useCallback, useState } from "react";
2
2
  import dot from "dot-prop-immutable";
3
3
  import useDeepCompareEffect from "use-deep-compare-effect";
4
+ import { isLayoutDescriptor } from "@webiny/app-headless-cms-common/types/model.js";
4
5
  import { plugins } from "@webiny/plugins";
5
6
  import * as utils from "./utils/index.js";
6
7
  import { useModelFieldEditor } from "./useModelFieldEditor.js";
@@ -39,9 +40,11 @@ export const FieldEditorProvider = ({
39
40
  }) => {
40
41
  // We need to determine depth of this provider so we can render drop zones with correct z-indexes.
41
42
  let depth = 0;
43
+ let parentEditorContext;
42
44
  try {
43
45
  const editor = useModelFieldEditor();
44
46
  depth = editor.depth + 1;
47
+ parentEditorContext = editor;
45
48
  } catch {
46
49
  // There's no parent provider, so this is the top-level one.
47
50
  }
@@ -97,6 +100,37 @@ export const FieldEditorProvider = ({
97
100
  return onDropTarget;
98
101
  }
99
102
 
103
+ // Handle new layout field drops (separator, alert, tabs, etc.)
104
+ if (type === "newLayoutField") {
105
+ const plugin = getLayoutFieldPlugin(source.layoutFieldType || "");
106
+ if (!plugin) {
107
+ return null;
108
+ }
109
+ const descriptor = plugin.field.createDescriptor();
110
+ insertLayoutCell(descriptor, dropTarget);
111
+ return null;
112
+ }
113
+
114
+ // Handle moving an existing layout field to a new position
115
+ if (type === "layoutField") {
116
+ if (source.descriptor) {
117
+ if (parentId !== source.parent) {
118
+ // Cross-parent: insert a copy of the descriptor into this context
119
+ insertLayoutCell(source.descriptor, dropTarget);
120
+ // Also add any fields carried by this descriptor (e.g. fields inside tabs)
121
+ if (fields.length > 0) {
122
+ for (const f of fields) {
123
+ addField(f);
124
+ }
125
+ }
126
+ } else {
127
+ // Same parent: move within this context
128
+ moveLayoutCell(source.descriptor.id, dropTarget);
129
+ }
130
+ }
131
+ return onDropTarget;
132
+ }
133
+
100
134
  // If source pos is set, we are moving an existing field.
101
135
  if (pos) {
102
136
  if (!field) {
@@ -142,27 +176,35 @@ export const FieldEditorProvider = ({
142
176
  const onEndDrag = ({
143
177
  type,
144
178
  field,
145
- fields
179
+ fields,
180
+ descriptor
146
181
  }, monitor) => {
147
182
  if (!monitor.didDrop()) {
148
183
  return;
149
184
  }
150
185
 
151
- // Check if we dropped outside of the source fieldset, and if yes, remove the field from the original parent.
186
+ // Check if we dropped outside of the source fieldset, and if yes, remove the item from the original parent.
152
187
  const monitorResult = monitor.getDropResult();
153
188
  const parentId = parent ? parent.fieldId : null;
154
189
  if (monitorResult?.dropTarget === parentId) {
155
190
  return;
156
191
  }
192
+ if (type === "layoutField" && descriptor?.id) {
193
+ deleteLayoutCell(descriptor.id);
194
+ return;
195
+ }
157
196
  const removeFields = type === "row" ? fields || [] : field ? [field] : [];
158
197
  removeFields.forEach(field => deleteField(field));
159
198
  };
160
199
  const getFieldsInLayout = () => {
161
- // Replace every field ID with actual field object.
200
+ // Replace every field ID with actual field object, pass through layout descriptors.
162
201
  return state.layout.filter(arr => arr.length).map(row => {
163
- return row.map(id => {
202
+ return row.map(cell => {
203
+ if (isLayoutDescriptor(cell)) {
204
+ return cell;
205
+ }
164
206
  return getField({
165
- id
207
+ id: cell
166
208
  });
167
209
  }).filter(Boolean);
168
210
  }).filter(row => {
@@ -205,7 +247,7 @@ export const FieldEditorProvider = ({
205
247
  position
206
248
  }) => {
207
249
  if (!field.id) {
208
- field.id = generateFieldId(layout.flat());
250
+ field.id = generateFieldId(layout.flat().filter(c => typeof c === "string"));
209
251
  }
210
252
  if (!field.type) {
211
253
  throw new Error(`Field "type" missing.`);
@@ -283,6 +325,175 @@ export const FieldEditorProvider = ({
283
325
  });
284
326
  });
285
327
  };
328
+
329
+ /**
330
+ * Add a field to the fields array without placing it in the layout.
331
+ * Used by tabs to hoist fields to the parent context.
332
+ */
333
+ const addField = field => {
334
+ setState(prev => {
335
+ // Don't add if already exists
336
+ if (prev.fields.some(f => f.id === field.id)) {
337
+ return prev;
338
+ }
339
+ return {
340
+ ...prev,
341
+ fields: [...prev.fields, field]
342
+ };
343
+ });
344
+ };
345
+
346
+ /**
347
+ * Remove a field from the fields array by ID.
348
+ * Used by tabs to un-hoist fields from the parent context.
349
+ */
350
+ const removeField = fieldId => {
351
+ setState(prev => ({
352
+ ...prev,
353
+ fields: prev.fields.filter(f => f.id !== fieldId)
354
+ }));
355
+ };
356
+
357
+ /**
358
+ * Return layout field plugin by type.
359
+ */
360
+ const getLayoutFieldPlugin = type => {
361
+ return plugins.byType("cms-editor-layout-field-type").find(plugin => plugin.field.type === type);
362
+ };
363
+
364
+ /**
365
+ * Insert a layout descriptor into the layout at the given position.
366
+ */
367
+ const insertLayoutCell = (descriptor, position) => {
368
+ // Auto-assign a unique ID to the descriptor.
369
+ const cell = {
370
+ ...descriptor,
371
+ id: generateAlphaNumericLowerCaseId(8)
372
+ };
373
+ setState(prev => {
374
+ const newLayout = [...prev.layout.map(row => [...row])];
375
+ const {
376
+ row
377
+ } = position;
378
+
379
+ // Layout fields always occupy a full row.
380
+ newLayout.splice(row, 0, [cell]);
381
+ return {
382
+ ...prev,
383
+ layout: newLayout.filter(r => r.length > 0)
384
+ };
385
+ });
386
+ };
387
+
388
+ /**
389
+ * Update a layout descriptor found by its ID.
390
+ */
391
+ const updateLayoutCell = (descriptorId, descriptor) => {
392
+ setState(prev => {
393
+ const newLayout = prev.layout.map(row => row.map(cell => {
394
+ if (isLayoutDescriptor(cell) && cell.id === descriptorId) {
395
+ return {
396
+ ...descriptor,
397
+ id: descriptorId
398
+ };
399
+ }
400
+ return cell;
401
+ }));
402
+ return {
403
+ ...prev,
404
+ layout: newLayout
405
+ };
406
+ });
407
+ };
408
+
409
+ /**
410
+ * Delete a layout descriptor found by its ID.
411
+ * If it's a tabs descriptor, also remove all hoisted fields from the fields array.
412
+ */
413
+ const deleteLayoutCell = descriptorId => {
414
+ setState(prev => {
415
+ let fields = prev.fields;
416
+
417
+ // Find the descriptor to check if it's tabs (need to clean up hoisted fields)
418
+ for (const row of prev.layout) {
419
+ for (const cell of row) {
420
+ if (isLayoutDescriptor(cell) && cell.id === descriptorId && cell.type === "tabs") {
421
+ const tabsDescriptor = cell;
422
+ const fieldIdsInTabs = new Set();
423
+ tabsDescriptor.tabs.forEach(tab => {
424
+ tab.layout.forEach(r => {
425
+ r.forEach(c => {
426
+ if (typeof c === "string") {
427
+ fieldIdsInTabs.add(c);
428
+ }
429
+ });
430
+ });
431
+ });
432
+ if (fieldIdsInTabs.size > 0) {
433
+ fields = fields.filter(f => !fieldIdsInTabs.has(f.id));
434
+ }
435
+ }
436
+ }
437
+ }
438
+ const newLayout = prev.layout.map(row => row.filter(cell => !(isLayoutDescriptor(cell) && cell.id === descriptorId)));
439
+ return {
440
+ ...prev,
441
+ fields,
442
+ layout: newLayout.filter(r => r.length > 0)
443
+ };
444
+ });
445
+ };
446
+
447
+ /**
448
+ * Move a layout descriptor (found by its ID) to a new position.
449
+ */
450
+ const moveLayoutCell = (descriptorId, position) => {
451
+ setState(prev => {
452
+ // Find the descriptor by ID.
453
+ let descriptor;
454
+ let sourceRow = -1;
455
+ for (let ri = 0; ri < prev.layout.length; ri++) {
456
+ for (const cell of prev.layout[ri]) {
457
+ if (isLayoutDescriptor(cell) && cell.id === descriptorId) {
458
+ descriptor = cell;
459
+ sourceRow = ri;
460
+ break;
461
+ }
462
+ }
463
+ if (descriptor) {
464
+ break;
465
+ }
466
+ }
467
+ if (!descriptor || sourceRow === -1) {
468
+ return prev;
469
+ }
470
+
471
+ // 1. Remove the descriptor from its source position.
472
+ const withoutSource = prev.layout.map(row => row.filter(cell => !(isLayoutDescriptor(cell) && cell.id === descriptorId)));
473
+
474
+ // 2. Was the source row emptied?
475
+ const sourceRowEmptied = withoutSource[sourceRow].length === 0;
476
+
477
+ // 3. Calculate the effective target row index.
478
+ // The drop target row was computed against the original layout.
479
+ // If we emptied a source row that was BEFORE the target, shift down by 1.
480
+ let targetRow = position.row;
481
+ if (sourceRowEmptied && sourceRow < targetRow) {
482
+ targetRow--;
483
+ }
484
+
485
+ // 4. Remove empty rows.
486
+ const cleaned = withoutSource.filter(r => r.length > 0);
487
+
488
+ // 5. Clamp target row and insert the descriptor as its own row.
489
+ targetRow = Math.max(0, Math.min(targetRow, cleaned.length));
490
+ cleaned.splice(targetRow, 0, [descriptor]);
491
+ return {
492
+ ...prev,
493
+ layout: cleaned
494
+ };
495
+ });
496
+ };
286
497
  const noConflict = useCallback(isVisible => item => {
287
498
  const sameParent = item.parent === onDropTarget.dropTarget;
288
499
  const draggedFields = [];
@@ -306,6 +517,7 @@ export const FieldEditorProvider = ({
306
517
  }, [fields.map(f => f.fieldId).join(".")]);
307
518
  const value = {
308
519
  parent,
520
+ parentEditorContext,
309
521
  depth,
310
522
  getFieldsInLayout,
311
523
  getFieldPlugin,
@@ -321,6 +533,13 @@ export const FieldEditorProvider = ({
321
533
  moveRow,
322
534
  updateField,
323
535
  deleteField,
536
+ insertLayoutCell,
537
+ updateLayoutCell,
538
+ deleteLayoutCell,
539
+ moveLayoutCell,
540
+ getLayoutFieldPlugin,
541
+ addField,
542
+ removeField,
324
543
  fields: getFieldsInLayout(),
325
544
  noConflict,
326
545
  layout: state.layout
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useState","dot","useDeepCompareEffect","plugins","utils","useModelFieldEditor","generateAlphaNumericLowerCaseId","FieldEditorContext","createContext","undefined","maxGenerateIdIterations","generateFieldId","layout","id","iteration","includes","Error","FieldEditorProvider","parent","fields","onChange","children","depth","editor","state","setState","field","dropTarget","row","index","editField","onDropTarget","fieldId","onFieldDrop","source","pos","type","fieldType","parentId","forEach","insertField","position","moveRow","moveField","plugin","getFieldPlugin","fieldData","createField","canEditSettings","onEndDrag","monitor","didDrop","monitorResult","getDropResult","removeFields","deleteField","getFieldsInLayout","filter","arr","length","map","getField","Boolean","byType","find","getFieldRendererPlugin","name","renderer","rendererName","query","key","flat","fieldPlugin","prev","next","concat","data","destination","updateField","i","set","noConflict","isVisible","item","sameParent","draggedFields","push","some","f","join","value","createElement","Provider"],"sources":["FieldEditorContext.tsx"],"sourcesContent":["import React, { useCallback, useState } from \"react\";\nimport dot from \"dot-prop-immutable\";\nimport useDeepCompareEffect from \"use-deep-compare-effect\";\nimport type {\n CmsEditorFieldId,\n CmsEditorFieldRendererPlugin,\n CmsEditorFieldsLayout,\n CmsEditorFieldTypePlugin,\n CmsModelField,\n DragSource,\n FieldLayoutPosition\n} from \"~/types.js\";\nimport { plugins } from \"@webiny/plugins\";\nimport * as utils from \"./utils/index.js\";\nimport type { FieldEditorProps } from \"./FieldEditor.js\";\nimport type { DragSourceMonitor } from \"react-dnd\";\nimport { useModelFieldEditor } from \"~/admin/components/FieldEditor/useModelFieldEditor.js\";\nimport { generateAlphaNumericLowerCaseId } from \"@webiny/utils\";\nimport type { DragObject } from \"../Droppable.js\";\n\ninterface DropTarget {\n row: number;\n index: number | null;\n}\n\n/**\n * Property in GetFieldParams can be any key from CmsEditorField, but TS does not allow union types\n */\ninterface GetFieldParams {\n id?: string;\n fieldId?: string;\n}\ninterface InsertFieldParams {\n field: CmsModelField;\n position: FieldLayoutPosition;\n}\ninterface MoveFieldParams {\n field: CmsEditorFieldId | CmsModelField;\n position: FieldLayoutPosition;\n}\ninterface GetFieldsInLayoutCallable {\n (): CmsModelField[][];\n}\ninterface GetFieldPluginCallable {\n (type: string): CmsEditorFieldTypePlugin | undefined;\n}\ninterface GetFieldCallable {\n (query: GetFieldParams): CmsModelField | undefined;\n}\ninterface GetFieldRendererCallable {\n (rendererName: string): CmsEditorFieldRendererPlugin | undefined;\n}\ninterface OnFieldDropCallable {\n (source: Partial<DragSource>, target: DropTarget): void;\n}\ninterface InsertFieldCallable {\n (params: InsertFieldParams): void;\n}\ninterface MoveFieldCallable {\n (params: MoveFieldParams): void;\n}\ninterface OnEndDragCallable<DragObject = unknown, DropResult = unknown> {\n (item: DragSource, monitor: DragSourceMonitor<DragObject, DropResult>): void;\n}\ninterface MoveRowCallable {\n (source: number, destination: number): void;\n}\ninterface UpdateFieldCallable {\n (field: CmsModelField): void;\n}\ninterface DeleteFieldCallable {\n (field: Pick<CmsModelField, \"id\">): void;\n}\nexport interface IsVisibleCallable {\n (item: DragSource): boolean;\n}\ninterface NoConflictCallable {\n (cb?: IsVisibleCallable): (item: DragSource) => boolean;\n}\nexport interface FieldEditorContext {\n fields: CmsModelField[][];\n noConflict: NoConflictCallable;\n layout: CmsEditorFieldsLayout;\n onChange?: (data: any) => void;\n getFieldsInLayout: GetFieldsInLayoutCallable;\n getFieldPlugin: GetFieldPluginCallable;\n getField: GetFieldCallable;\n getFieldRendererPlugin: GetFieldRendererCallable;\n editField: (field: CmsModelField | null) => void;\n field: CmsModelField | null;\n parent?: CmsModelField;\n depth: number;\n dropTarget: DropTarget;\n onFieldDrop: OnFieldDropCallable;\n onEndDrag: OnEndDragCallable;\n insertField: InsertFieldCallable;\n moveField: MoveFieldCallable;\n moveRow: MoveRowCallable;\n updateField: UpdateFieldCallable;\n deleteField: DeleteFieldCallable;\n}\n\ninterface FieldEditorProviderProps extends FieldEditorProps {\n children: React.ReactElement;\n}\n\ntype DropResult = {\n dropTarget: string | null;\n};\n\nexport const FieldEditorContext = React.createContext<FieldEditorContext | undefined>(undefined);\n/**\n * We try to generate the random id string but with the check that it does not exist already.\n * Chances that the same string exists are quite small, but let's check it anyway.\n *\n * In most cases, there will be no iterations anyway...\n */\nconst maxGenerateIdIterations = 100;\nconst generateFieldId = (layout: string[]): string => {\n let id = generateAlphaNumericLowerCaseId(8);\n\n let iteration = 0;\n while (layout.includes(id) && iteration < maxGenerateIdIterations) {\n id = generateAlphaNumericLowerCaseId(8);\n iteration++;\n }\n if (iteration >= maxGenerateIdIterations) {\n throw new Error(`Could not generate field ID in ${maxGenerateIdIterations} iterations.`);\n }\n return id;\n};\n\ninterface State {\n layout: CmsEditorFieldsLayout;\n fields: CmsModelField[];\n field: CmsModelField | null;\n dropTarget: DropTarget;\n}\nexport const FieldEditorProvider = ({\n parent,\n fields,\n layout,\n onChange,\n children\n}: FieldEditorProviderProps) => {\n // We need to determine depth of this provider so we can render drop zones with correct z-indexes.\n let depth = 0;\n try {\n const editor = useModelFieldEditor();\n depth = editor.depth + 1;\n } catch {\n // There's no parent provider, so this is the top-level one.\n }\n\n const [state, setState] = useState<State>({\n layout,\n fields,\n field: null,\n dropTarget: {\n row: -1,\n index: null\n }\n });\n\n useDeepCompareEffect(() => {\n onChange({ fields: state.fields, layout: state.layout });\n }, [state.fields, state.layout]);\n\n const editField = useCallback((field: CmsModelField | null) => {\n setState(state => ({ ...state, field }));\n }, []);\n\n const onDropTarget = {\n dropTarget: parent ? parent.fieldId : null\n };\n\n const onFieldDrop = useCallback<OnFieldDropCallable>((source, dropTarget) => {\n const { pos, type, fieldType, field, fields = [] } = source;\n\n const parentId = parent ? parent.fieldId : null;\n\n if (type === \"row\") {\n if (parentId !== source.parent) {\n // We're dragging an existing row from another fieldset\n fields.forEach((field, index) => {\n insertField({\n field,\n position: {\n row: dropTarget.row,\n index: index === 0 ? null : index\n }\n });\n });\n } else if (pos && pos.row !== undefined) {\n // We're dragging a row within the same fieldset\n moveRow(pos.row, dropTarget.row);\n }\n\n return onDropTarget;\n }\n\n // If source pos is set, we are moving an existing field.\n if (pos) {\n if (!field) {\n return onDropTarget;\n }\n if (parentId !== source.parent) {\n // We're dragging an existing field from another fieldset\n insertField({ field, position: dropTarget });\n } else {\n // We're dragging a field within the same fieldset\n moveField({ field, position: dropTarget });\n }\n return onDropTarget;\n }\n\n if (!fieldType) {\n return null;\n }\n const plugin = getFieldPlugin(fieldType);\n if (!plugin) {\n return null;\n }\n\n const fieldData = plugin.field.createField() as CmsModelField;\n\n if (plugin.field.canEditSettings !== false) {\n editField(fieldData);\n setState(state => ({\n ...state,\n dropTarget\n }));\n } else {\n insertField({ field: fieldData, position: dropTarget });\n }\n return null;\n }, []);\n\n const onEndDrag: OnEndDragCallable<DragObject, DropResult> = (\n { type, field, fields },\n monitor\n ) => {\n if (!monitor.didDrop()) {\n return;\n }\n\n // Check if we dropped outside of the source fieldset, and if yes, remove the field from the original parent.\n const monitorResult = monitor.getDropResult();\n const parentId = parent ? parent.fieldId : null;\n if (monitorResult?.dropTarget === parentId) {\n return;\n }\n\n const removeFields = type === \"row\" ? fields || [] : field ? [field] : [];\n removeFields.forEach(field => deleteField(field));\n };\n\n const getFieldsInLayout: GetFieldsInLayoutCallable = () => {\n // Replace every field ID with actual field object.\n return state.layout\n .filter(arr => arr.length)\n .map(row => {\n return row\n .map(id => {\n return getField({ id });\n })\n .filter(Boolean);\n })\n .filter(row => {\n return row.length > 0;\n }) as CmsModelField[][];\n };\n\n /**\n * Return field plugin.\n */\n const getFieldPlugin: GetFieldPluginCallable = type => {\n return plugins\n .byType<CmsEditorFieldTypePlugin>(\"cms-editor-field-type\")\n .find(plugin => plugin.field.type === type);\n };\n\n const getFieldRendererPlugin: GetFieldRendererCallable = name => {\n return plugins\n .byType<CmsEditorFieldRendererPlugin>(\"cms-editor-field-renderer\")\n .find(plugin => plugin.renderer.rendererName === name);\n };\n\n /**\n * Checks if field of given type already exists in the list of fields.\n */\n const getField: GetFieldCallable = query => {\n return state.fields.find(field => {\n for (const key in query) {\n if (!(key in field)) {\n return false;\n }\n\n if (field[key as keyof typeof field] !== query[key as keyof typeof query]) {\n return false;\n }\n }\n\n return true;\n });\n };\n\n /**\n * Inserts a new field into the target position.\n */\n const insertField: InsertFieldCallable = ({ field, position }) => {\n if (!field.id) {\n field.id = generateFieldId(layout.flat());\n }\n\n if (!field.type) {\n throw new Error(`Field \"type\" missing.`);\n }\n\n const fieldPlugin = getFieldPlugin(field.type);\n if (!fieldPlugin) {\n throw new Error(`No plugin found for field type \"${field.type}\".`);\n }\n\n setState(prev => {\n const next: State = {\n ...prev,\n fields: (prev.fields || []).concat(field)\n };\n\n // Move field to position where it was dropped.\n return utils.moveField({ field, position, data: next });\n });\n };\n\n /**\n * Moves field to the given target position.\n */\n const moveField: MoveFieldCallable = ({ field, position }) => {\n setState(data => {\n return utils.moveField<State>({ field, position, data });\n });\n };\n\n /**\n * Moves row to a destination row.\n */\n const moveRow: MoveRowCallable = (source, destination) => {\n setState(data => {\n return utils.moveRow({ data, source, destination });\n });\n };\n\n /**\n * Updates field.\n */\n const updateField: UpdateFieldCallable = field => {\n setState(data => {\n for (let i = 0; i < data.fields.length; i++) {\n if (data.fields[i].id === field.id) {\n return dot.set(data, `fields.${i}`, field);\n }\n }\n return data;\n });\n };\n\n /**\n * Deletes a field (both from the list of field and the layout).\n */\n const deleteField: DeleteFieldCallable = field => {\n setState(data => {\n return utils.deleteField({ field, data });\n });\n };\n\n const noConflict: NoConflictCallable = useCallback(\n (isVisible?: IsVisibleCallable) => item => {\n const sameParent = item.parent === onDropTarget.dropTarget;\n const draggedFields: string[] = [];\n switch (item.type) {\n case \"row\":\n (item.fields || []).forEach(field => draggedFields.push(field.fieldId));\n break;\n case \"field\":\n if (!item.field) {\n break;\n }\n draggedFields.push(item.field.fieldId);\n break;\n default:\n break;\n }\n\n if (\n draggedFields.length &&\n !sameParent &&\n fields.some(field => draggedFields.includes(field.fieldId))\n ) {\n return false;\n }\n\n return typeof isVisible === \"function\" ? isVisible(item) : true;\n },\n [fields.map(f => f.fieldId).join(\".\")]\n );\n\n const value: FieldEditorContext = {\n parent,\n depth,\n getFieldsInLayout,\n getFieldPlugin,\n getFieldRendererPlugin,\n getField,\n editField,\n field: state.field,\n dropTarget: state.dropTarget,\n onFieldDrop,\n onEndDrag,\n insertField,\n moveField,\n moveRow,\n updateField,\n deleteField,\n fields: getFieldsInLayout(),\n noConflict,\n layout: state.layout\n };\n\n return <FieldEditorContext.Provider value={value}>{children}</FieldEditorContext.Provider>;\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","useCallback","useState","dot","useDeepCompareEffect","isLayoutDescriptor","plugins","utils","useModelFieldEditor","generateAlphaNumericLowerCaseId","FieldEditorContext","createContext","undefined","maxGenerateIdIterations","generateFieldId","layout","id","iteration","includes","Error","FieldEditorProvider","parent","fields","onChange","children","depth","parentEditorContext","editor","state","setState","field","dropTarget","row","index","editField","onDropTarget","fieldId","onFieldDrop","source","pos","type","fieldType","parentId","forEach","insertField","position","moveRow","plugin","getLayoutFieldPlugin","layoutFieldType","descriptor","createDescriptor","insertLayoutCell","length","f","addField","moveLayoutCell","moveField","getFieldPlugin","fieldData","createField","canEditSettings","onEndDrag","monitor","didDrop","monitorResult","getDropResult","deleteLayoutCell","removeFields","deleteField","getFieldsInLayout","filter","arr","map","cell","getField","Boolean","byType","find","getFieldRendererPlugin","name","renderer","rendererName","query","key","flat","c","fieldPlugin","prev","next","concat","data","destination","updateField","i","set","some","removeField","newLayout","splice","r","updateLayoutCell","descriptorId","tabsDescriptor","fieldIdsInTabs","Set","tabs","tab","add","size","has","sourceRow","ri","withoutSource","sourceRowEmptied","targetRow","cleaned","Math","max","min","noConflict","isVisible","item","sameParent","draggedFields","push","join","value","createElement","Provider"],"sources":["FieldEditorContext.tsx"],"sourcesContent":["import React, { useCallback, useState } from \"react\";\nimport dot from \"dot-prop-immutable\";\nimport useDeepCompareEffect from \"use-deep-compare-effect\";\nimport type {\n CmsEditorFieldId,\n CmsEditorFieldRendererPlugin,\n CmsEditorFieldsLayout,\n CmsEditorFieldTypePlugin,\n CmsLayoutFieldTypePlugin,\n CmsModelField,\n DragSource,\n FieldLayoutPosition\n} from \"~/types.js\";\nimport type {\n CmsLayoutDescriptor,\n CmsEditorLayoutCell\n} from \"@webiny/app-headless-cms-common/types/model.js\";\nimport { isLayoutDescriptor } from \"@webiny/app-headless-cms-common/types/model.js\";\nimport { plugins } from \"@webiny/plugins\";\nimport * as utils from \"./utils/index.js\";\nimport type { FieldEditorProps } from \"./FieldEditor.js\";\nimport type { DragSourceMonitor } from \"react-dnd\";\nimport { useModelFieldEditor } from \"~/admin/components/FieldEditor/useModelFieldEditor.js\";\nimport { generateAlphaNumericLowerCaseId } from \"@webiny/utils\";\nimport type { DragObject } from \"../Droppable.js\";\n\ninterface DropTarget {\n row: number;\n index: number | null;\n}\n\n/**\n * Property in GetFieldParams can be any key from CmsEditorField, but TS does not allow union types\n */\ninterface GetFieldParams {\n id?: string;\n fieldId?: string;\n}\ninterface InsertFieldParams {\n field: CmsModelField;\n position: FieldLayoutPosition;\n}\ninterface AddFieldCallable {\n (field: CmsModelField): void;\n}\ninterface RemoveFieldCallable {\n (fieldId: string): void;\n}\ninterface MoveFieldParams {\n field: CmsEditorFieldId | CmsModelField;\n position: FieldLayoutPosition;\n}\ninterface GetFieldsInLayoutCallable {\n (): (CmsModelField | CmsLayoutDescriptor)[][];\n}\ninterface InsertLayoutCellCallable {\n (\n descriptor: Omit<CmsLayoutDescriptor, \"id\"> | CmsLayoutDescriptor,\n position: FieldLayoutPosition\n ): void;\n}\ninterface UpdateLayoutCellCallable {\n (descriptorId: string, descriptor: CmsLayoutDescriptor): void;\n}\ninterface DeleteLayoutCellCallable {\n (descriptorId: string): void;\n}\ninterface MoveLayoutCellCallable {\n (descriptorId: string, position: FieldLayoutPosition): void;\n}\ninterface GetLayoutFieldPluginCallable {\n (type: string): CmsLayoutFieldTypePlugin | undefined;\n}\ninterface GetFieldPluginCallable {\n (type: string): CmsEditorFieldTypePlugin | undefined;\n}\ninterface GetFieldCallable {\n (query: GetFieldParams): CmsModelField | undefined;\n}\ninterface GetFieldRendererCallable {\n (rendererName: string): CmsEditorFieldRendererPlugin | undefined;\n}\ninterface OnFieldDropCallable {\n (source: Partial<DragSource>, target: DropTarget): void;\n}\ninterface InsertFieldCallable {\n (params: InsertFieldParams): void;\n}\ninterface MoveFieldCallable {\n (params: MoveFieldParams): void;\n}\ninterface OnEndDragCallable<DragObject = unknown, DropResult = unknown> {\n (item: DragSource, monitor: DragSourceMonitor<DragObject, DropResult>): void;\n}\ninterface MoveRowCallable {\n (source: number, destination: number): void;\n}\ninterface UpdateFieldCallable {\n (field: CmsModelField): void;\n}\ninterface DeleteFieldCallable {\n (field: Pick<CmsModelField, \"id\">): void;\n}\nexport interface IsVisibleCallable {\n (item: DragSource): boolean;\n}\ninterface NoConflictCallable {\n (cb?: IsVisibleCallable): (item: DragSource) => boolean;\n}\nexport interface FieldEditorContext {\n fields: (CmsModelField | CmsLayoutDescriptor)[][];\n noConflict: NoConflictCallable;\n layout: CmsEditorFieldsLayout;\n onChange?: (data: any) => void;\n getFieldsInLayout: GetFieldsInLayoutCallable;\n getFieldPlugin: GetFieldPluginCallable;\n getField: GetFieldCallable;\n getFieldRendererPlugin: GetFieldRendererCallable;\n editField: (field: CmsModelField | null) => void;\n field: CmsModelField | null;\n parent?: CmsModelField;\n parentEditorContext?: FieldEditorContext;\n depth: number;\n dropTarget: DropTarget;\n onFieldDrop: OnFieldDropCallable;\n onEndDrag: OnEndDragCallable;\n insertField: InsertFieldCallable;\n moveField: MoveFieldCallable;\n moveRow: MoveRowCallable;\n updateField: UpdateFieldCallable;\n deleteField: DeleteFieldCallable;\n insertLayoutCell: InsertLayoutCellCallable;\n updateLayoutCell: UpdateLayoutCellCallable;\n deleteLayoutCell: DeleteLayoutCellCallable;\n moveLayoutCell: MoveLayoutCellCallable;\n getLayoutFieldPlugin: GetLayoutFieldPluginCallable;\n addField: AddFieldCallable;\n removeField: RemoveFieldCallable;\n}\n\ninterface FieldEditorProviderProps extends FieldEditorProps {\n children: React.ReactElement;\n}\n\ntype DropResult = {\n dropTarget: string | null;\n};\n\nexport const FieldEditorContext = React.createContext<FieldEditorContext | undefined>(undefined);\n/**\n * We try to generate the random id string but with the check that it does not exist already.\n * Chances that the same string exists are quite small, but let's check it anyway.\n *\n * In most cases, there will be no iterations anyway...\n */\nconst maxGenerateIdIterations = 100;\nconst generateFieldId = (layout: string[]): string => {\n let id = generateAlphaNumericLowerCaseId(8);\n\n let iteration = 0;\n while (layout.includes(id) && iteration < maxGenerateIdIterations) {\n id = generateAlphaNumericLowerCaseId(8);\n iteration++;\n }\n if (iteration >= maxGenerateIdIterations) {\n throw new Error(`Could not generate field ID in ${maxGenerateIdIterations} iterations.`);\n }\n return id;\n};\n\ninterface State {\n layout: CmsEditorFieldsLayout;\n fields: CmsModelField[];\n field: CmsModelField | null;\n dropTarget: DropTarget;\n}\nexport const FieldEditorProvider = ({\n parent,\n fields,\n layout,\n onChange,\n children\n}: FieldEditorProviderProps) => {\n // We need to determine depth of this provider so we can render drop zones with correct z-indexes.\n let depth = 0;\n let parentEditorContext: FieldEditorContext | undefined;\n try {\n const editor = useModelFieldEditor();\n depth = editor.depth + 1;\n parentEditorContext = editor;\n } catch {\n // There's no parent provider, so this is the top-level one.\n }\n\n const [state, setState] = useState<State>({\n layout,\n fields,\n field: null,\n dropTarget: {\n row: -1,\n index: null\n }\n });\n\n useDeepCompareEffect(() => {\n onChange({ fields: state.fields, layout: state.layout });\n }, [state.fields, state.layout]);\n\n const editField = useCallback((field: CmsModelField | null) => {\n setState(state => ({ ...state, field }));\n }, []);\n\n const onDropTarget = {\n dropTarget: parent ? parent.fieldId : null\n };\n\n const onFieldDrop = useCallback<OnFieldDropCallable>((source, dropTarget) => {\n const { pos, type, fieldType, field, fields = [] } = source;\n\n const parentId = parent ? parent.fieldId : null;\n\n if (type === \"row\") {\n if (parentId !== source.parent) {\n // We're dragging an existing row from another fieldset\n fields.forEach((field, index) => {\n insertField({\n field,\n position: {\n row: dropTarget.row,\n index: index === 0 ? null : index\n }\n });\n });\n } else if (pos && pos.row !== undefined) {\n // We're dragging a row within the same fieldset\n moveRow(pos.row, dropTarget.row);\n }\n\n return onDropTarget;\n }\n\n // Handle new layout field drops (separator, alert, tabs, etc.)\n if (type === \"newLayoutField\") {\n const plugin = getLayoutFieldPlugin(source.layoutFieldType || \"\");\n if (!plugin) {\n return null;\n }\n const descriptor = plugin.field.createDescriptor();\n insertLayoutCell(descriptor, dropTarget);\n return null;\n }\n\n // Handle moving an existing layout field to a new position\n if (type === \"layoutField\") {\n if (source.descriptor) {\n if (parentId !== source.parent) {\n // Cross-parent: insert a copy of the descriptor into this context\n insertLayoutCell(source.descriptor, dropTarget);\n // Also add any fields carried by this descriptor (e.g. fields inside tabs)\n if (fields.length > 0) {\n for (const f of fields) {\n addField(f);\n }\n }\n } else {\n // Same parent: move within this context\n moveLayoutCell(source.descriptor.id, dropTarget);\n }\n }\n return onDropTarget;\n }\n\n // If source pos is set, we are moving an existing field.\n if (pos) {\n if (!field) {\n return onDropTarget;\n }\n if (parentId !== source.parent) {\n // We're dragging an existing field from another fieldset\n insertField({ field, position: dropTarget });\n } else {\n // We're dragging a field within the same fieldset\n moveField({ field, position: dropTarget });\n }\n return onDropTarget;\n }\n\n if (!fieldType) {\n return null;\n }\n const plugin = getFieldPlugin(fieldType);\n if (!plugin) {\n return null;\n }\n\n const fieldData = plugin.field.createField() as CmsModelField;\n\n if (plugin.field.canEditSettings !== false) {\n editField(fieldData);\n setState(state => ({\n ...state,\n dropTarget\n }));\n } else {\n insertField({ field: fieldData, position: dropTarget });\n }\n return null;\n }, []);\n\n const onEndDrag: OnEndDragCallable<DragObject, DropResult> = (\n { type, field, fields, descriptor },\n monitor\n ) => {\n if (!monitor.didDrop()) {\n return;\n }\n\n // Check if we dropped outside of the source fieldset, and if yes, remove the item from the original parent.\n const monitorResult = monitor.getDropResult();\n const parentId = parent ? parent.fieldId : null;\n if (monitorResult?.dropTarget === parentId) {\n return;\n }\n\n if (type === \"layoutField\" && descriptor?.id) {\n deleteLayoutCell(descriptor.id);\n return;\n }\n\n const removeFields = type === \"row\" ? fields || [] : field ? [field] : [];\n removeFields.forEach(field => deleteField(field));\n };\n\n const getFieldsInLayout: GetFieldsInLayoutCallable = () => {\n // Replace every field ID with actual field object, pass through layout descriptors.\n return state.layout\n .filter(arr => arr.length)\n .map(row => {\n return row\n .map((cell: CmsEditorLayoutCell) => {\n if (isLayoutDescriptor(cell)) {\n return cell;\n }\n return getField({ id: cell });\n })\n .filter(Boolean);\n })\n .filter(row => {\n return row.length > 0;\n }) as (CmsModelField | CmsLayoutDescriptor)[][];\n };\n\n /**\n * Return field plugin.\n */\n const getFieldPlugin: GetFieldPluginCallable = type => {\n return plugins\n .byType<CmsEditorFieldTypePlugin>(\"cms-editor-field-type\")\n .find(plugin => plugin.field.type === type);\n };\n\n const getFieldRendererPlugin: GetFieldRendererCallable = name => {\n return plugins\n .byType<CmsEditorFieldRendererPlugin>(\"cms-editor-field-renderer\")\n .find(plugin => plugin.renderer.rendererName === name);\n };\n\n /**\n * Checks if field of given type already exists in the list of fields.\n */\n const getField: GetFieldCallable = query => {\n return state.fields.find(field => {\n for (const key in query) {\n if (!(key in field)) {\n return false;\n }\n\n if (field[key as keyof typeof field] !== query[key as keyof typeof query]) {\n return false;\n }\n }\n\n return true;\n });\n };\n\n /**\n * Inserts a new field into the target position.\n */\n const insertField: InsertFieldCallable = ({ field, position }) => {\n if (!field.id) {\n field.id = generateFieldId(\n layout.flat().filter((c): c is string => typeof c === \"string\")\n );\n }\n\n if (!field.type) {\n throw new Error(`Field \"type\" missing.`);\n }\n\n const fieldPlugin = getFieldPlugin(field.type);\n if (!fieldPlugin) {\n throw new Error(`No plugin found for field type \"${field.type}\".`);\n }\n\n setState(prev => {\n const next: State = {\n ...prev,\n fields: (prev.fields || []).concat(field)\n };\n\n // Move field to position where it was dropped.\n return utils.moveField({ field, position, data: next });\n });\n };\n\n /**\n * Moves field to the given target position.\n */\n const moveField: MoveFieldCallable = ({ field, position }) => {\n setState(data => {\n return utils.moveField<State>({ field, position, data });\n });\n };\n\n /**\n * Moves row to a destination row.\n */\n const moveRow: MoveRowCallable = (source, destination) => {\n setState(data => {\n return utils.moveRow({ data, source, destination });\n });\n };\n\n /**\n * Updates field.\n */\n const updateField: UpdateFieldCallable = field => {\n setState(data => {\n for (let i = 0; i < data.fields.length; i++) {\n if (data.fields[i].id === field.id) {\n return dot.set(data, `fields.${i}`, field);\n }\n }\n return data;\n });\n };\n\n /**\n * Deletes a field (both from the list of field and the layout).\n */\n const deleteField: DeleteFieldCallable = field => {\n setState(data => {\n return utils.deleteField({ field, data });\n });\n };\n\n /**\n * Add a field to the fields array without placing it in the layout.\n * Used by tabs to hoist fields to the parent context.\n */\n const addField: AddFieldCallable = field => {\n setState(prev => {\n // Don't add if already exists\n if (prev.fields.some(f => f.id === field.id)) {\n return prev;\n }\n return { ...prev, fields: [...prev.fields, field] };\n });\n };\n\n /**\n * Remove a field from the fields array by ID.\n * Used by tabs to un-hoist fields from the parent context.\n */\n const removeField: RemoveFieldCallable = fieldId => {\n setState(prev => ({\n ...prev,\n fields: prev.fields.filter(f => f.id !== fieldId)\n }));\n };\n\n /**\n * Return layout field plugin by type.\n */\n const getLayoutFieldPlugin: GetLayoutFieldPluginCallable = type => {\n return plugins\n .byType<CmsLayoutFieldTypePlugin>(\"cms-editor-layout-field-type\")\n .find(plugin => plugin.field.type === type);\n };\n\n /**\n * Insert a layout descriptor into the layout at the given position.\n */\n const insertLayoutCell: InsertLayoutCellCallable = (descriptor, position) => {\n // Auto-assign a unique ID to the descriptor.\n const cell = {\n ...descriptor,\n id: generateAlphaNumericLowerCaseId(8)\n } as CmsLayoutDescriptor;\n\n setState(prev => {\n const newLayout = [...prev.layout.map(row => [...row])];\n const { row } = position;\n\n // Layout fields always occupy a full row.\n newLayout.splice(row, 0, [cell]);\n\n return { ...prev, layout: newLayout.filter(r => r.length > 0) };\n });\n };\n\n /**\n * Update a layout descriptor found by its ID.\n */\n const updateLayoutCell: UpdateLayoutCellCallable = (descriptorId, descriptor) => {\n setState(prev => {\n const newLayout = prev.layout.map(row =>\n row.map(cell => {\n if (isLayoutDescriptor(cell) && cell.id === descriptorId) {\n return { ...descriptor, id: descriptorId };\n }\n return cell;\n })\n );\n return { ...prev, layout: newLayout };\n });\n };\n\n /**\n * Delete a layout descriptor found by its ID.\n * If it's a tabs descriptor, also remove all hoisted fields from the fields array.\n */\n const deleteLayoutCell: DeleteLayoutCellCallable = descriptorId => {\n setState(prev => {\n let fields = prev.fields;\n\n // Find the descriptor to check if it's tabs (need to clean up hoisted fields)\n for (const row of prev.layout) {\n for (const cell of row) {\n if (\n isLayoutDescriptor(cell) &&\n cell.id === descriptorId &&\n cell.type === \"tabs\"\n ) {\n const tabsDescriptor =\n cell as import(\"@webiny/app-headless-cms-common/types/model.js\").CmsTabLayoutDescriptor;\n const fieldIdsInTabs = new Set<string>();\n tabsDescriptor.tabs.forEach(tab => {\n tab.layout.forEach(r => {\n r.forEach(c => {\n if (typeof c === \"string\") {\n fieldIdsInTabs.add(c);\n }\n });\n });\n });\n if (fieldIdsInTabs.size > 0) {\n fields = fields.filter(f => !fieldIdsInTabs.has(f.id));\n }\n }\n }\n }\n\n const newLayout = prev.layout.map(row =>\n row.filter(cell => !(isLayoutDescriptor(cell) && cell.id === descriptorId))\n );\n\n return {\n ...prev,\n fields,\n layout: newLayout.filter(r => r.length > 0)\n };\n });\n };\n\n /**\n * Move a layout descriptor (found by its ID) to a new position.\n */\n const moveLayoutCell: MoveLayoutCellCallable = (descriptorId, position) => {\n setState(prev => {\n // Find the descriptor by ID.\n let descriptor: CmsLayoutDescriptor | undefined;\n let sourceRow = -1;\n\n for (let ri = 0; ri < prev.layout.length; ri++) {\n for (const cell of prev.layout[ri]) {\n if (isLayoutDescriptor(cell) && cell.id === descriptorId) {\n descriptor = cell;\n sourceRow = ri;\n break;\n }\n }\n if (descriptor) {\n break;\n }\n }\n\n if (!descriptor || sourceRow === -1) {\n return prev;\n }\n\n // 1. Remove the descriptor from its source position.\n const withoutSource = prev.layout.map(row =>\n row.filter(cell => !(isLayoutDescriptor(cell) && cell.id === descriptorId))\n );\n\n // 2. Was the source row emptied?\n const sourceRowEmptied = withoutSource[sourceRow].length === 0;\n\n // 3. Calculate the effective target row index.\n // The drop target row was computed against the original layout.\n // If we emptied a source row that was BEFORE the target, shift down by 1.\n let targetRow = position.row;\n if (sourceRowEmptied && sourceRow < targetRow) {\n targetRow--;\n }\n\n // 4. Remove empty rows.\n const cleaned = withoutSource.filter(r => r.length > 0);\n\n // 5. Clamp target row and insert the descriptor as its own row.\n targetRow = Math.max(0, Math.min(targetRow, cleaned.length));\n cleaned.splice(targetRow, 0, [descriptor]);\n\n return { ...prev, layout: cleaned };\n });\n };\n\n const noConflict: NoConflictCallable = useCallback(\n (isVisible?: IsVisibleCallable) => item => {\n const sameParent = item.parent === onDropTarget.dropTarget;\n const draggedFields: string[] = [];\n switch (item.type) {\n case \"row\":\n (item.fields || []).forEach(field => draggedFields.push(field.fieldId));\n break;\n case \"field\":\n if (!item.field) {\n break;\n }\n draggedFields.push(item.field.fieldId);\n break;\n default:\n break;\n }\n\n if (\n draggedFields.length &&\n !sameParent &&\n fields.some(field => draggedFields.includes(field.fieldId))\n ) {\n return false;\n }\n\n return typeof isVisible === \"function\" ? isVisible(item) : true;\n },\n [fields.map(f => f.fieldId).join(\".\")]\n );\n\n const value: FieldEditorContext = {\n parent,\n parentEditorContext,\n depth,\n getFieldsInLayout,\n getFieldPlugin,\n getFieldRendererPlugin,\n getField,\n editField,\n field: state.field,\n dropTarget: state.dropTarget,\n onFieldDrop,\n onEndDrag,\n insertField,\n moveField,\n moveRow,\n updateField,\n deleteField,\n insertLayoutCell,\n updateLayoutCell,\n deleteLayoutCell,\n moveLayoutCell,\n getLayoutFieldPlugin,\n addField,\n removeField,\n fields: getFieldsInLayout(),\n noConflict,\n layout: state.layout\n };\n\n return <FieldEditorContext.Provider value={value}>{children}</FieldEditorContext.Provider>;\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import type { CmsLayoutDescriptor } from "@webiny/app-headless-cms-common/types/model.js";
3
+ interface LayoutCellProps {
4
+ descriptor: CmsLayoutDescriptor;
5
+ rowIndex: number;
6
+ cellIndex: number;
7
+ }
8
+ export declare const LayoutCell: ({ descriptor }: LayoutCellProps) => React.JSX.Element;
9
+ export {};
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { useModelFieldEditor } from "./useModelFieldEditor.js";
3
+ import { Text } from "@webiny/admin-ui";
4
+ export const LayoutCell = ({
5
+ descriptor
6
+ }) => {
7
+ const {
8
+ getLayoutFieldPlugin,
9
+ updateLayoutCell,
10
+ deleteLayoutCell
11
+ } = useModelFieldEditor();
12
+ const plugin = getLayoutFieldPlugin(descriptor.type);
13
+ if (!plugin) {
14
+ return /*#__PURE__*/React.createElement("div", {
15
+ className: "p-md bg-destructive-dimmed rounded-xs"
16
+ }, /*#__PURE__*/React.createElement(Text, {
17
+ size: "sm"
18
+ }, "Unknown layout field type: \"", descriptor.type, "\""));
19
+ }
20
+ const onUpdate = d => {
21
+ updateLayoutCell(descriptor.id, d);
22
+ };
23
+ const onDelete = () => {
24
+ deleteLayoutCell(descriptor.id);
25
+ };
26
+ return plugin.field.render({
27
+ descriptor,
28
+ onUpdate,
29
+ onDelete
30
+ });
31
+ };
32
+
33
+ //# sourceMappingURL=LayoutCell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useModelFieldEditor","Text","LayoutCell","descriptor","getLayoutFieldPlugin","updateLayoutCell","deleteLayoutCell","plugin","type","createElement","className","size","onUpdate","d","id","onDelete","field","render"],"sources":["LayoutCell.tsx"],"sourcesContent":["import React from \"react\";\nimport type { CmsLayoutDescriptor } from \"@webiny/app-headless-cms-common/types/model.js\";\nimport { useModelFieldEditor } from \"./useModelFieldEditor.js\";\nimport { Text } from \"@webiny/admin-ui\";\n\ninterface LayoutCellProps {\n descriptor: CmsLayoutDescriptor;\n rowIndex: number;\n cellIndex: number;\n}\n\nexport const LayoutCell = ({ descriptor }: LayoutCellProps) => {\n const { getLayoutFieldPlugin, updateLayoutCell, deleteLayoutCell } = useModelFieldEditor();\n\n const plugin = getLayoutFieldPlugin(descriptor.type);\n\n if (!plugin) {\n return (\n <div className={\"p-md bg-destructive-dimmed rounded-xs\"}>\n <Text size={\"sm\"}>Unknown layout field type: &quot;{descriptor.type}&quot;</Text>\n </div>\n );\n }\n\n const onUpdate = (d: CmsLayoutDescriptor) => {\n updateLayoutCell(descriptor.id, d);\n };\n\n const onDelete = () => {\n deleteLayoutCell(descriptor.id);\n };\n\n return plugin.field.render({ descriptor, onUpdate, onDelete });\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAEzB,SAASC,mBAAmB;AAC5B,SAASC,IAAI,QAAQ,kBAAkB;AAQvC,OAAO,MAAMC,UAAU,GAAGA,CAAC;EAAEC;AAA4B,CAAC,KAAK;EAC3D,MAAM;IAAEC,oBAAoB;IAAEC,gBAAgB;IAAEC;EAAiB,CAAC,GAAGN,mBAAmB,CAAC,CAAC;EAE1F,MAAMO,MAAM,GAAGH,oBAAoB,CAACD,UAAU,CAACK,IAAI,CAAC;EAEpD,IAAI,CAACD,MAAM,EAAE;IACT,oBACIR,KAAA,CAAAU,aAAA;MAAKC,SAAS,EAAE;IAAwC,gBACpDX,KAAA,CAAAU,aAAA,CAACR,IAAI;MAACU,IAAI,EAAE;IAAK,GAAC,+BAAiC,EAACR,UAAU,CAACK,IAAI,EAAC,IAAY,CAC/E,CAAC;EAEd;EAEA,MAAMI,QAAQ,GAAIC,CAAsB,IAAK;IACzCR,gBAAgB,CAACF,UAAU,CAACW,EAAE,EAAED,CAAC,CAAC;EACtC,CAAC;EAED,MAAME,QAAQ,GAAGA,CAAA,KAAM;IACnBT,gBAAgB,CAACH,UAAU,CAACW,EAAE,CAAC;EACnC,CAAC;EAED,OAAOP,MAAM,CAACS,KAAK,CAACC,MAAM,CAAC;IAAEd,UAAU;IAAES,QAAQ;IAAEG;EAAS,CAAC,CAAC;AAClE,CAAC","ignoreList":[]}
@@ -8,7 +8,7 @@ export default params => {
8
8
  const fieldIndex = prev.fields.findIndex(item => item.id === field.id);
9
9
  const data = dot.delete(prev, `fields.${fieldIndex}`);
10
10
 
11
- // ...and rebuild the layout object.
11
+ // ...and rebuild the layout object, preserving layout descriptors.
12
12
  return dot.set(data, "layout", layout => {
13
13
  if (!layout) {
14
14
  return [];
@@ -16,15 +16,23 @@ export default params => {
16
16
  const newLayout = [];
17
17
  let currentRowIndex = 0;
18
18
  layout.forEach(row => {
19
- row.forEach(fieldId => {
20
- const field = data.fields.find(item => item.id === fieldId);
19
+ row.forEach(cell => {
20
+ // Preserve layout descriptors (objects) as-is
21
+ if (typeof cell !== "string") {
22
+ if (!Array.isArray(newLayout[currentRowIndex])) {
23
+ newLayout[currentRowIndex] = [];
24
+ }
25
+ newLayout[currentRowIndex].push(cell);
26
+ return;
27
+ }
28
+ const field = data.fields.find(item => item.id === cell);
21
29
  if (!field) {
22
30
  return;
23
31
  }
24
32
  if (!Array.isArray(newLayout[currentRowIndex])) {
25
33
  newLayout[currentRowIndex] = [];
26
34
  }
27
- newLayout[currentRowIndex].push(fieldId);
35
+ newLayout[currentRowIndex].push(cell);
28
36
  });
29
37
  newLayout[currentRowIndex] && newLayout[currentRowIndex].length && currentRowIndex++;
30
38
  });
@@ -1 +1 @@
1
- {"version":3,"names":["dot","params","field","data","prev","fieldIndex","fields","findIndex","item","id","delete","set","layout","newLayout","currentRowIndex","forEach","row","fieldId","find","Array","isArray","push","length"],"sources":["deleteField.ts"],"sourcesContent":["import dot from \"dot-prop-immutable\";\nimport type { CmsModelField, CmsModel } from \"~/types.js\";\n\ntype DeleteFieldParamsData = Pick<CmsModel, \"fields\" | \"layout\">;\ninterface DeleteFieldParams {\n field: Pick<CmsModelField, \"id\">;\n data: DeleteFieldParamsData;\n}\nexport default (params: DeleteFieldParams) => {\n const { field, data: prev } = params;\n // Remove the field from fields list...\n const fieldIndex = prev.fields.findIndex(item => item.id === field.id);\n const data = dot.delete(prev, `fields.${fieldIndex}`) as DeleteFieldParamsData;\n\n // ...and rebuild the layout object.\n return dot.set(data, \"layout\", (layout: DeleteFieldParamsData[\"layout\"]) => {\n if (!layout) {\n return [];\n }\n const newLayout: DeleteFieldParamsData[\"layout\"] = [];\n let currentRowIndex = 0;\n layout.forEach(row => {\n row.forEach(fieldId => {\n const field = data.fields.find(item => item.id === fieldId);\n if (!field) {\n return;\n }\n if (!Array.isArray(newLayout[currentRowIndex])) {\n newLayout[currentRowIndex] = [];\n }\n\n newLayout[currentRowIndex].push(fieldId);\n });\n newLayout[currentRowIndex] && newLayout[currentRowIndex].length && currentRowIndex++;\n });\n\n return newLayout;\n });\n};\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,oBAAoB;AAQpC,eAAgBC,MAAyB,IAAK;EAC1C,MAAM;IAAEC,KAAK;IAAEC,IAAI,EAAEC;EAAK,CAAC,GAAGH,MAAM;EACpC;EACA,MAAMI,UAAU,GAAGD,IAAI,CAACE,MAAM,CAACC,SAAS,CAACC,IAAI,IAAIA,IAAI,CAACC,EAAE,KAAKP,KAAK,CAACO,EAAE,CAAC;EACtE,MAAMN,IAAI,GAAGH,GAAG,CAACU,MAAM,CAACN,IAAI,EAAE,UAAUC,UAAU,EAAE,CAA0B;;EAE9E;EACA,OAAOL,GAAG,CAACW,GAAG,CAACR,IAAI,EAAE,QAAQ,EAAGS,MAAuC,IAAK;IACxE,IAAI,CAACA,MAAM,EAAE;MACT,OAAO,EAAE;IACb;IACA,MAAMC,SAA0C,GAAG,EAAE;IACrD,IAAIC,eAAe,GAAG,CAAC;IACvBF,MAAM,CAACG,OAAO,CAACC,GAAG,IAAI;MAClBA,GAAG,CAACD,OAAO,CAACE,OAAO,IAAI;QACnB,MAAMf,KAAK,GAAGC,IAAI,CAACG,MAAM,CAACY,IAAI,CAACV,IAAI,IAAIA,IAAI,CAACC,EAAE,KAAKQ,OAAO,CAAC;QAC3D,IAAI,CAACf,KAAK,EAAE;UACR;QACJ;QACA,IAAI,CAACiB,KAAK,CAACC,OAAO,CAACP,SAAS,CAACC,eAAe,CAAC,CAAC,EAAE;UAC5CD,SAAS,CAACC,eAAe,CAAC,GAAG,EAAE;QACnC;QAEAD,SAAS,CAACC,eAAe,CAAC,CAACO,IAAI,CAACJ,OAAO,CAAC;MAC5C,CAAC,CAAC;MACFJ,SAAS,CAACC,eAAe,CAAC,IAAID,SAAS,CAACC,eAAe,CAAC,CAACQ,MAAM,IAAIR,eAAe,EAAE;IACxF,CAAC,CAAC;IAEF,OAAOD,SAAS;EACpB,CAAC,CAAC;AACN,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["dot","params","field","data","prev","fieldIndex","fields","findIndex","item","id","delete","set","layout","newLayout","currentRowIndex","forEach","row","cell","Array","isArray","push","find","length"],"sources":["deleteField.ts"],"sourcesContent":["import dot from \"dot-prop-immutable\";\nimport type { CmsModelField, CmsModel } from \"~/types.js\";\nimport type { CmsEditorLayoutCell } from \"@webiny/app-headless-cms-common/types/model.js\";\n\ntype DeleteFieldParamsData = Pick<CmsModel, \"fields\" | \"layout\">;\ninterface DeleteFieldParams {\n field: Pick<CmsModelField, \"id\">;\n data: DeleteFieldParamsData;\n}\nexport default (params: DeleteFieldParams) => {\n const { field, data: prev } = params;\n // Remove the field from fields list...\n const fieldIndex = prev.fields.findIndex(item => item.id === field.id);\n const data = dot.delete(prev, `fields.${fieldIndex}`) as DeleteFieldParamsData;\n\n // ...and rebuild the layout object, preserving layout descriptors.\n return dot.set(data, \"layout\", (layout: DeleteFieldParamsData[\"layout\"]) => {\n if (!layout) {\n return [];\n }\n const newLayout: CmsEditorLayoutCell[][] = [];\n let currentRowIndex = 0;\n layout.forEach(row => {\n row.forEach(cell => {\n // Preserve layout descriptors (objects) as-is\n if (typeof cell !== \"string\") {\n if (!Array.isArray(newLayout[currentRowIndex])) {\n newLayout[currentRowIndex] = [];\n }\n newLayout[currentRowIndex].push(cell);\n return;\n }\n const field = data.fields.find(item => item.id === cell);\n if (!field) {\n return;\n }\n if (!Array.isArray(newLayout[currentRowIndex])) {\n newLayout[currentRowIndex] = [];\n }\n\n newLayout[currentRowIndex].push(cell);\n });\n newLayout[currentRowIndex] && newLayout[currentRowIndex].length && currentRowIndex++;\n });\n\n return newLayout;\n });\n};\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,oBAAoB;AASpC,eAAgBC,MAAyB,IAAK;EAC1C,MAAM;IAAEC,KAAK;IAAEC,IAAI,EAAEC;EAAK,CAAC,GAAGH,MAAM;EACpC;EACA,MAAMI,UAAU,GAAGD,IAAI,CAACE,MAAM,CAACC,SAAS,CAACC,IAAI,IAAIA,IAAI,CAACC,EAAE,KAAKP,KAAK,CAACO,EAAE,CAAC;EACtE,MAAMN,IAAI,GAAGH,GAAG,CAACU,MAAM,CAACN,IAAI,EAAE,UAAUC,UAAU,EAAE,CAA0B;;EAE9E;EACA,OAAOL,GAAG,CAACW,GAAG,CAACR,IAAI,EAAE,QAAQ,EAAGS,MAAuC,IAAK;IACxE,IAAI,CAACA,MAAM,EAAE;MACT,OAAO,EAAE;IACb;IACA,MAAMC,SAAkC,GAAG,EAAE;IAC7C,IAAIC,eAAe,GAAG,CAAC;IACvBF,MAAM,CAACG,OAAO,CAACC,GAAG,IAAI;MAClBA,GAAG,CAACD,OAAO,CAACE,IAAI,IAAI;QAChB;QACA,IAAI,OAAOA,IAAI,KAAK,QAAQ,EAAE;UAC1B,IAAI,CAACC,KAAK,CAACC,OAAO,CAACN,SAAS,CAACC,eAAe,CAAC,CAAC,EAAE;YAC5CD,SAAS,CAACC,eAAe,CAAC,GAAG,EAAE;UACnC;UACAD,SAAS,CAACC,eAAe,CAAC,CAACM,IAAI,CAACH,IAAI,CAAC;UACrC;QACJ;QACA,MAAMf,KAAK,GAAGC,IAAI,CAACG,MAAM,CAACe,IAAI,CAACb,IAAI,IAAIA,IAAI,CAACC,EAAE,KAAKQ,IAAI,CAAC;QACxD,IAAI,CAACf,KAAK,EAAE;UACR;QACJ;QACA,IAAI,CAACgB,KAAK,CAACC,OAAO,CAACN,SAAS,CAACC,eAAe,CAAC,CAAC,EAAE;UAC5CD,SAAS,CAACC,eAAe,CAAC,GAAG,EAAE;QACnC;QAEAD,SAAS,CAACC,eAAe,CAAC,CAACM,IAAI,CAACH,IAAI,CAAC;MACzC,CAAC,CAAC;MACFJ,SAAS,CAACC,eAAe,CAAC,IAAID,SAAS,CAACC,eAAe,CAAC,CAACQ,MAAM,IAAIR,eAAe,EAAE;IACxF,CAAC,CAAC;IAEF,OAAOD,SAAS;EACpB,CAAC,CAAC;AACN,CAAC","ignoreList":[]}
@@ -8,7 +8,12 @@ export default params => {
8
8
  for (let i = 0; i < layout.length; i++) {
9
9
  const row = layout[i];
10
10
  for (let j = 0; j < row.length; j++) {
11
- if (row[j] === id) {
11
+ const cell = row[j];
12
+ // Skip layout descriptors (objects) — only match string field IDs
13
+ if (typeof cell !== "string") {
14
+ continue;
15
+ }
16
+ if (cell === id) {
12
17
  return {
13
18
  row: i,
14
19
  index: j
@@ -1 +1 @@
1
- {"version":3,"names":["params","field","data","id","layout","i","length","row","j","index"],"sources":["getFieldPosition.ts"],"sourcesContent":["import type { CmsModelField, CmsModel, FieldLayoutPosition } from \"~/types.js\";\n\ninterface GetFieldPositionParams {\n field: string | CmsModelField;\n data: Pick<CmsModel, \"layout\">;\n}\nexport default (params: GetFieldPositionParams): FieldLayoutPosition | null => {\n const { field, data } = params;\n const id = typeof field === \"string\" ? field : field.id;\n const layout = data.layout ? data.layout : [];\n for (let i = 0; i < layout.length; i++) {\n const row = layout[i];\n for (let j = 0; j < row.length; j++) {\n if (row[j] === id) {\n return { row: i, index: j };\n }\n }\n }\n\n return null;\n};\n"],"mappings":"AAMA,eAAgBA,MAA8B,IAAiC;EAC3E,MAAM;IAAEC,KAAK;IAAEC;EAAK,CAAC,GAAGF,MAAM;EAC9B,MAAMG,EAAE,GAAG,OAAOF,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAGA,KAAK,CAACE,EAAE;EACvD,MAAMC,MAAM,GAAGF,IAAI,CAACE,MAAM,GAAGF,IAAI,CAACE,MAAM,GAAG,EAAE;EAC7C,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGD,MAAM,CAACE,MAAM,EAAED,CAAC,EAAE,EAAE;IACpC,MAAME,GAAG,GAAGH,MAAM,CAACC,CAAC,CAAC;IACrB,KAAK,IAAIG,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGD,GAAG,CAACD,MAAM,EAAEE,CAAC,EAAE,EAAE;MACjC,IAAID,GAAG,CAACC,CAAC,CAAC,KAAKL,EAAE,EAAE;QACf,OAAO;UAAEI,GAAG,EAAEF,CAAC;UAAEI,KAAK,EAAED;QAAE,CAAC;MAC/B;IACJ;EACJ;EAEA,OAAO,IAAI;AACf,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["params","field","data","id","layout","i","length","row","j","cell","index"],"sources":["getFieldPosition.ts"],"sourcesContent":["import type { CmsModelField, CmsModel, FieldLayoutPosition } from \"~/types.js\";\n\ninterface GetFieldPositionParams {\n field: string | CmsModelField;\n data: Pick<CmsModel, \"layout\">;\n}\nexport default (params: GetFieldPositionParams): FieldLayoutPosition | null => {\n const { field, data } = params;\n const id = typeof field === \"string\" ? field : field.id;\n const layout = data.layout ? data.layout : [];\n for (let i = 0; i < layout.length; i++) {\n const row = layout[i];\n for (let j = 0; j < row.length; j++) {\n const cell = row[j];\n // Skip layout descriptors (objects) — only match string field IDs\n if (typeof cell !== \"string\") {\n continue;\n }\n if (cell === id) {\n return { row: i, index: j };\n }\n }\n }\n\n return null;\n};\n"],"mappings":"AAMA,eAAgBA,MAA8B,IAAiC;EAC3E,MAAM;IAAEC,KAAK;IAAEC;EAAK,CAAC,GAAGF,MAAM;EAC9B,MAAMG,EAAE,GAAG,OAAOF,KAAK,KAAK,QAAQ,GAAGA,KAAK,GAAGA,KAAK,CAACE,EAAE;EACvD,MAAMC,MAAM,GAAGF,IAAI,CAACE,MAAM,GAAGF,IAAI,CAACE,MAAM,GAAG,EAAE;EAC7C,KAAK,IAAIC,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGD,MAAM,CAACE,MAAM,EAAED,CAAC,EAAE,EAAE;IACpC,MAAME,GAAG,GAAGH,MAAM,CAACC,CAAC,CAAC;IACrB,KAAK,IAAIG,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGD,GAAG,CAACD,MAAM,EAAEE,CAAC,EAAE,EAAE;MACjC,MAAMC,IAAI,GAAGF,GAAG,CAACC,CAAC,CAAC;MACnB;MACA,IAAI,OAAOC,IAAI,KAAK,QAAQ,EAAE;QAC1B;MACJ;MACA,IAAIA,IAAI,KAAKN,EAAE,EAAE;QACb,OAAO;UAAEI,GAAG,EAAEF,CAAC;UAAEK,KAAK,EAAEF;QAAE,CAAC;MAC/B;IACJ;EACJ;EAEA,OAAO,IAAI;AACf,CAAC","ignoreList":[]}
@@ -1,6 +1,6 @@
1
1
  import type { CmsErrorResponse, CmsModel } from "../../types.js";
2
- export declare const FIELDS_FIELDS = "\n id\n fieldId\n storageId\n type\n label\n tags\n placeholder\n description\n note\n help\n predefinedValues {\n enabled\n values {\n label\n value\n selected\n }\n }\n list\n renderer {\n name\n settings\n }\n validation {\n name\n settings\n message\n }\n listValidation {\n name\n settings\n message\n }\n settings\n";
3
- export declare const MODEL_FIELDS = "\n name\n group\n icon\n description\n modelId\n singularApiName\n pluralApiName\n savedOn\n createdBy {\n id\n displayName\n }\n titleFieldId\n descriptionFieldId\n imageFieldId\n layout\n tags\n fields {\n \n id\n fieldId\n storageId\n type\n label\n tags\n placeholder\n description\n note\n help\n predefinedValues {\n enabled\n values {\n label\n value\n selected\n }\n }\n list\n renderer {\n name\n settings\n }\n validation {\n name\n settings\n message\n }\n listValidation {\n name\n settings\n message\n }\n settings\n\n }\n plugin\n isBeingDeleted\n";
2
+ export declare const FIELDS_FIELDS = "\n id\n fieldId\n storageId\n type\n label\n tags\n placeholder\n description\n note\n help\n predefinedValues {\n enabled\n values {\n label\n value\n selected\n }\n }\n list\n renderer {\n name\n settings\n }\n validation {\n name\n settings\n message\n }\n listValidation {\n name\n settings\n message\n }\n settings\n rules {\n type\n target\n operator\n value\n action\n }\n";
3
+ export declare const MODEL_FIELDS = "\n name\n group\n icon\n description\n modelId\n singularApiName\n pluralApiName\n savedOn\n createdBy {\n id\n displayName\n }\n titleFieldId\n descriptionFieldId\n imageFieldId\n layout\n tags\n fields {\n \n id\n fieldId\n storageId\n type\n label\n tags\n placeholder\n description\n note\n help\n predefinedValues {\n enabled\n values {\n label\n value\n selected\n }\n }\n list\n renderer {\n name\n settings\n }\n validation {\n name\n settings\n message\n }\n listValidation {\n name\n settings\n message\n }\n settings\n rules {\n type\n target\n operator\n value\n action\n }\n\n }\n plugin\n isBeingDeleted\n";
4
4
  /**
5
5
  * ############################
6
6
  * Get Query
@@ -39,6 +39,13 @@ export const FIELDS_FIELDS = `
39
39
  message
40
40
  }
41
41
  settings
42
+ rules {
43
+ type
44
+ target
45
+ operator
46
+ value
47
+ action
48
+ }
42
49
  `;
43
50
  export const MODEL_FIELDS = `
44
51
  name
@@ -1 +1 @@
1
- {"version":3,"names":["gql","ERROR_FIELDS","FIELDS_FIELDS","MODEL_FIELDS","GET_CONTENT_MODEL","UPDATE_CONTENT_MODEL"],"sources":["contentModels.ts"],"sourcesContent":["import gql from \"graphql-tag\";\nimport type { CmsErrorResponse, CmsModel } from \"~/types.js\";\n\nconst ERROR_FIELDS = `\n message\n code\n data\n`;\nexport const FIELDS_FIELDS = `\n id\n fieldId\n storageId\n type\n label\n tags\n placeholder\n description\n note\n help\n predefinedValues {\n enabled\n values {\n label\n value\n selected\n }\n }\n list\n renderer {\n name\n settings\n }\n validation {\n name\n settings\n message\n }\n listValidation {\n name\n settings\n message\n }\n settings\n`;\n\nexport const MODEL_FIELDS = `\n name\n group\n icon\n description\n modelId\n singularApiName\n pluralApiName\n savedOn\n createdBy {\n id\n displayName\n }\n titleFieldId\n descriptionFieldId\n imageFieldId\n layout\n tags\n fields {\n ${FIELDS_FIELDS}\n }\n plugin\n isBeingDeleted\n`;\n/**\n * ############################\n * Get Query\n */\nexport interface GetCmsModelQueryResponse {\n getContentModel: {\n data?: CmsModel;\n error?: CmsErrorResponse;\n };\n}\nexport interface GetCmsModelQueryVariables {\n modelId: string;\n}\nexport const GET_CONTENT_MODEL = gql`\n query CmsGetContentModel($modelId: ID!) {\n getContentModel(modelId: $modelId) {\n data {\n ${MODEL_FIELDS}\n }\n error {\n ${ERROR_FIELDS}\n }\n }\n }\n`;\n\n/**\n * ############################\n * Update Mutation\n */\nexport interface UpdateCmsModelMutationResponse {\n updateContentModel: {\n data: CmsModel | null;\n error: CmsErrorResponse | null;\n };\n}\nexport interface UpdateCmsModelMutationVariables {\n modelId: string;\n // TODO @ts-refactor write the types.\n data: Partial<CmsModel>;\n}\nexport const UPDATE_CONTENT_MODEL = gql`\n mutation CmsUpdateContentModel($modelId: ID!, $data: CmsContentModelUpdateInput!) {\n updateContentModel(modelId: $modelId, data: $data) {\n data {\n ${MODEL_FIELDS}\n }\n error {\n ${ERROR_FIELDS}\n }\n }\n }\n`;\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,aAAa;AAG7B,MAAMC,YAAY,GAAG;AACrB;AACA;AACA;AACA,CAAC;AACD,OAAO,MAAMC,aAAa,GAAG;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,YAAY,GAAG;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAUD,aAAa;AACvB;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;;AAUA,OAAO,MAAME,iBAAiB,GAAGJ,GAAG;AACpC;AACA;AACA;AACA,kBAAkBG,YAAY;AAC9B;AACA;AACA,kBAAkBF,YAAY;AAC9B;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;;AAYA,OAAO,MAAMI,oBAAoB,GAAGL,GAAG;AACvC;AACA;AACA;AACA,kBAAkBG,YAAY;AAC9B;AACA;AACA,kBAAkBF,YAAY;AAC9B;AACA;AACA;AACA,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["gql","ERROR_FIELDS","FIELDS_FIELDS","MODEL_FIELDS","GET_CONTENT_MODEL","UPDATE_CONTENT_MODEL"],"sources":["contentModels.ts"],"sourcesContent":["import gql from \"graphql-tag\";\nimport type { CmsErrorResponse, CmsModel } from \"~/types.js\";\n\nconst ERROR_FIELDS = `\n message\n code\n data\n`;\nexport const FIELDS_FIELDS = `\n id\n fieldId\n storageId\n type\n label\n tags\n placeholder\n description\n note\n help\n predefinedValues {\n enabled\n values {\n label\n value\n selected\n }\n }\n list\n renderer {\n name\n settings\n }\n validation {\n name\n settings\n message\n }\n listValidation {\n name\n settings\n message\n }\n settings\n rules {\n type\n target\n operator\n value\n action\n }\n`;\n\nexport const MODEL_FIELDS = `\n name\n group\n icon\n description\n modelId\n singularApiName\n pluralApiName\n savedOn\n createdBy {\n id\n displayName\n }\n titleFieldId\n descriptionFieldId\n imageFieldId\n layout\n tags\n fields {\n ${FIELDS_FIELDS}\n }\n plugin\n isBeingDeleted\n`;\n/**\n * ############################\n * Get Query\n */\nexport interface GetCmsModelQueryResponse {\n getContentModel: {\n data?: CmsModel;\n error?: CmsErrorResponse;\n };\n}\nexport interface GetCmsModelQueryVariables {\n modelId: string;\n}\nexport const GET_CONTENT_MODEL = gql`\n query CmsGetContentModel($modelId: ID!) {\n getContentModel(modelId: $modelId) {\n data {\n ${MODEL_FIELDS}\n }\n error {\n ${ERROR_FIELDS}\n }\n }\n }\n`;\n\n/**\n * ############################\n * Update Mutation\n */\nexport interface UpdateCmsModelMutationResponse {\n updateContentModel: {\n data: CmsModel | null;\n error: CmsErrorResponse | null;\n };\n}\nexport interface UpdateCmsModelMutationVariables {\n modelId: string;\n // TODO @ts-refactor write the types.\n data: Partial<CmsModel>;\n}\nexport const UPDATE_CONTENT_MODEL = gql`\n mutation CmsUpdateContentModel($modelId: ID!, $data: CmsContentModelUpdateInput!) {\n updateContentModel(modelId: $modelId, data: $data) {\n data {\n ${MODEL_FIELDS}\n }\n error {\n ${ERROR_FIELDS}\n }\n }\n }\n`;\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,aAAa;AAG7B,MAAMC,YAAY,GAAG;AACrB;AACA;AACA;AACA,CAAC;AACD,OAAO,MAAMC,aAAa,GAAG;AAC7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,OAAO,MAAMC,YAAY,GAAG;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,UAAUD,aAAa;AACvB;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;;AAUA,OAAO,MAAME,iBAAiB,GAAGJ,GAAG;AACpC;AACA;AACA;AACA,kBAAkBG,YAAY;AAC9B;AACA;AACA,kBAAkBF,YAAY;AAC9B;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;;AAYA,OAAO,MAAMI,oBAAoB,GAAGL,GAAG;AACvC;AACA;AACA;AACA,kBAAkBG,YAAY;AAC9B;AACA;AACA,kBAAkBF,YAAY;AAC9B;AACA;AACA;AACA,CAAC","ignoreList":[]}
@@ -21,6 +21,7 @@ export declare const useModelFieldGraphqlContext: () => {
21
21
  settings?: Record<string, any>;
22
22
  } | import("@webiny/app-headless-cms-common/types").CmsModelFieldRendererPlugin["renderer"]["render"];
23
23
  tags?: string[];
24
+ rules?: import("@webiny/app-headless-cms-common/types").FieldRule[];
24
25
  };
25
26
  };
26
27
  };