@strapi/content-manager 0.0.0-next.39bf1ab0d2e327b0a192d2f5adcb4182de865411 → 0.0.0-next.3a1d87a9c3b1d4d89f741c6ecd7f501230fd8d76

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 (130) hide show
  1. package/dist/_chunks/{ComponentConfigurationPage-DYq8aqos.js → ComponentConfigurationPage-DMxUlNOo.js} +3 -3
  2. package/dist/_chunks/{ComponentConfigurationPage-DYq8aqos.js.map → ComponentConfigurationPage-DMxUlNOo.js.map} +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-CzVt9QCC.mjs → ComponentConfigurationPage-baEkO-OV.mjs} +3 -3
  4. package/dist/_chunks/{ComponentConfigurationPage-CzVt9QCC.mjs.map → ComponentConfigurationPage-baEkO-OV.mjs.map} +1 -1
  5. package/dist/_chunks/{EditConfigurationPage-C9IATpr0.js → EditConfigurationPage-CXxV7mKn.js} +3 -3
  6. package/dist/_chunks/{EditConfigurationPage-C9IATpr0.js.map → EditConfigurationPage-CXxV7mKn.js.map} +1 -1
  7. package/dist/_chunks/{EditConfigurationPage-CLDwrUv5.mjs → EditConfigurationPage-YR8-4VCS.mjs} +3 -3
  8. package/dist/_chunks/{EditConfigurationPage-CLDwrUv5.mjs.map → EditConfigurationPage-YR8-4VCS.mjs.map} +1 -1
  9. package/dist/_chunks/{EditViewPage-Ch-uBvbv.js → EditViewPage-BfR6jAR6.js} +13 -76
  10. package/dist/_chunks/EditViewPage-BfR6jAR6.js.map +1 -0
  11. package/dist/_chunks/{EditViewPage-DtKM7Jgw.mjs → EditViewPage-DFF7c27p.mjs} +11 -74
  12. package/dist/_chunks/EditViewPage-DFF7c27p.mjs.map +1 -0
  13. package/dist/_chunks/{Form-C3kjKrPw.js → Form-CjcMRP5A.js} +2 -2
  14. package/dist/_chunks/{Form-C3kjKrPw.js.map → Form-CjcMRP5A.js.map} +1 -1
  15. package/dist/_chunks/{Form-BB5i9Pxl.mjs → Form-MSOSfGGN.mjs} +2 -2
  16. package/dist/_chunks/{Form-BB5i9Pxl.mjs.map → Form-MSOSfGGN.mjs.map} +1 -1
  17. package/dist/_chunks/{History-AwrK0-SA.js → History-BgZ7gVuF.js} +43 -19
  18. package/dist/_chunks/History-BgZ7gVuF.js.map +1 -0
  19. package/dist/_chunks/{History-Cw2Q7OQL.mjs → History-WOQNVho-.mjs} +32 -8
  20. package/dist/_chunks/History-WOQNVho-.mjs.map +1 -0
  21. package/dist/_chunks/{Field-Bn1jgMeF.mjs → Input-BkKwZ6Qt.mjs} +1215 -1193
  22. package/dist/_chunks/Input-BkKwZ6Qt.mjs.map +1 -0
  23. package/dist/_chunks/{Field-B9ADaInZ.js → Input-BwOibhc3.js} +1297 -1274
  24. package/dist/_chunks/Input-BwOibhc3.js.map +1 -0
  25. package/dist/_chunks/{ListConfigurationPage-B47JIu1e.mjs → ListConfigurationPage-BeXfr6uW.mjs} +2 -2
  26. package/dist/_chunks/{ListConfigurationPage-B47JIu1e.mjs.map → ListConfigurationPage-BeXfr6uW.mjs.map} +1 -1
  27. package/dist/_chunks/{ListConfigurationPage-CNTJ0DBm.js → ListConfigurationPage-DnJ3nbwL.js} +2 -2
  28. package/dist/_chunks/{ListConfigurationPage-CNTJ0DBm.js.map → ListConfigurationPage-DnJ3nbwL.js.map} +1 -1
  29. package/dist/_chunks/{ListViewPage-Be_UEBar.js → ListViewPage-CJFDudKl.js} +13 -10
  30. package/dist/_chunks/{ListViewPage-Be_UEBar.js.map → ListViewPage-CJFDudKl.js.map} +1 -1
  31. package/dist/_chunks/{ListViewPage-DuvjX6ra.mjs → ListViewPage-VK2v44Q1.mjs} +8 -5
  32. package/dist/_chunks/{ListViewPage-DuvjX6ra.mjs.map → ListViewPage-VK2v44Q1.mjs.map} +1 -1
  33. package/dist/_chunks/{NoContentTypePage-C6M-Q0Tv.mjs → NoContentTypePage-T8ttty6K.mjs} +2 -2
  34. package/dist/_chunks/{NoContentTypePage-C6M-Q0Tv.mjs.map → NoContentTypePage-T8ttty6K.mjs.map} +1 -1
  35. package/dist/_chunks/{NoContentTypePage-B1J0KUCO.js → NoContentTypePage-en2PwWgI.js} +2 -2
  36. package/dist/_chunks/{NoContentTypePage-B1J0KUCO.js.map → NoContentTypePage-en2PwWgI.js.map} +1 -1
  37. package/dist/_chunks/{NoPermissionsPage-CN34TlEE.js → NoPermissionsPage-CcjILry3.js} +2 -2
  38. package/dist/_chunks/{NoPermissionsPage-CN34TlEE.js.map → NoPermissionsPage-CcjILry3.js.map} +1 -1
  39. package/dist/_chunks/{NoPermissionsPage-CAi3zCAD.mjs → NoPermissionsPage-CokBHhhy.mjs} +2 -2
  40. package/dist/_chunks/{NoPermissionsPage-CAi3zCAD.mjs.map → NoPermissionsPage-CokBHhhy.mjs.map} +1 -1
  41. package/dist/_chunks/{Preview-BrBRcL10.mjs → Preview-BF81YhRj.mjs} +10 -16
  42. package/dist/_chunks/Preview-BF81YhRj.mjs.map +1 -0
  43. package/dist/_chunks/{Preview-DOqm5jcJ.js → Preview-DgzAuzWQ.js} +10 -16
  44. package/dist/_chunks/Preview-DgzAuzWQ.js.map +1 -0
  45. package/dist/_chunks/{Relations-xtKZHtTN.js → Relations-1O-JcM4t.js} +3 -3
  46. package/dist/_chunks/{Relations-xtKZHtTN.js.map → Relations-1O-JcM4t.js.map} +1 -1
  47. package/dist/_chunks/{Relations-_K-HYOiM.mjs → Relations-BncdhGCd.mjs} +3 -3
  48. package/dist/_chunks/{Relations-_K-HYOiM.mjs.map → Relations-BncdhGCd.mjs.map} +1 -1
  49. package/dist/_chunks/{en-Dtk_ot79.mjs → en-BZaUty0m.mjs} +8 -2
  50. package/dist/_chunks/{en-Dtk_ot79.mjs.map → en-BZaUty0m.mjs.map} +1 -1
  51. package/dist/_chunks/{en-BK8Xyl5I.js → en-CzCnBk4S.js} +8 -2
  52. package/dist/_chunks/{en-BK8Xyl5I.js.map → en-CzCnBk4S.js.map} +1 -1
  53. package/dist/_chunks/{index-tETMKK2G.mjs → index-DiluOUp6.mjs} +214 -52
  54. package/dist/_chunks/index-DiluOUp6.mjs.map +1 -0
  55. package/dist/_chunks/{index-BlX-OdHL.js → index-EXJvmn4t.js} +197 -35
  56. package/dist/_chunks/index-EXJvmn4t.js.map +1 -0
  57. package/dist/_chunks/{layout-D8Sz3KxF.js → layout-4TbKVax8.js} +3 -3
  58. package/dist/_chunks/{layout-D8Sz3KxF.js.map → layout-4TbKVax8.js.map} +1 -1
  59. package/dist/_chunks/{layout-BaQBaz56.mjs → layout-mSwsYzxv.mjs} +3 -3
  60. package/dist/_chunks/{layout-BaQBaz56.mjs.map → layout-mSwsYzxv.mjs.map} +1 -1
  61. package/dist/_chunks/{relations-CsfmCqOU.mjs → relations--YOvQBqv.mjs} +2 -2
  62. package/dist/_chunks/{relations-CsfmCqOU.mjs.map → relations--YOvQBqv.mjs.map} +1 -1
  63. package/dist/_chunks/{relations-CAbbX8Sa.js → relations-Ai6Izh7h.js} +2 -2
  64. package/dist/_chunks/{relations-CAbbX8Sa.js.map → relations-Ai6Izh7h.js.map} +1 -1
  65. package/dist/_chunks/{useDebounce-DmuSJIF3.mjs → usePrev-CZGy2Vjf.mjs} +11 -11
  66. package/dist/_chunks/usePrev-CZGy2Vjf.mjs.map +1 -0
  67. package/dist/_chunks/{useDebounce-CtcjDB3L.js → usePrev-D5J_2fEu.js} +8 -8
  68. package/dist/_chunks/usePrev-D5J_2fEu.js.map +1 -0
  69. package/dist/admin/index.js +2 -1
  70. package/dist/admin/index.js.map +1 -1
  71. package/dist/admin/index.mjs +6 -5
  72. package/dist/admin/src/exports.d.ts +1 -0
  73. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  74. package/dist/admin/src/hooks/useDocument.d.ts +19 -2
  75. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +1 -1
  76. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  77. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  78. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  79. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
  80. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
  81. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -0
  82. package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
  83. package/dist/admin/src/preview/pages/Preview.d.ts +1 -1
  84. package/dist/admin/src/preview/services/preview.d.ts +1 -1
  85. package/dist/admin/src/services/api.d.ts +1 -1
  86. package/dist/admin/src/services/components.d.ts +2 -2
  87. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  88. package/dist/admin/src/services/documents.d.ts +16 -16
  89. package/dist/admin/src/services/init.d.ts +1 -1
  90. package/dist/admin/src/services/relations.d.ts +2 -2
  91. package/dist/admin/src/services/uid.d.ts +3 -3
  92. package/dist/server/index.js +156 -142
  93. package/dist/server/index.js.map +1 -1
  94. package/dist/server/index.mjs +157 -143
  95. package/dist/server/index.mjs.map +1 -1
  96. package/dist/server/src/controllers/utils/metadata.d.ts +1 -0
  97. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  98. package/dist/server/src/history/controllers/history-version.d.ts +1 -1
  99. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  100. package/dist/server/src/history/services/history.d.ts +3 -3
  101. package/dist/server/src/history/services/history.d.ts.map +1 -1
  102. package/dist/server/src/history/services/utils.d.ts +6 -10
  103. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  104. package/dist/server/src/index.d.ts +3 -2
  105. package/dist/server/src/index.d.ts.map +1 -1
  106. package/dist/server/src/preview/index.d.ts.map +1 -1
  107. package/dist/server/src/services/document-metadata.d.ts +4 -2
  108. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  109. package/dist/server/src/services/index.d.ts +3 -2
  110. package/dist/server/src/services/index.d.ts.map +1 -1
  111. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  112. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  113. package/dist/server/src/services/utils/populate.d.ts +2 -2
  114. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  115. package/package.json +8 -7
  116. package/dist/_chunks/EditViewPage-Ch-uBvbv.js.map +0 -1
  117. package/dist/_chunks/EditViewPage-DtKM7Jgw.mjs.map +0 -1
  118. package/dist/_chunks/Field-B9ADaInZ.js.map +0 -1
  119. package/dist/_chunks/Field-Bn1jgMeF.mjs.map +0 -1
  120. package/dist/_chunks/History-AwrK0-SA.js.map +0 -1
  121. package/dist/_chunks/History-Cw2Q7OQL.mjs.map +0 -1
  122. package/dist/_chunks/Preview-BrBRcL10.mjs.map +0 -1
  123. package/dist/_chunks/Preview-DOqm5jcJ.js.map +0 -1
  124. package/dist/_chunks/index-BlX-OdHL.js.map +0 -1
  125. package/dist/_chunks/index-tETMKK2G.mjs.map +0 -1
  126. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +0 -1
  127. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +0 -1
  128. package/dist/admin/src/preview/constants.d.ts +0 -1
  129. package/dist/server/src/preview/constants.d.ts +0 -2
  130. package/dist/server/src/preview/constants.d.ts.map +0 -1
@@ -1,25 +1,75 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { useState, useEffect, useCallback, memo } from "react";
4
- import { useStrapiApp, createContext, useField, useNotification, useForm, useAPIErrorHandler, useQueryParams, useFocusInputField, InputRenderer as InputRenderer$1 } from "@strapi/admin/strapi-admin";
5
- import { Box, SingleSelect, SingleSelectOption, Typography, Flex, BaseLink, Button, Popover, Field, Tooltip, IconButton, useComposedRefs, Portal, FocusTrap, Divider, VisuallyHidden, Grid as Grid$1, Accordion, TextButton, TextInput, IconButtonGroup, Menu, MenuItem } from "@strapi/design-system";
6
- import pipe$1 from "lodash/fp/pipe";
4
+ import { useStrapiApp, createContext, useField, useForm, useNotification, useAPIErrorHandler, useQueryParams, useFocusInputField, InputRenderer as InputRenderer$1 } from "@strapi/admin/strapi-admin";
5
+ import { Box, SingleSelect, SingleSelectOption, Typography, Flex, BaseLink, Button, Popover, Field, Tooltip, IconButton, useComposedRefs, Portal, FocusTrap, Divider, VisuallyHidden, Accordion, Menu, MenuItem, Grid as Grid$1, TextInput, IconButtonGroup, TextButton } from "@strapi/design-system";
6
+ import { CodeBlock as CodeBlock$1, HeadingOne, HeadingTwo, HeadingThree, HeadingFour, HeadingFive, HeadingSix, Image as Image$1, NumberList, BulletList, Paragraph, Quotes, Link as Link$1, Drag, Collapse, Bold, Italic, Underline, StrikeThrough, Code, Expand, PlusCircle, Trash, More, EyeStriked, CheckCircle, WarningCircle, Loader, ArrowClockwise, Plus } from "@strapi/icons";
7
7
  import { useIntl } from "react-intl";
8
- import { m as DOCUMENT_META_FIELDS, g as getTranslation, c as useDoc, e as contentManagerApi, n as CLONE_PATH, d as buildValidParams, f as useDocumentRBAC, S as SINGLE_TYPES, o as useDocLayout } from "./index-tETMKK2G.mjs";
9
- import { generateNKeysBetween } from "fractional-indexing";
10
- import { u as useComponent, C as ComponentProvider, M as MemoizedRelationsField } from "./Relations-_K-HYOiM.mjs";
11
- import { CodeBlock as CodeBlock$1, HeadingOne, HeadingTwo, HeadingThree, HeadingFour, HeadingFive, HeadingSix, Image as Image$1, NumberList, BulletList, Paragraph, Quotes, Link as Link$1, Drag, Collapse, Bold, Italic, Underline, StrikeThrough, Code, Expand, PlusCircle, Plus, Trash, EyeStriked, CheckCircle, WarningCircle, Loader, ArrowClockwise, More } from "@strapi/icons";
8
+ import { g as getTranslation, m as useDocLayout, c as useDoc, n as createDefaultForm, t as transformDocument, e as contentManagerApi, o as CLONE_PATH, d as buildValidParams, f as useDocumentRBAC, S as SINGLE_TYPES } from "./index-DiluOUp6.mjs";
12
9
  import { styled, css, keyframes } from "styled-components";
13
- import { C as ComponentIcon, a as COMPONENT_ICONS } from "./ComponentIcon-u4bIXTFY.mjs";
14
- import { getEmptyImage } from "react-dnd-html5-backend";
15
- import { a as DIRECTIONS, u as useDragAndDrop, I as ItemTypes } from "./useDragAndDrop-DJ6jqvZN.mjs";
16
- import { g as getIn } from "./objects-D6yBsdmx.mjs";
17
10
  import { Editor as Editor$1, Transforms, Node, Element, Range, Path, Point, createEditor } from "slate";
18
11
  import { withHistory } from "slate-history";
19
12
  import { useFocused, useSelected, ReactEditor, Editable, useSlate, Slate, withReact } from "slate-react";
20
- import { p as prefixFileUrlWithBackendUrl, u as usePrev, a as useDebounce } from "./useDebounce-DmuSJIF3.mjs";
13
+ import * as Prism from "prismjs";
14
+ import "prismjs/themes/prism-solarizedlight.css";
15
+ import "prismjs/components/prism-asmatmel";
16
+ import "prismjs/components/prism-bash";
17
+ import "prismjs/components/prism-basic";
18
+ import "prismjs/components/prism-c";
19
+ import "prismjs/components/prism-clojure";
20
+ import "prismjs/components/prism-cobol";
21
+ import "prismjs/components/prism-cpp";
22
+ import "prismjs/components/prism-csharp";
23
+ import "prismjs/components/prism-dart";
24
+ import "prismjs/components/prism-docker";
25
+ import "prismjs/components/prism-elixir";
26
+ import "prismjs/components/prism-erlang";
27
+ import "prismjs/components/prism-fortran";
28
+ import "prismjs/components/prism-fsharp";
29
+ import "prismjs/components/prism-go";
30
+ import "prismjs/components/prism-graphql";
31
+ import "prismjs/components/prism-groovy";
32
+ import "prismjs/components/prism-haskell";
33
+ import "prismjs/components/prism-haxe";
34
+ import "prismjs/components/prism-ini";
35
+ import "prismjs/components/prism-java";
36
+ import "prismjs/components/prism-javascript";
37
+ import "prismjs/components/prism-jsx";
38
+ import "prismjs/components/prism-json";
39
+ import "prismjs/components/prism-julia";
40
+ import "prismjs/components/prism-kotlin";
41
+ import "prismjs/components/prism-latex";
42
+ import "prismjs/components/prism-lua";
43
+ import "prismjs/components/prism-markdown";
44
+ import "prismjs/components/prism-matlab";
45
+ import "prismjs/components/prism-makefile";
46
+ import "prismjs/components/prism-objectivec";
47
+ import "prismjs/components/prism-perl";
48
+ import "prismjs/components/prism-php";
49
+ import "prismjs/components/prism-powershell";
50
+ import "prismjs/components/prism-python";
51
+ import "prismjs/components/prism-r";
52
+ import "prismjs/components/prism-ruby";
53
+ import "prismjs/components/prism-rust";
54
+ import "prismjs/components/prism-sas";
55
+ import "prismjs/components/prism-scala";
56
+ import "prismjs/components/prism-scheme";
57
+ import "prismjs/components/prism-sql";
58
+ import "prismjs/components/prism-stata";
59
+ import "prismjs/components/prism-swift";
60
+ import "prismjs/components/prism-typescript";
61
+ import "prismjs/components/prism-tsx";
62
+ import "prismjs/components/prism-vbnet";
63
+ import "prismjs/components/prism-yaml";
64
+ import { p as prefixFileUrlWithBackendUrl, u as useDebounce, a as usePrev } from "./usePrev-CZGy2Vjf.mjs";
65
+ import { a as DIRECTIONS, u as useDragAndDrop, I as ItemTypes } from "./useDragAndDrop-DJ6jqvZN.mjs";
21
66
  import * as Toolbar from "@radix-ui/react-toolbar";
22
- import { useLocation, useMatch } from "react-router-dom";
67
+ import { getEmptyImage } from "react-dnd-html5-backend";
68
+ import { useMatch, useLocation } from "react-router-dom";
69
+ import { g as getIn } from "./objects-D6yBsdmx.mjs";
70
+ import { u as useComponent, C as ComponentProvider, M as MemoizedRelationsField } from "./Relations-BncdhGCd.mjs";
71
+ import pipe$1 from "lodash/fp/pipe";
72
+ import { C as ComponentIcon, a as COMPONENT_ICONS } from "./ComponentIcon-u4bIXTFY.mjs";
23
73
  import CodeMirror from "codemirror5";
24
74
  import sanitizeHtml from "sanitize-html";
25
75
  import { getLanguage, highlight, highlightAuto } from "highlight.js";
@@ -35,93 +85,6 @@ import sub from "markdown-it-sub";
35
85
  import sup from "markdown-it-sup";
36
86
  import "highlight.js/styles/solarized-dark.css";
37
87
  import "codemirror5/addon/display/placeholder";
38
- const BLOCK_LIST_ATTRIBUTE_KEYS = ["__component", "__temp_key__"];
39
- const traverseData = (predicate, transform) => (schema, components = {}) => (data = {}) => {
40
- const traverse = (datum, attributes) => {
41
- return Object.entries(datum).reduce((acc, [key, value]) => {
42
- const attribute = attributes[key];
43
- if (BLOCK_LIST_ATTRIBUTE_KEYS.includes(key) || value === null || value === void 0) {
44
- acc[key] = value;
45
- return acc;
46
- }
47
- if (attribute.type === "component") {
48
- if (attribute.repeatable) {
49
- const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
50
- acc[key] = componentValue.map(
51
- (componentData) => traverse(componentData, components[attribute.component]?.attributes ?? {})
52
- );
53
- } else {
54
- const componentValue = predicate(attribute, value) ? transform(value, attribute) : value;
55
- acc[key] = traverse(componentValue, components[attribute.component]?.attributes ?? {});
56
- }
57
- } else if (attribute.type === "dynamiczone") {
58
- const dynamicZoneValue = predicate(attribute, value) ? transform(value, attribute) : value;
59
- acc[key] = dynamicZoneValue.map(
60
- (componentData) => traverse(componentData, components[componentData.__component]?.attributes ?? {})
61
- );
62
- } else if (predicate(attribute, value)) {
63
- acc[key] = transform(value, attribute);
64
- } else {
65
- acc[key] = value;
66
- }
67
- return acc;
68
- }, {});
69
- };
70
- return traverse(data, schema.attributes);
71
- };
72
- const removeProhibitedFields = (prohibitedFields) => traverseData(
73
- (attribute) => prohibitedFields.includes(attribute.type),
74
- () => ""
75
- );
76
- const prepareRelations = traverseData(
77
- (attribute) => attribute.type === "relation",
78
- () => ({
79
- connect: [],
80
- disconnect: []
81
- })
82
- );
83
- const prepareTempKeys = traverseData(
84
- (attribute) => attribute.type === "component" && attribute.repeatable || attribute.type === "dynamiczone",
85
- (data) => {
86
- if (Array.isArray(data) && data.length > 0) {
87
- const keys = generateNKeysBetween(void 0, void 0, data.length);
88
- return data.map((datum, index) => ({
89
- ...datum,
90
- __temp_key__: keys[index]
91
- }));
92
- }
93
- return data;
94
- }
95
- );
96
- const removeFieldsThatDontExistOnSchema = (schema) => (data) => {
97
- const schemaKeys = Object.keys(schema.attributes);
98
- const dataKeys = Object.keys(data);
99
- const keysToRemove = dataKeys.filter((key) => !schemaKeys.includes(key));
100
- const revisedData = [...keysToRemove, ...DOCUMENT_META_FIELDS].reduce((acc, key) => {
101
- delete acc[key];
102
- return acc;
103
- }, structuredClone(data));
104
- return revisedData;
105
- };
106
- const removeNullValues = (data) => {
107
- return Object.entries(data).reduce((acc, [key, value]) => {
108
- if (value === null) {
109
- return acc;
110
- }
111
- acc[key] = value;
112
- return acc;
113
- }, {});
114
- };
115
- const transformDocument = (schema, components = {}) => (document2) => {
116
- const transformations = pipe$1(
117
- removeFieldsThatDontExistOnSchema(schema),
118
- removeProhibitedFields(["password"])(schema, components),
119
- removeNullValues,
120
- prepareRelations(schema, components),
121
- prepareTempKeys(schema, components)
122
- );
123
- return transformations(document2);
124
- };
125
88
  const componentStore = /* @__PURE__ */ new Map();
126
89
  const useLazyComponents = (componentUids = []) => {
127
90
  const [lazyComponentStore, setLazyComponentStore] = useState(Object.fromEntries(componentStore));
@@ -163,7 +126,8 @@ const useLazyComponents = (componentUids = []) => {
163
126
  const codeLanguages = [
164
127
  {
165
128
  value: "asm",
166
- label: "Assembly"
129
+ label: "Assembly",
130
+ decorate: "asmatmel"
167
131
  },
168
132
  {
169
133
  value: "bash",
@@ -199,7 +163,8 @@ const codeLanguages = [
199
163
  },
200
164
  {
201
165
  value: "dockerfile",
202
- label: "Dockerfile"
166
+ label: "Dockerfile",
167
+ decorate: "docker"
203
168
  },
204
169
  {
205
170
  value: "elixir",
@@ -355,7 +320,8 @@ const codeLanguages = [
355
320
  },
356
321
  {
357
322
  value: "typescript",
358
- label: "TypeScript"
323
+ label: "TypeScript",
324
+ decorate: "ts"
359
325
  },
360
326
  {
361
327
  value: "tsx",
@@ -371,7 +337,8 @@ const codeLanguages = [
371
337
  },
372
338
  {
373
339
  value: "yaml",
374
- label: "YAML"
340
+ label: "YAML",
341
+ decorate: "yml"
375
342
  }
376
343
  ];
377
344
  const baseHandleConvert = (editor, attributesToSet) => {
@@ -437,6 +404,29 @@ const pressEnterTwiceToExit = (editor) => {
437
404
  });
438
405
  }
439
406
  };
407
+ const decorateCode = ([node, path]) => {
408
+ const ranges = [];
409
+ if (!Element.isElement(node) || node.type !== "code") return ranges;
410
+ const text = Node.string(node);
411
+ const language = codeLanguages.find((lang) => lang.value === node.language);
412
+ const decorateKey = language?.decorate ?? language?.value;
413
+ const selectedLanguage = Prism.languages[decorateKey || "plaintext"];
414
+ const tokens = Prism.tokenize(text, selectedLanguage);
415
+ let start = 0;
416
+ for (const token of tokens) {
417
+ const length = token.length;
418
+ const end = start + length;
419
+ if (typeof token !== "string") {
420
+ ranges.push({
421
+ anchor: { path, offset: start },
422
+ focus: { path, offset: end },
423
+ className: `token ${token.type}`
424
+ });
425
+ }
426
+ start = end;
427
+ }
428
+ return ranges;
429
+ };
440
430
  const CodeBlock = styled.pre`
441
431
  border-radius: ${({ theme }) => theme.borderRadius};
442
432
  background-color: ${({ theme }) => theme.colors.neutral100};
@@ -521,8 +511,7 @@ const codeBlocks = {
521
511
  handleEnterKey(editor) {
522
512
  pressEnterTwiceToExit(editor);
523
513
  },
524
- snippets: ["```"],
525
- dragHandleTopMargin: "10px"
514
+ snippets: ["```"]
526
515
  }
527
516
  };
528
517
  const H1 = styled(Typography).attrs({ tag: "h1" })`
@@ -1301,13 +1290,13 @@ const quoteBlocks = {
1301
1290
  handleEnterKey(editor) {
1302
1291
  pressEnterTwiceToExit(editor);
1303
1292
  },
1304
- snippets: [">"],
1305
- dragHandleTopMargin: "6px"
1293
+ snippets: [">"]
1306
1294
  }
1307
1295
  };
1308
1296
  const ToolbarWrapper = styled(Flex)`
1309
1297
  &[aria-disabled='true'] {
1310
1298
  cursor: not-allowed;
1299
+ background: ${({ theme }) => theme.colors.neutral150};
1311
1300
  }
1312
1301
  `;
1313
1302
  const Separator = styled(Toolbar.Separator)`
@@ -1318,7 +1307,7 @@ const Separator = styled(Toolbar.Separator)`
1318
1307
  const FlexButton = styled(Flex)`
1319
1308
  // Inherit the not-allowed cursor from ToolbarWrapper when disabled
1320
1309
  &[aria-disabled] {
1321
- cursor: inherit;
1310
+ cursor: not-allowed;
1322
1311
  }
1323
1312
 
1324
1313
  &[aria-disabled='false'] {
@@ -1670,7 +1659,7 @@ const BlocksToolbar = () => {
1670
1659
  return false;
1671
1660
  };
1672
1661
  const isButtonDisabled = checkButtonDisabled();
1673
- return /* @__PURE__ */ jsx(Toolbar.Root, { "aria-disabled": disabled, asChild: true, children: /* @__PURE__ */ jsxs(ToolbarWrapper, { gap: 2, padding: 2, children: [
1662
+ return /* @__PURE__ */ jsx(Toolbar.Root, { "aria-disabled": disabled, asChild: true, children: /* @__PURE__ */ jsxs(ToolbarWrapper, { gap: 2, padding: 2, width: "100%", children: [
1674
1663
  /* @__PURE__ */ jsx(BlocksDropdown, {}),
1675
1664
  /* @__PURE__ */ jsx(Separator, {}),
1676
1665
  /* @__PURE__ */ jsx(Toolbar.ToggleGroup, { type: "multiple", asChild: true, children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
@@ -1744,30 +1733,32 @@ const DragIconButton = styled(IconButton)`
1744
1733
  display: flex;
1745
1734
  align-items: center;
1746
1735
  justify-content: center;
1736
+ border: none;
1747
1737
  border-radius: ${({ theme }) => theme.borderRadius};
1748
- width: ${({ theme }) => theme.spaces[4]};
1749
- height: ${({ theme }) => theme.spaces[6]};
1738
+ padding-left: ${({ theme }) => theme.spaces[0]};
1739
+ padding-right: ${({ theme }) => theme.spaces[0]};
1740
+ padding-top: ${({ theme }) => theme.spaces[1]};
1741
+ padding-bottom: ${({ theme }) => theme.spaces[1]};
1750
1742
  visibility: hidden;
1751
1743
  cursor: grab;
1752
1744
  opacity: inherit;
1753
1745
  margin-top: ${(props) => props.$dragHandleTopMargin ?? 0};
1754
1746
 
1755
1747
  &:hover {
1756
- background: ${({ theme }) => theme.colors.neutral200};
1748
+ background: ${({ theme }) => theme.colors.neutral100};
1757
1749
  }
1758
1750
  &:active {
1759
1751
  cursor: grabbing;
1752
+ background: ${({ theme }) => theme.colors.neutral150};
1760
1753
  }
1761
1754
  &[aria-disabled='true'] {
1762
- cursor: not-allowed;
1763
- background: transparent;
1755
+ visibility: hidden;
1764
1756
  }
1765
1757
  svg {
1766
- height: auto;
1767
1758
  min-width: ${({ theme }) => theme.spaces[3]};
1768
1759
 
1769
1760
  path {
1770
- fill: ${({ theme }) => theme.colors.neutral700};
1761
+ fill: ${({ theme }) => theme.colors.neutral500};
1771
1762
  }
1772
1763
  }
1773
1764
  `;
@@ -1918,7 +1909,7 @@ const baseRenderLeaf = (props, modifiers2) => {
1918
1909
  }
1919
1910
  return currentChildren;
1920
1911
  }, props.children);
1921
- return /* @__PURE__ */ jsx("span", { ...props.attributes, children: wrappedChildren });
1912
+ return /* @__PURE__ */ jsx("span", { ...props.attributes, className: props.leaf.className, children: wrappedChildren });
1922
1913
  };
1923
1914
  const baseRenderElement = ({
1924
1915
  props,
@@ -2120,7 +2111,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2120
2111
  background: "neutral0",
2121
2112
  color: "neutral800",
2122
2113
  lineHeight: 6,
2123
- paddingRight: 4,
2114
+ paddingRight: 7,
2124
2115
  paddingTop: 6,
2125
2116
  paddingBottom: 3,
2126
2117
  children: [
@@ -2131,6 +2122,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2131
2122
  readOnly: disabled,
2132
2123
  placeholder,
2133
2124
  isExpandedMode,
2125
+ decorate: decorateCode,
2134
2126
  renderElement,
2135
2127
  renderLeaf,
2136
2128
  onKeyDown: handleKeyDown,
@@ -2453,6 +2445,7 @@ const ExpandIconButton = styled(IconButton)`
2453
2445
  position: absolute;
2454
2446
  bottom: 1.2rem;
2455
2447
  right: 1.2rem;
2448
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
2456
2449
  `;
2457
2450
  function useResetKey(value) {
2458
2451
  const slateUpdatesCount = React.useRef(0);
@@ -2584,26 +2577,6 @@ const BlocksInput = React.forwardRef(
2584
2577
  }
2585
2578
  );
2586
2579
  const MemoizedBlocksInput = React.memo(BlocksInput);
2587
- const createDefaultForm = (contentType, components = {}) => {
2588
- const traverseSchema = (attributes) => {
2589
- return Object.entries(attributes).reduce((acc, [key, attribute]) => {
2590
- if ("default" in attribute) {
2591
- acc[key] = attribute.default;
2592
- } else if (attribute.type === "component" && attribute.required) {
2593
- const defaultComponentForm = traverseSchema(components[attribute.component].attributes);
2594
- if (attribute.repeatable) {
2595
- acc[key] = attribute.min ? [...Array(attribute.min).fill(defaultComponentForm)] : [];
2596
- } else {
2597
- acc[key] = defaultComponentForm;
2598
- }
2599
- } else if (attribute.type === "dynamiczone" && attribute.required) {
2600
- acc[key] = [];
2601
- }
2602
- return acc;
2603
- }, {});
2604
- };
2605
- return traverseSchema(contentType.attributes);
2606
- };
2607
2580
  const Initializer = ({ disabled, name: name2, onClick }) => {
2608
2581
  const { formatMessage } = useIntl();
2609
2582
  const field = useField(name2);
@@ -2638,126 +2611,451 @@ const Initializer = ({ disabled, name: name2, onClick }) => {
2638
2611
  }
2639
2612
  ) });
2640
2613
  };
2641
- const NonRepeatableComponent = ({
2642
- attribute,
2643
- name: name2,
2614
+ const AddComponentButton = ({
2615
+ hasError,
2616
+ isDisabled,
2617
+ isOpen,
2644
2618
  children,
2645
- layout
2619
+ onClick
2620
+ }) => {
2621
+ return /* @__PURE__ */ jsx(
2622
+ StyledButton,
2623
+ {
2624
+ type: "button",
2625
+ onClick,
2626
+ disabled: isDisabled,
2627
+ background: "neutral0",
2628
+ style: { cursor: isDisabled ? "not-allowed" : "pointer" },
2629
+ variant: "tertiary",
2630
+ children: /* @__PURE__ */ jsxs(Flex, { tag: "span", gap: 2, children: [
2631
+ /* @__PURE__ */ jsx(StyledAddIcon, { "aria-hidden": true, $isOpen: isOpen, $hasError: hasError && !isOpen }),
2632
+ /* @__PURE__ */ jsx(
2633
+ Typography,
2634
+ {
2635
+ variant: "pi",
2636
+ fontWeight: "bold",
2637
+ textColor: hasError && !isOpen ? "danger600" : "neutral600",
2638
+ children
2639
+ }
2640
+ )
2641
+ ] })
2642
+ }
2643
+ );
2644
+ };
2645
+ const StyledAddIcon = styled(PlusCircle)`
2646
+ height: ${({ theme }) => theme.spaces[6]};
2647
+ width: ${({ theme }) => theme.spaces[6]};
2648
+ transform: ${({ $isOpen }) => $isOpen ? "rotate(45deg)" : "rotate(0deg)"};
2649
+
2650
+ > circle {
2651
+ fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger200 : theme.colors.neutral150};
2652
+ }
2653
+ > path {
2654
+ fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger600 : theme.colors.neutral500};
2655
+ }
2656
+ `;
2657
+ const StyledButton = styled(Button)`
2658
+ padding-left: ${({ theme }) => theme.spaces[3]};
2659
+ border-radius: 26px;
2660
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
2661
+ height: 5rem;
2662
+ `;
2663
+ const ComponentCategory = ({
2664
+ category,
2665
+ components = [],
2666
+ variant = "primary",
2667
+ onAddComponent
2646
2668
  }) => {
2647
2669
  const { formatMessage } = useIntl();
2648
- const { value } = useField(name2);
2649
- const level = useComponent("NonRepeatableComponent", (state) => state.level);
2650
- const isNested = level > 0;
2651
- return /* @__PURE__ */ jsx(ComponentProvider, { id: value?.id, uid: attribute.component, level: level + 1, type: "component", children: /* @__PURE__ */ jsx(
2670
+ return /* @__PURE__ */ jsxs(Accordion.Item, { value: category, children: [
2671
+ /* @__PURE__ */ jsx(Accordion.Header, { variant, children: /* @__PURE__ */ jsx(Accordion.Trigger, { children: formatMessage({ id: category, defaultMessage: category }) }) }),
2672
+ /* @__PURE__ */ jsx(ResponsiveAccordionContent, { children: /* @__PURE__ */ jsx(Grid, { paddingTop: 4, paddingBottom: 4, paddingLeft: 3, paddingRight: 3, children: components.map(({ uid, displayName, icon }) => /* @__PURE__ */ jsx(
2673
+ ComponentBox,
2674
+ {
2675
+ tag: "button",
2676
+ type: "button",
2677
+ background: "neutral100",
2678
+ justifyContent: "center",
2679
+ onClick: onAddComponent(uid),
2680
+ hasRadius: true,
2681
+ height: "8.4rem",
2682
+ shrink: 0,
2683
+ borderColor: "neutral200",
2684
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, alignItems: "center", justifyContent: "center", children: [
2685
+ /* @__PURE__ */ jsx(ComponentIcon, { color: "currentColor", background: "primary200", icon }),
2686
+ /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: displayName })
2687
+ ] })
2688
+ },
2689
+ uid
2690
+ )) }) })
2691
+ ] });
2692
+ };
2693
+ const ResponsiveAccordionContent = styled(Accordion.Content)`
2694
+ container-type: inline-size;
2695
+ `;
2696
+ const Grid = styled(Box)`
2697
+ display: grid;
2698
+ grid-template-columns: repeat(auto-fill, 100%);
2699
+ grid-gap: ${({ theme }) => theme.spaces[1]};
2700
+
2701
+ @container (min-width: ${() => RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
2702
+ grid-template-columns: repeat(auto-fill, 14rem);
2703
+ }
2704
+ `;
2705
+ const ComponentBox = styled(Flex)`
2706
+ color: ${({ theme }) => theme.colors.neutral600};
2707
+ cursor: pointer;
2708
+
2709
+ @media (prefers-reduced-motion: no-preference) {
2710
+ transition: color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
2711
+ }
2712
+
2713
+ &:focus,
2714
+ &:hover {
2715
+ border: 1px solid ${({ theme }) => theme.colors.primary200};
2716
+ background: ${({ theme }) => theme.colors.primary100};
2717
+ color: ${({ theme }) => theme.colors.primary600};
2718
+ }
2719
+ `;
2720
+ const ComponentPicker = ({
2721
+ dynamicComponentsByCategory = {},
2722
+ isOpen,
2723
+ onClickAddComponent
2724
+ }) => {
2725
+ const { formatMessage } = useIntl();
2726
+ const handleAddComponentToDz = (componentUid) => () => {
2727
+ onClickAddComponent(componentUid);
2728
+ };
2729
+ if (!isOpen) {
2730
+ return null;
2731
+ }
2732
+ return /* @__PURE__ */ jsxs(
2652
2733
  Box,
2653
2734
  {
2654
- background: "neutral100",
2655
- paddingLeft: 6,
2656
- paddingRight: 6,
2657
2735
  paddingTop: 6,
2658
2736
  paddingBottom: 6,
2659
- hasRadius: isNested,
2660
- borderColor: isNested ? "neutral200" : void 0,
2661
- children: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: layout.map((row, index) => {
2662
- return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
2663
- const completeFieldName = `${name2}.${field.name}`;
2664
- const translatedLabel = formatMessage({
2665
- id: `content-manager.components.${attribute.component}.${field.name}`,
2666
- defaultMessage: field.label
2667
- });
2668
- return /* @__PURE__ */ jsx(
2669
- Grid$1.Item,
2670
- {
2671
- col: size,
2672
- s: 12,
2673
- xs: 12,
2674
- direction: "column",
2675
- alignItems: "stretch",
2676
- children: children({ ...field, label: translatedLabel, name: completeFieldName })
2677
- },
2678
- completeFieldName
2679
- );
2680
- }) }, index);
2681
- }) })
2737
+ paddingLeft: 5,
2738
+ paddingRight: 5,
2739
+ background: "neutral0",
2740
+ shadow: "tableShadow",
2741
+ borderColor: "neutral150",
2742
+ hasRadius: true,
2743
+ children: [
2744
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral600", children: formatMessage({
2745
+ id: getTranslation("components.DynamicZone.ComponentPicker-label"),
2746
+ defaultMessage: "Pick one component"
2747
+ }) }) }),
2748
+ /* @__PURE__ */ jsx(Box, { paddingTop: 2, children: /* @__PURE__ */ jsx(Accordion.Root, { defaultValue: Object.keys(dynamicComponentsByCategory)[0], children: Object.entries(dynamicComponentsByCategory).map(([category, components], index) => /* @__PURE__ */ jsx(
2749
+ ComponentCategory,
2750
+ {
2751
+ category,
2752
+ components,
2753
+ onAddComponent: handleAddComponentToDz,
2754
+ variant: index % 2 === 1 ? "primary" : "secondary"
2755
+ },
2756
+ category
2757
+ )) }) })
2758
+ ]
2682
2759
  }
2683
- ) });
2760
+ );
2684
2761
  };
2685
- const RepeatableComponent = ({
2686
- attribute,
2762
+ const DynamicComponent = ({
2763
+ componentUid,
2687
2764
  disabled,
2765
+ index,
2688
2766
  name: name2,
2689
- mainField,
2690
- children,
2691
- layout
2767
+ onRemoveComponentClick,
2768
+ onMoveComponent,
2769
+ onGrabItem,
2770
+ onDropItem,
2771
+ onCancel,
2772
+ dynamicComponentsByCategory = {},
2773
+ onAddComponent,
2774
+ children
2692
2775
  }) => {
2693
- const { toggleNotification } = useNotification();
2694
2776
  const { formatMessage } = useIntl();
2695
- const { search: searchString } = useLocation();
2696
- const search = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
2697
- const { components } = useDoc();
2777
+ const formValues = useForm("DynamicComponent", (state) => state.values);
2698
2778
  const {
2699
- value = [],
2700
- error,
2701
- rawError
2702
- } = useField(name2);
2703
- const addFieldRow = useForm("RepeatableComponent", (state) => state.addFieldRow);
2704
- const moveFieldRow = useForm("RepeatableComponent", (state) => state.moveFieldRow);
2705
- const removeFieldRow = useForm("RepeatableComponent", (state) => state.removeFieldRow);
2706
- const { max = Infinity } = attribute;
2707
- const [collapseToOpen, setCollapseToOpen] = React.useState("");
2708
- const [liveText, setLiveText] = React.useState("");
2709
- React.useEffect(() => {
2710
- const hasNestedErrors = rawError && Array.isArray(rawError) && rawError.length > 0;
2711
- const hasNestedValue = value && Array.isArray(value) && value.length > 0;
2712
- if (hasNestedErrors && hasNestedValue) {
2713
- const errorOpenItems = rawError.map((_, idx) => {
2714
- return value[idx] ? value[idx].__temp_key__ : null;
2715
- }).filter((value2) => !!value2);
2716
- if (errorOpenItems && errorOpenItems.length > 0) {
2717
- setCollapseToOpen((collapseToOpen2) => {
2718
- if (!errorOpenItems.includes(collapseToOpen2)) {
2719
- return errorOpenItems[0];
2720
- }
2721
- return collapseToOpen2;
2722
- });
2723
- }
2779
+ edit: { components }
2780
+ } = useDocLayout();
2781
+ const title = React.useMemo(() => {
2782
+ const { mainField } = components[componentUid]?.settings ?? { mainField: "id" };
2783
+ const mainFieldValue = getIn(formValues, `${name2}.${index}.${mainField}`);
2784
+ const displayedValue = mainField === "id" || !mainFieldValue ? "" : String(mainFieldValue).trim();
2785
+ const mainValue = displayedValue.length > 0 ? `- ${displayedValue}` : displayedValue;
2786
+ return mainValue;
2787
+ }, [componentUid, components, formValues, name2, index]);
2788
+ const { icon, displayName } = React.useMemo(() => {
2789
+ const [category] = componentUid.split(".");
2790
+ const { icon: icon2, displayName: displayName2 } = (dynamicComponentsByCategory[category] ?? []).find(
2791
+ (component) => component.uid === componentUid
2792
+ ) ?? { icon: null, displayName: null };
2793
+ return { icon: icon2, displayName: displayName2 };
2794
+ }, [componentUid, dynamicComponentsByCategory]);
2795
+ const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
2796
+ type: `${ItemTypes.DYNAMIC_ZONE}_${name2}`,
2797
+ index,
2798
+ item: {
2799
+ index,
2800
+ displayedValue: `${displayName} ${title}`,
2801
+ icon
2802
+ },
2803
+ onMoveItem: onMoveComponent,
2804
+ onDropItem,
2805
+ onGrabItem,
2806
+ onCancel
2807
+ });
2808
+ React.useEffect(() => {
2809
+ dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
2810
+ }, [dragPreviewRef, index]);
2811
+ const accordionValue = React.useId();
2812
+ const { value = [], rawError } = useField(`${name2}.${index}`);
2813
+ const [collapseToOpen, setCollapseToOpen] = React.useState("");
2814
+ React.useEffect(() => {
2815
+ if (rawError && value) {
2816
+ setCollapseToOpen(accordionValue);
2724
2817
  }
2725
- }, [rawError, value]);
2726
- const componentTmpKeyWithFocussedField = React.useMemo(() => {
2727
- if (search.has("field")) {
2728
- const fieldParam = search.get("field");
2729
- if (!fieldParam) {
2730
- return void 0;
2818
+ }, [rawError, value, accordionValue]);
2819
+ const composedBoxRefs = useComposedRefs(boxRef, dropRef);
2820
+ const accordionActions = disabled ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
2821
+ /* @__PURE__ */ jsx(
2822
+ IconButton,
2823
+ {
2824
+ variant: "ghost",
2825
+ label: formatMessage(
2826
+ {
2827
+ id: getTranslation("components.DynamicZone.delete-label"),
2828
+ defaultMessage: "Delete {name}"
2829
+ },
2830
+ { name: title }
2831
+ ),
2832
+ onClick: onRemoveComponentClick,
2833
+ children: /* @__PURE__ */ jsx(Trash, {})
2731
2834
  }
2732
- const [, path] = fieldParam.split(`${name2}.`);
2733
- if (getIn(value, path, void 0) !== void 0) {
2734
- const [subpath] = path.split(".");
2735
- return getIn(value, subpath, void 0)?.__temp_key__;
2835
+ ),
2836
+ /* @__PURE__ */ jsx(
2837
+ IconButton,
2838
+ {
2839
+ variant: "ghost",
2840
+ onClick: (e) => e.stopPropagation(),
2841
+ "data-handler-id": handlerId,
2842
+ ref: dragRef,
2843
+ label: formatMessage({
2844
+ id: getTranslation("components.DragHandle-label"),
2845
+ defaultMessage: "Drag"
2846
+ }),
2847
+ onKeyDown: handleKeyDown,
2848
+ children: /* @__PURE__ */ jsx(Drag, {})
2736
2849
  }
2850
+ ),
2851
+ /* @__PURE__ */ jsxs(Menu.Root, { children: [
2852
+ /* @__PURE__ */ jsx(Menu.Trigger, { size: "S", endIcon: null, paddingLeft: 0, paddingRight: 0, children: /* @__PURE__ */ jsx(
2853
+ IconButton,
2854
+ {
2855
+ variant: "ghost",
2856
+ label: formatMessage({
2857
+ id: getTranslation("components.DynamicZone.more-actions"),
2858
+ defaultMessage: "More actions"
2859
+ }),
2860
+ tag: "span",
2861
+ children: /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false })
2862
+ }
2863
+ ) }),
2864
+ /* @__PURE__ */ jsxs(Menu.Content, { children: [
2865
+ /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
2866
+ /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
2867
+ id: getTranslation("components.DynamicZone.add-item-above"),
2868
+ defaultMessage: "Add component above"
2869
+ }) }),
2870
+ /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
2871
+ /* @__PURE__ */ jsx(Menu.Label, { children: category }),
2872
+ components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index), children: displayName2 }, componentUid))
2873
+ ] }, category)) })
2874
+ ] }),
2875
+ /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
2876
+ /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
2877
+ id: getTranslation("components.DynamicZone.add-item-below"),
2878
+ defaultMessage: "Add component below"
2879
+ }) }),
2880
+ /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
2881
+ /* @__PURE__ */ jsx(Menu.Label, { children: category }),
2882
+ components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index + 1), children: displayName2 }, componentUid))
2883
+ ] }, category)) })
2884
+ ] })
2885
+ ] })
2886
+ ] })
2887
+ ] });
2888
+ const accordionTitle = title ? `${displayName} ${title}` : displayName;
2889
+ return /* @__PURE__ */ jsxs(ComponentContainer, { tag: "li", width: "100%", children: [
2890
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Rectangle, { background: "neutral200" }) }),
2891
+ /* @__PURE__ */ jsx(StyledBox, { ref: composedBoxRefs, hasRadius: true, children: isDragging ? /* @__PURE__ */ jsx(Preview$1, {}) : /* @__PURE__ */ jsx(Accordion.Root, { value: collapseToOpen, onValueChange: setCollapseToOpen, children: /* @__PURE__ */ jsxs(Accordion.Item, { value: accordionValue, children: [
2892
+ /* @__PURE__ */ jsxs(Accordion.Header, { children: [
2893
+ /* @__PURE__ */ jsx(
2894
+ Accordion.Trigger,
2895
+ {
2896
+ icon: icon && COMPONENT_ICONS[icon] ? COMPONENT_ICONS[icon] : COMPONENT_ICONS.dashboard,
2897
+ children: accordionTitle
2898
+ }
2899
+ ),
2900
+ /* @__PURE__ */ jsx(Accordion.Actions, { children: accordionActions })
2901
+ ] }),
2902
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(AccordionContentRadius, { background: "neutral0", children: /* @__PURE__ */ jsx(Box, { paddingLeft: 6, paddingRight: 6, paddingTop: 6, paddingBottom: 6, children: /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: components[componentUid]?.layout?.map((row, rowInd) => /* @__PURE__ */ jsx(
2903
+ Grid$1.Item,
2904
+ {
2905
+ col: 12,
2906
+ s: 12,
2907
+ xs: 12,
2908
+ direction: "column",
2909
+ alignItems: "stretch",
2910
+ children: /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
2911
+ const fieldName = `${name2}.${index}.${field.name}`;
2912
+ const fieldWithTranslatedLabel = {
2913
+ ...field,
2914
+ label: formatMessage({
2915
+ id: `content-manager.components.${componentUid}.${field.name}`,
2916
+ defaultMessage: field.label
2917
+ })
2918
+ };
2919
+ return /* @__PURE__ */ jsx(
2920
+ ResponsiveGridItem,
2921
+ {
2922
+ col: size,
2923
+ s: 12,
2924
+ xs: 12,
2925
+ direction: "column",
2926
+ alignItems: "stretch",
2927
+ children: children ? children({ ...fieldWithTranslatedLabel, name: fieldName }) : /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...fieldWithTranslatedLabel, name: fieldName })
2928
+ },
2929
+ fieldName
2930
+ );
2931
+ }) })
2932
+ },
2933
+ rowInd
2934
+ )) }) }) }) })
2935
+ ] }) }) })
2936
+ ] });
2937
+ };
2938
+ const StyledBox = styled(Box)`
2939
+ > div:first-child {
2940
+ box-shadow: ${({ theme }) => theme.shadows.tableShadow};
2941
+ }
2942
+ `;
2943
+ const AccordionContentRadius = styled(Box)`
2944
+ border-radius: 0 0 ${({ theme }) => theme.spaces[1]} ${({ theme }) => theme.spaces[1]};
2945
+ `;
2946
+ const Rectangle = styled(Box)`
2947
+ width: ${({ theme }) => theme.spaces[2]};
2948
+ height: ${({ theme }) => theme.spaces[4]};
2949
+ `;
2950
+ const Preview$1 = styled.span`
2951
+ display: block;
2952
+ background-color: ${({ theme }) => theme.colors.primary100};
2953
+ outline: 1px dashed ${({ theme }) => theme.colors.primary500};
2954
+ outline-offset: -1px;
2955
+ padding: ${({ theme }) => theme.spaces[6]};
2956
+ `;
2957
+ const ComponentContainer = styled(Box)`
2958
+ list-style: none;
2959
+ padding: 0;
2960
+ margin: 0;
2961
+ `;
2962
+ const DynamicZoneLabel = ({
2963
+ hint,
2964
+ label,
2965
+ labelAction,
2966
+ name: name2,
2967
+ numberOfComponents = 0,
2968
+ required
2969
+ }) => {
2970
+ return /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
2971
+ Box,
2972
+ {
2973
+ paddingTop: 3,
2974
+ paddingBottom: 3,
2975
+ paddingRight: 4,
2976
+ paddingLeft: 4,
2977
+ borderRadius: "26px",
2978
+ background: "neutral0",
2979
+ shadow: "filterShadow",
2980
+ color: "neutral500",
2981
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", justifyContent: "center", children: [
2982
+ /* @__PURE__ */ jsxs(Flex, { maxWidth: "35.6rem", children: [
2983
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", ellipsis: true, children: [
2984
+ label || name2,
2985
+ " "
2986
+ ] }),
2987
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", children: [
2988
+ "(",
2989
+ numberOfComponents,
2990
+ ")"
2991
+ ] }),
2992
+ required && /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: "*" }),
2993
+ labelAction && /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: labelAction })
2994
+ ] }),
2995
+ hint && /* @__PURE__ */ jsx(Box, { paddingTop: 1, maxWidth: "35.6rem", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", ellipsis: true, children: hint }) })
2996
+ ] })
2737
2997
  }
2738
- return void 0;
2739
- }, [search, name2, value]);
2740
- const prevValue = usePrev(value);
2741
- React.useEffect(() => {
2742
- if (prevValue && prevValue.length < value.length) {
2743
- setCollapseToOpen(value[value.length - 1].__temp_key__);
2744
- }
2745
- }, [value, prevValue]);
2746
- React.useEffect(() => {
2747
- if (typeof componentTmpKeyWithFocussedField === "string") {
2748
- setCollapseToOpen(componentTmpKeyWithFocussedField);
2749
- }
2750
- }, [componentTmpKeyWithFocussedField]);
2751
- const toggleCollapses = () => {
2752
- setCollapseToOpen("");
2998
+ ) });
2999
+ };
3000
+ const [DynamicZoneProvider, useDynamicZone] = createContext(
3001
+ "DynamicZone",
3002
+ {
3003
+ isInDynamicZone: false
3004
+ }
3005
+ );
3006
+ const DynamicZone = ({
3007
+ attribute,
3008
+ disabled: disabledProp,
3009
+ hint,
3010
+ label,
3011
+ labelAction,
3012
+ name: name2,
3013
+ required = false,
3014
+ children
3015
+ }) => {
3016
+ const { max = Infinity, min = -Infinity } = attribute ?? {};
3017
+ const [addComponentIsOpen, setAddComponentIsOpen] = React.useState(false);
3018
+ const [liveText, setLiveText] = React.useState("");
3019
+ const { components, isLoading } = useDoc();
3020
+ const disabled = disabledProp || isLoading;
3021
+ const { addFieldRow, removeFieldRow, moveFieldRow } = useForm(
3022
+ "DynamicZone",
3023
+ ({ addFieldRow: addFieldRow2, removeFieldRow: removeFieldRow2, moveFieldRow: moveFieldRow2 }) => ({
3024
+ addFieldRow: addFieldRow2,
3025
+ removeFieldRow: removeFieldRow2,
3026
+ moveFieldRow: moveFieldRow2
3027
+ })
3028
+ );
3029
+ const { value = [], error } = useField(name2);
3030
+ const dynamicComponentsByCategory = React.useMemo(() => {
3031
+ return attribute.components.reduce((acc, componentUid) => {
3032
+ const { category, info } = components[componentUid] ?? { info: {} };
3033
+ const component = { uid: componentUid, displayName: info.displayName, icon: info.icon };
3034
+ if (!acc[category]) {
3035
+ acc[category] = [];
3036
+ }
3037
+ acc[category] = [...acc[category], component];
3038
+ return acc;
3039
+ }, {});
3040
+ }, [attribute.components, components]);
3041
+ const { formatMessage } = useIntl();
3042
+ const { toggleNotification } = useNotification();
3043
+ const dynamicDisplayedComponentsLength = value.length;
3044
+ const handleAddComponent = (uid, position) => {
3045
+ setAddComponentIsOpen(false);
3046
+ const schema = components[uid];
3047
+ const form = createDefaultForm(schema, components);
3048
+ const transformations = pipe$1(transformDocument(schema, components), (data2) => ({
3049
+ ...data2,
3050
+ __component: uid
3051
+ }));
3052
+ const data = transformations(form);
3053
+ addFieldRow(name2, data, position);
2753
3054
  };
2754
- const handleClick = () => {
2755
- if (value.length < max) {
2756
- const schema = components[attribute.component];
2757
- const form = createDefaultForm(schema, components);
2758
- const data = transformDocument(schema, components)(form);
2759
- addFieldRow(name2, data);
2760
- } else if (value.length >= max) {
3055
+ const handleClickOpenPicker = () => {
3056
+ if (dynamicDisplayedComponentsLength < max) {
3057
+ setAddComponentIsOpen((prev) => !prev);
3058
+ } else {
2761
3059
  toggleNotification({
2762
3060
  type: "info",
2763
3061
  message: formatMessage({
@@ -2766,7 +3064,7 @@ const RepeatableComponent = ({
2766
3064
  });
2767
3065
  }
2768
3066
  };
2769
- const handleMoveComponentField = (newIndex, currentIndex) => {
3067
+ const handleMoveComponent = (newIndex, currentIndex) => {
2770
3068
  setLiveText(
2771
3069
  formatMessage(
2772
3070
  {
@@ -2781,9 +3079,6 @@ const RepeatableComponent = ({
2781
3079
  );
2782
3080
  moveFieldRow(name2, currentIndex, newIndex);
2783
3081
  };
2784
- const handleValueChange = (key) => {
2785
- setCollapseToOpen(key);
2786
- };
2787
3082
  const getItemPos = (index) => `${index + 1} of ${value.length}`;
2788
3083
  const handleCancel = (index) => {
2789
3084
  setLiveText(
@@ -2816,446 +3111,119 @@ const RepeatableComponent = ({
2816
3111
  setLiveText(
2817
3112
  formatMessage(
2818
3113
  {
2819
- id: getTranslation("dnd.drop-item"),
2820
- defaultMessage: `{item}, dropped. Final position in list: {position}.`
2821
- },
2822
- {
2823
- item: `${name2}.${index}`,
2824
- position: getItemPos(index)
2825
- }
2826
- )
2827
- );
2828
- };
2829
- const ariaDescriptionId = React.useId();
2830
- const level = useComponent("RepeatableComponent", (state) => state.level);
2831
- if (value.length === 0) {
2832
- return /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleClick });
2833
- }
2834
- return /* @__PURE__ */ jsxs(Box, { hasRadius: true, children: [
2835
- /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
2836
- id: getTranslation("dnd.instructions"),
2837
- defaultMessage: `Press spacebar to grab and re-order`
2838
- }) }),
2839
- /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
2840
- /* @__PURE__ */ jsxs(
2841
- AccordionRoot,
2842
- {
2843
- $error: error,
2844
- value: collapseToOpen,
2845
- onValueChange: handleValueChange,
2846
- "aria-describedby": ariaDescriptionId,
2847
- children: [
2848
- value.map(({ __temp_key__: key, id }, index) => {
2849
- const nameWithIndex = `${name2}.${index}`;
2850
- return /* @__PURE__ */ jsx(
2851
- ComponentProvider,
2852
- {
2853
- id,
2854
- uid: attribute.component,
2855
- level: level + 1,
2856
- type: "repeatable",
2857
- children: /* @__PURE__ */ jsx(
2858
- Component,
2859
- {
2860
- disabled,
2861
- name: nameWithIndex,
2862
- attribute,
2863
- index,
2864
- mainField,
2865
- onMoveItem: handleMoveComponentField,
2866
- onDeleteComponent: () => {
2867
- removeFieldRow(name2, index);
2868
- toggleCollapses();
2869
- },
2870
- toggleCollapses,
2871
- onCancel: handleCancel,
2872
- onDropItem: handleDropItem,
2873
- onGrabItem: handleGrabItem,
2874
- __temp_key__: key,
2875
- children: layout.map((row, index2) => {
2876
- return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
2877
- const completeFieldName = `${nameWithIndex}.${field.name}`;
2878
- const translatedLabel = formatMessage({
2879
- id: `content-manager.components.${attribute.component}.${field.name}`,
2880
- defaultMessage: field.label
2881
- });
2882
- return /* @__PURE__ */ jsx(
2883
- Grid$1.Item,
2884
- {
2885
- col: size,
2886
- s: 12,
2887
- xs: 12,
2888
- direction: "column",
2889
- alignItems: "stretch",
2890
- children: children({
2891
- ...field,
2892
- label: translatedLabel,
2893
- name: completeFieldName
2894
- })
2895
- },
2896
- completeFieldName
2897
- );
2898
- }) }, index2);
2899
- })
2900
- }
2901
- )
2902
- },
2903
- key
2904
- );
2905
- }),
2906
- /* @__PURE__ */ jsx(TextButtonCustom, { disabled, onClick: handleClick, startIcon: /* @__PURE__ */ jsx(Plus, {}), children: formatMessage({
2907
- id: getTranslation("containers.EditView.add.new-entry"),
2908
- defaultMessage: "Add an entry"
2909
- }) })
2910
- ]
2911
- }
2912
- )
2913
- ] });
2914
- };
2915
- const AccordionRoot = styled(Accordion.Root)`
2916
- border: 1px solid
2917
- ${({ theme, $error }) => $error ? theme.colors.danger600 : theme.colors.neutral200};
2918
- `;
2919
- const TextButtonCustom = styled(TextButton)`
2920
- width: 100%;
2921
- display: flex;
2922
- justify-content: center;
2923
- border-top: 1px solid ${({ theme }) => theme.colors.neutral200};
2924
- padding-inline: ${(props) => props.theme.spaces[6]};
2925
- padding-block: ${(props) => props.theme.spaces[3]};
2926
-
2927
- &:not([disabled]) {
2928
- cursor: pointer;
2929
-
2930
- &:hover {
2931
- background-color: ${(props) => props.theme.colors.primary100};
2932
- }
2933
- }
2934
-
2935
- span {
2936
- font-weight: 600;
2937
- font-size: 1.4rem;
2938
- line-height: 2.4rem;
2939
- }
2940
-
2941
- @media (prefers-reduced-motion: no-preference) {
2942
- transition: background-color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
2943
- }
2944
- `;
2945
- const Component = ({
2946
- disabled,
2947
- index,
2948
- name: name2,
2949
- mainField = {
2950
- name: "id",
2951
- type: "integer"
2952
- },
2953
- children,
2954
- onDeleteComponent,
2955
- toggleCollapses,
2956
- __temp_key__,
2957
- ...dragProps
2958
- }) => {
2959
- const { formatMessage } = useIntl();
2960
- const displayValue = useForm("RepeatableComponent", (state) => {
2961
- return getIn(state.values, [...name2.split("."), mainField.name]);
2962
- });
2963
- const accordionRef = React.useRef(null);
2964
- const componentKey = name2.split(".").slice(0, -1).join(".");
2965
- const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
2966
- type: `${ItemTypes.COMPONENT}_${componentKey}`,
2967
- index,
2968
- item: {
2969
- index,
2970
- displayedValue: displayValue
2971
- },
2972
- onStart() {
2973
- toggleCollapses();
2974
- },
2975
- ...dragProps
2976
- });
2977
- React.useEffect(() => {
2978
- dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
2979
- }, [dragPreviewRef, index]);
2980
- const composedAccordionRefs = useComposedRefs(accordionRef, dragRef);
2981
- const composedBoxRefs = useComposedRefs(
2982
- boxRef,
2983
- dropRef
2984
- );
2985
- return /* @__PURE__ */ jsx(Fragment, { children: isDragging ? /* @__PURE__ */ jsx(Preview$1, {}) : /* @__PURE__ */ jsxs(Accordion.Item, { ref: composedBoxRefs, value: __temp_key__, children: [
2986
- /* @__PURE__ */ jsxs(Accordion.Header, { children: [
2987
- /* @__PURE__ */ jsx(Accordion.Trigger, { children: displayValue }),
2988
- /* @__PURE__ */ jsxs(Accordion.Actions, { children: [
2989
- /* @__PURE__ */ jsx(
2990
- IconButton,
2991
- {
2992
- variant: "ghost",
2993
- onClick: onDeleteComponent,
2994
- label: formatMessage({
2995
- id: getTranslation("containers.Edit.delete"),
2996
- defaultMessage: "Delete"
2997
- }),
2998
- children: /* @__PURE__ */ jsx(Trash, {})
2999
- }
3000
- ),
3001
- /* @__PURE__ */ jsx(
3002
- IconButton,
3003
- {
3004
- ref: composedAccordionRefs,
3005
- variant: "ghost",
3006
- onClick: (e) => e.stopPropagation(),
3007
- "data-handler-id": handlerId,
3008
- label: formatMessage({
3009
- id: getTranslation("components.DragHandle-label"),
3010
- defaultMessage: "Drag"
3011
- }),
3012
- onKeyDown: handleKeyDown,
3013
- children: /* @__PURE__ */ jsx(Drag, {})
3014
- }
3015
- )
3016
- ] })
3017
- ] }),
3018
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(
3019
- Flex,
3020
- {
3021
- direction: "column",
3022
- alignItems: "stretch",
3023
- background: "neutral100",
3024
- padding: 6,
3025
- gap: 6,
3026
- children
3027
- }
3028
- ) })
3029
- ] }) });
3030
- };
3031
- const Preview$1 = () => {
3032
- return /* @__PURE__ */ jsx(StyledSpan, { tag: "span", padding: 6, background: "primary100" });
3033
- };
3034
- const StyledSpan = styled(Box)`
3035
- display: block;
3036
- outline: 1px dashed ${({ theme }) => theme.colors.primary500};
3037
- outline-offset: -1px;
3038
- `;
3039
- const ComponentInput = ({
3040
- label,
3041
- required,
3042
- name: name2,
3043
- attribute,
3044
- disabled,
3045
- labelAction,
3046
- ...props
3047
- }) => {
3048
- const { formatMessage } = useIntl();
3049
- const field = useField(name2);
3050
- const showResetComponent = !attribute.repeatable && field.value && !disabled;
3051
- const { components } = useDoc();
3052
- const handleInitialisationClick = () => {
3053
- const schema = components[attribute.component];
3054
- const form = createDefaultForm(schema, components);
3055
- const data = transformDocument(schema, components)(form);
3056
- field.onChange(name2, data);
3057
- };
3058
- return /* @__PURE__ */ jsxs(Field.Root, { error: field.error, required, children: [
3059
- /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3060
- /* @__PURE__ */ jsxs(Field.Label, { action: labelAction, children: [
3061
- label,
3062
- attribute.repeatable && /* @__PURE__ */ jsxs(Fragment, { children: [
3063
- " (",
3064
- Array.isArray(field.value) ? field.value.length : 0,
3065
- ")"
3066
- ] })
3067
- ] }),
3068
- showResetComponent && /* @__PURE__ */ jsx(
3069
- IconButton,
3070
- {
3071
- label: formatMessage({
3072
- id: getTranslation("components.reset-entry"),
3073
- defaultMessage: "Reset Entry"
3074
- }),
3075
- variant: "ghost",
3076
- onClick: () => {
3077
- field.onChange(name2, null);
3078
- },
3079
- children: /* @__PURE__ */ jsx(Trash, {})
3114
+ id: getTranslation("dnd.drop-item"),
3115
+ defaultMessage: `{item}, dropped. Final position in list: {position}.`
3116
+ },
3117
+ {
3118
+ item: `${name2}.${index}`,
3119
+ position: getItemPos(index)
3080
3120
  }
3081
3121
  )
3082
- ] }),
3083
- !attribute.repeatable && !field.value && /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleInitialisationClick }),
3084
- !attribute.repeatable && field.value ? /* @__PURE__ */ jsx(NonRepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }) : null,
3085
- attribute.repeatable && /* @__PURE__ */ jsx(RepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }),
3086
- /* @__PURE__ */ jsx(Field.Error, {})
3087
- ] });
3088
- };
3089
- const MemoizedComponentInput = React.memo(ComponentInput);
3090
- const AddComponentButton = ({
3091
- hasError,
3092
- isDisabled,
3093
- isOpen,
3094
- children,
3095
- onClick
3096
- }) => {
3097
- return /* @__PURE__ */ jsx(
3098
- StyledButton,
3099
- {
3100
- type: "button",
3101
- onClick,
3102
- disabled: isDisabled,
3103
- background: "neutral0",
3104
- style: { cursor: isDisabled ? "not-allowed" : "pointer" },
3105
- variant: "tertiary",
3106
- children: /* @__PURE__ */ jsxs(Flex, { tag: "span", gap: 2, children: [
3107
- /* @__PURE__ */ jsx(StyledAddIcon, { "aria-hidden": true, $isOpen: isOpen, $hasError: hasError && !isOpen }),
3108
- /* @__PURE__ */ jsx(
3109
- AddComponentTitle,
3110
- {
3111
- variant: "pi",
3112
- fontWeight: "bold",
3113
- textColor: hasError && !isOpen ? "danger600" : "neutral500",
3114
- children
3115
- }
3116
- )
3117
- ] })
3118
- }
3119
- );
3120
- };
3121
- const StyledAddIcon = styled(PlusCircle)`
3122
- height: ${({ theme }) => theme.spaces[6]};
3123
- width: ${({ theme }) => theme.spaces[6]};
3124
- transform: ${({ $isOpen }) => $isOpen ? "rotate(45deg)" : "rotate(0deg)"};
3125
-
3126
- > circle {
3127
- fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger200 : theme.colors.neutral150};
3128
- }
3129
- > path {
3130
- fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger600 : theme.colors.neutral600};
3131
- }
3132
- `;
3133
- const AddComponentTitle = styled(Typography)``;
3134
- const StyledButton = styled(Button)`
3135
- border-radius: 26px;
3136
- border-color: ${({ theme }) => theme.colors.neutral150};
3137
- box-shadow: ${({ theme }) => theme.shadows.filterShadow};
3138
- height: 5rem;
3139
-
3140
- &:hover {
3141
- ${AddComponentTitle} {
3142
- color: ${({ theme }) => theme.colors.primary600};
3143
- }
3144
-
3145
- ${StyledAddIcon} {
3146
- > circle {
3147
- fill: ${({ theme }) => theme.colors.primary600};
3148
- }
3149
- > path {
3150
- fill: ${({ theme }) => theme.colors.primary600};
3151
- }
3122
+ );
3123
+ };
3124
+ const handleRemoveComponent = (name22, currentIndex) => () => {
3125
+ removeFieldRow(name22, currentIndex);
3126
+ };
3127
+ const hasError = error !== void 0;
3128
+ const renderButtonLabel = () => {
3129
+ if (addComponentIsOpen) {
3130
+ return formatMessage({ id: "app.utils.close-label", defaultMessage: "Close" });
3152
3131
  }
3153
- }
3154
- &:active {
3155
- ${AddComponentTitle} {
3156
- color: ${({ theme }) => theme.colors.primary600};
3132
+ if (hasError && dynamicDisplayedComponentsLength > max) {
3133
+ return formatMessage(
3134
+ {
3135
+ id: getTranslation(`components.DynamicZone.extra-components`),
3136
+ defaultMessage: "There {number, plural, =0 {are # extra components} one {is # extra component} other {are # extra components}}"
3137
+ },
3138
+ {
3139
+ number: dynamicDisplayedComponentsLength - max
3140
+ }
3141
+ );
3157
3142
  }
3158
- ${StyledAddIcon} {
3159
- > circle {
3160
- fill: ${({ theme }) => theme.colors.primary600};
3161
- }
3162
- > path {
3163
- fill: ${({ theme }) => theme.colors.neutral100};
3164
- }
3143
+ if (hasError && dynamicDisplayedComponentsLength < min) {
3144
+ return formatMessage(
3145
+ {
3146
+ id: getTranslation(`components.DynamicZone.missing-components`),
3147
+ defaultMessage: "There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}"
3148
+ },
3149
+ { number: min - dynamicDisplayedComponentsLength }
3150
+ );
3165
3151
  }
3166
- }
3167
- `;
3168
- const ComponentCategory = ({
3169
- category,
3170
- components = [],
3171
- variant = "primary",
3172
- onAddComponent
3173
- }) => {
3174
- const { formatMessage } = useIntl();
3175
- return /* @__PURE__ */ jsxs(Accordion.Item, { value: category, children: [
3176
- /* @__PURE__ */ jsx(Accordion.Header, { variant, children: /* @__PURE__ */ jsx(Accordion.Trigger, { children: formatMessage({ id: category, defaultMessage: category }) }) }),
3177
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Grid, { paddingTop: 4, paddingBottom: 4, paddingLeft: 3, paddingRight: 3, children: components.map(({ uid, displayName, icon }) => /* @__PURE__ */ jsx(
3178
- ComponentBox,
3152
+ return formatMessage(
3179
3153
  {
3180
- tag: "button",
3181
- type: "button",
3182
- background: "neutral100",
3183
- justifyContent: "center",
3184
- onClick: onAddComponent(uid),
3185
- hasRadius: true,
3186
- height: "8.4rem",
3187
- shrink: 0,
3188
- borderColor: "neutral200",
3189
- children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, alignItems: "center", justifyContent: "center", children: [
3190
- /* @__PURE__ */ jsx(ComponentIcon, { color: "currentColor", background: "primary200", icon }),
3191
- /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: displayName })
3192
- ] })
3154
+ id: getTranslation("components.DynamicZone.add-component"),
3155
+ defaultMessage: "Add a component to {componentName}"
3193
3156
  },
3194
- uid
3195
- )) }) })
3196
- ] });
3197
- };
3198
- const Grid = styled(Box)`
3199
- display: grid;
3200
- grid-template-columns: repeat(auto-fit, 14rem);
3201
- grid-gap: ${({ theme }) => theme.spaces[1]};
3202
- `;
3203
- const ComponentBox = styled(Flex)`
3204
- color: ${({ theme }) => theme.colors.neutral600};
3205
- cursor: pointer;
3206
-
3207
- @media (prefers-reduced-motion: no-preference) {
3208
- transition: color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
3209
- }
3210
-
3211
- &:focus,
3212
- &:hover {
3213
- border: 1px solid ${({ theme }) => theme.colors.primary200};
3214
- background: ${({ theme }) => theme.colors.primary100};
3215
- color: ${({ theme }) => theme.colors.primary600};
3216
- }
3217
- `;
3218
- const ComponentPicker = ({
3219
- dynamicComponentsByCategory = {},
3220
- isOpen,
3221
- onClickAddComponent
3222
- }) => {
3223
- const { formatMessage } = useIntl();
3224
- const handleAddComponentToDz = (componentUid) => () => {
3225
- onClickAddComponent(componentUid);
3157
+ { componentName: label || name2 }
3158
+ );
3226
3159
  };
3227
- if (!isOpen) {
3228
- return null;
3229
- }
3230
- return /* @__PURE__ */ jsxs(
3231
- Box,
3232
- {
3233
- paddingTop: 6,
3234
- paddingBottom: 6,
3235
- paddingLeft: 5,
3236
- paddingRight: 5,
3237
- background: "neutral0",
3238
- shadow: "tableShadow",
3239
- borderColor: "neutral150",
3240
- hasRadius: true,
3241
- children: [
3242
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral600", children: formatMessage({
3243
- id: getTranslation("components.DynamicZone.ComponentPicker-label"),
3244
- defaultMessage: "Pick one component"
3245
- }) }) }),
3246
- /* @__PURE__ */ jsx(Box, { paddingTop: 2, children: /* @__PURE__ */ jsx(Accordion.Root, { defaultValue: Object.keys(dynamicComponentsByCategory)[0], children: Object.entries(dynamicComponentsByCategory).map(([category, components], index) => /* @__PURE__ */ jsx(
3247
- ComponentCategory,
3248
- {
3249
- category,
3250
- components,
3251
- onAddComponent: handleAddComponentToDz,
3252
- variant: index % 2 === 1 ? "primary" : "secondary"
3253
- },
3254
- category
3255
- )) }) })
3256
- ]
3257
- }
3258
- );
3160
+ const level = useComponent("DynamicZone", (state) => state.level);
3161
+ const ariaDescriptionId = React.useId();
3162
+ return /* @__PURE__ */ jsx(DynamicZoneProvider, { isInDynamicZone: true, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
3163
+ dynamicDisplayedComponentsLength > 0 && /* @__PURE__ */ jsxs(Box, { children: [
3164
+ /* @__PURE__ */ jsx(
3165
+ DynamicZoneLabel,
3166
+ {
3167
+ hint,
3168
+ label,
3169
+ labelAction,
3170
+ name: name2,
3171
+ numberOfComponents: dynamicDisplayedComponentsLength,
3172
+ required
3173
+ }
3174
+ ),
3175
+ /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
3176
+ id: getTranslation("dnd.instructions"),
3177
+ defaultMessage: `Press spacebar to grab and re-order`
3178
+ }) }),
3179
+ /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
3180
+ /* @__PURE__ */ jsx("ol", { "aria-describedby": ariaDescriptionId, children: value.map((field, index) => /* @__PURE__ */ jsx(
3181
+ ComponentProvider,
3182
+ {
3183
+ level: level + 1,
3184
+ uid: field.__component,
3185
+ id: field.id,
3186
+ type: "dynamiczone",
3187
+ children: /* @__PURE__ */ jsx(
3188
+ DynamicComponent,
3189
+ {
3190
+ disabled,
3191
+ name: name2,
3192
+ index,
3193
+ componentUid: field.__component,
3194
+ onMoveComponent: handleMoveComponent,
3195
+ onRemoveComponentClick: handleRemoveComponent(name2, index),
3196
+ onCancel: handleCancel,
3197
+ onDropItem: handleDropItem,
3198
+ onGrabItem: handleGrabItem,
3199
+ onAddComponent: handleAddComponent,
3200
+ dynamicComponentsByCategory,
3201
+ children
3202
+ }
3203
+ )
3204
+ },
3205
+ field.__temp_key__
3206
+ )) })
3207
+ ] }),
3208
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
3209
+ AddComponentButton,
3210
+ {
3211
+ hasError,
3212
+ isDisabled: disabled,
3213
+ isOpen: addComponentIsOpen,
3214
+ onClick: handleClickOpenPicker,
3215
+ children: renderButtonLabel()
3216
+ }
3217
+ ) }),
3218
+ /* @__PURE__ */ jsx(
3219
+ ComponentPicker,
3220
+ {
3221
+ dynamicComponentsByCategory,
3222
+ isOpen: addComponentIsOpen,
3223
+ onClickAddComponent: handleAddComponent
3224
+ }
3225
+ )
3226
+ ] }) });
3259
3227
  };
3260
3228
  const NotAllowedInput = ({ hint, label, required, name: name2 }) => {
3261
3229
  const { formatMessage } = useIntl();
@@ -4997,567 +4965,621 @@ const InputRenderer = ({ visible, hint: providedHint, ...props }) => {
4997
4965
  return /* @__PURE__ */ jsx(
4998
4966
  MemoizedComponentInput,
4999
4967
  {
5000
- ...props,
5001
- hint,
5002
- layout: components[props.attribute.component].layout,
5003
- disabled: fieldIsDisabled,
5004
- children: (inputProps) => /* @__PURE__ */ jsx(InputRenderer, { ...inputProps })
4968
+ ...props,
4969
+ hint,
4970
+ layout: components[props.attribute.component].layout,
4971
+ disabled: fieldIsDisabled,
4972
+ children: (inputProps) => /* @__PURE__ */ jsx(InputRenderer, { ...inputProps })
4973
+ }
4974
+ );
4975
+ case "dynamiczone":
4976
+ return /* @__PURE__ */ jsx(DynamicZone, { ...props, hint, disabled: fieldIsDisabled });
4977
+ case "relation":
4978
+ return /* @__PURE__ */ jsx(MemoizedRelationsField, { ...props, hint, disabled: fieldIsDisabled });
4979
+ case "richtext":
4980
+ return /* @__PURE__ */ jsx(MemoizedWysiwyg, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4981
+ case "uid":
4982
+ return /* @__PURE__ */ jsx(MemoizedUIDInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4983
+ case "enumeration":
4984
+ return /* @__PURE__ */ jsx(
4985
+ InputRenderer$1,
4986
+ {
4987
+ ...props,
4988
+ hint,
4989
+ options: props.attribute.enum.map((value) => ({ value })),
4990
+ type: props.customField ? "custom-field" : props.type,
4991
+ disabled: fieldIsDisabled
4992
+ }
4993
+ );
4994
+ default:
4995
+ const { unique: _unique, mainField: _mainField, ...restProps } = props;
4996
+ return /* @__PURE__ */ jsx(
4997
+ InputRenderer$1,
4998
+ {
4999
+ ...restProps,
5000
+ hint,
5001
+ type: props.customField ? "custom-field" : props.type,
5002
+ disabled: fieldIsDisabled
5003
+ }
5004
+ );
5005
+ }
5006
+ };
5007
+ const attributeHasCustomFieldProperty = (attribute) => "customField" in attribute && typeof attribute.customField === "string";
5008
+ const useFieldHint = (hint = void 0, attribute) => {
5009
+ const { formatMessage } = useIntl();
5010
+ const { maximum, minimum } = getMinMax(attribute);
5011
+ if (!maximum && !minimum) {
5012
+ return hint;
5013
+ }
5014
+ const units = !["biginteger", "integer", "number", "dynamiczone", "component"].includes(
5015
+ attribute.type
5016
+ ) ? formatMessage(
5017
+ {
5018
+ id: "content-manager.form.Input.hint.character.unit",
5019
+ defaultMessage: "{maxValue, plural, one { character} other { characters}}"
5020
+ },
5021
+ {
5022
+ maxValue: Math.max(minimum || 0, maximum || 0)
5023
+ }
5024
+ ) : null;
5025
+ const hasMinAndMax = typeof minimum === "number" && typeof maximum === "number";
5026
+ return formatMessage(
5027
+ {
5028
+ id: "content-manager.form.Input.hint.text",
5029
+ defaultMessage: "{min, select, undefined {} other {min. {min}}}{divider}{max, select, undefined {} other {max. {max}}}{unit}{br}{description}"
5030
+ },
5031
+ {
5032
+ min: minimum,
5033
+ max: maximum,
5034
+ description: hint,
5035
+ unit: units,
5036
+ divider: hasMinAndMax ? formatMessage({
5037
+ id: "content-manager.form.Input.hint.minMaxDivider",
5038
+ defaultMessage: " / "
5039
+ }) : null,
5040
+ br: /* @__PURE__ */ jsx("br", {})
5041
+ }
5042
+ );
5043
+ };
5044
+ const getMinMax = (attribute) => {
5045
+ if ("min" in attribute || "max" in attribute) {
5046
+ return {
5047
+ maximum: !Number.isNaN(Number(attribute.max)) ? Number(attribute.max) : void 0,
5048
+ minimum: !Number.isNaN(Number(attribute.min)) ? Number(attribute.min) : void 0
5049
+ };
5050
+ } else if ("maxLength" in attribute || "minLength" in attribute) {
5051
+ return { maximum: attribute.maxLength, minimum: attribute.minLength };
5052
+ } else {
5053
+ return { maximum: void 0, minimum: void 0 };
5054
+ }
5055
+ };
5056
+ const MemoizedInputRenderer = memo(InputRenderer);
5057
+ const RESPONSIVE_CONTAINER_BREAKPOINTS = {
5058
+ sm: "27.5rem"
5059
+ // 440px
5060
+ };
5061
+ const ResponsiveGridRoot = styled(Grid$1.Root)`
5062
+ container-type: inline-size;
5063
+ `;
5064
+ const ResponsiveGridItem = styled(Grid$1.Item)`
5065
+ grid-column: span 12;
5066
+
5067
+ @container (min-width: ${RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
5068
+ ${({ col }) => col && `grid-column: span ${col};`}
5069
+ }
5070
+ `;
5071
+ const FormLayout = ({ layout }) => {
5072
+ const { formatMessage } = useIntl();
5073
+ const { model } = useDoc();
5074
+ return /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: layout.map((panel, index) => {
5075
+ if (panel.some((row) => row.some((field) => field.type === "dynamiczone"))) {
5076
+ const [row] = panel;
5077
+ const [field] = row;
5078
+ const fieldWithTranslatedLabel = {
5079
+ ...field,
5080
+ label: formatMessage({
5081
+ id: `content-manager.content-types.${model}.${field.name}`,
5082
+ defaultMessage: field.label
5083
+ })
5084
+ };
5085
+ return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: /* @__PURE__ */ jsx(Grid$1.Item, { col: 12, s: 12, xs: 12, direction: "column", alignItems: "stretch", children: /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...fieldWithTranslatedLabel }) }) }, field.name);
5086
+ }
5087
+ return /* @__PURE__ */ jsx(
5088
+ Box,
5089
+ {
5090
+ hasRadius: true,
5091
+ background: "neutral0",
5092
+ shadow: "tableShadow",
5093
+ paddingLeft: 6,
5094
+ paddingRight: 6,
5095
+ paddingTop: 6,
5096
+ paddingBottom: 6,
5097
+ borderColor: "neutral150",
5098
+ children: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: panel.map((row, gridRowIndex) => /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
5099
+ const fieldWithTranslatedLabel = {
5100
+ ...field,
5101
+ label: formatMessage({
5102
+ id: `content-manager.content-types.${model}.${field.name}`,
5103
+ defaultMessage: field.label
5104
+ })
5105
+ };
5106
+ return /* @__PURE__ */ jsx(
5107
+ ResponsiveGridItem,
5108
+ {
5109
+ col: size,
5110
+ s: 12,
5111
+ xs: 12,
5112
+ direction: "column",
5113
+ alignItems: "stretch",
5114
+ children: /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...fieldWithTranslatedLabel })
5115
+ },
5116
+ field.name
5117
+ );
5118
+ }) }, gridRowIndex)) })
5119
+ },
5120
+ index
5121
+ );
5122
+ }) });
5123
+ };
5124
+ const NonRepeatableComponent = ({
5125
+ attribute,
5126
+ name: name2,
5127
+ children,
5128
+ layout
5129
+ }) => {
5130
+ const { formatMessage } = useIntl();
5131
+ const { value } = useField(name2);
5132
+ const level = useComponent("NonRepeatableComponent", (state) => state.level);
5133
+ const isNested = level > 0;
5134
+ return /* @__PURE__ */ jsx(ComponentProvider, { id: value?.id, uid: attribute.component, level: level + 1, type: "component", children: /* @__PURE__ */ jsx(
5135
+ Box,
5136
+ {
5137
+ background: "neutral100",
5138
+ paddingLeft: 6,
5139
+ paddingRight: 6,
5140
+ paddingTop: 6,
5141
+ paddingBottom: 6,
5142
+ hasRadius: isNested,
5143
+ borderColor: isNested ? "neutral200" : void 0,
5144
+ children: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: layout.map((row, index) => {
5145
+ return /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
5146
+ const completeFieldName = `${name2}.${field.name}`;
5147
+ const translatedLabel = formatMessage({
5148
+ id: `content-manager.components.${attribute.component}.${field.name}`,
5149
+ defaultMessage: field.label
5150
+ });
5151
+ return /* @__PURE__ */ jsx(
5152
+ ResponsiveGridItem,
5153
+ {
5154
+ col: size,
5155
+ s: 12,
5156
+ xs: 12,
5157
+ direction: "column",
5158
+ alignItems: "stretch",
5159
+ children: children({ ...field, label: translatedLabel, name: completeFieldName })
5160
+ },
5161
+ completeFieldName
5162
+ );
5163
+ }) }, index);
5164
+ }) })
5165
+ }
5166
+ ) });
5167
+ };
5168
+ const RepeatableComponent = ({
5169
+ attribute,
5170
+ disabled,
5171
+ name: name2,
5172
+ mainField,
5173
+ children,
5174
+ layout
5175
+ }) => {
5176
+ const { toggleNotification } = useNotification();
5177
+ const { formatMessage } = useIntl();
5178
+ const { search: searchString } = useLocation();
5179
+ const search = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
5180
+ const { components } = useDoc();
5181
+ const {
5182
+ value = [],
5183
+ error,
5184
+ rawError
5185
+ } = useField(name2);
5186
+ const addFieldRow = useForm("RepeatableComponent", (state) => state.addFieldRow);
5187
+ const moveFieldRow = useForm("RepeatableComponent", (state) => state.moveFieldRow);
5188
+ const removeFieldRow = useForm("RepeatableComponent", (state) => state.removeFieldRow);
5189
+ const { max = Infinity } = attribute;
5190
+ const [collapseToOpen, setCollapseToOpen] = React.useState("");
5191
+ const [liveText, setLiveText] = React.useState("");
5192
+ React.useEffect(() => {
5193
+ const hasNestedErrors = rawError && Array.isArray(rawError) && rawError.length > 0;
5194
+ const hasNestedValue = value && Array.isArray(value) && value.length > 0;
5195
+ if (hasNestedErrors && hasNestedValue) {
5196
+ const errorOpenItems = rawError.map((_, idx) => {
5197
+ return value[idx] ? value[idx].__temp_key__ : null;
5198
+ }).filter((value2) => !!value2);
5199
+ if (errorOpenItems && errorOpenItems.length > 0) {
5200
+ setCollapseToOpen((collapseToOpen2) => {
5201
+ if (!errorOpenItems.includes(collapseToOpen2)) {
5202
+ return errorOpenItems[0];
5203
+ }
5204
+ return collapseToOpen2;
5205
+ });
5206
+ }
5207
+ }
5208
+ }, [rawError, value]);
5209
+ const componentTmpKeyWithFocussedField = React.useMemo(() => {
5210
+ if (search.has("field")) {
5211
+ const fieldParam = search.get("field");
5212
+ if (!fieldParam) {
5213
+ return void 0;
5214
+ }
5215
+ const [, path] = fieldParam.split(`${name2}.`);
5216
+ if (getIn(value, path, void 0) !== void 0) {
5217
+ const [subpath] = path.split(".");
5218
+ return getIn(value, subpath, void 0)?.__temp_key__;
5219
+ }
5220
+ }
5221
+ return void 0;
5222
+ }, [search, name2, value]);
5223
+ const prevValue = usePrev(value);
5224
+ React.useEffect(() => {
5225
+ if (prevValue && prevValue.length < value.length) {
5226
+ setCollapseToOpen(value[value.length - 1].__temp_key__);
5227
+ }
5228
+ }, [value, prevValue]);
5229
+ React.useEffect(() => {
5230
+ if (typeof componentTmpKeyWithFocussedField === "string") {
5231
+ setCollapseToOpen(componentTmpKeyWithFocussedField);
5232
+ }
5233
+ }, [componentTmpKeyWithFocussedField]);
5234
+ const toggleCollapses = () => {
5235
+ setCollapseToOpen("");
5236
+ };
5237
+ const handleClick = () => {
5238
+ if (value.length < max) {
5239
+ const schema = components[attribute.component];
5240
+ const form = createDefaultForm(schema, components);
5241
+ const data = transformDocument(schema, components)(form);
5242
+ addFieldRow(name2, data);
5243
+ } else if (value.length >= max) {
5244
+ toggleNotification({
5245
+ type: "info",
5246
+ message: formatMessage({
5247
+ id: getTranslation("components.notification.info.maximum-requirement")
5248
+ })
5249
+ });
5250
+ }
5251
+ };
5252
+ const handleMoveComponentField = (newIndex, currentIndex) => {
5253
+ setLiveText(
5254
+ formatMessage(
5255
+ {
5256
+ id: getTranslation("dnd.reorder"),
5257
+ defaultMessage: "{item}, moved. New position in list: {position}."
5258
+ },
5259
+ {
5260
+ item: `${name2}.${currentIndex}`,
5261
+ position: getItemPos(newIndex)
5005
5262
  }
5006
- );
5007
- case "dynamiczone":
5008
- return /* @__PURE__ */ jsx(DynamicZone, { ...props, hint, disabled: fieldIsDisabled });
5009
- case "relation":
5010
- return /* @__PURE__ */ jsx(MemoizedRelationsField, { ...props, hint, disabled: fieldIsDisabled });
5011
- case "richtext":
5012
- return /* @__PURE__ */ jsx(MemoizedWysiwyg, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
5013
- case "uid":
5014
- return /* @__PURE__ */ jsx(MemoizedUIDInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
5015
- case "enumeration":
5016
- return /* @__PURE__ */ jsx(
5017
- InputRenderer$1,
5263
+ )
5264
+ );
5265
+ moveFieldRow(name2, currentIndex, newIndex);
5266
+ };
5267
+ const handleValueChange = (key) => {
5268
+ setCollapseToOpen(key);
5269
+ };
5270
+ const getItemPos = (index) => `${index + 1} of ${value.length}`;
5271
+ const handleCancel = (index) => {
5272
+ setLiveText(
5273
+ formatMessage(
5018
5274
  {
5019
- ...props,
5020
- hint,
5021
- options: props.attribute.enum.map((value) => ({ value })),
5022
- type: props.customField ? "custom-field" : props.type,
5023
- disabled: fieldIsDisabled
5275
+ id: getTranslation("dnd.cancel-item"),
5276
+ defaultMessage: "{item}, dropped. Re-order cancelled."
5277
+ },
5278
+ {
5279
+ item: `${name2}.${index}`
5024
5280
  }
5025
- );
5026
- default:
5027
- const { unique: _unique, mainField: _mainField, ...restProps } = props;
5028
- return /* @__PURE__ */ jsx(
5029
- InputRenderer$1,
5281
+ )
5282
+ );
5283
+ };
5284
+ const handleGrabItem = (index) => {
5285
+ setLiveText(
5286
+ formatMessage(
5030
5287
  {
5031
- ...restProps,
5032
- hint,
5033
- type: props.customField ? "custom-field" : props.type,
5034
- disabled: fieldIsDisabled
5288
+ id: getTranslation("dnd.grab-item"),
5289
+ defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
5290
+ },
5291
+ {
5292
+ item: `${name2}.${index}`,
5293
+ position: getItemPos(index)
5035
5294
  }
5036
- );
5295
+ )
5296
+ );
5297
+ };
5298
+ const handleDropItem = (index) => {
5299
+ setLiveText(
5300
+ formatMessage(
5301
+ {
5302
+ id: getTranslation("dnd.drop-item"),
5303
+ defaultMessage: `{item}, dropped. Final position in list: {position}.`
5304
+ },
5305
+ {
5306
+ item: `${name2}.${index}`,
5307
+ position: getItemPos(index)
5308
+ }
5309
+ )
5310
+ );
5311
+ };
5312
+ const ariaDescriptionId = React.useId();
5313
+ const level = useComponent("RepeatableComponent", (state) => state.level);
5314
+ if (value.length === 0) {
5315
+ return /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleClick });
5037
5316
  }
5317
+ return /* @__PURE__ */ jsxs(Box, { hasRadius: true, children: [
5318
+ /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
5319
+ id: getTranslation("dnd.instructions"),
5320
+ defaultMessage: `Press spacebar to grab and re-order`
5321
+ }) }),
5322
+ /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
5323
+ /* @__PURE__ */ jsxs(
5324
+ AccordionRoot,
5325
+ {
5326
+ $error: error,
5327
+ value: collapseToOpen,
5328
+ onValueChange: handleValueChange,
5329
+ "aria-describedby": ariaDescriptionId,
5330
+ children: [
5331
+ value.map(({ __temp_key__: key, id }, index) => {
5332
+ const nameWithIndex = `${name2}.${index}`;
5333
+ return /* @__PURE__ */ jsx(
5334
+ ComponentProvider,
5335
+ {
5336
+ id,
5337
+ uid: attribute.component,
5338
+ level: level + 1,
5339
+ type: "repeatable",
5340
+ children: /* @__PURE__ */ jsx(
5341
+ Component,
5342
+ {
5343
+ disabled,
5344
+ name: nameWithIndex,
5345
+ attribute,
5346
+ index,
5347
+ mainField,
5348
+ onMoveItem: handleMoveComponentField,
5349
+ onDeleteComponent: () => {
5350
+ removeFieldRow(name2, index);
5351
+ toggleCollapses();
5352
+ },
5353
+ toggleCollapses,
5354
+ onCancel: handleCancel,
5355
+ onDropItem: handleDropItem,
5356
+ onGrabItem: handleGrabItem,
5357
+ __temp_key__: key,
5358
+ children: layout.map((row, index2) => {
5359
+ return /* @__PURE__ */ jsx(ResponsiveGridRoot, { gap: 4, children: row.map(({ size, ...field }) => {
5360
+ const completeFieldName = `${nameWithIndex}.${field.name}`;
5361
+ const translatedLabel = formatMessage({
5362
+ id: `content-manager.components.${attribute.component}.${field.name}`,
5363
+ defaultMessage: field.label
5364
+ });
5365
+ return /* @__PURE__ */ jsx(
5366
+ ResponsiveGridItem,
5367
+ {
5368
+ col: size,
5369
+ s: 12,
5370
+ xs: 12,
5371
+ direction: "column",
5372
+ alignItems: "stretch",
5373
+ children: children({
5374
+ ...field,
5375
+ label: translatedLabel,
5376
+ name: completeFieldName
5377
+ })
5378
+ },
5379
+ completeFieldName
5380
+ );
5381
+ }) }, index2);
5382
+ })
5383
+ }
5384
+ )
5385
+ },
5386
+ key
5387
+ );
5388
+ }),
5389
+ /* @__PURE__ */ jsx(TextButtonCustom, { disabled, onClick: handleClick, startIcon: /* @__PURE__ */ jsx(Plus, {}), children: formatMessage({
5390
+ id: getTranslation("containers.EditView.add.new-entry"),
5391
+ defaultMessage: "Add an entry"
5392
+ }) })
5393
+ ]
5394
+ }
5395
+ )
5396
+ ] });
5038
5397
  };
5039
- const attributeHasCustomFieldProperty = (attribute) => "customField" in attribute && typeof attribute.customField === "string";
5040
- const useFieldHint = (hint = void 0, attribute) => {
5041
- const { formatMessage } = useIntl();
5042
- const { maximum, minimum } = getMinMax(attribute);
5043
- if (!maximum && !minimum) {
5044
- return hint;
5045
- }
5046
- const units = !["biginteger", "integer", "number", "dynamiczone", "component"].includes(
5047
- attribute.type
5048
- ) ? formatMessage(
5049
- {
5050
- id: "content-manager.form.Input.hint.character.unit",
5051
- defaultMessage: "{maxValue, plural, one { character} other { characters}}"
5052
- },
5053
- {
5054
- maxValue: Math.max(minimum || 0, maximum || 0)
5055
- }
5056
- ) : null;
5057
- const hasMinAndMax = typeof minimum === "number" && typeof maximum === "number";
5058
- return formatMessage(
5059
- {
5060
- id: "content-manager.form.Input.hint.text",
5061
- defaultMessage: "{min, select, undefined {} other {min. {min}}}{divider}{max, select, undefined {} other {max. {max}}}{unit}{br}{description}"
5062
- },
5063
- {
5064
- min: minimum,
5065
- max: maximum,
5066
- description: hint,
5067
- unit: units,
5068
- divider: hasMinAndMax ? formatMessage({
5069
- id: "content-manager.form.Input.hint.minMaxDivider",
5070
- defaultMessage: " / "
5071
- }) : null,
5072
- br: /* @__PURE__ */ jsx("br", {})
5398
+ const AccordionRoot = styled(Accordion.Root)`
5399
+ border: 1px solid
5400
+ ${({ theme, $error }) => $error ? theme.colors.danger600 : theme.colors.neutral200};
5401
+ `;
5402
+ const TextButtonCustom = styled(TextButton)`
5403
+ width: 100%;
5404
+ display: flex;
5405
+ justify-content: center;
5406
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral200};
5407
+ padding-inline: ${(props) => props.theme.spaces[6]};
5408
+ padding-block: ${(props) => props.theme.spaces[3]};
5409
+
5410
+ &:not([disabled]) {
5411
+ cursor: pointer;
5412
+
5413
+ &:hover {
5414
+ background-color: ${(props) => props.theme.colors.primary100};
5073
5415
  }
5074
- );
5075
- };
5076
- const getMinMax = (attribute) => {
5077
- if ("min" in attribute || "max" in attribute) {
5078
- return {
5079
- maximum: !Number.isNaN(Number(attribute.max)) ? Number(attribute.max) : void 0,
5080
- minimum: !Number.isNaN(Number(attribute.min)) ? Number(attribute.min) : void 0
5081
- };
5082
- } else if ("maxLength" in attribute || "minLength" in attribute) {
5083
- return { maximum: attribute.maxLength, minimum: attribute.minLength };
5084
- } else {
5085
- return { maximum: void 0, minimum: void 0 };
5086
5416
  }
5087
- };
5088
- const MemoizedInputRenderer = memo(InputRenderer);
5089
- const DynamicComponent = ({
5090
- componentUid,
5417
+
5418
+ span {
5419
+ font-weight: 600;
5420
+ font-size: 1.4rem;
5421
+ line-height: 2.4rem;
5422
+ }
5423
+
5424
+ @media (prefers-reduced-motion: no-preference) {
5425
+ transition: background-color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
5426
+ }
5427
+ `;
5428
+ const Component = ({
5091
5429
  disabled,
5092
5430
  index,
5093
5431
  name: name2,
5094
- onRemoveComponentClick,
5095
- onMoveComponent,
5096
- onGrabItem,
5097
- onDropItem,
5098
- onCancel,
5099
- dynamicComponentsByCategory = {},
5100
- onAddComponent
5432
+ mainField = {
5433
+ name: "id",
5434
+ type: "integer"
5435
+ },
5436
+ children,
5437
+ onDeleteComponent,
5438
+ toggleCollapses,
5439
+ __temp_key__,
5440
+ ...dragProps
5101
5441
  }) => {
5102
5442
  const { formatMessage } = useIntl();
5103
- const formValues = useForm("DynamicComponent", (state) => state.values);
5104
- const {
5105
- edit: { components }
5106
- } = useDocLayout();
5107
- const title = React.useMemo(() => {
5108
- const { mainField } = components[componentUid]?.settings ?? { mainField: "id" };
5109
- const mainFieldValue = getIn(formValues, `${name2}.${index}.${mainField}`);
5110
- const displayedValue = mainField === "id" || !mainFieldValue ? "" : String(mainFieldValue).trim();
5111
- const mainValue = displayedValue.length > 0 ? `- ${displayedValue}` : displayedValue;
5112
- return mainValue;
5113
- }, [componentUid, components, formValues, name2, index]);
5114
- const { icon, displayName } = React.useMemo(() => {
5115
- const [category] = componentUid.split(".");
5116
- const { icon: icon2, displayName: displayName2 } = (dynamicComponentsByCategory[category] ?? []).find(
5117
- (component) => component.uid === componentUid
5118
- ) ?? { icon: null, displayName: null };
5119
- return { icon: icon2, displayName: displayName2 };
5120
- }, [componentUid, dynamicComponentsByCategory]);
5443
+ const displayValue = useForm("RepeatableComponent", (state) => {
5444
+ return getIn(state.values, [...name2.split("."), mainField.name]);
5445
+ });
5446
+ const accordionRef = React.useRef(null);
5447
+ const componentKey = name2.split(".").slice(0, -1).join(".");
5121
5448
  const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
5122
- type: `${ItemTypes.DYNAMIC_ZONE}_${name2}`,
5449
+ type: `${ItemTypes.COMPONENT}_${componentKey}`,
5123
5450
  index,
5124
5451
  item: {
5125
5452
  index,
5126
- displayedValue: `${displayName} ${title}`,
5127
- icon
5453
+ displayedValue: displayValue
5128
5454
  },
5129
- onMoveItem: onMoveComponent,
5130
- onDropItem,
5131
- onGrabItem,
5132
- onCancel
5455
+ onStart() {
5456
+ toggleCollapses();
5457
+ },
5458
+ ...dragProps
5133
5459
  });
5134
5460
  React.useEffect(() => {
5135
5461
  dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
5136
5462
  }, [dragPreviewRef, index]);
5137
- const accordionValue = React.useId();
5138
- const { value = [], rawError } = useField(`${name2}.${index}`);
5139
- const [collapseToOpen, setCollapseToOpen] = React.useState("");
5140
- React.useEffect(() => {
5141
- if (rawError && value) {
5142
- setCollapseToOpen(accordionValue);
5143
- }
5144
- }, [rawError, value, accordionValue]);
5145
- const composedBoxRefs = useComposedRefs(boxRef, dropRef);
5146
- const accordionActions = disabled ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
5147
- /* @__PURE__ */ jsx(
5148
- IconButton,
5149
- {
5150
- variant: "ghost",
5151
- label: formatMessage(
5463
+ const composedAccordionRefs = useComposedRefs(accordionRef, dragRef);
5464
+ const composedBoxRefs = useComposedRefs(
5465
+ boxRef,
5466
+ dropRef
5467
+ );
5468
+ return /* @__PURE__ */ jsx(Fragment, { children: isDragging ? /* @__PURE__ */ jsx(Preview, {}) : /* @__PURE__ */ jsxs(Accordion.Item, { ref: composedBoxRefs, value: __temp_key__, children: [
5469
+ /* @__PURE__ */ jsxs(Accordion.Header, { children: [
5470
+ /* @__PURE__ */ jsx(Accordion.Trigger, { children: displayValue }),
5471
+ /* @__PURE__ */ jsxs(Accordion.Actions, { children: [
5472
+ /* @__PURE__ */ jsx(
5473
+ IconButton,
5152
5474
  {
5153
- id: getTranslation("components.DynamicZone.delete-label"),
5154
- defaultMessage: "Delete {name}"
5155
- },
5156
- { name: title }
5475
+ variant: "ghost",
5476
+ onClick: onDeleteComponent,
5477
+ label: formatMessage({
5478
+ id: getTranslation("containers.Edit.delete"),
5479
+ defaultMessage: "Delete"
5480
+ }),
5481
+ children: /* @__PURE__ */ jsx(Trash, {})
5482
+ }
5157
5483
  ),
5158
- onClick: onRemoveComponentClick,
5159
- children: /* @__PURE__ */ jsx(Trash, {})
5160
- }
5161
- ),
5162
- /* @__PURE__ */ jsx(
5163
- IconButton,
5164
- {
5165
- variant: "ghost",
5166
- onClick: (e) => e.stopPropagation(),
5167
- "data-handler-id": handlerId,
5168
- ref: dragRef,
5169
- label: formatMessage({
5170
- id: getTranslation("components.DragHandle-label"),
5171
- defaultMessage: "Drag"
5172
- }),
5173
- onKeyDown: handleKeyDown,
5174
- children: /* @__PURE__ */ jsx(Drag, {})
5175
- }
5176
- ),
5177
- /* @__PURE__ */ jsxs(Menu.Root, { children: [
5178
- /* @__PURE__ */ jsxs(Menu.Trigger, { size: "S", endIcon: null, paddingLeft: 2, paddingRight: 2, children: [
5179
- /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
5180
- /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage({
5181
- id: getTranslation("components.DynamicZone.more-actions"),
5182
- defaultMessage: "More actions"
5183
- }) })
5184
- ] }),
5185
- /* @__PURE__ */ jsxs(Menu.Content, { children: [
5186
- /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
5187
- /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
5188
- id: getTranslation("components.DynamicZone.add-item-above"),
5189
- defaultMessage: "Add component above"
5190
- }) }),
5191
- /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
5192
- /* @__PURE__ */ jsx(Menu.Label, { children: category }),
5193
- components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index), children: displayName2 }, componentUid))
5194
- ] }, category)) })
5195
- ] }),
5196
- /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
5197
- /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
5198
- id: getTranslation("components.DynamicZone.add-item-below"),
5199
- defaultMessage: "Add component below"
5200
- }) }),
5201
- /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
5202
- /* @__PURE__ */ jsx(Menu.Label, { children: category }),
5203
- components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index + 1), children: displayName2 }, componentUid))
5204
- ] }, category)) })
5205
- ] })
5206
- ] })
5207
- ] })
5208
- ] });
5209
- const accordionTitle = title ? `${displayName} ${title}` : displayName;
5210
- return /* @__PURE__ */ jsxs(ComponentContainer, { tag: "li", width: "100%", children: [
5211
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Rectangle, { background: "neutral200" }) }),
5212
- /* @__PURE__ */ jsx(StyledBox, { ref: composedBoxRefs, hasRadius: true, children: isDragging ? /* @__PURE__ */ jsx(Preview, {}) : /* @__PURE__ */ jsx(Accordion.Root, { value: collapseToOpen, onValueChange: setCollapseToOpen, children: /* @__PURE__ */ jsxs(Accordion.Item, { value: accordionValue, children: [
5213
- /* @__PURE__ */ jsxs(Accordion.Header, { children: [
5214
5484
  /* @__PURE__ */ jsx(
5215
- Accordion.Trigger,
5485
+ IconButton,
5216
5486
  {
5217
- icon: icon && COMPONENT_ICONS[icon] ? COMPONENT_ICONS[icon] : COMPONENT_ICONS.dashboard,
5218
- children: accordionTitle
5487
+ ref: composedAccordionRefs,
5488
+ variant: "ghost",
5489
+ onClick: (e) => e.stopPropagation(),
5490
+ "data-handler-id": handlerId,
5491
+ label: formatMessage({
5492
+ id: getTranslation("components.DragHandle-label"),
5493
+ defaultMessage: "Drag"
5494
+ }),
5495
+ onKeyDown: handleKeyDown,
5496
+ children: /* @__PURE__ */ jsx(Drag, {})
5219
5497
  }
5220
- ),
5221
- /* @__PURE__ */ jsx(Accordion.Actions, { children: accordionActions })
5222
- ] }),
5223
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(AccordionContentRadius, { background: "neutral0", children: /* @__PURE__ */ jsx(Box, { paddingLeft: 6, paddingRight: 6, paddingTop: 6, paddingBottom: 6, children: /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: components[componentUid]?.layout?.map((row, rowInd) => /* @__PURE__ */ jsx(
5224
- Grid$1.Item,
5225
- {
5226
- col: 12,
5227
- s: 12,
5228
- xs: 12,
5229
- direction: "column",
5230
- alignItems: "stretch",
5231
- children: /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
5232
- const fieldName = `${name2}.${index}.${field.name}`;
5233
- const fieldWithTranslatedLabel = {
5234
- ...field,
5235
- label: formatMessage({
5236
- id: `content-manager.components.${componentUid}.${field.name}`,
5237
- defaultMessage: field.label
5238
- })
5239
- };
5240
- return /* @__PURE__ */ jsx(
5241
- Grid$1.Item,
5242
- {
5243
- col: size,
5244
- s: 12,
5245
- xs: 12,
5246
- direction: "column",
5247
- alignItems: "stretch",
5248
- children: /* @__PURE__ */ jsx(MemoizedInputRenderer, { ...fieldWithTranslatedLabel, name: fieldName })
5249
- },
5250
- fieldName
5251
- );
5252
- }) })
5253
- },
5254
- rowInd
5255
- )) }) }) }) })
5256
- ] }) }) })
5257
- ] });
5258
- };
5259
- const StyledBox = styled(Box)`
5260
- > div:first-child {
5261
- box-shadow: ${({ theme }) => theme.shadows.tableShadow};
5262
- }
5263
- `;
5264
- const AccordionContentRadius = styled(Box)`
5265
- border-radius: 0 0 ${({ theme }) => theme.spaces[1]} ${({ theme }) => theme.spaces[1]};
5266
- `;
5267
- const Rectangle = styled(Box)`
5268
- width: ${({ theme }) => theme.spaces[2]};
5269
- height: ${({ theme }) => theme.spaces[4]};
5270
- `;
5271
- const Preview = styled.span`
5272
- display: block;
5273
- background-color: ${({ theme }) => theme.colors.primary100};
5274
- outline: 1px dashed ${({ theme }) => theme.colors.primary500};
5275
- outline-offset: -1px;
5276
- padding: ${({ theme }) => theme.spaces[6]};
5277
- `;
5278
- const ComponentContainer = styled(Box)`
5279
- list-style: none;
5280
- padding: 0;
5281
- margin: 0;
5282
- `;
5283
- const DynamicZoneLabel = ({
5284
- hint,
5285
- label,
5286
- labelAction,
5287
- name: name2,
5288
- numberOfComponents = 0,
5289
- required
5290
- }) => {
5291
- return /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
5292
- Box,
5293
- {
5294
- paddingTop: 3,
5295
- paddingBottom: 3,
5296
- paddingRight: 4,
5297
- paddingLeft: 4,
5298
- borderRadius: "26px",
5299
- background: "neutral0",
5300
- shadow: "filterShadow",
5301
- color: "neutral500",
5302
- children: /* @__PURE__ */ jsxs(Flex, { direction: "column", justifyContent: "center", children: [
5303
- /* @__PURE__ */ jsxs(Flex, { maxWidth: "35.6rem", children: [
5304
- /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", ellipsis: true, children: [
5305
- label || name2,
5306
- " "
5307
- ] }),
5308
- /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral600", fontWeight: "bold", children: [
5309
- "(",
5310
- numberOfComponents,
5311
- ")"
5312
- ] }),
5313
- required && /* @__PURE__ */ jsx(Typography, { textColor: "danger600", children: "*" }),
5314
- labelAction && /* @__PURE__ */ jsx(Box, { paddingLeft: 1, children: labelAction })
5315
- ] }),
5316
- hint && /* @__PURE__ */ jsx(Box, { paddingTop: 1, maxWidth: "35.6rem", children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", ellipsis: true, children: hint }) })
5498
+ )
5317
5499
  ] })
5318
- }
5319
- ) });
5320
- };
5321
- const [DynamicZoneProvider, useDynamicZone] = createContext(
5322
- "DynamicZone",
5323
- {
5324
- isInDynamicZone: false
5325
- }
5326
- );
5327
- const DynamicZone = ({
5328
- attribute,
5329
- disabled: disabledProp,
5330
- hint,
5500
+ ] }),
5501
+ /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(
5502
+ Flex,
5503
+ {
5504
+ direction: "column",
5505
+ alignItems: "stretch",
5506
+ background: "neutral100",
5507
+ padding: 6,
5508
+ gap: 6,
5509
+ children
5510
+ }
5511
+ ) })
5512
+ ] }) });
5513
+ };
5514
+ const Preview = () => {
5515
+ return /* @__PURE__ */ jsx(StyledSpan, { tag: "span", padding: 6, background: "primary100" });
5516
+ };
5517
+ const StyledSpan = styled(Box)`
5518
+ display: block;
5519
+ outline: 1px dashed ${({ theme }) => theme.colors.primary500};
5520
+ outline-offset: -1px;
5521
+ `;
5522
+ const ComponentInput = ({
5331
5523
  label,
5332
- labelAction,
5524
+ required,
5333
5525
  name: name2,
5334
- required = false
5526
+ attribute,
5527
+ disabled,
5528
+ labelAction,
5529
+ ...props
5335
5530
  }) => {
5336
- const { max = Infinity, min = -Infinity } = attribute ?? {};
5337
- const [addComponentIsOpen, setAddComponentIsOpen] = React.useState(false);
5338
- const [liveText, setLiveText] = React.useState("");
5339
- const { components, isLoading } = useDoc();
5340
- const disabled = disabledProp || isLoading;
5341
- const { addFieldRow, removeFieldRow, moveFieldRow } = useForm(
5342
- "DynamicZone",
5343
- ({ addFieldRow: addFieldRow2, removeFieldRow: removeFieldRow2, moveFieldRow: moveFieldRow2 }) => ({
5344
- addFieldRow: addFieldRow2,
5345
- removeFieldRow: removeFieldRow2,
5346
- moveFieldRow: moveFieldRow2
5347
- })
5348
- );
5349
- const { value = [], error } = useField(name2);
5350
- const dynamicComponentsByCategory = React.useMemo(() => {
5351
- return attribute.components.reduce((acc, componentUid) => {
5352
- const { category, info } = components[componentUid] ?? { info: {} };
5353
- const component = { uid: componentUid, displayName: info.displayName, icon: info.icon };
5354
- if (!acc[category]) {
5355
- acc[category] = [];
5356
- }
5357
- acc[category] = [...acc[category], component];
5358
- return acc;
5359
- }, {});
5360
- }, [attribute.components, components]);
5361
5531
  const { formatMessage } = useIntl();
5362
- const { toggleNotification } = useNotification();
5363
- const dynamicDisplayedComponentsLength = value.length;
5364
- const handleAddComponent = (uid, position) => {
5365
- setAddComponentIsOpen(false);
5366
- const schema = components[uid];
5532
+ const field = useField(name2);
5533
+ const showResetComponent = !attribute.repeatable && field.value && !disabled;
5534
+ const { components } = useDoc();
5535
+ const handleInitialisationClick = () => {
5536
+ const schema = components[attribute.component];
5367
5537
  const form = createDefaultForm(schema, components);
5368
- const transformations = pipe$1(transformDocument(schema, components), (data2) => ({
5369
- ...data2,
5370
- __component: uid
5371
- }));
5372
- const data = transformations(form);
5373
- addFieldRow(name2, data, position);
5374
- };
5375
- const handleClickOpenPicker = () => {
5376
- if (dynamicDisplayedComponentsLength < max) {
5377
- setAddComponentIsOpen((prev) => !prev);
5378
- } else {
5379
- toggleNotification({
5380
- type: "info",
5381
- message: formatMessage({
5382
- id: getTranslation("components.notification.info.maximum-requirement")
5383
- })
5384
- });
5385
- }
5386
- };
5387
- const handleMoveComponent = (newIndex, currentIndex) => {
5388
- setLiveText(
5389
- formatMessage(
5390
- {
5391
- id: getTranslation("dnd.reorder"),
5392
- defaultMessage: "{item}, moved. New position in list: {position}."
5393
- },
5394
- {
5395
- item: `${name2}.${currentIndex}`,
5396
- position: getItemPos(newIndex)
5397
- }
5398
- )
5399
- );
5400
- moveFieldRow(name2, currentIndex, newIndex);
5401
- };
5402
- const getItemPos = (index) => `${index + 1} of ${value.length}`;
5403
- const handleCancel = (index) => {
5404
- setLiveText(
5405
- formatMessage(
5406
- {
5407
- id: getTranslation("dnd.cancel-item"),
5408
- defaultMessage: "{item}, dropped. Re-order cancelled."
5409
- },
5410
- {
5411
- item: `${name2}.${index}`
5412
- }
5413
- )
5414
- );
5415
- };
5416
- const handleGrabItem = (index) => {
5417
- setLiveText(
5418
- formatMessage(
5419
- {
5420
- id: getTranslation("dnd.grab-item"),
5421
- defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
5422
- },
5423
- {
5424
- item: `${name2}.${index}`,
5425
- position: getItemPos(index)
5426
- }
5427
- )
5428
- );
5538
+ const data = transformDocument(schema, components)(form);
5539
+ field.onChange(name2, data);
5429
5540
  };
5430
- const handleDropItem = (index) => {
5431
- setLiveText(
5432
- formatMessage(
5433
- {
5434
- id: getTranslation("dnd.drop-item"),
5435
- defaultMessage: `{item}, dropped. Final position in list: {position}.`
5436
- },
5541
+ return /* @__PURE__ */ jsxs(Field.Root, { error: field.error, required, children: [
5542
+ /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
5543
+ /* @__PURE__ */ jsxs(Field.Label, { action: labelAction, children: [
5544
+ label,
5545
+ attribute.repeatable && /* @__PURE__ */ jsxs(Fragment, { children: [
5546
+ " (",
5547
+ Array.isArray(field.value) ? field.value.length : 0,
5548
+ ")"
5549
+ ] })
5550
+ ] }),
5551
+ showResetComponent && /* @__PURE__ */ jsx(
5552
+ IconButton,
5437
5553
  {
5438
- item: `${name2}.${index}`,
5439
- position: getItemPos(index)
5554
+ label: formatMessage({
5555
+ id: getTranslation("components.reset-entry"),
5556
+ defaultMessage: "Reset Entry"
5557
+ }),
5558
+ variant: "ghost",
5559
+ onClick: () => {
5560
+ field.onChange(name2, null);
5561
+ },
5562
+ children: /* @__PURE__ */ jsx(Trash, {})
5440
5563
  }
5441
5564
  )
5442
- );
5443
- };
5444
- const handleRemoveComponent = (name22, currentIndex) => () => {
5445
- removeFieldRow(name22, currentIndex);
5446
- };
5447
- const hasError = error !== void 0;
5448
- const renderButtonLabel = () => {
5449
- if (addComponentIsOpen) {
5450
- return formatMessage({ id: "app.utils.close-label", defaultMessage: "Close" });
5451
- }
5452
- if (hasError && dynamicDisplayedComponentsLength > max) {
5453
- return formatMessage(
5454
- {
5455
- id: getTranslation(`components.DynamicZone.extra-components`),
5456
- defaultMessage: "There {number, plural, =0 {are # extra components} one {is # extra component} other {are # extra components}}"
5457
- },
5458
- {
5459
- number: dynamicDisplayedComponentsLength - max
5460
- }
5461
- );
5462
- }
5463
- if (hasError && dynamicDisplayedComponentsLength < min) {
5464
- return formatMessage(
5465
- {
5466
- id: getTranslation(`components.DynamicZone.missing-components`),
5467
- defaultMessage: "There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}"
5468
- },
5469
- { number: min - dynamicDisplayedComponentsLength }
5470
- );
5471
- }
5472
- return formatMessage(
5473
- {
5474
- id: getTranslation("components.DynamicZone.add-component"),
5475
- defaultMessage: "Add a component to {componentName}"
5476
- },
5477
- { componentName: label || name2 }
5478
- );
5479
- };
5480
- const level = useComponent("DynamicZone", (state) => state.level);
5481
- const ariaDescriptionId = React.useId();
5482
- return /* @__PURE__ */ jsx(DynamicZoneProvider, { isInDynamicZone: true, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
5483
- dynamicDisplayedComponentsLength > 0 && /* @__PURE__ */ jsxs(Box, { children: [
5484
- /* @__PURE__ */ jsx(
5485
- DynamicZoneLabel,
5486
- {
5487
- hint,
5488
- label,
5489
- labelAction,
5490
- name: name2,
5491
- numberOfComponents: dynamicDisplayedComponentsLength,
5492
- required
5493
- }
5494
- ),
5495
- /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
5496
- id: getTranslation("dnd.instructions"),
5497
- defaultMessage: `Press spacebar to grab and re-order`
5498
- }) }),
5499
- /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
5500
- /* @__PURE__ */ jsx("ol", { "aria-describedby": ariaDescriptionId, children: value.map((field, index) => /* @__PURE__ */ jsx(
5501
- ComponentProvider,
5502
- {
5503
- level: level + 1,
5504
- uid: field.__component,
5505
- id: field.id,
5506
- type: "dynamiczone",
5507
- children: /* @__PURE__ */ jsx(
5508
- DynamicComponent,
5509
- {
5510
- disabled,
5511
- name: name2,
5512
- index,
5513
- componentUid: field.__component,
5514
- onMoveComponent: handleMoveComponent,
5515
- onRemoveComponentClick: handleRemoveComponent(name2, index),
5516
- onCancel: handleCancel,
5517
- onDropItem: handleDropItem,
5518
- onGrabItem: handleGrabItem,
5519
- onAddComponent: handleAddComponent,
5520
- dynamicComponentsByCategory
5521
- }
5522
- )
5523
- },
5524
- field.__temp_key__
5525
- )) })
5526
5565
  ] }),
5527
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
5528
- AddComponentButton,
5529
- {
5530
- hasError,
5531
- isDisabled: disabled,
5532
- isOpen: addComponentIsOpen,
5533
- onClick: handleClickOpenPicker,
5534
- children: renderButtonLabel()
5535
- }
5536
- ) }),
5537
- /* @__PURE__ */ jsx(
5538
- ComponentPicker,
5539
- {
5540
- dynamicComponentsByCategory,
5541
- isOpen: addComponentIsOpen,
5542
- onClickAddComponent: handleAddComponent
5543
- }
5544
- )
5545
- ] }) });
5566
+ !attribute.repeatable && !field.value && /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleInitialisationClick }),
5567
+ !attribute.repeatable && field.value ? /* @__PURE__ */ jsx(NonRepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }) : null,
5568
+ attribute.repeatable && /* @__PURE__ */ jsx(RepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }),
5569
+ /* @__PURE__ */ jsx(Field.Error, {})
5570
+ ] });
5546
5571
  };
5572
+ const MemoizedComponentInput = React.memo(ComponentInput);
5547
5573
  export {
5548
5574
  DynamicZone as D,
5549
- MemoizedInputRenderer as M,
5575
+ FormLayout as F,
5576
+ MemoizedUIDInput as M,
5550
5577
  NotAllowedInput as N,
5551
5578
  useDynamicZone as a,
5552
5579
  useFieldHint as b,
5553
- createDefaultForm as c,
5554
- MemoizedUIDInput as d,
5555
- MemoizedWysiwyg as e,
5556
- MemoizedComponentInput as f,
5557
- MemoizedBlocksInput as g,
5558
- prepareTempKeys as p,
5559
- removeFieldsThatDontExistOnSchema as r,
5560
- transformDocument as t,
5580
+ MemoizedWysiwyg as c,
5581
+ MemoizedComponentInput as d,
5582
+ MemoizedBlocksInput as e,
5561
5583
  useLazyComponents as u
5562
5584
  };
5563
- //# sourceMappingURL=Field-Bn1jgMeF.mjs.map
5585
+ //# sourceMappingURL=Input-BkKwZ6Qt.mjs.map