@strapi/content-manager 5.14.0 → 5.15.1

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 (44) hide show
  1. package/dist/admin/components/ConfigurationForm/Fields.js +300 -204
  2. package/dist/admin/components/ConfigurationForm/Fields.js.map +1 -1
  3. package/dist/admin/components/ConfigurationForm/Fields.mjs +304 -209
  4. package/dist/admin/components/ConfigurationForm/Fields.mjs.map +1 -1
  5. package/dist/admin/history/components/VersionHeader.js +6 -0
  6. package/dist/admin/history/components/VersionHeader.js.map +1 -1
  7. package/dist/admin/history/components/VersionHeader.mjs +7 -1
  8. package/dist/admin/history/components/VersionHeader.mjs.map +1 -1
  9. package/dist/admin/pages/EditView/EditViewPage.js +81 -74
  10. package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
  11. package/dist/admin/pages/EditView/EditViewPage.mjs +82 -75
  12. package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
  13. package/dist/admin/pages/EditView/components/DocumentActions.js +24 -7
  14. package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
  15. package/dist/admin/pages/EditView/components/DocumentActions.mjs +24 -7
  16. package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
  17. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js +19 -33
  18. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.js.map +1 -1
  19. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.mjs +19 -33
  20. package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksToolbar.mjs.map +1 -1
  21. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +2 -1
  22. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  23. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +2 -1
  24. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
  25. package/dist/admin/pages/EditView/components/FormLayout.js +19 -23
  26. package/dist/admin/pages/EditView/components/FormLayout.js.map +1 -1
  27. package/dist/admin/pages/EditView/components/FormLayout.mjs +19 -23
  28. package/dist/admin/pages/EditView/components/FormLayout.mjs.map +1 -1
  29. package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.js +2 -1
  30. package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.js.map +1 -1
  31. package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.mjs +2 -1
  32. package/dist/admin/pages/ListView/components/BulkActions/ConfirmBulkActionDialog.mjs.map +1 -1
  33. package/dist/admin/src/components/ConfigurationForm/Fields.d.ts +6 -4
  34. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +7 -7
  35. package/dist/admin/translations/en.json.js +1 -0
  36. package/dist/admin/translations/en.json.js.map +1 -1
  37. package/dist/admin/translations/en.json.mjs +1 -0
  38. package/dist/admin/translations/en.json.mjs.map +1 -1
  39. package/dist/server/history/services/lifecycles.js +3 -0
  40. package/dist/server/history/services/lifecycles.js.map +1 -1
  41. package/dist/server/history/services/lifecycles.mjs +3 -0
  42. package/dist/server/history/services/lifecycles.mjs.map +1 -1
  43. package/dist/server/src/history/services/lifecycles.d.ts.map +1 -1
  44. package/package.json +11 -8
@@ -1,19 +1,60 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
+ import { DndContext, DragOverlay, useDroppable } from '@dnd-kit/core';
4
+ import { arrayMove, SortableContext, useSortable } from '@dnd-kit/sortable';
5
+ import { CSS } from '@dnd-kit/utilities';
3
6
  import { useForm, useField } from '@strapi/admin/strapi-admin';
4
- import { IconButton, Typography, Flex, Box, Grid, Menu, useComposedRefs, Modal, Link } from '@strapi/design-system';
7
+ import { IconButton, Typography, Flex, Box, Grid, Menu, Modal, Link } from '@strapi/design-system';
5
8
  import { Plus, Drag, Pencil, Cross, Cog } from '@strapi/icons';
6
- import { generateNKeysBetween as generateNKeysBetween$1 } from 'fractional-indexing';
7
- import { getEmptyImage } from 'react-dnd-html5-backend';
9
+ import { generateNKeysBetween } from 'fractional-indexing';
10
+ import { produce } from 'immer';
8
11
  import { useIntl } from 'react-intl';
9
12
  import { NavLink } from 'react-router-dom';
10
13
  import { styled } from 'styled-components';
11
- import { ItemTypes } from '../../constants/dragAndDrop.mjs';
12
- import { useDragAndDrop } from '../../hooks/useDragAndDrop.mjs';
13
14
  import { getTranslation } from '../../utils/translations.mjs';
14
15
  import { ComponentIcon } from '../ComponentIcon.mjs';
15
16
  import { EditFieldForm } from './EditFieldForm.mjs';
16
17
 
18
+ const GRID_COLUMNS = 12;
19
+ /* -------------------------------------------------------------------------------------------------
20
+ * Drag and Drop
21
+ * -----------------------------------------------------------------------------------------------*/ const DroppableContainer = ({ id, children })=>{
22
+ const droppable = useDroppable({
23
+ id
24
+ });
25
+ return children(droppable);
26
+ };
27
+ const SortableItem = ({ id, children })=>{
28
+ const { attributes, setNodeRef, transform, transition } = useSortable({
29
+ id
30
+ });
31
+ const style = {
32
+ transform: CSS.Transform.toString(transform),
33
+ transition,
34
+ height: '100%'
35
+ };
36
+ return /*#__PURE__*/ jsx("div", {
37
+ ref: setNodeRef,
38
+ style: style,
39
+ ...attributes,
40
+ children: children
41
+ });
42
+ };
43
+ /**
44
+ * Compute uids and formName for drag and drop items for the incoming layout
45
+ */ const createDragAndDropContainersFromLayout = (layout)=>{
46
+ return layout.map((row, containerIndex)=>({
47
+ ...row,
48
+ // Use unique ids for drag and drop items
49
+ dndId: `container-${containerIndex}`,
50
+ children: row.children.map((child, childIndex)=>({
51
+ ...child,
52
+ dndId: `container-${containerIndex}-child-${childIndex}`,
53
+ // The formName must be recomputed each time an item is moved
54
+ formName: `layout.${containerIndex}.children.${childIndex}`
55
+ }))
56
+ }));
57
+ };
17
58
  const Fields = ({ attributes, fieldSizes, components, metadatas = {} })=>{
18
59
  const { formatMessage } = useIntl();
19
60
  const layout = useForm('Fields', (state)=>state.values.layout ?? []);
@@ -29,7 +70,7 @@ const Fields = ({ attributes, fieldSizes, components, metadatas = {} })=>{
29
70
  const [name, { visible, ...field }] = current;
30
71
  if (!existingFields.includes(name) && visible === true) {
31
72
  const type = attributes[name]?.type;
32
- const size = type ? fieldSizes[type] : 12;
73
+ const size = type ? fieldSizes[type] : GRID_COLUMNS;
33
74
  acc.push({
34
75
  ...field,
35
76
  label: field.label ?? name,
@@ -39,61 +80,65 @@ const Fields = ({ attributes, fieldSizes, components, metadatas = {} })=>{
39
80
  }
40
81
  return acc;
41
82
  }, []);
42
- const handleMoveField = ([newRowIndex, newFieldIndex], [currentRowIndex, currentFieldIndex])=>{
43
- /**
44
- * Because this view has the constraint that the sum of field sizes cannot be greater
45
- * than 12, we don't use the form's method to move field rows, instead, we calculate
46
- * the new layout and set the entire form.
47
- */ const newLayout = structuredClone(layout);
48
- /**
49
- * Remove field from the current layout space using splice so we have the item
50
- */ const [field] = newLayout[currentRowIndex].children.splice(currentFieldIndex, 1);
51
- if (!field || field.name === TEMP_FIELD_NAME) {
52
- return;
53
- }
54
- const newRow = newLayout[newRowIndex].children;
55
- const [newFieldKey] = generateNKeysBetween(newRow, 1, currentFieldIndex, newFieldIndex);
56
- /**
57
- * Next we inject the field into it's new row at it's specified index, we then remove the spaces
58
- * if they exist and recalculate into potentially two arrays ONLY if the sizing is now over 12,
59
- * the row and the rest of the row that couldn't fit.
60
- *
61
- * for example, if i have a row of `[{size: 4}, {size: 6}]` and i add `{size: 8}` a index 0,
62
- * the new array will look like `[{size: 8}, {size: 4}, {size: 6}]` which breaks the limit of 12,
63
- * so instead we make two arrays for the new rows `[[{size: 8}, {size: 4}], [{size: 6}]]` which we
64
- * then inject at the original row point with spacers included.
65
- */ newRow.splice(newFieldIndex, 0, {
66
- ...field,
67
- __temp_key__: newFieldKey
68
- });
69
- if (newLayout[newRowIndex].children.reduce((acc, curr)=>acc + curr.size, 0) > 12) {
70
- const recalculatedRows = chunkArray(newLayout[newRowIndex].children.filter((field)=>field.name !== TEMP_FIELD_NAME));
71
- const rowKeys = generateNKeysBetween(newLayout, recalculatedRows.length, currentRowIndex, newRowIndex);
72
- newLayout.splice(newRowIndex, 1, ...recalculatedRows.map((row, index)=>({
73
- __temp_key__: rowKeys[index],
74
- children: row
75
- })));
83
+ const handleRemoveField = (rowIndex, fieldIndex)=>()=>{
84
+ if (layout[rowIndex].children.length === 1) {
85
+ removeFieldRow(`layout`, rowIndex);
86
+ } else {
87
+ onChange(`layout.${rowIndex}.children`, [
88
+ ...layout[rowIndex].children.slice(0, fieldIndex),
89
+ ...layout[rowIndex].children.slice(fieldIndex + 1)
90
+ ]);
91
+ }
92
+ };
93
+ const handleAddField = (field)=>()=>{
94
+ addFieldRow('layout', {
95
+ children: [
96
+ field
97
+ ]
98
+ });
99
+ };
100
+ const [containers, setContainers] = React.useState(()=>createDragAndDropContainersFromLayout(layout));
101
+ const [activeDragItem, setActiveDragItem] = React.useState(null);
102
+ /**
103
+ * Finds either the parent container id or the child id within a container
104
+ */ function findContainer(id, containersAsDictionary) {
105
+ // If the id is a key, then it is the parent container
106
+ if (id in containersAsDictionary) {
107
+ return id;
76
108
  }
77
- /**
78
- * Now we remove our spacers from the rows so we can understand what dead rows exist:
79
- * - if there's only spacers left
80
- * - there's nothing in the row, e.g. a size 12 field left it.
81
- * These rows are then filtered out.
82
- * After that, we recalculate the spacers for the rows that need them.
83
- */ const newLayoutWithSpacers = newLayout.map((row)=>({
109
+ // Otherwise, it is a child inside a container
110
+ return Object.keys(containersAsDictionary).find((key)=>containersAsDictionary[key].children.find((child)=>child.dndId === id));
111
+ }
112
+ /**
113
+ * Gets an item from a container based on its id
114
+ */ const getItemFromContainer = (id, container)=>{
115
+ return container.children.find((item)=>id === item.dndId);
116
+ };
117
+ /**
118
+ * Gets the containers as dictionary for quick lookup
119
+ */ const getContainersAsDictionary = ()=>{
120
+ return Object.fromEntries(containers.map((container)=>[
121
+ container.dndId,
122
+ container
123
+ ]));
124
+ };
125
+ /**
126
+ * Recomputes the empty space in the grid
127
+ */ const createContainersWithSpacers = (layout)=>{
128
+ return layout.map((row)=>({
84
129
  ...row,
85
130
  children: row.children.filter((field)=>field.name !== TEMP_FIELD_NAME)
86
131
  })).filter((row)=>row.children.length > 0).map((row)=>{
87
132
  const totalSpaceTaken = row.children.reduce((acc, curr)=>acc + curr.size, 0);
88
- if (totalSpaceTaken < 12) {
89
- const [spacerKey] = generateNKeysBetween$1(row.children.at(-1)?.__temp_key__, undefined, 1);
133
+ if (totalSpaceTaken < GRID_COLUMNS) {
134
+ const [spacerKey] = generateNKeysBetween(row.children.at(-1)?.__temp_key__, undefined, 1);
90
135
  return {
91
136
  ...row,
92
137
  children: [
93
138
  ...row.children,
94
139
  {
95
140
  name: TEMP_FIELD_NAME,
96
- size: 12 - totalSpaceTaken,
141
+ size: GRID_COLUMNS - totalSpaceTaken,
97
142
  __temp_key__: spacerKey
98
143
  }
99
144
  ]
@@ -101,182 +146,233 @@ const Fields = ({ attributes, fieldSizes, components, metadatas = {} })=>{
101
146
  }
102
147
  return row;
103
148
  });
104
- onChange('layout', newLayoutWithSpacers);
105
149
  };
106
- const handleRemoveField = (rowIndex, fieldIndex)=>()=>{
107
- if (layout[rowIndex].children.length === 1) {
108
- removeFieldRow(`layout`, rowIndex);
109
- } else {
110
- onChange(`layout.${rowIndex}.children`, [
111
- ...layout[rowIndex].children.slice(0, fieldIndex),
112
- ...layout[rowIndex].children.slice(fieldIndex + 1)
113
- ]);
150
+ /**
151
+ * When layout changes (e.g. when a field size is changed or the containers are reordered)
152
+ * we need to update the ids and form names
153
+ */ React.useEffect(()=>{
154
+ const containers = createDragAndDropContainersFromLayout(layout);
155
+ setContainers(containers);
156
+ }, [
157
+ layout,
158
+ setContainers
159
+ ]);
160
+ return /*#__PURE__*/ jsx(DndContext, {
161
+ onDragStart: (event)=>{
162
+ const containersAsDictionary = getContainersAsDictionary();
163
+ const activeContainer = findContainer(event.active.id, containersAsDictionary);
164
+ if (!activeContainer) return;
165
+ const activeItem = getItemFromContainer(event.active.id, containersAsDictionary[activeContainer]);
166
+ if (activeItem) {
167
+ setActiveDragItem(activeItem);
114
168
  }
115
- };
116
- const handleAddField = (field)=>()=>{
117
- addFieldRow('layout', {
118
- children: [
119
- field
120
- ]
169
+ },
170
+ onDragOver: ({ active, over })=>{
171
+ const containersAsDictionary = getContainersAsDictionary();
172
+ const activeContainer = findContainer(active.id, containersAsDictionary);
173
+ const overContainer = findContainer(over?.id ?? '', containersAsDictionary);
174
+ const activeContainerIndex = containers.findIndex((container)=>container.dndId === activeContainer);
175
+ const overContainerIndex = containers.findIndex((container)=>container.dndId === overContainer);
176
+ if (!activeContainer || !overContainer) {
177
+ return;
178
+ }
179
+ const draggedItem = getItemFromContainer(active.id, containersAsDictionary[activeContainer]);
180
+ const overItem = getItemFromContainer(over?.id ?? '', containersAsDictionary[overContainer]);
181
+ const overIndex = containersAsDictionary[overContainer].children.findIndex((item)=>item.dndId === over?.id);
182
+ if (!draggedItem) return;
183
+ // Handle a full width field being dragged
184
+ if (draggedItem?.size === GRID_COLUMNS) {
185
+ // Swap the items in the containers
186
+ const update = produce(containers, (draft)=>{
187
+ draft[activeContainerIndex].children = containers[overContainerIndex].children;
188
+ draft[overContainerIndex].children = containers[activeContainerIndex].children;
189
+ });
190
+ setContainers(update);
191
+ return;
192
+ }
193
+ /**
194
+ * Handle an item being dragged from one container to another,
195
+ * the item is removed from its current container, and then added to its new container
196
+ * An item can only be added in a container if there is enough space.
197
+ */ const update = produce(containers, (draft)=>{
198
+ draft[activeContainerIndex].children = draft[activeContainerIndex].children.filter((item)=>item.dndId !== active.id);
199
+ const spaceTaken = draft[overContainerIndex].children.reduce((acc, curr)=>{
200
+ if (curr.name === TEMP_FIELD_NAME) {
201
+ return acc;
202
+ }
203
+ return acc + curr.size;
204
+ }, 0);
205
+ // Check the sizes of the children, if there is no room, exit
206
+ if (spaceTaken + draggedItem.size > GRID_COLUMNS) {
207
+ // Leave the item where it started
208
+ draft[activeContainerIndex].children = containers[activeContainerIndex].children;
209
+ return;
210
+ }
211
+ if (overItem?.name === TEMP_FIELD_NAME) {
212
+ // We are over an invisible spacer, replace it with the dragged item
213
+ draft[overContainerIndex].children.splice(overIndex, 1, draggedItem);
214
+ return;
215
+ }
216
+ // There is room for the item in the container, drop it
217
+ draft[overContainerIndex].children.splice(overIndex, 0, draggedItem);
121
218
  });
122
- };
123
- return /*#__PURE__*/ jsxs(Flex, {
124
- paddingTop: 6,
125
- direction: "column",
126
- alignItems: "stretch",
127
- gap: 4,
128
- children: [
129
- /*#__PURE__*/ jsxs(Flex, {
130
- alignItems: "flex-start",
131
- direction: "column",
132
- justifyContent: "space-between",
133
- children: [
134
- /*#__PURE__*/ jsx(Typography, {
135
- fontWeight: "bold",
136
- children: formatMessage({
137
- id: getTranslation('containers.list.displayedFields'),
138
- defaultMessage: 'Displayed fields'
139
- })
140
- }),
141
- /*#__PURE__*/ jsx(Typography, {
142
- variant: "pi",
143
- textColor: "neutral600",
144
- children: formatMessage({
145
- id: 'containers.SettingPage.editSettings.description',
146
- defaultMessage: 'Drag & drop the fields to build the layout'
147
- })
148
- })
149
- ]
150
- }),
151
- /*#__PURE__*/ jsx(Box, {
152
- padding: 4,
153
- hasRadius: true,
154
- borderStyle: "dashed",
155
- borderWidth: "1px",
156
- borderColor: "neutral300",
157
- children: /*#__PURE__*/ jsxs(Flex, {
219
+ setContainers(update);
220
+ },
221
+ onDragEnd: (event)=>{
222
+ const { active, over } = event;
223
+ const { id } = active;
224
+ const overId = over?.id;
225
+ const containersAsDictionary = getContainersAsDictionary();
226
+ const activeContainer = findContainer(id, containersAsDictionary);
227
+ const overContainer = findContainer(overId, containersAsDictionary);
228
+ if (!activeContainer || !overContainer) {
229
+ return;
230
+ }
231
+ const activeIndex = containersAsDictionary[activeContainer].children.findIndex((children)=>children.dndId === id);
232
+ const overIndex = containersAsDictionary[overContainer].children.findIndex((children)=>children.dndId === overId);
233
+ const movedContainerItems = produce(containersAsDictionary, (draft)=>{
234
+ if (activeIndex !== overIndex && activeContainer === overContainer) {
235
+ // Move items around inside their own container
236
+ draft[activeContainer].children = arrayMove(draft[activeContainer].children, activeIndex, overIndex);
237
+ }
238
+ });
239
+ // Remove properties the server does not expect before updating the form
240
+ const updatedContainers = Object.values(movedContainerItems);
241
+ const updatedContainersWithSpacers = createContainersWithSpacers(updatedContainers);
242
+ const updatedLayout = updatedContainersWithSpacers.map(({ dndId: _dndId, children, ...container })=>({
243
+ ...container,
244
+ children: children.map(({ dndId: _dndId, formName: _formName, ...child })=>child)
245
+ }));
246
+ // Update the layout
247
+ onChange('layout', updatedLayout);
248
+ setActiveDragItem(null);
249
+ },
250
+ children: /*#__PURE__*/ jsxs(Flex, {
251
+ paddingTop: 6,
252
+ direction: "column",
253
+ alignItems: "stretch",
254
+ gap: 4,
255
+ children: [
256
+ /*#__PURE__*/ jsxs(Flex, {
257
+ alignItems: "flex-start",
158
258
  direction: "column",
159
- alignItems: "stretch",
160
- gap: 2,
259
+ justifyContent: "space-between",
161
260
  children: [
162
- layout.map((row, rowIndex)=>/*#__PURE__*/ jsx(Grid.Root, {
163
- gap: 2,
164
- children: row.children.map(({ size, ...field }, fieldIndex)=>/*#__PURE__*/ jsx(Grid.Item, {
165
- col: size,
166
- direction: "column",
167
- alignItems: "stretch",
168
- children: /*#__PURE__*/ jsx(Field, {
169
- attribute: attributes[field.name],
170
- components: components,
171
- index: [
172
- rowIndex,
173
- fieldIndex
174
- ],
175
- name: `layout.${rowIndex}.children.${fieldIndex}`,
176
- onMoveField: handleMoveField,
177
- onRemoveField: handleRemoveField(rowIndex, fieldIndex)
178
- })
179
- }, field.name))
180
- }, row.__temp_key__)),
181
- /*#__PURE__*/ jsxs(Menu.Root, {
182
- children: [
183
- /*#__PURE__*/ jsx(Menu.Trigger, {
184
- startIcon: /*#__PURE__*/ jsx(Plus, {}),
185
- endIcon: null,
186
- disabled: remainingFields.length === 0,
187
- fullWidth: true,
188
- variant: "secondary",
189
- children: formatMessage({
190
- id: getTranslation('containers.SettingPage.add.field'),
191
- defaultMessage: 'Insert another field'
192
- })
193
- }),
194
- /*#__PURE__*/ jsx(Menu.Content, {
195
- children: remainingFields.map((field)=>/*#__PURE__*/ jsx(Menu.Item, {
196
- onSelect: handleAddField(field),
197
- children: field.label
198
- }, field.name))
199
- })
200
- ]
261
+ /*#__PURE__*/ jsx(Typography, {
262
+ fontWeight: "bold",
263
+ children: formatMessage({
264
+ id: getTranslation('containers.list.displayedFields'),
265
+ defaultMessage: 'Displayed fields'
266
+ })
267
+ }),
268
+ /*#__PURE__*/ jsx(Typography, {
269
+ variant: "pi",
270
+ textColor: "neutral600",
271
+ children: formatMessage({
272
+ id: 'containers.SettingPage.editSettings.description',
273
+ defaultMessage: 'Drag & drop the fields to build the layout'
274
+ })
201
275
  })
202
276
  ]
277
+ }),
278
+ /*#__PURE__*/ jsx(Box, {
279
+ padding: 4,
280
+ hasRadius: true,
281
+ borderStyle: "dashed",
282
+ borderWidth: "1px",
283
+ borderColor: "neutral300",
284
+ children: /*#__PURE__*/ jsxs(Flex, {
285
+ direction: "column",
286
+ alignItems: "stretch",
287
+ gap: 2,
288
+ children: [
289
+ containers.map((container, containerIndex)=>/*#__PURE__*/ jsx(SortableContext, {
290
+ id: container.dndId,
291
+ items: container.children.map((child)=>({
292
+ id: child.dndId
293
+ })),
294
+ children: /*#__PURE__*/ jsx(DroppableContainer, {
295
+ id: container.dndId,
296
+ children: ({ setNodeRef })=>/*#__PURE__*/ jsx(Grid.Root, {
297
+ ref: setNodeRef,
298
+ gap: 2,
299
+ children: container.children.map((child, childIndex)=>/*#__PURE__*/ jsx(Grid.Item, {
300
+ col: child.size,
301
+ direction: "column",
302
+ alignItems: "stretch",
303
+ children: /*#__PURE__*/ jsx(SortableItem, {
304
+ id: child.dndId,
305
+ children: /*#__PURE__*/ jsx(Field, {
306
+ attribute: attributes[child.name],
307
+ components: components,
308
+ name: child.formName,
309
+ onRemoveField: handleRemoveField(containerIndex, childIndex),
310
+ dndId: child.dndId
311
+ })
312
+ })
313
+ }, child.dndId))
314
+ }, container.dndId)
315
+ })
316
+ }, container.dndId)),
317
+ /*#__PURE__*/ jsx(DragOverlay, {
318
+ children: activeDragItem ? /*#__PURE__*/ jsx(Field, {
319
+ attribute: attributes[activeDragItem.name],
320
+ components: components,
321
+ name: activeDragItem.formName,
322
+ dndId: activeDragItem.dndId
323
+ }) : null
324
+ }),
325
+ /*#__PURE__*/ jsxs(Menu.Root, {
326
+ children: [
327
+ /*#__PURE__*/ jsx(Menu.Trigger, {
328
+ startIcon: /*#__PURE__*/ jsx(Plus, {}),
329
+ endIcon: null,
330
+ disabled: remainingFields.length === 0,
331
+ fullWidth: true,
332
+ variant: "secondary",
333
+ children: formatMessage({
334
+ id: getTranslation('containers.SettingPage.add.field'),
335
+ defaultMessage: 'Insert another field'
336
+ })
337
+ }),
338
+ /*#__PURE__*/ jsx(Menu.Content, {
339
+ children: remainingFields.map((field)=>/*#__PURE__*/ jsx(Menu.Item, {
340
+ onSelect: handleAddField(field),
341
+ children: field.label
342
+ }, field.name))
343
+ })
344
+ ]
345
+ })
346
+ ]
347
+ })
203
348
  })
204
- })
205
- ]
349
+ ]
350
+ })
206
351
  });
207
352
  };
208
- /**
209
- * @internal
210
- * @description Small abstraction to solve within an array of fields where you can
211
- * add a field to the beginning or start, move back and forth what it's index range
212
- * should be when calculating it's new temp key
213
- */ const generateNKeysBetween = (field, count, currInd, newInd)=>{
214
- const startKey = currInd > newInd ? field[newInd - 1]?.__temp_key__ : field[newInd]?.__temp_key__;
215
- const endKey = currInd > newInd ? field[newInd]?.__temp_key__ : field[newInd + 1]?.__temp_key__;
216
- return generateNKeysBetween$1(startKey, endKey, count);
217
- };
218
- /**
219
- * @internal
220
- * @description chunks a row of layouts by the max size we allow, 12. It does not add the
221
- * spacers again, that should be added separately.
222
- */ const chunkArray = (array)=>{
223
- const result = [];
224
- let temp = [];
225
- array.reduce((acc, field)=>{
226
- if (acc + field.size > 12) {
227
- result.push(temp);
228
- temp = [
229
- field
230
- ];
231
- return field.size;
232
- } else {
233
- temp.push(field);
234
- return acc + field.size;
235
- }
236
- }, 0);
237
- if (temp.length > 0) {
238
- result.push(temp);
239
- }
240
- return result;
241
- };
242
353
  const TEMP_FIELD_NAME = '_TEMP_';
243
354
  /**
244
355
  * Displays a field in the layout with drag options, also
245
356
  * opens a modal to edit the details of said field.
246
- */ const Field = ({ attribute, components, name, index, onMoveField, onRemoveField })=>{
357
+ */ const Field = ({ attribute, components, name, onRemoveField, dndId })=>{
247
358
  const [isModalOpen, setIsModalOpen] = React.useState(false);
248
359
  const { formatMessage } = useIntl();
249
360
  const { value } = useField(name);
250
- const [{ isDragging }, objectRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(true, {
251
- dropSensitivity: 'immediate',
252
- type: ItemTypes.EDIT_FIELD,
253
- item: {
254
- index,
255
- label: value?.label,
256
- name
257
- },
258
- index,
259
- onMoveItem: onMoveField
361
+ const { listeners, setActivatorNodeRef } = useSortable({
362
+ id: dndId
260
363
  });
261
- React.useEffect(()=>{
262
- dragPreviewRef(getEmptyImage(), {
263
- captureDraggingState: false
264
- });
265
- }, [
266
- dragPreviewRef
267
- ]);
268
- const composedRefs = useComposedRefs(dragRef, objectRef);
269
364
  const handleRemoveField = (e)=>{
270
365
  e.preventDefault();
271
366
  e.stopPropagation();
272
- onRemoveField(e);
367
+ if (onRemoveField) {
368
+ onRemoveField?.(e);
369
+ }
273
370
  };
274
371
  const onEditFieldMeta = (e)=>{
275
372
  e.preventDefault();
276
373
  e.stopPropagation();
277
374
  setIsModalOpen(true);
278
375
  };
279
- const tempRefs = useComposedRefs(dropRef, objectRef);
280
376
  if (!value) {
281
377
  return null;
282
378
  }
@@ -286,10 +382,12 @@ const TEMP_FIELD_NAME = '_TEMP_';
286
382
  height: "100%",
287
383
  style: {
288
384
  opacity: 0
289
- },
290
- ref: tempRefs
385
+ }
291
386
  });
292
387
  }
388
+ if (!attribute) {
389
+ return null;
390
+ }
293
391
  return /*#__PURE__*/ jsxs(Modal.Root, {
294
392
  open: isModalOpen,
295
393
  onOpenChange: setIsModalOpen,
@@ -298,10 +396,6 @@ const TEMP_FIELD_NAME = '_TEMP_';
298
396
  borderColor: "neutral150",
299
397
  background: "neutral100",
300
398
  hasRadius: true,
301
- style: {
302
- opacity: isDragging ? 0.5 : 1
303
- },
304
- ref: dropRef,
305
399
  gap: 3,
306
400
  cursor: "pointer",
307
401
  onClick: ()=>{
@@ -309,6 +403,7 @@ const TEMP_FIELD_NAME = '_TEMP_';
309
403
  },
310
404
  children: [
311
405
  /*#__PURE__*/ jsx(DragButton, {
406
+ ref: setActivatorNodeRef,
312
407
  tag: "span",
313
408
  withTooltip: false,
314
409
  label: formatMessage({
@@ -317,8 +412,7 @@ const TEMP_FIELD_NAME = '_TEMP_';
317
412
  }, {
318
413
  item: value.label
319
414
  }),
320
- onClick: (e)=>e.stopPropagation(),
321
- ref: composedRefs,
415
+ ...listeners,
322
416
  children: /*#__PURE__*/ jsx(Drag, {})
323
417
  }),
324
418
  /*#__PURE__*/ jsxs(Flex, {
@@ -425,6 +519,7 @@ const TEMP_FIELD_NAME = '_TEMP_';
425
519
  alignItems: "flex-start",
426
520
  gap: 2,
427
521
  width: "100%",
522
+ wrap: "wrap",
428
523
  children: attribute?.components.map((uid)=>/*#__PURE__*/ jsxs(ComponentLink, {
429
524
  // used to stop the edit form from appearing when we click here.
430
525
  onClick: (e)=>e.stopPropagation(),
@@ -508,5 +603,5 @@ const ComponentLink = styled(NavLink)`
508
603
  }
509
604
  `;
510
605
 
511
- export { Fields, TEMP_FIELD_NAME };
606
+ export { Fields, SortableItem, TEMP_FIELD_NAME };
512
607
  //# sourceMappingURL=Fields.mjs.map