@strapi/content-manager 0.0.0-experimental.8c83c87960f2f5ddf95ae2f0acf849052f4a9ab4 → 0.0.0-experimental.8e4302929d7fe147203ed0266450d0a565c69660

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