@strapi/content-manager 0.0.0-next.6d1431fe2a53b80b47ad9f00187cd7bae9d5f46b → 0.0.0-next.7051057497777a23c7418e675330d2fb69c89fec

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 (174) hide show
  1. package/dist/_chunks/CardDragPreview-C0QyJgRA.js.map +1 -1
  2. package/dist/_chunks/CardDragPreview-DOxamsuj.mjs.map +1 -1
  3. package/dist/_chunks/{ComponentConfigurationPage-CS4dK8sJ.mjs → ComponentConfigurationPage-D4H-v0et.mjs} +3 -3
  4. package/dist/_chunks/{ComponentConfigurationPage-CS4dK8sJ.mjs.map → ComponentConfigurationPage-D4H-v0et.mjs.map} +1 -1
  5. package/dist/_chunks/{ComponentConfigurationPage-BXrB6Fyz.js → ComponentConfigurationPage-DdkVGfXC.js} +4 -5
  6. package/dist/_chunks/{ComponentConfigurationPage-BXrB6Fyz.js.map → ComponentConfigurationPage-DdkVGfXC.js.map} +1 -1
  7. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js → ComponentIcon-CRbtQEUV.js} +2 -3
  8. package/dist/_chunks/{ComponentIcon-BXdiCGQp.js.map → ComponentIcon-CRbtQEUV.js.map} +1 -1
  9. package/dist/_chunks/ComponentIcon-u4bIXTFY.mjs.map +1 -1
  10. package/dist/_chunks/{EditConfigurationPage-KPmdp3nZ.mjs → EditConfigurationPage-D1nvB7Br.mjs} +3 -3
  11. package/dist/_chunks/{EditConfigurationPage-KPmdp3nZ.mjs.map → EditConfigurationPage-D1nvB7Br.mjs.map} +1 -1
  12. package/dist/_chunks/{EditConfigurationPage-BFrTf6Wt.js → EditConfigurationPage-LYEvR4fW.js} +4 -5
  13. package/dist/_chunks/{EditConfigurationPage-BFrTf6Wt.js.map → EditConfigurationPage-LYEvR4fW.js.map} +1 -1
  14. package/dist/_chunks/{EditViewPage-BnPxp-t3.mjs → EditViewPage-Bcnff6Vd.mjs} +21 -54
  15. package/dist/_chunks/EditViewPage-Bcnff6Vd.mjs.map +1 -0
  16. package/dist/_chunks/{EditViewPage-CCj-eG0Y.js → EditViewPage-DqelJ9UK.js} +23 -57
  17. package/dist/_chunks/EditViewPage-DqelJ9UK.js.map +1 -0
  18. package/dist/_chunks/FieldTypeIcon-CMlNO8PE.mjs.map +1 -1
  19. package/dist/_chunks/FieldTypeIcon-Dnwq_IRF.js.map +1 -1
  20. package/dist/_chunks/{Form-DbQ4gxkw.js → Form-CnHfBeiB.js} +5 -6
  21. package/dist/_chunks/{Form-DbQ4gxkw.js.map → Form-CnHfBeiB.js.map} +1 -1
  22. package/dist/_chunks/{Form-C8z5hjjO.mjs → Form-CzPCJi3B.mjs} +3 -3
  23. package/dist/_chunks/{Form-C8z5hjjO.mjs.map → Form-CzPCJi3B.mjs.map} +1 -1
  24. package/dist/_chunks/{History-CuPXsYZL.mjs → History-CcmSn3Mj.mjs} +37 -61
  25. package/dist/_chunks/History-CcmSn3Mj.mjs.map +1 -0
  26. package/dist/_chunks/{History-C23owO-n.js → History-zArjENzj.js} +48 -73
  27. package/dist/_chunks/History-zArjENzj.js.map +1 -0
  28. package/dist/_chunks/{Field-SRNzJb2F.js → Input-CDHKQd7o.js} +1294 -1271
  29. package/dist/_chunks/Input-CDHKQd7o.js.map +1 -0
  30. package/dist/_chunks/{Field-DSDtEDLU.mjs → Input-aV8SSoTa.mjs} +1333 -1310
  31. package/dist/_chunks/Input-aV8SSoTa.mjs.map +1 -0
  32. package/dist/_chunks/{ListConfigurationPage-ChKIEXi-.mjs → ListConfigurationPage-BPvzENJJ.mjs} +6 -5
  33. package/dist/_chunks/ListConfigurationPage-BPvzENJJ.mjs.map +1 -0
  34. package/dist/_chunks/{ListConfigurationPage-CyfKtibC.js → ListConfigurationPage-ByZAO_9H.js} +6 -6
  35. package/dist/_chunks/ListConfigurationPage-ByZAO_9H.js.map +1 -0
  36. package/dist/_chunks/{ListViewPage-BLcdkiiW.js → ListViewPage-BVKBeQAA.js} +74 -60
  37. package/dist/_chunks/ListViewPage-BVKBeQAA.js.map +1 -0
  38. package/dist/_chunks/{ListViewPage-BicHoHdt.mjs → ListViewPage-HljQVnFH.mjs} +68 -53
  39. package/dist/_chunks/ListViewPage-HljQVnFH.mjs.map +1 -0
  40. package/dist/_chunks/{NoContentTypePage-D9NSOYTF.js → NoContentTypePage-BV5zfDxr.js} +2 -2
  41. package/dist/_chunks/{NoContentTypePage-D9NSOYTF.js.map → NoContentTypePage-BV5zfDxr.js.map} +1 -1
  42. package/dist/_chunks/{NoContentTypePage-Clby61Hd.mjs → NoContentTypePage-BfHaSM-K.mjs} +2 -2
  43. package/dist/_chunks/{NoContentTypePage-Clby61Hd.mjs.map → NoContentTypePage-BfHaSM-K.mjs.map} +1 -1
  44. package/dist/_chunks/{NoPermissionsPage-DD72Qxzx.mjs → NoPermissionsPage-D6ze2nQL.mjs} +2 -2
  45. package/dist/_chunks/{NoPermissionsPage-DD72Qxzx.mjs.map → NoPermissionsPage-D6ze2nQL.mjs.map} +1 -1
  46. package/dist/_chunks/{NoPermissionsPage-CPcXGv0N.js → NoPermissionsPage-vdNpc6jb.js} +2 -2
  47. package/dist/_chunks/{NoPermissionsPage-CPcXGv0N.js.map → NoPermissionsPage-vdNpc6jb.js.map} +1 -1
  48. package/dist/_chunks/Preview-DEHdENT1.js +305 -0
  49. package/dist/_chunks/Preview-DEHdENT1.js.map +1 -0
  50. package/dist/_chunks/Preview-vfWOtPG5.mjs +287 -0
  51. package/dist/_chunks/Preview-vfWOtPG5.mjs.map +1 -0
  52. package/dist/_chunks/{Relations-BK3w1JyT.mjs → Relations-B7_hbF0w.mjs} +9 -10
  53. package/dist/_chunks/Relations-B7_hbF0w.mjs.map +1 -0
  54. package/dist/_chunks/{Relations-mHVb9pZH.js → Relations-DcoOBejP.js} +10 -12
  55. package/dist/_chunks/Relations-DcoOBejP.js.map +1 -0
  56. package/dist/_chunks/{en-tanszW-q.js → en-BR48D_RH.js} +16 -3
  57. package/dist/_chunks/{en-tanszW-q.js.map → en-BR48D_RH.js.map} +1 -1
  58. package/dist/_chunks/{en-pIGSfG2_.mjs → en-D65uIF6Y.mjs} +16 -3
  59. package/dist/_chunks/{en-pIGSfG2_.mjs.map → en-D65uIF6Y.mjs.map} +1 -1
  60. package/dist/_chunks/{fr-B2Kyv8Z9.js → fr-C43IbhA_.js} +4 -1
  61. package/dist/_chunks/{fr-B2Kyv8Z9.js.map → fr-C43IbhA_.js.map} +1 -1
  62. package/dist/_chunks/{fr--pg5jUbt.mjs → fr-DBseuRuB.mjs} +4 -1
  63. package/dist/_chunks/{fr--pg5jUbt.mjs.map → fr-DBseuRuB.mjs.map} +1 -1
  64. package/dist/_chunks/hooks-BAaaKPS_.js.map +1 -1
  65. package/dist/_chunks/{index-KzSpgsQa.js → index-CxLSGwnk.js} +545 -248
  66. package/dist/_chunks/index-CxLSGwnk.js.map +1 -0
  67. package/dist/_chunks/{index-Bl3BGqcN.mjs → index-EH8ZtHd5.mjs} +563 -265
  68. package/dist/_chunks/index-EH8ZtHd5.mjs.map +1 -0
  69. package/dist/_chunks/{layout-DFhUhimv.mjs → layout-CxDMdJ13.mjs} +4 -4
  70. package/dist/_chunks/{layout-DFhUhimv.mjs.map → layout-CxDMdJ13.mjs.map} +1 -1
  71. package/dist/_chunks/{layout-CKU3YxH7.js → layout-DSeUTfMv.js} +5 -6
  72. package/dist/_chunks/{layout-CKU3YxH7.js.map → layout-DSeUTfMv.js.map} +1 -1
  73. package/dist/_chunks/objects-BcXOv6_9.js.map +1 -1
  74. package/dist/_chunks/objects-D6yBsdmx.mjs.map +1 -1
  75. package/dist/_chunks/{relations-KkpGHlgm.mjs → relations-B8_Uu38Q.mjs} +17 -3
  76. package/dist/_chunks/relations-B8_Uu38Q.mjs.map +1 -0
  77. package/dist/_chunks/{relations-CnyTxXmA.js → relations-S5nNKdN3.js} +16 -2
  78. package/dist/_chunks/relations-S5nNKdN3.js.map +1 -0
  79. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js → useDragAndDrop-BMtgCYzL.js} +5 -9
  80. package/dist/_chunks/{useDragAndDrop-J0TUUbR6.js.map → useDragAndDrop-BMtgCYzL.js.map} +1 -1
  81. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs → useDragAndDrop-DJ6jqvZN.mjs} +4 -7
  82. package/dist/_chunks/{useDragAndDrop-DdHgKsqq.mjs.map → useDragAndDrop-DJ6jqvZN.mjs.map} +1 -1
  83. package/dist/_chunks/{useDebounce-CtcjDB3L.js → usePrev-B9w_-eYc.js} +1 -14
  84. package/dist/_chunks/usePrev-B9w_-eYc.js.map +1 -0
  85. package/dist/_chunks/usePrev-DH6iah0A.mjs +16 -0
  86. package/dist/_chunks/usePrev-DH6iah0A.mjs.map +1 -0
  87. package/dist/admin/index.js +2 -1
  88. package/dist/admin/index.js.map +1 -1
  89. package/dist/admin/index.mjs +6 -5
  90. package/dist/admin/src/content-manager.d.ts +3 -2
  91. package/dist/admin/src/exports.d.ts +1 -0
  92. package/dist/admin/src/history/services/historyVersion.d.ts +1 -1
  93. package/dist/admin/src/hooks/useDocument.d.ts +19 -2
  94. package/dist/admin/src/pages/EditView/EditViewPage.d.ts +9 -1
  95. package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
  96. package/dist/admin/src/pages/EditView/components/DocumentStatus.d.ts +3 -3
  97. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/Code.d.ts +7 -0
  98. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/Blocks/utils/prismLanguages.d.ts +49 -0
  99. package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/utils/constants.d.ts +1 -0
  100. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.d.ts +4 -1
  101. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +4 -1
  102. package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +27 -0
  103. package/dist/admin/src/pages/EditView/utils/data.d.ts +1 -0
  104. package/dist/admin/src/preview/components/PreviewContent.d.ts +2 -0
  105. package/dist/admin/src/preview/components/PreviewHeader.d.ts +2 -0
  106. package/dist/admin/src/preview/pages/Preview.d.ts +1 -1
  107. package/dist/admin/src/preview/services/preview.d.ts +1 -1
  108. package/dist/admin/src/router.d.ts +1 -1
  109. package/dist/admin/src/services/api.d.ts +1 -1
  110. package/dist/admin/src/services/components.d.ts +2 -2
  111. package/dist/admin/src/services/contentTypes.d.ts +3 -3
  112. package/dist/admin/src/services/documents.d.ts +16 -19
  113. package/dist/admin/src/services/init.d.ts +1 -1
  114. package/dist/admin/src/services/relations.d.ts +2 -2
  115. package/dist/admin/src/services/uid.d.ts +3 -3
  116. package/dist/server/index.js +230 -187
  117. package/dist/server/index.js.map +1 -1
  118. package/dist/server/index.mjs +231 -187
  119. package/dist/server/index.mjs.map +1 -1
  120. package/dist/server/src/controllers/utils/metadata.d.ts +1 -0
  121. package/dist/server/src/controllers/utils/metadata.d.ts.map +1 -1
  122. package/dist/server/src/history/controllers/history-version.d.ts +1 -1
  123. package/dist/server/src/history/controllers/history-version.d.ts.map +1 -1
  124. package/dist/server/src/history/services/history.d.ts +3 -3
  125. package/dist/server/src/history/services/history.d.ts.map +1 -1
  126. package/dist/server/src/history/services/utils.d.ts +6 -10
  127. package/dist/server/src/history/services/utils.d.ts.map +1 -1
  128. package/dist/server/src/index.d.ts +3 -2
  129. package/dist/server/src/index.d.ts.map +1 -1
  130. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -1
  131. package/dist/server/src/preview/index.d.ts.map +1 -1
  132. package/dist/server/src/preview/services/index.d.ts +1 -0
  133. package/dist/server/src/preview/services/index.d.ts.map +1 -1
  134. package/dist/server/src/preview/services/preview-config.d.ts +2 -0
  135. package/dist/server/src/preview/services/preview-config.d.ts.map +1 -1
  136. package/dist/server/src/preview/utils.d.ts +1 -0
  137. package/dist/server/src/preview/utils.d.ts.map +1 -1
  138. package/dist/server/src/register.d.ts.map +1 -1
  139. package/dist/server/src/services/document-manager.d.ts.map +1 -1
  140. package/dist/server/src/services/document-metadata.d.ts +4 -2
  141. package/dist/server/src/services/document-metadata.d.ts.map +1 -1
  142. package/dist/server/src/services/index.d.ts +3 -2
  143. package/dist/server/src/services/index.d.ts.map +1 -1
  144. package/dist/server/src/services/utils/configuration/index.d.ts +2 -2
  145. package/dist/server/src/services/utils/configuration/layouts.d.ts +2 -2
  146. package/dist/server/src/services/utils/populate.d.ts +2 -2
  147. package/dist/server/src/services/utils/populate.d.ts.map +1 -1
  148. package/package.json +12 -11
  149. package/dist/_chunks/EditViewPage-BnPxp-t3.mjs.map +0 -1
  150. package/dist/_chunks/EditViewPage-CCj-eG0Y.js.map +0 -1
  151. package/dist/_chunks/Field-DSDtEDLU.mjs.map +0 -1
  152. package/dist/_chunks/Field-SRNzJb2F.js.map +0 -1
  153. package/dist/_chunks/History-C23owO-n.js.map +0 -1
  154. package/dist/_chunks/History-CuPXsYZL.mjs.map +0 -1
  155. package/dist/_chunks/ListConfigurationPage-ChKIEXi-.mjs.map +0 -1
  156. package/dist/_chunks/ListConfigurationPage-CyfKtibC.js.map +0 -1
  157. package/dist/_chunks/ListViewPage-BLcdkiiW.js.map +0 -1
  158. package/dist/_chunks/ListViewPage-BicHoHdt.mjs.map +0 -1
  159. package/dist/_chunks/Preview-DcrNJ6zU.mjs +0 -122
  160. package/dist/_chunks/Preview-DcrNJ6zU.mjs.map +0 -1
  161. package/dist/_chunks/Preview-DpB7tlma.js +0 -141
  162. package/dist/_chunks/Preview-DpB7tlma.js.map +0 -1
  163. package/dist/_chunks/Relations-BK3w1JyT.mjs.map +0 -1
  164. package/dist/_chunks/Relations-mHVb9pZH.js.map +0 -1
  165. package/dist/_chunks/index-Bl3BGqcN.mjs.map +0 -1
  166. package/dist/_chunks/index-KzSpgsQa.js.map +0 -1
  167. package/dist/_chunks/relations-CnyTxXmA.js.map +0 -1
  168. package/dist/_chunks/relations-KkpGHlgm.mjs.map +0 -1
  169. package/dist/_chunks/useDebounce-CtcjDB3L.js.map +0 -1
  170. package/dist/_chunks/useDebounce-DmuSJIF3.mjs +0 -29
  171. package/dist/_chunks/useDebounce-DmuSJIF3.mjs.map +0 -1
  172. package/dist/admin/src/preview/constants.d.ts +0 -1
  173. package/dist/server/src/preview/constants.d.ts +0 -2
  174. 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-Bl3BGqcN.mjs";
9
- import { generateNKeysBetween } from "fractional-indexing";
10
- import { u as useComponent, C as ComponentProvider, M as MemoizedRelationsField } from "./Relations-BK3w1JyT.mjs";
11
- import { Code, HeadingOne, HeadingTwo, HeadingThree, HeadingFour, HeadingFive, HeadingSix, Image as Image$1, NumberList, BulletList, Paragraph, Quotes, Link as Link$1, Drag, Collapse, Bold, Italic, Underline, StrikeThrough, 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-DdHgKsqq.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};
@@ -508,7 +499,7 @@ const CodeEditor = (props) => {
508
499
  const codeBlocks = {
509
500
  code: {
510
501
  renderElement: (props) => /* @__PURE__ */ jsx(CodeEditor, { ...props }),
511
- icon: Code,
502
+ icon: CodeBlock$1,
512
503
  label: {
513
504
  id: "components.Blocks.blocks.code",
514
505
  defaultMessage: "Code block"
@@ -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" })`
@@ -697,8 +687,7 @@ const ImageDialog = () => {
697
687
  const [isOpen, setIsOpen] = React.useState(true);
698
688
  const { editor } = useBlocksEditorContext("ImageDialog");
699
689
  const components = useStrapiApp("ImageDialog", (state) => state.components);
700
- if (!components || !isOpen)
701
- return null;
690
+ if (!components || !isOpen) return null;
702
691
  const MediaLibraryDialog = components["media-library"];
703
692
  const insertImages = (images) => {
704
693
  Transforms.unwrapNodes(editor, {
@@ -707,14 +696,12 @@ const ImageDialog = () => {
707
696
  });
708
697
  const nodeEntryBeingReplaced = Editor$1.above(editor, {
709
698
  match(node) {
710
- if (Editor$1.isEditor(node))
711
- return false;
699
+ if (Editor$1.isEditor(node)) return false;
712
700
  const isInlineNode = ["text", "link"].includes(node.type);
713
701
  return !isInlineNode;
714
702
  }
715
703
  });
716
- if (!nodeEntryBeingReplaced)
717
- return;
704
+ if (!nodeEntryBeingReplaced) return;
718
705
  const [, pathToInsert] = nodeEntryBeingReplaced;
719
706
  Transforms.removeNodes(editor);
720
707
  const nodesToInsert = images.map((image) => {
@@ -892,8 +879,7 @@ const LinkContent = React.forwardRef(
892
879
  ReactEditor.focus(editor);
893
880
  };
894
881
  React.useEffect(() => {
895
- if (popoverOpen)
896
- linkInputRef.current?.focus();
882
+ if (popoverOpen) linkInputRef.current?.focus();
897
883
  }, [popoverOpen]);
898
884
  const inputNotDirty = !linkText || !linkUrl || link.url && link.url === linkUrl && elementText && elementText === linkText;
899
885
  return /* @__PURE__ */ jsxs(Popover.Root, { open: popoverOpen, children: [
@@ -963,11 +949,11 @@ const LinkContent = React.forwardRef(
963
949
  ),
964
950
  /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
965
951
  /* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: handleClose, children: formatMessage({
966
- id: "components.Blocks.popover.cancel",
952
+ id: "global.cancel",
967
953
  defaultMessage: "Cancel"
968
954
  }) }),
969
955
  /* @__PURE__ */ jsx(Button, { disabled: Boolean(inputNotDirty) || isSaveDisabled, onClick: handleSave, children: formatMessage({
970
- id: "components.Blocks.popover.save",
956
+ id: "global.save",
971
957
  defaultMessage: "Save"
972
958
  }) })
973
959
  ] })
@@ -1048,8 +1034,7 @@ const isText$1 = (node) => {
1048
1034
  return Node.isNode(node) && !Editor$1.isEditor(node) && node.type === "text";
1049
1035
  };
1050
1036
  const handleBackspaceKeyOnList = (editor, event) => {
1051
- if (!editor.selection)
1052
- return;
1037
+ if (!editor.selection) return;
1053
1038
  const [currentListItem, currentListItemPath] = Editor$1.parent(editor, editor.selection.anchor);
1054
1039
  const [currentList, currentListPath] = Editor$1.parent(editor, currentListItemPath);
1055
1040
  const isListEmpty = currentList.children.length === 1 && isText$1(currentListItem.children[0]) && currentListItem.children[0].text === "";
@@ -1158,8 +1143,7 @@ const handleEnterKeyOnList = (editor) => {
1158
1143
  };
1159
1144
  const handleConvertToList = (editor, format) => {
1160
1145
  const convertedPath = baseHandleConvert(editor, { type: "list-item" });
1161
- if (!convertedPath)
1162
- return;
1146
+ if (!convertedPath) return;
1163
1147
  Transforms.wrapNodes(editor, { type: "list", format, children: [] }, { at: convertedPath });
1164
1148
  };
1165
1149
  const handleTabOnList = (editor) => {
@@ -1171,8 +1155,7 @@ const handleTabOnList = (editor) => {
1171
1155
  }
1172
1156
  const [currentListItem, currentListItemPath] = currentListItemEntry;
1173
1157
  const [currentList] = Editor$1.parent(editor, currentListItemPath);
1174
- if (currentListItem === currentList.children[0])
1175
- return;
1158
+ if (currentListItem === currentList.children[0]) return;
1176
1159
  const currentListItemIndex = currentList.children.findIndex((item) => item === currentListItem);
1177
1160
  const previousNode = currentList.children[currentListItemIndex - 1];
1178
1161
  if (previousNode.type === "list") {
@@ -1308,13 +1291,13 @@ const quoteBlocks = {
1308
1291
  handleEnterKey(editor) {
1309
1292
  pressEnterTwiceToExit(editor);
1310
1293
  },
1311
- snippets: [">"],
1312
- dragHandleTopMargin: "6px"
1294
+ snippets: [">"]
1313
1295
  }
1314
1296
  };
1315
1297
  const ToolbarWrapper = styled(Flex)`
1316
1298
  &[aria-disabled='true'] {
1317
1299
  cursor: not-allowed;
1300
+ background: ${({ theme }) => theme.colors.neutral150};
1318
1301
  }
1319
1302
  `;
1320
1303
  const Separator = styled(Toolbar.Separator)`
@@ -1325,7 +1308,7 @@ const Separator = styled(Toolbar.Separator)`
1325
1308
  const FlexButton = styled(Flex)`
1326
1309
  // Inherit the not-allowed cursor from ToolbarWrapper when disabled
1327
1310
  &[aria-disabled] {
1328
- cursor: inherit;
1311
+ cursor: not-allowed;
1329
1312
  }
1330
1313
 
1331
1314
  &[aria-disabled='false'] {
@@ -1539,8 +1522,7 @@ const isListNode = (node) => {
1539
1522
  const ListButton = ({ block, format }) => {
1540
1523
  const { editor, disabled, blocks } = useBlocksEditorContext("ListButton");
1541
1524
  const isListActive = () => {
1542
- if (!editor.selection)
1543
- return false;
1525
+ if (!editor.selection) return false;
1544
1526
  const currentListEntry = Editor$1.above(editor, {
1545
1527
  match: (node) => !Editor$1.isEditor(node) && node.type === "list",
1546
1528
  at: editor.selection.anchor
@@ -1614,8 +1596,7 @@ const LinkButton = ({ disabled }) => {
1614
1596
  const { editor } = useBlocksEditorContext("LinkButton");
1615
1597
  const isLinkActive = () => {
1616
1598
  const { selection } = editor;
1617
- if (!selection)
1618
- return false;
1599
+ if (!selection) return false;
1619
1600
  const [match] = Array.from(
1620
1601
  Editor$1.nodes(editor, {
1621
1602
  at: Editor$1.unhangRange(editor, selection),
@@ -1679,7 +1660,7 @@ const BlocksToolbar = () => {
1679
1660
  return false;
1680
1661
  };
1681
1662
  const isButtonDisabled = checkButtonDisabled();
1682
- 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: [
1683
1664
  /* @__PURE__ */ jsx(BlocksDropdown, {}),
1684
1665
  /* @__PURE__ */ jsx(Separator, {}),
1685
1666
  /* @__PURE__ */ jsx(Toolbar.ToggleGroup, { type: "multiple", asChild: true, children: /* @__PURE__ */ jsxs(Flex, { gap: 1, children: [
@@ -1753,30 +1734,32 @@ const DragIconButton = styled(IconButton)`
1753
1734
  display: flex;
1754
1735
  align-items: center;
1755
1736
  justify-content: center;
1737
+ border: none;
1756
1738
  border-radius: ${({ theme }) => theme.borderRadius};
1757
- width: ${({ theme }) => theme.spaces[4]};
1758
- 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]};
1759
1743
  visibility: hidden;
1760
1744
  cursor: grab;
1761
1745
  opacity: inherit;
1762
1746
  margin-top: ${(props) => props.$dragHandleTopMargin ?? 0};
1763
1747
 
1764
1748
  &:hover {
1765
- background: ${({ theme }) => theme.colors.neutral200};
1749
+ background: ${({ theme }) => theme.colors.neutral100};
1766
1750
  }
1767
1751
  &:active {
1768
1752
  cursor: grabbing;
1753
+ background: ${({ theme }) => theme.colors.neutral150};
1769
1754
  }
1770
1755
  &[aria-disabled='true'] {
1771
- cursor: not-allowed;
1772
- background: transparent;
1756
+ visibility: hidden;
1773
1757
  }
1774
1758
  svg {
1775
- height: auto;
1776
1759
  min-width: ${({ theme }) => theme.spaces[3]};
1777
1760
 
1778
1761
  path {
1779
- fill: ${({ theme }) => theme.colors.neutral700};
1762
+ fill: ${({ theme }) => theme.colors.neutral500};
1780
1763
  }
1781
1764
  }
1782
1765
  `;
@@ -1821,8 +1804,7 @@ const DragAndDropElement = ({
1821
1804
  displayedValue: children
1822
1805
  },
1823
1806
  onDropItem(currentIndex, newIndex) {
1824
- if (newIndex)
1825
- handleMoveBlock(newIndex, currentIndex);
1807
+ if (newIndex) handleMoveBlock(newIndex, currentIndex);
1826
1808
  }
1827
1809
  });
1828
1810
  const composedBoxRefs = useComposedRefs(blockRef, dropRef);
@@ -1928,7 +1910,7 @@ const baseRenderLeaf = (props, modifiers2) => {
1928
1910
  }
1929
1911
  return currentChildren;
1930
1912
  }, props.children);
1931
- return /* @__PURE__ */ jsx("span", { ...props.attributes, children: wrappedChildren });
1913
+ return /* @__PURE__ */ jsx("span", { ...props.attributes, className: props.leaf.className, children: wrappedChildren });
1932
1914
  };
1933
1915
  const baseRenderElement = ({
1934
1916
  props,
@@ -1966,8 +1948,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
1966
1948
  [modifiers2]
1967
1949
  );
1968
1950
  const handleMoveBlocks = (editor2, event) => {
1969
- if (!editor2.selection)
1970
- return;
1951
+ if (!editor2.selection) return;
1971
1952
  const start = Range.start(editor2.selection);
1972
1953
  const currentIndex = [start.path[0]];
1973
1954
  let newIndexPosition = 0;
@@ -2104,8 +2085,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2104
2085
  }
2105
2086
  };
2106
2087
  const handleScrollSelectionIntoView = () => {
2107
- if (!editor.selection)
2108
- return;
2088
+ if (!editor.selection) return;
2109
2089
  const domRange = ReactEditor.toDOMRange(editor, editor.selection);
2110
2090
  const domRect = domRange.getBoundingClientRect();
2111
2091
  const blocksInput = blocksRef.current;
@@ -2132,7 +2112,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2132
2112
  background: "neutral0",
2133
2113
  color: "neutral800",
2134
2114
  lineHeight: 6,
2135
- paddingRight: 4,
2115
+ paddingRight: 7,
2136
2116
  paddingTop: 6,
2137
2117
  paddingBottom: 3,
2138
2118
  children: [
@@ -2143,6 +2123,7 @@ const BlocksContent = ({ placeholder, ariaLabelId }) => {
2143
2123
  readOnly: disabled,
2144
2124
  placeholder,
2145
2125
  isExpandedMode,
2126
+ decorate: decorateCode,
2146
2127
  renderElement,
2147
2128
  renderLeaf,
2148
2129
  onKeyDown: handleKeyDown,
@@ -2299,8 +2280,7 @@ const InlineCode = styled.code`
2299
2280
  `;
2300
2281
  const baseCheckIsActive = (editor, name2) => {
2301
2282
  const marks = Editor$1.marks(editor);
2302
- if (!marks)
2303
- return false;
2283
+ if (!marks) return false;
2304
2284
  return Boolean(marks[name2]);
2305
2285
  };
2306
2286
  const baseHandleToggle = (editor, name2) => {
@@ -2466,6 +2446,7 @@ const ExpandIconButton = styled(IconButton)`
2466
2446
  position: absolute;
2467
2447
  bottom: 1.2rem;
2468
2448
  right: 1.2rem;
2449
+ box-shadow: ${({ theme }) => theme.shadows.filterShadow};
2469
2450
  `;
2470
2451
  function useResetKey(value) {
2471
2452
  const slateUpdatesCount = React.useRef(0);
@@ -2597,26 +2578,6 @@ const BlocksInput = React.forwardRef(
2597
2578
  }
2598
2579
  );
2599
2580
  const MemoizedBlocksInput = React.memo(BlocksInput);
2600
- const createDefaultForm = (contentType, components = {}) => {
2601
- const traverseSchema = (attributes) => {
2602
- return Object.entries(attributes).reduce((acc, [key, attribute]) => {
2603
- if ("default" in attribute) {
2604
- acc[key] = attribute.default;
2605
- } else if (attribute.type === "component" && attribute.required) {
2606
- const defaultComponentForm = traverseSchema(components[attribute.component].attributes);
2607
- if (attribute.repeatable) {
2608
- acc[key] = attribute.min ? [...Array(attribute.min).fill(defaultComponentForm)] : [];
2609
- } else {
2610
- acc[key] = defaultComponentForm;
2611
- }
2612
- } else if (attribute.type === "dynamiczone" && attribute.required) {
2613
- acc[key] = [];
2614
- }
2615
- return acc;
2616
- }, {});
2617
- };
2618
- return traverseSchema(contentType.attributes);
2619
- };
2620
2581
  const Initializer = ({ disabled, name: name2, onClick }) => {
2621
2582
  const { formatMessage } = useIntl();
2622
2583
  const field = useField(name2);
@@ -2624,7 +2585,7 @@ const Initializer = ({ disabled, name: name2, onClick }) => {
2624
2585
  Box,
2625
2586
  {
2626
2587
  tag: "button",
2627
- background: "neutral100",
2588
+ background: disabled ? "neutral150" : "neutral100",
2628
2589
  borderColor: field.error ? "danger600" : "neutral200",
2629
2590
  hasRadius: true,
2630
2591
  disabled,
@@ -2632,631 +2593,638 @@ const Initializer = ({ disabled, name: name2, onClick }) => {
2632
2593
  paddingTop: 9,
2633
2594
  paddingBottom: 9,
2634
2595
  type: "button",
2596
+ style: { cursor: disabled ? "not-allowed" : "pointer" },
2635
2597
  children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
2636
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(CircleIcon, {}) }),
2637
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { textColor: "primary600", variant: "pi", fontWeight: "bold", children: formatMessage({
2638
- id: getTranslation("components.empty-repeatable"),
2639
- defaultMessage: "No entry yet. Click to add one."
2640
- }) }) })
2598
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", color: disabled ? "neutral500" : "primary600", children: /* @__PURE__ */ jsx(PlusCircle, { width: "3.2rem", height: "3.2rem" }) }),
2599
+ /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(
2600
+ Typography,
2601
+ {
2602
+ textColor: disabled ? "neutral600" : "primary600",
2603
+ variant: "pi",
2604
+ fontWeight: "bold",
2605
+ children: formatMessage({
2606
+ id: getTranslation("components.empty-repeatable"),
2607
+ defaultMessage: "No entry yet. Click to add one."
2608
+ })
2609
+ }
2610
+ ) })
2641
2611
  ] })
2642
2612
  }
2643
2613
  ) });
2644
2614
  };
2645
- const CircleIcon = styled(PlusCircle)`
2646
- width: 2.4rem;
2647
- height: 2.4rem;
2615
+ const AddComponentButton = ({
2616
+ hasError,
2617
+ isDisabled,
2618
+ isOpen,
2619
+ children,
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
+
2648
2651
  > circle {
2649
- fill: ${({ theme }) => theme.colors.primary200};
2652
+ fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger200 : theme.colors.neutral150};
2650
2653
  }
2651
2654
  > path {
2652
- fill: ${({ theme }) => theme.colors.primary600};
2655
+ fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger600 : theme.colors.neutral500};
2653
2656
  }
2654
2657
  `;
2655
- const NonRepeatableComponent = ({
2656
- attribute,
2657
- name: name2,
2658
- children,
2659
- layout
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
2660
2669
  }) => {
2661
- const { value } = useField(name2);
2662
- const level = useComponent("NonRepeatableComponent", (state) => state.level);
2663
- const isNested = level > 0;
2664
- return /* @__PURE__ */ jsx(ComponentProvider, { id: value?.id, uid: attribute.component, level: level + 1, type: "component", children: /* @__PURE__ */ jsx(
2670
+ const { formatMessage } = useIntl();
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(
2665
2734
  Box,
2666
2735
  {
2667
- background: "neutral100",
2668
- paddingLeft: 6,
2669
- paddingRight: 6,
2670
2736
  paddingTop: 6,
2671
2737
  paddingBottom: 6,
2672
- hasRadius: isNested,
2673
- borderColor: isNested ? "neutral200" : void 0,
2674
- children: /* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: layout.map((row, index) => {
2675
- return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
2676
- const completeFieldName = `${name2}.${field.name}`;
2677
- return /* @__PURE__ */ jsx(
2678
- Grid$1.Item,
2679
- {
2680
- col: size,
2681
- s: 12,
2682
- xs: 12,
2683
- direction: "column",
2684
- alignItems: "stretch",
2685
- children: children({ ...field, name: completeFieldName })
2686
- },
2687
- completeFieldName
2688
- );
2689
- }) }, index);
2690
- }) })
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
+ ]
2691
2760
  }
2692
- ) });
2761
+ );
2693
2762
  };
2694
- const RepeatableComponent = ({
2695
- attribute,
2763
+ const DynamicComponent = ({
2764
+ componentUid,
2696
2765
  disabled,
2766
+ index,
2697
2767
  name: name2,
2698
- mainField,
2699
- children,
2700
- layout
2768
+ onRemoveComponentClick,
2769
+ onMoveComponent,
2770
+ onGrabItem,
2771
+ onDropItem,
2772
+ onCancel,
2773
+ dynamicComponentsByCategory = {},
2774
+ onAddComponent,
2775
+ children
2701
2776
  }) => {
2702
- const { toggleNotification } = useNotification();
2703
2777
  const { formatMessage } = useIntl();
2704
- const { search: searchString } = useLocation();
2705
- const search = React.useMemo(() => new URLSearchParams(searchString), [searchString]);
2706
- const { components } = useDoc();
2778
+ const formValues = useForm("DynamicComponent", (state) => state.values);
2707
2779
  const {
2708
- value = [],
2709
- error,
2710
- rawError
2711
- } = useField(name2);
2712
- const addFieldRow = useForm("RepeatableComponent", (state) => state.addFieldRow);
2713
- const moveFieldRow = useForm("RepeatableComponent", (state) => state.moveFieldRow);
2714
- const removeFieldRow = useForm("RepeatableComponent", (state) => state.removeFieldRow);
2715
- const { max = Infinity } = attribute;
2716
- const [collapseToOpen, setCollapseToOpen] = React.useState("");
2717
- const [liveText, setLiveText] = React.useState("");
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
+ });
2718
2809
  React.useEffect(() => {
2719
- const hasNestedErrors = rawError && Array.isArray(rawError) && rawError.length > 0;
2720
- const hasNestedValue = value && Array.isArray(value) && value.length > 0;
2721
- if (hasNestedErrors && hasNestedValue) {
2722
- const errorOpenItems = rawError.map((_, idx) => {
2723
- return value[idx] ? value[idx].__temp_key__ : null;
2724
- }).filter((value2) => !!value2);
2725
- if (errorOpenItems && errorOpenItems.length > 0) {
2726
- setCollapseToOpen((collapseToOpen2) => {
2727
- if (!errorOpenItems.includes(collapseToOpen2)) {
2728
- return errorOpenItems[0];
2729
- }
2730
- return collapseToOpen2;
2731
- });
2732
- }
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);
2733
2818
  }
2734
- }, [rawError, value]);
2735
- const componentTmpKeyWithFocussedField = React.useMemo(() => {
2736
- if (search.has("field")) {
2737
- const fieldParam = search.get("field");
2738
- if (!fieldParam) {
2739
- 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, {})
2740
2835
  }
2741
- const [, path] = fieldParam.split(`${name2}.`);
2742
- if (getIn(value, path, void 0) !== void 0) {
2743
- const [subpath] = path.split(".");
2744
- 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, {})
2745
2850
  }
2746
- }
2747
- return void 0;
2748
- }, [search, name2, value]);
2749
- const prevValue = usePrev(value);
2750
- React.useEffect(() => {
2751
- if (prevValue && prevValue.length < value.length) {
2752
- setCollapseToOpen(value[value.length - 1].__temp_key__);
2753
- }
2754
- }, [value, prevValue]);
2755
- React.useEffect(() => {
2756
- if (typeof componentTmpKeyWithFocussedField === "string") {
2757
- setCollapseToOpen(componentTmpKeyWithFocussedField);
2758
- }
2759
- }, [componentTmpKeyWithFocussedField]);
2760
- const toggleCollapses = () => {
2761
- setCollapseToOpen("");
2762
- };
2763
- const handleClick = () => {
2764
- if (value.length < max) {
2765
- const schema = components[attribute.component];
2766
- const form = createDefaultForm(schema, components);
2767
- const data = transformDocument(schema, components)(form);
2768
- addFieldRow(name2, data);
2769
- } else if (value.length >= max) {
2770
- toggleNotification({
2771
- type: "info",
2772
- message: formatMessage({
2773
- id: getTranslation("components.notification.info.maximum-requirement")
2774
- })
2775
- });
2776
- }
2777
- };
2778
- const handleMoveComponentField = (newIndex, currentIndex) => {
2779
- setLiveText(
2780
- formatMessage(
2781
- {
2782
- id: getTranslation("dnd.reorder"),
2783
- defaultMessage: "{item}, moved. New position in list: {position}."
2784
- },
2785
- {
2786
- item: `${name2}.${currentIndex}`,
2787
- position: getItemPos(newIndex)
2788
- }
2789
- )
2790
- );
2791
- moveFieldRow(name2, currentIndex, newIndex);
2792
- };
2793
- const handleValueChange = (key) => {
2794
- setCollapseToOpen(key);
2795
- };
2796
- const getItemPos = (index) => `${index + 1} of ${value.length}`;
2797
- const handleCancel = (index) => {
2798
- setLiveText(
2799
- formatMessage(
2800
- {
2801
- id: getTranslation("dnd.cancel-item"),
2802
- defaultMessage: "{item}, dropped. Re-order cancelled."
2803
- },
2804
- {
2805
- item: `${name2}.${index}`
2806
- }
2807
- )
2808
- );
2809
- };
2810
- const handleGrabItem = (index) => {
2811
- setLiveText(
2812
- formatMessage(
2813
- {
2814
- id: getTranslation("dnd.grab-item"),
2815
- defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
2816
- },
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,
2817
2855
  {
2818
- item: `${name2}.${index}`,
2819
- position: getItemPos(index)
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 })
2820
2863
  }
2821
- )
2822
- );
2823
- };
2824
- const handleDropItem = (index) => {
2825
- setLiveText(
2826
- formatMessage(
2827
- {
2828
- id: getTranslation("dnd.drop-item"),
2829
- defaultMessage: `{item}, dropped. Final position in list: {position}.`
2830
- },
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,
2831
2905
  {
2832
- item: `${name2}.${index}`,
2833
- position: getItemPos(index)
2834
- }
2835
- )
2836
- );
2837
- };
2838
- const ariaDescriptionId = React.useId();
2839
- const level = useComponent("RepeatableComponent", (state) => state.level);
2840
- if (value.length === 0) {
2841
- return /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleClick });
2842
- }
2843
- return /* @__PURE__ */ jsxs(Box, { hasRadius: true, children: [
2844
- /* @__PURE__ */ jsx(VisuallyHidden, { id: ariaDescriptionId, children: formatMessage({
2845
- id: getTranslation("dnd.instructions"),
2846
- defaultMessage: `Press spacebar to grab and re-order`
2847
- }) }),
2848
- /* @__PURE__ */ jsx(VisuallyHidden, { "aria-live": "assertive", children: liveText }),
2849
- /* @__PURE__ */ jsxs(
2850
- AccordionRoot,
2851
- {
2852
- $error: error,
2853
- value: collapseToOpen,
2854
- onValueChange: handleValueChange,
2855
- "aria-describedby": ariaDescriptionId,
2856
- children: [
2857
- value.map(({ __temp_key__: key, id }, index) => {
2858
- const nameWithIndex = `${name2}.${index}`;
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
+ };
2859
2920
  return /* @__PURE__ */ jsx(
2860
- ComponentProvider,
2921
+ ResponsiveGridItem,
2861
2922
  {
2862
- id,
2863
- uid: attribute.component,
2864
- level: level + 1,
2865
- type: "repeatable",
2866
- children: /* @__PURE__ */ jsx(
2867
- Component,
2868
- {
2869
- disabled,
2870
- name: nameWithIndex,
2871
- attribute,
2872
- index,
2873
- mainField,
2874
- onMoveItem: handleMoveComponentField,
2875
- onDeleteComponent: () => {
2876
- removeFieldRow(name2, index);
2877
- toggleCollapses();
2878
- },
2879
- toggleCollapses,
2880
- onCancel: handleCancel,
2881
- onDropItem: handleDropItem,
2882
- onGrabItem: handleGrabItem,
2883
- __temp_key__: key,
2884
- children: layout.map((row, index2) => {
2885
- return /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
2886
- const completeFieldName = `${nameWithIndex}.${field.name}`;
2887
- return /* @__PURE__ */ jsx(
2888
- Grid$1.Item,
2889
- {
2890
- col: size,
2891
- s: 12,
2892
- xs: 12,
2893
- direction: "column",
2894
- alignItems: "stretch",
2895
- children: children({ ...field, name: completeFieldName })
2896
- },
2897
- completeFieldName
2898
- );
2899
- }) }, index2);
2900
- })
2901
- }
2902
- )
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 })
2903
2929
  },
2904
- key
2930
+ fieldName
2905
2931
  );
2906
- }),
2907
- /* @__PURE__ */ jsx(TextButtonCustom, { disabled, onClick: handleClick, startIcon: /* @__PURE__ */ jsx(Plus, {}), children: formatMessage({
2908
- id: getTranslation("containers.EditView.add.new-entry"),
2909
- defaultMessage: "Add an entry"
2910
2932
  }) })
2911
- ]
2912
- }
2913
- )
2933
+ },
2934
+ rowInd
2935
+ )) }) }) }) })
2936
+ ] }) }) })
2914
2937
  ] });
2915
2938
  };
2916
- const AccordionRoot = styled(Accordion.Root)`
2917
- border: 1px solid
2918
- ${({ theme, $error }) => $error ? theme.colors.danger600 : theme.colors.neutral200};
2919
- `;
2920
- const TextButtonCustom = styled(TextButton)`
2921
- width: 100%;
2922
- display: flex;
2923
- justify-content: center;
2924
- border-top: 1px solid ${({ theme }) => theme.colors.neutral200};
2925
- padding-inline: ${(props) => props.theme.spaces[6]};
2926
- padding-block: ${(props) => props.theme.spaces[3]};
2927
-
2928
- &:not([disabled]) {
2929
- cursor: pointer;
2930
-
2931
- &:hover {
2932
- background-color: ${(props) => props.theme.colors.primary100};
2933
- }
2934
- }
2935
-
2936
- span {
2937
- font-weight: 600;
2938
- font-size: 1.4rem;
2939
- line-height: 2.4rem;
2940
- }
2941
-
2942
- @media (prefers-reduced-motion: no-preference) {
2943
- transition: background-color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
2939
+ const StyledBox = styled(Box)`
2940
+ > div:first-child {
2941
+ box-shadow: ${({ theme }) => theme.shadows.tableShadow};
2944
2942
  }
2945
2943
  `;
2946
- const Component = ({
2947
- disabled,
2948
- index,
2949
- name: name2,
2950
- mainField = {
2951
- name: "id",
2952
- type: "integer"
2953
- },
2954
- children,
2955
- onDeleteComponent,
2956
- toggleCollapses,
2957
- __temp_key__,
2958
- ...dragProps
2959
- }) => {
2960
- const { formatMessage } = useIntl();
2961
- const displayValue = useForm("RepeatableComponent", (state) => {
2962
- return getIn(state.values, [...name2.split("."), mainField.name]);
2963
- });
2964
- const accordionRef = React.useRef(null);
2965
- const componentKey = name2.split(".").slice(0, -1).join(".");
2966
- const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
2967
- type: `${ItemTypes.COMPONENT}_${componentKey}`,
2968
- index,
2969
- item: {
2970
- index,
2971
- displayedValue: displayValue
2972
- },
2973
- onStart() {
2974
- toggleCollapses();
2975
- },
2976
- ...dragProps
2977
- });
2978
- React.useEffect(() => {
2979
- dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
2980
- }, [dragPreviewRef, index]);
2981
- const composedAccordionRefs = useComposedRefs(accordionRef, dragRef);
2982
- const composedBoxRefs = useComposedRefs(
2983
- boxRef,
2984
- dropRef
2985
- );
2986
- return /* @__PURE__ */ jsx(Fragment, { children: isDragging ? /* @__PURE__ */ jsx(Preview$1, {}) : /* @__PURE__ */ jsxs(Accordion.Item, { ref: composedBoxRefs, value: __temp_key__, children: [
2987
- /* @__PURE__ */ jsxs(Accordion.Header, { children: [
2988
- /* @__PURE__ */ jsx(Accordion.Trigger, { children: displayValue }),
2989
- /* @__PURE__ */ jsxs(Accordion.Actions, { children: [
2990
- /* @__PURE__ */ jsx(
2991
- IconButton,
2992
- {
2993
- variant: "ghost",
2994
- onClick: onDeleteComponent,
2995
- label: formatMessage({
2996
- id: getTranslation("containers.Edit.delete"),
2997
- defaultMessage: "Delete"
2998
- }),
2999
- children: /* @__PURE__ */ jsx(Trash, {})
3000
- }
3001
- ),
3002
- /* @__PURE__ */ jsx(
3003
- IconButton,
3004
- {
3005
- ref: composedAccordionRefs,
3006
- variant: "ghost",
3007
- onClick: (e) => e.stopPropagation(),
3008
- "data-handler-id": handlerId,
3009
- label: formatMessage({
3010
- id: getTranslation("components.DragHandle-label"),
3011
- defaultMessage: "Drag"
3012
- }),
3013
- onKeyDown: handleKeyDown,
3014
- children: /* @__PURE__ */ jsx(Drag, {})
3015
- }
3016
- )
3017
- ] })
3018
- ] }),
3019
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(
3020
- Flex,
3021
- {
3022
- direction: "column",
3023
- alignItems: "stretch",
3024
- background: "neutral100",
3025
- padding: 6,
3026
- gap: 6,
3027
- children
3028
- }
3029
- ) })
3030
- ] }) });
3031
- };
3032
- const Preview$1 = () => {
3033
- return /* @__PURE__ */ jsx(StyledSpan, { tag: "span", padding: 6, background: "primary100" });
3034
- };
3035
- const StyledSpan = styled(Box)`
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`
3036
2952
  display: block;
2953
+ background-color: ${({ theme }) => theme.colors.primary100};
3037
2954
  outline: 1px dashed ${({ theme }) => theme.colors.primary500};
3038
2955
  outline-offset: -1px;
2956
+ padding: ${({ theme }) => theme.spaces[6]};
3039
2957
  `;
3040
- const ComponentInput = ({
2958
+ const ComponentContainer = styled(Box)`
2959
+ list-style: none;
2960
+ padding: 0;
2961
+ margin: 0;
2962
+ `;
2963
+ const DynamicZoneLabel = ({
2964
+ hint,
3041
2965
  label,
3042
- required,
2966
+ labelAction,
3043
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
+ ] })
2998
+ }
2999
+ ) });
3000
+ };
3001
+ const [DynamicZoneProvider, useDynamicZone] = createContext(
3002
+ "DynamicZone",
3003
+ {
3004
+ isInDynamicZone: false
3005
+ }
3006
+ );
3007
+ const DynamicZone = ({
3044
3008
  attribute,
3045
- disabled,
3009
+ disabled: disabledProp,
3010
+ hint,
3011
+ label,
3046
3012
  labelAction,
3047
- ...props
3013
+ name: name2,
3014
+ required = false,
3015
+ children
3048
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]);
3049
3042
  const { formatMessage } = useIntl();
3050
- const field = useField(name2);
3051
- const showResetComponent = !attribute.repeatable && field.value && !disabled;
3052
- const { components } = useDoc();
3053
- const handleInitialisationClick = () => {
3054
- const schema = components[attribute.component];
3043
+ const { toggleNotification } = useNotification();
3044
+ const dynamicDisplayedComponentsLength = value.length;
3045
+ const handleAddComponent = (uid, position) => {
3046
+ setAddComponentIsOpen(false);
3047
+ const schema = components[uid];
3055
3048
  const form = createDefaultForm(schema, components);
3056
- const data = transformDocument(schema, components)(form);
3057
- field.onChange(name2, data);
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);
3058
3055
  };
3059
- return /* @__PURE__ */ jsxs(Field.Root, { error: field.error, required, children: [
3060
- /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", children: [
3061
- /* @__PURE__ */ jsxs(Field.Label, { action: labelAction, children: [
3062
- label,
3063
- attribute.repeatable && /* @__PURE__ */ jsxs(Fragment, { children: [
3064
- " (",
3065
- Array.isArray(field.value) ? field.value.length : 0,
3066
- ")"
3067
- ] })
3068
- ] }),
3069
- showResetComponent && /* @__PURE__ */ jsx(
3070
- IconButton,
3056
+ const handleClickOpenPicker = () => {
3057
+ if (dynamicDisplayedComponentsLength < max) {
3058
+ setAddComponentIsOpen((prev) => !prev);
3059
+ } else {
3060
+ toggleNotification({
3061
+ type: "info",
3062
+ message: formatMessage({
3063
+ id: getTranslation("components.notification.info.maximum-requirement")
3064
+ })
3065
+ });
3066
+ }
3067
+ };
3068
+ const handleMoveComponent = (newIndex, currentIndex) => {
3069
+ setLiveText(
3070
+ formatMessage(
3071
3071
  {
3072
- label: formatMessage({
3073
- id: getTranslation("components.reset-entry"),
3074
- defaultMessage: "Reset Entry"
3075
- }),
3076
- variant: "ghost",
3077
- onClick: () => {
3078
- field.onChange(name2, null);
3079
- },
3080
- children: /* @__PURE__ */ jsx(Trash, {})
3072
+ id: getTranslation("dnd.reorder"),
3073
+ defaultMessage: "{item}, moved. New position in list: {position}."
3074
+ },
3075
+ {
3076
+ item: `${name2}.${currentIndex}`,
3077
+ position: getItemPos(newIndex)
3081
3078
  }
3082
3079
  )
3083
- ] }),
3084
- !attribute.repeatable && !field.value && /* @__PURE__ */ jsx(Initializer, { disabled, name: name2, onClick: handleInitialisationClick }),
3085
- !attribute.repeatable && field.value ? /* @__PURE__ */ jsx(NonRepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }) : null,
3086
- attribute.repeatable && /* @__PURE__ */ jsx(RepeatableComponent, { attribute, name: name2, disabled, ...props, children: props.children }),
3087
- /* @__PURE__ */ jsx(Field.Error, {})
3088
- ] });
3089
- };
3090
- const MemoizedComponentInput = React.memo(ComponentInput);
3091
- const AddComponentButton = ({
3092
- hasError,
3093
- isDisabled,
3094
- isOpen,
3095
- children,
3096
- onClick
3097
- }) => {
3098
- return /* @__PURE__ */ jsx(
3099
- StyledButton,
3100
- {
3101
- type: "button",
3102
- onClick,
3103
- disabled: isDisabled,
3104
- background: "neutral0",
3105
- style: { cursor: isDisabled ? "not-allowed" : "pointer" },
3106
- variant: "tertiary",
3107
- children: /* @__PURE__ */ jsxs(Flex, { tag: "span", gap: 2, children: [
3108
- /* @__PURE__ */ jsx(StyledAddIcon, { "aria-hidden": true, $isOpen: isOpen, $hasError: hasError && !isOpen }),
3109
- /* @__PURE__ */ jsx(
3110
- AddComponentTitle,
3111
- {
3112
- variant: "pi",
3113
- fontWeight: "bold",
3114
- textColor: hasError && !isOpen ? "danger600" : "neutral500",
3115
- children
3116
- }
3117
- )
3118
- ] })
3119
- }
3120
- );
3121
- };
3122
- const StyledAddIcon = styled(PlusCircle)`
3123
- height: ${({ theme }) => theme.spaces[6]};
3124
- width: ${({ theme }) => theme.spaces[6]};
3125
- transform: ${({ $isOpen }) => $isOpen ? "rotate(45deg)" : "rotate(0deg)"};
3126
-
3127
- > circle {
3128
- fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger200 : theme.colors.neutral150};
3129
- }
3130
- > path {
3131
- fill: ${({ theme, $hasError }) => $hasError ? theme.colors.danger600 : theme.colors.neutral600};
3132
- }
3133
- `;
3134
- const AddComponentTitle = styled(Typography)``;
3135
- const StyledButton = styled(Button)`
3136
- border-radius: 26px;
3137
- border-color: ${({ theme }) => theme.colors.neutral150};
3138
- box-shadow: ${({ theme }) => theme.shadows.filterShadow};
3139
- height: 5rem;
3140
-
3141
- &:hover {
3142
- ${AddComponentTitle} {
3143
- color: ${({ theme }) => theme.colors.primary600};
3144
- }
3145
-
3146
- ${StyledAddIcon} {
3147
- > circle {
3148
- fill: ${({ theme }) => theme.colors.primary600};
3149
- }
3150
- > path {
3151
- fill: ${({ theme }) => theme.colors.primary600};
3152
- }
3080
+ );
3081
+ moveFieldRow(name2, currentIndex, newIndex);
3082
+ };
3083
+ const getItemPos = (index) => `${index + 1} of ${value.length}`;
3084
+ const handleCancel = (index) => {
3085
+ setLiveText(
3086
+ formatMessage(
3087
+ {
3088
+ id: getTranslation("dnd.cancel-item"),
3089
+ defaultMessage: "{item}, dropped. Re-order cancelled."
3090
+ },
3091
+ {
3092
+ item: `${name2}.${index}`
3093
+ }
3094
+ )
3095
+ );
3096
+ };
3097
+ const handleGrabItem = (index) => {
3098
+ setLiveText(
3099
+ formatMessage(
3100
+ {
3101
+ id: getTranslation("dnd.grab-item"),
3102
+ defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
3103
+ },
3104
+ {
3105
+ item: `${name2}.${index}`,
3106
+ position: getItemPos(index)
3107
+ }
3108
+ )
3109
+ );
3110
+ };
3111
+ const handleDropItem = (index) => {
3112
+ setLiveText(
3113
+ formatMessage(
3114
+ {
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)
3121
+ }
3122
+ )
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" });
3153
3132
  }
3154
- }
3155
- &:active {
3156
- ${AddComponentTitle} {
3157
- 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
+ );
3158
3143
  }
3159
- ${StyledAddIcon} {
3160
- > circle {
3161
- fill: ${({ theme }) => theme.colors.primary600};
3162
- }
3163
- > path {
3164
- fill: ${({ theme }) => theme.colors.neutral100};
3165
- }
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
+ );
3166
3152
  }
3167
- }
3168
- `;
3169
- const ComponentCategory = ({
3170
- category,
3171
- components = [],
3172
- variant = "primary",
3173
- onAddComponent
3174
- }) => {
3175
- const { formatMessage } = useIntl();
3176
- return /* @__PURE__ */ jsxs(Accordion.Item, { value: category, children: [
3177
- /* @__PURE__ */ jsx(Accordion.Header, { variant, children: /* @__PURE__ */ jsx(Accordion.Trigger, { children: formatMessage({ id: category, defaultMessage: category }) }) }),
3178
- /* @__PURE__ */ jsx(Accordion.Content, { children: /* @__PURE__ */ jsx(Grid, { paddingTop: 4, paddingBottom: 4, paddingLeft: 3, paddingRight: 3, children: components.map(({ uid, displayName, icon }) => /* @__PURE__ */ jsx(
3179
- ComponentBox,
3153
+ return formatMessage(
3180
3154
  {
3181
- tag: "button",
3182
- type: "button",
3183
- background: "neutral100",
3184
- justifyContent: "center",
3185
- onClick: onAddComponent(uid),
3186
- hasRadius: true,
3187
- height: "8.4rem",
3188
- shrink: 0,
3189
- borderColor: "neutral200",
3190
- children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, alignItems: "center", justifyContent: "center", children: [
3191
- /* @__PURE__ */ jsx(ComponentIcon, { color: "currentColor", background: "primary200", icon }),
3192
- /* @__PURE__ */ jsx(Typography, { variant: "pi", fontWeight: "bold", children: displayName })
3193
- ] })
3155
+ id: getTranslation("components.DynamicZone.add-component"),
3156
+ defaultMessage: "Add a component to {componentName}"
3194
3157
  },
3195
- uid
3196
- )) }) })
3197
- ] });
3198
- };
3199
- const Grid = styled(Box)`
3200
- display: grid;
3201
- grid-template-columns: repeat(auto-fit, 14rem);
3202
- grid-gap: ${({ theme }) => theme.spaces[1]};
3203
- `;
3204
- const ComponentBox = styled(Flex)`
3205
- color: ${({ theme }) => theme.colors.neutral600};
3206
- cursor: pointer;
3207
-
3208
- @media (prefers-reduced-motion: no-preference) {
3209
- transition: color 120ms ${(props) => props.theme.motion.easings.easeOutQuad};
3210
- }
3211
-
3212
- &:focus,
3213
- &:hover {
3214
- border: 1px solid ${({ theme }) => theme.colors.primary200};
3215
- background: ${({ theme }) => theme.colors.primary100};
3216
- color: ${({ theme }) => theme.colors.primary600};
3217
- }
3218
- `;
3219
- const ComponentPicker = ({
3220
- dynamicComponentsByCategory = {},
3221
- isOpen,
3222
- onClickAddComponent
3223
- }) => {
3224
- const { formatMessage } = useIntl();
3225
- const handleAddComponentToDz = (componentUid) => () => {
3226
- onClickAddComponent(componentUid);
3158
+ { componentName: label || name2 }
3159
+ );
3227
3160
  };
3228
- if (!isOpen) {
3229
- return null;
3230
- }
3231
- return /* @__PURE__ */ jsxs(
3232
- Box,
3233
- {
3234
- paddingTop: 6,
3235
- paddingBottom: 6,
3236
- paddingLeft: 5,
3237
- paddingRight: 5,
3238
- background: "neutral0",
3239
- shadow: "tableShadow",
3240
- borderColor: "neutral150",
3241
- hasRadius: true,
3242
- children: [
3243
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Typography, { fontWeight: "bold", textColor: "neutral600", children: formatMessage({
3244
- id: getTranslation("components.DynamicZone.ComponentPicker-label"),
3245
- defaultMessage: "Pick one component"
3246
- }) }) }),
3247
- /* @__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(
3248
- ComponentCategory,
3249
- {
3250
- category,
3251
- components,
3252
- onAddComponent: handleAddComponentToDz,
3253
- variant: index % 2 === 1 ? "primary" : "secondary"
3254
- },
3255
- category
3256
- )) }) })
3257
- ]
3258
- }
3259
- );
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
+ ] }) });
3260
3228
  };
3261
3229
  const NotAllowedInput = ({ hint, label, required, name: name2 }) => {
3262
3230
  const { formatMessage } = useIntl();
@@ -3736,8 +3704,7 @@ const Wrapper = styled.div`
3736
3704
  `;
3737
3705
  var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, unorderedListRE = /[*+-]\s/;
3738
3706
  function newlineAndIndentContinueMarkdownList(cm) {
3739
- if (cm.getOption("disableInput"))
3740
- return CodeMirror.Pass;
3707
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
3741
3708
  var ranges = cm.listSelections(), replacements = [];
3742
3709
  for (var i = 0; i < ranges.length; i++) {
3743
3710
  var pos = ranges[i].head;
@@ -3771,8 +3738,7 @@ function newlineAndIndentContinueMarkdownList(cm) {
3771
3738
  var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
3772
3739
  var bullet = numbered ? parseInt(match[3], 10) + 1 + match[4] : match[2].replace("x", " ");
3773
3740
  replacements[i] = "\n" + indent + bullet + after;
3774
- if (numbered)
3775
- incrementRemainingMarkdownListNumbers(cm, pos);
3741
+ if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
3776
3742
  }
3777
3743
  }
3778
3744
  cm.replaceSelections(replacements);
@@ -3790,10 +3756,8 @@ function incrementRemainingMarkdownListNumbers(cm, pos) {
3790
3756
  var newNumber = parseInt(startItem[3], 10) + lookAhead - skipCount;
3791
3757
  var nextNumber = parseInt(nextItem[3], 10), itemNumber = nextNumber;
3792
3758
  if (startIndent === nextIndent && !isNaN(nextNumber)) {
3793
- if (newNumber === nextNumber)
3794
- itemNumber = nextNumber + 1;
3795
- if (newNumber > nextNumber)
3796
- itemNumber = newNumber + 1;
3759
+ if (newNumber === nextNumber) itemNumber = nextNumber + 1;
3760
+ if (newNumber > nextNumber) itemNumber = newNumber + 1;
3797
3761
  cm.replaceRange(
3798
3762
  nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
3799
3763
  {
@@ -3806,10 +3770,8 @@ function incrementRemainingMarkdownListNumbers(cm, pos) {
3806
3770
  }
3807
3771
  );
3808
3772
  } else {
3809
- if (startIndent.length > nextIndent.length)
3810
- return;
3811
- if (startIndent.length < nextIndent.length && lookAhead === 1)
3812
- return;
3773
+ if (startIndent.length > nextIndent.length) return;
3774
+ if (startIndent.length < nextIndent.length && lookAhead === 1) return;
3813
3775
  skipCount += 1;
3814
3776
  }
3815
3777
  }
@@ -4943,621 +4905,682 @@ const Wysiwyg = React.forwardRef(
4943
4905
  /* @__PURE__ */ jsx(MediaLibraryDialog, { onClose: handleToggleMediaLib, onSelectAssets: handleSelectAssets })
4944
4906
  ] });
4945
4907
  }
4946
- );
4947
- const MemoizedWysiwyg = React.memo(Wysiwyg);
4948
- const InputRenderer = ({ visible, hint: providedHint, ...props }) => {
4949
- const { id, document: document2, collectionType } = useDoc();
4950
- const isFormDisabled = useForm("InputRenderer", (state) => state.disabled);
4951
- const isInDynamicZone = useDynamicZone("isInDynamicZone", (state) => state.isInDynamicZone);
4952
- const canCreateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canCreateFields);
4953
- const canReadFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canReadFields);
4954
- const canUpdateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUpdateFields);
4955
- const canUserAction = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUserAction);
4956
- let idToCheck = id;
4957
- if (collectionType === SINGLE_TYPES) {
4958
- idToCheck = document2?.documentId;
4908
+ );
4909
+ const MemoizedWysiwyg = React.memo(Wysiwyg);
4910
+ const InputRenderer = ({ visible, hint: providedHint, ...props }) => {
4911
+ const { id, document: document2, collectionType } = useDoc();
4912
+ const isFormDisabled = useForm("InputRenderer", (state) => state.disabled);
4913
+ const isInDynamicZone = useDynamicZone("isInDynamicZone", (state) => state.isInDynamicZone);
4914
+ const canCreateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canCreateFields);
4915
+ const canReadFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canReadFields);
4916
+ const canUpdateFields = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUpdateFields);
4917
+ const canUserAction = useDocumentRBAC("InputRenderer", (rbac) => rbac.canUserAction);
4918
+ let idToCheck = id;
4919
+ if (collectionType === SINGLE_TYPES) {
4920
+ idToCheck = document2?.documentId;
4921
+ }
4922
+ const editableFields = idToCheck ? canUpdateFields : canCreateFields;
4923
+ const readableFields = idToCheck ? canReadFields : canCreateFields;
4924
+ const canUserReadField = canUserAction(props.name, readableFields, props.type);
4925
+ const canUserEditField = canUserAction(props.name, editableFields, props.type);
4926
+ const fields = useStrapiApp("InputRenderer", (app) => app.fields);
4927
+ const { lazyComponentStore } = useLazyComponents(
4928
+ attributeHasCustomFieldProperty(props.attribute) ? [props.attribute.customField] : void 0
4929
+ );
4930
+ const hint = useFieldHint(providedHint, props.attribute);
4931
+ const {
4932
+ edit: { components }
4933
+ } = useDocLayout();
4934
+ const field = useField(props.name);
4935
+ if (!visible) {
4936
+ return null;
4937
+ }
4938
+ if (!canUserReadField && !isInDynamicZone) {
4939
+ return /* @__PURE__ */ jsx(NotAllowedInput, { hint, ...props });
4940
+ }
4941
+ const fieldIsDisabled = !canUserEditField && !isInDynamicZone || props.disabled || isFormDisabled;
4942
+ if (attributeHasCustomFieldProperty(props.attribute)) {
4943
+ const CustomInput = lazyComponentStore[props.attribute.customField];
4944
+ if (CustomInput) {
4945
+ return /* @__PURE__ */ jsx(CustomInput, { ...props, ...field, hint, disabled: fieldIsDisabled });
4946
+ }
4947
+ return /* @__PURE__ */ jsx(
4948
+ InputRenderer$1,
4949
+ {
4950
+ ...props,
4951
+ hint,
4952
+ type: props.attribute.customField,
4953
+ disabled: fieldIsDisabled
4954
+ }
4955
+ );
4956
+ }
4957
+ const addedInputTypes = Object.keys(fields);
4958
+ if (!attributeHasCustomFieldProperty(props.attribute) && addedInputTypes.includes(props.type)) {
4959
+ const CustomInput = fields[props.type];
4960
+ return /* @__PURE__ */ jsx(CustomInput, { ...props, hint, disabled: fieldIsDisabled });
4961
+ }
4962
+ switch (props.type) {
4963
+ case "blocks":
4964
+ return /* @__PURE__ */ jsx(MemoizedBlocksInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
4965
+ case "component":
4966
+ return /* @__PURE__ */ jsx(
4967
+ MemoizedComponentInput,
4968
+ {
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;
4959
5014
  }
4960
- const editableFields = idToCheck ? canUpdateFields : canCreateFields;
4961
- const readableFields = idToCheck ? canReadFields : canCreateFields;
4962
- const canUserReadField = canUserAction(props.name, readableFields, props.type);
4963
- const canUserEditField = canUserAction(props.name, editableFields, props.type);
4964
- const fields = useStrapiApp("InputRenderer", (app) => app.fields);
4965
- const { lazyComponentStore } = useLazyComponents(
4966
- attributeHasCustomFieldProperty(props.attribute) ? [props.attribute.customField] : void 0
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
+ }
4967
5043
  );
4968
- const hint = useFieldHint(providedHint, props.attribute);
4969
- const {
4970
- edit: { components }
4971
- } = useDocLayout();
4972
- const field = useField(props.name);
4973
- if (!visible) {
4974
- return null;
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 };
4975
5055
  }
4976
- if (!canUserReadField && !isInDynamicZone) {
4977
- return /* @__PURE__ */ jsx(NotAllowedInput, { hint, ...props });
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};`}
4978
5070
  }
4979
- const fieldIsDisabled = !canUserEditField && !isInDynamicZone || props.disabled || isFormDisabled;
4980
- if (attributeHasCustomFieldProperty(props.attribute)) {
4981
- const CustomInput = lazyComponentStore[props.attribute.customField];
4982
- if (CustomInput) {
4983
- return /* @__PURE__ */ jsx(CustomInput, { ...props, ...field, hint, disabled: fieldIsDisabled });
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);
4984
5087
  }
4985
5088
  return /* @__PURE__ */ jsx(
4986
- InputRenderer$1,
5089
+ Box,
4987
5090
  {
4988
- ...props,
4989
- hint,
4990
- type: props.attribute.customField,
4991
- disabled: fieldIsDisabled
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__;
4992
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)
5263
+ }
5264
+ )
4993
5265
  );
4994
- }
4995
- const addedInputTypes = Object.keys(fields);
4996
- if (!attributeHasCustomFieldProperty(props.attribute) && addedInputTypes.includes(props.type)) {
4997
- const CustomInput = fields[props.type];
4998
- return /* @__PURE__ */ jsx(CustomInput, { ...props, hint, disabled: fieldIsDisabled });
4999
- }
5000
- switch (props.type) {
5001
- case "blocks":
5002
- return /* @__PURE__ */ jsx(MemoizedBlocksInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
5003
- case "component":
5004
- return /* @__PURE__ */ jsx(
5005
- MemoizedComponentInput,
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(
5006
5275
  {
5007
- ...props,
5008
- hint,
5009
- layout: components[props.attribute.component].layout,
5010
- disabled: fieldIsDisabled,
5011
- children: (inputProps) => /* @__PURE__ */ jsx(InputRenderer, { ...inputProps })
5276
+ id: getTranslation("dnd.cancel-item"),
5277
+ defaultMessage: "{item}, dropped. Re-order cancelled."
5278
+ },
5279
+ {
5280
+ item: `${name2}.${index}`
5012
5281
  }
5013
- );
5014
- case "dynamiczone":
5015
- return /* @__PURE__ */ jsx(DynamicZone, { ...props, hint, disabled: fieldIsDisabled });
5016
- case "relation":
5017
- return /* @__PURE__ */ jsx(MemoizedRelationsField, { ...props, hint, disabled: fieldIsDisabled });
5018
- case "richtext":
5019
- return /* @__PURE__ */ jsx(MemoizedWysiwyg, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
5020
- case "uid":
5021
- return /* @__PURE__ */ jsx(MemoizedUIDInput, { ...props, hint, type: props.type, disabled: fieldIsDisabled });
5022
- case "enumeration":
5023
- return /* @__PURE__ */ jsx(
5024
- InputRenderer$1,
5282
+ )
5283
+ );
5284
+ };
5285
+ const handleGrabItem = (index) => {
5286
+ setLiveText(
5287
+ formatMessage(
5025
5288
  {
5026
- ...props,
5027
- hint,
5028
- options: props.attribute.enum.map((value) => ({ value })),
5029
- type: props.customField ? "custom-field" : props.type,
5030
- 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)
5031
5295
  }
5032
- );
5033
- default:
5034
- const { unique: _unique, mainField: _mainField, ...restProps } = props;
5035
- return /* @__PURE__ */ jsx(
5036
- InputRenderer$1,
5296
+ )
5297
+ );
5298
+ };
5299
+ const handleDropItem = (index) => {
5300
+ setLiveText(
5301
+ formatMessage(
5037
5302
  {
5038
- ...restProps,
5039
- hint,
5040
- type: props.customField ? "custom-field" : props.type,
5041
- disabled: fieldIsDisabled
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)
5042
5309
  }
5043
- );
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 });
5044
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
+ ] });
5045
5398
  };
5046
- const attributeHasCustomFieldProperty = (attribute) => "customField" in attribute && typeof attribute.customField === "string";
5047
- const useFieldHint = (hint = void 0, attribute) => {
5048
- const { formatMessage } = useIntl();
5049
- const { maximum, minimum } = getMinMax(attribute);
5050
- if (!maximum && !minimum) {
5051
- return hint;
5052
- }
5053
- const units = !["biginteger", "integer", "number", "dynamiczone", "component"].includes(
5054
- attribute.type
5055
- ) ? formatMessage(
5056
- {
5057
- id: "content-manager.form.Input.hint.character.unit",
5058
- defaultMessage: "{maxValue, plural, one { character} other { characters}}"
5059
- },
5060
- {
5061
- maxValue: Math.max(minimum || 0, maximum || 0)
5062
- }
5063
- ) : null;
5064
- const hasMinAndMax = typeof minimum === "number" && typeof maximum === "number";
5065
- return formatMessage(
5066
- {
5067
- id: "content-manager.form.Input.hint.text",
5068
- defaultMessage: "{min, select, undefined {} other {min. {min}}}{divider}{max, select, undefined {} other {max. {max}}}{unit}{br}{description}"
5069
- },
5070
- {
5071
- min: minimum,
5072
- max: maximum,
5073
- description: hint,
5074
- unit: units,
5075
- divider: hasMinAndMax ? formatMessage({
5076
- id: "content-manager.form.Input.hint.minMaxDivider",
5077
- defaultMessage: " / "
5078
- }) : null,
5079
- 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};
5080
5416
  }
5081
- );
5082
- };
5083
- const getMinMax = (attribute) => {
5084
- if ("min" in attribute || "max" in attribute) {
5085
- return {
5086
- maximum: !Number.isNaN(Number(attribute.max)) ? Number(attribute.max) : void 0,
5087
- minimum: !Number.isNaN(Number(attribute.min)) ? Number(attribute.min) : void 0
5088
- };
5089
- } else if ("maxLength" in attribute || "minLength" in attribute) {
5090
- return { maximum: attribute.maxLength, minimum: attribute.minLength };
5091
- } else {
5092
- return { maximum: void 0, minimum: void 0 };
5093
5417
  }
5094
- };
5095
- const MemoizedInputRenderer = memo(InputRenderer);
5096
- const DynamicComponent = ({
5097
- 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 = ({
5098
5430
  disabled,
5099
- index,
5100
- name: name2,
5101
- onRemoveComponentClick,
5102
- onMoveComponent,
5103
- onGrabItem,
5104
- onDropItem,
5105
- onCancel,
5106
- dynamicComponentsByCategory = {},
5107
- onAddComponent
5431
+ index,
5432
+ name: name2,
5433
+ mainField = {
5434
+ name: "id",
5435
+ type: "integer"
5436
+ },
5437
+ children,
5438
+ onDeleteComponent,
5439
+ toggleCollapses,
5440
+ __temp_key__,
5441
+ ...dragProps
5108
5442
  }) => {
5109
5443
  const { formatMessage } = useIntl();
5110
- const formValues = useForm("DynamicComponent", (state) => state.values);
5111
- const {
5112
- edit: { components }
5113
- } = useDocLayout();
5114
- const title = React.useMemo(() => {
5115
- const { mainField } = components[componentUid]?.settings ?? { mainField: "id" };
5116
- const mainFieldValue = getIn(formValues, `${name2}.${index}.${mainField}`);
5117
- const displayedValue = mainField === "id" || !mainFieldValue ? "" : String(mainFieldValue).trim();
5118
- const mainValue = displayedValue.length > 0 ? `- ${displayedValue}` : displayedValue;
5119
- return mainValue;
5120
- }, [componentUid, components, formValues, name2, index]);
5121
- const { icon, displayName } = React.useMemo(() => {
5122
- const [category] = componentUid.split(".");
5123
- const { icon: icon2, displayName: displayName2 } = (dynamicComponentsByCategory[category] ?? []).find(
5124
- (component) => component.uid === componentUid
5125
- ) ?? { icon: null, displayName: null };
5126
- return { icon: icon2, displayName: displayName2 };
5127
- }, [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(".");
5128
5449
  const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] = useDragAndDrop(!disabled, {
5129
- type: `${ItemTypes.DYNAMIC_ZONE}_${name2}`,
5450
+ type: `${ItemTypes.COMPONENT}_${componentKey}`,
5130
5451
  index,
5131
5452
  item: {
5132
5453
  index,
5133
- displayedValue: `${displayName} ${title}`,
5134
- icon
5454
+ displayedValue: displayValue
5135
5455
  },
5136
- onMoveItem: onMoveComponent,
5137
- onDropItem,
5138
- onGrabItem,
5139
- onCancel
5456
+ onStart() {
5457
+ toggleCollapses();
5458
+ },
5459
+ ...dragProps
5140
5460
  });
5141
5461
  React.useEffect(() => {
5142
5462
  dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
5143
5463
  }, [dragPreviewRef, index]);
5144
- const accordionValue = React.useId();
5145
- const { value = [], rawError } = useField(`${name2}.${index}`);
5146
- const [collapseToOpen, setCollapseToOpen] = React.useState("");
5147
- React.useEffect(() => {
5148
- if (rawError && value) {
5149
- setCollapseToOpen(accordionValue);
5150
- }
5151
- }, [rawError, value, accordionValue]);
5152
- const composedBoxRefs = useComposedRefs(boxRef, dropRef);
5153
- const accordionActions = disabled ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
5154
- /* @__PURE__ */ jsx(
5155
- IconButton,
5156
- {
5157
- variant: "ghost",
5158
- 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,
5159
5475
  {
5160
- id: getTranslation("components.DynamicZone.delete-label"),
5161
- defaultMessage: "Delete {name}"
5162
- },
5163
- { 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
+ }
5164
5484
  ),
5165
- onClick: onRemoveComponentClick,
5166
- children: /* @__PURE__ */ jsx(Trash, {})
5167
- }
5168
- ),
5169
- /* @__PURE__ */ jsx(
5170
- IconButton,
5171
- {
5172
- variant: "ghost",
5173
- onClick: (e) => e.stopPropagation(),
5174
- "data-handler-id": handlerId,
5175
- ref: dragRef,
5176
- label: formatMessage({
5177
- id: getTranslation("components.DragHandle-label"),
5178
- defaultMessage: "Drag"
5179
- }),
5180
- onKeyDown: handleKeyDown,
5181
- children: /* @__PURE__ */ jsx(Drag, {})
5182
- }
5183
- ),
5184
- /* @__PURE__ */ jsxs(Menu.Root, { children: [
5185
- /* @__PURE__ */ jsxs(Menu.Trigger, { size: "S", endIcon: null, paddingLeft: 2, paddingRight: 2, children: [
5186
- /* @__PURE__ */ jsx(More, { "aria-hidden": true, focusable: false }),
5187
- /* @__PURE__ */ jsx(VisuallyHidden, { tag: "span", children: formatMessage({
5188
- id: getTranslation("components.DynamicZone.more-actions"),
5189
- defaultMessage: "More actions"
5190
- }) })
5191
- ] }),
5192
- /* @__PURE__ */ jsxs(Menu.Content, { children: [
5193
- /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
5194
- /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
5195
- id: getTranslation("components.DynamicZone.add-item-above"),
5196
- defaultMessage: "Add component above"
5197
- }) }),
5198
- /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
5199
- /* @__PURE__ */ jsx(Menu.Label, { children: category }),
5200
- components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index), children: displayName2 }, componentUid))
5201
- ] }, category)) })
5202
- ] }),
5203
- /* @__PURE__ */ jsxs(Menu.SubRoot, { children: [
5204
- /* @__PURE__ */ jsx(Menu.SubTrigger, { children: formatMessage({
5205
- id: getTranslation("components.DynamicZone.add-item-below"),
5206
- defaultMessage: "Add component below"
5207
- }) }),
5208
- /* @__PURE__ */ jsx(Menu.SubContent, { children: Object.entries(dynamicComponentsByCategory).map(([category, components2]) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
5209
- /* @__PURE__ */ jsx(Menu.Label, { children: category }),
5210
- components2.map(({ displayName: displayName2, uid }) => /* @__PURE__ */ jsx(MenuItem, { onSelect: () => onAddComponent(uid, index + 1), children: displayName2 }, componentUid))
5211
- ] }, category)) })
5212
- ] })
5213
- ] })
5214
- ] })
5215
- ] });
5216
- const accordionTitle = title ? `${displayName} ${title}` : displayName;
5217
- return /* @__PURE__ */ jsxs(ComponentContainer, { tag: "li", width: "100%", children: [
5218
- /* @__PURE__ */ jsx(Flex, { justifyContent: "center", children: /* @__PURE__ */ jsx(Rectangle, { background: "neutral200" }) }),
5219
- /* @__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: [
5220
- /* @__PURE__ */ jsxs(Accordion.Header, { children: [
5221
5485
  /* @__PURE__ */ jsx(
5222
- Accordion.Trigger,
5486
+ IconButton,
5223
5487
  {
5224
- icon: icon && COMPONENT_ICONS[icon] ? COMPONENT_ICONS[icon] : COMPONENT_ICONS.dashboard,
5225
- 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, {})
5226
5498
  }
5227
- ),
5228
- /* @__PURE__ */ jsx(Accordion.Actions, { children: accordionActions })
5229
- ] }),
5230
- /* @__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(
5231
- Grid$1.Item,
5232
- {
5233
- col: 12,
5234
- s: 12,
5235
- xs: 12,
5236
- direction: "column",
5237
- alignItems: "stretch",
5238
- children: /* @__PURE__ */ jsx(Grid$1.Root, { gap: 4, children: row.map(({ size, ...field }) => {
5239
- const fieldName = `${name2}.${index}.${field.name}`;
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, { ...field, 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-DSDtEDLU.mjs.map
5586
+ //# sourceMappingURL=Input-aV8SSoTa.mjs.map